feat: phase 3 - ledger and asset management

Add group expense tracking (ledger) and public asset inventory (asset) features.
Ledger supports income/expense recording with monthly summary. Asset tracks
group equipment with free-form holder transfer. Both are independent pages
accessible from GroupView navigation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
congsh
2026-04-18 19:42:04 +08:00
parent 625d0baf7d
commit c5413644f9
21 changed files with 4407 additions and 1 deletions
+99
View File
@@ -0,0 +1,99 @@
// 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))
// 加载账目列表和汇总
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) {
await subscribeLedgers(groupId, () => {
// 收到变更后重新加载当前月份的数据
loadLedgers(groupId)
})
}
return {
ledgers,
loading,
summary,
currentMonth,
loadLedgers,
loadSummary,
addLedger,
editLedger,
removeLedger,
startSubscription
}
})