From 74ccddb1a7f68eef6d5e7d1c79792f50a38052aa Mon Sep 17 00:00:00 2001 From: lingniu Date: Sun, 5 Jul 2026 00:31:58 +0800 Subject: [PATCH] feat(platform): refine vehicle operations language --- .../apps/web/src/layout/AppShell.tsx | 12 +++--- .../apps/web/src/pages/Realtime.tsx | 36 ++++++++-------- .../apps/web/src/pages/Vehicles.tsx | 8 ++-- .../apps/web/src/test/App.test.tsx | 42 +++++++++---------- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/vehicle-data-platform/apps/web/src/layout/AppShell.tsx b/vehicle-data-platform/apps/web/src/layout/AppShell.tsx index cf6d1f24..5c7f8201 100644 --- a/vehicle-data-platform/apps/web/src/layout/AppShell.tsx +++ b/vehicle-data-platform/apps/web/src/layout/AppShell.tsx @@ -30,11 +30,11 @@ const navGroups = [ ] }, { - title: '查询分析', + title: '轨迹与统计', items: [ { itemKey: 'history', text: '轨迹回放', icon: }, - { itemKey: 'history-query', text: '历史查询', icon: }, - { itemKey: 'mileage', text: '统计查询', icon: } + { itemKey: 'history-query', text: '数据导出', icon: }, + { itemKey: 'mileage', text: '里程统计', icon: } ] }, { @@ -133,7 +133,7 @@ export function AppShell({ 车辆服务中台 - 一车一服务 / 多源归并 + 地图监控 / 轨迹回放 / 里程统计
@@ -180,8 +180,8 @@ export function AppShell({ - - + + ) : 服务状态稳定} {staleCount > 0 ? 核对超时车辆 {staleCount.toLocaleString()} : 实时新鲜} @@ -822,16 +822,16 @@ export function Realtime({
-
协议地图覆盖
+
车辆覆盖概览
{sourceCoverageRows.length === 0 ? ( - 当前页暂无协议来源。 + 当前页暂无车辆数据通道。 ) : sourceCoverageRows.map((item) => ( - +
0 ? 'orange' as const : 'green' as const }, - { label: '降级服务', value: degradedCount.toLocaleString(), color: degradedCount > 0 ? 'orange' as const : 'green' as const }, - { label: '来源类型', value: primaryProtocols.size.toLocaleString(), color: 'blue' as const } + { label: '需要关注', value: degradedCount.toLocaleString(), color: degradedCount > 0 ? 'orange' as const : 'green' as const }, + { label: '数据通道', value: primaryProtocols.size.toLocaleString(), color: 'blue' as const } ].map((item) => (
{item.label} @@ -885,7 +885,7 @@ export function Realtime({
))} - 高德 Web JS Key 和安全密钥通过运行环境配置,前端只读取公开 Key;安全密钥后续走服务端代理,避免明文下发。 + 地图用于观察车辆在线、定位新鲜度和异常车辆分布;内部接入状态由系统运维页单独承接。 {selectedMapRow ? (
@@ -915,7 +915,7 @@ export function Realtime({
) : null}
-
地图接入状态
+
地图能力状态
{mapIntegrationRows.map((item) => (
@@ -927,7 +927,7 @@ export function Realtime({ ))}
-
多来源一致性检查
+
车辆数据一致性检查
{sourceIssueRows.length === 0 ? ( 当前页车辆来源一致 ) : ( diff --git a/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx b/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx index ecb270cb..b3fc4aff 100644 --- a/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx @@ -120,7 +120,7 @@ const vehicleExportColumns: CsvColumn[] = [ { title: 'OEM', value: (row) => row.oem }, { title: '来源', value: (row) => row.protocols?.join('|') }, { title: '缺失来源', value: (row) => row.missingProtocols?.join('|') }, - { title: '来源覆盖', value: (row) => sourceEvidenceText(row) }, + { title: '车辆覆盖', value: (row) => sourceEvidenceText(row) }, { title: '服务状态', value: (row) => vehicleServiceStatus(row).label }, { title: '诊断摘要', value: (row) => sourceDiagnosisText(row) }, { title: '档案完整度', value: (row) => vehicleArchiveCompleteness(row).label }, @@ -150,7 +150,7 @@ function vehicleFilterSummary(filters: Record) { return [ filters.keyword ? `关键词:${filters.keyword}` : '', filters.protocol ? `数据来源:${filters.protocol}` : '', - filters.coverage ? `来源覆盖:${coverageLabel[filters.coverage] ?? filters.coverage}` : '', + filters.coverage ? `车辆覆盖:${coverageLabel[filters.coverage] ?? filters.coverage}` : '', filters.missingProtocol ? `缺失来源:${filters.missingProtocol}` : '', filters.serviceStatus ? `服务状态:${serviceStatusLabel[filters.serviceStatus] ?? filters.serviceStatus}` : '', filters.online ? `在线:${onlineLabel[filters.online] ?? filters.online}` : '', @@ -654,7 +654,7 @@ export function Vehicles({ return (
- +
{ const nextFilters = values as Record; @@ -666,7 +666,7 @@ export function Vehicles({ JT808 YUTONG_MQTT - + 单源 多源 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 68c44a05..eaf32a50 100644 --- a/vehicle-data-platform/apps/web/src/test/App.test.tsx +++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx @@ -21,9 +21,9 @@ test('renders vehicle platform shell', () => { render(); 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(1); @@ -197,11 +197,11 @@ test('exposes AMap operations shortcuts when map key is configured', async () => expect(window.location.hash).toBe('#/realtime'); fireEvent.click(screen.getByRole('button', { name: '顶部轨迹回放' })); expect(window.location.hash.startsWith('#/history')).toBe(true); - fireEvent.click(screen.getByRole('button', { name: '顶部历史查询' })); + fireEvent.click(screen.getByRole('button', { name: '顶部数据导出' })); expect(window.location.hash.startsWith('#/history-query')).toBe(true); expect(new URLSearchParams(window.location.hash.split('?')[1] ?? '').get('tab')).toBe('raw'); expect(await screen.findByRole('heading', { name: '历史查询' })).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'); @@ -2340,7 +2340,7 @@ test('shows and clears current vehicle service filters', async () => { expect(await screen.findByText('当前车辆筛选')).toBeInTheDocument(); expect(screen.getByText('关键词:粤A')).toBeInTheDocument(); expect(screen.getByText('数据来源:JT808')).toBeInTheDocument(); - expect(screen.getByText('来源覆盖:多源')).toBeInTheDocument(); + expect(screen.getByText('车辆覆盖:多源')).toBeInTheDocument(); expect(screen.getByText('缺失来源:YUTONG_MQTT')).toBeInTheDocument(); expect(screen.getByText('服务状态:来源不完整')).toBeInTheDocument(); expect(screen.getByText('在线:在线')).toBeInTheDocument(); @@ -9160,13 +9160,13 @@ test('copies realtime operations summary from realtime page', async () => { expect(screen.getByText('实时作业入口')).toBeInTheDocument(); expect(screen.getByRole('button', { name: '实时筛选 在线车辆 2' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: '实时筛选 离线车辆 1' })).toBeInTheDocument(); - expect(screen.getByRole('button', { name: '实时筛选 降级服务 2' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: '实时筛选 需要关注 2' })).toBeInTheDocument(); expect(screen.getByText('建议处置')).toBeInTheDocument(); - expect(screen.getByText('排查降级服务 2')).toBeInTheDocument(); - expect(screen.getByText('协议地图覆盖')).toBeInTheDocument(); - expect(screen.getByRole('button', { name: '筛选协议 GB32960' })).toHaveTextContent('GB32960'); - expect(screen.getByRole('button', { name: '筛选协议 JT808' })).toHaveTextContent('2 辆'); - expect(screen.getByRole('button', { name: '筛选协议 YUTONG_MQTT' })).toHaveTextContent('超时 1'); + expect(screen.getByText('查看需关注车辆 2')).toBeInTheDocument(); + expect(screen.getByText('车辆覆盖概览')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: '筛选数据通道 GB32960' })).toHaveTextContent('GB32960'); + expect(screen.getByRole('button', { name: '筛选数据通道 JT808' })).toHaveTextContent('2 辆'); + expect(screen.getByRole('button', { name: '筛选数据通道 YUTONG_MQTT' })).toHaveTextContent('超时 1'); expect(screen.getByText('实时覆盖判读')).toBeInTheDocument(); expect(screen.getByText('在线率')).toBeInTheDocument(); expect(screen.getAllByText('66.7%').length).toBeGreaterThanOrEqual(3); @@ -9180,7 +9180,7 @@ test('copies realtime operations summary from realtime page', async () => { expect(writeText).toHaveBeenCalledWith(expect.stringContaining('当前筛选:数据来源:JT808;在线:在线')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆总数:3,当前页:3')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('在线车辆:2,定位有效:2')); - expect(writeText).toHaveBeenCalledWith(expect.stringContaining('降级服务:2,来源类型:3')); + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('需要关注:2,数据通道:3')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('地图配置:已配置')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('重点车辆:')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('粤A摘要3 / YUTONG_MQTT / 车辆离线')); @@ -9197,18 +9197,18 @@ test('copies realtime operations summary from realtime page', async () => { expect(writeText).toHaveBeenCalledWith(expect.stringContaining('实时监控:http://localhost:3000/#/realtime?keyword=VIN-RT-SUMMARY-003&protocol=JT808')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('轨迹回放:http://localhost:3000/#/history?keyword=VIN-RT-SUMMARY-003&protocol=JT808')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('告警事件:http://localhost:3000/#/alert-events?keyword=VIN-RT-SUMMARY-003&protocol=JT808')); - fireEvent.click(screen.getByRole('button', { name: '复制实时值班交接包' })); - expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【实时值班交接包】')); + fireEvent.click(screen.getByRole('button', { name: '复制实时运营交接包' })); + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【实时运营交接包】')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('页面车辆:3 / 总计 3;版本:')); - expect(writeText).toHaveBeenCalledWith(expect.stringContaining('在线:2;离线:1;定位有效:2;降级:2;超时:')); - expect(writeText).toHaveBeenCalledWith(expect.stringContaining('来源覆盖:GB32960:在线 1/1,实时 1/1;JT808:在线 1/2,实时 2/2;YUTONG_MQTT:在线 0/1,实时 1/1')); - expect(writeText).toHaveBeenCalledWith(expect.stringContaining('值班入口:http://localhost:3000/#/realtime?protocol=JT808&online=online')); + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('在线:2;离线:1;定位有效:2;需要关注:2;超时:')); + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆覆盖:GB32960:在线 1/1,实时 1/1;JT808:在线 1/2,实时 2/2;YUTONG_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('历史RAW: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' })); + fireEvent.click(screen.getByRole('button', { name: '实时筛选 需要关注 2' })); expect(window.location.hash).toBe('#/realtime?protocol=JT808&serviceStatus=degraded&online=online'); - fireEvent.click(screen.getByRole('button', { name: '筛选协议 GB32960' })); + fireEvent.click(screen.getByRole('button', { name: '筛选数据通道 GB32960' })); expect(window.location.hash).toBe('#/realtime?protocol=GB32960&serviceStatus=degraded&online=online'); }); @@ -9313,7 +9313,7 @@ test('shows production AMap integration status on realtime page', async () => { render(); - expect(await screen.findByText('地图接入状态')).toBeInTheDocument(); + expect(await screen.findByText('地图能力状态')).toBeInTheDocument(); expect(screen.getByText('Web JS Key')).toBeInTheDocument(); expect(screen.getByText('服务端 API Key')).toBeInTheDocument(); expect(screen.getAllByText('已配置').length).toBeGreaterThan(0); @@ -9682,7 +9682,7 @@ test('surfaces multi-source realtime consistency issues with quality drilldown', render(); - expect(await screen.findByText('多来源一致性检查')).toBeInTheDocument(); + expect(await screen.findByText('车辆数据一致性检查')).toBeInTheDocument(); expect(screen.getAllByText('粤A一致监控').length).toBeGreaterThan(0); expect(screen.getByText('一致性诊断:YUTONG_MQTT 离线,GB32960/JT808 仍可支撑车辆服务')).toBeInTheDocument(); expect(screen.getByText('一致性:YUTONG_MQTT 离线')).toBeInTheDocument();