feat(platform): align customer mileage service wording

This commit is contained in:
lingniu
2026-07-06 06:19:40 +08:00
parent e847e1c7e8
commit 536d37ca9b
9 changed files with 316 additions and 316 deletions

View File

@@ -37,27 +37,27 @@ test('renders vehicle platform shell', () => {
render(<App />);
expect(screen.getByText('车辆服务中台')).toBeInTheDocument();
expect(screen.getByText('实时地图 / 轨迹统计 / 告警通知')).toBeInTheDocument();
expect(screen.getByText('实时地图 / 轨迹里程 / 告警通知')).toBeInTheDocument();
expect(screen.getByText('客户主线')).toBeInTheDocument();
expect(screen.getByText('先看车,再查时间窗,最后导出和通知。')).toBeInTheDocument();
expect(screen.getByText('客户任务分发台')).toBeInTheDocument();
expect(screen.getByText('输入 VIN / 车牌 / 手机号后,地图、轨迹、统计、导出和告警都围绕同一辆车服务。')).toBeInTheDocument();
expect(screen.getByText('输入 VIN / 车牌 / 手机号后,地图、轨迹、里程、导出和告警都围绕同一辆车服务。')).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();
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();
expect(screen.getByText('车辆监控')).toBeInTheDocument();
expect(screen.getByText('地图看车、实时状态、异常优先')).toBeInTheDocument();
expect(screen.getAllByText('车辆服务').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('按 VIN、车牌、手机号管理车辆')).toBeInTheDocument();
expect(screen.getAllByText('轨迹统计').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('回放轨迹、统计查询、导出数据')).toBeInTheDocument();
expect(screen.getAllByText('轨迹里程').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('回放轨迹、里程统计、导出数据')).toBeInTheDocument();
expect(screen.getAllByText('告警通知').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('接入运维')).toBeInTheDocument();
expect(screen.getAllByText('客户').length).toBeGreaterThanOrEqual(3);
@@ -498,10 +498,10 @@ test('dashboard presents customer vehicle service modules before operations deta
const servicePath = await screen.findByLabelText('客户车辆服务路径');
const serviceOverview = within(servicePath).getByLabelText('客户服务总览');
expect(within(serviceOverview).getByText('客户服务总览')).toBeInTheDocument();
expect(within(serviceOverview).getByText('地图、轨迹、统计、导出是客户能直接使用的车辆服务;协议来源只进入证据和追溯。')).toBeInTheDocument();
expect(within(serviceOverview).getByText('地图、轨迹、里程、导出是客户能直接使用的车辆服务;协议来源只进入证据和追溯。')).toBeInTheDocument();
expect(within(serviceOverview).getByRole('button', { name: '客户服务总览 车辆地图 进入地图' })).toBeInTheDocument();
expect(within(serviceOverview).getByRole('button', { name: '客户服务总览 轨迹回放 回放轨迹' })).toBeInTheDocument();
expect(within(serviceOverview).getByRole('button', { name: '客户服务总览 统计查询 查看统计' })).toBeInTheDocument();
expect(within(serviceOverview).getByRole('button', { name: '客户服务总览 里程统计 查看统计' })).toBeInTheDocument();
expect(within(serviceOverview).getByRole('button', { name: '客户服务总览 历史数据 查询导出' })).toBeInTheDocument();
});
@@ -525,7 +525,7 @@ test('topbar frames customer work as a vehicle service delivery strip', () => {
expect(screen.getByText('服务动作')).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();
});
@@ -545,7 +545,7 @@ test('topbar exposes a mobile vehicle service shortcut dock', () => {
expect(screen.getByRole('navigation', { 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();
expect(screen.getByRole('button', { name: '移动端车辆服务快捷入口 告警' })).toBeInTheDocument();
});
@@ -725,7 +725,7 @@ test('exposes AMap operations shortcuts when map key is configured', async () =>
expect(await screen.findByRole('heading', { name: '历史查询导出' })).toBeInTheDocument();
expect(screen.getByText('默认查询最近一天,不预置任何车辆;输入 VIN、车牌或手机号后进入单车查询导出。')).toBeInTheDocument();
expect(screen.queryByDisplayValue('LB9A32A24R0LS1426')).not.toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: '顶部统计查询' }));
fireEvent.click(screen.getByRole('button', { name: '顶部里程统计' }));
expect(window.location.hash.startsWith('#/mileage')).toBe(true);
fireEvent.click(await screen.findByRole('button', { name: '顶部告警事件正常' }));
expect(window.location.hash).toBe('#/alert-events');
@@ -1208,7 +1208,7 @@ test('dashboard prioritizes customer vehicle service command over data sources',
expect((await screen.findAllByText('车辆服务指挥台')).length).toBeGreaterThan(0);
expect(screen.getByText('10 秒内回答客户最关心的事:车辆在哪里、哪辆车异常、这段时间怎么跑、数据能不能导出。')).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.getAllByText('客户今日运营台').length).toBeGreaterThanOrEqual(1);
@@ -1248,7 +1248,7 @@ test('dashboard prioritizes customer vehicle service command over data sources',
expect(screen.getByRole('button', { name: '车辆服务驾驶舱 车辆总览 1,033 辆 车辆中心' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务驾驶舱 实时可见 208 在线 地图看车' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务驾驶舱 轨迹复盘 4 今日活跃 回放轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务驾驶舱 里程统计 1 天窗口 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务驾驶舱 里程统计 1 天窗口 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务驾驶舱 数据交付 1,286,320 今日数据 导出证据' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务驾驶舱 告警通知 7 告警 闭环处理' })).toBeInTheDocument();
expect(await screen.findByText('车辆服务闭环')).toBeInTheDocument();
@@ -1256,7 +1256,7 @@ test('dashboard prioritizes customer vehicle service command over data sources',
expect(screen.getByRole('button', { name: '车辆服务闭环 1 选车 1,033 车辆中心' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务闭环 2 实时看车 208 在线 实时地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务闭环 3 锁定时间窗 1 天窗口 自定义时间' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务闭环 4 复盘统计 4 活跃 轨迹统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务闭环 4 复盘里程 4 活跃 轨迹里程' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务闭环 5 交付闭环 7 告警 导出通知' })).toBeInTheDocument();
expect(screen.getByText('车辆地图态势')).toBeInTheDocument();
expect(screen.getByText('先看在线车辆在哪里,再决定是否回放轨迹、核对里程、导出数据或通知处理。')).toBeInTheDocument();
@@ -1272,7 +1272,7 @@ test('dashboard prioritizes customer vehicle service command over data sources',
expect(screen.getByText('三个接入来源统一沉到证据层,首页只回答客户怎么监控车辆、回放轨迹、核对里程、导出数据和处理告警。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务总控台 实时地图 208 在线 进入地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务总控台 轨迹回放 4 活跃 回放轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务总控台 统计查询 1,033 车辆 查统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务总控台 里程统计 1,033 车辆 查里程' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务总控台 时间窗监控 1 天窗口 自定义时间' })).toBeInTheDocument();
expect(screen.getByText('同一时间窗贯穿轨迹、统计、历史导出和告警复盘。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务总控台 数据导出 1,286,320 今日数据 查询导出' })).toBeInTheDocument();
@@ -1295,7 +1295,7 @@ test('dashboard prioritizes customer vehicle service command over data sources',
expect(screen.getByRole('button', { name: '车辆健康与能耗工作台 实时工况 208 在线 实时监控' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆健康与能耗工作台 SOC/氢能字段 1,286,320 今日数据 字段证据' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆健康与能耗工作台 异常维护 7 告警 告警事件' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆健康与能耗工作台 里程能耗 1 天窗口 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆健康与能耗工作台 里程能耗 1 天窗口 里程统计' })).toBeInTheDocument();
expect(screen.getByText('地图服务能力清单')).toBeInTheDocument();
expect(screen.getByText('把高德 Web JS 和服务端 API 翻译成客户能使用的车辆服务能力。')).toBeInTheDocument();
expect(screen.getByText('实时底图')).toBeInTheDocument();
@@ -1399,7 +1399,7 @@ test('dashboard presents a customer dispatch operations home', async () => {
expect(screen.getByRole('button', { name: '客户调度运营首页 今日重点 7 告警 处理告警' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '调度运营任务 看全域位置 208 在线 实时地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '调度运营任务 回放重点轨迹 4 活跃 轨迹回放' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '调度运营任务 核对时间窗里程 1,033 车辆 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '调度运营任务 核对时间窗里程 1,033 车辆 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '调度运营任务 导出客户证据 1,286,320 帧 历史导出' })).toBeInTheDocument();
});
@@ -1495,7 +1495,7 @@ test('dashboard frames history query and export as a customer delivery workbench
expect(screen.getByRole('button', { name: '客户常用时间范围 本周 2026-06-29 至 2026-07-05 应用' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户常用时间范围 自定义复盘 当前范围 应用' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户查询导出交付台 轨迹回放 4 活跃 回放轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户查询导出交付台 里程统计 1,033 车辆 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户查询导出交付台 里程统计 1,033 车辆 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户查询导出交付台 历史明细 1,286,320 帧 历史导出' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户查询导出交付台 告警说明 7 告警 告警通知' })).toBeInTheDocument();
});
@@ -1585,7 +1585,7 @@ test('dashboard separates customer vehicle service from operations evidence', as
expect(screen.getByText('默认展示车辆地图、时间窗、里程、导出和告警;三类数据源只作为二级证据。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户主流程 实时地图 208 在线 打开地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户主流程 时间窗复盘 1 天窗口 查询导出' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户主流程 里程统计 1,033 车辆 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户主流程 里程统计 1,033 车辆 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户主流程 告警通知 7 告警 通知处理' })).toBeInTheDocument();
expect(screen.getByText('运维证据层')).toBeInTheDocument();
expect(screen.getByText('用于解释车辆服务不可用的链路、队列、缓存、存储和来源证据,不作为客户默认入口。')).toBeInTheDocument();
@@ -1679,7 +1679,7 @@ test('dashboard guides customer custom time window service path', async () => {
expect(screen.getByText('锁定同一辆车和同一时间范围后,按轨迹、里程、历史证据和告警说明形成客户可复盘的交付路径。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗服务路径 1 锁定范围 1 天窗口 应用时间窗' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗服务路径 2 回放轨迹 4 活跃 轨迹回放' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗服务路径 3 核对里程 1,033 车辆 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗服务路径 3 核对里程 1,033 车辆 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗服务路径 4 导出证据 1,286,320 帧 数据导出' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗服务路径 5 告警说明 7 告警 告警通知' })).toBeInTheDocument();
expect(screen.getByText('时间窗下一步行动条')).toBeInTheDocument();
@@ -1690,7 +1690,7 @@ test('dashboard guides customer custom time window service path', async () => {
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();
});
@@ -1779,7 +1779,7 @@ test('time monitor route exposes a dedicated customer time window workspace', as
expect(screen.getAllByText('时间窗监控').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('当前监控范围粤A时间窗 / JT808 / 2026-07-01 至 2026-07-03')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控入口 轨迹回放 3 天窗口' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控入口 统计查询 3 天窗口' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控入口 里程统计 3 天窗口' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控入口 历史导出 9,988 帧' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控入口 告警复盘 2 告警' })).toBeInTheDocument();
expect(screen.getByText('时间窗复盘 SLA 作业台')).toBeInTheDocument();
@@ -1795,7 +1795,7 @@ test('time monitor route exposes a dedicated customer time window workspace', as
});
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('作业范围粤A时间窗 / JT808 / 2026-07-01 至 2026-07-03'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付SLA3 天窗口内完成轨迹复盘、统计核对、历史导出和告警说明'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付物:轨迹回放链接 / 统计查询链接 / 历史导出链接 / 告警复盘链接'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付物:轨迹回放链接 / 里程统计链接 / 历史导出链接 / 告警复盘链接'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('升级条件2 告警车辆需要先进入告警复盘'));
});
@@ -1997,7 +1997,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
expect(screen.getByText('把实时地图、轨迹回放、里程统计、历史导出和告警通知收敛成一个可交付的车辆服务入口。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务驾驶舱 车辆在哪里 0 有定位 打开地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务驾驶舱 轨迹能否回放 4 活跃 轨迹回放' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务驾驶舱 里程怎么算 1,033 车辆 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务驾驶舱 里程怎么算 1,033 车辆 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务驾驶舱 数据怎么导出 1,286,320 今日数据 历史导出' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务驾驶舱 异常谁处理 7 告警 告警通知' })).toBeInTheDocument();
expect(screen.getByText('客户车辆服务中台蓝图')).toBeInTheDocument();
@@ -2009,10 +2009,10 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
expect(screen.getByRole('button', { name: '客户车辆服务中台蓝图 车辆健康 1,033 车辆 车辆中心' })).toBeInTheDocument();
expect(screen.getByRole('region', { name: '客户常用视图库' })).toBeInTheDocument();
expect(screen.getByText('一个车辆服务入口,而不是三个数据源入口。')).toBeInTheDocument();
expect(screen.getByText('把车队范围、时间窗、地图态势、轨迹回放、统计查询、导出模板和告警订阅保存成客户可复用的车辆服务入口。')).toBeInTheDocument();
expect(screen.getByText('把车队范围、时间窗、地图态势、轨迹回放、里程统计、导出模板和告警订阅保存成客户可复用的车辆服务入口。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户常用视图库 在线车队视图 208 在线 打开地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户常用视图库 轨迹日报模板 4 活跃 历史导出' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户常用视图库 里程周报模板 1,033 车辆 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户常用视图库 里程周报模板 1,033 车辆 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户常用视图库 告警订阅视图 7 告警 通知闭环' })).toBeInTheDocument();
expect(screen.getByRole('region', { name: '十秒车辆处置台' })).toBeInTheDocument();
expect(screen.getByText('登录后先知道哪三类车辆最需要处理,再进入地图、车辆中心或告警通知。')).toBeInTheDocument();
@@ -2023,7 +2023,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
expect(screen.getByText('一屏完成车辆地图、轨迹回放、里程统计、数据导出和告警闭环。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '现代车队运营台 Live Map 208 在线 打开地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '现代车队运营台 Route Replay 4 活跃 回放轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '现代车队运营台 Mileage 1,033 车辆 查统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '现代车队运营台 Mileage 1,033 车辆 查里程' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '现代车队运营台 Export 1,286,320 今日数据 导出数据' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '现代车队运营台 Alerts 7 告警 通知闭环' })).toBeInTheDocument();
expect(screen.getByText('高德地图车辆服务底座')).toBeInTheDocument();
@@ -2034,19 +2034,19 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
expect(screen.getByRole('button', { name: '高德地图车辆服务底座 时间窗导出 1,286,320 今日数据 历史导出' })).toBeInTheDocument();
expect(screen.getByText('车辆监控中心')).toBeInTheDocument();
expect(screen.getByText('先看车在哪里,再处理轨迹、统计、告警和导出')).toBeInTheDocument();
expect(screen.getByText('客户主流程围绕车辆本身:地图看车、实时状态、时间窗复盘、统计查询、历史数据导出和告警通知。接入来源只作为追溯证据。')).toBeInTheDocument();
expect(screen.getByText('客户主流程围绕车辆本身:地图看车、实时状态、时间窗复盘、里程统计、历史数据导出和告警通知。接入来源只作为追溯证据。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆监控指标 车辆总数 1,033' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆监控指标 在线车辆 208' })).toBeInTheDocument();
expect(screen.getByText('客户任务导航')).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.getByText('客户问题处理台')).toBeInTheDocument();
expect(screen.getByText('先回答客户问题,再下钻到车辆、轨迹、统计和证据。')).toBeInTheDocument();
expect(screen.getByText('客户首先关心的是车辆、位置、时间、里程、告警和导出GB32960、JT808、MQTT 只放在证据层。')).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();
@@ -2062,7 +2062,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
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();
expect(screen.getByRole('button', { name: '客户车辆工作流 告警通知 告警事件' })).toBeInTheDocument();
expect(screen.getByText('客户常问')).toBeInTheDocument();
@@ -2072,10 +2072,10 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
expect(screen.getByRole('button', { name: '客户常问 数据能导出给客户吗? 查询导出' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户常问 哪些车需要马上处理? 告警事件' })).toBeInTheDocument();
expect(screen.getByText('来源只作为可信度证据,不作为客户主导航。')).toBeInTheDocument();
expect(screen.getByText('同一时间窗会同步用于轨迹回放、统计查询、历史查询和告警复盘。')).toBeInTheDocument();
expect(screen.getByText('同一时间窗会同步用于轨迹回放、里程统计、历史查询和告警复盘。')).toBeInTheDocument();
expect(screen.getByText('客户交付驾驶舱')).toBeInTheDocument();
expect(screen.getByText('把车辆位置、时间窗、里程统计、历史证据和告警通知组织成客户可以直接使用的服务包。')).toBeInTheDocument();
expect(screen.getByText('客户打开首页后,先知道今天能交付什么,再选择地图、轨迹、统计、导出或通知。')).toBeInTheDocument();
expect(screen.getByText('客户打开首页后,先知道今天能交付什么,再选择地图、轨迹、里程、导出或通知。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户交付驾驶舱 在线车辆交付 实时地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户交付驾驶舱 时间窗复盘 轨迹回放' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户交付驾驶舱 数据证据交付 历史导出' })).toBeInTheDocument();
@@ -2135,17 +2135,17 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
expect(screen.getByRole('button', { name: '复制复盘包' })).toBeInTheDocument();
expect(screen.getByText('这个范围会同步带入轨迹、统计、历史证据和告警复盘适合客户问询、BI 核对和异常解释。')).toBeInTheDocument();
expect(screen.getByText('查看轨迹')).toBeInTheDocument();
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).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('里程统计').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('历史证据').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('告警复盘').length).toBeGreaterThanOrEqual(1);
expect(screen.getByRole('button', { name: '时间窗作业 轨迹回放 打开轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗作业 历史证据 导出证据' })).toBeInTheDocument();
expect(screen.getByText('今天车辆轨迹')).toBeInTheDocument();
expect(screen.getByText('历史时间窗')).toBeInTheDocument();
expect(screen.getAllByText('统计查询').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('里程统计').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('告警复盘').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('运维和证据层')).toBeInTheDocument();
expect(screen.getByText('来源覆盖、地图配置、告警预览和实时证据默认收起,客户主流程先看车辆监控、轨迹、统计、告警和导出。')).toBeInTheDocument();
@@ -2165,7 +2165,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
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.getByText('区间闭合复核')).toBeInTheDocument();
expect(screen.getByText('高德轨迹证据')).toBeInTheDocument();
@@ -2197,7 +2197,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
cleanup();
await renderDashboard();
fireEvent.click(screen.getByRole('button', { name: '今日任务 按时间窗复盘 统计查询' }));
fireEvent.click(screen.getByRole('button', { name: '今日任务 按时间窗复盘 里程统计' }));
expect(window.location.hash.startsWith('#/mileage')).toBe(true);
expect(new URLSearchParams(window.location.hash.split('?')[1] ?? '').get('dateFrom')).toBeTruthy();
cleanup();
@@ -2234,7 +2234,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
cleanup();
await renderDashboard();
fireEvent.click(screen.getAllByRole('button', { name: '统计查询' })[0]);
fireEvent.click(screen.getAllByRole('button', { name: '里程统计' })[0]);
expect(window.location.hash.startsWith('#/mileage')).toBe(true);
expect(new URLSearchParams(window.location.hash.split('?')[1] ?? '').get('dateFrom')).toBeTruthy();
expect(new URLSearchParams(window.location.hash.split('?')[1] ?? '').get('dateTo')).toBeTruthy();
@@ -2270,7 +2270,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
cleanup();
await renderDashboard();
fireEvent.click(screen.getByRole('button', { name: '时间监控 统计查询' }));
fireEvent.click(screen.getByRole('button', { name: '时间监控 里程统计' }));
expect(window.location.hash.startsWith('#/mileage')).toBe(true);
cleanup();
@@ -2318,7 +2318,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
cleanup();
await renderDashboard();
fireEvent.click(screen.getByRole('button', { name: '能力入口 统计查询' }));
fireEvent.click(screen.getByRole('button', { name: '能力入口 里程统计' }));
expect(window.location.hash.startsWith('#/mileage')).toBe(true);
}, 10000);
@@ -2742,7 +2742,7 @@ test('dashboard exposes end-to-end operations workflow entries', async () => {
expect(await screen.findByText('自定义时间窗复盘')).toBeInTheDocument();
expect(screen.getByText('今天车辆轨迹')).toBeInTheDocument();
expect(screen.getByText('历史时间窗')).toBeInTheDocument();
expect(screen.getAllByText('统计查询').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('里程统计').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('告警复盘').length).toBeGreaterThanOrEqual(1);
fireEvent.click(screen.getByRole('button', { name: '时间监控 今天车辆轨迹' }));
@@ -3333,7 +3333,7 @@ test('shows vehicle service result summary on vehicle list filters', async () =>
expect(screen.getByRole('button', { name: '客户车队指挥台 当前交付 2 辆 数据导出' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车队指挥台 轨迹复盘 先选车辆 轨迹回放' })).toBeInTheDocument();
expect(screen.getByText('高德地图车辆服务底座')).toBeInTheDocument();
expect(screen.getByText('用地图把车辆监控、轨迹回放、围栏告警、统计查询和历史导出串成客户能理解的一条服务路径。')).toBeInTheDocument();
expect(screen.getByText('用地图把车辆监控、轨迹回放、围栏告警、里程统计和历史导出串成客户能理解的一条服务路径。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '高德地图车辆服务底座 实时看车 73 在线 打开地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '高德地图车辆服务底座 轨迹复盘 先选车辆 回放轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '高德地图车辆服务底座 围栏告警 13 待处理 告警通知' })).toBeInTheDocument();
@@ -3343,7 +3343,7 @@ test('shows vehicle service result summary on vehicle list filters', async () =>
expect(screen.getByRole('button', { name: '客户车辆服务台 车辆池 181 车辆 找车' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务台 实时地图 73 在线 打开地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务台 轨迹回放 先选车辆 回放' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务台 统计查询 单车后可用 查询统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务台 里程统计 单车后可用 查询里程' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户车辆服务台 告警通知 13 待处理 查看告警' })).toBeInTheDocument();
expect(screen.getByText('车辆资产运营台')).toBeInTheDocument();
expect(screen.getByText('像车队资产系统一样,先判断车辆能不能服务,再进入地图、实时、轨迹、统计、导出和告警。')).toBeInTheDocument();
@@ -3392,14 +3392,14 @@ test('shows vehicle service result summary on vehicle list filters', async () =>
expect(screen.getByText('客户车辆服务交付包')).toBeInTheDocument();
expect(screen.getByText('客户交付')).toBeInTheDocument();
expect(screen.getByText('车辆池包')).toBeInTheDocument();
expect(screen.getByText('把车辆地图、实时监控、轨迹回放、统计查询、告警通知和历史导出放在同一份服务包里,客户不用理解 GB32960、808 或 MQTT 的差异。')).toBeInTheDocument();
expect(screen.getByText('把车辆地图、实时监控、轨迹回放、里程统计、告警通知和历史导出放在同一份服务包里,客户不用理解 GB32960、808 或 MQTT 的差异。')).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();
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.getByText('建议下一步')).toBeInTheDocument();
@@ -3446,7 +3446,7 @@ test('shows vehicle service result summary on vehicle list filters', async () =>
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('服务范围:当前车辆池'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆地图http://localhost:3000/#/map?'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('轨迹回放http://localhost:3000/#/history?tab=location'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('统计查询http://localhost:3000/#/mileage'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程统计http://localhost:3000/#/mileage'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('告警通知http://localhost:3000/#/alert-events?coverage=multi'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('历史数据导出http://localhost:3000/#/history?tab=raw&includeFields=true'));
});
@@ -4198,7 +4198,7 @@ test('shows resolved vehicle service status after topbar search', async () => {
fireEvent.click(screen.getByRole('button', { name: '客户任务 轨迹回放 这段时间怎么跑' }));
expect(window.location.hash).toBe('#/history?keyword=LB9A32A24R0LS1426&protocol=JT808');
fireEvent.click(screen.getByRole('button', { name: '客户任务 统计查询 里程怎么算' }));
fireEvent.click(screen.getByRole('button', { name: '客户任务 里程统计 里程怎么算' }));
expect(window.location.hash).toBe('#/mileage?keyword=LB9A32A24R0LS1426&protocol=JT808');
fireEvent.click(screen.getByRole('button', { name: '客户任务 数据导出 证据怎么给客户' }));
expect(window.location.hash).toBe('#/history-query?keyword=LB9A32A24R0LS1426&protocol=JT808&tab=raw');
@@ -6888,12 +6888,12 @@ test('copies trajectory playback summary from history page', async () => {
expect(screen.getByText('像 Trips History 一样,先锁定车辆和时间,再回放路线、核对里程、导出证据。')).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.getByText('客户时间窗证据链')).toBeInTheDocument();
expect(screen.getByText('同一辆车和同一时间窗,串起实时轨迹、里程核对、历史导出、字段裁剪和告警复盘。')).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();
@@ -6905,7 +6905,7 @@ test('copies trajectory playback summary from history page', async () => {
expect(screen.getByRole('button', { name: '行程复盘摘要 最高速度 58.8 km/h' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '行程复盘摘要 异常提示 1 项' })).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.getByText('按车辆和时间窗复盘每一段行程')).toBeInTheDocument();
@@ -6914,17 +6914,17 @@ test('copies trajectory playback summary from history page', async () => {
expect(screen.getByRole('button', { name: '轨迹回放工作台 轨迹复盘 播放轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '轨迹回放工作台 客户导出 复制交付' })).toBeInTheDocument();
expect(screen.getByText('客户轨迹决策台')).toBeInTheDocument();
expect(screen.getByText('先判断轨迹能否复盘,再进入证据、字段和统计查询')).toBeInTheDocument();
expect(screen.getByText('先判断轨迹能否复盘,再进入证据、字段和里程统计')).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.getAllByRole('button', { name: /复制决策说明/ })[0]);
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【客户轨迹决策说明】'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('决策结论:可复盘,需附异常说明'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('客户复盘路径:'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('4. 最后回到依据:异常点必须打开明细证据、字段裁剪和统计查询复核。'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('4. 最后回到依据:异常点必须打开明细证据、字段裁剪和里程统计复核。'));
fireEvent.click(screen.getByRole('button', { name: /复制轨迹摘要/ }));
@@ -6949,7 +6949,7 @@ test('copies trajectory playback summary from history page', async () => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('历史位置http://localhost:3000/#/history-query?keyword=VIN-HISTORY-SUMMARY&protocol=JT808&tab=location&dateFrom=2026-07-03&dateTo=2026-07-04'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('明细证据http://localhost:3000/#/history-query?keyword=VIN-HISTORY-SUMMARY&protocol=JT808&tab=raw&dateFrom=2026-07-03&dateTo=2026-07-04&includeFields=true'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('字段裁剪http://localhost:3000/#/history-query?keyword=VIN-HISTORY-SUMMARY&protocol=JT808&tab=fields&dateFrom=2026-07-03&dateTo=2026-07-04&includeFields=true'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('统计查询http://localhost:3000/#/mileage?keyword=VIN-HISTORY-SUMMARY&protocol=JT808&dateFrom=2026-07-03&dateTo=2026-07-04'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程统计http://localhost:3000/#/mileage?keyword=VIN-HISTORY-SUMMARY&protocol=JT808&dateFrom=2026-07-03&dateTo=2026-07-04'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆服务http://localhost:3000/#/detail?keyword=VIN-HISTORY-SUMMARY&protocol=JT808'));
fireEvent.click(screen.getByRole('button', { name: /复制客户影响/ }));
@@ -6975,7 +6975,7 @@ test('copies trajectory playback summary from history page', async () => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程速度:区间里程 22.6 km / 最高速度 58.8 km/h'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('当前回放点:点 1/22026-07-03 10:00:0012.5 km/h1,000 km'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('异常判读:断点 1 / 里程回退 0 / 超速 0'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('下一步:建议核对明细证据、字段裁剪、当日统计查询,并确认平台是否存在断链或补发。'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('下一步:建议核对明细证据、字段裁剪、当日里程统计,并确认平台是否存在断链或补发。'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('明细证据http://localhost:3000/#/history-query?keyword=VIN-HISTORY-SUMMARY&protocol=JT808&tab=raw&dateFrom=2026-07-03&dateTo=2026-07-04&includeFields=true'));
});
@@ -7822,7 +7822,7 @@ test('applies protocol from shareable history hash to API requests', async () =>
expect(screen.getByText('当前车辆粤AG18312')).toBeInTheDocument();
expect(screen.getAllByText('来源证据JT808').length).toBeGreaterThan(0);
fireEvent.click(screen.getByRole('button', { name: '顶部统计查询' }));
fireEvent.click(screen.getByRole('button', { name: '顶部里程统计' }));
expect(window.location.hash).toBe('#/mileage?keyword=%E7%B2%A4AG18312&protocol=JT808&dateFrom=2026-07-01&dateTo=2026-07-03');
fireEvent.click(screen.getByRole('button', { name: '顶部数据导出' }));
expect(window.location.hash).toBe('#/history-query?keyword=%E7%B2%A4AG18312&protocol=JT808&tab=raw&dateFrom=2026-07-01&dateTo=2026-07-03');
@@ -7880,7 +7880,7 @@ test('topbar customer time window scopes vehicle service tasks', async () => {
render(<App />);
expect(screen.getByText('客户时间窗')).toBeInTheDocument();
expect(screen.getByText('同步约束地图、轨迹、统计、导出和告警')).toBeInTheDocument();
expect(screen.getByText('同步约束地图、轨迹、里程、导出和告警')).toBeInTheDocument();
expect(screen.getByLabelText('客户时间窗开始日期')).toHaveAttribute('placeholder', 'YYYY-MM-DD');
expect(screen.getByLabelText('客户时间窗结束日期')).toHaveAttribute('placeholder', 'YYYY-MM-DD');
@@ -7890,7 +7890,7 @@ test('topbar customer time window scopes vehicle service tasks', async () => {
fireEvent.click(screen.getByRole('button', { name: '查询车辆' }));
expect(await screen.findByText('粤A时间窗 / VIN-TOPBAR-WINDOW')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: '顶部统计查询' }));
fireEvent.click(screen.getByRole('button', { name: '顶部里程统计' }));
expect(window.location.hash).toBe('#/mileage?keyword=VIN-TOPBAR-WINDOW&protocol=JT808&dateFrom=2026-07-01&dateTo=2026-07-03');
fireEvent.click(screen.getByRole('button', { name: '顶部数据导出' }));
@@ -7970,7 +7970,7 @@ test('topbar customer time window presets support common monitoring ranges', asy
expect(screen.getByLabelText('顶部时间窗开始')).toHaveValue('');
expect(screen.getByLabelText('顶部时间窗结束')).toHaveValue('');
fireEvent.click(screen.getByRole('button', { name: '顶部统计查询' }));
fireEvent.click(screen.getByRole('button', { name: '顶部里程统计' }));
expect(window.location.hash).toBe('#/mileage?keyword=VIN-TOPBAR-PRESET&protocol=GB32960');
});
@@ -8038,7 +8038,7 @@ test('topbar copies customer vehicle service scope links', async () => {
expect(copied).toContain('时间窗2026-06-29 至 2026-07-05');
expect(copied).toContain('实时地图http://localhost:3000/#/map?keyword=VIN-SHARE-SCOPE&protocol=JT808');
expect(copied).toContain('轨迹回放http://localhost:3000/#/history?keyword=VIN-SHARE-SCOPE&protocol=JT808&dateFrom=2026-06-29&dateTo=2026-07-05');
expect(copied).toContain('统计查询http://localhost:3000/#/mileage?keyword=VIN-SHARE-SCOPE&protocol=JT808&dateFrom=2026-06-29&dateTo=2026-07-05');
expect(copied).toContain('里程统计http://localhost:3000/#/mileage?keyword=VIN-SHARE-SCOPE&protocol=JT808&dateFrom=2026-06-29&dateTo=2026-07-05');
expect(copied).toContain('数据导出http://localhost:3000/#/history-query?keyword=VIN-SHARE-SCOPE&protocol=JT808&tab=raw&dateFrom=2026-06-29&dateTo=2026-07-05');
expect(copied).toContain('告警通知http://localhost:3000/#/alert-events?keyword=VIN-SHARE-SCOPE&protocol=JT808&dateFrom=2026-06-29&dateTo=2026-07-05');
});
@@ -8109,7 +8109,7 @@ test('topbar saves and restores reusable customer vehicle views', async () => {
expect(screen.getByLabelText('顶部时间窗开始')).toHaveValue('2026-06-29');
expect(screen.getByLabelText('顶部时间窗结束')).toHaveValue('2026-07-05');
fireEvent.click(screen.getByRole('button', { name: '顶部统计查询' }));
fireEvent.click(screen.getByRole('button', { name: '顶部里程统计' }));
expect(window.location.hash).toBe('#/mileage?keyword=VIN-SAVED-SCOPE&protocol=GB32960&dateFrom=2026-06-29&dateTo=2026-07-05');
});
@@ -8306,20 +8306,20 @@ test('shows parsed field history as a flattened evidence table', async () => {
expect(screen.getAllByText('来源证据GB32960').length).toBeGreaterThan(0);
expect(screen.getByText('当前服务范围VIN-FIELDS-001 / GB32960')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆历史服务台 路线复盘 0 点 查询位置' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆历史服务台 里程核对 - 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆历史服务台 里程核对 - 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆历史服务台 明细证据 1 帧 查看证据' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆历史服务台 字段裁剪 2 字段 字段配置' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆历史服务台 客户导出 可交付 复制交付' })).toBeInTheDocument();
expect(screen.getByText('客户导出中心')).toBeInTheDocument();
expect(screen.getByText('按客户用途选择报表:行程历史、里程对账、字段证据和告警说明。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户导出中心 行程历史 0 点 导出轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户导出中心 里程对账 - 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户导出中心 里程对账 - 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户导出中心 字段证据 2 字段 导出字段' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户导出中心 告警说明 无明显异常 复制说明' })).toBeInTheDocument();
expect(screen.getByText('自定义时间窗监控台')).toBeInTheDocument();
expect(screen.getByText('客户选定车辆和时间范围后,直接判断这个窗口能否用于轨迹复盘、统计核对、历史证据导出和告警说明。')).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.getByText('客户数据交付台')).toBeInTheDocument();
@@ -8327,7 +8327,7 @@ test('shows parsed field history as a flattened evidence table', async () => {
expect(screen.getByText('按车辆和时间窗复盘每一段行程')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '轨迹回放工作台 明细证据 查看证据' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '轨迹回放工作台 客户导出 复制交付' })).toBeInTheDocument();
expect(screen.getByText('面向客户的数据导出以车辆服务为中心同一个筛选范围可以交付轨迹报告、位置历史、明细证据、字段裁剪、CSV 文件和统计查询。')).toBeInTheDocument();
expect(screen.getByText('面向客户的数据导出以车辆服务为中心同一个筛选范围可以交付轨迹报告、位置历史、明细证据、字段裁剪、CSV 文件和里程统计。')).toBeInTheDocument();
expect(screen.getByText('先锁定车辆和时间窗,再选择交付物并导出')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户数据交付台 选择范围 调整筛选' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户数据交付台 位置历史 导出位置' })).toBeInTheDocument();
@@ -8340,7 +8340,7 @@ test('shows parsed field history as a flattened evidence table', async () => {
expect(screen.getByText('客户历史问题')).toBeInTheDocument();
expect(screen.getByText('用客户语言回答路线、里程、异常和导出问题')).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();
@@ -8382,7 +8382,7 @@ test('shows parsed field history as a flattened evidence table', async () => {
expect(screen.getByText('客户交付物清单')).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();
expect(screen.getByRole('button', { name: '客户交付清单 质量提示 复制清单' })).toBeInTheDocument();
@@ -8391,7 +8391,7 @@ test('shows parsed field history as a flattened evidence table', async () => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【客户数据交付封面包】'));
});
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付主题VIN-FIELDS-001 / GB32960 / 2026-07-03 至 2026-07-04'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付物:轨迹报告 / 位置历史 CSV / 明细证据 CSV / 字段裁剪 CSV / 统计查询链接 / 质量提示'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付物:轨迹报告 / 位置历史 CSV / 明细证据 CSV / 字段裁剪 CSV / 里程统计链接 / 质量提示'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('当前证据:位置 0 条 / 有效坐标 0 点 / 明细 1 帧 / 字段 2 个'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('建议动作:优先导出字段证据,并补查轨迹位置。'));
fireEvent.click(screen.getByRole('button', { name: /复制导出向导包/ }));
@@ -8405,14 +8405,14 @@ test('shows parsed field history as a flattened evidence table', async () => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('字段裁剪http://localhost:3000/#/history-query?keyword=VIN-FIELDS-001&protocol=GB32960&tab=fields&dateFrom=2026-07-03&dateTo=2026-07-04&includeFields=true&fields=gb32960.vehicle.speed_kmh'));
fireEvent.click(screen.getByRole('button', { name: /复制交付清单/ }));
await waitFor(() => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付物:轨迹报告 / 位置历史 / 统计查询 / 明细证据 / 字段裁剪 / 质量提示'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付物:轨迹报告 / 位置历史 / 里程统计 / 明细证据 / 字段裁剪 / 质量提示'));
});
fireEvent.click(screen.getByRole('button', { name: '报表交付模板 周期交付计划 复制计划' }));
await waitFor(() => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【历史数据周期交付计划】'));
});
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('推荐频率:日报用于客户复盘,周报用于客户对账,临时导出用于问题解释。'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付内容:轨迹报告 / 位置历史 CSV / 明细证据 CSV / 字段裁剪 CSV / 统计查询链接 / 质量提示。'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('交付内容:轨迹报告 / 位置历史 CSV / 明细证据 CSV / 字段裁剪 CSV / 里程统计链接 / 质量提示。'));
fireEvent.click(screen.getByRole('button', { name: '保存报表视图 当前筛选 VIN-FIELDS-001 保存视图' }));
await waitFor(() => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【保存报表视图】'));
@@ -8691,7 +8691,7 @@ test('flags trajectory playback anomalies for gap mileage and speed review', asy
expect(screen.getByText('2 km')).toBeInTheDocument();
expect(screen.getByText('速度异常')).toBeInTheDocument();
expect(screen.getAllByText('132 km/h').length).toBeGreaterThan(0);
expect(screen.getByText('建议核对明细证据和当日统计查询')).toBeInTheDocument();
expect(screen.getByText('建议核对明细证据和当日里程统计')).toBeInTheDocument();
});
test('opens amap route from trajectory playback workspace', async () => {
@@ -9337,7 +9337,7 @@ test('updates mileage hash when mileage filters are submitted', async () => {
render(<App />);
await screen.findByRole('heading', { name: '统计查询' });
await screen.findByRole('heading', { name: '里程统计' });
fireEvent.change(screen.getByPlaceholderText('VIN / 车牌 / 手机号 / OEM'), { target: { value: '粤AG18312' } });
fireEvent.click(screen.getByText('全部数据通道'));
fireEvent.click(await screen.findByText('JT808'));
@@ -9738,7 +9738,7 @@ test('shows mileage anomaly action guidance', async () => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆服务http://localhost:3000/#/detail?keyword=VIN-MILEAGE-ANOMALY&protocol=GB32960'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('轨迹证据http://localhost:3000/#/history?keyword=VIN-MILEAGE-ANOMALY&protocol=GB32960&dateFrom=2026-07-03&dateTo=2026-07-04'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('历史明细http://localhost:3000/#/history-query?keyword=VIN-MILEAGE-ANOMALY&protocol=GB32960&tab=raw&dateFrom=2026-07-03&dateTo=2026-07-04&includeFields=true'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('统计查询http://localhost:3000/#/mileage?keyword=VIN-MILEAGE-ANOMALY&protocol=GB32960&dateFrom=2026-07-03&dateTo=2026-07-04'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程统计http://localhost:3000/#/mileage?keyword=VIN-MILEAGE-ANOMALY&protocol=GB32960&dateFrom=2026-07-03&dateTo=2026-07-04'));
});
test('shows mileage statistics workspace with trend source and definition', async () => {
@@ -9841,7 +9841,7 @@ test('shows mileage statistics workspace with trend source and definition', asyn
expect(screen.getAllByText('100%').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('闭合校验').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('0 km').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('统计口径').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('里程口径').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText((content) => content.includes('区间总值应等于各日里程之和'))).toBeInTheDocument();
});
@@ -9958,7 +9958,7 @@ test('shows vehicle-first statistics domains for one vehicle service', async ()
render(<App />);
expect(await screen.findByText('客户统计查询')).toBeInTheDocument();
expect(await screen.findByText('客户里程统计')).toBeInTheDocument();
expect(screen.getByText('客户里程对账总控')).toBeInTheDocument();
expect(screen.getByText('把区间里程、每日闭合、轨迹证明、异常通知和报表导出收敛成客户可验收的对账链路。')).toBeInTheDocument();
expect(screen.getByText('里程报表交付旅程')).toBeInTheDocument();
@@ -10002,11 +10002,11 @@ test('shows vehicle-first statistics domains for one vehicle service', async ()
expect(screen.getByRole('button', { name: '客户里程统计工作台 历史导出 3 条 导出明细' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户里程统计工作台 告警通知 1 离线 在线态势' })).toBeInTheDocument();
expect(screen.getByText('先定车辆和时间范围,再判断里程能否交付')).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();
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.getByText('客户里程对账台')).toBeInTheDocument();
expect(screen.getByText('用同一辆车和同一时间窗完成区间里程、日报闭合、轨迹证据、告警通知和报表导出。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户里程对账台 区间里程 210 km 复制摘要' })).toBeInTheDocument();
@@ -10016,7 +10016,7 @@ test('shows vehicle-first statistics domains for one vehicle service', async ()
expect(screen.getByRole('button', { name: '客户里程对账台 报表导出 3 条 导出CSV' })).toBeInTheDocument();
expect(screen.getByText('客户里程交付导航')).toBeInTheDocument();
expect(screen.getByText('把里程统计变成客户能看懂的交付路径:先确认口径,再回放轨迹,最后导出明细和结论。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户里程交付导航 确认统计口径 复制统计摘要' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户里程交付导航 确认里程口径 复制统计摘要' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户里程交付导航 回放里程轨迹 轨迹复核' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户里程交付导航 导出明细证据 导出CSV' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户里程交付导航 发送交付结论 复制交付包' })).toBeInTheDocument();
@@ -10063,7 +10063,7 @@ test('shows vehicle-first statistics domains for one vehicle service', async ()
expect(screen.getByRole('button', { name: '复制影响范围' })).toBeInTheDocument();
expect(screen.getByText('影响待复核')).toBeInTheDocument();
expect(screen.getByText('3 辆车')).toBeInTheDocument();
expect(screen.getByText('当前筛选会影响 6 条里程记录、210 km 统计口径和 1 辆离线车辆判断。')).toBeInTheDocument();
expect(screen.getByText('当前筛选会影响 6 条里程记录、210 km 里程口径和 1 辆离线车辆判断。')).toBeInTheDocument();
expect(screen.getByText('里程服务任务板')).toBeInTheDocument();
expect(screen.getAllByText('发布判断').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('区间复核')).toBeInTheDocument();
@@ -10133,7 +10133,7 @@ test('shows vehicle-first statistics domains for one vehicle service', async ()
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆范围VIN-STATS-SERVICE'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('累计里程210 km'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('发布判断:复核后发布'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('统计口径:日里程按首末总里程差值计算,区间总值应等于每日里程之和'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程口径:日里程按首末总里程差值计算,区间总值应等于每日里程之和'));
expect(await screen.findByText('在线状态明细')).toBeInTheDocument();
expect(await screen.findByText('VIN-STATS-SERVICE-OFFLINE')).toBeInTheDocument();
expect(screen.getByText('粤A离线1')).toBeInTheDocument();
@@ -10220,13 +10220,13 @@ test('copies mileage statistics summary for operations reporting', async () => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('当前页里程140 km'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('异常记录1'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('最大单日粤A统计2 / 2026-07-02 / 100 km'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('统计口径:区间总值等于各日里程之和'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('统计查询http://localhost:3000/#/mileage?keyword=VIN-MILEAGE-COPY&protocol=JT808&dateFrom=2026-07-01&dateTo=2026-07-03'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程口径:区间总值等于各日里程之和'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程统计http://localhost:3000/#/mileage?keyword=VIN-MILEAGE-COPY&protocol=JT808&dateFrom=2026-07-01&dateTo=2026-07-03'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆服务http://localhost:3000/#/detail?keyword=VIN-MILEAGE-COPY&protocol=JT808'));
fireEvent.click(screen.getByRole('button', { name: '复制BI发布口径' }));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【BI里程发布口径】'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('发布结论:需复核后发布'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('统计口径:日里程按首末总里程差值计算,区间总值等于每日里程之和'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程口径:日里程按首末总里程差值计算,区间总值等于每日里程之和'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('闭合状态:分页抽样'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('记录覆盖率50%'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('异常记录1'));
@@ -10474,7 +10474,7 @@ test('opens same-day mileage statistics from history location row', async () =>
expect((await screen.findAllByText('VIN-HISTORY-MILEAGE')).length).toBeGreaterThan(0);
const locationRow = screen.getByRole('row', { name: /VIN-HISTORY-MILEAGE/ });
fireEvent.click(within(locationRow).getByRole('button', { name: '统计查询' }));
fireEvent.click(within(locationRow).getByRole('button', { name: '里程统计' }));
await waitFor(() => {
expect(window.location.hash).toBe('#/mileage?keyword=VIN-HISTORY-MILEAGE&protocol=JT808&dateFrom=2026-07-03&dateTo=2026-07-04');
@@ -10765,12 +10765,12 @@ test('opens same-day mileage statistics from raw history row', async () => {
expect((await screen.findAllByText('raw-jt808-mileage-001')).length).toBeGreaterThanOrEqual(1);
const rawRow = screen.getByRole('row', { name: /raw-jt808-mileage-001/ });
fireEvent.click(within(rawRow).getByRole('button', { name: '统计查询' }));
fireEvent.click(within(rawRow).getByRole('button', { name: '里程统计' }));
await waitFor(() => {
expect(window.location.hash).toBe('#/mileage?keyword=VIN-RAW-MILEAGE&protocol=JT808&dateFrom=2026-07-03&dateTo=2026-07-04');
});
expect(await screen.findByRole('heading', { name: '统计查询' })).toBeInTheDocument();
expect(await screen.findByRole('heading', { name: '里程统计' })).toBeInTheDocument();
});
test('opens current vehicle service from history header with current source evidence', async () => {
@@ -11354,7 +11354,7 @@ test('frames realtime page as one vehicle service with source evidence', async (
expect(screen.getByText('客户打开实时监控时,直接围绕选中车辆查看在线、位置、里程、新鲜度,并进入轨迹、统计、历史导出和告警通知。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '实时单车服务快照 车辆服务 粤ART002 车辆档案' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '实时单车服务快照 轨迹回放 更新超时 打开轨迹' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '实时单车服务快照 统计查询 119925 km 查里程' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '实时单车服务快照 里程统计 119925 km 查里程' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '实时单车服务快照 历史导出 GB32960 导出证据' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '实时单车服务快照 告警通知 服务正常 查看告警' })).toBeInTheDocument();
expect(screen.getAllByText('定位有效').length).toBeGreaterThan(0);
@@ -11388,7 +11388,7 @@ test('frames realtime page as one vehicle service with source evidence', async (
expect(screen.getByText('把同一辆车、同一时间窗贯穿到轨迹、里程、历史导出和告警说明,避免客户跨页面重复筛选。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控任务台 1 锁定车辆 粤ART002 已锁定' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控任务台 2 轨迹复盘 1 天窗口 轨迹回放' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控任务台 3 里程核对 119925 km 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控任务台 3 里程核对 119925 km 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控任务台 4 历史导出 GB32960 导出证据' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗监控任务台 5 告警闭环 服务正常 告警复盘' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '时间窗复盘 轨迹回放 打开轨迹' })).toBeInTheDocument();
@@ -11601,7 +11601,7 @@ test('shows realtime freshness status for recently updated and stale vehicles',
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.getByRole('button', { name: '车队服务旅程条 1 实时找车 1 在线' })).toBeInTheDocument();
@@ -11939,7 +11939,7 @@ test('copies realtime operations summary from realtime page', async () => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆覆盖GB32960在线 1/1实时 1/1JT808在线 1/2实时 2/2YUTONG_MQTT在线 0/1实时 1/1'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('实时入口http://localhost:3000/#/realtime?protocol=JT808&online=online'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆服务http://localhost:3000/#/detail?keyword=VIN-RT-SUMMARY-003&protocol=JT808'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('统计查询http://localhost:3000/#/mileage?keyword=VIN-RT-SUMMARY-003&protocol=JT808'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('里程统计http://localhost:3000/#/mileage?keyword=VIN-RT-SUMMARY-003&protocol=JT808'));
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('历史查询http://localhost:3000/api/history/raw-frames?protocol=JT808&vin=VIN-RT-SUMMARY-003&limit=20&includeFields=true'));
fireEvent.click(screen.getByRole('button', { name: '实时筛选 需要关注 2' }));
expect(window.location.hash).toBe('#/realtime?protocol=JT808&serviceStatus=degraded&online=online');
@@ -13510,13 +13510,13 @@ test('switches vehicle detail to a source from the source matrix', async () => {
expect(screen.getByText('数据通道归并矩阵')).toBeInTheDocument();
expect(screen.getByText('主实时通道')).toBeInTheDocument();
expect(screen.getAllByText('定位数据').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('统计口径').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('里程口径').length).toBeGreaterThanOrEqual(1);
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(screen.getByText('车辆服务角色')).toBeInTheDocument();
expect(screen.getAllByText('主数据通道').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('在线数据通道').length).toBeGreaterThanOrEqual(1);
@@ -13606,7 +13606,7 @@ test('shows unified service overview on vehicle detail', async () => {
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();
expect(screen.getByText('单车服务任务台')).toBeInTheDocument();
expect(screen.getByText('单车服务处理清单')).toBeInTheDocument();
@@ -13620,12 +13620,12 @@ test('shows unified service overview on vehicle detail', async () => {
expect(screen.getAllByText('轨迹回放').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('历史数据').length).toBeGreaterThan(0);
expect(screen.getByText('告警处置')).toBeInTheDocument();
expect(screen.getAllByText('统计复核').length).toBeGreaterThan(0);
expect(screen.getAllByText('里程复核').length).toBeGreaterThan(0);
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();
expect(screen.getByText('车辆在线状态、最新时间、有效坐标均可解释。')).toBeInTheDocument();
expect(screen.getByText('2026-07-03 20:12:10')).toBeInTheDocument();
expect(screen.getAllByText('12 条历史').length).toBeGreaterThanOrEqual(1);
@@ -13637,7 +13637,7 @@ test('shows unified service overview on vehicle detail', async () => {
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: '单车服务任务台 历史数据 查看历史数据' }));
expect(window.location.hash).toBe('#/history-query?keyword=VIN001&tab=raw');
@@ -14130,12 +14130,12 @@ test('copies vehicle service diagnostic summary', async () => {
expect(screen.getByText('业务可用性')).toBeInTheDocument();
expect(await screen.findByText('车辆服务结论')).toBeInTheDocument();
expect(screen.getByText('单车 Live View')).toBeInTheDocument();
expect(screen.getByText('客户打开一辆车时先看当前位置、最后上报、速度、SOC、总里程和告警再进入轨迹回放、统计查询、数据导出和告警闭环。')).toBeInTheDocument();
expect(screen.getByText('客户打开一辆车时先看当前位置、最后上报、速度、SOC、总里程和告警再进入轨迹回放、里程统计、数据导出和告警闭环。')).toBeInTheDocument();
expect(screen.getByText('客户单车操作台')).toBeInTheDocument();
expect(screen.getByText('围绕这辆车直接完成看车、回放、统计、导出和告警通知。')).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户单车操作台 看当前位置 113.2, 23.1 实时地图' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户单车操作台 回放轨迹 12 条 轨迹回放' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户单车操作台 核对里程 3 条 统计查询' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户单车操作台 核对里程 3 条 里程统计' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户单车操作台 导出证据 34 条 历史导出' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '客户单车操作台 告警通知 1 项 告警闭环' })).toBeInTheDocument();
expect(screen.getByText('当前位置')).toBeInTheDocument();
@@ -14147,22 +14147,22 @@ test('copies vehicle service diagnostic summary', async () => {
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.getByText('客户常问')).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();
expect(screen.getByRole('button', { name: '单车客户常问 是否需要通知处理? 告警通知' })).toBeInTheDocument();
expect(screen.getByText('车辆服务档案总览')).toBeInTheDocument();
expect(screen.getByText('单车客户服务交付包')).toBeInTheDocument();
expect(screen.getByText('面向客户交付时,以车辆为主对象提供实时监控、轨迹回放、历史数据查询、告警通知和统计查询,协议来源只作为可追溯证据。')).toBeInTheDocument();
expect(screen.getByText('面向客户交付时,以车辆为主对象提供实时监控、轨迹回放、历史数据查询、告警通知和里程统计,协议来源只作为可追溯证据。')).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();
expect(screen.getAllByText('单车时间窗交付').length).toBeGreaterThan(0);
expect(screen.getByText('把同一辆车和同一段时间带入轨迹回放、里程统计、历史导出和告警通知,客户复盘时不需要跨页面重复输入。')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: /复制归一摘要/ }));
@@ -14200,12 +14200,12 @@ test('copies vehicle service diagnostic summary', async () => {
const customerPackageCopied = String(writeText.mock.lastCall?.[0] ?? '');
expect(customerPackageCopied).toContain('【单车客户服务交付包】');
expect(customerPackageCopied).toContain('车辆粤A诊断1 / VIN-SUMMARY-001');
expect(customerPackageCopied).toContain('平台能力:实时监控 / 轨迹回放 / 历史数据查询 / 告警通知 / 统计查询');
expect(customerPackageCopied).toContain('平台能力:实时监控 / 轨迹回放 / 历史数据查询 / 告警通知 / 里程统计');
expect(customerPackageCopied).toContain('实时监控http://localhost:3000/#/realtime?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(customerPackageCopied).toContain('轨迹回放http://localhost:3000/#/history?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(customerPackageCopied).toContain('历史数据查询http://localhost:3000/#/history-query?keyword=VIN-SUMMARY-001&protocol=JT808&tab=raw&includeFields=true');
expect(customerPackageCopied).toContain('告警通知http://localhost:3000/#/alert-events?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(customerPackageCopied).toContain('统计查询http://localhost:3000/#/mileage?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(customerPackageCopied).toContain('里程统计http://localhost:3000/#/mileage?keyword=VIN-SUMMARY-001&protocol=JT808');
fireEvent.click(screen.getByRole('button', { name: /复制诊断摘要/ }));
await waitFor(() => {
@@ -14228,7 +14228,7 @@ test('copies vehicle service diagnostic summary', async () => {
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/#/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(() => {
@@ -14250,7 +14250,7 @@ test('copies vehicle service diagnostic summary', async () => {
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/#/mileage?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(operationsCopied).toContain('里程统计http://localhost:3000/#/mileage?keyword=VIN-SUMMARY-001&protocol=JT808');
fireEvent.click(screen.getByRole('button', { name: '复制处理清单' }));
await waitFor(() => {
@@ -14264,10 +14264,10 @@ test('copies vehicle service diagnostic summary', async () => {
expect(runbookCopied).toContain('2. 回放轨迹断点');
expect(runbookCopied).toContain('3. 查询历史数据');
expect(runbookCopied).toContain('4. 处理告警闭环');
expect(runbookCopied).toContain('5. 复核统计口径');
expect(runbookCopied).toContain('5. 复核里程口径');
expect(runbookCopied).toContain('验收:车辆在线状态、最新时间、有效坐标均可解释。');
expect(runbookCopied).toContain('告警事件http://localhost:3000/#/alert-events?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(runbookCopied).toContain('统计查询http://localhost:3000/#/mileage?keyword=VIN-SUMMARY-001&protocol=JT808');
expect(runbookCopied).toContain('里程统计http://localhost:3000/#/mileage?keyword=VIN-SUMMARY-001&protocol=JT808');
fireEvent.change(screen.getByPlaceholderText('单车开始日期'), { target: { value: '2026-07-01' } });
fireEvent.change(screen.getByPlaceholderText('单车结束日期'), { target: { value: '2026-07-03' } });