feat(platform): add vehicle operations summary

This commit is contained in:
lingniu
2026-07-04 20:23:12 +08:00
parent fb4bcbaa55
commit 284d2e1741
2 changed files with 51 additions and 0 deletions

View File

@@ -450,6 +450,34 @@ export function VehicleDetail({
}
return actions;
}, [activeProtocol, detail?.sourceStatus, displayLookupKey, hasResolvedVIN, missingProtocols, onOpenQuality, onOpenRealtime, onOpenVehicles, qualityCount, resolvedVIN]);
const copyVehicleOperationsSummary = () => {
if (!detail) {
Toast.warning('当前没有可复制的运营摘要');
return;
}
const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
const actionLines = serviceActions.map((item, index) => `${index + 1}. ${item.label}${item.description}`);
const lines = [
'【车辆服务运营摘要】',
`车辆:${vehicleName}`,
`当前范围:${scopeText}`,
`服务状态:${serviceStatus?.title ?? serviceConclusion.status}`,
`业务影响:${serviceConclusion.risk}`,
`建议动作:${serviceConclusion.nextStep}`,
`在线来源:${evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount}` : '-'}`,
`定位来源:${evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount}` : '0'}`,
`质量问题:${qualityCount.toLocaleString()}`,
`数据规模:历史 ${overview?.historyCount ?? detail.history.total ?? 0} / RAW ${overview?.rawCount ?? detail.raw.total ?? 0} / 里程 ${overview?.mileageCount ?? detail.mileage.total ?? 0}`,
`下一步清单:${actionLines.length > 0 ? '' : '暂无明确处置项,持续观察实时状态。'}`,
...actionLines,
`车辆服务:${vehicleServiceURL(vehicleServiceHash('detail'))}`,
`实时监控:${vehicleServiceURL(vehicleServiceHash('realtime'))}`,
`轨迹回放:${vehicleServiceURL(vehicleServiceHash('history'))}`,
`RAW证据${vehicleServiceURL(vehicleServiceHash('history-query', { tab: 'raw', includeFields: 'true' }))}`,
`里程统计:${vehicleServiceURL(vehicleServiceHash('mileage'))}`
];
copyText(lines.join('\n'), '运营摘要');
};
const detailWorkbench = [
{
title: '实时定位',
@@ -581,6 +609,7 @@ export function VehicleDetail({
<Button icon={<IconRefresh />} onClick={() => load(query)} loading={loading}></Button>
<Button icon={<IconCopy />} onClick={copyVehicleServiceURL}></Button>
<Button disabled={!detail} icon={<IconCopy />} onClick={copyVehicleDiagnosticSummary}></Button>
<Button disabled={!detail} icon={<IconCopy />} onClick={copyVehicleOperationsSummary}></Button>
<Button disabled={!detail} icon={<IconDownload />} onClick={exportVehicleReport}> CSV</Button>
<Button disabled={!hasResolvedVIN} onClick={() => onOpenRealtime(resolvedVIN, activeProtocol)}></Button>
<Button disabled={!hasResolvedVIN} onClick={() => onOpenHistory(resolvedVIN, activeProtocol)}></Button>

View File

@@ -10556,6 +10556,28 @@ test('copies vehicle service diagnostic summary', async () => {
expect(copied).toContain('轨迹http://localhost:3000/#/history?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(copied).toContain('RAWhttp://localhost:3000/#/history-query?keyword=VIN-SUMMARY-001&protocol=JT808&tab=raw&includeFields=true');
expect(copied).toContain('里程http://localhost:3000/#/mileage?keyword=VIN-SUMMARY-001&protocol=JT808');
fireEvent.click(screen.getByRole('button', { name: /复制运营摘要/ }));
await waitFor(() => {
expect(writeText.mock.calls.some((call) => String(call[0]).includes('【车辆服务运营摘要】'))).toBe(true);
});
const operationsCopied = String(writeText.mock.lastCall?.[0] ?? '');
expect(operationsCopied).toContain('【车辆服务运营摘要】');
expect(operationsCopied).toContain('车辆粤A诊断1 / VIN-SUMMARY-001');
expect(operationsCopied).toContain('当前范围单一来源JT808');
expect(operationsCopied).toContain('服务状态:来源不完整');
expect(operationsCopied).toContain('在线来源1/2');
expect(operationsCopied).toContain('定位来源2');
expect(operationsCopied).toContain('质量问题1 项');
expect(operationsCopied).toContain('下一步清单:');
expect(operationsCopied).toContain('补齐 YUTONG_MQTT 来源');
expect(operationsCopied).toContain('排查 GB32960 离线');
expect(operationsCopied).toContain('处理质量问题 1 项');
expect(operationsCopied).toContain('车辆服务http://localhost:3000/#/detail?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(operationsCopied).toContain('实时监控http://localhost:3000/#/realtime?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(operationsCopied).toContain('轨迹回放http://localhost:3000/#/history?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(operationsCopied).toContain('RAW证据http://localhost:3000/#/history-query?keyword=VIN-SUMMARY-001&protocol=JT808&tab=raw&includeFields=true');
expect(operationsCopied).toContain('里程统计http://localhost:3000/#/mileage?keyword=VIN-SUMMARY-001&protocol=JT808');
});
test('exports vehicle detail service dossier as csv', async () => {