parent
8ce773f264
commit
88d5661e0c
|
|
@ -55,34 +55,50 @@ export interface ViewedRowStorageAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 已读行持久化配置
|
* 已读行持久化 — 公共基础字段
|
||||||
*/
|
*/
|
||||||
export interface ViewedRowPersistOptions {
|
interface ViewedRowPersistBase {
|
||||||
/**
|
|
||||||
* 存储类型,默认 'localStorage'
|
|
||||||
* - memory: 仅内存,不持久化
|
|
||||||
* - localStorage: 使用 localStorage 整体存储
|
|
||||||
* - sessionStorage: 使用 sessionStorage 整体存储
|
|
||||||
* - indexedDB: 使用 IndexedDB 单条存储(支持单条 TTL)
|
|
||||||
* - custom: 用户自定义存储适配器
|
|
||||||
*/
|
|
||||||
type?: 'custom' | 'indexedDB' | 'localStorage' | 'memory' | 'sessionStorage';
|
|
||||||
/** 存储 key / prefix(type 为 localStorage/sessionStorage/indexedDB 时必传) */
|
|
||||||
key?: string;
|
|
||||||
/** 持久化数据的存活时间(毫秒) */
|
/** 持久化数据的存活时间(毫秒) */
|
||||||
ttl?: number;
|
ttl?: number;
|
||||||
/** 最大缓存数量,超出时淘汰最早标记的 key(FIFO),默认 100 */
|
/** 最大缓存数量,超出时淘汰最早标记的 key(FIFO),默认 100 */
|
||||||
maxSize?: number;
|
maxSize?: number;
|
||||||
/** IndexedDB 数据库名称(仅 type='indexedDB' 时生效,默认 'viewed-table-db') */
|
|
||||||
dbName?: string;
|
|
||||||
/** IndexedDB 数据库版本(仅 type='indexedDB' 时生效,默认 1) */
|
|
||||||
dbVersion?: number;
|
|
||||||
/** IndexedDB 对象存储名称(仅 type='indexedDB' 时生效,默认 'viewed-table-row') */
|
|
||||||
storeName?: string;
|
|
||||||
/** 自定义存储适配器(仅 type='custom' 时生效,不传则降级为 memory) */
|
|
||||||
storage?: ViewedRowStorageAdapter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已读行持久化配置(按 type 区分的联合类型)
|
||||||
|
*
|
||||||
|
* - 'memory' → 仅内存,不持久化
|
||||||
|
* - 'localStorage' → 使用 localStorage 整体存储,key 必传
|
||||||
|
* - 'sessionStorage' → 使用 sessionStorage 整体存储,key 必传
|
||||||
|
* - 'indexedDB' → 使用 IndexedDB 单条存储,key 必传
|
||||||
|
* - 'custom' → 用户自定义存储适配器,storage 必传
|
||||||
|
*/
|
||||||
|
export type ViewedRowPersistOptions =
|
||||||
|
({
|
||||||
|
/** IndexedDB 数据库名称,默认 'viewed-table-db' */
|
||||||
|
dbName?: string;
|
||||||
|
/** IndexedDB 数据库版本,默认 1 */
|
||||||
|
dbVersion?: number;
|
||||||
|
/** 存储 key / prefix(必传) */
|
||||||
|
key: string;
|
||||||
|
/** IndexedDB 对象存储名称,默认 'viewed-table-row' */
|
||||||
|
storeName?: string;
|
||||||
|
type: 'indexedDB';
|
||||||
|
} & ViewedRowPersistBase)
|
||||||
|
| ({
|
||||||
|
/** 存储 key(必传) */
|
||||||
|
key: string;
|
||||||
|
type: 'localStorage' | 'sessionStorage';
|
||||||
|
} & ViewedRowPersistBase)
|
||||||
|
| ({
|
||||||
|
/** 自定义存储适配器(必传) */
|
||||||
|
storage: ViewedRowStorageAdapter;
|
||||||
|
type: 'custom';
|
||||||
|
} & ViewedRowPersistBase)
|
||||||
|
| (ViewedRowPersistBase & {
|
||||||
|
type: 'memory';
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 已查看row设置
|
* 已查看row设置
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,9 @@ function createWebStorageAdapter(
|
||||||
* 单条存储:prefix:1 → { expiry, value: 1 }
|
* 单条存储:prefix:1 → { expiry, value: 1 }
|
||||||
*/
|
*/
|
||||||
function createIndexedDBAdapter(
|
function createIndexedDBAdapter(
|
||||||
opts: ViewedRowPersistOptions,
|
opts: Extract<ViewedRowPersistOptions, { type: 'indexedDB' }>,
|
||||||
): ViewedRowStorageAdapter {
|
): ViewedRowStorageAdapter {
|
||||||
const prefix = opts.key || 'viewed';
|
const prefix = opts.key;
|
||||||
const manager = new StorageManager({
|
const manager = new StorageManager({
|
||||||
driver: new IndexedDBDriver({
|
driver: new IndexedDBDriver({
|
||||||
dbName: opts.dbName || 'viewed-table-db',
|
dbName: opts.dbName || 'viewed-table-db',
|
||||||
|
|
@ -69,16 +69,11 @@ function createIndexedDBAdapter(
|
||||||
return {
|
return {
|
||||||
async getKeys() {
|
async getKeys() {
|
||||||
try {
|
try {
|
||||||
// 通过 StorageManager 的 driver 获取所有 key,再逐条读取(自动过滤过期)
|
// 通过 StorageManager 获取当前前缀下所有 key,再逐条读取(自动过滤过期)
|
||||||
const allKeys = (await (manager as any).driver.keys()) as string[];
|
const shortKeys = await manager.keys();
|
||||||
const fullPrefix = prefix ? `${prefix}-` : '';
|
|
||||||
const prefixedKeys = allKeys.filter((k: string) =>
|
|
||||||
k.startsWith(fullPrefix),
|
|
||||||
);
|
|
||||||
|
|
||||||
const results: Array<number | string> = [];
|
const results: Array<number | string> = [];
|
||||||
for (const fullKey of prefixedKeys) {
|
for (const shortKey of shortKeys) {
|
||||||
const shortKey = fullKey.replace(fullPrefix, '');
|
|
||||||
const value = await manager.getItem<number | string>(shortKey);
|
const value = await manager.getItem<number | string>(shortKey);
|
||||||
if (value !== null) {
|
if (value !== null) {
|
||||||
results.push(value);
|
results.push(value);
|
||||||
|
|
@ -124,43 +119,21 @@ function createStorageAdapter(
|
||||||
return createWebStorageAdapter('localStorage', persist);
|
return createWebStorageAdapter('localStorage', persist);
|
||||||
}
|
}
|
||||||
|
|
||||||
const {type = 'localStorage'} = persist;
|
switch (persist.type) {
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'custom': {
|
case 'custom': {
|
||||||
if (!persist.storage) {
|
|
||||||
// 没有提供 storage 适配器,降级为 memory
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// 用户自定义适配器,解除 Vue 响应式代理
|
// 用户自定义适配器,解除 Vue 响应式代理
|
||||||
return toRaw(persist.storage);
|
return toRaw(persist.storage);
|
||||||
}
|
}
|
||||||
case 'indexedDB': {
|
case 'indexedDB': {
|
||||||
if (!persist.key) {
|
|
||||||
console.warn('[viewedRow] persist.key is required for indexedDB type');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return createIndexedDBAdapter(persist);
|
return createIndexedDBAdapter(persist);
|
||||||
}
|
}
|
||||||
case 'localStorage': {
|
case 'localStorage': {
|
||||||
if (!persist.key) {
|
|
||||||
console.warn(
|
|
||||||
'[viewedRow] persist.key is required for localStorage type',
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return createWebStorageAdapter('localStorage', persist.key, persist.ttl);
|
return createWebStorageAdapter('localStorage', persist.key, persist.ttl);
|
||||||
}
|
}
|
||||||
case 'memory': {
|
case 'memory': {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
case 'sessionStorage': {
|
case 'sessionStorage': {
|
||||||
if (!persist.key) {
|
|
||||||
console.warn(
|
|
||||||
'[viewedRow] persist.key is required for sessionStorage type',
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return createWebStorageAdapter(
|
return createWebStorageAdapter(
|
||||||
'sessionStorage',
|
'sessionStorage',
|
||||||
persist.key,
|
persist.key,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue