import { hash } from 'ohash' const CacheInvalidationStrategy = Object.freeze({ CLEAR_ALL: 'clear_all', CLEAR_CURRENT: 'clear_current', CLEAR_PAGINATION: 'clear_pagination', KEEP_ALL: 'keep_all' }) class TableCache { constructor(cacheTime = 5 * 60 * 1e3, maxSize = 50, enableLog = false) { this.cache = new Map() this.cacheTime = cacheTime this.maxSize = maxSize this.enableLog = enableLog } // 内部日志工具 log(message, ...args) { if (this.enableLog) { console.log(`[TableCache] ${message}`, ...args) } } // 生成稳定的缓存键 generateKey(params) { return hash(params) } // 🔧 优化:增强类型安全性 generateTags(params) { const tags = /* @__PURE__ */ new Set() const searchKeys = Object.keys(params).filter( (key) => !['current', 'size', 'total'].includes(key) && params[key] !== void 0 && params[key] !== '' && params[key] !== null ) if (searchKeys.length > 0) { const searchTag = searchKeys.map((key) => `${key}:${String(params[key])}`).join('|') tags.add(`search:${searchTag}`) } else { tags.add('search:default') } tags.add(`pagination:${params.size || 10}`) tags.add('pagination') return tags } // 🔧 优化:LRU 缓存清理 evictLRU() { if (this.cache.size <= this.maxSize) return let lruKey = '' let minAccessCount = Infinity let oldestTime = Infinity for (const [key, item] of this.cache.entries()) { if ( item.accessCount < minAccessCount || (item.accessCount === minAccessCount && item.lastAccessTime < oldestTime) ) { lruKey = key minAccessCount = item.accessCount oldestTime = item.lastAccessTime } } if (lruKey) { this.cache.delete(lruKey) this.log(`LRU 清理缓存: ${lruKey}`) } } // 设置缓存 set(params, data, response) { const key = this.generateKey(params) const tags = this.generateTags(params) const now = Date.now() this.evictLRU() this.cache.set(key, { data, response, timestamp: now, params: key, tags, accessCount: 1, lastAccessTime: now }) } // 获取缓存 get(params) { const key = this.generateKey(params) const item = this.cache.get(key) if (!item) return null if (Date.now() - item.timestamp > this.cacheTime) { this.cache.delete(key) return null } item.accessCount++ item.lastAccessTime = Date.now() return item } // 根据标签清除缓存 clearByTags(tags) { let clearedCount = 0 for (const [key, item] of this.cache.entries()) { const hasMatchingTag = tags.some((tag) => Array.from(item.tags).some((itemTag) => itemTag.includes(tag)) ) if (hasMatchingTag) { this.cache.delete(key) clearedCount++ } } return clearedCount } // 清除当前搜索条件的缓存 clearCurrentSearch(params) { const key = this.generateKey(params) const deleted = this.cache.delete(key) return deleted ? 1 : 0 } // 清除分页缓存 clearPagination() { return this.clearByTags(['pagination']) } // 清空所有缓存 clear() { this.cache.clear() } // 获取缓存统计信息 getStats() { const total = this.cache.size let totalSize = 0 let totalAccess = 0 for (const item of this.cache.values()) { totalSize += JSON.stringify(item.data).length totalAccess += item.accessCount } const sizeInKB = (totalSize / 1024).toFixed(2) const avgHits = total > 0 ? (totalAccess / total).toFixed(1) : '0' return { total, size: `${sizeInKB}KB`, hitRate: `${avgHits} avg hits` } } // 清理过期缓存 cleanupExpired() { let cleanedCount = 0 const now = Date.now() for (const [key, item] of this.cache.entries()) { if (now - item.timestamp > this.cacheTime) { this.cache.delete(key) cleanedCount++ } } return cleanedCount } } export { CacheInvalidationStrategy, TableCache }