refactor(web): unify bills as UIBill, remove BillRecord

This commit is contained in:
clz
2026-01-18 21:14:54 +08:00
parent c61691249f
commit 65ea2fa477
13 changed files with 484 additions and 613 deletions

View File

@@ -9,13 +9,13 @@
import AreaChart from '@lucide/svelte/icons/area-chart';
import LineChart from '@lucide/svelte/icons/line-chart';
import { Button } from '$lib/components/ui/button';
import type { BillRecord } from '$lib/api';
import type { UIBill } from '$lib/models/bill';
import { pieColors } from '$lib/constants/chart';
import { formatLocalDate } from '$lib/utils';
import BillRecordsTable from './BillRecordsTable.svelte';
interface Props {
records: BillRecord[];
records: UIBill[];
categories?: string[];
}
@@ -24,7 +24,7 @@
// Dialog 状态
let dialogOpen = $state(false);
let selectedDate = $state<Date | null>(null);
let selectedDateRecords = $state<BillRecord[]>([]);
let selectedDateRecords = $state<UIBill[]>([]);
// 时间范围选项
type TimeRange = '7d' | 'week' | '30d' | 'month' | '3m' | 'year';
@@ -125,7 +125,7 @@
// 过滤支出记录
const expenseRecords = records.filter(r => {
if (r.income_expense !== '支出') return false;
if (r.incomeExpense !== '支出') return false;
const recordDate = new Date(extractDateStr(r.time));
return recordDate >= cutoffDate;
});
@@ -139,7 +139,7 @@
expenseRecords.forEach(record => {
const dateStr = extractDateStr(record.time);
const category = record.category || '其他';
const amount = parseFloat(record.amount) || 0;
const amount = record.amount || 0;
categoryTotals[category] = (categoryTotals[category] || 0) + amount;
@@ -502,6 +502,19 @@
tooltipData = null;
}
function openDateDetails(clickedDate: Date) {
const dateStr = formatLocalDate(clickedDate);
selectedDate = clickedDate;
selectedDateRecords = records.filter(r => {
if (r.incomeExpense !== '支出') return false;
const recordDateStr = extractDateStr(r.time);
return recordDateStr === dateStr;
});
dialogOpen = true;
}
// 点击打开 Dialog
function handleClick(event: MouseEvent, data: any[], maxValue: number) {
if (data.length === 0) return;
@@ -527,17 +540,7 @@
// 点击图表任意位置都触发,选择最近的日期
const clickedDate = data[closestIdx].date;
const dateStr = formatLocalDate(clickedDate);
// 找出当天的所有支出记录
selectedDate = clickedDate;
selectedDateRecords = records.filter(r => {
if (r.income_expense !== '支出') return false;
const recordDateStr = extractDateStr(r.time);
return recordDateStr === dateStr;
});
dialogOpen = true;
openDateDetails(clickedDate);
}
// 计算选中日期的统计
@@ -549,7 +552,7 @@
selectedDateRecords.forEach(r => {
const cat = r.category || '其他';
const amount = parseFloat(r.amount) || 0;
const amount = r.amount || 0;
total += amount;
if (!categoryMap.has(cat)) {
@@ -648,16 +651,22 @@
<!-- 趋势图 (自定义 SVG) -->
<div class="relative w-full" style="aspect-ratio: {chartWidth}/{chartHeight};">
<!-- svelte-ignore a11y_no_noninteractive_tabindex a11y_no_noninteractive_element_interactions a11y_click_events_have_key_events -->
<svg
viewBox="0 0 {chartWidth} {chartHeight}"
class="w-full h-full cursor-pointer outline-none focus:outline-none"
role="application"
role="button"
aria-label="每日支出趋势图表,点击可查看当日详情"
tabindex="-1"
tabindex="0"
onmousemove={(e) => handleMouseMove(e, data, maxValue)}
onmouseleave={handleMouseLeave}
onclick={(e) => handleClick(e, data, maxValue)}
onkeydown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
const last = data[data.length - 1];
if (last?.date) openDateDetails(last.date);
}
}}
>
<!-- Y 轴 -->
<line