import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { databaseService } from '@/services/database' import { repositoryManager } from '@/repositories' import type { Transaction, Category, Account, TransactionWithDetails, TransactionFilters, SyncStatus } from '@/types' export const useDatabaseStore = defineStore('database', () => { // 基础状态 const isInitialized = ref(false) const isLoading = ref(false) const error = ref(null) // 数据状态 const transactions = ref([]) const categories = ref([]) const accounts = ref([]) // 离线状态 const isOnline = ref(navigator.onLine) const syncStatus = ref({ isOnline: navigator.onLine, pendingChanges: 0, syncInProgress: false }) // 缓存状态 const lastRefreshTime = ref(null) const cacheExpiry = 5 * 60 * 1000 // 5分钟缓存 // 计算属性 const pendingTransactions = computed(() => transactions.value.filter(t => t.sync_status === 'pending') ) const conflictTransactions = computed(() => transactions.value.filter(t => t.sync_status === 'conflict') ) const totalBalance = computed(() => { const income = transactions.value .filter(t => t.type === 'income') .reduce((sum, t) => sum + t.amount, 0) const expense = transactions.value .filter(t => t.type === 'expense') .reduce((sum, t) => sum + t.amount, 0) return income - expense }) const monthlyStats = computed(() => { const now = new Date() const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1) const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0) const monthlyTransactions = transactions.value.filter(t => { const transactionDate = new Date(t.date) return transactionDate >= startOfMonth && transactionDate <= endOfMonth }) const income = monthlyTransactions .filter(t => t.type === 'income') .reduce((sum, t) => sum + t.amount, 0) const expense = monthlyTransactions .filter(t => t.type === 'expense') .reduce((sum, t) => sum + t.amount, 0) return { income, expense, balance: income - expense, transactionCount: monthlyTransactions.length } }) // 网络状态监听 function setupNetworkListeners() { window.addEventListener('online', () => { isOnline.value = true syncStatus.value.isOnline = true // 自动同步待处理的更改 syncPendingChanges() }) window.addEventListener('offline', () => { isOnline.value = false syncStatus.value.isOnline = false }) } // 初始化数据库 async function initialize() { if (isInitialized.value) return isLoading.value = true error.value = null try { await databaseService.initialize() await loadInitialData() setupNetworkListeners() updateSyncStatus() isInitialized.value = true console.log('Database store initialized successfully') } catch (err) { error.value = err instanceof Error ? err.message : 'Database initialization failed' console.error('Database store initialization failed:', err) } finally { isLoading.value = false } } // 加载初始数据 async function loadInitialData() { try { const [transactionsData, categoriesData, accountsData] = await Promise.all([ repositoryManager.transaction.findAll({ page: 1, limit: 50, offset: 0 }), repositoryManager.category.findAll(), repositoryManager.account.findAll() ]) transactions.value = transactionsData categories.value = categoriesData accounts.value = accountsData lastRefreshTime.value = new Date() } catch (err) { console.error('Failed to load initial data:', err) throw err } } // 刷新数据(如果缓存过期) async function refreshIfNeeded() { if (!lastRefreshTime.value || Date.now() - lastRefreshTime.value.getTime() > cacheExpiry) { await loadInitialData() } } // 更新同步状态 function updateSyncStatus() { syncStatus.value = { isOnline: isOnline.value, lastSyncTime: syncStatus.value.lastSyncTime, pendingChanges: pendingTransactions.value.length, syncInProgress: syncStatus.value.syncInProgress, syncError: syncStatus.value.syncError } } // 交易操作 async function addTransaction(transaction: Omit) { try { const id = await repositoryManager.transaction.create(transaction) const newTransaction = { ...transaction, id, sync_status: 'pending' as const } as TransactionWithDetails transactions.value.unshift(newTransaction) updateSyncStatus() // 如果在线,尝试立即同步 if (isOnline.value) { syncPendingChanges() } return id } catch (err) { console.error('Failed to add transaction:', err) throw err } } async function updateTransaction(id: number, updates: Partial) { try { await repositoryManager.transaction.update(id, { ...updates, sync_status: 'pending' }) const index = transactions.value.findIndex(t => t.id === id) if (index !== -1) { transactions.value[index] = { ...transactions.value[index], ...updates, sync_status: 'pending' } } updateSyncStatus() if (isOnline.value) { syncPendingChanges() } } catch (err) { console.error('Failed to update transaction:', err) throw err } } async function deleteTransaction(id: number) { try { await repositoryManager.transaction.delete(id) const index = transactions.value.findIndex(t => t.id === id) if (index !== -1) { transactions.value.splice(index, 1) } updateSyncStatus() } catch (err) { console.error('Failed to delete transaction:', err) throw err } } // 分类操作 async function addCategory(category: Omit) { try { const id = await repositoryManager.category.create(category) const newCategory = { ...category, id } categories.value.push(newCategory) return id } catch (err) { console.error('Failed to add category:', err) throw err } } async function updateCategory(id: number, updates: Partial) { try { await repositoryManager.category.update(id, updates) const index = categories.value.findIndex(c => c.id === id) if (index !== -1) { categories.value[index] = { ...categories.value[index], ...updates } } } catch (err) { console.error('Failed to update category:', err) throw err } } async function deleteCategory(id: number) { try { await repositoryManager.category.delete(id) const index = categories.value.findIndex(c => c.id === id) if (index !== -1) { categories.value.splice(index, 1) } } catch (err) { console.error('Failed to delete category:', err) throw err } } // 账户操作 async function addAccount(account: Omit) { try { const id = await repositoryManager.account.create(account) const newAccount = { ...account, id } accounts.value.push(newAccount) return id } catch (err) { console.error('Failed to add account:', err) throw err } } async function updateAccount(id: number, updates: Partial) { try { await repositoryManager.account.update(id, updates) const index = accounts.value.findIndex(a => a.id === id) if (index !== -1) { accounts.value[index] = { ...accounts.value[index], ...updates } } } catch (err) { console.error('Failed to update account:', err) throw err } } async function deleteAccount(id: number) { try { await repositoryManager.account.delete(id) const index = accounts.value.findIndex(a => a.id === id) if (index !== -1) { accounts.value.splice(index, 1) } } catch (err) { console.error('Failed to delete account:', err) throw err } } // 搜索和筛选 async function searchTransactions(query: string) { try { const results = await repositoryManager.transaction.search(query) return results } catch (err) { console.error('Failed to search transactions:', err) throw err } } async function filterTransactions(filters: TransactionFilters) { try { const results = await repositoryManager.transaction.findWithFilters(filters) return results } catch (err) { console.error('Failed to filter transactions:', err) throw err } } // 获取默认分类和账户 function getDefaultCategory(type: 'income' | 'expense'): Category | undefined { return categories.value.find(c => c.is_default && (c.type === type || c.type === 'both')) } function getDefaultAccount(): Account | undefined { return accounts.value.find(a => a.is_default) } // 同步功能(占位符,将在云端功能中实现) async function syncPendingChanges() { if (!isOnline.value || syncStatus.value.syncInProgress) return syncStatus.value.syncInProgress = true try { // 这里将在后续任务中实现实际的同步逻辑 console.log('Sync pending changes (placeholder)') // 模拟同步延迟 await new Promise(resolve => setTimeout(resolve, 1000)) syncStatus.value.lastSyncTime = new Date().toISOString() syncStatus.value.syncError = undefined } catch (err) { syncStatus.value.syncError = err instanceof Error ? err.message : 'Sync failed' console.error('Sync failed:', err) } finally { syncStatus.value.syncInProgress = false updateSyncStatus() } } // 强制同步 async function forceSync() { await syncPendingChanges() } // 离线模式提示 function showOfflineMessage() { return !isOnline.value } // 数据统计 async function getStats(startDate?: string, endDate?: string) { try { return await repositoryManager.transaction.getStats(startDate, endDate) } catch (err) { console.error('Failed to get stats:', err) throw err } } // 数据完整性检查 async function checkDataIntegrity() { try { return await repositoryManager.checkDataIntegrity() } catch (err) { console.error('Failed to check data integrity:', err) throw err } } // 清理错误状态 function clearError() { error.value = null syncStatus.value.syncError = undefined } return { // 基础状态 isInitialized, isLoading, error, // 数据状态 transactions, categories, accounts, // 离线状态 isOnline, syncStatus, // 计算属性 pendingTransactions, conflictTransactions, totalBalance, monthlyStats, // 基础方法 initialize, loadInitialData, refreshIfNeeded, clearError, // 交易操作 addTransaction, updateTransaction, deleteTransaction, // 分类操作 addCategory, updateCategory, deleteCategory, // 账户操作 addAccount, updateAccount, deleteAccount, // 搜索和筛选 searchTransactions, filterTransactions, // 工具方法 getDefaultCategory, getDefaultAccount, getStats, checkDataIntegrity, // 同步功能 syncPendingChanges, forceSync, showOfflineMessage } })