admin-vue3/src/views/im/utils/storage.ts

50 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import localforage from 'localforage'
/**
* IM 模块的 IndexedDB 实例localforage 优先 IndexedDB自动降级到 WebSQL / localStorage
*
* 为什么不用 localStorage 直接存:
* 1. 配额localStorage 整体上限 5~10MB多会话长历史很容易撑爆
* 2. 写放大localStorage 必须按 key 整体写入,单次写就是 MB 级序列化阻塞主线程
*
* 配套策略:会话与消息按 key 分桶(见 StorageKeys让单次变更只重写最小粒度的 key。
* IndexedDB 默认配额一般是浏览器可用空间的 ~50%,远大于 localStorage配合分桶才发挥效果。
*/
export const imStorage = localforage.createInstance({
name: 'im',
storeName: 'conversation',
description: 'IM 会话索引与消息缓存'
})
/**
* 存储 key 统一在此生成
*
* - 会话相关meta / message走 imStorageIndexedDBkey 形如 `conversation:xxx:{userId}:...`
* - 轻量 UI 状态(侧边栏宽度)仍走 localStorage体积小、跨 Tab 同步天然,没必要走 IndexedDB
*
* 所有会话相关 key 都注入 userId多账号切换时按用户隔离避免数据互串。
*/
export const StorageKeys = {
/**
* 会话索引:游标 + 会话元数据(不含 messages对应 ConversationStoreMeta
*
* 任何会话级元数据变更top / muted / unread / 列表增删 / 排序)都会重写这一个 key
* 由于 messages 已剥离到独立 key单次写体积稳定仅元数据量级 KB 级)。
*/
conversationMeta: (userId: number | string) => `conversation:meta:${userId}`,
/**
* 单会话消息:按 (type, targetId) 分桶,存 Message[]
*
* - type私聊 / 群聊(对齐 ImConversationType
* - targetId私聊的对方 userId / 群聊的 groupId
*
* 每条消息变更只重写当前会话这一个 key避免老方案"全量写所有会话所有消息"的写放大。
* 软删除会话时由 conversationStore.removeConversationMessages 物理删除该 key避免 orphan 残留。
*/
conversationMessage: (userId: number | string, type: number, targetId: number) =>
`conversation:message:${userId}:${type}:${targetId}`,
/** 侧边栏宽度localStorage三个 Tab 共用一份记忆,对齐微信(拖一次到处一致)。 */
asideWidth: 'im:aside'
} as const