feat:新增ai分析,新增储值账户,优化通知规则

This commit is contained in:
2026-03-12 14:03:01 +08:00
parent 6a00875246
commit 6ca962a187
22 changed files with 1294 additions and 237 deletions

View File

@@ -1,5 +1,6 @@
import { defineStore } from 'pinia'
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { shouldCountAsExpense, shouldCountAsIncome } from '../config/ledger.js'
import { maybeEnrichTransactionWithAi } from '../services/ai/aiService.js'
import {
deleteTransaction,
@@ -52,19 +53,19 @@ export const useTransactionStore = defineStore(
})
const totalExpense = computed(() =>
sortedTransactions.value.reduce((sum, tx) => (tx.amount < 0 ? sum + tx.amount : sum), 0),
sortedTransactions.value.reduce((sum, tx) => (shouldCountAsExpense(tx) ? sum + tx.amount : sum), 0),
)
const totalIncome = computed(() =>
sortedTransactions.value.reduce((sum, tx) => (tx.amount > 0 ? sum + tx.amount : sum), 0),
sortedTransactions.value.reduce((sum, tx) => (shouldCountAsIncome(tx) ? sum + tx.amount : sum), 0),
)
const todaysExpense = computed(() =>
todaysTransactions.value.reduce((sum, tx) => (tx.amount < 0 ? sum + tx.amount : sum), 0),
todaysTransactions.value.reduce((sum, tx) => (shouldCountAsExpense(tx) ? sum + tx.amount : sum), 0),
)
const todaysIncome = computed(() =>
todaysTransactions.value.reduce((sum, tx) => (tx.amount > 0 ? sum + tx.amount : sum), 0),
todaysTransactions.value.reduce((sum, tx) => (shouldCountAsIncome(tx) ? sum + tx.amount : sum), 0),
)
const latestTransactions = computed(() => sortedTransactions.value.slice(0, 5))
@@ -90,7 +91,7 @@ export const useTransactionStore = defineStore(
dayKey,
label: formatDayLabel(dayKey),
totalExpense: records
.filter((tx) => tx.amount < 0)
.filter((tx) => shouldCountAsExpense(tx))
.reduce((sum, tx) => sum + Math.abs(tx.amount), 0),
items: records,
}))
@@ -117,10 +118,21 @@ export const useTransactionStore = defineStore(
}
}
const upsertTransaction = (nextTransaction) => {
transactions.value = replaceTransaction(transactions.value, nextTransaction)
}
const enrichTransactionInBackground = async (transaction) => {
const enriched = await maybeEnrichTransactionWithAi(transaction)
const enriched = await maybeEnrichTransactionWithAi(transaction, {
onProgress: (nextTransaction) => {
if (nextTransaction?.id === transaction.id) {
upsertTransaction(nextTransaction)
}
},
})
if (!enriched || enriched.id !== transaction.id) return
transactions.value = replaceTransaction(transactions.value, enriched)
upsertTransaction(enriched)
}
const addTransaction = async (payload) => {
@@ -141,7 +153,7 @@ export const useTransactionStore = defineStore(
}
const updated = await updateTransaction(normalized)
if (updated) {
transactions.value = replaceTransaction(transactions.value, updated)
upsertTransaction(updated)
void enrichTransactionInBackground(updated)
}
return updated

View File

@@ -1,7 +1,7 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
// 负责全局 UI 状态,例如新增记录的底部弹窗
// 管理全局 UI 状态,例如记一笔弹层的开关和当前编辑项。
export const useUiStore = defineStore('ui', () => {
const addEntryVisible = ref(false)
const editingTransactionId = ref('')
@@ -23,4 +23,3 @@ export const useUiStore = defineStore('ui', () => {
closeAddEntry,
}
})