feat(platform): show realtime coverage metrics

This commit is contained in:
lingniu
2026-07-04 14:53:35 +08:00
parent 10c598e013
commit df37277717
2 changed files with 31 additions and 0 deletions

View File

@@ -36,6 +36,10 @@ function sourceEvidenceText(row: VehicleRealtimeRow) {
return `${row.onlineSourceCount}/${row.sourceCount} 来源在线`;
}
function formatPercent(value: number) {
return Number.isFinite(value) ? `${value.toLocaleString(undefined, { maximumFractionDigits: 1 })}%` : '0%';
}
function serviceStatusWeight(row: VehicleRealtimeRow) {
const severity = row.serviceStatus?.severity;
if (severity === 'error') return 4;
@@ -233,6 +237,10 @@ export function Realtime({
const onlineCount = rows.filter((row) => row.online).length;
const locatedCount = rows.filter(isValidCoordinate).length;
const degradedCount = rows.filter((row) => row.onlineSourceCount < row.sourceCount).length;
const onlineRate = rows.length > 0 ? (onlineCount / rows.length) * 100 : 0;
const locatedRate = rows.length > 0 ? (locatedCount / rows.length) * 100 : 0;
const degradedRate = rows.length > 0 ? (degradedCount / rows.length) * 100 : 0;
const pageCoverageRate = pagination.total > 0 ? (rows.length / pagination.total) * 100 : 0;
const primaryProtocols = new Set(rows.map((row) => row.primaryProtocol).filter(Boolean));
const sourceIssueRows = rows
.filter((row) => canOpenVehicle(row.vin) && hasSourceIssue(row))
@@ -417,6 +425,22 @@ export function Realtime({
</div>
</div>
</div>
<Card bordered title="实时覆盖判读" style={{ marginBottom: 16 }}>
<div className="vp-stat-insight-grid">
{[
{ label: '在线率', value: formatPercent(onlineRate), color: onlineRate >= 80 ? 'green' as const : 'orange' as const, detail: `${onlineCount.toLocaleString()} / ${rows.length.toLocaleString()} 辆在线。` },
{ label: '定位有效率', value: formatPercent(locatedRate), color: locatedRate >= 80 ? 'green' as const : 'orange' as const, detail: `${locatedCount.toLocaleString()} / ${rows.length.toLocaleString()} 辆坐标有效。` },
{ label: '降级率', value: formatPercent(degradedRate), color: degradedCount > 0 ? 'orange' as const : 'green' as const, detail: `${degradedCount.toLocaleString()} 辆存在来源不完整或离线。` },
{ label: '分页覆盖率', value: formatPercent(pageCoverageRate), color: pageCoverageRate >= 100 ? 'green' as const : 'grey' as const, detail: '当前页车辆数 / 当前筛选总车辆数。' }
].map((item) => (
<Card key={item.label} bordered>
<Tag color={item.color}>{item.label}</Tag>
<div className="vp-monitor-metric-value">{item.value}</div>
<Typography.Text type="secondary">{item.detail}</Typography.Text>
</Card>
))}
</div>
</Card>
<Tabs type="line">
<Tabs.TabPane tab="表格视图" itemKey="table">
<div className="vp-table-toolbar">

View File

@@ -7056,6 +7056,13 @@ test('copies realtime operations summary from realtime page', async () => {
render(<App />);
expect((await screen.findAllByText('VIN-RT-SUMMARY-001')).length).toBeGreaterThan(0);
expect(screen.getByText('实时覆盖判读')).toBeInTheDocument();
expect(screen.getByText('在线率')).toBeInTheDocument();
expect(screen.getAllByText('66.7%').length).toBeGreaterThanOrEqual(3);
expect(screen.getByText('定位有效率')).toBeInTheDocument();
expect(screen.getByText('降级率')).toBeInTheDocument();
expect(screen.getByText('分页覆盖率')).toBeInTheDocument();
expect(screen.getByText('100%')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: '复制实时摘要' }));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【实时监控摘要】'));