174 lines
4.9 KiB
TypeScript
174 lines
4.9 KiB
TypeScript
|
import { defineStore } from 'pinia'
|
||
|
import { ref } from 'vue'
|
||
|
import { databaseService, type Transaction, type Category, type Account } from '@/services/database'
|
||
|
|
||
|
export const useDatabaseStore = defineStore('database', () => {
|
||
|
const isInitialized = ref(false)
|
||
|
const isLoading = ref(false)
|
||
|
const error = ref<string | null>(null)
|
||
|
|
||
|
// 数据状态
|
||
|
const transactions = ref<Transaction[]>([])
|
||
|
const categories = ref<Category[]>([])
|
||
|
const accounts = ref<Account[]>([])
|
||
|
|
||
|
// 初始化数据库
|
||
|
async function initialize() {
|
||
|
if (isInitialized.value) return
|
||
|
|
||
|
isLoading.value = true
|
||
|
error.value = null
|
||
|
|
||
|
try {
|
||
|
await databaseService.initialize()
|
||
|
await loadInitialData()
|
||
|
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([
|
||
|
databaseService.getTransactions(20, 0),
|
||
|
databaseService.getCategories(),
|
||
|
databaseService.getAccounts()
|
||
|
])
|
||
|
|
||
|
transactions.value = transactionsData
|
||
|
categories.value = categoriesData
|
||
|
accounts.value = accountsData
|
||
|
} catch (err) {
|
||
|
console.error('Failed to load initial data:', err)
|
||
|
throw err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 交易操作
|
||
|
async function addTransaction(transaction: Omit<Transaction, 'id'>) {
|
||
|
try {
|
||
|
const id = await databaseService.createTransaction(transaction)
|
||
|
const newTransaction = { ...transaction, id }
|
||
|
transactions.value.unshift(newTransaction)
|
||
|
return id
|
||
|
} catch (err) {
|
||
|
console.error('Failed to add transaction:', err)
|
||
|
throw err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function updateTransaction(id: number, updates: Partial<Transaction>) {
|
||
|
try {
|
||
|
await databaseService.updateTransaction(id, updates)
|
||
|
const index = transactions.value.findIndex(t => t.id === id)
|
||
|
if (index !== -1) {
|
||
|
transactions.value[index] = { ...transactions.value[index], ...updates }
|
||
|
}
|
||
|
} catch (err) {
|
||
|
console.error('Failed to update transaction:', err)
|
||
|
throw err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function deleteTransaction(id: number) {
|
||
|
try {
|
||
|
await databaseService.deleteTransaction(id)
|
||
|
const index = transactions.value.findIndex(t => t.id === id)
|
||
|
if (index !== -1) {
|
||
|
transactions.value.splice(index, 1)
|
||
|
}
|
||
|
} catch (err) {
|
||
|
console.error('Failed to delete transaction:', err)
|
||
|
throw err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 分类操作
|
||
|
async function addCategory(category: Omit<Category, 'id'>) {
|
||
|
try {
|
||
|
const id = await databaseService.createCategory(category)
|
||
|
const newCategory = { ...category, id }
|
||
|
categories.value.push(newCategory)
|
||
|
return id
|
||
|
} catch (err) {
|
||
|
console.error('Failed to add category:', err)
|
||
|
throw err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 账户操作
|
||
|
async function addAccount(account: Omit<Account, 'id'>) {
|
||
|
try {
|
||
|
const id = await databaseService.createAccount(account)
|
||
|
const newAccount = { ...account, id }
|
||
|
accounts.value.push(newAccount)
|
||
|
return id
|
||
|
} catch (err) {
|
||
|
console.error('Failed to add account:', 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)
|
||
|
}
|
||
|
|
||
|
// 搜索和筛选
|
||
|
function searchTransactions(query: string): Transaction[] {
|
||
|
if (!query.trim()) return transactions.value
|
||
|
|
||
|
const lowerQuery = query.toLowerCase()
|
||
|
return transactions.value.filter(t =>
|
||
|
t.merchant.toLowerCase().includes(lowerQuery) ||
|
||
|
(t.description && t.description.toLowerCase().includes(lowerQuery))
|
||
|
)
|
||
|
}
|
||
|
|
||
|
function filterTransactionsByCategory(categoryId: number): Transaction[] {
|
||
|
return transactions.value.filter(t => t.category_id === categoryId)
|
||
|
}
|
||
|
|
||
|
function filterTransactionsByAccount(accountId: number): Transaction[] {
|
||
|
return transactions.value.filter(t => t.account_id === accountId)
|
||
|
}
|
||
|
|
||
|
function filterTransactionsByDateRange(startDate: string, endDate: string): Transaction[] {
|
||
|
return transactions.value.filter(t => t.date >= startDate && t.date <= endDate)
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
// 状态
|
||
|
isInitialized,
|
||
|
isLoading,
|
||
|
error,
|
||
|
transactions,
|
||
|
categories,
|
||
|
accounts,
|
||
|
|
||
|
// 方法
|
||
|
initialize,
|
||
|
loadInitialData,
|
||
|
addTransaction,
|
||
|
updateTransaction,
|
||
|
deleteTransaction,
|
||
|
addCategory,
|
||
|
addAccount,
|
||
|
getDefaultCategory,
|
||
|
getDefaultAccount,
|
||
|
searchTransactions,
|
||
|
filterTransactionsByCategory,
|
||
|
filterTransactionsByAccount,
|
||
|
filterTransactionsByDateRange
|
||
|
}
|
||
|
})
|