From 2457d5ec69434d70cbd8384d33ac2a98c6987e63 Mon Sep 17 00:00:00 2001 From: Zhengen TANG Date: Fri, 7 Aug 2026 15:34:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8E=A5=E5=85=A5=E9=A2=84=E8=A7=88?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=EF=BC=88Next.js=20Draft=20Mode=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/blog/[slug]/page.tsx | 8 +++- app/cases/[slug]/page.tsx | 8 +++- app/layout.tsx | 16 ++++++- app/page.tsx | 8 +++- app/preview/disable/route.ts | 18 ++++++++ app/preview/route.ts | 54 +++++++++++++++++++++++ app/products/[slug]/page.tsx | 8 +++- app/solutions/[slug]/page.tsx | 8 +++- services/preview.service.ts | 81 +++++++++++++++++++++++++++++++++++ 9 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 app/preview/disable/route.ts create mode 100644 app/preview/route.ts create mode 100644 services/preview.service.ts diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index a8f5922..4783411 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -1,7 +1,9 @@ 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 }>; @@ -17,7 +19,11 @@ export async function generateMetadata({ export default async function BlogDetailPage({ params }: BlogDetailPageProps) { const { slug } = await params; - const post = await getBlogBySlug(slug).catch(() => null); + const post = await getPreviewOrFallback( + "blog.blogpage", + "body,intro,published_at", + () => getBlogBySlug(slug).catch(() => null), + ); if (!post) { notFound(); diff --git a/app/cases/[slug]/page.tsx b/app/cases/[slug]/page.tsx index 70d00e6..a9c2104 100644 --- a/app/cases/[slug]/page.tsx +++ b/app/cases/[slug]/page.tsx @@ -1,7 +1,9 @@ import { notFound } from "next/navigation"; import type { Metadata } from "next"; import { getCaseStudyBySlug } from "@/services/case.service"; +import { getPreviewOrFallback } from "@/services/preview.service"; import { BlockRenderer } from "@/blocks/BlockRenderer"; +import type { CaseStudyPageDetail } from "@/types/wagtail"; interface CaseStudyDetailPageProps { params: Promise<{ slug: string }>; @@ -19,7 +21,11 @@ export default async function CaseStudyDetailPage({ params, }: CaseStudyDetailPageProps) { const { slug } = await params; - const item = await getCaseStudyBySlug(slug).catch(() => null); + const item = await getPreviewOrFallback( + "cases.casestudypage", + "body,client_name,industry,published_at,summary", + () => getCaseStudyBySlug(slug).catch(() => null), + ); if (!item) { notFound(); diff --git a/app/layout.tsx b/app/layout.tsx index de21770..c4533b6 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,4 +1,5 @@ import type { Metadata } from "next"; +import { draftMode } from "next/headers"; import "./globals.css"; import Header from "@/components/layout/Header"; import Footer from "@/components/layout/Footer"; @@ -16,11 +17,24 @@ export const metadata: Metadata = { description: "企业级 Headless CMS 驱动的现代化官网", }; -export default function RootLayout({ children }: LayoutProps<"/">) { +export default async function RootLayout({ children }: LayoutProps<"/">) { + const { isEnabled: isPreview } = await draftMode(); + return ( + {isPreview && ( +
+ 预览模式:当前显示的是未发布的草稿内容 + + 退出预览 + +
+ )}
{children}