From 003a0b580cb7d776cec775e9bfc3770cbf7ba7c7 Mon Sep 17 00:00:00 2001 From: kkfluous Date: Fri, 7 Aug 2026 17:07:29 +0800 Subject: [PATCH] feat: focus ETC metric drilldowns --- src/modules/energy/ETCDetails.tsx | 6 +++- src/modules/energy/ETCView.tsx | 54 ++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/modules/energy/ETCDetails.tsx b/src/modules/energy/ETCDetails.tsx index 2796931..df7857f 100644 --- a/src/modules/energy/ETCDetails.tsx +++ b/src/modules/energy/ETCDetails.tsx @@ -89,7 +89,11 @@ export default function ETCDetails({ }; return ( -
+
diff --git a/src/modules/energy/ETCView.tsx b/src/modules/energy/ETCView.tsx index f0fa971..47ef5b3 100644 --- a/src/modules/energy/ETCView.tsx +++ b/src/modules/energy/ETCView.tsx @@ -1,4 +1,5 @@ import { useCallback, useEffect, useState } from 'react'; +import type { ReactNode } from 'react'; import { CircleCheck, CircleX, Clock3, Database, ReceiptText, RefreshCw, Route, Truck } from 'lucide-react'; import { fetchEtcOverview } from './api'; import type { EtcOverviewResponse } from './types'; @@ -23,6 +24,31 @@ function syncStatusLabel(status: EtcOverviewResponse['integration']['lastSyncSta return '状态未知'; } +function DrilldownMetricButton({ + label, + title, + onClick, + children, +}: { + label: string; + title: string; + onClick: () => void; + children: ReactNode; +}) { + return ( + + ); +} + export default function ETCView() { const [data, setData] = useState(null); const [error, setError] = useState(null); @@ -47,6 +73,18 @@ export default function ETCView() { ); }, [commitDetailContext, detailContext]); + const openDetailView = useCallback((next: EtcDetailView) => { + selectDetailView(next); + window.requestAnimationFrame(() => { + const details = document.getElementById('etc-details'); + details?.focus({ preventScroll: true }); + details?.scrollIntoView({ + behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth', + block: 'start', + }); + }); + }, [selectDetailView]); + useEffect(() => { const handlePopState = () => setDetailContext(parseEtcDrillContext(window.location.search)); window.addEventListener('popstate', handlePopState); @@ -104,10 +142,18 @@ export default function ETCView() {
- - - - + openDetailView('records')}> + + + openDetailView('records')}> + + + openDetailView('records')}> + + + openDetailView('bills')}> + +