refactor(ui): adopt Nuxt UI components for homepage and layout

This commit refactors the main layout and homepage to utilize components from the Nuxt UI library, simplifying the
codebase and reducing custom boilerplate.

- The default layout is now built with `UPage`, `UHeader`, `UMain`, and `UFooter`.
- The homepage (`pages/index.vue`) has been updated to use `UPageHero` and `UBlogPosts`.
- The `IndexHero` and `IndexNews` components have been removed as their functionality is now integrated directly into
the index page.
- `Donate`, `Events`, and `HallOfFame` components are now wrapped with `UPageCTA` or `UPageSection`.
This commit is contained in:
xiaomai
2025-10-23 09:16:59 +08:00
parent e7f2bc2c47
commit 6473bdcc15
10 changed files with 188 additions and 183 deletions

View File

@@ -1,16 +1,14 @@
<template>
<div>
<!-- 捐赠模块 -->
<section id="donate" class="py-16 text-center bg-secondary">
<h3 class="text-2xl font-bold text-gray-900 mb-4">支持与捐赠功能未开放</h3>
<p class="max-w-2xl mx-auto text-gray-700 mb-6">您的捐赠将用于奖学金校园建设及校友活动发展感谢您对母校的支持</p>
<a href="#" class="bg-primary text-white px-8 py-3 rounded-xl shadow hover:opacity-90">立即捐赠</a>
</section>
</div>
<UPageCTA
class="bg-secondary"
title="支持与捐赠"
description="您的捐赠将用于奖学金、校园建设及校友活动发展。感谢您对母校的支持!"
:links="donationLinks"
/>
</template>
<script lang="ts" setup>
const donationLinks = ref([{ label: "立即捐赠", icon: "mdi:cash" }]);
</script>
<style></style>
<style></style>

View File

@@ -1,32 +1,35 @@
<template>
<div>
<!-- 活动模块 -->
<section id="events" class="bg-gray-100 py-16">
<div class="max-w-6xl mx-auto px-4">
<h3 class="text-2xl font-bold text-gray-900 mb-6">校友活动</h3>
<div class="grid md:grid-cols-3 gap-6">
<div v-for="event in events" :key="event.id" class="bg-white shadow rounded-xl">
<img :src="event.cover" :alt="event.title" class="rounded-xl" />
<div class="p-6">
<h4 class="font-semibold text-lg mb-2">{{ event.title }}</h4>
<p class="text-sm text-gray-600 mb-1">日期{{ useChineseDateFormat(event.date) }}</p>
<p class="text-sm text-gray-600 mb-4">地点{{ event.location }}</p>
<a :href="event.path" class="bg-primary text-white px-5 py-2 rounded-lg hover:opacity-90">阅读详情</a>
</div>
</div>
<!-- 活动模块 -->
<UPageSection title="校友活动" class="bg-gray-100">
<div class="grid md:grid-cols-3 gap-6">
<div
v-for="event in events"
:key="event.id"
class="bg-white shadow rounded-xl"
>
<img :src="event.cover" :alt="event.title" class="rounded-xl" />
<div class="p-6">
<h4 class="font-semibold text-lg mb-2">{{ event.title }}</h4>
<p class="text-sm text-gray-600 mb-1">
日期{{ useChineseDateFormat(event.date) }}
</p>
<p class="text-sm text-gray-600 mb-4">地点{{ event.location }}</p>
<!-- <a
:href="event.path"
class="bg-primary text-white px-5 py-2 rounded-lg hover:opacity-90"
>阅读详情</a
> -->
<UButton label="阅读详情" :to="event.path" trailing-icon="mdi:glasses"/>
</div>
</div>
</section>
</div>
</div>
</UPageSection>
</template>
<script lang="ts" setup>
const { data: events } = await useAsyncData('events', () =>
queryCollection('events')
.order("date", "DESC")
.limit(3)
.all()
)
const { data: events } = await useAsyncData("events", () =>
queryCollection("events").order("date", "DESC").limit(3).all()
);
</script>
<style></style>
<style></style>

View File

