diff --git a/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx b/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx
index 730481fe..7c07d681 100644
--- a/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx
+++ b/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx
@@ -1,4 +1,5 @@
import { Button, Card, Col, Form, Row, Select, Space, Spin, Table, Tag, Toast, Typography } from '@douyinfe/semi-ui';
+import { IconSearch } from '@douyinfe/semi-icons';
import { useEffect, useState } from 'react';
import { api } from '../api/client';
import type { DashboardSummary, LinkHealth, ProtocolStat, QualityIssueRow, ServiceStatusStat, VehicleCoverageRow, VehicleRealtimeRow } from '../api/types';
@@ -108,7 +109,19 @@ export function Dashboard({ onOpenVehicle, onOpenQuality }: { onOpenVehicle: (vi
title: '状态',
render: (_: unknown, row: ServiceStatusStat) => {row.title}
},
- { title: '车辆数', dataIndex: 'count' }
+ { title: '车辆数', dataIndex: 'count' },
+ {
+ title: '操作',
+ width: 90,
+ render: (_: unknown, row: ServiceStatusStat) => (
+ }
+ size="small"
+ onClick={() => loadCoverage({ serviceStatus: row.status })}
+ />
+ )
+ }
]}
/>
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 c3ff78a7..479973b1 100644
--- a/vehicle-data-platform/apps/web/src/test/App.test.tsx
+++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx
@@ -217,6 +217,50 @@ test('filters dashboard coverage by service status', async () => {
});
});
+test('opens dashboard coverage from service status distribution', async () => {
+ window.history.replaceState(null, '', '/#/dashboard');
+ const fetchMock = vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => {
+ const path = String(input);
+ if (path.includes('/api/dashboard/summary')) {
+ return {
+ ok: true,
+ json: async () => ({
+ data: {
+ onlineVehicles: 3,
+ activeToday: 4,
+ frameToday: 1286320,
+ issueVehicles: 7,
+ kafkaLag: 0,
+ protocols: [],
+ serviceStatuses: [
+ { status: 'degraded', title: '部分来源离线', count: 39 }
+ ],
+ linkHealth: []
+ },
+ traceId: 'trace-test',
+ timestamp: 1783094400000
+ })
+ } as Response;
+ }
+ return {
+ ok: true,
+ json: async () => ({
+ data: { items: [], total: 0, limit: 8, offset: 0 },
+ traceId: 'trace-test',
+ timestamp: 1783094400000
+ })
+ } as Response;
+ });
+
+ render();
+
+ fireEvent.click(await screen.findByRole('button', { name: '查看部分来源离线' }));
+
+ await waitFor(() => {
+ expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('serviceStatus=degraded'), undefined);
+ });
+});
+
test('opens vehicle detail from shareable hash', async () => {
window.history.replaceState(null, '', '/#/detail?keyword=%E7%B2%A4AG18312');
vi.spyOn(globalThis, 'fetch').mockResolvedValue({