diff --git a/src/modules/mileage/DailyReportView.tsx b/src/modules/mileage/DailyReportView.tsx index 9da7f24..89a6846 100644 --- a/src/modules/mileage/DailyReportView.tsx +++ b/src/modules/mileage/DailyReportView.tsx @@ -83,12 +83,132 @@ function dateShift(date: string, days: number): string { return value.toISOString().slice(0, 10); } +function monthShift(month: string, months: number): string { + const value = new Date(`${month}-01T00:00:00Z`); + value.setUTCMonth(value.getUTCMonth() + months); + return value.toISOString().slice(0, 7); +} + +function reportDateLabel(value: string): string { + const date = new Date(`${value}T00:00:00Z`); + return new Intl.DateTimeFormat('zh-CN', { + timeZone: 'UTC', + year: 'numeric', + month: 'long', + day: 'numeric', + weekday: 'short', + }).format(date).replace(/日(?=周)/, '日 '); +} + function initialReportDate(): string { const params = new URLSearchParams(window.location.search); const value = params.get('mileageReportDate'); return /^\d{4}-\d{2}-\d{2}$/.test(value || '') ? value! : shanghaiYmd(-1); } +function ReportDatePicker({ + value, + maxDate, + onChange, +}: { + value: string; + maxDate: string; + onChange: (date: string) => void; +}) { + const [open, setOpen] = useState(false); + const [month, setMonth] = useState(value.slice(0, 7)); + const monthStart = new Date(`${month}-01T00:00:00Z`); + const firstGridDate = new Date(monthStart); + firstGridDate.setUTCDate(1 - monthStart.getUTCDay()); + const days = Array.from({ length: 42 }, (_, index) => { + const date = new Date(firstGridDate); + date.setUTCDate(firstGridDate.getUTCDate() + index); + return date; + }); + const weekdayLabels = ['日', '一', '二', '三', '四', '五', '六']; + const monthLabel = new Intl.DateTimeFormat('zh-CN', { + timeZone: 'UTC', + year: 'numeric', + month: 'long', + }).format(monthStart); + + return ( +
+ + + {open ? ( +
+
+ +
{monthLabel}
+ +
+
+ {weekdayLabels.map(day => {day})} + {days.map(date => { + const dateValue = date.toISOString().slice(0, 10); + const inMonth = dateValue.slice(0, 7) === month; + const selected = dateValue === value; + const disabled = dateValue > maxDate; + return ( + + ); + })} +
+
+ ) : null} +
+ ); +} + function updateReportDateInUrl(date: string): void { const url = new URL(window.location.href); url.searchParams.set('mileageReportDate', date); @@ -711,7 +831,7 @@ function roundMileageForDisplay(value: number): number { } export default function DailyReportView() { - const maxDate = shanghaiYmd(-1); + const maxDate = shanghaiYmd(); const [selectedDate, setSelectedDate] = useState(initialReportDate); const [report, setReport] = useState(null); const [loading, setLoading] = useState(true); @@ -777,10 +897,12 @@ export default function DailyReportView() {

{fmtDate(report.reportDate)} · {report.source === 'XLSX_IMPORT' ? '人工台账归档' - : `仪表数据更新至 ${fmtDateTime(report.sourceUpdatedAt)}`} + : report.status === 'ARCHIVED' + ? `归档于 ${fmtDateTime(report.generatedAt)}` + : `仪表数据更新至 ${fmtDateTime(report.sourceUpdatedAt)}`}

- 统计口径:每天 00:30 自动汇总前一日里程 + 统计周期:自然日 · 汇总频率:每日 00:30 汇总前一日里程

@@ -794,17 +916,16 @@ export default function DailyReportView() { > - + +