fix: 修复日期范围选择器时区和性能问题
- 修复时区问题:使用本地时区格式化日期,避免 toISOString() 导致的日期偏移 - 优化日期范围选择器性能:使用 untrack 避免循环更新 - 统一日期格式化方法:在 utils.ts 中添加 formatLocalDate 工具函数 - 修复分页逻辑:优化页码计算和显示 - 更新相关页面:bills 和 analysis 页面使用统一的日期格式化方法
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import type { BillRecord } from '$lib/api';
|
||||
import { pieColors } from '$lib/constants/chart';
|
||||
import { formatLocalDate } from '$lib/utils';
|
||||
import BillRecordsTable from './BillRecordsTable.svelte';
|
||||
|
||||
interface Props {
|
||||
@@ -96,7 +97,7 @@
|
||||
const day = d.getDay();
|
||||
const diff = d.getDate() - day + (day === 0 ? -6 : 1); // 调整到周一
|
||||
d.setDate(diff);
|
||||
return d.toISOString().split('T')[0];
|
||||
return formatLocalDate(d);
|
||||
}
|
||||
|
||||
// 获取月份标识
|
||||
@@ -526,7 +527,7 @@
|
||||
|
||||
// 点击图表任意位置都触发,选择最近的日期
|
||||
const clickedDate = data[closestIdx].date;
|
||||
const dateStr = clickedDate.toISOString().split('T')[0];
|
||||
const dateStr = formatLocalDate(clickedDate);
|
||||
|
||||
// 找出当天的所有支出记录
|
||||
selectedDate = clickedDate;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { untrack } from 'svelte';
|
||||
import { CalendarDate, type DateValue } from "@internationalized/date";
|
||||
import CalendarIcon from "@lucide/svelte/icons/calendar";
|
||||
import * as Popover from "$lib/components/ui/popover";
|
||||
@@ -29,12 +30,45 @@
|
||||
return `${date.year}-${String(date.month).padStart(2, '0')}-${String(date.day).padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
// 内部日期范围状态,使用 $derived 响应 props 变化
|
||||
let value: DateRange = $derived({
|
||||
// 内部日期范围状态
|
||||
let value: DateRange = $state({
|
||||
start: parseDate(startDate),
|
||||
end: parseDate(endDate)
|
||||
});
|
||||
|
||||
// 当 startDate 或 endDate 从外部变化时,同步更新 value
|
||||
$effect(() => {
|
||||
const newStart = parseDate(startDate);
|
||||
const newEnd = parseDate(endDate);
|
||||
|
||||
// 检查值是否真的变化了
|
||||
const currentStartStr = untrack(() => value.start ? formatDate(value.start) : '');
|
||||
const currentEndStr = untrack(() => value.end ? formatDate(value.end) : '');
|
||||
|
||||
if (currentStartStr !== startDate || currentEndStr !== endDate) {
|
||||
value = {
|
||||
start: newStart,
|
||||
end: newEnd
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// 当 value 变化时(用户通过日历选择),更新绑定的 startDate 和 endDate
|
||||
$effect(() => {
|
||||
const newStartDate = value.start ? formatDate(value.start) : '';
|
||||
const newEndDate = value.end ? formatDate(value.end) : '';
|
||||
|
||||
// 检查是否与当前值不同,避免循环更新
|
||||
if (newStartDate !== untrack(() => startDate) || newEndDate !== untrack(() => endDate)) {
|
||||
startDate = newStartDate;
|
||||
endDate = newEndDate;
|
||||
// 调用回调函数(只在有完整日期范围时)
|
||||
if (onchange && value.start && value.end) {
|
||||
onchange(newStartDate, newEndDate);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 格式化显示文本
|
||||
let displayText = $derived(() => {
|
||||
if (value.start && value.end) {
|
||||
@@ -45,13 +79,6 @@
|
||||
}
|
||||
return "选择日期范围";
|
||||
});
|
||||
|
||||
// 当日期变化时通知父组件
|
||||
function handleValueChange(newValue: DateRange) {
|
||||
if (newValue.start && newValue.end && onchange) {
|
||||
onchange(formatDate(newValue.start), formatDate(newValue.end));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Popover.Root>
|
||||
@@ -73,8 +100,7 @@
|
||||
</Popover.Trigger>
|
||||
<Popover.Content class="w-auto p-0" align="start">
|
||||
<RangeCalendar
|
||||
{value}
|
||||
onValueChange={handleValueChange}
|
||||
bind:value
|
||||
numberOfMonths={2}
|
||||
locale="zh-CN"
|
||||
weekStartsOn={1}
|
||||
|
||||
Reference in New Issue
Block a user