@@ -1,31 +1,33 @@
<template>
<div>
<section id="hall-of-fame" class="py-16">
<div class="max-w-6xl mx-auto px-4">
<h3 class="text-2xl font-bold text-center text-gray-900 mb-6">名人堂</h3>
<div class="grid md:grid-cols-4 gap-6">
<div v-for="person in persons" :key="person.id" class="flex flex-col items-center cursor-pointer transition hover:scale-105 hover:drop-shadow-2xl hover:-translate-y-1" @click="jumpToPersonIntro(person.path)">
<img :src="person.photo" :alt="person.name" class="w-40 rounded-full border-primary border-4" />
<h4 class="text-lg font-bold">{{ person.name }}</h4>
<p class="text-sm text-gray-500">{{ person.title }}</p>
</div>
</div>
<UPageSection title="名人堂">
<div class="grid md:grid-cols-4 gap-6">
<div
v-for="person in persons"
:key="person.id"
class="flex flex-col items-center cursor-pointer transition hover:scale-105 hover:drop-shadow-2xl hover:-translate-y-1"
@click="jumpToPersonIntro(person.path)"
>
<img
:src="person.photo"
:alt="person.name"
class="w-40 rounded-full border-primary border-4"
/>
<h4 class="text-lg font-bold">{{ person.name }}</h4>
<p class="text-sm text-gray-500">{{ person.title }}</p>
</div>
</section>
</div>
</div>
</UPageSection>
</template>
<script lang="ts" setup>
const { data: persons } = await useAsyncData('hall-of-fames', () =>
queryCollection('hallOfFames')
.limit(4)
.all()
)
const { data: persons } = await useAsyncData("hall-of-fames", () =>
queryCollection("hallOfFames").limit(4).all()
);
var router = useRouter()
var router = useRouter();
const jumpToPersonIntro = (path: string) => {
router.push(path)
}
router.push(path);
};
</script>
<style></style>
<style></style>

View File

@@ -1,35 +0,0 @@
<template>
<div>
<!-- Hero Banner -->
<section class="relative bg-secondary py-32 md:py-48 lg:py-64 text-center bg-cover bg-center"
style="background-image: url('/hero-image.jpg');">
<!-- 遮罩 -->
<div class="absolute inset-0 bg-black/40"></div>
<!-- 内容 -->
<div class="relative z-10 max-w-3xl mx-auto px-4">
<h2 class="text-3xl md:text-5xl font-extrabold text-white drop-shadow-lg">
连接校友 · 传承精神
</h2>
<p class="mt-4 text-lg text-gray-100">
马来西亚柔佛永平中学校友会官方网站
</p>
<div class="mt-6 space-x-4">
<a href="/join-us" class="bg-primary text-white px-6 py-3 rounded-xl shadow hover:opacity-90">
立即加入我们
</a>
<!-- <a href="#donate"
class="bg-white border-2 border-secondary text-secondary px-6 py-3 rounded-xl hover:bg-secondary hover:text-white">
支持捐赠
</a> -->
</div>
</div>
</section>
</div>
</template>
<script lang="ts" setup>
</script>
<style></style>

View File

@@ -1,37 +0,0 @@
<template>
<div>
<!-- 新闻公告 -->
<section id="news" class="max-w-6xl mx-auto py-16 px-4">
<h2 class="text-2xl font-bold text-gray-900 mb-6">最新新闻与公告</h2>
<div class="grid md:grid-cols-3 gap-6">
<article v-for="n in news" :key="n.id" @click="jumpToNewsDetail(n.stem)"
class="bg-secondary/10 rounded-xl shadow cursor-pointer transition transform hover:-translate-y-1 hover:scale-105 hover:shadow-xl duration-300 ease-in-out">
<img class="rounded-xl" :src="n.cover" :alt="n.title">
<div class="p-5">
<h3 class="font-semibold mb-2">{{ n.title }}</h3>
<div class="px-1 w-max bg-secondary/25 border-secondary border-2 rounded-xl text-primary text-sm mb-2">{{
useChineseDateFormat(n.date) }}</div>
<p class="text-sm text-gray-600">{{ n.description }}</p>
</div>
</article>
</div>
</section>
</div>
</template>
<script lang="ts" setup>
const { data: news } = await useAsyncData('news', () =>
queryCollection('news')
.order("date", "DESC")
.limit(3)
.all()
)
const router = useRouter();
const jumpToNewsDetail = (newsPath: string) => {
router.push(newsPath);
}
</script>
<style></style>