Files
gamegroup2/frontend/src/stores/ledger.ts
T
congsh e4b730c8db fix(phase3): subscription leak, image mime type validation
- Ledger store: add stopSubscription() to properly clean up realtime
  subscriptions, matching asset store pattern
- LedgerList: call stopSubscription on unmount
- Assets migration: restrict image upload to image/* mime types
  (C3 updateRule is a known tradeoff — PocketBase lacks field-level
  permissions, frontend enforces edit restrictions instead)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 19:52:34 +08:00

109 lines
2.6 KiB
TypeScript

// src/stores/ledger.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Ledger } from '@/types'
import {
listLedgers,
createLedger,
updateLedger,
deleteLedger,
getLedgerSummary,
subscribeLedgers
} from '@/api/ledgers'
export const useLedgerStore = defineStore('ledger', () => {
const ledgers = ref<Ledger[]>([])
const loading = ref(false)
const summary = ref({ totalIncome: 0, totalExpense: 0, balance: 0 })
const currentMonth = ref(new Date().toISOString().slice(0, 7))
let unsubFn: (() => Promise<void> | void) | null = null
// 加载账目列表和汇总
async function loadLedgers(groupId: string, month?: string) {
try {
loading.value = true
const filterMonth = month || currentMonth.value
const [listResult, summaryResult] = await Promise.all([
listLedgers(groupId, { month: filterMonth }),
getLedgerSummary(groupId, filterMonth)
])
ledgers.value = listResult.items
summary.value = summaryResult
if (month) currentMonth.value = month
} catch (error) {
console.error('加载账目列表失败:', error)
} finally {
loading.value = false
}
}
// 只加载汇总
async function loadSummary(groupId: string, month?: string) {
try {
const filterMonth = month || currentMonth.value
summary.value = await getLedgerSummary(groupId, filterMonth)
} catch (error) {
console.error('加载账目汇总失败:', error)
}
}
// 新增账目
async function addLedger(data: Parameters<typeof createLedger>[0]) {
try {
await createLedger(data)
} catch (error) {
console.error('新增账目失败:', error)
throw error
}
}
// 编辑账目
async function editLedger(ledgerId: string, data: Parameters<typeof updateLedger>[1]) {
try {
await updateLedger(ledgerId, data)
} catch (error) {
console.error('编辑账目失败:', error)
throw error
}
}
// 删除账目
async function removeLedger(ledgerId: string) {
try {
await deleteLedger(ledgerId)
} catch (error) {
console.error('删除账目失败:', error)
throw error
}
}
// 订阅实时更新
async function startSubscription(groupId: string) {
stopSubscription()
unsubFn = await subscribeLedgers(groupId, () => {
loadLedgers(groupId)
})
}
function stopSubscription() {
if (unsubFn) {
unsubFn()
unsubFn = null
}
}
return {
ledgers,
loading,
summary,
currentMonth,
loadLedgers,
loadSummary,
addLedger,
editLedger,
removeLedger,
startSubscription,
stopSubscription
}
})