feat: 补全剩余 6 个 StreamField Block 前端渲染 (ProductCard/Pricing/Timeline/Team/TechStack/Video)

- types/wagtail.ts 新增对应 6 个 Block 值类型接口及 StreamFieldBlock 联合类型分支
- 新建 6 个渲染组件:ProductCardGrid/Pricing/Timeline/Team/TechStack/Video,风格与既有 Block 一致
- BlockRenderer.tsx 映射表接入新组件,key 与后端 COMMON_BLOCKS 保持一致
- lint/build 均验证通过
This commit is contained in:
2026-08-07 15:59:08 +08:00
parent 2457d5ec69
commit 4bbd6947da
8 changed files with 314 additions and 1 deletions
+46
View File
@@ -0,0 +1,46 @@
import Link from "next/link";
import Image from "next/image";
import type { ProductCardBlockValue } from "@/types/wagtail";
export default function ProductCardGrid({ value }: { value: ProductCardBlockValue }) {
return (
<section className="py-24">
<div className="mx-auto max-w-7xl px-6">
{value.heading && (
<h2 className="mb-16 text-4xl font-bold text-slate-900">{value.heading}</h2>
)}
<div className="grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
{value.items?.map((item, index) => {
const card = (
<div className="h-full rounded-3xl border border-slate-100 p-6 shadow-sm transition hover:shadow-md">
{item.image && (
<Image
src={item.image.url}
alt={item.image.title}
width={400}
height={240}
className="mb-6 h-40 w-full rounded-2xl object-cover"
/>
)}
<h3 className="mb-2 text-xl font-semibold text-slate-900">
{item.title}
</h3>
{item.description && (
<p className="text-slate-600">{item.description}</p>
)}
</div>
);
const key = `${item.title}-${index}`;
return item.link ? (
<Link key={key} href={item.link} className="block h-full">
{card}
</Link>
) : (
<div key={key}>{card}</div>
);
})}
</div>
</div>
</section>
);
}