{[
- { label: '证据来源', value: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '-' },
- { label: '定位证据', value: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个证据有位置` : '暂无位置' },
+ { label: '数据通道', value: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '-' },
+ { label: '定位数据', value: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个通道有位置` : '暂无位置' },
{ label: '里程差异', value: formatCompactNumber(evidenceMileageDelta, ' km') },
{ label: '时间差异', value: formatSeconds(evidenceTimeDeltaSeconds) },
- { label: '主证据来源', value: overview?.primaryProtocol || summary?.primaryProtocol || '-' },
- { label: '服务结论', value: consistencyTitle }
+ { label: '主数据通道', value: overview?.primaryProtocol || summary?.primaryProtocol || '-' },
+ { label: '服务结论', value: customerStatusTitle(consistencyTitle) || consistencyTitle }
].map((item) => (
{item.label}
@@ -1305,7 +1314,7 @@ export function VehicleDetail({
{hasResolvedVIN && sourceFusionRows.length > 0 ? (
多证据归并矩阵} onClick={copySourceFusionReport}>复制归并矩阵}
+ title={数据通道归并矩阵} onClick={copySourceFusionReport}>复制归并矩阵}
style={{ marginTop: 16 }}
>
@@ -1327,7 +1336,7 @@ export function VehicleDetail({
{[
{ label: '实时', value: row.realtimeText },
{ label: '定位', value: row.locationText },
- { label: '原始记录', value: row.rawText },
+ { label: '历史数据', value: row.rawText },
{ label: '里程', value: row.mileageText }
].map((item) => (
@@ -1349,7 +1358,7 @@ export function VehicleDetail({
-
+
@@ -1424,7 +1433,7 @@ export function VehicleDetail({
{qualityIssueVehicleLabel(priorityQualityIssue, resolvedVIN)}
- {priorityQualityIssue.detail || '该车存在告警事件,需要结合轨迹和原始记录确认影响范围。'}
+ {priorityQualityIssue.detail || '该车存在告警事件,需要结合轨迹和历史数据确认影响范围。'}
@@ -1445,13 +1454,13 @@ export function VehicleDetail({
轨迹证据
@@ -1484,14 +1493,14 @@ export function VehicleDetail({
{ key: '归并来源数', value: archiveSourceCount },
{ key: '在线', value:
},
{
- key: '证据来源',
+ key: '数据通道',
value: protocols.length > 0 ? (
) : '-'
},
- { key: '在线证据', value: summary ? `${summary.onlineSourceCount}/${summary.sourceCount}` : '-' },
+ { key: '在线数据通道', value: summary ? `${summary.onlineSourceCount}/${summary.sourceCount}` : '-' },
{ key: '最后位置时间', value: lastSeen },
- { key: '最新原始记录时间', value: latestRaw?.serverTime ?? '-' },
+ { key: '最新历史数据时间', value: latestRaw?.serverTime ?? '-' },
{ key: '质量问题', value:
0 ? 'orange' : 'green'}>{qualityCount > 0 ? `${qualityCount} 项` : '无'} }
]}
/>
@@ -1509,14 +1518,14 @@ export function VehicleDetail({
{hasResolvedVIN ? (
<>
-
+
{detail?.sourceStatus?.length ? (
<>
- {activeProtocol ? `当前 ${activeProtocol}` : '当前 全部证据来源'}
+ {activeProtocol ? `当前 ${activeProtocol}` : '当前 全部数据通道'}
-
+
(
@@ -1598,7 +1607,7 @@ export function VehicleDetail({
disabled={!row.hasRaw}
onClick={() => onOpenRaw(resolvedVIN, row.protocol)}
>
- 查看 {row.protocol} 原始记录
+ 查看 {row.protocol} 历史数据
>
) : (
- 暂未查询到该车辆的证据来源覆盖。
+ 暂未查询到该车辆的数据通道覆盖。
)}
@@ -1624,13 +1633,13 @@ export function VehicleDetail({
0 ? `${consistencySourceCount} 个证据` : '-' },
- { key: '在线证据', value: consistencySourceCount > 0 ? `${consistencyOnlineSourceCount}/${consistencySourceCount} 在线` : '-' },
- { key: '缺失证据', value: missingProtocolText },
- { key: '位置覆盖', value: consistencyLocatedSourceCount > 0 ? `${consistencyLocatedSourceCount} 个证据有位置` : '暂无位置' },
+ { key: '一致性结论', value: customerStatusTitle(consistencyTitle) || consistencyTitle },
+ { key: '通道覆盖', value: consistencySourceCount > 0 ? `${consistencySourceCount} 个通道` : '-' },
+ { key: '在线数据通道', value: consistencySourceCount > 0 ? `${consistencyOnlineSourceCount}/${consistencySourceCount} 在线` : '-' },
+ { key: '缺失通道', value: missingProtocolText },
+ { key: '位置覆盖', value: consistencyLocatedSourceCount > 0 ? `${consistencyLocatedSourceCount} 个通道有位置` : '暂无位置' },
{ key: '里程差异', value: formatCompactNumber(consistencyMileageDelta, ' km') },
- { key: '证据时间差', value: formatSeconds(consistencyTimeDeltaSeconds) },
+ { key: '通道时间差', value: formatSeconds(consistencyTimeDeltaSeconds) },
{ key: '诊断说明', value: consistencyDetail },
{ key: '车辆服务视角', value: activeProtocol ? `当前只看 ${activeProtocol}` : '三类来源合并为同一车辆服务' }
]}
@@ -1713,7 +1722,7 @@ export function VehicleDetail({
{ title: '入库时间', dataIndex: 'serverTime', width: 190 }
]}
/>
- 最新原始记录字段明细
+ 最新历史数据字段明细
{JSON.stringify(latestRaw?.parsedFields ?? {}, null, 2)}
diff --git a/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx b/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx
index b6e110d7..edc8b809 100644
--- a/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx
+++ b/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx
@@ -149,7 +149,7 @@ type VehicleActionQueueItem = {
function vehicleFilterSummary(filters: Record) {
return [
filters.keyword ? `关键词:${filters.keyword}` : '',
- filters.protocol ? `证据来源:${filters.protocol}` : '',
+ filters.protocol ? `数据通道:${filters.protocol}` : '',
filters.coverage ? `车辆覆盖:${coverageLabel[filters.coverage] ?? filters.coverage}` : '',
filters.missingProtocol ? `缺失来源:${filters.missingProtocol}` : '',
filters.serviceStatus ? `服务状态:${serviceStatusLabel[filters.serviceStatus] ?? filters.serviceStatus}` : '',
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 bf0e6678..209338f2 100644
--- a/vehicle-data-platform/apps/web/src/test/App.test.tsx
+++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx
@@ -6583,12 +6583,19 @@ test('prevents unscoped raw parsed-field query from history form', async () => {
await waitFor(() => {
expect(keywordInput).toHaveValue('');
});
+ fireEvent.change(screen.getByPlaceholderText('2026-07-03 00:00:00'), { target: { value: '' } });
+ fireEvent.change(screen.getByPlaceholderText('2026-07-03 23:59:59'), { target: { value: '' } });
fireEvent.click(screen.getByRole('checkbox', { name: '返回字段明细' }));
fireEvent.click(screen.getByRole('button', { name: 'search 查询' }));
expect((await screen.findAllByText('字段明细查询需要车辆、时间范围或字段裁剪')).length).toBeGreaterThanOrEqual(1);
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('/api/history/locations?'), undefined);
- expect(fetchMock).not.toHaveBeenCalledWith('/api/history/raw-frames/query', expect.anything());
+ const unscopedRawQueries = fetchMock.mock.calls.filter(([url, init]) => {
+ if (url !== '/api/history/raw-frames/query') return false;
+ const body = JSON.parse(String((init as RequestInit | undefined)?.body ?? '{}')) as Record;
+ return !body.keyword && !body.dateFrom && !body.dateTo && !body.fields;
+ });
+ expect(unscopedRawQueries).toHaveLength(0);
});
test('shows trajectory playback workspace from history locations', async () => {
@@ -7545,7 +7552,8 @@ test('opens vehicle service from mileage row with row source evidence', async ()
render();
expect(await screen.findByText('VIN-MILEAGE-ROW')).toBeInTheDocument();
- fireEvent.click(screen.getAllByRole('button', { name: '车辆服务' })[0]);
+ const serviceButtons = screen.getAllByRole('button', { name: '车辆服务' });
+ fireEvent.click(serviceButtons[serviceButtons.length - 1]);
await waitFor(() => {
expect(window.location.hash).toBe('#/detail?keyword=VIN-MILEAGE-ROW&protocol=JT808');
@@ -8329,7 +8337,9 @@ test('opens vehicle service from history results with row source evidence', asyn
render();
expect(await screen.findByText('VIN-JT808-001')).toBeInTheDocument();
- fireEvent.click(screen.getAllByRole('button', { name: '车辆服务' })[0]);
+ const locationRow = screen.getByText('VIN-JT808-001').closest('tr');
+ expect(locationRow).not.toBeNull();
+ fireEvent.click(within(locationRow!).getByRole('button', { name: '车辆服务' }));
await waitFor(() => {
expect(window.location.hash).toBe('#/detail?keyword=VIN-JT808-001&protocol=JT808');
@@ -8609,7 +8619,9 @@ test('opens vehicle service from raw history rows with row source evidence', asy
fireEvent.click(await screen.findByRole('tab', { name: '历史明细' }));
expect(await screen.findByText('raw-gb32960-001')).toBeInTheDocument();
- fireEvent.click(screen.getAllByRole('button', { name: '车辆服务' })[0]);
+ const rawRow = screen.getByText('raw-gb32960-001').closest('tr');
+ expect(rawRow).not.toBeNull();
+ fireEvent.click(within(rawRow!).getByRole('button', { name: '车辆服务' }));
await waitFor(() => {
expect(window.location.hash).toBe('#/detail?keyword=VIN-GB32960-001&protocol=GB32960');
@@ -11063,19 +11075,19 @@ test('switches vehicle detail to a source from the source matrix', async () => {
expect(screen.getAllByText('GB32960 在线').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('JT808 在线').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('YUTONG_MQTT 未接入').length).toBeGreaterThanOrEqual(1);
- expect(screen.getByText('多证据归并矩阵')).toBeInTheDocument();
- expect(screen.getByText('主实时证据')).toBeInTheDocument();
- expect(screen.getAllByText('定位证据').length).toBeGreaterThanOrEqual(1);
+ expect(screen.getByText('数据通道归并矩阵')).toBeInTheDocument();
+ expect(screen.getByText('主实时通道')).toBeInTheDocument();
+ expect(screen.getAllByText('定位数据').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('统计口径').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('无实时字段')).toBeInTheDocument();
- expect(screen.getByText('无原始记录')).toBeInTheDocument();
+ expect(screen.getByText('无历史数据')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: '复制归并矩阵' }));
- expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【单车多证据归并矩阵】'));
- expect(writeText).toHaveBeenCalledWith(expect.stringContaining('1. GB32960 / 主证据'));
- expect(writeText).toHaveBeenCalledWith(expect.stringContaining('贡献:主实时证据、在线心跳、实时字段、定位证据、轨迹回放、原始记录、统计口径'));
+ expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【单车数据通道归并矩阵】'));
+ expect(writeText).toHaveBeenCalledWith(expect.stringContaining('1. GB32960 / 主数据通道'));
+ expect(writeText).toHaveBeenCalledWith(expect.stringContaining('贡献:主实时通道、在线心跳、实时字段、定位数据、轨迹回放、历史数据、统计口径'));
expect(screen.getByText('车辆服务角色')).toBeInTheDocument();
- expect(screen.getAllByText('主证据').length).toBeGreaterThanOrEqual(1);
- expect(screen.getAllByText('在线证据').length).toBeGreaterThanOrEqual(1);
+ expect(screen.getAllByText('主数据通道').length).toBeGreaterThanOrEqual(1);
+ expect(screen.getAllByText('在线数据通道').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('暂无来源').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('最新位置')).toBeInTheDocument();
expect(screen.getAllByText('113.2, 23.1').length).toBeGreaterThan(0);
@@ -11161,7 +11173,7 @@ test('shows unified service overview on vehicle detail', async () => {
expect(screen.getByText('今日单车服务任务板')).toBeInTheDocument();
expect(screen.getByText('看实时位置')).toBeInTheDocument();
expect(screen.getByText('回放轨迹证据')).toBeInTheDocument();
- expect(screen.getByText('导出原始证据')).toBeInTheDocument();
+ expect(screen.getAllByText('查询历史数据').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('复核里程统计')).toBeInTheDocument();
expect(screen.getByText('闭环告警事件')).toBeInTheDocument();
expect(screen.getByText('单车运营工作台')).toBeInTheDocument();
@@ -11169,17 +11181,17 @@ test('shows unified service overview on vehicle detail', async () => {
expect(screen.getAllByText('档案完整度').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('实时')).toBeInTheDocument();
expect(screen.getAllByText('轨迹').length).toBeGreaterThanOrEqual(1);
- expect(screen.getAllByText('原始记录').length).toBeGreaterThanOrEqual(1);
+ expect(screen.getAllByText('历史数据').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('里程').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('告警').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('实时定位')).toBeInTheDocument();
expect(screen.getAllByText('轨迹回放').length).toBeGreaterThanOrEqual(1);
- expect(screen.getAllByText('原始记录').length).toBeGreaterThan(0);
+ expect(screen.getAllByText('历史数据').length).toBeGreaterThan(0);
expect(screen.getByText('告警处置')).toBeInTheDocument();
expect(screen.getByText('里程复核')).toBeInTheDocument();
expect(screen.getByText('确认实时状态')).toBeInTheDocument();
expect(screen.getByText('回放轨迹断点')).toBeInTheDocument();
- expect(screen.getByText('核对原始记录')).toBeInTheDocument();
+ expect(screen.getAllByText('查询历史数据').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('处理告警闭环')).toBeInTheDocument();
expect(screen.getByText('复核统计口径')).toBeInTheDocument();
expect(screen.getByText('车辆在线状态、最新时间、有效坐标均可解释。')).toBeInTheDocument();
@@ -11189,13 +11201,13 @@ test('shows unified service overview on vehicle detail', async () => {
expect(screen.getAllByText('1 项').length).toBeGreaterThan(0);
expect(screen.getAllByText('7 条统计').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('2/3')).toBeInTheDocument();
- expect(screen.getByText('轨迹 12 / 原始记录 34 / 里程 7')).toBeInTheDocument();
+ expect(screen.getByText('轨迹 12 / 历史数据 34 / 里程 7')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '单车任务 看实时位置 实时监控' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '单车任务 回放轨迹证据 轨迹回放' })).toBeInTheDocument();
- expect(screen.getByRole('button', { name: '单车任务 导出原始证据 数据导出' })).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '单车任务 查询历史数据 历史数据' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '单车任务 复核里程统计 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '单车任务 闭环告警事件 告警事件' })).toBeInTheDocument();
- fireEvent.click(screen.getByRole('button', { name: '单车运营工作台 原始记录 查看原始记录' }));
+ fireEvent.click(screen.getByRole('button', { name: '单车运营工作台 历史数据 查看历史数据' }));
expect(window.location.hash).toBe('#/history-query?keyword=VIN001&tab=raw');
});
@@ -11348,7 +11360,7 @@ test('quality health shows structured capacity findings', async () => {
expect(screen.getByText('kafka lag 42')).toBeInTheDocument();
});
-test('shows vehicle service evidence chain before source details', async () => {
+test('shows vehicle service data chain before source details', async () => {
window.history.replaceState(null, '', '/#/detail?keyword=VIN001');
vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => {
const path = String(input);
@@ -11428,9 +11440,9 @@ test('shows vehicle service evidence chain before source details', async () => {
render();
- expect(await screen.findByText('车辆服务证据链')).toBeInTheDocument();
+ expect(await screen.findByText('车辆服务数据链')).toBeInTheDocument();
expect(screen.getAllByText('2/3 在线').length).toBeGreaterThan(0);
- expect(screen.getAllByText('2 个证据有位置').length).toBeGreaterThan(0);
+ expect(screen.getAllByText('2 个通道有位置').length).toBeGreaterThan(0);
expect(screen.getAllByText('1.4 km').length).toBeGreaterThan(0);
expect(screen.getAllByText('125 秒').length).toBeGreaterThan(0);
expect(screen.getAllByText('MQTT 离线,32960 与 808 仍可支撑车辆服务').length).toBeGreaterThan(0);
@@ -11682,7 +11694,7 @@ test('copies vehicle service diagnostic summary', async () => {
expect(await screen.findByText('车辆运营总览')).toBeInTheDocument();
expect(screen.getByRole('button', { name: /复制归一摘要/ })).toBeInTheDocument();
expect(screen.getByText('车辆身份')).toBeInTheDocument();
- expect(screen.getByText('实时主证据来源')).toBeInTheDocument();
+ expect(screen.getByText('实时主数据通道')).toBeInTheDocument();
expect(screen.getByText('业务可用性')).toBeInTheDocument();
expect(await screen.findByText('车辆服务结论')).toBeInTheDocument();
expect(screen.getByText('车辆服务档案总览')).toBeInTheDocument();
@@ -11700,13 +11712,13 @@ test('copies vehicle service diagnostic summary', async () => {
const unifiedCopied = String(writeText.mock.lastCall?.[0] ?? '');
expect(unifiedCopied).toContain('【统一车辆服务摘要】');
expect(unifiedCopied).toContain('车辆:粤A诊断1 / VIN-SUMMARY-001');
- expect(unifiedCopied).toContain('当前范围:单一来源:JT808');
+ expect(unifiedCopied).toContain('当前范围:单一数据通道:JT808');
expect(unifiedCopied).toContain('车辆身份:VIN-SUMMARY-001');
- expect(unifiedCopied).toContain('服务状态:来源不完整');
- expect(unifiedCopied).toContain('实时主证据来源:JT808');
- expect(unifiedCopied).toContain('证据在线:1/2');
+ expect(unifiedCopied).toContain('服务状态:数据通道不完整');
+ expect(unifiedCopied).toContain('实时主数据通道:JT808');
+ expect(unifiedCopied).toContain('通道在线:1/2');
expect(unifiedCopied).toContain('业务可用性:在线可用');
- expect(unifiedCopied).toContain('服务数据:实时 2 / 轨迹 12 / 原始记录 34 / 里程 3 / 告警 1');
+ expect(unifiedCopied).toContain('服务数据:实时 2 / 轨迹 12 / 历史数据 34 / 里程 3 / 告警 1');
expect(unifiedCopied).toContain('车辆服务:http://localhost:3000/#/detail?keyword=VIN-SUMMARY-001&protocol=JT808');
fireEvent.click(screen.getByRole('button', { name: /复制档案/ }));
await waitFor(() => {
@@ -11715,10 +11727,10 @@ test('copies vehicle service diagnostic summary', async () => {
const dossierCopied = String(writeText.mock.lastCall?.[0] ?? '');
expect(dossierCopied).toContain('【车辆服务档案】');
expect(dossierCopied).toContain('车辆:粤A诊断1 / VIN-SUMMARY-001');
- expect(dossierCopied).toContain('当前范围:单一来源:JT808');
- expect(dossierCopied).toContain('主证据来源:JT808');
- expect(dossierCopied).toContain('证据在线:1/2');
- expect(dossierCopied).toContain('资产概览:实时 2 / 轨迹 12 / 原始记录 34 / 里程 3 / 告警 1');
+ expect(dossierCopied).toContain('当前范围:单一数据通道:JT808');
+ expect(dossierCopied).toContain('主数据通道:JT808');
+ expect(dossierCopied).toContain('通道在线:1/2');
+ expect(dossierCopied).toContain('资产概览:实时 2 / 轨迹 12 / 历史数据 34 / 里程 3 / 告警 1');
expect(dossierCopied).toContain('车辆服务:http://localhost:3000/#/detail?keyword=VIN-SUMMARY-001&protocol=JT808');
fireEvent.click(screen.getByRole('button', { name: /复制交付包/ }));
await waitFor(() => {
@@ -11742,19 +11754,19 @@ test('copies vehicle service diagnostic summary', async () => {
expect(copied).toContain('【车辆服务诊断摘要】');
expect(copied).toContain('运行版本:platform-20260704155844');
expect(copied).toContain('车辆:粤A诊断1 / VIN-SUMMARY-001');
- expect(copied).toContain('当前范围:单一来源:JT808');
- expect(copied).toContain('服务状态:来源不完整');
- expect(copied).toContain('证据来源:1/2 在线');
- expect(copied).toContain('定位证据:2 个证据有位置');
+ expect(copied).toContain('当前范围:单一数据通道:JT808');
+ expect(copied).toContain('服务状态:数据通道不完整');
+ expect(copied).toContain('数据通道:1/2 在线');
+ expect(copied).toContain('定位数据:2 个通道有位置');
expect(copied).toContain('里程差异:12.6 km');
expect(copied).toContain('时间差异:90 秒');
- expect(copied).toContain('服务数据:实时 2 / 轨迹 12 / 原始记录 34 / 里程 3 / 告警 1');
- expect(copied).toContain('一致性:来源不完整');
+ expect(copied).toContain('服务数据:实时 2 / 轨迹 12 / 历史数据 34 / 里程 3 / 告警 1');
+ expect(copied).toContain('一致性:数据通道不完整');
expect(copied).toContain('下一步:');
expect(copied).toContain('车辆服务:http://localhost:3000/#/detail?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(copied).toContain('实时:http://localhost:3000/#/realtime?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(copied).toContain('轨迹:http://localhost:3000/#/history?keyword=VIN-SUMMARY-001&protocol=JT808');
- expect(copied).toContain('原始记录:http://localhost:3000/#/history-query?keyword=VIN-SUMMARY-001&protocol=JT808&tab=raw&includeFields=true');
+ expect(copied).toContain('历史数据: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');
fireEvent.click(screen.getByRole('button', { name: /复制运营摘要/ }));
@@ -11764,10 +11776,10 @@ test('copies vehicle service diagnostic summary', async () => {
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('当前范围:单一数据通道: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 证据');
@@ -11776,7 +11788,7 @@ test('copies vehicle service diagnostic summary', async () => {
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('原始记录:http://localhost:3000/#/history-query?keyword=VIN-SUMMARY-001&protocol=JT808&tab=raw&includeFields=true');
+ expect(operationsCopied).toContain('历史数据: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');
fireEvent.click(screen.getByRole('button', { name: '复制处理清单' }));
@@ -11786,10 +11798,10 @@ test('copies vehicle service diagnostic summary', async () => {
const runbookCopied = String(writeText.mock.lastCall?.[0] ?? '');
expect(runbookCopied).toContain('【单车服务处理清单】');
expect(runbookCopied).toContain('车辆:粤A诊断1 / VIN-SUMMARY-001');
- expect(runbookCopied).toContain('当前范围:单一来源:JT808');
+ expect(runbookCopied).toContain('当前范围:单一数据通道:JT808');
expect(runbookCopied).toContain('1. 确认实时状态');
expect(runbookCopied).toContain('2. 回放轨迹断点');
- expect(runbookCopied).toContain('3. 核对原始记录');
+ expect(runbookCopied).toContain('3. 查询历史数据');
expect(runbookCopied).toContain('4. 处理告警闭环');
expect(runbookCopied).toContain('5. 复核统计口径');
expect(runbookCopied).toContain('验收:车辆在线状态、最新时间、有效坐标均可解释。');
@@ -12037,7 +12049,7 @@ test('opens raw history with the currently selected vehicle detail source', asyn
render();
fireEvent.click(await screen.findByRole('button', { name: '仅看 JT808' }));
- fireEvent.click(screen.getAllByRole('button', { name: '数据导出' })[0]);
+ fireEvent.click(screen.getAllByRole('button', { name: '历史数据' })[0]);
await waitFor(() => {
expect(window.location.hash).toBe('#/history-query?keyword=VIN001&protocol=JT808&tab=raw');
@@ -12195,7 +12207,7 @@ test('opens source-specific history directly from vehicle detail source card', a
});
});
-test('opens source-specific raw history directly from vehicle detail source evidence', async () => {
+test('opens source-specific raw history directly from vehicle detail source data channel', async () => {
window.history.replaceState(null, '', '/#/detail?keyword=VIN001');
vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => {
const path = String(input);
@@ -12263,7 +12275,7 @@ test('opens source-specific raw history directly from vehicle detail source evid
render();
- fireEvent.click(await screen.findByRole('button', { name: '查看 JT808 原始记录' }));
+ fireEvent.click(await screen.findByRole('button', { name: '查看 JT808 历史数据' }));
await waitFor(() => {
expect(window.location.hash).toBe('#/history-query?keyword=VIN001&protocol=JT808&tab=raw');
@@ -12394,9 +12406,9 @@ test('shows selected source scope on vehicle detail', async () => {
render();
expect(await screen.findByText('当前查看范围')).toBeInTheDocument();
- expect(screen.getAllByText('单一来源:JT808').length).toBeGreaterThan(0);
+ expect(screen.getAllByText('单一数据通道:JT808').length).toBeGreaterThan(0);
expect(screen.getByText('车辆服务状态')).toBeInTheDocument();
- expect(screen.getAllByText('来源不完整').length).toBeGreaterThan(0);
+ expect(screen.getAllByText('数据通道不完整').length).toBeGreaterThan(0);
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('/api/vehicle-service?keyword=VIN001&protocol=JT808'), undefined);
});
@@ -12490,12 +12502,12 @@ test('shows cross-source consistency for one vehicle service', async () => {
render();
expect(await screen.findByText('跨证据一致性')).toBeInTheDocument();
- expect(screen.getAllByText('来源不完整').length).toBeGreaterThanOrEqual(1);
+ expect(screen.getAllByText('数据通道不完整').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('2/3 个来源在线,车辆服务可用但缺少 YUTONG_MQTT 来源。').length).toBeGreaterThan(0);
- expect(screen.getByText('3 个证据')).toBeInTheDocument();
+ expect(screen.getByText('3 个通道')).toBeInTheDocument();
expect(screen.getAllByText('2/3 在线').length).toBeGreaterThan(0);
- expect(screen.getByText('缺失证据')).toBeInTheDocument();
- expect(screen.getAllByText('3 个证据有位置').length).toBeGreaterThan(0);
+ expect(screen.getByText('缺失通道')).toBeInTheDocument();
+ expect(screen.getAllByText('3 个通道有位置').length).toBeGreaterThan(0);
expect(screen.getAllByText('0.4 km').length).toBeGreaterThan(0);
expect(screen.getAllByText('35 秒').length).toBeGreaterThan(0);
fireEvent.click(screen.getByRole('button', { name: '查看缺 YUTONG_MQTT 车辆' }));