42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
import { notFound } from "next/navigation";
|
|
import type { Metadata } from "next";
|
|
import { getBlogBySlug } from "@/services/blog.service";
|
|
import { getPreviewOrFallback } from "@/services/preview.service";
|
|
import { BlockRenderer } from "@/blocks/BlockRenderer";
|
|
import type { BlogPageDetail } from "@/types/wagtail";
|
|
|
|
interface BlogDetailPageProps {
|
|
params: Promise<{ slug: string }>;
|
|
}
|
|
|
|
export async function generateMetadata({
|
|
params,
|
|
}: BlogDetailPageProps): Promise<Metadata> {
|
|
const { slug } = await params;
|
|
const post = await getBlogBySlug(slug).catch(() => null);
|
|
return { title: post?.title ?? "文章未找到" };
|
|
}
|
|
|
|
export default async function BlogDetailPage({ params }: BlogDetailPageProps) {
|
|
const { slug } = await params;
|
|
const post = await getPreviewOrFallback<BlogPageDetail>(
|
|
"blog.blogpage",
|
|
"body,intro,published_at",
|
|
() => getBlogBySlug(slug).catch(() => null),
|
|
);
|
|
|
|
if (!post) {
|
|
notFound();
|
|
}
|
|
|
|
return (
|
|
<article className="mx-auto max-w-3xl px-6 py-24">
|
|
<h1 className="mb-4 text-4xl font-bold text-slate-900">{post.title}</h1>
|
|
{post.published_at && (
|
|
<p className="mb-12 text-sm text-slate-500">{post.published_at}</p>
|
|
)}
|
|
<BlockRenderer blocks={post.body} />
|
|
</article>
|
|
);
|
|
}
|