feat(export): 导出日期范围添加时间选择功能

为导出窗口的日期范围选择器添加了时间(HH:mm)选择功能:

- 在日期输入框下方添加了时间选择控件(type="time")
- 默认时间范围:开始 00:00,结束 23:59
- 支持精确到分钟的时间范围设置
- 预设类型(今天、昨天、最近7天等)默认使用 00:00-23:59
- 自定义时间范围保留用户设置的具体时间
- 添加了结束时间不能早于开始时间的验证

修改文件:
- src/utils/exportDateRange.ts - 支持 YYYY-MM-DD HH:mm 格式的解析和格式化
- src/components/Export/ExportDateRangeDialog.tsx - 添加时间选择 UI 和逻辑
- src/components/Export/ExportDateRangeDialog.scss - 时间输入框样式
- src/pages/ExportPage.tsx - 修复 preset 类型的默认时间不正确的 bug
This commit is contained in:
佘志高
2026-04-11 22:00:32 +08:00
parent 5bec4f3cd6
commit f2d6188c53
4 changed files with 279 additions and 73 deletions

View File

@@ -1105,21 +1105,42 @@ const clampExportSelectionToBounds = (
): ExportDateRangeSelection => {
if (!bounds) return cloneExportDateRangeSelection(selection)
const boundedStart = startOfDay(bounds.minDate)
const boundedEnd = endOfDay(bounds.maxDate)
const originalStart = selection.useAllTime ? boundedStart : startOfDay(selection.dateRange.start)
const originalEnd = selection.useAllTime ? boundedEnd : endOfDay(selection.dateRange.end)
const nextStart = new Date(Math.min(Math.max(originalStart.getTime(), boundedStart.getTime()), boundedEnd.getTime()))
const nextEndCandidate = new Date(Math.min(Math.max(originalEnd.getTime(), boundedStart.getTime()), boundedEnd.getTime()))
const nextEnd = nextEndCandidate.getTime() < nextStart.getTime() ? endOfDay(nextStart) : nextEndCandidate
const rangeChanged = nextStart.getTime() !== originalStart.getTime() || nextEnd.getTime() !== originalEnd.getTime()
// For custom selections, only ensure end >= start, preserve time precision
if (selection.preset === 'custom' && !selection.useAllTime) {
const { start, end } = selection.dateRange
if (end.getTime() < start.getTime()) {
return {
...selection,
dateRange: { start, end: start }
}
}
return cloneExportDateRangeSelection(selection)
}
// For useAllTime, use bounds directly
if (selection.useAllTime) {
return {
preset: selection.preset,
useAllTime: true,
dateRange: {
start: bounds.minDate,
end: bounds.maxDate
}
}
}
// For preset selections (not custom), clamp dates to bounds and use default times
const boundedStart = new Date(Math.min(Math.max(selection.dateRange.start.getTime(), bounds.minDate.getTime()), bounds.maxDate.getTime()))
const boundedEnd = new Date(Math.min(Math.max(selection.dateRange.end.getTime(), bounds.minDate.getTime()), bounds.maxDate.getTime()))
// Use default times: start at 00:00, end at 23:59:59
boundedStart.setHours(0, 0, 0, 0)
boundedEnd.setHours(23, 59, 59, 999)
return {
preset: selection.useAllTime ? selection.preset : (rangeChanged ? 'custom' : selection.preset),
useAllTime: selection.useAllTime,
preset: selection.preset,
useAllTime: false,
dateRange: {
start: nextStart,
end: nextEnd
start: boundedStart,
end: boundedEnd
}
}
}