Compare commits
2 Commits
dbd1abdc1c
...
9bca019b50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bca019b50 | ||
|
|
6288a1b01b |
@@ -7,9 +7,13 @@
|
|||||||
<!-- 卡片装饰边框(浅色渐变) -->
|
<!-- 卡片装饰边框(浅色渐变) -->
|
||||||
<!-- <div class="absolute inset-0 bg-linear-to-r from-blue-100 to-purple-100 rounded-2xl blur-sm"></div> -->
|
<!-- <div class="absolute inset-0 bg-linear-to-r from-blue-100 to-purple-100 rounded-2xl blur-sm"></div> -->
|
||||||
|
|
||||||
<div class="relative rounded-xl border border-gray-200 shadow-xl overflow-hidden">
|
<div
|
||||||
|
class="relative rounded-xl border border-gray-200 shadow-xl overflow-hidden"
|
||||||
|
>
|
||||||
<!-- 顶部装饰条(明亮渐变) -->
|
<!-- 顶部装饰条(明亮渐变) -->
|
||||||
<div class="h-1 bg-linear-to-r from-blue-400 via-purple-400 to-cyan-400"></div>
|
<div
|
||||||
|
class="h-1 bg-linear-to-r from-blue-400 via-purple-400 to-cyan-400"
|
||||||
|
></div>
|
||||||
|
|
||||||
<div class="p-8 sm:p-10 lg:p-12">
|
<div class="p-8 sm:p-10 lg:p-12">
|
||||||
<!-- 内容渲染器 -->
|
<!-- 内容渲染器 -->
|
||||||
@@ -17,16 +21,32 @@
|
|||||||
<ContentRenderer :value="event ?? {}">
|
<ContentRenderer :value="event ?? {}">
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<div class="text-center py-16">
|
<div class="text-center py-16">
|
||||||
<div class="inline-flex items-center justify-center w-16 h-16 bg-blue-100 rounded-full mb-4">
|
<div
|
||||||
<svg class="w-8 h-8 text-blue-500 animate-spin" fill="none" viewBox="0 0 24 24">
|
class="inline-flex items-center justify-center w-16 h-16 bg-blue-100 rounded-full mb-4"
|
||||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4">
|
>
|
||||||
</circle>
|
<svg
|
||||||
<path class="opacity-75" fill="currentColor"
|
class="w-8 h-8 text-blue-500 animate-spin"
|
||||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
|
fill="none"
|
||||||
</path>
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<circle
|
||||||
|
class="opacity-25"
|
||||||
|
cx="12"
|
||||||
|
cy="12"
|
||||||
|
r="10"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="4"
|
||||||
|
></circle>
|
||||||
|
<path
|
||||||
|
class="opacity-75"
|
||||||
|
fill="currentColor"
|
||||||
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||||
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-gray-700 text-lg font-medium">内容加载中...</p>
|
<p class="text-gray-700 text-lg font-medium">
|
||||||
|
内容加载中...
|
||||||
|
</p>
|
||||||
<p class="text-gray-400 text-sm mt-2">请稍等片刻</p>
|
<p class="text-gray-400 text-sm mt-2">请稍等片刻</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -41,16 +61,43 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
const route = useRoute()
|
const route = useRoute();
|
||||||
const { data: event } = await useAsyncData('event-detail', () =>
|
const { data: event } = await useAsyncData("event-detail", () =>
|
||||||
queryCollection('events')
|
queryCollection("events").path(`/events/${route.params.slug}`).first()
|
||||||
.path(`/events/${route.params.slug}`)
|
);
|
||||||
.first()
|
|
||||||
)
|
|
||||||
|
|
||||||
useHead({
|
if (event.value) {
|
||||||
title: event.value?.title
|
// 1. 确定图片:优先用 ogImage,没有就用 cover
|
||||||
})
|
const shareImage = event.value.ogImage || event.value.cover;
|
||||||
|
|
||||||
|
// 2. 确定标题和描述:优先用 seoTitle,没有就用 title
|
||||||
|
const shareTitle = event.value.seoTitle || event.value.title;
|
||||||
|
const shareDesc = event.value.seoDescription || event.value.description;
|
||||||
|
|
||||||
|
// 3. 注入 SEO
|
||||||
|
useSeoMeta({
|
||||||
|
// 基础
|
||||||
|
title: shareTitle,
|
||||||
|
description: shareDesc,
|
||||||
|
|
||||||
|
// Open Graph (Facebook / WhatsApp)
|
||||||
|
ogTitle: shareTitle,
|
||||||
|
ogDescription: shareDesc,
|
||||||
|
ogImage: shareImage,
|
||||||
|
ogType: "article",
|
||||||
|
|
||||||
|
// Twitter Card
|
||||||
|
twitterCard: "summary_large_image",
|
||||||
|
twitterTitle: shareTitle,
|
||||||
|
twitterDescription: shareDesc,
|
||||||
|
twitterImage: shareImage,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果你用了 nuxt-og-image 模块生成动态图
|
||||||
|
if (shareImage) {
|
||||||
|
defineOgImage({ url: shareImage });
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { defineContentConfig, defineCollection, z } from "@nuxt/content";
|
import { defineContentConfig, defineCollection, z } from "@nuxt/content";
|
||||||
|
import { asSeoCollection } from "@nuxtjs/seo/content";
|
||||||
|
|
||||||
export default defineContentConfig({
|
export default defineContentConfig({
|
||||||
collections: {
|
collections: {
|
||||||
@@ -12,11 +13,12 @@ export default defineContentConfig({
|
|||||||
date: z.coerce.date(),
|
date: z.coerce.date(),
|
||||||
location: z.string(),
|
location: z.string(),
|
||||||
cover: z.string().url(),
|
cover: z.string().url(),
|
||||||
draft: z.boolean().optional().default(false)
|
draft: z.boolean().optional().default(false),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
// 新闻集合
|
// 新闻集合
|
||||||
news: defineCollection({
|
news: defineCollection(
|
||||||
|
asSeoCollection({
|
||||||
type: "page",
|
type: "page",
|
||||||
source: "news/*.md",
|
source: "news/*.md",
|
||||||
schema: z.object({
|
schema: z.object({
|
||||||
@@ -32,9 +34,10 @@ export default defineContentConfig({
|
|||||||
seoTitle: z.string().optional(),
|
seoTitle: z.string().optional(),
|
||||||
seoDescription: z.string().optional(),
|
seoDescription: z.string().optional(),
|
||||||
ogImage: z.string().optional(),
|
ogImage: z.string().optional(),
|
||||||
draft: z.boolean().optional().default(false)
|
draft: z.boolean().optional().default(false),
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
|
})
|
||||||
|
),
|
||||||
// 名人堂
|
// 名人堂
|
||||||
hallOfFames: defineCollection({
|
hallOfFames: defineCollection({
|
||||||
type: "page",
|
type: "page",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ title: "永平中学第 60 届毕业典礼"
|
|||||||
subtitle: "暨初中第 67 届毕业典礼"
|
subtitle: "暨初中第 67 届毕业典礼"
|
||||||
date: "2025-11-15"
|
date: "2025-11-15"
|
||||||
location: "永平中学邱廉书礼堂"
|
location: "永平中学邱廉书礼堂"
|
||||||
# cover: "/events/20250927-return-to-school/event-photo-1.jpg"
|
cover: "https://img.yphsalumni.org/i/2025/11/27/st6hzt.jpg"
|
||||||
draft: false
|
draft: false
|
||||||
|
|
||||||
# SEO 主要字段
|
# SEO 主要字段
|
||||||
@@ -17,49 +17,39 @@ keywords:
|
|||||||
- 刘连升老师
|
- 刘连升老师
|
||||||
- 永中校友会
|
- 永中校友会
|
||||||
|
|
||||||
# Open Graph / Facebook
|
# --- SEO 专用字段 (对应你的 Zod Schema) ---
|
||||||
og:
|
|
||||||
title: "永平中学第 60 届毕业典礼|初中第 67 届毕业典礼"
|
|
||||||
description: "2025 年永平中学毕业典礼隆重举行,包含师长致辞、奖学金颁发、荣休老师欢送,以及学生精彩演出等精彩环节。"
|
|
||||||
# image: "/events/20250927-return-to-school/event-photo-1.jpg"
|
|
||||||
type: "article"
|
|
||||||
|
|
||||||
# Twitter 卡片
|
# 对应 schema: seoTitle
|
||||||
twitter:
|
# 如果不填,代码里会默认使用 title
|
||||||
card: "summary_large_image"
|
seoTitle: "永平中学第 60 届毕业典礼|初中第 67 届毕业典礼"
|
||||||
title: "永平中学第 60 届毕业典礼"
|
|
||||||
description: "永平中学 2025 毕业典礼精彩回顾:致辞、演出、奖学金颁发与荣休教师表扬。"
|
|
||||||
# image: "/events/20250927-return-to-school/event-photo-1.jpg"
|
|
||||||
|
|
||||||
# 文章结构化数据(可选,Nuxt SEO module 会自动识别)
|
# 对应 schema: seoDescription
|
||||||
structuredData:
|
# 如果不填,代码里会默认使用 description
|
||||||
"@type": "NewsArticle"
|
seoDescription: "2025 年永平中学毕业典礼隆重举行,包含师长致辞、奖学金颁发、荣休老师欢送,以及学生精彩演出等精彩环节。"
|
||||||
headline: "永平中学第 60 届毕业典礼圆满举行"
|
|
||||||
# image: "/events/20250927-return-to-school/event-photo-1.jpg"
|
# 对应 schema: ogImage
|
||||||
datePublished: "2025-11-15"
|
# 只有当你想要分享的图片和封面图不一样时才填,否则代码里会默认用 cover
|
||||||
author:
|
ogImage: "https://img.yphsalumni.org/i/2025/11/27/st6hzt.jpg"
|
||||||
"@type": "Organization"
|
|
||||||
name: "永平中学校友会"
|
|
||||||
publisher:
|
|
||||||
"@type": "Organization"
|
|
||||||
name: "永平中学"
|
|
||||||
logo:
|
|
||||||
"@type": "ImageObject"
|
|
||||||
url: "/logo.png"
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 永平中学高中第 60 届、初中第 67 届毕业典礼圆满举行
|
# 永平中学高中第 60 届、初中第 67 届毕业典礼圆满举行
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
2025 年 11 月 15 日,永平中学邱廉书礼堂见证了一个充满祝福与感动的重要时刻:高中第 60 届与初中第 67 届毕业典礼隆重举行。礼堂内座无虚席,毕业生、家长、师长与嘉宾齐聚一堂,共同庆祝学子们学习旅程的重要里程碑。
|
2025 年 11 月 15 日,永平中学邱廉书礼堂见证了一个充满祝福与感动的重要时刻:高中第 60 届与初中第 67 届毕业典礼隆重举行。礼堂内座无虚席,毕业生、家长、师长与嘉宾齐聚一堂,共同庆祝学子们学习旅程的重要里程碑。
|
||||||
|
|
||||||
经过六年的努力与成长,高三学生正式迎来人生的新阶段;初三毕业生亦迈向更高层次的挑战。典礼在庄严的国州歌声中启幕,掀开充满意义的一天。
|
经过六年的努力与成长,高三学生正式迎来人生的新阶段;初三毕业生亦迈向更高层次的挑战。典礼在庄严的国州歌声中启幕,掀开充满意义的一天。
|
||||||
|
|
||||||
## 董事长马彣清博士致词(由代表宣读)
|
## 董事长马彣清博士致词(由代表宣读)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
因公务繁忙未克出席,马彣清董事长由董事会秘书长黄仰力董事代表致辞。他转达董事长的寄语:“成功从来不是侥幸,而是毅力不断累积的成果。” 同时肯定毕业生在求学路上的坚持,并勉励他们继续以积极态度面对未来。
|
因公务繁忙未克出席,马彣清董事长由董事会秘书长黄仰力董事代表致辞。他转达董事长的寄语:“成功从来不是侥幸,而是毅力不断累积的成果。” 同时肯定毕业生在求学路上的坚持,并勉励他们继续以积极态度面对未来。
|
||||||
|
|
||||||
## 张嘉群校长三项叮咛:以品格与眼界开创未来
|
## 张嘉群校长三项叮咛:以品格与眼界开创未来
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
张嘉群校长在致辞中寄语毕业生,并提出三项叮咛,期许他们在往后的道路上继续发光发热:
|
张嘉群校长在致辞中寄语毕业生,并提出三项叮咛,期许他们在往后的道路上继续发光发热:
|
||||||
|
|
||||||
### 叮咛一:永怀初心
|
### 叮咛一:永怀初心
|
||||||
@@ -79,10 +69,14 @@ structuredData:
|
|||||||
|
|
||||||
## 柔佛州董联会主席兼校务顾问陈大锦先生致辞
|
## 柔佛州董联会主席兼校务顾问陈大锦先生致辞
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
陈大锦先生分享了他访问上海中医药大学的见闻,特别是该校完善的奖助学金制度。他希望本校辅导处与升学资讯处能协助学生把握机会,踊跃申请明年 9 月开课的相关奖学金,为升学之路开拓更多可能。
|
陈大锦先生分享了他访问上海中医药大学的见闻,特别是该校完善的奖助学金制度。他希望本校辅导处与升学资讯处能协助学生把握机会,踊跃申请明年 9 月开课的相关奖学金,为升学之路开拓更多可能。
|
||||||
|
|
||||||
## 欢送刘连升老师光荣荣休
|
## 欢送刘连升老师光荣荣休
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
在典礼上,校方特别举行了“欢送刘连升老师荣休”环节,为这位服务永平中学 35 年、深受师生爱戴的资深教师献上诚挚祝福。
|
在典礼上,校方特别举行了“欢送刘连升老师荣休”环节,为这位服务永平中学 35 年、深受师生爱戴的资深教师献上诚挚祝福。
|
||||||
|
|
||||||
刘连升老师在任职期间,以其和蔼可亲的性格与渊博的历史知识,陪伴无数学生走过求学阶段。他不仅课堂上“聊古论今”,从古代帝王先烈谈到世界变迁,更在课余时与学生畅谈时事,从传统文化一路聊到新兴科技与 AI 技术,是学生眼中既严谨又风趣的良师益友。
|
刘连升老师在任职期间,以其和蔼可亲的性格与渊博的历史知识,陪伴无数学生走过求学阶段。他不仅课堂上“聊古论今”,从古代帝王先烈谈到世界变迁,更在课余时与学生畅谈时事,从传统文化一路聊到新兴科技与 AI 技术,是学生眼中既严谨又风趣的良师益友。
|
||||||
@@ -94,10 +88,12 @@ structuredData:
|
|||||||
## 颁发董事长设立的奖学金
|
## 颁发董事长设立的奖学金
|
||||||
|
|
||||||
典礼上同步进行董事长设立的各项奖学金颁发仪式,以表扬在学业、操行与综合表现上有卓越成绩的学生。
|
典礼上同步进行董事长设立的各项奖学金颁发仪式,以表扬在学业、操行与综合表现上有卓越成绩的学生。
|
||||||
(详见图集)
|
(详见[图集](https://drive.google.com/drive/folders/1n3aRxxBwn-k6jzAOogV2ChBHKDA0c0qG))
|
||||||
|
|
||||||
## 特别演出:永中之星冠军林妤桐献唱
|
## 特别演出:永中之星冠军林妤桐献唱
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
在典礼进入高潮之前,校方安排了一场温馨惊喜表演 —— 第一届“永中之星”冠军、来自初三诚的林妤桐学妹献唱两首歌曲:《Forever Young》以及《凤凰花开的路口》。她以清亮而富感染力的歌声,向高三学长姐献上最真挚的祝福,也为典礼增添一份青春与深情的色彩。
|
在典礼进入高潮之前,校方安排了一场温馨惊喜表演 —— 第一届“永中之星”冠军、来自初三诚的林妤桐学妹献唱两首歌曲:《Forever Young》以及《凤凰花开的路口》。她以清亮而富感染力的歌声,向高三学长姐献上最真挚的祝福,也为典礼增添一份青春与深情的色彩。
|
||||||
|
|
||||||
## 高三教师团队呈献毕业回忆视频
|
## 高三教师团队呈献毕业回忆视频
|
||||||
@@ -108,6 +104,10 @@ structuredData:
|
|||||||
|
|
||||||
## 歌声中道别,在掌声中启航
|
## 歌声中道别,在掌声中启航
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
典礼尾声,高三毕业生深情演唱《再见》,而初三与高三学生共同合唱《毕业歌》,歌声回荡礼堂,为今年的毕业典礼写下温馨句点。现场气氛在歌声中变得格外动人,许多毕业生眼眶泛红,纷纷表示将铭记这一刻。
|
典礼尾声,高三毕业生深情演唱《再见》,而初三与高三学生共同合唱《毕业歌》,歌声回荡礼堂,为今年的毕业典礼写下温馨句点。现场气氛在歌声中变得格外动人,许多毕业生眼眶泛红,纷纷表示将铭记这一刻。
|
||||||
|
|
||||||
上午 11 时正,典礼圆满结束。为感谢师生与来宾的参与,马彣清董事长特别准备了供 600 人享用的自助餐,设宴于礼堂楼下。现场气氛融洽温馨。同时,本校友会也成功招收 14 名新会员,为未来的发展注入新的力量。
|
上午 11 时正,典礼圆满结束。为感谢师生与来宾的参与,马彣清董事长特别准备了供 600 人享用的自助餐,设宴于礼堂楼下。现场气氛融洽温馨。同时,本校友会也成功招收 14 名新会员,为未来的发展注入新的力量。
|
||||||
|
|
||||||
|
[2025 年毕业典礼图集](https://drive.google.com/drive/folders/1n3aRxxBwn-k6jzAOogV2ChBHKDA0c0qG)
|
||||||
@@ -5,14 +5,15 @@ export default defineNuxtConfig({
|
|||||||
compatibilityDate: "2025-07-15",
|
compatibilityDate: "2025-07-15",
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
modules: [
|
modules: [
|
||||||
"@nuxtjs/seo",
|
|
||||||
"@nuxt/ui",
|
"@nuxt/ui",
|
||||||
|
"@nuxtjs/seo",
|
||||||
"@nuxt/content",
|
"@nuxt/content",
|
||||||
"@nuxt/image",
|
"@nuxt/image",
|
||||||
"reka-ui/nuxt",
|
"reka-ui/nuxt",
|
||||||
"@nuxtjs/robots",
|
"@nuxtjs/robots",
|
||||||
"@nuxtjs/sitemap",
|
"@nuxtjs/sitemap",
|
||||||
],
|
],
|
||||||
|
ssr: true,
|
||||||
css: ["~/assets/css/main.css"],
|
css: ["~/assets/css/main.css"],
|
||||||
vite: {
|
vite: {
|
||||||
plugins: [tailwindcss()],
|
plugins: [tailwindcss()],
|
||||||
|
|||||||
Reference in New Issue
Block a user