154 lines
5.2 KiB
TypeScript
Raw Permalink Normal View History

2025-09-16 17:19:58 +08:00
import type { Metadata } from 'next';
import { getSEOConfig } from '../../../../lib/seo-config';
import { Article } from '@/lib/types';
import NewsArticleServerComponent from '@/app/components/news/NewsArticleServerComponent';
import { notFound } from 'next/navigation';
// 服务端获取文章数据
async function getArticleData(slug: string, locale: string) {
try {
// 检查是否为静态导出模式
const isStaticMode = process.env.BUILD_MODE === 'static';
if (isStaticMode) {
// 静态模式下直接从文件系统读取
const { getStaticArticleBySlug, getStaticArticles } = await import('../../../../lib/static-data');
const article = getStaticArticleBySlug(slug, locale as 'zh-CN' | 'zh-TW' | 'en');
if (!article) {
return null;
}
// 获取相关文章
const allArticles = getStaticArticles(locale as 'zh-CN' | 'zh-TW' | 'en');
const relatedArticles = allArticles
.filter(a => a.slug !== slug && a.metadata.category === article.metadata.category)
.slice(0, 3);
return { article, relatedArticles };
} else {
// 开发模式下使用 API
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000';
const response = await fetch(`${baseUrl}/api/articles/${slug}?locale=${locale}`, {
// 使用 ISR 缓存策略1小时后重新验证
next: { revalidate: 3600 }
});
if (!response.ok) {
if (response.status === 404) {
return null;
}
throw new Error('Failed to fetch article');
}
const data = await response.json();
return data;
}
} catch (error) {
console.error('Error fetching article:', error);
return null;
}
}
// 生成静态参数
export async function generateStaticParams() {
const { getStaticArticles } = await import('../../../../lib/static-data');
const locales = ['zh-CN', 'zh-TW', 'en'];
const params = [];
for (const locale of locales) {
const articles = getStaticArticles(locale as 'zh-CN' | 'zh-TW' | 'en');
for (const article of articles) {
// 为每个locale生成对应的路由参数
if (locale === 'zh-CN') {
// 为简体中文生成两个路由zh 和 zh-CN
params.push({
locale: 'zh',
id: article.slug,
});
params.push({
locale: 'zh-CN',
id: article.slug,
});
} else {
params.push({
locale: locale,
id: article.slug,
});
}
}
}
return params;
}
// 生成动态元数据
export async function generateMetadata({
params: { locale, id },
}: {
params: { locale: string; id: string };
}): Promise<Metadata> {
const mappedLocale = locale === 'zh' ? 'zh-CN' : locale === 'zh-CN' ? 'zh-CN' : locale === 'zh-TW' ? 'zh-TW' : 'en';
const data = await getArticleData(id, mappedLocale);
if (!data?.article) {
return {
title: '文章未找到 - AwsLinker',
description: '您访问的文章不存在或已被移除。',
};
}
const article: Article = data.article;
const language = mappedLocale;
return {
title: `${article.metadata.title} - AwsLinker`,
description: article.metadata.description,
keywords: article.metadata.tags,
openGraph: {
title: article.metadata.title,
description: article.metadata.description,
type: 'article',
images: article.metadata.image ? [{ url: article.metadata.image }] : undefined,
publishedTime: article.metadata.date,
authors: article.metadata.author ? [article.metadata.author] : undefined,
},
twitter: {
card: 'summary_large_image',
title: article.metadata.title,
description: article.metadata.description,
images: article.metadata.image ? [article.metadata.image] : undefined,
},
alternates: {
canonical: locale === 'zh' ? `/news/${id}` : `/${locale}/news/${id}`,
languages: {
'zh-CN': `/news/${id}`,
'zh-TW': `/zh-TW/news/${id}`,
en: `/en/news/${id}`,
},
},
};
}
// 服务器组件 - 预渲染数据
export default async function NewsArticlePage({
params: { locale, id },
}: {
params: { locale: string; id: string };
}) {
const mappedLocale = locale === 'zh' ? 'zh-CN' : locale === 'zh-CN' ? 'zh-CN' : locale === 'zh-TW' ? 'zh-TW' : 'en';
const data = await getArticleData(id, mappedLocale);
if (!data?.article) {
notFound();
}
return (
<NewsArticleServerComponent
article={data.article}
relatedArticles={data.relatedArticles || []}
locale={mappedLocale}
/>
);
}