diff --git a/vehicle-data-platform/apps/api/internal/platform/handler_test.go b/vehicle-data-platform/apps/api/internal/platform/handler_test.go index 880586b7..645c036a 100644 --- a/vehicle-data-platform/apps/api/internal/platform/handler_test.go +++ b/vehicle-data-platform/apps/api/internal/platform/handler_test.go @@ -429,13 +429,13 @@ func TestHandlerVehicleServiceOverviewEndpoint(t *testing.T) { if body.Data.SourceCount != 2 || body.Data.OnlineSourceCount != 1 || body.Data.CoverageStatus != "partial" { t.Fatalf("overview endpoint should summarize vehicle service coverage, got %+v", body.Data) } - if body.Data.ServiceStatus == nil || body.Data.ServiceStatus.Status != "degraded" || body.Data.ServiceStatus.Title != "部分来源离线" { + if body.Data.ServiceStatus == nil || body.Data.ServiceStatus.Status != "degraded" || body.Data.ServiceStatus.Title != "来源不完整" { t.Fatalf("overview endpoint should expose canonical service status, got %+v", body.Data.ServiceStatus) } if body.Data.SourceConsistency == nil || body.Data.SourceConsistency.SourceCount != 2 || body.Data.SourceConsistency.OnlineSourceCount != 1 { t.Fatalf("overview endpoint should expose source consistency, got %+v", body.Data.SourceConsistency) } - if body.Data.SourceConsistency.Status != "degraded" || body.Data.SourceConsistency.Title != "部分来源离线" { + if body.Data.SourceConsistency.Status != "degraded" || body.Data.SourceConsistency.Title != "来源不完整" { t.Fatalf("overview source consistency should expose diagnosis, got %+v", body.Data.SourceConsistency) } if strings.Contains(rec.Body.String(), `"raw"`) || strings.Contains(rec.Body.String(), `"history"`) { @@ -468,8 +468,8 @@ func TestHandlerVehicleServiceSummaryEndpoint(t *testing.T) { } noDataStatusFound := false for _, status := range body.Data.ServiceStatuses { - if status.Status == "degraded" && status.Title != "来源异常" { - t.Fatalf("summary degraded status should use broad source exception title, got %+v", status) + if status.Status == "degraded" && status.Title != "来源不完整" { + t.Fatalf("summary degraded status should use vehicle-service missing source title, got %+v", status) } if status.Status == "no_data" { noDataStatusFound = true diff --git a/vehicle-data-platform/apps/api/internal/platform/mock_store.go b/vehicle-data-platform/apps/api/internal/platform/mock_store.go index 58e8db3b..bb896106 100644 --- a/vehicle-data-platform/apps/api/internal/platform/mock_store.go +++ b/vehicle-data-platform/apps/api/internal/platform/mock_store.go @@ -46,7 +46,7 @@ func (m *MockStore) DashboardSummary(context.Context) (DashboardSummary, error) }, ServiceStatuses: []ServiceStatusStat{ {Status: "healthy", Title: "服务正常", Count: 2}, - {Status: "degraded", Title: "来源异常", Count: 1}, + {Status: "degraded", Title: "来源不完整", Count: 1}, {Status: "offline", Title: "车辆离线", Count: 1}, {Status: "identity_required", Title: "身份未绑定", Count: 0}, }, @@ -201,7 +201,7 @@ func (m *MockStore) VehicleServiceSummary(ctx context.Context) (VehicleServiceSu } statusCounts := map[string]*ServiceStatusStat{ "healthy": {Status: "healthy", Title: "服务正常"}, - "degraded": {Status: "degraded", Title: "来源异常"}, + "degraded": {Status: "degraded", Title: "来源不完整"}, "offline": {Status: "offline", Title: "车辆离线"}, "no_data": {Status: "no_data", Title: "暂无数据来源"}, "identity_required": {Status: "identity_required", Title: "身份未绑定"}, diff --git a/vehicle-data-platform/apps/api/internal/platform/production_store.go b/vehicle-data-platform/apps/api/internal/platform/production_store.go index 0600203c..36587823 100644 --- a/vehicle-data-platform/apps/api/internal/platform/production_store.go +++ b/vehicle-data-platform/apps/api/internal/platform/production_store.go @@ -76,7 +76,7 @@ func (s *ProductionStore) DashboardSummary(ctx context.Context) (DashboardSummar func (s *ProductionStore) serviceStatusStats(ctx context.Context) ([]ServiceStatusStat, error) { definitions := []ServiceStatusStat{ {Status: "healthy", Title: "服务正常"}, - {Status: "degraded", Title: "来源异常"}, + {Status: "degraded", Title: "来源不完整"}, {Status: "offline", Title: "车辆离线"}, {Status: "no_data", Title: "暂无数据来源"}, {Status: "identity_required", Title: "身份未绑定"}, @@ -149,7 +149,7 @@ GROUP BY v.vin } summary.ServiceStatuses = []ServiceStatusStat{ {Status: "healthy", Title: "服务正常", Count: healthy}, - {Status: "degraded", Title: "来源异常", Count: degraded}, + {Status: "degraded", Title: "来源不完整", Count: degraded}, {Status: "offline", Title: "车辆离线", Count: offline}, {Status: "no_data", Title: "暂无数据来源", Count: summary.NoDataVehicles}, {Status: "identity_required", Title: "身份未绑定", Count: summary.IdentityRequiredVehicles}, diff --git a/vehicle-data-platform/apps/api/internal/platform/service.go b/vehicle-data-platform/apps/api/internal/platform/service.go index dfc872d1..e419868a 100644 --- a/vehicle-data-platform/apps/api/internal/platform/service.go +++ b/vehicle-data-platform/apps/api/internal/platform/service.go @@ -492,7 +492,7 @@ func applyVehicleSourceConsistencyDiagnosis(consistency *VehicleSourceConsistenc case consistency.OnlineSourceCount < consistency.SourceCount: consistency.Status = "degraded" consistency.Severity = "warning" - consistency.Title = "部分来源离线" + consistency.Title = "来源不完整" consistency.Detail = sourceCoverageDetail(consistency.SourceCount, consistency.OnlineSourceCount, "车辆服务可用但需要关注离线来源。") case consistency.MileageDeltaKm > 5: consistency.Status = "mileage_divergent" @@ -1013,7 +1013,7 @@ func buildVehicleServiceStatus(resolved bool, statuses []VehicleSourceStatus) *V return &VehicleServiceStatus{ Status: "degraded", Severity: "warning", - Title: "部分来源离线", + Title: "来源不完整", Detail: sourceCoverageDetail(sourceCount, onlineSourceCount, "车辆服务可用但需要关注离线来源。"), SourceCount: sourceCount, OnlineSourceCount: onlineSourceCount, @@ -1084,7 +1084,7 @@ func buildVehicleCoverageServiceStatus(row VehicleCoverageRow) *VehicleServiceSt return &VehicleServiceStatus{ Status: "degraded", Severity: "warning", - Title: "部分来源离线", + Title: "来源不完整", Detail: sourceCoverageDetail(row.SourceCount, row.OnlineSourceCount, "车辆服务可用但需要关注离线来源。"), SourceCount: row.SourceCount, OnlineSourceCount: row.OnlineSourceCount, diff --git a/vehicle-data-platform/apps/web/src/App.tsx b/vehicle-data-platform/apps/web/src/App.tsx index 539a155f..aa67101b 100644 --- a/vehicle-data-platform/apps/web/src/App.tsx +++ b/vehicle-data-platform/apps/web/src/App.tsx @@ -462,7 +462,7 @@ function serviceStatusFromOverview(overview: VehicleServiceOverview): VehicleSer return { status: 'degraded', severity: 'warning', - title: '来源异常', + title: '来源不完整', detail: `${onlineSourceCount}/${sourceCount} 个来源在线,车辆服务可用但需要关注离线来源。`, sourceCount, onlineSourceCount diff --git a/vehicle-data-platform/apps/web/src/api/client.test.ts b/vehicle-data-platform/apps/web/src/api/client.test.ts index 5ec5aa48..ede961c9 100644 --- a/vehicle-data-platform/apps/web/src/api/client.test.ts +++ b/vehicle-data-platform/apps/web/src/api/client.test.ts @@ -87,7 +87,7 @@ test('vehicleServiceOverview sends keyword to the lightweight overview endpoint' serviceStatus: { status: 'degraded', severity: 'warning', - title: '部分来源离线', + title: '来源不完整', detail: '1/2 个来源在线', sourceCount: 2, onlineSourceCount: 1 diff --git a/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx b/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx index c25402c5..e33c61e2 100644 --- a/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Dashboard.tsx @@ -24,7 +24,7 @@ const serviceStatusColor: Record = const serviceStatusTitle: Record = { healthy: '服务正常', - degraded: '来源异常', + degraded: '来源不完整', offline: '车辆离线', no_data: '暂无数据来源', identity_required: '身份未绑定' @@ -62,7 +62,7 @@ function rowServiceStatus(row: { serviceStatus?: { title: string; severity: stri return { label: '车辆离线', color: 'red' as const }; } if (row.onlineSourceCount < row.sourceCount) { - return { label: '来源异常', color: 'orange' as const }; + return { label: '来源不完整', color: 'orange' as const }; } return { label: '服务正常', color: 'green' as const }; } @@ -312,7 +312,7 @@ export function Dashboard({ onOpenVehicle, onOpenQuality, onOpenVehicles }: { on 服务正常 - 来源异常 + 来源不完整 车辆离线 暂无数据来源 身份未绑定 diff --git a/vehicle-data-platform/apps/web/src/pages/Realtime.tsx b/vehicle-data-platform/apps/web/src/pages/Realtime.tsx index 7c1763bd..88f364c4 100644 --- a/vehicle-data-platform/apps/web/src/pages/Realtime.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Realtime.tsx @@ -23,7 +23,7 @@ function vehicleServiceStatus(row: VehicleRealtimeRow) { return { label: '车辆离线', color: 'red' as const }; } if (row.onlineSourceCount < row.sourceCount) { - return { label: '来源异常', color: 'orange' as const }; + return { label: '来源不完整', color: 'orange' as const }; } return { label: '服务正常', color: 'green' as const }; } @@ -93,7 +93,7 @@ export function Realtime({ 服务正常 - 来源异常 + 来源不完整 车辆离线 身份未绑定 diff --git a/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx b/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx index 595e3eca..524803ec 100644 --- a/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx @@ -25,7 +25,7 @@ function vehicleServiceStatus(row: VehicleCoverageRow) { return { label: '车辆离线', color: 'red' as const }; } if (row.onlineSourceCount < row.sourceCount) { - return { label: '来源异常', color: 'orange' as const }; + return { label: '来源不完整', color: 'orange' as const }; } return { label: '服务正常', color: 'green' as const }; } @@ -227,7 +227,7 @@ export function Vehicles({ 服务正常 - 来源异常 + 来源不完整 车辆离线 暂无数据来源 身份未绑定 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 d8dc4535..2acaa57c 100644 --- a/vehicle-data-platform/apps/web/src/test/App.test.tsx +++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx @@ -31,7 +31,7 @@ test('shows vehicle service status distribution on dashboard', async () => { protocols: [], serviceStatuses: [ { status: 'healthy', title: '服务正常', count: 12 }, - { status: 'degraded', title: '部分来源离线', count: 39 } + { status: 'degraded', title: '来源不完整', count: 39 } ], linkHealth: [] }, @@ -53,7 +53,7 @@ test('shows vehicle service status distribution on dashboard', async () => { render(); expect(await screen.findByText('车辆服务状态')).toBeInTheDocument(); - expect(screen.getByText('部分来源离线')).toBeInTheDocument(); + expect(screen.getByText('来源不完整')).toBeInTheDocument(); expect(screen.getByText('39')).toBeInTheDocument(); }); @@ -94,7 +94,7 @@ test('dashboard renders vehicle service summary metrics', async () => { identityRequiredVehicles: 9, serviceStatuses: [ { status: 'healthy', title: '服务正常', count: 161 }, - { status: 'degraded', title: '部分来源离线', count: 41 } + { status: 'degraded', title: '来源不完整', count: 41 } ], protocols: [ { protocol: 'JT808', online: 157, total: 388 }, @@ -310,7 +310,7 @@ test('shows vehicle service result summary on vehicle list filters', async () => serviceStatus: { status: 'degraded', severity: 'warning', - title: '部分来源离线', + title: '来源不完整', detail: '1/2 个来源在线', sourceCount: 2, onlineSourceCount: 1 @@ -913,7 +913,7 @@ test('filters dashboard coverage from source consistency diagnosis', async () => expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('serviceStatus=degraded'), undefined); }); expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('missingProtocol=JT808'), undefined); - expect(screen.getByText('当前筛选:来源异常 / 缺 JT808')).toBeInTheDocument(); + expect(screen.getByText('当前筛选:来源不完整 / 缺 JT808')).toBeInTheDocument(); }); test('opens full vehicle service list from dashboard coverage filters', async () => { @@ -1251,13 +1251,13 @@ test('filters dashboard coverage by service status', async () => { expect(await screen.findByText('车辆服务覆盖')).toBeInTheDocument(); fireEvent.click(screen.getByTestId('dashboard-service-status-filter')); - fireEvent.click(await screen.findByText('来源异常')); + fireEvent.click(await screen.findByText('来源不完整')); fireEvent.click(screen.getByRole('button', { name: '筛选' })); await waitFor(() => { expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('serviceStatus=degraded'), undefined); }); - expect(screen.getByText('当前筛选:来源异常')).toBeInTheDocument(); + expect(screen.getByText('当前筛选:来源不完整')).toBeInTheDocument(); }); test('filters dashboard coverage by missing source evidence', async () => { @@ -1322,7 +1322,7 @@ test('opens dashboard coverage from service status distribution', async () => { kafkaLag: 0, protocols: [], serviceStatuses: [ - { status: 'degraded', title: '部分来源离线', count: 39 } + { status: 'degraded', title: '来源不完整', count: 39 } ], linkHealth: [] }, @@ -1343,7 +1343,7 @@ test('opens dashboard coverage from service status distribution', async () => { render(); - fireEvent.click(await screen.findByRole('button', { name: '查看部分来源离线' })); + fireEvent.click(await screen.findByRole('button', { name: '查看来源不完整' })); await waitFor(() => { expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('serviceStatus=degraded'), undefined); @@ -1816,7 +1816,7 @@ test('shows vehicle context when opening detail from shareable hash', async () = render(); expect(await screen.findByText('粤AG18312 / VIN001')).toBeInTheDocument(); - expect(screen.getByText('当前车辆:来源异常')).toBeInTheDocument(); + expect(screen.getByText('当前车辆:来源不完整')).toBeInTheDocument(); }); test('refreshes vehicle context when hash changes to another detail vehicle', async () => { @@ -2769,7 +2769,7 @@ test('shows canonical service status in realtime vehicles', async () => { serviceStatus: { status: 'degraded', severity: 'warning', - title: '部分来源离线', + title: '来源不完整', detail: '由实时车辆 API 统一判定', sourceCount: 2, onlineSourceCount: 1 @@ -2797,7 +2797,7 @@ test('shows canonical service status in realtime vehicles', async () => { render(); expect(await screen.findByText('VIN-RT-DEGRADED')).toBeInTheDocument(); - expect(screen.getByText('部分来源离线')).toBeInTheDocument(); + expect(screen.getByText('来源不完整')).toBeInTheDocument(); }); test('frames realtime page as one vehicle service with source evidence', async () => { @@ -2983,7 +2983,7 @@ test('shows vehicle service status in vehicle list', async () => { serviceStatus: { status: 'degraded', severity: 'warning', - title: '部分来源离线', + title: '来源不完整', detail: '由车辆服务 API 统一判定', sourceCount: 2, onlineSourceCount: 1 @@ -3014,7 +3014,7 @@ test('shows vehicle service status in vehicle list', async () => { expect(await screen.findByText('VIN-DEGRADED-001')).toBeInTheDocument(); expect(screen.getByText('车辆服务状态')).toBeInTheDocument(); - expect(screen.getByText('部分来源离线')).toBeInTheDocument(); + expect(screen.getByText('来源不完整')).toBeInTheDocument(); }); test('shows source consistency diagnosis in vehicle service list', async () => { @@ -3373,7 +3373,7 @@ test('filters vehicle list by service status', async () => { await screen.findByRole('heading', { name: '车辆服务' }); fireEvent.click(screen.getByTestId('service-status-filter')); - fireEvent.click(await screen.findByText('来源异常')); + fireEvent.click(await screen.findByText('来源不完整')); fireEvent.click(screen.getByRole('button', { name: '查询' })); await waitFor(() => { @@ -3500,7 +3500,7 @@ test('shows unified service overview on vehicle detail', async () => { serviceStatus: { status: 'degraded', severity: 'warning', - title: '部分来源离线', + title: '来源不完整', detail: '2/3 个来源在线', sourceCount: 3, onlineSourceCount: 2 @@ -3569,7 +3569,7 @@ test('shows vehicle service evidence chain before source details', async () => { serviceStatus: { status: 'degraded', severity: 'warning', - title: '部分来源离线', + title: '来源不完整', detail: '2/3 个来源在线', sourceCount: 3, onlineSourceCount: 2 @@ -3583,7 +3583,7 @@ test('shows vehicle service evidence chain before source details', async () => { scope: 'vehicle', status: 'degraded', severity: 'warning', - title: '部分来源离线', + title: '来源不完整', detail: 'MQTT 离线,32960 与 808 仍可支撑车辆服务' }, sources: ['GB32960', 'JT808', 'YUTONG_MQTT'], @@ -4145,7 +4145,7 @@ test('shows selected source scope on vehicle detail', async () => { serviceStatus: { status: 'degraded', severity: 'warning', - title: '部分来源离线', + title: '来源不完整', detail: '1/2 个来源在线,车辆服务可用但需要关注离线来源。', sourceCount: 2, onlineSourceCount: 1 @@ -4178,7 +4178,7 @@ test('shows selected source scope on vehicle detail', async () => { expect(await screen.findByText('当前查看范围')).toBeInTheDocument(); expect(screen.getByText('单一来源:JT808')).toBeInTheDocument(); expect(screen.getByText('车辆服务状态')).toBeInTheDocument(); - expect(screen.getByText('部分来源离线')).toBeInTheDocument(); + expect(screen.getByText('来源不完整')).toBeInTheDocument(); expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('/api/vehicle-service?keyword=VIN001&protocol=JT808'), undefined); });