db (IndexedDB)

基于 Dexie 的 IndexedDB 简易封装,framework 用它缓存 .bnc 解密后的资源(SwImage / SwAsyncText / useDecryptedAsset 的持久缓存层)。业务需要客户端持久化大块二进制 / 结构化数据时也可直接用。3 个函数全部 auto-import。

工作原理

  1. 模块加载时即创建 Dexie 实例(数据库名 database,版本 1),固定包含两个 store:
    • image — 解密后的图片二进制 / blob URL 缓存
    • text — 解密后的文本片段缓存
  2. 每条记录带自增 ++id 和 updated_at 索引,便于按时间淘汰。
  3. 每个 API 首次调用会懒打开数据库,Dexie 处理并发竞争;实例为模块级单例,同一标签页内多处调用共享连接。
  4. dbPut 自动覆写 updated_at(秒级时间戳),调用方无需手动维护。

API

函数签名说明
dbPut(data: object, storeName: string) => Promise<void>新增或更新一条记录(data 需含 id 字段作主键),自动写 updated_at
dbGet(id: string, storeName: string) => Promise<unknown>按 id 查询单条记录,未命中返回 undefined
dbClear(storeName: string) => Promise<void>清空指定 store

使用示例

dbPut / dbGet 读写(刷新仍在)

加载中...
// 缓存解密后的图片 blob URL
await dbPut({ id: 'cover.bnc', url: blobUrl }, 'image')

// 读取缓存,未命中则回源解密
const hit = await dbGet('cover.bnc', 'image')
const url = hit?.url ?? await decryptAndCache('cover.bnc')

// 退出登录时清空全部缓存
await dbClear('image')
await dbClear('text')

注意事项

仅客户端可用(DB-001,blocker)

IndexedDB 是浏览器 API,Node.js 端不存在 —— SSR 期调用直接报错。所有 db API 必须在 onMounted / IS_CLIENT 守卫 / client-only 组件内调用:

// ❌ setup 顶层调用,SSR 期 indexedDB is not defined
const hit = await dbGet('cover.bnc', 'image')

// ✅ onMounted 内调用
onMounted(async () => {
  const hit = await dbGet('cover.bnc', 'image')
})

storeName 只能是 'image' / 'text'(DB-002,warning)

schema 固定只有这两个 store,但 storeName 参数类型是裸 string、无编译校验。传未定义的表名(如 'user' / 'cover'),Dexie 返回"幽灵 table" —— 写入成功不报错,但数据进虚空、永远读不回来,排查极难:

// ❌ 'cover' 不是 framework 建的 store → 写入成功但读不回
await dbPut({ id: 'x', url }, 'cover')
const hit = await dbGet('x', 'cover') // 永远 undefined

// ✅ 只用框架建的两个表名
await dbPut({ id: 'x', url }, 'image')

需要业务自有表结构时,请在业务层另建自己的 Dexie 实例,不要复用 framework 的 database。