refactor(about): 重构关于页面路由为静态路径

将关于页面的查询参数路由改为静态路径结构,如/about/company
更新i18n消息中的链接路径
添加新的[section]页面处理逻辑
优化静态生成参数和错误处理
This commit is contained in:
砂糖
2025-12-11 09:10:41 +08:00
parent d8ec1d4384
commit 450337a019
25 changed files with 234 additions and 215 deletions

View File

@@ -0,0 +1,120 @@
import MDXComponents from "@/components/mdx/MDXComponents";
import { Locale, LOCALES } from "@/i18n/routing";
import { constructMetadata } from "@/lib/metadata";
import fs from "fs/promises";
import { Metadata } from "next";
import { getTranslations } from "next-intl/server";
import { MDXRemote } from "next-mdx-remote-client/rsc";
import path from "path";
import remarkGfm from "remark-gfm";
// 强制静态渲染
export const dynamic = "force-static";
const options = {
parseFrontmatter: true,
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [],
},
};
// 增强添加参数校验防止undefined
async function getMDXContent(locale: string, section: string) {
// 兜底校验:确保参数是字符串
const validLocale = locale?.trim() || "en"; // 兜底为默认语言
const validSection = section?.trim() || "company"; // 兜底为默认section
// 校验LOCALES是否包含当前locale
if (!LOCALES.includes(validLocale)) {
console.error(`Locale "${validLocale}" not found in LOCALES!`);
return "";
}
const filePath = path.join(
process.cwd(),
"content",
"about",
validSection, // 使用校验后的section
`${validLocale}.mdx` // 使用校验后的locale
);
try {
// 先检查文件是否存在,避免读取不存在的文件
await fs.access(filePath);
const content = await fs.readFile(filePath, "utf-8");
return content;
} catch (error) {
console.error(`Error accessing/reading MDX file (${filePath}):`, error);
return "";
}
}
// 修正路由参数类型locale + section
type Params = {
locale: string;
section: string;
};
type MetadataProps = {
params: Params;
};
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
const { locale, section } = params;
const t = await getTranslations({ locale, namespace: "About" });
return constructMetadata({
page: `About - ${section}`,
title: t(`title`) || t("title"), // 适配不同section的标题
description: t(`description`) || t("description"),
locale: locale as Locale,
path: `/about/${section}`,
canonicalUrl: `/about/${section}`,
});
}
// 页面组件从params获取locale和section路由参数
export default async function AboutPage({
params,
}: {
params: Promise<Params>;
}) {
const { locale, section } = await params;
console.log(`Rendering AboutPage for locale: ${locale}, section: ${section}`);
// 调用带校验的getContent函数
const content = await getMDXContent(locale, section);
return (
<article className="w-full md:w-3/5 px-2 md:px-12">
<MDXRemote
source={content}
components={MDXComponents}
options={options}
/>
</article>
);
}
// 关键生成locale + section的所有静态组合覆盖vi/organization等
export async function generateStaticParams() {
const sections = ['company', 'awards', 'base', 'culture', 'history', 'organization'];
// 确保LOCALES包含"vi"越南语否则会生成undefined
if (!LOCALES.includes("vi")) {
console.warn("⚠️ LOCALES does not include 'vi'! Add it to fix /vi/about/* paths.");
// 临时兜底如果没有vi手动添加或检查你的i18n/routing.ts
// LOCALES.push("vi");
}
// 生成所有locale × section的组合
return LOCALES.flatMap((locale) =>
sections.map((section) => ({
locale,
section,
}))
);
}

View File

@@ -1,88 +1,32 @@
import MDXComponents from "@/components/mdx/MDXComponents";
import { Locale, LOCALES } from "@/i18n/routing";
import { constructMetadata } from "@/lib/metadata";
import fs from "fs/promises";
import { Metadata } from "next";
import { getTranslations } from "next-intl/server";
import { MDXRemote } from "next-mdx-remote-client/rsc";
import path from "path";
import remarkGfm from "remark-gfm";
import { LOCALES } from "@/i18n/routing";
import { redirect } from "next/navigation";
const options = {
parseFrontmatter: true,
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [],
},
};
async function getMDXContent(locale: string, section: string) {
const filePath = path.join(
process.cwd(),
"content",
"about",
section,
`${locale}.mdx`
);
try {
const content = await fs.readFile(filePath, "utf-8");
return content;
} catch (error) {
console.error(`Error reading MDX file: ${error}`);
return "";
}
}
type Params = Promise<{
locale: string;
}>;
type MetadataProps = {
params: Params;
};
export async function generateMetadata({
// 重定向到 /about/company
export default async function Page({
params,
}: MetadataProps): Promise<Metadata> {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: "About" });
return constructMetadata({
page: "About",
title: t("title"),
description: t("description"),
locale: locale as Locale,
path: `/about`,
canonicalUrl: `/about`,
});
}
export default async function AboutPage({
params,
searchParams
}: {
params: Params;
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
const resolvedSearchParams = await searchParams;
const section = (resolvedSearchParams.section as string) || "company";
const content = await getMDXContent(locale, section);
return (
<article className="w-full md:w-3/5 px-2 md:px-12">
<MDXRemote
source={content}
components={MDXComponents}
options={options}
/>
</article>
);
return redirect(`/${locale}/about/company`);
}
// 关键生成locale + section的所有静态组合覆盖vi/organization等
export async function generateStaticParams() {
return LOCALES.map((locale) => ({
locale,
}));
const sections = ['company', 'awards', 'base', 'culture', 'history', 'organization'];
// 确保LOCALES包含"vi"越南语否则会生成undefined
if (!LOCALES.includes("vi")) {
console.warn("⚠️ LOCALES does not include 'vi'! Add it to fix /vi/about/* paths.");
// 临时兜底如果没有vi手动添加或检查你的i18n/routing.ts
// LOCALES.push("vi");
}
// 生成所有locale × section的组合
return LOCALES.flatMap((locale) =>
sections.map((section) => ({
locale,
section,
}))
);
}