Files
dinner.tootaio.com/20251108/sponsorList/index.html
xiaomai 60afabb845 feat(ui): add QR code to sponsor list and improve styling
This commit enhances the user interface for the sponsor list pages.

- A QR code linking to the mobile view is now displayed on the main sponsor list page.
- The QR code on the landing page now has a pulsing animation to draw attention.
- Readability of the sponsor list is improved by increasing font sizes and adjusting title colors.
- The 'Special Thanks' banner has been moved to the top for better visibility.
2025-11-09 12:12:42 +08:00

342 lines
11 KiB
HTML

<!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>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<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="w-screen h-screen overflow-clip select-none">
<div class="flex w-full h-full">
<!-- <div class="flex-2 bg-amber-50"></div> -->
<div
class="flex-8 relative bg-linear-to-b from-pink-900 to-pink-500 px-6"
>
<!-- QR Code Container -->
<div
class="absolute z-99 top-16 left-16 flex flex-col items-center justify-center w-fit"
>
<div
class="cursor-pointer transition-transform duration-300 hover:scale-105"
>
<img
class="size-32 ring-8 ring-white shadow-lg"
src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://dinner.tootaio.com/20251108/sponsorList/mobile/"
alt="Mobile Sponsor List QR"
/>
</div>
<div
class="text-2xl font-bold mt-4 text-black bg-white/50 px-4 py-2 rounded-full"
>
Scan for sponsor list!
</div>
</div>
<!-- 上:可滚动 / 填满剩余空间 -->
<div class="absolute inset-0 overflow-hidden">
<div class="sponsor-marquee-track">
<div
v-for="([key, value], index) in sponsorsTwice"
:key="key + '-' + index"
>
<div v-if="!value.showTogether" class="pt-8 space-y-8">
<div v-for="sponsor in value.list" :key="sponsor">
<div
class="backdrop-blur-xl bg-linear-to-br from-pink-500/20 to-white/10 border border-white/30 rounded-2xl p-8 shadow-2xl"
>
<div
:class="['text-center font-bold mb-4 text-amber-400', (value.titleFontSize || 'text-4xl')]"
>
{{ formatRm(key) }}
</div>
<div
:class="['text-center text-5xl text-white text-shadow-amber-400 text-shadow-lg']"
>
{{ sponsor }}
</div>
</div>
</div>
</div>
<div v-else class="pt-8 space-y-8">
<div
class="backdrop-blur-xl bg-linear-to-br from-white/20 to-white/10 border border-white/30 rounded-2xl p-8 shadow-2xl"
>
<div
:class="['text-center font-bold mb-4 text-amber-400', (value.titleFontSize || 'text-4xl')]"
>
{{ formatRm(key) }}
</div>
<div
class="flex flex-wrap gap-x-8 gap-y-4 p-4 justify-start"
>
<div
v-for="sponsor in value.list"
:key="sponsor"
class="text-4xl border-white border px-4 py-2 rounded-md shadow-md text-white"
>
{{sponsor}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 下:特别鸣谢 -->
<div
class="absolute top-0 left-0 right-0 bg-white/30 backdrop-blur-md rounded-t-xl border-t border-white/40 shadow-lg"
>
<div class="flex items-center">
<div class="p-6 text-3xl font-bold text-nowrap">特别鸣谢:</div>
<div
class="overflow-hidden flex-1 mask-x-from-95% mask-x-to-100%"
>
<div class="flex w-max pl-4 gap-4 special-marquee-track">
<div
class="text-3xl px-6 py-2 border border-gray-500 rounded-full"
v-for="specialSponsor in specialSponsorTwice"
:key="specialSponsor"
>
{{specialSponsor}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
const { createApp, ref, computed } = Vue;
createApp({
setup() {
const eventTitle = ref("永平捷兔会 30 周年庆大跑晚宴");
const formatRm = (s) =>
s.replace(
/RM\s*([0-9,]+(?:\.\d+)?)/i,
(_, num) =>
"RM" + Number(num.replace(/,/g, "")).toLocaleString("en-MY")
);
const sponsors = ref({
Rm5000: { titleFontSize: "text-9xl", list: ["Top Gan"] },
Rm2000: {
titleFontSize: "text-8xl",
list: [
"Ketua Kampung",
"校长",
"Natural 9",
"明盛弟",
"联合周",
"新成酒家",
],
},
Rm1600: { titleFontSize: "text-7xl", list: ["Moon"] },
Rm1200: { titleFontSize: "text-6xl", list: ["Labis Bon"] },
Rm1000: { titleFontSize: "text-5xl", list: ["Angel"] },
Rm800: {
list: [
"拿督",
"Mari Chan",
"霖主席",
"MDL阿德",
"Cool Lo",
"刘薇薇",
],
},
Rm500: { list: ["Hun Shap Tou", "Good Man", "学生妹", "三太子"] },
Rm400: {
showTogether: true,
list: [
"Founder Koh",
"Founder Ang",
"Founder Koid",
"Superman",
"榴梿",
"阳阳",
"Lawyer",
"小老板",
"富婆",
"Farmer",
"Farmer嫂",
"Durian King",
"大傻",
"Datin",
"Mohamad Ali",
"Wireman",
"Ki Ka Poh",
"TV",
"Sexy",
"Uncle Low",
"小黑",
"黑夫人",
"Jimmy",
"Ah Boon",
"米桶",
"Pasar Malam",
"Public Ong",
"Pet pet",
"梅惠",
"910",
"伟哥",
"仙女",
"Boss",
"彩虹",
"花瓶",
"黑珍珠",
"木薯老板",
"美国佬",
"三公子",
"来",
"宝强",
"Steven",
"老二",
"车斗Lau",
"海南Huat",
"龙门铁宝",
"山竹祥",
"旺庆",
"福承",
"立家",
"鸿兴",
"江老板",
"Wong Long",
"健芳",
"杨文德",
"古早味",
"猪笼",
"Bangkali Pusing",
"999",
"012",
"Wu Wei Xiong",
"Fan Shu",
"肥福",
"Kulai:阿祥",
"Kulai:Robert",
"国宝",
"Puki Ayam",
"爱情鸟",
"William Soh",
"Darren",
"林总",
"High More",
"Tiger",
"Lim Kopi",
"林董",
"Lighting Chan",
"Jag",
"Corina",
"Jiu Xiao",
"Love Bird",
"Sepuluh Dua",
"哈哈",
"狗爷",
],
},
Rm200: {
showTogether: true,
list: [
"兰总",
"Kampopo",
"Lim Kee Meng",
"003",
"Tan Brother",
"E-Sun",
"Kami",
"Kami嫂",
"美发师",
"美女",
"Oong Lai",
"乃乃",
"Naluri",
"妹子",
"Joan",
"Kai De Tan",
"企鹅",
"老二",
"二娘",
"DJ Yap",
"菜头",
"Ketam",
"Roket",
"土豪",
"天鹅",
"老板娘",
"Momo",
"Happyman",
"阿琳",
"花木兰",
"财政",
"财政夫人",
"走火",
"表妹",
"鸡脚老大",
"阿锦",
"维哥",
"牛车轮",
"陈进平",
],
},
});
const specialSponsor = ref([
"HEINEKEN MARKETING MALAYSIA SDN.BHD.: 100 件 T-Shirt & 500 件小毛巾",
"花奇 Nou: 大蛋糕一个",
"绝世旅游 500 - 550 环保袋",
]);
const specialSponsorTwice = computed(() => [
...specialSponsor.value,
...specialSponsor.value,
]);
const sponsorsTwice = computed(() => {
// 转成数组,因为对象遍历时 Vue 不保证顺序
const entries = Object.entries(sponsors.value);
// 重复一次,实现无缝衔接
return [...entries, ...entries];
});
return {
eventTitle,
formatRm,
sponsorsTwice,
specialSponsorTwice,
};
},
}).mount("#app");
</script>
</body>
</html>