+
+
+
本周{{ activeTabTitle }}率
+
+ {{ overallStats.week.rate }}%
+
+
{{ overallStats.week.count }}个预算
+
+
+
+
本月{{ activeTabTitle }}率
+
+ {{ overallStats.month.rate }}%
+
+
{{ overallStats.month.count }}个预算
+
+
+
+
年度{{ activeTabTitle }}率
+
+ {{ overallStats.year.rate }}%
+
+
{{ overallStats.year.count }}个预算
+
+
@@ -321,6 +396,53 @@ const expenseBudgets = ref([])
const incomeBudgets = ref([])
const savingsBudgets = ref([])
+const activeTabTitle = computed(() => {
+ if (activeTab.value === BudgetCategory.Expense) return '使用'
+ return '达成'
+})
+
+const overallStats = computed(() => {
+ const allBudgets = [...expenseBudgets.value, ...incomeBudgets.value, ...savingsBudgets.value]
+
+ const getStatsForType = (type) => {
+ const category = activeTab.value
+ const filtered = allBudgets.filter(b => b.type === type && b.category === category && !b.isStopped)
+
+ if (filtered.length === 0) return { rate: '0.0', current: 0, limit: 0, count: 0 }
+
+ const current = filtered.reduce((sum, b) => sum + (b.current || 0), 0)
+ const limit = filtered.reduce((sum, b) => sum + (b.limit || 0), 0)
+ const rate = limit > 0 ? (current / limit) * 100 : 0
+
+ return {
+ rate: rate.toFixed(1),
+ current,
+ limit,
+ count: filtered.length
+ }
+ }
+
+ return {
+ week: getStatsForType(BudgetPeriodType.Week),
+ month: getStatsForType(BudgetPeriodType.Month),
+ year: getStatsForType(BudgetPeriodType.Year)
+ }
+})
+
+const getValueClass = (rate) => {
+ const numRate = parseFloat(rate)
+ if (numRate === 0) return ''
+ if (activeTab.value === BudgetCategory.Expense) {
+ if (numRate >= 100) return 'expense'
+ if (numRate >= 80) return 'warning'
+ return 'income'
+ } else {
+ if (numRate >= 100) return 'income'
+ if (numRate >= 80) return 'warning'
+ return 'expense'
+ }
+}
+
const form = reactive({
name: '',
type: BudgetPeriodType.Month,
@@ -457,7 +579,6 @@ const handleDelete = (budget) => {
const res = await deleteBudget(budget.id)
if (res.success) {
showToast('已删除')
- delete refDateMap[budget.id]
fetchBudgetList()
}
} catch (err) {
@@ -684,4 +805,70 @@ const onSubmit = async () => {
:deep(.van-tabs__nav--card) {
margin: 0 12px;
}
+
+.summary-card {
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ text-align: center;
+ padding: 12px 16px;
+ margin-top: 12px;
+ margin-bottom: 4px;
+}
+
+.summary-item {
+ flex: 1;
+}
+
+.summary-item .label {
+ font-size: 12px;
+ color: #969799;
+ margin-bottom: 6px;
+}
+
+.summary-item .value {
+ font-size: 20px;
+ font-weight: bold;
+ margin-bottom: 2px;
+ color: #323233;
+}
+
+.summary-item .value.expense {
+ color: #ee0a24;
+}
+
+.summary-item .value.income {
+ color: #07c160;
+}
+
+.summary-item .value.warning {
+ color: #ff976a;
+}
+
+.summary-item .unit {
+ font-size: 11px;
+ margin-left: 1px;
+ font-weight: normal;
+}
+
+.summary-item .sub-label {
+ font-size: 11px;
+ color: #c8c9cc;
+}
+
+.divider {
+ width: 1px;
+ height: 24px;
+ background-color: #ebedf0;
+ margin: 0 4px;
+}
+
+@media (prefers-color-scheme: dark) {
+ .summary-item .value {
+ color: #f5f5f5;
+ }
+ .divider {
+ background-color: #2c2c2c;
+ }
+}