diff --git a/app/demo/[industry]/[[...path]]/page.tsx b/app/demo/[industry]/[[...path]]/page.tsx new file mode 100644 index 0000000..9c286f9 --- /dev/null +++ b/app/demo/[industry]/[[...path]]/page.tsx @@ -0,0 +1,63 @@ +import Link from "next/link"; +import type { Metadata } from "next"; +import { notFound } from "next/navigation"; +import { ApiError } from "@/services/api-client"; +import { getDemoPage, getIndustryDemos } from "@/services/demo.service"; +import { BlockRenderer } from "@/blocks/BlockRenderer"; + +type Props = { params: Promise<{ industry: string; path?: string[] }> }; + +async function load(params: Props["params"]) { + const { industry, path } = await params; + try { + return await getDemoPage(industry, path); + } catch (error) { + if (error instanceof ApiError && error.status === 404) notFound(); + throw error; + } +} + +export async function generateMetadata({ params }: Props): Promise { + const page = await load(params); + return { title: { absolute: `${page.title} | ${page.label}演示` }, robots: { index: false, follow: false } }; +} + +export default async function IndustryDemoPage({ params }: Props) { + const [page, demos, route] = await Promise.all([load(params), getIndustryDemos(), params]); + const base = `/demo/${page.industry}`; + const colors: Record = { + software: "border-sky-500", manufacturing: "border-orange-500", consulting: "border-emerald-500", + education: "border-violet-500", healthcare: "border-teal-500", dining: "border-rose-500", + construction: "border-amber-500", "real-estate": "border-indigo-500", "home-renovation": "border-lime-500", + "agri-food": "border-green-500", "energy-environment": "border-cyan-500", "auto-services": "border-red-500", + "culture-media": "border-fuchsia-500", "sports-fitness": "border-blue-500", "pet-services": "border-yellow-500", + "legal-services": "border-slate-700", "finance-tax": "border-purple-500", "human-resources": "border-pink-500", + }; + return ( +
+ +
+
+ {page.company} + +
+ +
+ {route.path?.length ?

{page.title}

{page.intro &&

{page.intro}

}
: null} + {page.html &&
} + + {!!page.children.length &&
{page.children.map((child) => {child.title} →)}
} +
+

{page.company} · 模板内容仅供演示

+
演示隐私说明切换模板返回当前官网
+
+
+ ); +} diff --git a/app/demo/page.tsx b/app/demo/page.tsx new file mode 100644 index 0000000..82436d9 --- /dev/null +++ b/app/demo/page.tsx @@ -0,0 +1,28 @@ +import Link from "next/link"; +import type { Metadata } from "next"; +import { getIndustryDemos } from "@/services/demo.service"; + +export const metadata: Metadata = { title: { absolute: "行业官网模板演示" }, robots: { index: false, follow: false } }; + +export default async function DemoGallery() { + const result = await getIndustryDemos().catch(() => null); + return ( +
+ 返回当前官网 +

行业官网模板演示

+

浏览下方行业模板:独立内容,无损切换。所有企业及案例均为虚构演示。

+ {!result?.items.length &&

演示内容尚未就绪,请启动后端并运行 seed_industry_templates 初始化命令。

} +
+ {result?.items.map((item, index) => ( + + 模板 {String(index + 1).padStart(2, "0")} +

{item.label}

+

{item.company}

+

{item.description}

+ 浏览演示 → + + ))} +
+
+ ); +} diff --git a/app/layout.tsx b/app/layout.tsx index 2c22409..38ecdf1 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -6,6 +6,7 @@ import Footer from "@/components/layout/Footer"; import CookieConsent from "@/components/layout/CookieConsent"; import ReactQueryProvider from "@/providers/react-query-provider"; import { getSiteSettings } from "@/services/site-settings.service"; +import SiteChrome from "@/components/layout/SiteChrome"; // 面向中国大陆用户,避免依赖 next/font/google(构建期需访问 Google 服务器)。 // 生产环境建议自托管思源黑体 / HarmonyOS Sans 子集,这里先用系统字体栈占位。 @@ -37,9 +38,9 @@ export default async function RootLayout({ children }: LayoutProps<"/">) {
)} -
+
{children}
-