diff --git a/vehicle-data-platform/apps/web/src/App.tsx b/vehicle-data-platform/apps/web/src/App.tsx index 4a6440f0..c12f0809 100644 --- a/vehicle-data-platform/apps/web/src/App.tsx +++ b/vehicle-data-platform/apps/web/src/App.tsx @@ -31,12 +31,17 @@ export default function App() { const [currentVehicleLabel, setCurrentVehicleLabel] = useState(''); const [currentVehicleConsistency, setCurrentVehicleConsistency] = useState(); - const loadVehicleContext = useCallback(async (keyword: string) => { + const loadVehicleContext = useCallback(async (keyword: string, protocol?: string) => { const lookupKey = keyword.trim(); if (!lookupKey) { return undefined; } - const overview = await api.vehicleServiceOverview(new URLSearchParams({ keyword: lookupKey })); + const params = new URLSearchParams({ keyword: lookupKey }); + const source = protocol?.trim(); + if (source) { + params.set('protocol', source); + } + const overview = await api.vehicleServiceOverview(params); const nextKey = overview.vin || lookupKey; const resolved = Boolean(overview.vin); setCurrentVehicleStatus(overview.serviceStatus ?? serviceStatusFromOverview(overview)); @@ -62,7 +67,7 @@ export default function App() { if (initialRoute.page !== 'detail' || !initialRoute.keyword) { return; } - loadVehicleContext(initialRoute.keyword).catch((error) => { + loadVehicleContext(initialRoute.keyword, initialRoute.protocol).catch((error) => { Toast.error(error instanceof Error ? error.message : '车辆查询失败'); }); }, [initialRoute.keyword, initialRoute.page, loadVehicleContext]); @@ -169,7 +174,7 @@ export default function App() { return; } try { - const context = await loadVehicleContext(lookupKey); + const context = await loadVehicleContext(lookupKey, nextProtocol); const resolved = context?.resolved; const nextKey = context?.nextKey ?? lookupKey; setActiveVin(nextKey); 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 4ee06974..6e0cfdf1 100644 --- a/vehicle-data-platform/apps/web/src/test/App.test.tsx +++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx @@ -2195,7 +2195,7 @@ test('opens current vehicle service from history header with current source evid test('opens vehicle service from realtime vehicles with primary source evidence', async () => { window.history.replaceState(null, '', '/#/realtime'); - vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { + const fetchMock = vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => { const path = String(input); if (path.includes('/api/realtime/vehicles')) { return { @@ -2228,20 +2228,22 @@ test('opens vehicle service from realtime vehicles with primary source evidence' }) } as Response; } - if (path.includes('/api/vehicles/resolve')) { + if (path.includes('/api/vehicle-service/overview')) { return { ok: true, json: async () => ({ data: { - lookupKey: 'VIN-MQTT-001', - resolved: true, vin: 'VIN-MQTT-001', plate: '川AHTWO1', - phone: '', - oem: '宇通', - protocols: ['GB32960', 'YUTONG_MQTT'], - online: true, - lastSeen: '2026-07-03 20:12:10' + sourceCount: 2, + onlineSourceCount: 1, + coverageStatus: 'online', + primaryProtocol: 'YUTONG_MQTT', + lastSeen: '2026-07-03 20:12:10', + historyCount: 0, + rawCount: 0, + mileageCount: 0, + qualityIssueCount: 0 }, traceId: 'trace-test', timestamp: 1783094400000 @@ -2266,6 +2268,7 @@ test('opens vehicle service from realtime vehicles with primary source evidence' await waitFor(() => { expect(window.location.hash).toBe('#/detail?keyword=VIN-MQTT-001&protocol=YUTONG_MQTT'); }); + expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('/api/vehicle-service/overview?keyword=VIN-MQTT-001&protocol=YUTONG_MQTT'), undefined); }); test('shows canonical service status in realtime vehicles', async () => {