From ba1e0e9f16fefeabc9c0f391c8da768e9f22ced1 Mon Sep 17 00:00:00 2001 From: kkfluous Date: Fri, 17 Apr 2026 09:25:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(scheduling):=20add=20=E8=BF=91=E6=9C=9F?= =?UTF-8?q?=E5=B7=B2=E5=B9=B2=E9=A2=84=20summary=20card=20(last=207=20days?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore 替换建议 card and add a new emerald 近期已干预 card. Clicking opens the history modal pre-filtered to the last 7 days (excluding cancelled) via a toggle chip users can switch off. Co-Authored-By: Claude Opus 4.7 --- .../scheduling/NotificationHistory.tsx | 33 ++++++++++++++++--- src/modules/scheduling/SchedulingModule.tsx | 30 ++++++++++++++--- src/server/routes/scheduling/algorithm.ts | 1 + src/server/routes/scheduling/notify.ts | 12 +++++++ src/server/routes/scheduling/suggestions.ts | 6 ++-- src/shared/scheduling/types.ts | 2 ++ 6 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/modules/scheduling/NotificationHistory.tsx b/src/modules/scheduling/NotificationHistory.tsx index e1bd56a..34c8e6f 100644 --- a/src/modules/scheduling/NotificationHistory.tsx +++ b/src/modules/scheduling/NotificationHistory.tsx @@ -8,8 +8,12 @@ import Blur from '../../components/Blur'; interface Props { onClose: () => void; onChange?: () => void; + /** When true, pre-filter to the last 7 days (excluding cancelled). */ + recentOnly?: boolean; } +const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000; + type StatusTab = 'all' | NotificationStatus; const STATUS_TABS: { key: StatusTab; label: string }[] = [ @@ -36,15 +40,23 @@ function fmtDateTime(iso: string): string { return `${y}-${m}-${day} ${hh}:${mm}`; } -export default function NotificationHistory({ onClose, onChange }: Props) { +export default function NotificationHistory({ onClose, onChange, recentOnly = false }: Props) { const [records, setRecords] = useState([]); const [loading, setLoading] = useState(false); const [tab, setTab] = useState('all'); + const [recent7d, setRecent7d] = useState(recentOnly); const [mutatingId, setMutatingId] = useState(null); const [executeTarget, setExecuteTarget] = useState(null); const [afterMileageInput, setAfterMileageInput] = useState(''); const [notesInput, setNotesInput] = useState(''); + const visibleRecords = recent7d + ? records.filter(r => { + const t = Date.parse(r.createdAt); + return Number.isFinite(t) && Date.now() - t <= SEVEN_DAYS_MS && r.status !== 'cancelled'; + }) + : records; + const load = useCallback(async () => { setLoading(true); try { @@ -117,7 +129,7 @@ export default function NotificationHistory({ onClose, onChange }: Props) { {/* Status tabs */} -
+
{STATUS_TABS.map(t => ( +
{/* Body */} @@ -137,14 +160,14 @@ export default function NotificationHistory({ onClose, onChange }: Props) {
加载中
- ) : records.length === 0 ? ( + ) : visibleRecords.length === 0 ? (
-

暂无记录

+

{recent7d ? '最近 7 天暂无干预记录' : '暂无记录'}

) : (
- {records.map(rec => { + {visibleRecords.map(rec => { const badge = statusBadge(rec.status); const busy = mutatingId === rec.id; return ( diff --git a/src/modules/scheduling/SchedulingModule.tsx b/src/modules/scheduling/SchedulingModule.tsx index 94c444e..bc5de46 100644 --- a/src/modules/scheduling/SchedulingModule.tsx +++ b/src/modules/scheduling/SchedulingModule.tsx @@ -171,6 +171,7 @@ export default function SchedulingModule() { const [batchInFlight, setBatchInFlight] = useState(false); const [batchResultMsg, setBatchResultMsg] = useState(null); const [showHistory, setShowHistory] = useState(false); + const [historyRecentOnly, setHistoryRecentOnly] = useState(false); const loadData = useCallback(async () => { setLoading(true); @@ -277,7 +278,7 @@ export default function SchedulingModule() {
{/* ===== Summary Cards ===== */} -
+
{/* 里程高·换下 — warm orange */} + + {/* 近期已干预 — emerald */} +
{/* ===== List Card ===== */} @@ -363,7 +381,7 @@ export default function SchedulingModule() {