diff --git a/sync/bme-db.js b/sync/bme-db.js index e8c8d20..5eb99a2 100644 --- a/sync/bme-db.js +++ b/sync/bme-db.js @@ -2224,6 +2224,31 @@ async function loadDexieFromNodeFallback() { throw new Error("Dexie 不可用(Node 环境缺少 dexie 依赖)"); } +async function loadDexieByModuleImport() { + const moduleUrl = new URL(DEXIE_SCRIPT_SOURCE, import.meta.url).toString(); + try { + const imported = await import(moduleUrl); + const DexieCtor = + imported?.default || + imported?.Dexie || + globalThis.Dexie || + null; + if (typeof DexieCtor === "function") { + globalThis.Dexie = DexieCtor; + return DexieCtor; + } + if (typeof globalThis.Dexie === "function") { + return globalThis.Dexie; + } + } catch (error) { + throw new Error( + `Dexie 模块导入失败: ${error?.message || String(error) || moduleUrl}`, + ); + } + + throw new Error("Dexie 模块已加载但未导出可用构造函数"); +} + async function loadDexieByScriptInjection() { const scriptUrl = new URL(DEXIE_SCRIPT_SOURCE, import.meta.url).toString(); const doc = globalThis.document; @@ -2291,6 +2316,12 @@ export async function ensureDexieLoaded() { return await loadDexieFromNodeFallback(); } + try { + return await loadDexieByModuleImport(); + } catch (moduleError) { + console.warn("[ST-BME] Dexie 模块导入失败,回退脚本注入:", moduleError); + } + return await loadDexieByScriptInjection(); })() .then((DexieCtor) => { diff --git a/tests/dexie-loader.mjs b/tests/dexie-loader.mjs new file mode 100644 index 0000000..6ac93a6 --- /dev/null +++ b/tests/dexie-loader.mjs @@ -0,0 +1,37 @@ +import assert from "node:assert/strict"; + +import { ensureDexieLoaded } from "../sync/bme-db.js"; + +const previousDocument = globalThis.document; +const previousDexie = globalThis.Dexie; +const previousLoadPromise = globalThis.__stBmeDexieLoadPromise; + +try { + globalThis.document = {}; + delete globalThis.Dexie; + delete globalThis.__stBmeDexieLoadPromise; + + const DexieCtor = await ensureDexieLoaded(); + assert.equal(typeof DexieCtor, "function"); + assert.equal(globalThis.Dexie, DexieCtor); +} finally { + if (previousDocument === undefined) { + delete globalThis.document; + } else { + globalThis.document = previousDocument; + } + + if (previousDexie === undefined) { + delete globalThis.Dexie; + } else { + globalThis.Dexie = previousDexie; + } + + if (previousLoadPromise === undefined) { + delete globalThis.__stBmeDexieLoadPromise; + } else { + globalThis.__stBmeDexieLoadPromise = previousLoadPromise; + } +} + +console.log("dexie-loader tests passed"); diff --git a/ui/panel.js b/ui/panel.js index 98e3cea..a319d03 100644 --- a/ui/panel.js +++ b/ui/panel.js @@ -11759,10 +11759,13 @@ function _refreshPersistenceRepairUi( } if (loadInfo?.pendingPersist === true) { - help.textContent = + const baseMessage = isLuker ? "最近一批提取已经完成,但 Luker manifest 还没确认。先试“重试持久化”,如果仍未确认,再试“修复主 Sidecar”或“重建本地缓存”。" : "最近一批提取已经完成,但正式写回还没确认。先试“重试持久化”,如果状态没变化,再试“重新探测图谱”。"; + help.textContent = loadInfo?.indexedDbLastError + ? `${baseMessage}\n本地错误:${loadInfo.indexedDbLastError}` + : baseMessage; return; }