From 6580a434eea3933ad22bcfa313e8fe53dcbfeded Mon Sep 17 00:00:00 2001 From: CHE LIANG ZHAO Date: Tue, 13 Jan 2026 13:23:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20=E6=96=B0=E5=A2=9E=20DateTimePicke?= =?UTF-8?q?r=20=E7=BB=84=E4=BB=B6=EF=BC=8C=E4=BC=98=E5=8C=96=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E6=B7=BB=E5=8A=A0=E8=B4=A6=E5=8D=95=E8=A1=A8=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 shadcn-ui 的 Calendar + Popover 替换原生 datetime-local - 根据收支类型动态切换分类选项(支出/收入分类) - 切换收支类型时自动清空已选分类 - 收入模式下隐藏支付方式和交易状态输入框 - 调整表单布局为 1:1 两列 --- .../components/bills/ManualBillInput.svelte | 66 ++++----- .../date-time-picker/date-time-picker.svelte | 137 ++++++++++++++++++ .../components/ui/date-time-picker/index.ts | 3 + web/src/routes/bills/+page.svelte | 2 +- 4 files changed, 171 insertions(+), 37 deletions(-) create mode 100644 web/src/lib/components/ui/date-time-picker/date-time-picker.svelte create mode 100644 web/src/lib/components/ui/date-time-picker/index.ts diff --git a/web/src/lib/components/bills/ManualBillInput.svelte b/web/src/lib/components/bills/ManualBillInput.svelte index e0a2b8f..1a9f1b3 100644 --- a/web/src/lib/components/bills/ManualBillInput.svelte +++ b/web/src/lib/components/bills/ManualBillInput.svelte @@ -7,21 +7,21 @@ import { Label } from '$lib/components/ui/label'; import { Badge } from '$lib/components/ui/badge'; import * as Table from '$lib/components/ui/table'; + import { DateTimePicker } from '$lib/components/ui/date-time-picker'; import { createManualBills, type ManualBillInput } from '$lib/api'; + import { expenseCategories, incomeCategories } from '$lib/data/categories'; import Plus from '@lucide/svelte/icons/plus'; import Trash2 from '@lucide/svelte/icons/trash-2'; import Send from '@lucide/svelte/icons/send'; import Loader2 from '@lucide/svelte/icons/loader-2'; import CheckCircle from '@lucide/svelte/icons/check-circle'; import AlertCircle from '@lucide/svelte/icons/alert-circle'; - import Clock from '@lucide/svelte/icons/clock'; interface Props { - categories: string[]; onSuccess?: () => void; } - let { categories, onSuccess }: Props = $props(); + let { onSuccess }: Props = $props(); // 获取当前日期时间(格式化为 YYYY-MM-DDTHH:mm) function getCurrentDateTimeLocal(): string { @@ -43,8 +43,7 @@ // 表单状态 let formData = $state({ - time: '', - timeLocal: getCurrentDateTimeLocal(), // 用于时间选择器的格式 + time: getCurrentDateTime(), category: '', merchant: '', description: '', @@ -55,6 +54,13 @@ remark: '', }); + // 根据收支类型动态计算分类列表 + let currentCategories = $derived( + formData.income_expense === '收入' + ? [...incomeCategories] + : [...expenseCategories] + ); + // 待提交的账单列表 let pendingBills = $state([]); @@ -74,6 +80,8 @@ function handleIncomeExpenseChange(value: string | undefined) { if (value !== undefined) { formData.income_expense = value; + // 切换收支类型时清空已选分类(因为分类列表会变化) + formData.category = ''; } } @@ -89,19 +97,11 @@ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } - // 设置当前时间 - function setCurrentTime() { - formData.timeLocal = getCurrentDateTimeLocal(); - formData.time = convertDateTimeLocal(formData.timeLocal); + // 处理日期时间变化 + function handleDateTimeChange(value: string) { + formData.time = value; } - // 监听时间选择器变化 - $effect(() => { - if (formData.timeLocal) { - formData.time = convertDateTimeLocal(formData.timeLocal); - } - }); - // 验证表单 function validateForm(): string | null { if (!formData.time) return '请输入交易时间'; @@ -137,8 +137,7 @@ const savedCategory = formData.category; const savedIncomeExpense = formData.income_expense; formData = { - time: '', - timeLocal: getCurrentDateTimeLocal(), + time: getCurrentDateTime(), category: savedCategory, merchant: '', description: '', @@ -197,9 +196,9 @@ } -
+
- + @@ -212,18 +211,11 @@
-
- - -
-

已选择:{formData.time || '未选择'}

+
@@ -235,7 +227,7 @@ - {#each categories as cat} + {#each currentCategories as cat} {cat} {/each} @@ -284,15 +276,16 @@
- +
+ {#if formData.income_expense === '支出'}
@@ -314,6 +307,7 @@ bind:value={formData.status} />
+ {/if}
@@ -336,7 +330,7 @@ - +
diff --git a/web/src/lib/components/ui/date-time-picker/date-time-picker.svelte b/web/src/lib/components/ui/date-time-picker/date-time-picker.svelte new file mode 100644 index 0000000..e556bdb --- /dev/null +++ b/web/src/lib/components/ui/date-time-picker/date-time-picker.svelte @@ -0,0 +1,137 @@ + + + + + {#snippet child({ props })} + + {/snippet} + + + +
+ +
+
+ + 时间 + + +
+
+
+ +
+
+
+
+
diff --git a/web/src/lib/components/ui/date-time-picker/index.ts b/web/src/lib/components/ui/date-time-picker/index.ts new file mode 100644 index 0000000..bfea72a --- /dev/null +++ b/web/src/lib/components/ui/date-time-picker/index.ts @@ -0,0 +1,3 @@ +import DateTimePicker from "./date-time-picker.svelte"; + +export { DateTimePicker }; diff --git a/web/src/routes/bills/+page.svelte b/web/src/routes/bills/+page.svelte index 5da3ea2..fc873dc 100644 --- a/web/src/routes/bills/+page.svelte +++ b/web/src/routes/bills/+page.svelte @@ -483,6 +483,6 @@ {#if activeTab === 'manual'} - + {/if}