- 后台全面引入 Naive UI 组件库,统一 UI 规范 - 前台 usePublicApi 切换到 API 调用(GET /api/content/[key]) - 前后台数据源统一(site_content 表) - 产品线统一管理(tour/camp/course 三套编辑器) - 产品数据归一化(itinerary/faq/pricing 格式统一) - 表单提交 API 改写入 submissions 表 - 新增 submissions 标记已读 API - site-content PUT 支持 upsert - 修复前台 bug(stories 路由冲突、占位符警告、selector breadcrumb) - 消除 PageHero 类型警告(useSEO reactive 修复) - 25 个前台页面全部 HTTP 200,展示效果不变 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
57 行
1.2 KiB
JavaScript
57 行
1.2 KiB
JavaScript
/**
|
|
* 文件存储工具
|
|
* 将表单数据追加写入 server/storage/ 目录下的 JSON 文件
|
|
*/
|
|
|
|
import { promises as fs } from 'fs'
|
|
import { resolve } from 'path'
|
|
|
|
const STORAGE_DIR = resolve(process.cwd(), 'server/storage')
|
|
|
|
/**
|
|
* 确保存储目录存在
|
|
*/
|
|
async function ensureDir() {
|
|
try {
|
|
await fs.mkdir(STORAGE_DIR, { recursive: true })
|
|
} catch {
|
|
// 目录已存在,忽略
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 将记录追加到指定文件
|
|
* @param {string} filename - 不含路径,如 'customize.json'
|
|
* @param {object} record
|
|
*/
|
|
export async function appendRecord(filename, record) {
|
|
await ensureDir()
|
|
const filepath = resolve(STORAGE_DIR, filename)
|
|
|
|
let records = []
|
|
try {
|
|
const raw = await fs.readFile(filepath, 'utf-8')
|
|
records = JSON.parse(raw)
|
|
} catch {
|
|
// 文件不存在或解析失败,从空数组开始
|
|
}
|
|
|
|
records.push(record)
|
|
await fs.writeFile(filepath, JSON.stringify(records, null, 2), 'utf-8')
|
|
return record
|
|
}
|
|
|
|
/**
|
|
* 读取所有记录(管理员用)
|
|
* @param {string} filename
|
|
*/
|
|
export async function readRecords(filename) {
|
|
const filepath = resolve(STORAGE_DIR, filename)
|
|
try {
|
|
const raw = await fs.readFile(filepath, 'utf-8')
|
|
return JSON.parse(raw)
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|