feat(platform): add vehicle operations summary
This commit is contained in:
@@ -450,6 +450,34 @@ export function VehicleDetail({
|
|||||||
}
|
}
|
||||||
return actions;
|
return actions;
|
||||||
}, [activeProtocol, detail?.sourceStatus, displayLookupKey, hasResolvedVIN, missingProtocols, onOpenQuality, onOpenRealtime, onOpenVehicles, qualityCount, resolvedVIN]);
|
}, [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 = [
|
const detailWorkbench = [
|
||||||
{
|
{
|
||||||
title: '实时定位',
|
title: '实时定位',
|
||||||
@@ -581,6 +609,7 @@ export function VehicleDetail({
|
|||||||
<Button icon={<IconRefresh />} onClick={() => load(query)} loading={loading}>刷新</Button>
|
<Button icon={<IconRefresh />} onClick={() => load(query)} loading={loading}>刷新</Button>
|
||||||
<Button icon={<IconCopy />} onClick={copyVehicleServiceURL}>复制服务链接</Button>
|
<Button icon={<IconCopy />} onClick={copyVehicleServiceURL}>复制服务链接</Button>
|
||||||
<Button disabled={!detail} icon={<IconCopy />} onClick={copyVehicleDiagnosticSummary}>复制诊断摘要</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={!detail} icon={<IconDownload />} onClick={exportVehicleReport}>导出档案 CSV</Button>
|
||||||
<Button disabled={!hasResolvedVIN} onClick={() => onOpenRealtime(resolvedVIN, activeProtocol)}>查看实时</Button>
|
<Button disabled={!hasResolvedVIN} onClick={() => onOpenRealtime(resolvedVIN, activeProtocol)}>查看实时</Button>
|
||||||
<Button disabled={!hasResolvedVIN} onClick={() => onOpenHistory(resolvedVIN, activeProtocol)}>查看历史</Button>
|
<Button disabled={!hasResolvedVIN} onClick={() => onOpenHistory(resolvedVIN, activeProtocol)}>查看历史</Button>
|
||||||
|
|||||||
@@ -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('轨迹:http://localhost:3000/#/history?keyword=VIN-SUMMARY-001&protocol=JT808');
|
||||||
expect(copied).toContain('RAW:http://localhost:3000/#/history-query?keyword=VIN-SUMMARY-001&protocol=JT808&tab=raw&includeFields=true');
|
expect(copied).toContain('RAW:http://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');
|
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 () => {
|
test('exports vehicle detail service dossier as csv', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user