feat: add products/cases pages and lead-capture form block

- types: Product/CaseStudy page types, CaseStudyBlockValue, FormBlockValue
- services: product.service.ts, case.service.ts
- app/products, app/cases: list + detail pages
- blocks: CaseStudyCard, LeadForm (submits to /api/v1/custom/leads/)
- Header nav: add 产品/案例 links
This commit is contained in:
2026-08-06 16:04:43 +08:00
parent 7e30631c68
commit b5fe5e13ab
11 changed files with 391 additions and 1 deletions
+39
View File
@@ -0,0 +1,39 @@
import { notFound } from "next/navigation";
import type { Metadata } from "next";
import { getProductBySlug } from "@/services/product.service";
import { BlockRenderer } from "@/blocks/BlockRenderer";
interface ProductDetailPageProps {
params: Promise<{ slug: string }>;
}
export async function generateMetadata({
params,
}: ProductDetailPageProps): Promise<Metadata> {
const { slug } = await params;
const product = await getProductBySlug(slug).catch(() => null);
return { title: product?.title ?? "产品未找到" };
}
export default async function ProductDetailPage({
params,
}: ProductDetailPageProps) {
const { slug } = await params;
const product = await getProductBySlug(slug).catch(() => null);
if (!product) {
notFound();
}
return (
<article className="mx-auto max-w-3xl px-6 py-24">
<h1 className="mb-4 text-4xl font-bold text-slate-900">
{product.title}
</h1>
{product.summary && (
<p className="mb-12 text-lg text-slate-600">{product.summary}</p>
)}
<BlockRenderer blocks={product.body} />
</article>
);
}