From 8dbf91ca25eb86df062c7df4c5b582d098607143 Mon Sep 17 00:00:00 2001 From: lingniu Date: Sat, 4 Jul 2026 12:18:06 +0800 Subject: [PATCH] feat(platform): link raw frames to mileage evidence --- .../apps/web/src/pages/History.tsx | 14 ++- .../apps/web/src/test/App.test.tsx | 104 ++++++++++++++++++ 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/vehicle-data-platform/apps/web/src/pages/History.tsx b/vehicle-data-platform/apps/web/src/pages/History.tsx index 9d21e531..e1a25399 100644 --- a/vehicle-data-platform/apps/web/src/pages/History.tsx +++ b/vehicle-data-platform/apps/web/src/pages/History.tsx @@ -294,6 +294,15 @@ export function History({ ...(day ? { dateFrom: day, dateTo: nextDate(day) } : {}) }); }; + const openRawMileage = (row: RawFrameRow) => { + if (!canOpenVehicle(row.vin)) return; + const day = dateOnly(row.deviceTime || row.serverTime); + onOpenMileage?.({ + keyword: row.vin, + protocol: row.protocol, + ...(day ? { dateFrom: day, dateTo: nextDate(day) } : {}) + }); + }; return (
@@ -500,10 +509,11 @@ export function History({ { title: '入库时间', dataIndex: 'serverTime', width: 190 }, { title: '操作', - width: 200, + width: 280, render: (_: unknown, row: RawFrameRow) => ( - + + ) 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 8c01d9d2..cb93bb06 100644 --- a/vehicle-data-platform/apps/web/src/test/App.test.tsx +++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx @@ -4673,6 +4673,110 @@ test('opens vehicle service from raw history rows with row source evidence', asy }); }); +test('opens same-day mileage statistics from raw history row', async () => { + window.history.replaceState(null, '', '/#/history?keyword=VIN-RAW-MILEAGE&protocol=JT808&tab=raw'); + vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { + const path = String(input); + if (path.includes('/api/ops/health')) { + return { + ok: true, + json: async () => ({ + data: { linkHealth: [], kafkaLag: 0, redisOnlineKeys: 0, tdengineWritable: true, mysqlWritable: true, runtime: { requestTimeoutMs: 5000 } }, + traceId: 'trace-test', + timestamp: 1783094400000 + }) + } as Response; + } + if (path.includes('/api/history/locations')) { + return { + ok: true, + json: async () => ({ + data: { items: [], total: 0, limit: 10, offset: 0 }, + traceId: 'trace-test', + timestamp: 1783094400000 + }) + } as Response; + } + if (path.includes('/api/history/raw-frames/query')) { + return { + ok: true, + json: async () => ({ + data: { + items: [{ + id: 'raw-jt808-mileage-001', + vin: 'VIN-RAW-MILEAGE', + plate: '粤ARAW里', + protocol: 'JT808', + frameType: '0x0200', + deviceTime: '2026-07-03 20:12:10', + serverTime: '2026-07-03 20:12:11', + rawSizeBytes: 128, + parsedFields: { 'jt808.location.total_mileage_km': 218.8 } + }], + total: 1, + limit: 10, + offset: 0 + }, + traceId: 'trace-test', + timestamp: 1783094400000 + }) + } as Response; + } + if (path.includes('/api/mileage/summary')) { + return { + ok: true, + json: async () => ({ + data: { vehicleCount: 1, recordCount: 1, sourceCount: 1, totalMileageKm: 18.8, averageMileagePerVin: 18.8 }, + traceId: 'trace-test', + timestamp: 1783094400000 + }) + } as Response; + } + if (path.includes('/api/mileage/daily')) { + return { + ok: true, + json: async () => ({ + data: { + items: [{ + vin: 'VIN-RAW-MILEAGE', + plate: '粤ARAW里', + source: 'JT808', + date: '2026-07-03', + startMileageKm: 200, + endMileageKm: 218.8, + dailyMileageKm: 18.8, + anomalySeverity: '' + }], + total: 1, + limit: 20, + offset: 0 + }, + traceId: 'trace-test', + timestamp: 1783094400000 + }) + } as Response; + } + return { + ok: true, + json: async () => ({ + data: { items: [], total: 0, limit: 10, offset: 0 }, + traceId: 'trace-test', + timestamp: 1783094400000 + }) + } as Response; + }); + + render(); + + expect(await screen.findByText('raw-jt808-mileage-001')).toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: '核对里程' })); + + await waitFor(() => { + expect(window.location.hash).toBe('#/mileage?keyword=VIN-RAW-MILEAGE&protocol=JT808&dateFrom=2026-07-03&dateTo=2026-07-04'); + }); + expect(await screen.findByRole('heading', { name: '里程统计' })).toBeInTheDocument(); +}); + test('opens current vehicle service from history header with current source evidence', async () => { window.history.replaceState(null, '', '/#/history?keyword=VIN-JT808-HEADER&protocol=JT808'); vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => {