Files
dinner.tootaio.com/20251115/sponsorList/index.html
xiaomai ce206654b2 fix(sponsorList): correct property name for special sponsors display
The display page was referencing an incorrect property `specialSponsor` instead of `specialSponsors`, causing the list not to render. This has been corrected.

Additionally, the sponsor data file has been updated with new entries and corrections, including moving '地南祥子' from a table sponsor to a cash donation.
2025-11-15 00:13:08 +08:00

370 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>赞助名单 | Sponsor List - 永平新港汕河二周年联欢晚宴</title>
<script src="/analysis.js"></script>
<!-- ✅ 基本 SEO 元信息 -->
<meta
name="description"
content="汕河活动赞助名单与特别鸣谢。感谢所有支持汕河文化与社区发展的赞助商,让我们携手共建更美好的明天。"
/>
<meta
name="keywords"
content="汕河, Sponsor List, 赞助名单, 活动赞助, 马来西亚汕头同乡会, 捐款名单, 汕河活动"
/>
<meta name="author" content="汕河活动组委会" />
<meta name="robots" content="index, follow" />
<!-- ✅ 结构化数据Google Rich Snippet -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Event",
"name": "汕河赞助名单",
"description": "汕河文化活动赞助名单与鸣谢,包含现金赞助、物品赞助与特别支持单位。",
"startDate": "2025-11-12",
"eventAttendanceMode": "https://schema.org/OnlineEventAttendanceMode",
"eventStatus": "https://schema.org/EventScheduled",
"organizer": {
"@type": "Organization",
"name": "汕河活动组委会",
"url": "https://dinner.tootaio.com"
},
"image": "https://dinner.tootaio.com/assets/og-cover.jpg",
"url": "https://dinner.tootaio.com/sponsor-list"
}
</script>
<!-- ✅ Open Graph for Facebook / 微信 / LINE 分享 -->
<meta property="og:type" content="website" />
<meta property="og:title" content="汕河赞助名单 | Sponsor List" />
<meta
property="og:description"
content="感谢所有支持汕河文化活动的赞助单位与个人,让爱心与文化同行。"
/>
<meta
property="og:image"
content="https://dinner.tootaio.com/assets/og-cover.jpg"
/>
<meta property="og:url" content="https://dinner.tootaio.com/sponsor-list" />
<meta property="og:site_name" content="汕河活动" />
<!-- ✅ Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="汕河赞助名单 | Sponsor List" />
<meta
name="twitter:description"
content="汕河活动赞助名单与特别鸣谢。感谢所有支持汕河文化的伙伴!"
/>
<meta
name="twitter:image"
content="https://dinner.tootaio.com/assets/og-cover.jpg"
/>
<!-- ✅ Favicon -->
<link rel="icon" href="/favicon.ico" />
<!-- ✅ Canonical URL避免重复收录 -->
<link rel="canonical" href="https://dinner.tootaio.com/sponsor-list" />
<!-- ✅ PWA / Mobile 优化 -->
<meta name="theme-color" content="#B91C1C" />
<meta name="apple-mobile-web-app-title" content="汕河赞助名单" />
<link rel="apple-touch-icon" href="/assets/og-cover.jpg" />
<script src="/analysis.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style type="text/tailwindcss">
@theme {
/* 🎨 定义自定义字体族变量 */
--font-bai-ge: "BaiGeTianXing", sans-serif;
--font-gu-huang: "ShangShouGuHuang", sans-serif;
--font-tang-ying: "YeZiTangYingHei", sans-serif;
}
@font-face {
font-family: "BaiGeTianXing";
src: url("/fonts/字魂白鸽天行体.ttf") format("truetype");
font-display: swap;
}
@font-face {
font-family: "ShangShouGuHuang";
src: url("/fonts/ShangShouGuHuangTi-2.ttf") format("truetype");
font-display: swap;
}
@font-face {
font-family: "YeZiTangYingHei";
src: url("/fonts/YeZiGongChangTangYingHei-2.ttf") format("truetype");
font-display: swap;
}
.poem {
@apply flex-1 [writing-mode:vertical-rl] flex items-center justify-center text-6xl font-bai-ge tracking-[0.5em] text-white ring-amber-300 text-shadow-lg text-shadow-black;
}
</style>
<style>
.sponsor-marquee-track {
animation: sponsor-marquee-move-text 120s linear infinite;
}
.special-marquee-track {
animation: special-marquee-move-text 30s linear infinite;
}
@keyframes sponsor-marquee-move-text {
to {
transform: translateY(-50%);
}
}
@keyframes special-marquee-move-text {
to {
transform: translateX(-50%);
}
}
</style>
</head>
<body>
<div id="app" class="h-screen flex flex-col select-none">
<div class="text-center text-6xl font-bold p-8 bg-red-700 text-white">
{{eventTitle}}
</div>
<!-- 特别赞助 -->
<div class="py-6 bg-yellow-300 text-red-500 shadow-yellow-500 shadow-lg">
<div class="overflow-clip mask-x-from-95% mask-x-to-100%">
<div class="flex pl-4 gap-4 w-max special-marquee-track text-4xl">
<div v-for="sponsor in specialSponsorDouble" :key="sponsor">
{{sponsor}}
</div>
</div>
</div>
</div>
<!-- 下半部分二八分,左侧放 image右侧走马灯 -->
<div
class="flex-1 flex min-h-0 overflow-clip bg-linear-to-b from-red-500 to-red-900"
>
<!-- <div class="flex-2 flex flex-col items-center justify-around">
<img
v-for="logo in logos"
:src="`../assets/${logo.imgSrc}`"
:alt="logo.imgSrc"
class="w-[80%] drop-shadow-2xl"
/>
</div> -->
<div class="poem">汕水流长通四海</div>
<div class="flex-8 inset-red-lg">
<div class="flex flex-col pt-4 gap-4 px-4 sponsor-marquee-track">
<div
v-for="sponsor in sponsorListDouble"
:key="sponsor"
class="bg-linear-to-br from-white/20 to-white/10 px-16 py-4 rounded-2xl border-2 border-white/40"
>
<div v-if="sponsor.type == 'cash'" class="text-center py-8">
<div class="text-7xl text-yellow-400 font-bold">
RM {{sponsor.displayAmount}}
</div>
<div
class="text-7xl text-white text-shadow-amber-400 text-shadow-lg"
>
{{sponsor.name}}
</div>
</div>
<div
v-else-if="sponsor.type == 'cash-group'"
class="text-center py-8"
>
<div class="text-7xl text-yellow-400 font-bold mb-8">
RM {{sponsor.amount}}
</div>
<div class="flex flex-wrap gap-4">
<div
v-for="child in sponsor.children"
class="text-3xl px-4 py-2 bg-white/40 rounded-2xl"
>
{{child}}
</div>
</div>
</div>
<div
v-else-if="sponsor.type == 'table'"
class="flex items-center"
>
<div
class="text-3xl bg-red-500 text-white font-bold px-4 py-2 border-2 border-white rounded-full"
>
{{tableToSeats(sponsor.amount)}}
</div>
<div class="text-4xl font-bold flex-1 ml-4 text-white">
{{sponsor.name}}
</div>
</div>
<div v-else-if="sponsor.type == 'item'" class="flex items-center">
<div
class="text-3xl bg-red-500 text-white font-bold px-4 py-2 border-2 border-white rounded-full"
>
{{sponsor.detail}}
</div>
<div class="text-4xl font-bold flex-1 ml-4 text-white">
{{sponsor.name}}
</div>
</div>
</div>
</div>
</div>
<div class="poem">河川万里泽邦家</div>
</div>
</div>
<script>
const { createApp, ref, computed, onMounted } = Vue;
createApp({
setup() {
const eventTitle = ref("");
const logos = ref([]);
const sponsorList = ref([]); // Load from JSON
const specialSponsor = ref("");
const typePriority = {
cash: 4,
"cash-group": 3,
table: 2,
item: 1,
};
const groupByCashLessThan = ref(0);
function sortSponsors(list) {
return list.sort((a, b) => {
// 先按 type 优先级排序
const typeDiff = typePriority[b.type] - typePriority[a.type];
if (typeDiff !== 0) return typeDiff;
// 若 type 相同,再按 amount 从大到小
if (b.amount !== a.amount) return b.amount - a.amount;
// 若 amount 相同,最后按名称排序(可选)
return a.name.localeCompare(b.name, "zh");
});
}
const loadData = async () => {
try {
const [sponsorListResult] = await Promise.all([
fetch("../sponsorList.json"),
]);
if (!sponsorListResult.ok) {
throw new Error(
"Error while loading sponsorList: " + sponsorListResult.status
);
}
const sponsorListJsonData = await sponsorListResult.json();
eventTitle.value = sponsorListJsonData.eventTitle || "活动名称";
specialSponsor.value = sponsorListJsonData.specialSponsors || "";
logos.value = sponsorListJsonData.logos || [];
sponsorList.value = (
sponsorListJsonData.sponsorList || []
).reduce((acc, s, idx) => {
const sponsor = {
...s,
displayAmount:
s.type == "cash"
? s.amount.toLocaleString("en-MY")
: s.amount,
_uid: `s-${idx}`,
};
// 如果是现金赞助且金额小于阈值
if (s.type === "cash" && s.amount < groupByCashLessThan.value) {
// 查找是否已存在该金额的分组
const groupId = `group-${s.amount}`;
let amountGroup = acc.find((item) => item._uid === groupId);
if (!amountGroup) {
// 创建新的金额分组
amountGroup = {
name: "其他赞助商",
type: "cash-group",
amount: s.amount, // 保持原始数字,不格式化
children: [],
_uid: groupId,
};
acc.push(amountGroup);
}
// 将赞助商名称添加到分组的children中
amountGroup.children.push(s.name);
} else {
// 其他赞助商直接添加到结果中
acc.push(sponsor);
}
return acc;
}, []);
// Sort SponsorList by type and amount
sponsorList.value = sortSponsors(sponsorList.value);
console.log(sponsorList.value);
} catch (err) {
console.error(err);
}
};
onMounted(async () => {
await loadData();
});
const sponsorListDouble = computed(() => {
const a = sponsorList.value.map((s) => ({
...s,
_uid: s._uid + "-a",
}));
const b = sponsorList.value.map((s) => ({
...s,
_uid: s._uid + "-b",
}));
return [...a, ...b];
});
const specialSponsorDouble = computed(() => [
specialSponsor.value,
specialSponsor.value,
specialSponsor.value,
specialSponsor.value,
]);
const tableToSeats = (amount) => {
switch (amount) {
case 2:
return "两席";
case 1:
return "一席";
case 0.5:
return "半席";
default:
console.error("Error while converting table amount: ", amount);
}
};
return {
eventTitle,
logos,
sponsorListDouble,
specialSponsorDouble,
tableToSeats,
};
},
}).mount("#app");
</script>
</body>
</html>