import { defineStore } from 'pinia' interface IndexedDBStoreConfig { name: string; keyPath: string; indexes?: Array<{ name: string keyPath: string | string[] options?: IDBIndexParameters }>; } interface IndexedDBConfig { dbName: string; version?: number; } export const useIndexedDBStore = defineStore('indexedDB', { state: () => ({ storeRegistry: new Map(), dbName: '', db: null, currentVersion: 0, isInitialized: false }), actions: { registerStore(storeConfig: IndexedDBStoreConfig) { if (!this.storeRegistry.has(storeConfig.name)) { this.storeRegistry.set(storeConfig.name, storeConfig) } }, deleteDB() { return new Promise((resolve, reject) => { const request = indexedDB.deleteDatabase(this.dbName) request.onsuccess = () => { resolve(true) window.location.reload() } request.onerror = () => { reject(request.error) } }) }, openDB(config: IndexedDBConfig) { if (config) { this.dbName = config.dbName this.currentVersion = config.version || 1 } return new Promise((resolve, reject) => { const request = indexedDB.open(this.dbName, this.currentVersion) request.onupgradeneeded = (event: IDBVersionChangeEvent) => { const db = (event.target as IDBOpenDBRequest).result // 从注册中心获取所有Store配置 const stores = Array.from(this.storeRegistry.values()) stores.forEach((storeConfig: any) => { if (!db.objectStoreNames.contains(storeConfig.name)) { const objectStore = db.createObjectStore( storeConfig.name, { keyPath: storeConfig.keyPath } ) storeConfig.indexes?.forEach((index: any) => { objectStore.createIndex( index.name, index.keyPath, index.options ) }) } }) } request.onsuccess = (event: Event) => { this.db = (event.target as IDBOpenDBRequest).result this.isInitialized = true Array.from(this.db.objectStoreNames).forEach((storeName: any) => { this.registerStore({ name: storeName, keyPath: 'id' }) }) resolve(this.db) } request.onerror = (event: Event) => { reject((event.target as IDBOpenDBRequest).error) } }) }, // 动态升级数据库版本 async upgradeVersion() { this.currentVersion += 1 localStorage.setItem('dbVersion', this.currentVersion.toString()) this.db?.close() return this.openDB({ dbName: this.dbName, version: this.currentVersion }) }, useStore(storeName: string) { const verifyStore = async () => { if (!this.storeRegistry.has(storeName)) { throw new Error(`Store ${storeName} not registered`) } if (this.db && !this.db.objectStoreNames.contains(storeName)) { await this.upgradeVersion() } } const executeWithTransaction = async (mode: IDBTransactionMode, operation: any) => { await verifyStore() if (!this.db) await this.openDB({ dbName: this.dbName, version: this.currentVersion }) return new Promise((resolve, reject) => { // this.db; const transaction = this.db!.transaction(storeName, mode) const objectStore = transaction.objectStore(storeName) // 事务成功完成时的回调 // transaction.oncomplete = () => { // resolve(); // 事务成功完成,返回结果 // }; // 事务失败时的回调 transaction.onerror = (event) => { reject((event.target as IDBRequest).error) } // 执行操作 operation(objectStore).then((result: any) => { // 操作成功,返回结果 resolve(result) }).catch((error: any) => { // 操作失败,拒绝 Promise reject(error) }) }) } return { add: (data: any) => executeWithTransaction( 'readwrite', (store: any) => new Promise((resolve, reject) => { const request = store.add(data) request.onsuccess = () => resolve(request.result as IDBValidKey) request.onerror = () => reject(request.error) }) ), get: (key: IDBValidKey) => executeWithTransaction( 'readonly', (store: any) => new Promise((resolve, reject) => { const request = store.get(key) request.onsuccess = () => resolve(request.result as any) request.onerror = () => reject(request.error) }) ), update: (data: any) => executeWithTransaction( 'readwrite', (store: any) => new Promise((resolve, reject) => { const request = store.put(data) request.onsuccess = () => resolve(request.result as IDBValidKey) request.onerror = () => reject(request.error) }) ), delete: (key: IDBValidKey) => executeWithTransaction( 'readwrite', (store: any) => new Promise((resolve, reject) => { const request = store.delete(key) request.onsuccess = () => resolve(undefined) request.onerror = () => reject(request.error) }) ), getAll: () => executeWithTransaction( 'readonly', (store: any) => new Promise((resolve, reject) => { const request = store.getAll() request.onsuccess = () => resolve(request.result as any[]) request.onerror = () => reject(request.error) }) ), clearAll: () => executeWithTransaction( 'readwrite', (store: any) => new Promise((resolve, reject) => { const request = store.clear() request.onsuccess = () => resolve(true) request.onerror = () => reject(request.error) }) ) } } } })