209 lines
6.0 KiB
TypeScript
209 lines
6.0 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import { accountApi } from '@/api/accounts'
|
|
import type {
|
|
FinancialAccount, AccountFormData, BalanceUpdateData,
|
|
AccountHistoryRecord, DebtInstallment, DebtInstallmentFormData
|
|
} from '@/api/types'
|
|
|
|
export const useAccountStore = defineStore('account', () => {
|
|
const accounts = ref<FinancialAccount[]>([])
|
|
const installments = ref<DebtInstallment[]>([])
|
|
const loading = ref(false)
|
|
|
|
const savingsAccounts = computed(() =>
|
|
accounts.value.filter(a => a.account_type === 'savings' && a.is_active)
|
|
)
|
|
|
|
const debtAccounts = computed(() =>
|
|
accounts.value.filter(a => a.account_type === 'debt' && a.is_active)
|
|
)
|
|
|
|
const totalSavings = computed(() =>
|
|
savingsAccounts.value.reduce((sum, a) => sum + a.balance, 0)
|
|
)
|
|
|
|
const totalDebt = computed(() =>
|
|
debtAccounts.value.reduce((sum, a) => sum + a.balance, 0)
|
|
)
|
|
|
|
const netAssets = computed(() => totalSavings.value - totalDebt.value)
|
|
|
|
const activeInstallments = computed(() =>
|
|
installments.value.filter(i => !i.is_completed && i.days_until_payment !== null)
|
|
)
|
|
|
|
const upcomingPayments = computed(() =>
|
|
activeInstallments.value
|
|
.filter(i => i.days_until_payment! >= 0)
|
|
.sort((a, b) => a.days_until_payment! - b.days_until_payment!)
|
|
)
|
|
|
|
// ============ 账户操作 ============
|
|
|
|
async function fetchAccounts() {
|
|
loading.value = true
|
|
try {
|
|
accounts.value = await accountApi.getAccounts()
|
|
} catch (error) {
|
|
console.error('获取账户列表失败:', error)
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
async function createAccount(data: AccountFormData): Promise<FinancialAccount | null> {
|
|
try {
|
|
const account = await accountApi.createAccount(data)
|
|
accounts.value.push(account)
|
|
return account
|
|
} catch (error) {
|
|
console.error('创建账户失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function updateAccount(id: number, data: Partial<AccountFormData>): Promise<FinancialAccount | null> {
|
|
try {
|
|
const updated = await accountApi.updateAccount(id, data)
|
|
const index = accounts.value.findIndex(a => a.id === id)
|
|
if (index !== -1) {
|
|
accounts.value[index] = updated
|
|
}
|
|
return updated
|
|
} catch (error) {
|
|
console.error('更新账户失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function deleteAccount(id: number): Promise<boolean> {
|
|
try {
|
|
await accountApi.deleteAccount(id)
|
|
accounts.value = accounts.value.filter(a => a.id !== id)
|
|
return true
|
|
} catch (error) {
|
|
console.error('删除账户失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function updateBalance(id: number, data: BalanceUpdateData): Promise<FinancialAccount | null> {
|
|
try {
|
|
const updated = await accountApi.updateBalance(id, data)
|
|
const index = accounts.value.findIndex(a => a.id === id)
|
|
if (index !== -1) {
|
|
accounts.value[index] = updated
|
|
}
|
|
return updated
|
|
} catch (error) {
|
|
console.error('更新余额失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function fetchHistory(id: number, page = 1, pageSize = 20): Promise<AccountHistoryResponse> {
|
|
try {
|
|
return await accountApi.getHistory(id, { page, page_size: pageSize })
|
|
} catch (error) {
|
|
console.error('获取变更历史失败:', error)
|
|
return { total: 0, page: 1, page_size: pageSize, records: [] }
|
|
}
|
|
}
|
|
|
|
// ============ 分期计划操作 ============
|
|
|
|
async function fetchInstallments() {
|
|
try {
|
|
installments.value = await accountApi.getInstallments()
|
|
} catch (error) {
|
|
console.error('获取分期计划失败:', error)
|
|
}
|
|
}
|
|
|
|
async function createInstallment(data: DebtInstallmentFormData): Promise<DebtInstallment | null> {
|
|
try {
|
|
const inst = await accountApi.createInstallment(data)
|
|
installments.value.push(inst)
|
|
installments.value.sort((a, b) => {
|
|
const aActive = !a.is_completed && a.days_until_payment !== null ? 0 : 1
|
|
const bActive = !b.is_completed && b.days_until_payment !== null ? 0 : 1
|
|
if (aActive !== bActive) return aActive - bActive
|
|
return (a.days_until_payment ?? 9999) - (b.days_until_payment ?? 9999)
|
|
})
|
|
return inst
|
|
} catch (error) {
|
|
console.error('创建分期计划失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function updateInstallment(id: number, data: Partial<DebtInstallmentFormData>): Promise<DebtInstallment | null> {
|
|
try {
|
|
const updated = await accountApi.updateInstallment(id, data)
|
|
const index = installments.value.findIndex(i => i.id === id)
|
|
if (index !== -1) {
|
|
installments.value[index] = updated
|
|
}
|
|
return updated
|
|
} catch (error) {
|
|
console.error('更新分期计划失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function deleteInstallment(id: number): Promise<boolean> {
|
|
try {
|
|
await accountApi.deleteInstallment(id)
|
|
installments.value = installments.value.filter(i => i.id !== id)
|
|
return true
|
|
} catch (error) {
|
|
console.error('删除分期计划失败:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function payInstallment(id: number): Promise<DebtInstallment | null> {
|
|
try {
|
|
const updated = await accountApi.payInstallment(id)
|
|
const index = installments.value.findIndex(i => i.id === id)
|
|
if (index !== -1) {
|
|
installments.value[index] = updated
|
|
}
|
|
return updated
|
|
} catch (error) {
|
|
console.error('标记还款失败:', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function init() {
|
|
await Promise.all([fetchAccounts(), fetchInstallments()])
|
|
}
|
|
|
|
return {
|
|
accounts,
|
|
installments,
|
|
loading,
|
|
savingsAccounts,
|
|
debtAccounts,
|
|
totalSavings,
|
|
totalDebt,
|
|
netAssets,
|
|
activeInstallments,
|
|
upcomingPayments,
|
|
fetchAccounts,
|
|
createAccount,
|
|
updateAccount,
|
|
deleteAccount,
|
|
updateBalance,
|
|
fetchHistory,
|
|
fetchInstallments,
|
|
createInstallment,
|
|
updateInstallment,
|
|
deleteInstallment,
|
|
payInstallment,
|
|
init,
|
|
}
|
|
})
|