feat(platform): streamline dashboard for vehicle service
This commit is contained in:
@@ -424,9 +424,9 @@ test('shows vehicle service status distribution on dashboard', async () => {
|
||||
|
||||
render(<App />);
|
||||
|
||||
expect(await screen.findByText('车辆服务状态')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('来源不完整').length).toBeGreaterThan(0);
|
||||
expect(screen.getByText('39')).toBeInTheDocument();
|
||||
expect(await screen.findByText('车辆服务覆盖')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('服务状态').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getByText('质量问题预览')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('dashboard renders vehicle service summary metrics', async () => {
|
||||
@@ -495,18 +495,12 @@ test('dashboard renders vehicle service summary metrics', async () => {
|
||||
|
||||
expect(await screen.findByText('总车辆')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('1,033').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getByText('单源车辆')).toBeInTheDocument();
|
||||
expect(screen.getByText('391')).toBeInTheDocument();
|
||||
expect(screen.getByText('多源车辆')).toBeInTheDocument();
|
||||
expect(screen.getByText('181')).toBeInTheDocument();
|
||||
expect(screen.getByText('暂无来源车辆')).toBeInTheDocument();
|
||||
expect(screen.getByText('461')).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();
|
||||
expect(screen.getByText('366')).toBeInTheDocument();
|
||||
expect(screen.getByText('来源证据在线分布')).toBeInTheDocument();
|
||||
expect(screen.getByText('YUTONG_MQTT')).toBeInTheDocument();
|
||||
expect(screen.getByText('0%')).toBeInTheDocument();
|
||||
expect(screen.queryByText('NaN%')).not.toBeInTheDocument();
|
||||
expect(fetchMock).toHaveBeenCalledWith('/api/vehicle-service/summary', undefined);
|
||||
});
|
||||
@@ -593,9 +587,9 @@ test('dashboard presents one vehicle service operating posture', async () => {
|
||||
|
||||
render(<App />);
|
||||
|
||||
expect(await screen.findByText('统一车辆服务入口')).toBeInTheDocument();
|
||||
expect(await screen.findByText('车辆服务入口')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('208 / 1,033 在线').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getByText('181 多源覆盖')).toBeInTheDocument();
|
||||
expect(screen.getByText('今日活跃 4')).toBeInTheDocument();
|
||||
expect(screen.getByText('7 告警事件')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -792,24 +786,24 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
|
||||
|
||||
await renderDashboard();
|
||||
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.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.getByText('数据流转作业链')).toBeInTheDocument();
|
||||
expect(screen.getByText('车联网场景导航')).toBeInTheDocument();
|
||||
expect(screen.getByText('高德 Web JS')).toBeInTheDocument();
|
||||
expect(screen.getByText('服务端 API')).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.getAllByText('历史证据').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getByText('运营闭环')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('已配置').length).toBeGreaterThanOrEqual(2);
|
||||
expect(screen.getByText('已启用')).toBeInTheDocument();
|
||||
expect(screen.getByText('未暴露')).toBeInTheDocument();
|
||||
@@ -822,7 +816,6 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
|
||||
expect(screen.getByText('告警事件与通知')).toBeInTheDocument();
|
||||
expect(screen.getByText('区间闭合复核')).toBeInTheDocument();
|
||||
expect(screen.getByText('高德轨迹证据')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('Kafka Lag 0').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getByText('1,033 车辆口径')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('在线 208').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getAllByText('在线态势 208').length).toBeGreaterThanOrEqual(1);
|
||||
@@ -840,9 +833,6 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('高德地图:Web JS 已配置;服务端 API 已配置;安全代理 已启用;安全码未暴露'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('1. 实时监控'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('SLA:目标 0-1 秒内进入实时视图'));
|
||||
fireEvent.click(screen.getByRole('button', { name: '复制流转图' }));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【车辆数据中台数据流转图】'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('03. 实时投影 / Redis KV'));
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '客户工作流 实时车辆地图' }));
|
||||
expect(window.location.hash).toBe('#/map?online=online');
|
||||
@@ -867,14 +857,14 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
|
||||
cleanup();
|
||||
|
||||
await renderDashboard();
|
||||
fireEvent.click(screen.getByRole('button', { name: '数据流转 实时投影' }));
|
||||
expect(window.location.hash).toBe('#/realtime?online=online');
|
||||
fireEvent.click(screen.getByRole('button', { name: '时间监控 历史时间窗' }));
|
||||
expect(window.location.hash.startsWith('#/history-query')).toBe(true);
|
||||
expect(new URLSearchParams(window.location.hash.split('?')[1] ?? '').get('includeFields')).toBe('true');
|
||||
cleanup();
|
||||
|
||||
await renderDashboard();
|
||||
fireEvent.click(screen.getByRole('button', { name: '数据流转 统一解析' }));
|
||||
expect(window.location.hash.startsWith('#/history-query')).toBe(true);
|
||||
expect(new URLSearchParams(window.location.hash.split('?')[1] ?? '').get('includeFields')).toBe('true');
|
||||
fireEvent.click(screen.getByRole('button', { name: '时间监控 区间里程' }));
|
||||
expect(window.location.hash.startsWith('#/mileage')).toBe(true);
|
||||
cleanup();
|
||||
|
||||
await renderDashboard();
|
||||
@@ -1172,7 +1162,7 @@ test('dashboard shows vehicle service action queue', async () => {
|
||||
|
||||
test.each([
|
||||
{ buttonName: '查看在线车辆', expectedHash: '#/vehicles?online=online' },
|
||||
{ buttonName: '查看多源车辆', expectedHash: '#/vehicles?coverage=multi' },
|
||||
{ buttonName: '实时地图', expectedHash: '#/map?online=online' },
|
||||
{ buttonName: '查看告警事件', expectedHash: '#/alert-events' }
|
||||
])('dashboard posture opens %s', async ({ buttonName, expectedHash }) => {
|
||||
window.history.replaceState(null, '', '/#/dashboard');
|
||||
@@ -1335,18 +1325,16 @@ test('dashboard exposes end-to-end operations workflow entries', async () => {
|
||||
|
||||
render(<App />);
|
||||
|
||||
expect(await screen.findByText('全链路值班闭环')).toBeInTheDocument();
|
||||
expect(screen.getByText('接入巡检')).toBeInTheDocument();
|
||||
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(await screen.findByText('自定义时间监控')).toBeInTheDocument();
|
||||
expect(screen.getByText('今天车辆轨迹')).toBeInTheDocument();
|
||||
expect(screen.getByText('历史时间窗')).toBeInTheDocument();
|
||||
expect(screen.getByText('区间里程')).toBeInTheDocument();
|
||||
expect(screen.getByText('告警复盘')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '闭环入口 轨迹复盘' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: '时间监控 今天车辆轨迹' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(window.location.hash).toBe('#/history?keyword=LB9A32A24R0LS1426');
|
||||
expect(window.location.hash.startsWith('#/history')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1459,7 +1447,7 @@ test('dashboard surfaces highest priority quality issue with evidence shortcuts'
|
||||
render(<App />);
|
||||
|
||||
expect(await screen.findByText('重点车辆服务')).toBeInTheDocument();
|
||||
expect(screen.getByText('把协议来源作为证据,把实时、轨迹、RAW、统计和告警集中到同一辆车处理。')).toBeInTheDocument();
|
||||
expect(screen.getByText('把数据来源作为证据,把实时、轨迹、RAW、统计和告警集中到同一辆车处理。')).toBeInTheDocument();
|
||||
expect(screen.getByText('实时证据')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('轨迹证据').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getByText('告警证据')).toBeInTheDocument();
|
||||
@@ -1611,7 +1599,6 @@ test('dashboard copies highest priority quality issue notification text', async
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('在线车辆:88 / 1,033'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('今日活跃:96'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('今日帧量:1,286,320'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('Kafka Lag:0'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('最高告警:P0 VIN 缺失 / 粤A告警1 / 13307795425 / 2026-07-03 20:12:10'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('实时监控:http://localhost:3000/#/realtime?online=online'));
|
||||
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('实时地图:http://localhost:3000/#/map?online=online'));
|
||||
@@ -1695,11 +1682,11 @@ test('dashboard keeps core vehicle service metrics when preview requests fail',
|
||||
|
||||
expect(await screen.findByText('总车辆')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('1,033').length).toBeGreaterThanOrEqual(1);
|
||||
expect(screen.getByText('单源车辆')).toBeInTheDocument();
|
||||
expect(screen.getByText('391')).toBeInTheDocument();
|
||||
expect(screen.getByText('今日活跃')).toBeInTheDocument();
|
||||
expect(screen.getByText('告警车辆')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('opens dashboard coverage from missing source distribution', async () => {
|
||||
test('opens dashboard coverage from service action queue', async () => {
|
||||
window.history.replaceState(null, '', '/#/dashboard');
|
||||
const fetchMock = vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => {
|
||||
const path = String(input);
|
||||
@@ -1755,14 +1742,11 @@ test('opens dashboard coverage from missing source distribution', async () => {
|
||||
|
||||
render(<App />);
|
||||
|
||||
expect(await screen.findByText('缺失车辆')).toBeInTheDocument();
|
||||
expect(screen.getByText('983')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByRole('button', { name: '查看缺 YUTONG_MQTT' }));
|
||||
fireEvent.click(await screen.findByRole('button', { name: '补齐 YUTONG_MQTT 来源 983' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('missingProtocol=YUTONG_MQTT'), undefined);
|
||||
});
|
||||
expect(screen.getByText('当前筛选:缺 YUTONG_MQTT')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('opens vehicle list filtered by service summary KPI', async () => {
|
||||
@@ -1811,12 +1795,12 @@ test('opens vehicle list filtered by service summary KPI', async () => {
|
||||
|
||||
render(<App />);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: /暂无来源车辆/ }));
|
||||
fireEvent.click(await screen.findByRole('button', { name: /告警车辆/ }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('/api/vehicles/coverage?limit=20&offset=0&serviceStatus=no_data'), undefined);
|
||||
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('/api/vehicles/coverage?limit=20&offset=0&serviceStatus=degraded'), undefined);
|
||||
});
|
||||
expect(window.location.hash).toBe('#/vehicles?serviceStatus=no_data');
|
||||
expect(window.location.hash).toBe('#/vehicles?serviceStatus=degraded');
|
||||
});
|
||||
|
||||
test('shows vehicle service result summary on vehicle list filters', async () => {
|
||||
@@ -3362,7 +3346,10 @@ test('opens dashboard coverage from service status distribution', async () => {
|
||||
|
||||
render(<App />);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: '查看来源不完整' }));
|
||||
expect(await screen.findByText('车辆服务覆盖')).toBeInTheDocument();
|
||||
fireEvent.click(screen.getByTestId('dashboard-service-status-filter'));
|
||||
fireEvent.click(await screen.findByText('来源不完整'));
|
||||
fireEvent.click(screen.getByRole('button', { name: '筛选' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('serviceStatus=degraded'), undefined);
|
||||
|
||||
Reference in New Issue
Block a user