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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user