feat(admin): add initial admin dashboard structure
This commit introduces the foundational structure for the new admin dashboard. - Utilizes @nuxt/ui to build the dashboard layout, including a collapsible sidebar and navigation. - Adds initial pages for the dashboard, news, events, and hall of fame management. - Implements a composable `useDashboardSidebarLinks` for managing sidebar navigation. - Refactors the default layout by integrating the header and footer directly. - Swaps the primary and secondary theme colors across the application.
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
<template>
|
||||
<!-- 页脚 -->
|
||||
<footer class="bg-gray-900 text-gray-300 py-6">
|
||||
<div class="max-w-6xl mx-auto px-4 flex flex-col md:flex-row justify-between items-center">
|
||||
<!-- 左侧版权信息 -->
|
||||
<div class="text-center md:text-left">
|
||||
<p>© 2025 永平中学校友会. 保留所有权利.</p>
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
<p class="mt-1">
|
||||
Powered by:
|
||||
<a href="https://tootaio.com" target="_blank" class="font-semibold hover:underline" style="color: #e24545;">
|
||||
Tootaio Studio
|
||||
</a>
|
||||
<span class="mt-1 text-sm text-gray-400">2018 级毕业学长(麦祖奕)</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 右侧社交链接 -->
|
||||
<div class="flex space-x-4 mt-3 md:mt-0">
|
||||
<a href="#">
|
||||
<Icon name="mdi-facebook" />
|
||||
</a>
|
||||
<a href="#">
|
||||
<Icon name="mdi-instagram" />
|
||||
</a>
|
||||
<a href="#">
|
||||
<Icon name="mdi-gmail" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
@@ -1,25 +0,0 @@
|
||||
<template>
|
||||
<!-- 导航栏 -->
|
||||
<header class="bg-white shadow-md sticky top-0 z-50">
|
||||
<div class="max-w-6xl mx-auto px-4 py-3 flex justify-between items-center">
|
||||
<div>
|
||||
<img class="inline w-16" src="/Logo.svg" alt="YPHS Alumni">
|
||||
<h1 class="inline text-xl font-bold text-gray-900">
|
||||
<a href="/" class="ml-4 hover:text-secondary">永平中学校友会</a>
|
||||
</h1>
|
||||
</div>
|
||||
<nav class="space-x-6 hidden md:flex items-center">
|
||||
<a href="#news" class="hover:text-secondary">新闻</a>
|
||||
<a href="#events" class="hover:text-secondary">活动</a>
|
||||
<a href="#donate" class="hover:text-secondary">捐赠(未开放)</a>
|
||||
<a href="#about" class="hover:text-secondary">关于</a>
|
||||
<a href="/join-us"
|
||||
class="inline-flex items-center gap-2 bg-secondary text-white px-4 py-2 rounded-xl shadow hover:opacity-90">
|
||||
加入
|
||||
<Icon name="mdi:account-plus" class="w-5 h-5" />
|
||||
</a>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
52
app/components/admin/contents/news/AddModal.vue
Normal file
52
app/components/admin/contents/news/AddModal.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<UModal v-model:open="open" title="撰写新闻" description="在数据库中添加一篇新闻">
|
||||
<UButton label="撰写新闻" icon="mdi:newspaper-plus" />
|
||||
|
||||
<template #body>
|
||||
<UForm :schema="newsSchema" :state="newsState" @submit="onSubmit">
|
||||
<UFormField label="新闻标题" name="title">
|
||||
<UInput v-model="newsState.title" placeholder="请输入新闻标题" class="w-full" />
|
||||
</UFormField>
|
||||
<UFormField label="新闻内容" name="contents">
|
||||
<UTextarea v-model="newsState.content" class="w-full" />
|
||||
</UFormField>
|
||||
这里应该是要有一个 Markdown 编辑界面
|
||||
<div class="flex justify-end gap-2">
|
||||
<UButton label="Cancel" color="neutral" variant="subtle" @click="open = false" />
|
||||
<UButton label="Create" color="primary" variant="solid" type="submit" />
|
||||
</div>
|
||||
</UForm>
|
||||
</template>
|
||||
</UModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { FormSubmitEvent } from '@nuxt/ui';
|
||||
import * as z from 'zod'
|
||||
|
||||
const open = ref(false);
|
||||
|
||||
const newsSchema = z.object({
|
||||
title: z.string().min(2, '标题太短了容易产生歧义,请写长一些').max(15, '标题太长了影响阅读体验,请简短一些'),
|
||||
content: z.string()
|
||||
})
|
||||
|
||||
type NewsSchema = z.output<typeof newsSchema>
|
||||
|
||||
const newsState = reactive<Partial<NewsSchema>>({
|
||||
title: undefined,
|
||||
content: undefined
|
||||
})
|
||||
|
||||
const toast = useToast();
|
||||
const onSubmit = async (event: FormSubmitEvent<NewsSchema>) => {
|
||||
toast.add({
|
||||
title: "成功",
|
||||
description: `${event.data.title} 新闻稿已经撰写完毕`,
|
||||
color: 'success'
|
||||
})
|
||||
open.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 捐赠模块 -->
|
||||
<section id="donate" class="py-16 text-center bg-[var(--color-primary)]">
|
||||
<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-[var(--color-secondary)] text-white px-8 py-3 rounded-xl shadow hover:opacity-90">立即捐赠</a>
|
||||
<a href="#" class="bg-primary text-white px-8 py-3 rounded-xl shadow hover:opacity-90">立即捐赠</a>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<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-secondary text-white px-5 py-2 rounded-lg hover:opacity-90">阅读详情</a>
|
||||
<a :href="event.path" class="bg-primary text-white px-5 py-2 rounded-lg hover:opacity-90">阅读详情</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<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-secondary border-4" />
|
||||
<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>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Hero Banner -->
|
||||
<section class="relative bg-primary py-32 md:py-48 lg:py-64 text-center bg-cover bg-center"
|
||||
<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>
|
||||
@@ -15,7 +15,7 @@
|
||||
马来西亚柔佛永平中学校友会官方网站
|
||||
</p>
|
||||
<div class="mt-6 space-x-4">
|
||||
<a href="/join-us" class="bg-secondary text-white px-6 py-3 rounded-xl shadow hover:opacity-90">
|
||||
<a href="/join-us" class="bg-primary text-white px-6 py-3 rounded-xl shadow hover:opacity-90">
|
||||
立即加入我们
|
||||
</a>
|
||||
<!-- <a href="#donate"
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
<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-primary/10 rounded-xl shadow cursor-pointer transition transform hover:-translate-y-1 hover:scale-105 hover:shadow-xl duration-300 ease-in-out">
|
||||
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-primary/25 border-primary border-2 rounded-xl text-secondary text-sm mb-2">{{
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user