feat(platform): label source evidence

This commit is contained in:
lingniu
2026-07-04 04:15:42 +08:00
parent e077d99a5e
commit 0b53abf63d
4 changed files with 21 additions and 7 deletions

View File

@@ -51,6 +51,10 @@ function rowServiceStatus(row: { serviceStatus?: { title: string; severity: stri
return { label: '服务正常', color: 'green' as const };
}
function sourceEvidenceText(row: { onlineSourceCount: number; sourceCount: number }) {
return `${row.onlineSourceCount}/${row.sourceCount} 来源在线`;
}
export function Dashboard({ onOpenVehicle, onOpenQuality, onOpenVehicles }: { onOpenVehicle: (vin: string) => void; onOpenQuality: () => void; onOpenVehicles: (filters?: Record<string, string>) => void }) {
const [summary, setSummary] = useState<DashboardSummary | null>(null);
const [serviceSummary, setServiceSummary] = useState<VehicleServiceSummary | null>(null);
@@ -250,7 +254,7 @@ export function Dashboard({ onOpenVehicle, onOpenQuality, onOpenVehicles }: { on
{ title: '车牌', dataIndex: 'plate', width: 110 },
{ title: 'VIN', dataIndex: 'vin', width: 190 },
{
title: '来源',
title: '来源证据',
width: 240,
render: (_: unknown, row: VehicleCoverageRow) => (
<Space spacing={4} wrap>
@@ -259,9 +263,9 @@ export function Dashboard({ onOpenVehicle, onOpenQuality, onOpenVehicles }: { on
)
},
{
title: '覆盖',
width: 110,
render: (_: unknown, row: VehicleCoverageRow) => `${row.onlineSourceCount}/${row.sourceCount}`
title: '证据覆盖',
width: 130,
render: (_: unknown, row: VehicleCoverageRow) => sourceEvidenceText(row)
},
{
title: '服务状态',
@@ -303,7 +307,7 @@ export function Dashboard({ onOpenVehicle, onOpenQuality, onOpenVehicles }: { on
{ title: '车牌', dataIndex: 'plate' },
{ title: 'VIN', dataIndex: 'vin' },
{
title: '来源',
title: '来源证据',
render: (_: unknown, row: VehicleRealtimeRow) => (
<Space spacing={4} wrap>
{row.protocols.map((protocol) => <Tag key={protocol} color={protocol === row.primaryProtocol ? 'blue' : 'grey'}>{protocol}</Tag>)}

View File

@@ -28,6 +28,10 @@ function vehicleServiceStatus(row: VehicleCoverageRow) {
return { label: '服务正常', color: 'green' as const };
}
function sourceEvidenceText(row: VehicleCoverageRow) {
return `${row.onlineSourceCount}/${row.sourceCount} 来源在线`;
}
export function Vehicles({
onOpenVehicle,
onFiltersChange,
@@ -100,7 +104,7 @@ export function Vehicles({
}
},
{
title: '来源',
title: '来源证据',
width: 240,
render: (_: unknown, row: VehicleCoverageRow) => (
<Space spacing={4} wrap>
@@ -108,7 +112,7 @@ export function Vehicles({
</Space>
)
},
{ title: '覆盖', width: 90, render: (_: unknown, row: VehicleCoverageRow) => `${row.onlineSourceCount}/${row.sourceCount}` },
{ title: '证据覆盖', width: 120, render: (_: unknown, row: VehicleCoverageRow) => sourceEvidenceText(row) },
{ title: '在线', width: 90, render: (_: unknown, row: VehicleCoverageRow) => <StatusTag status={row.online ? 'ok' : 'offline'} /> },
{ title: '最后在线', dataIndex: 'lastSeen', width: 170 },
{ title: '绑定', width: 90, render: (_: unknown, row: VehicleCoverageRow) => <Tag color={row.bindingStatus === 'bound' ? 'green' : 'orange'}>{row.bindingStatus === 'bound' ? '已绑定' : '未绑定'}</Tag> },

View File

@@ -260,6 +260,8 @@ test('shows vehicle service result summary on vehicle list filters', async () =>
expect(screen.getByText('在线车辆')).toBeInTheDocument();
expect(screen.getByText('待绑定')).toBeInTheDocument();
expect(screen.getByText('VIN-MULTI-001')).toBeInTheDocument();
expect(screen.getAllByText('来源证据').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('1/2 来源在线')).toBeInTheDocument();
});
test('filters vehicle list from result summary actions', async () => {
@@ -551,6 +553,8 @@ test('shows row service status in dashboard vehicle previews', async () => {
render(<App />);
expect(await screen.findByText('VIN-COVERAGE-WARN')).toBeInTheDocument();
expect(screen.getAllByText('来源证据').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('1/2 来源在线').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('覆盖部分离线')).toBeInTheDocument();
expect(screen.getByText('VIN-REALTIME-OFFLINE')).toBeInTheDocument();
expect(screen.getByText('实时车辆离线')).toBeInTheDocument();

View File

@@ -24,6 +24,8 @@ Vehicle lists should expose a vehicle-level service status derived from binding
Vehicle detail and top search context should expose one source-consistency conclusion, such as `来源一致`, `部分来源离线`, or `里程差异偏大`. This diagnosis comes from `sourceConsistency` and turns GB32960, JT808, and Yutong MQTT into explainable evidence under one vehicle service rather than three competing realtime products.
Vehicle service lists and dashboard previews should label protocol coverage as `来源证据`. The row should make the vehicle service coverage explicit, for example `2/3 来源在线`, while protocol tags remain compact evidence labels underneath the same vehicle row.
## Interaction Rules
- Tables are the default data surface.