/** * 数据存储层(JSON 文件落盘) * ------------------------------------------------------------- * 集合: * bookings —— 公益课报名 / 沙龙预约(前端预约表单) * events —— 公益课 + 沙龙排期(后台可增删改) * tests —— OPC 测评记录(前端测评上报) * 说明: * - 同步读写在数据量小的阶段足够;迁移真实数据库时替换本文件实现即可。 * - 带内存缓存,避免每次请求都读文件。 */ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import path from 'node:path'; const DIR = path.dirname(fileURLToPath(import.meta.url)); const FILES = { accounts: path.join(DIR, 'accounts.json'), bookings: path.join(DIR, 'bookings.json'), events: path.join(DIR, 'events.json'), tests: path.join(DIR, 'tests.json'), policyLogs: path.join(DIR, 'policyLogs.json'), planLogs: path.join(DIR, 'planLogs.json'), surveyLogs: path.join(DIR, 'surveyLogs.json') }; const CACHE = {}; function ensureFile(key) { const file = FILES[key]; if (!file) throw new Error('unknown store: ' + key); if (!existsSync(file)) { mkdirSync(path.dirname(file), { recursive: true }); writeFileSync(file, '[]', 'utf8'); } return file; } export function loadAll(key) { if (CACHE[key] !== undefined) return CACHE[key]; const file = ensureFile(key); try { CACHE[key] = JSON.parse(readFileSync(file, 'utf8') || '[]'); } catch { CACHE[key] = []; } if (!Array.isArray(CACHE[key])) CACHE[key] = []; return CACHE[key]; } export function save(key, list) { CACHE[key] = Array.isArray(list) ? list : []; const file = ensureFile(key); writeFileSync(file, JSON.stringify(CACHE[key], null, 2), 'utf8'); } export function add(key, entry) { const list = loadAll(key); list.push(entry); save(key, list); return entry; } export function update(key, id, patch) { const list = loadAll(key); const i = list.findIndex((x) => x.id === id); if (i < 0) return null; list[i] = { ...list[i], ...patch, id }; save(key, list); return list[i]; } export function remove(key, id) { const list = loadAll(key); const next = list.filter((x) => x.id !== id); if (next.length === list.length) return false; save(key, next); return true; } /** 首次运行注入种子数据(仅当集合为空时) */ export function seedIfEmpty(key, seed) { if (loadAll(key).length === 0) save(key, seed); }