Files
sage-home/app/[locale]/line/[slug]/page.tsx
砂糖 99ce2b7fb8 feat: 更新网站配置和内容,优化国际化设置
refactor: 重构产线页面和路由,移除无用代码
style: 调整内容格式和样式,统一中英文标点
docs: 更新产品描述和元数据,完善多语言支持
2026-01-26 16:22:07 +08:00

145 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { LOCALES } from "@/i18n/routing";
import { getLine, getLines } from "@/lib/lines";
import { constructMetadata } from "@/lib/metadata";
import { Line } from "@/types/line";
import { Metadata } from "next";
import { Locale } from "next-intl";
// 强制静态渲染
export const dynamic = "force-static";
// 固定 Params 类型为普通对象Next.js 原生传参无异步)
type Params = {
locale: string;
slug: string;
};
type MetadataProps = {
params: Params;
};
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
const { locale, slug } = await params;
const line = await getLine(locale, slug);
if (!line) {
return constructMetadata({
title: "404 - 产线不存在",
description: "请求的产线页面未找到",
noIndex: true,
locale: locale as Locale,
path: `/line/${slug}`,
canonicalUrl: `/line/${slug}`,
});
}
return constructMetadata({
title: line.title,
description: line.desc,
locale: locale as Locale,
path: `/line/${slug}`,
canonicalUrl: `/line/${slug}`,
});
}
// 页面主组件 - 仅保留字段展示+修复 Hydration 错误
export default async function ProductDetailPage({ params }: { params: Params }) {
// 🔴 修复params 是同步对象,移除不必要的 await
const { locale, slug } = await params;
const line = await getLine(locale, slug);
if (!line) return <div className="p-6">404 - 线</div>;
return (
<div className="product-detail max-w-5xl mx-auto p-6 md:p-8">
{/* 标题 */}
<h1 className="text-3xl md:text-4xl font-bold text-gray-800 mb-4">
{line.title}
</h1>
{/* 产品描述 */}
<p className="text-gray-700 text-lg mb-8 leading-relaxed">
{line.desc}
</p>
{/* 封面图 */}
{line.cover && (
<div className="mb-8 rounded-lg overflow-hidden shadow-md">
<img
src={line.cover}
alt={`${line.title} - 封面`}
className="w-full h-auto object-cover"
loading="lazy"
/>
</div>
)}
{/* 产品图片列表 */}
{line.images && line.images.length > 0 && (
<div className="mb-8">
<h2 className="text-2xl md:text-3xl font-semibold text-gray-800 mb-4">
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6">
{line.images.map((imgUrl, index) => (
<div
key={index}
className="rounded-lg overflow-hidden shadow-sm"
>
<img
src={imgUrl}
alt={`${line.title} - 图片${index + 1}`}
className="w-full h-auto object-cover"
loading="lazy"
/>
</div>
))}
</div>
</div>
)}
{/* 产品特性/参数 */}
{line.properties && line.properties.length > 0 && (
<div className="mb-4">
<h2 className="text-2xl md:text-3xl font-semibold text-gray-800 mb-4">
</h2>
<ul className="space-y-3">
{line.properties.map((prop, index) => (
<li
key={index}
className="p-4 bg-gray-50 rounded-lg text-gray-700"
>
{/* 处理参数中的换行符 \n */}
<span
dangerouslySetInnerHTML={{
__html: prop.replace(/\n/g, "<br />"),
}}
/>
</li>
))}
</ul>
</div>
)}
</div>
);
}
export async function generateStaticParams() {
try {
const defaultLocale = LOCALES[0];
const lines: Line[] = await getLines(defaultLocale);
return LOCALES.flatMap((locale) =>
lines.map((line) => ({
locale,
slug: line.slug as string,
}))
);
} catch (error) {
console.error("生成产线静态参数失败:", error);
return [];
}
}