import { get, set, del, keys } from 'idb-keyval'; import { Project, Generation, Asset } from '../types'; const CACHE_PREFIX = 'nano-banana'; const CACHE_VERSION = '1.0'; // 限制缓存项目数量 const MAX_CACHED_ITEMS = 50; // 限制缓存最大年龄 (3天) const MAX_CACHE_AGE = 3 * 24 * 60 * 60 * 1000; export class CacheService { private static getKey(type: string, id: string): string { return `${CACHE_PREFIX}-${CACHE_VERSION}-${type}-${id}`; } // Project caching static async saveProject(project: Project): Promise { // 在保存新项目之前,清理旧缓存 await this.clearOldCache(); await set(this.getKey('project', project.id), project); } static async getProject(id: string): Promise { return (await get(this.getKey('project', id))) || null; } static async getAllProjects(): Promise { const allKeys = await keys(); const projectKeys = allKeys.filter(key => typeof key === 'string' && key.includes(`${CACHE_PREFIX}-${CACHE_VERSION}-project-`) ); const projects = await Promise.all( projectKeys.map(key => get(key as string)) ); return projects.filter(Boolean) as Project[]; } // Asset caching (for offline access) static async cacheAsset(asset: Asset, data: Blob): Promise { // 在保存新资产之前,清理旧缓存 await this.clearOldCache(); await set(this.getKey('asset', asset.id), { asset, data, cachedAt: Date.now() }); } static async getCachedAsset(assetId: string): Promise<{ asset: Asset; data: Blob } | null> { const cached = await get(this.getKey('asset', assetId)); return cached || null; } // Generation metadata caching static async cacheGeneration(generation: Generation): Promise { // 在保存新生成记录之前,清理旧缓存 await this.clearOldCache(); await set(this.getKey('generation', generation.id), generation); } static async getGeneration(id: string): Promise { return (await get(this.getKey('generation', id))) || null; } // Clear old cache entries static async clearOldCache(maxAge: number = MAX_CACHE_AGE): Promise { const allKeys = await keys(); const now = Date.now(); // 收集需要删除的键 const keysToDelete: string[] = []; const validCachedItems: Array<{key: string, cachedAt: number}> = []; for (const key of allKeys) { if (typeof key === 'string' && key.startsWith(CACHE_PREFIX)) { const cached = await get(key); if (cached?.cachedAt) { // 检查是否过期 if ((now - cached.cachedAt) > maxAge) { keysToDelete.push(key); } else { validCachedItems.push({key, cachedAt: cached.cachedAt}); } } } } // 如果有效项目数量超过限制,删除最旧的项目 if (validCachedItems.length > MAX_CACHED_ITEMS) { // 按时间排序,最旧的在前面 validCachedItems.sort((a, b) => a.cachedAt - b.cachedAt); // 计算需要删除的数量 const excessCount = validCachedItems.length - MAX_CACHED_ITEMS; // 添加最旧的项目到删除列表 for (let i = 0; i < excessCount; i++) { keysToDelete.push(validCachedItems[i].key); } } // 执行删除 for (const key of keysToDelete) { await del(key); } } // 清空所有缓存 static async clearAllCache(): Promise { const allKeys = await keys(); const cacheKeys = allKeys.filter(key => typeof key === 'string' && key.startsWith(CACHE_PREFIX) ); for (const key of cacheKeys) { await del(key); } } }