/** * Demo 数据层:统一加载 assets/mock.json * 页面定义 window.renderPage(DB) 后由本文件回调渲染; * 交互函数直接修改 DB 并调用对应 renderPage 重渲染。 * 交互产生的数据变更通过 localStorage 持久化,跨页面/刷新保留; * mock.json 结构升级时提升 SCHEMA_VER 使旧存档失效。 */ const SCHEMA_VER = 6; const DB_KEY = 'opc_demo_db'; let DB = null; /** 徽章 */ const B = (pair) => pair ? `${pair[0]}` : '—'; /** 进度条 */ const BAR = (w, cls = '') => `
`; /** 步骤条 */ const STEPS = (steps) => `
` + steps .map((s, i) => `${i ? '→' : ''}${s[0]}`) .join('') + `
`; /** 标签 */ const TAG = (t) => `${t}`; /** 列表行(key-value) */ const LI = (l, r) => `
  • ${l}${r}
  • `; /** 将当前 DB 持久化到 localStorage */ function saveDB() { if (!DB) return; try { localStorage.setItem(DB_KEY, JSON.stringify({ v: SCHEMA_VER, data: DB })); } catch (e) { /* 存储满或隐私模式下静默降级 */ } } /** 清除演示存档,恢复 mock.json 初始数据 */ function resetDemo() { localStorage.removeItem(DB_KEY); location.reload(); } async function loadMock() { let fresh = {}; try { const res = await fetch('assets/mock.json'); fresh = await res.json(); } catch (e) { console.error('mock.json 加载失败(请通过 http 服务访问,勿用 file:// 直开)', e); } let saved = null; try { const raw = localStorage.getItem(DB_KEY); if (raw) { const pack = JSON.parse(raw); if (pack.v === SCHEMA_VER) saved = pack.data; } } catch (e) { /* 存档损坏时回退到初始数据 */ } // 存档优先,但用 fresh 补齐新增加的业务域 DB = saved ? Object.assign({}, fresh, saved) : fresh; window.addEventListener('beforeunload', saveDB); if (typeof window.renderPage === 'function') window.renderPage(DB); } document.addEventListener('DOMContentLoaded', loadMock);