This commit is contained in:
砂糖
2026-01-24 16:54:44 +08:00
commit 70f337bb92
186 changed files with 23792 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
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 workShops: Line[] = await getLines(defaultLocale);
return LOCALES.flatMap((locale) =>
workShops.map((workShop) => ({
locale,
slug: workShop.slug as string,
}))
);
} catch (error) {
console.error("生成产品静态参数失败:", error);
return [];
}
}