From dc3e12328e4d12eb6ddfbaadcc92568bf9616372 Mon Sep 17 00:00:00 2001 From: lingniu Date: Sat, 4 Jul 2026 01:35:15 +0800 Subject: [PATCH] feat(platform-web): link analysis pages to vehicle service --- .../apps/web/src/components/PageHeader.tsx | 16 ++++--- .../apps/web/src/pages/History.tsx | 12 ++++- .../apps/web/src/pages/Mileage.tsx | 12 ++++- .../apps/web/src/styles/global.css | 14 ++++++ .../apps/web/src/test/App.test.tsx | 45 +++++++++++++++++++ 5 files changed, 91 insertions(+), 8 deletions(-) diff --git a/vehicle-data-platform/apps/web/src/components/PageHeader.tsx b/vehicle-data-platform/apps/web/src/components/PageHeader.tsx index 8b58550e..e76bdf69 100644 --- a/vehicle-data-platform/apps/web/src/components/PageHeader.tsx +++ b/vehicle-data-platform/apps/web/src/components/PageHeader.tsx @@ -1,12 +1,16 @@ import { Typography } from '@douyinfe/semi-ui'; +import type { ReactNode } from 'react'; -export function PageHeader({ title, description }: { title: string; description: string }) { +export function PageHeader({ title, description, actions }: { title: string; description: string; actions?: ReactNode }) { return ( -
- - {title} - - {description} +
+
+ + {title} + + {description} +
+ {actions ?
{actions}
: null}
); } diff --git a/vehicle-data-platform/apps/web/src/pages/History.tsx b/vehicle-data-platform/apps/web/src/pages/History.tsx index 8cbf6013..051634d3 100644 --- a/vehicle-data-platform/apps/web/src/pages/History.tsx +++ b/vehicle-data-platform/apps/web/src/pages/History.tsx @@ -118,10 +118,20 @@ export function History({ initialVin, initialProtocol, onOpenVehicle }: { initia }, [initialVin, initialProtocol]); const rawFieldCount = useMemo(() => Object.keys(selectedRaw?.parsedFields ?? {}).length, [selectedRaw]); + const currentVehicleKeyword = filters.keyword?.trim() ?? ''; + const currentProtocol = filters.protocol?.trim() ?? ''; return (
- + onOpenVehicle(currentVehicleKeyword, currentProtocol)}> + 当前车辆服务 + + )} + />
submit(values)}> diff --git a/vehicle-data-platform/apps/web/src/pages/Mileage.tsx b/vehicle-data-platform/apps/web/src/pages/Mileage.tsx index 39d3bf4b..34e8a0ba 100644 --- a/vehicle-data-platform/apps/web/src/pages/Mileage.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Mileage.tsx @@ -39,6 +39,8 @@ export function Mileage({ initialVin, initialProtocol, onOpenVehicle }: { initia const [summaryLoading, setSummaryLoading] = useState(true); const [filters, setFilters] = useState>({ keyword: initialVin, protocol: initialProtocol ?? '' }); const [pagination, setPagination] = useState({ currentPage: 1, pageSize: 20, total: 0 }); + const currentVehicleKeyword = filters.keyword?.trim() ?? ''; + const currentProtocol = filters.protocol?.trim() ?? ''; const loadSummary = (values: Record = filters) => { setSummaryLoading(true); @@ -68,7 +70,15 @@ export function Mileage({ initialVin, initialProtocol, onOpenVehicle }: { initia return (
- + onOpenVehicle(currentVehicleKeyword, currentProtocol)}> + 当前车辆服务 + + )} + /> { const nextFilters = values as Record; diff --git a/vehicle-data-platform/apps/web/src/styles/global.css b/vehicle-data-platform/apps/web/src/styles/global.css index ce1fba77..8ec40d5a 100644 --- a/vehicle-data-platform/apps/web/src/styles/global.css +++ b/vehicle-data-platform/apps/web/src/styles/global.css @@ -84,6 +84,20 @@ body { padding: var(--vp-page-gutter); } +.vp-page-header { + min-height: 54px; + margin-bottom: 16px; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; +} + +.vp-page-header-actions { + flex: 0 0 auto; + padding-top: 2px; +} + .vp-section { background: var(--vp-surface); border: 1px solid var(--vp-border); diff --git a/vehicle-data-platform/apps/web/src/test/App.test.tsx b/vehicle-data-platform/apps/web/src/test/App.test.tsx index f259f563..c108a7bc 100644 --- a/vehicle-data-platform/apps/web/src/test/App.test.tsx +++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx @@ -398,3 +398,48 @@ test('opens history with the currently selected vehicle detail source', async () expect(window.location.hash).toBe('#/history?keyword=VIN001&protocol=JT808'); }); }); + +test('opens vehicle service from an empty history query with the current filters', async () => { + window.history.replaceState(null, '', '/#/history?keyword=VIN404&protocol=JT808'); + vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { + const path = String(input); + if (path.includes('/api/vehicles/resolve')) { + return { + ok: true, + json: async () => ({ + data: { + lookupKey: 'VIN404', + resolved: true, + vin: 'VIN404', + plate: '', + phone: '', + oem: '', + protocols: ['JT808'], + online: false, + lastSeen: '' + }, + traceId: 'trace-test', + timestamp: 1783094400000 + }) + } as Response; + } + return { + ok: true, + json: async () => ({ + data: path.includes('/api/ops/health') + ? { linkHealth: [], kafkaLag: 0, redisOnlineKeys: 0, tdengineWritable: true, mysqlWritable: true, runtime: { requestTimeoutMs: 5000 } } + : { items: [], total: 0, limit: 10, offset: 0 }, + traceId: 'trace-test', + timestamp: 1783094400000 + }) + } as Response; + }); + + render(); + + fireEvent.click(await screen.findByRole('button', { name: '当前车辆服务' })); + + await waitFor(() => { + expect(window.location.hash).toBe('#/detail?keyword=VIN404&protocol=JT808'); + }); +});