diff --git a/src/modules/mileage/DailyReportView.tsx b/src/modules/mileage/DailyReportView.tsx index 89a6846..a9a4f1d 100644 --- a/src/modules/mileage/DailyReportView.tsx +++ b/src/modules/mileage/DailyReportView.tsx @@ -41,7 +41,6 @@ import { import Blur from '../../components/Blur'; import { ErrorState, - LoadingState, MetricTile, SurfaceCard, } from '../../components/ui/surface'; @@ -57,6 +56,7 @@ type VehicleSortKey = 'dailyMileage' | 'sevenDayMileage' | 'completionRate'; type SortDirection = 'asc' | 'desc'; const VEHICLE_PAGE_SIZE = 20; +const MIN_REPORT_LOADING_MS = 280; const VEHICLE_FILTERS: { id: VehicleFilter; label: string }[] = [ { id: 'ALL', label: '全部' }, @@ -209,6 +209,48 @@ function ReportDatePicker({ ); } +function DailyReportLoadingOverlay({ reportDate }: { reportDate: string }) { + return ( + + + + + + + + + 正在加载日报 + 正在汇总 {fmtDate(reportDate)} 的里程数据 + + + + + + ); +} + function updateReportDateInUrl(date: string): void { const url = new URL(window.location.href); url.searchParams.set('mileageReportDate', date); @@ -831,7 +873,7 @@ function roundMileageForDisplay(value: number): number { } export default function DailyReportView() { - const maxDate = shanghaiYmd(); + const maxDate = shanghaiYmd(-1); const [selectedDate, setSelectedDate] = useState(initialReportDate); const [report, setReport] = useState(null); const [loading, setLoading] = useState(true); @@ -841,6 +883,8 @@ export default function DailyReportView() { useEffect(() => { let active = true; + let finishTimer: number | undefined; + const loadingStartedAt = performance.now(); setLoading(true); setError(''); updateReportDateInUrl(selectedDate); @@ -855,8 +899,17 @@ export default function DailyReportView() { if (!active) return; setError(cause instanceof Error ? cause.message : '日报加载失败'); }) - .finally(() => { if (active) setLoading(false); }); - return () => { active = false; }; + .finally(() => { + if (!active) return; + const delay = Math.max(0, MIN_REPORT_LOADING_MS - (performance.now() - loadingStartedAt)); + finishTimer = window.setTimeout(() => { + if (active) setLoading(false); + }, delay); + }); + return () => { + active = false; + if (finishTimer != null) window.clearTimeout(finishTimer); + }; }, [selectedDate]); const highMileageRate = report && report.totals.operatingCount > 0 @@ -871,7 +924,7 @@ export default function DailyReportView() { note => note.message !== '日行驶总里程延续人工汇报口径,包含库存车辆产生的里程。', ) || []; - if (loading && !report) return ; + if (loading && !report) return ; if (!report) return ; const trendGroup = trendTargetId == null ? null : report.groups.find(group => group.targetId === trendTargetId) || null; @@ -881,7 +934,7 @@ export default function DailyReportView() { const trendColor = trendGroup ? '#0f766e' : '#2563eb'; return ( - + @@ -917,15 +970,6 @@ export default function DailyReportView() { - setSelectedDate(maxDate)} - disabled={selectedDate === maxDate} - className="flex h-9 shrink-0 items-center justify-center rounded-lg border border-slate-200 bg-white px-2.5 text-[11px] font-black text-blue-600 hover:border-blue-200 hover:bg-blue-50 disabled:cursor-not-allowed disabled:opacity-35" - title="回到今天" - > - 今天 - setSelectedDate(dateShift(selectedDate, 1))} @@ -1139,11 +1183,9 @@ export default function DailyReportView() { ))} - {loading ? ( - - 正在切换日报 - - ) : null} + + {loading ? : null} + {error ? : null} );