import fs from "fs"; import path from "path"; import { cache } from "react"; import type { Floor, NavItem, HeroData, AboutData, TechData, SolutionsData, CasesData, PartnersData, NewsData, CareersData, ContactData, } from "../types"; // 内存缓存,避免重复读取文件 const fileCache = new Map(); function readJson(relativePath: string): T { const filePath = path.join(process.cwd(), relativePath); // 检查文件修改时间 let stats: fs.Stats; try { stats = fs.statSync(filePath); } catch { throw new Error(`File not found: ${relativePath}`); } // 检查缓存 const cached = fileCache.get(filePath); if (cached && cached.mtime === stats.mtimeMs) { return cached.data as T; } // 读取并缓存 const raw = fs.readFileSync(filePath, "utf-8"); const data = JSON.parse(raw) as T; fileCache.set(filePath, { data, mtime: stats.mtimeMs }); return data; } function dataPathFor(locale: string | undefined, filename: string): string { const base = "data"; const candidates = [ locale ? path.join(base, locale, filename) : undefined, path.join(base, filename), ].filter(Boolean) as string[]; for (const p of candidates) { if (fs.existsSync(path.join(process.cwd(), p))) return p; } return path.join(base, filename); } // 使用 React cache 包装所有数据读取函数,实现请求级别的缓存 export const getMainNav = cache((locale?: string) => { return readJson(dataPathFor(locale, "mainnav.json")); }); export const getFloors = cache((locale?: string) => { return readJson(dataPathFor(locale, "products.json")); }); export const getFloorBySlug = cache((slug: string, locale?: string) => { const floors = getFloors(locale); // 允许 id 带前缀,如 floor-phone,对应 slug phone return floors.find((f) => f.id === slug || f.id === `floor-${slug}`); }); export const getProductById = cache((id: string, locale?: string) => { const floors = getFloors(locale); for (const f of floors) { const p = f.products.find((x) => x.id === id); if (p) return { product: p, floor: f } as const; } return undefined; }); export const getHero = cache((locale?: string) => { return readJson(dataPathFor(locale, "hero.json")); }); export const getAbout = cache((locale?: string) => { return readJson(dataPathFor(locale, "about.json")); }); const getAboutMarkdownFile = cache((locale?: string): string => { const candidates = [ locale ? path.join("data", locale, "about.md") : undefined, path.join("data", "about.md"), path.join("..", "..", "关于我们.md"), ].filter(Boolean) as string[]; for (const relativePath of candidates) { const filePath = path.join(process.cwd(), relativePath); if (fs.existsSync(filePath)) { try { // 检查缓存 const stats = fs.statSync(filePath); const cached = fileCache.get(filePath); if (cached && cached.mtime === stats.mtimeMs && typeof cached.data === 'string') { return cached.data; } const content = fs.readFileSync(filePath, "utf-8"); fileCache.set(filePath, { data: content, mtime: stats.mtimeMs }); return content; } catch (error) { console.warn(`Failed to load ${relativePath}`, error); } } } console.warn("About markdown not found in any candidate path."); return ""; }); export const getAboutMarkdown = cache((locale?: string): string => { return getAboutMarkdownFile(locale); }); export const getTech = cache((locale?: string) => { return readJson(dataPathFor(locale, "tech.json")); }); export const getSolutions = cache((locale?: string) => { return readJson(dataPathFor(locale, "solutions.json")); }); export const getCases = cache((locale?: string) => { return readJson(dataPathFor(locale, "cases.json")); }); export const getPartners = cache((locale?: string) => { return readJson(dataPathFor(locale, "partners.json")); }); export const getNews = cache((locale?: string) => { return readJson(dataPathFor(locale, "news.json")); }); export const getCareers = cache((locale?: string) => { return readJson(dataPathFor(locale, "careers.json")); }); export const getContact = cache((locale?: string) => { return readJson(dataPathFor(locale, "contact.json")); });