- BFF 薄适配层(FastAPI,8090):QA 代理/SSE 中继/Neo4j 直连/抽取代理/会话持久化 - Vue3 前端:五相位检索流水线、文献来源与证据链、知识图谱、提取任务四 tab - 四档响应式(桌面/笔记本/平板/手机)、深浅主题 - 81 个 FR 全部实现,测试追溯矩阵 81/81,后端 121 测/前端 156 测 - 真实凭据已脱敏,运行时配置在 backend/.env(不入 git) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
47 lines
1.3 KiB
JavaScript
47 lines
1.3 KiB
JavaScript
// setup.js —— B1 归属,vitest 全局 setup(vitest.config.js setupFiles)。
|
||
// 环境适配(jsdom 25 + Node ≥22 组合下 window.localStorage 为 undefined):
|
||
// - Node ≥22 自带实验性 globalThis.localStorage(未配 --localstorage-file 时为 undefined),会遮蔽 jsdom 实现
|
||
// - jsdom 25 在较新 Node 上 window.localStorage 亦可能缺失
|
||
// 统一策略:window.localStorage 缺失时注入内存实现,并将其同时暴露到 globalThis。
|
||
class MemoryStorage {
|
||
constructor() {
|
||
this._m = new Map();
|
||
}
|
||
get length() {
|
||
return this._m.size;
|
||
}
|
||
key(i) {
|
||
return [...this._m.keys()][i] ?? null;
|
||
}
|
||
getItem(k) {
|
||
const key = String(k);
|
||
return this._m.has(key) ? this._m.get(key) : null;
|
||
}
|
||
setItem(k, v) {
|
||
this._m.set(String(k), String(v));
|
||
}
|
||
removeItem(k) {
|
||
this._m.delete(String(k));
|
||
}
|
||
clear() {
|
||
this._m.clear();
|
||
}
|
||
}
|
||
|
||
if (typeof window !== 'undefined') {
|
||
let storage = window.localStorage;
|
||
if (!storage) {
|
||
storage = new MemoryStorage();
|
||
try {
|
||
Object.defineProperty(window, 'localStorage', { value: storage, configurable: true });
|
||
} catch {
|
||
window.localStorage = storage;
|
||
}
|
||
}
|
||
try {
|
||
Object.defineProperty(globalThis, 'localStorage', { value: storage, configurable: true });
|
||
} catch {
|
||
globalThis.localStorage = storage;
|
||
}
|
||
}
|