TechCorp/app/news/[id]/page.tsx

91 lines
3.2 KiB
TypeScript
Raw Normal View History

2025-09-16 17:40:37 +08:00
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';
import { notFound } from 'next/navigation';
import { useTranslation } from '../../../lib/i18n/useTranslation';
import { languages } from '../../../lib/i18n/config';
const NEWS_DIR = path.join(process.cwd(), 'content/news');
export async function generateStaticParams() {
const files = fs.readdirSync(NEWS_DIR);
return files.map((file) => ({ id: file.replace(/\.md$/, '') }));
}
async function getNewsData(id: string) {
const filePath = path.join(NEWS_DIR, `${id}.md`);
if (!fs.existsSync(filePath)) return null;
const fileContent = fs.readFileSync(filePath, 'utf-8');
const { data, content } = matter(fileContent);
// 提取多语言正文
const langSections: Record<string, string> = {};
let currentLang = '';
let buffer: string[] = [];
for (const line of content.split('\n')) {
const langMatch = line.match(/^##\s*(\w[\w-]*)/);
if (langMatch) {
if (currentLang && buffer.length) {
langSections[currentLang] = buffer.join('\n').trim();
}
currentLang = langMatch[1];
buffer = [];
} else if (currentLang) {
buffer.push(line);
}
}
if (currentLang && buffer.length) {
langSections[currentLang] = buffer.join('\n').trim();
}
return { frontmatter: data, langSections };
}
export default async function NewsDetailPage({ params }: { params: { id: string } }) {
const { id } = params;
const news = await getNewsData(id);
if (!news) return notFound();
// 默认语言优先级
const langOrder = ['en', 'zh-CN', 'zh-TW'];
// 这里假设 SSR 时用 Accept-Language 或默认 en
let lang = langOrder.find((l) => news.langSections[l]);
let htmlContent = '';
if (lang) {
htmlContent = (await remark().use(html).process(news.langSections[lang])).toString();
}
// 渲染页面
return (
<div
className="min-h-screen bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50"
data-oid="7k5q43s"
>
<div className="max-w-4xl mx-auto py-16 px-4" data-oid="7y520yg">
<h1 className="text-4xl font-bold mb-4" data-oid="pj.he2s">
{news.frontmatter[`title_${lang}`] || news.frontmatter.title}
</h1>
<div className="text-gray-500 mb-2" data-oid="rgvpuvi">
{news.frontmatter.date} · {news.frontmatter.readTime} ·{' '}
{news.frontmatter.category}
</div>
<div className="mb-6" data-oid="dwkw1qu">
<img
src={news.frontmatter.image}
alt={news.frontmatter.title}
className="rounded-xl w-full h-80 object-cover"
data-oid="qdo4b98"
/>
</div>
<div
className="prose prose-lg max-w-none"
dangerouslySetInnerHTML={{ __html: htmlContent }}
data-oid="by0i9t7"
/>
</div>
</div>
);
}