| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- /**
- * 开发期数据维护入口(仅 dev 构建暴露)
- *
- * ## 为什么需要
- *
- * 会话/工作区/菜单配置都按用户存在 localStorage 里(`fmode_*_<uid>`)。
- * 这些键**不会因为代码改动而清空** —— 之前灌过的模拟数据会一直留在浏览器里,
- * 表现为"代码明明改了,界面上还是旧数据"(实测踩过两次)。
- *
- * ## 用法(浏览器控制台)
- *
- * ```js
- * __fmodeData.clearDemo() // 只删模拟数据($demo_ 前缀),保留真实会话
- * __fmodeData.clearSessions() // 清空会话索引(下次进入会重新从 Matrix 扫描)
- * __fmodeData.dump() // 打印当前各键的数量,排查用
- * __fmodeData.previewAlert() // 预览全局异常提示(调样式用,2026-11-10)
- * ```
- *
- * 🔴 只清**本地索引**,不碰 Matrix 服务端消息。
- */
- interface DataApi {
- clearDemo: () => void;
- clearSessions: () => void;
- dump: () => Record<string, unknown>;
- /** 预览全局异常提示(开发期调样式用) */
- previewAlert: () => void;
- }
- export function installDataApi(): void {
- if (typeof window === 'undefined') return;
- const keysOf = (prefix: string) =>
- Object.keys(localStorage).filter((k) => k.startsWith(prefix));
- const read = <T>(k: string): T[] => {
- try {
- const v = JSON.parse(localStorage.getItem(k) ?? '[]') as T[];
- return Array.isArray(v) ? v : [];
- } catch {
- return [];
- }
- };
- const api: DataApi = {
- clearDemo() {
- let removed = 0;
- for (const k of keysOf('fmode_chat_sessions_')) {
- if (k.endsWith('_removed')) continue;
- const kept = read<{ id?: string }>(k).filter(
- (s) => !String(s.id ?? '').startsWith('$demo_'),
- );
- localStorage.setItem(k, JSON.stringify(kept));
- }
- for (const k of keysOf('fmode_workspaces_')) {
- const kept = read<{ id?: string }>(k).filter(
- (w) => !String(w.id ?? '').startsWith('ws_demo_'),
- );
- removed += kept.length;
- localStorage.setItem(k, JSON.stringify(kept));
- }
- location.reload();
- },
- clearSessions() {
- for (const k of keysOf('fmode_chat_sessions_')) localStorage.removeItem(k);
- location.reload();
- },
- dump() {
- const out: Record<string, unknown> = {};
- for (const k of keysOf('fmode_')) {
- if (k === 'fmode_me' || k === 'fmode_session_token') {
- out[k] = '<已登录凭据,略>';
- continue;
- }
- const raw = localStorage.getItem(k) ?? '';
- try {
- const v = JSON.parse(raw);
- out[k] = Array.isArray(v) ? `${v.length} 项` : v;
- } catch {
- out[k] = raw.slice(0, 40);
- }
- }
- console.table(out);
- return out;
- },
- /*
- * 预览全局异常提示(2026-11-10)。
- *
- * 调样式时需要立即看到效果,而真实超时要等 3 分钟。
- * 只做前端展示,不改任何数据。
- */
- previewAlert() {
- const svc = (window as unknown as { ng?: { get?: (t: unknown) => unknown } }).ng?.get?.(
- // 惰性取 AlertService:避免 data-tools 与核心服务产生静态循环依赖
- (globalThis as unknown as { __alertToken?: unknown }).__alertToken,
- );
- if (svc) return;
- // 无 DI 访问通道时的兜底:直接派发自定义事件,由 App 根组件监听
- window.dispatchEvent(new CustomEvent('fmode:preview-alert'));
- },
- };
- (window as unknown as { __fmodeData?: DataApi }).__fmodeData = api;
- }
|