feat(seo): improve SEO configuration and enable SSR

- Enable `ssr: true` in `nuxt.config.ts` for server-side rendering of meta tags.
- Implement `useSeoMeta` in `events/.vue` with fallback logic for Open Graph and Twitter cards.
- Update `content.config.ts` to use `asSeoCollection` for the news collection.
- Migrate event markdown frontmatter to use standardized SEO fields.
This commit is contained in:
xiaomai
2025-11-27 23:07:24 +08:00
parent 6288a1b01b
commit 9bca019b50
4 changed files with 102 additions and 67 deletions

View File

@@ -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="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">
<!-- 内容渲染器 -->
@@ -17,16 +21,32 @@
<ContentRenderer :value="event ?? {}">
<template #empty>
<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">
<svg class="w-8 h-8 text-blue-500 animate-spin" fill="none" 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>
<div
class="inline-flex items-center justify-center w-16 h-16 bg-blue-100 rounded-full mb-4"
>
<svg
class="w-8 h-8 text-blue-500 animate-spin"
fill="none"
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>
</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>
</div>
</template>
@@ -41,16 +61,43 @@
</template>
<script lang="ts" setup>
const route = useRoute()
const { data: event } = await useAsyncData('event-detail', () =>
queryCollection('events')
.path(`/events/${route.params.slug}`)
.first()
)
const route = useRoute();
const { data: event } = await useAsyncData("event-detail", () =>
queryCollection("events").path(`/events/${route.params.slug}`).first()
);
useHead({
title: event.value?.title
})
if (event.value) {
// 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>
<style scoped></style>