db (IndexedDB)
基于 Dexie 的 IndexedDB 简易封装,framework 用它缓存 .bnc 解密后的资源(SwImage / SwAsyncText / useDecryptedAsset 的持久缓存层)。业务需要客户端持久化大块二进制 / 结构化数据时也可直接用。3 个函数全部 auto-import。
工作原理
- 模块加载时即创建 Dexie 实例(数据库名
database,版本 1),固定包含两个 store:image— 解密后的图片二进制 / blob URL 缓存text— 解密后的文本片段缓存
- 每条记录带自增
++id和updated_at索引,便于按时间淘汰。 - 每个 API 首次调用会懒打开数据库,Dexie 处理并发竞争;实例为模块级单例,同一标签页内多处调用共享连接。
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。