11import { Metadata } from "next" ;
22import BlogPost from "@/components/BlogPost" ;
33
4- // 动态生成 SEO 信息
5- export async function generateMetadata ( {
6- params,
7- } : {
8- params : Promise < { slug : string } > ;
9- } ) : Promise < Metadata > {
10- const { slug } = await params ;
4+ interface Post {
5+ id : string ;
6+ title : string ;
7+ slug : string ;
8+ content : string ;
9+ excerpt : string | null ;
10+ featured_image : string | null ;
11+ published : boolean ;
12+ author_id : string ;
13+ created_at : string ;
14+ updated_at : string ;
15+ published_at : string ;
16+ labels : string [ ] ;
17+ }
1118
19+ async function getPost ( slug : string ) : Promise < Post | null > {
1220 try {
13- const apiUrl = process . env . INTERNAL_API_BASE_URL ||
21+ const apiUrl =
22+ process . env . INTERNAL_API_BASE_URL ||
1423 process . env . NEXT_PUBLIC_API_BASE_URL ||
1524 "https://api.exquisitecore.xyz/api" ;
1625
@@ -19,24 +28,49 @@ export async function generateMetadata({
1928 } ) ;
2029
2130 if ( response . ok ) {
22- const post = await response . json ( ) ;
23- return {
24- title : post . title ,
25- description : post . excerpt || `阅读ExquisiteCore的文章:${ post . title } ` ,
26- keywords : `${ post . title } ,${ post . labels ?. join ( "," ) || "" } ,ExquisiteCore,技术博客` ,
27- openGraph : {
28- title : post . title ,
29- description : post . excerpt || `阅读ExquisiteCore的文章:${ post . title } ` ,
30- type : "article" ,
31- publishedTime : post . published_at ,
32- modifiedTime : post . updated_at ,
33- tags : post . labels || [ ] ,
34- images : post . featured_image ? [ post . featured_image ] : [ ] ,
35- } ,
36- } ;
31+ return await response . json ( ) ;
3732 }
3833 } catch ( error ) {
39- console . error ( "获取文章元数据失败:" , error ) ;
34+ console . error ( "获取文章失败:" , error ) ;
35+ }
36+ return null ;
37+ }
38+
39+ // 动态生成 SEO 信息
40+ export async function generateMetadata ( {
41+ params,
42+ } : {
43+ params : Promise < { slug : string } > ;
44+ } ) : Promise < Metadata > {
45+ const { slug } = await params ;
46+ const post = await getPost ( slug ) ;
47+
48+ if ( post ) {
49+ return {
50+ title : post . title ,
51+ description : post . excerpt || `阅读ExquisiteCore的文章:${ post . title } ` ,
52+ keywords : `${ post . title } ,${ post . labels ?. join ( "," ) || "" } ,ExquisiteCore,技术博客` ,
53+ openGraph : {
54+ title : post . title ,
55+ description : post . excerpt || `阅读ExquisiteCore的文章:${ post . title } ` ,
56+ type : "article" ,
57+ publishedTime : post . published_at ,
58+ modifiedTime : post . updated_at ,
59+ authors : [ "ExquisiteCore" ] ,
60+ tags : post . labels || [ ] ,
61+ images : post . featured_image ? [ post . featured_image ] : [ ] ,
62+ url : `https://blog.exquisitecore.xyz/blog/${ post . id } ` ,
63+ } ,
64+ twitter : {
65+ card : "summary_large_image" ,
66+ title : post . title ,
67+ description : post . excerpt || `阅读ExquisiteCore的文章:${ post . title } ` ,
68+ images : post . featured_image ? [ post . featured_image ] : [ ] ,
69+ } ,
70+ alternates : {
71+ canonical : `https://blog.exquisitecore.xyz/blog/${ post . id } ` ,
72+ } ,
73+ } ;
4074 }
4175
4276 return {
@@ -45,12 +79,58 @@ export async function generateMetadata({
4579 } ;
4680}
4781
82+ // 生成 Article JSON-LD 结构化数据
83+ function generateArticleJsonLd ( post : Post ) {
84+ return {
85+ "@context" : "https://schema.org" ,
86+ "@type" : "Article" ,
87+ headline : post . title ,
88+ description : post . excerpt || `阅读ExquisiteCore的文章:${ post . title } ` ,
89+ image : post . featured_image || "https://blog.exquisitecore.xyz/logo.svg" ,
90+ datePublished : post . published_at ,
91+ dateModified : post . updated_at ,
92+ author : {
93+ "@type" : "Person" ,
94+ name : "ExquisiteCore" ,
95+ url : "https://blog.exquisitecore.xyz/about" ,
96+ } ,
97+ publisher : {
98+ "@type" : "Organization" ,
99+ name : "ExquisiteCore Blog" ,
100+ logo : {
101+ "@type" : "ImageObject" ,
102+ url : "https://blog.exquisitecore.xyz/logo.svg" ,
103+ } ,
104+ } ,
105+ mainEntityOfPage : {
106+ "@type" : "WebPage" ,
107+ "@id" : `https://blog.exquisitecore.xyz/blog/${ post . id } ` ,
108+ } ,
109+ keywords : post . labels ?. join ( ", " ) || "" ,
110+ articleSection : "技术博客" ,
111+ inLanguage : "zh-CN" ,
112+ } ;
113+ }
114+
48115export default async function BlogPostPage ( {
49116 params,
50117} : {
51118 params : Promise < { slug : string } > ;
52119} ) {
53120 const { slug } = await params ;
121+ const post = await getPost ( slug ) ;
54122
55- return < BlogPost slug = { slug } /> ;
123+ return (
124+ < >
125+ { post && (
126+ < script
127+ type = "application/ld+json"
128+ dangerouslySetInnerHTML = { {
129+ __html : JSON . stringify ( generateArticleJsonLd ( post ) ) ,
130+ } }
131+ />
132+ ) }
133+ < BlogPost slug = { slug } />
134+ </ >
135+ ) ;
56136}
0 commit comments