fix(platform): unify degraded service wording

This commit is contained in:
lingniu
2026-07-04 08:03:24 +08:00
parent 4251ea5235
commit 5fa7858662
10 changed files with 40 additions and 40 deletions

View File

@@ -429,13 +429,13 @@ func TestHandlerVehicleServiceOverviewEndpoint(t *testing.T) {
if body.Data.SourceCount != 2 || body.Data.OnlineSourceCount != 1 || body.Data.CoverageStatus != "partial" { 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) 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) 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 { 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) 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) 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"`) { if strings.Contains(rec.Body.String(), `"raw"`) || strings.Contains(rec.Body.String(), `"history"`) {
@@ -468,8 +468,8 @@ func TestHandlerVehicleServiceSummaryEndpoint(t *testing.T) {
} }
noDataStatusFound := false noDataStatusFound := false
for _, status := range body.Data.ServiceStatuses { for _, status := range body.Data.ServiceStatuses {
if status.Status == "degraded" && status.Title != "来源异常" { if status.Status == "degraded" && status.Title != "来源不完整" {
t.Fatalf("summary degraded status should use broad source exception title, got %+v", status) t.Fatalf("summary degraded status should use vehicle-service missing source title, got %+v", status)
} }
if status.Status == "no_data" { if status.Status == "no_data" {
noDataStatusFound = true noDataStatusFound = true

View File

@@ -46,7 +46,7 @@ func (m *MockStore) DashboardSummary(context.Context) (DashboardSummary, error)
}, },
ServiceStatuses: []ServiceStatusStat{ ServiceStatuses: []ServiceStatusStat{
{Status: "healthy", Title: "服务正常", Count: 2}, {Status: "healthy", Title: "服务正常", Count: 2},
{Status: "degraded", Title: "来源异常", Count: 1}, {Status: "degraded", Title: "来源不完整", Count: 1},
{Status: "offline", Title: "车辆离线", Count: 1}, {Status: "offline", Title: "车辆离线", Count: 1},
{Status: "identity_required", Title: "身份未绑定", Count: 0}, {Status: "identity_required", Title: "身份未绑定", Count: 0},
}, },
@@ -201,7 +201,7 @@ func (m *MockStore) VehicleServiceSummary(ctx context.Context) (VehicleServiceSu
} }
statusCounts := map[string]*ServiceStatusStat{ statusCounts := map[string]*ServiceStatusStat{
"healthy": {Status: "healthy", Title: "服务正常"}, "healthy": {Status: "healthy", Title: "服务正常"},
"degraded": {Status: "degraded", Title: "来源异常"}, "degraded": {Status: "degraded", Title: "来源不完整"},
"offline": {Status: "offline", Title: "车辆离线"}, "offline": {Status: "offline", Title: "车辆离线"},
"no_data": {Status: "no_data", Title: "暂无数据来源"}, "no_data": {Status: "no_data", Title: "暂无数据来源"},
"identity_required": {Status: "identity_required", Title: "身份未绑定"}, "identity_required": {Status: "identity_required", Title: "身份未绑定"},

View File

@@ -76,7 +76,7 @@ func (s *ProductionStore) DashboardSummary(ctx context.Context) (DashboardSummar
func (s *ProductionStore) serviceStatusStats(ctx context.Context) ([]ServiceStatusStat, error) { func (s *ProductionStore) serviceStatusStats(ctx context.Context) ([]ServiceStatusStat, error) {
definitions := []ServiceStatusStat{ definitions := []ServiceStatusStat{
{Status: "healthy", Title: "服务正常"}, {Status: "healthy", Title: "服务正常"},
{Status: "degraded", Title: "来源异常"}, {Status: "degraded", Title: "来源不完整"},
{Status: "offline", Title: "车辆离线"}, {Status: "offline", Title: "车辆离线"},
{Status: "no_data", Title: "暂无数据来源"}, {Status: "no_data", Title: "暂无数据来源"},
{Status: "identity_required", Title: "身份未绑定"}, {Status: "identity_required", Title: "身份未绑定"},
@@ -149,7 +149,7 @@ GROUP BY v.vin
} }
summary.ServiceStatuses = []ServiceStatusStat{ summary.ServiceStatuses = []ServiceStatusStat{
{Status: "healthy", Title: "服务正常", Count: healthy}, {Status: "healthy", Title: "服务正常", Count: healthy},
{Status: "degraded", Title: "来源异常", Count: degraded}, {Status: "degraded", Title: "来源不完整", Count: degraded},
{Status: "offline", Title: "车辆离线", Count: offline}, {Status: "offline", Title: "车辆离线", Count: offline},
{Status: "no_data", Title: "暂无数据来源", Count: summary.NoDataVehicles}, {Status: "no_data", Title: "暂无数据来源", Count: summary.NoDataVehicles},
{Status: "identity_required", Title: "身份未绑定", Count: summary.IdentityRequiredVehicles}, {Status: "identity_required", Title: "身份未绑定", Count: summary.IdentityRequiredVehicles},

View File

@@ -492,7 +492,7 @@ func applyVehicleSourceConsistencyDiagnosis(consistency *VehicleSourceConsistenc
case consistency.OnlineSourceCount < consistency.SourceCount: case consistency.OnlineSourceCount < consistency.SourceCount:
consistency.Status = "degraded" consistency.Status = "degraded"
consistency.Severity = "warning" consistency.Severity = "warning"
consistency.Title = "部分来源离线" consistency.Title = "来源不完整"
consistency.Detail = sourceCoverageDetail(consistency.SourceCount, consistency.OnlineSourceCount, "车辆服务可用但需要关注离线来源。") consistency.Detail = sourceCoverageDetail(consistency.SourceCount, consistency.OnlineSourceCount, "车辆服务可用但需要关注离线来源。")
case consistency.MileageDeltaKm > 5: case consistency.MileageDeltaKm > 5:
consistency.Status = "mileage_divergent" consistency.Status = "mileage_divergent"
@@ -1013,7 +1013,7 @@ func buildVehicleServiceStatus(resolved bool, statuses []VehicleSourceStatus) *V
return &VehicleServiceStatus{ return &VehicleServiceStatus{
Status: "degraded", Status: "degraded",
Severity: "warning", Severity: "warning",
Title: "部分来源离线", Title: "来源不完整",
Detail: sourceCoverageDetail(sourceCount, onlineSourceCount, "车辆服务可用但需要关注离线来源。"), Detail: sourceCoverageDetail(sourceCount, onlineSourceCount, "车辆服务可用但需要关注离线来源。"),
SourceCount: sourceCount, SourceCount: sourceCount,
OnlineSourceCount: onlineSourceCount, OnlineSourceCount: onlineSourceCount,
@@ -1084,7 +1084,7 @@ func buildVehicleCoverageServiceStatus(row VehicleCoverageRow) *VehicleServiceSt
return &VehicleServiceStatus{ return &VehicleServiceStatus{
Status: "degraded", Status: "degraded",
Severity: "warning", Severity: "warning",
Title: "部分来源离线", Title: "来源不完整",
Detail: sourceCoverageDetail(row.SourceCount, row.OnlineSourceCount, "车辆服务可用但需要关注离线来源。"), Detail: sourceCoverageDetail(row.SourceCount, row.OnlineSourceCount, "车辆服务可用但需要关注离线来源。"),
SourceCount: row.SourceCount, SourceCount: row.SourceCount,
OnlineSourceCount: row.OnlineSourceCount, OnlineSourceCount: row.OnlineSourceCount,

View File

@@ -462,7 +462,7 @@ function serviceStatusFromOverview(overview: VehicleServiceOverview): VehicleSer
return { return {
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '来源异常', title: '来源不完整',
detail: `${onlineSourceCount}/${sourceCount} 个来源在线,车辆服务可用但需要关注离线来源。`, detail: `${onlineSourceCount}/${sourceCount} 个来源在线,车辆服务可用但需要关注离线来源。`,
sourceCount, sourceCount,
onlineSourceCount onlineSourceCount

View File

@@ -87,7 +87,7 @@ test('vehicleServiceOverview sends keyword to the lightweight overview endpoint'
serviceStatus: { serviceStatus: {
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '部分来源离线', title: '来源不完整',
detail: '1/2 个来源在线', detail: '1/2 个来源在线',
sourceCount: 2, sourceCount: 2,
onlineSourceCount: 1 onlineSourceCount: 1

View File

@@ -24,7 +24,7 @@ const serviceStatusColor: Record<string, 'green' | 'orange' | 'red' | 'grey'> =
const serviceStatusTitle: Record<string, string> = { const serviceStatusTitle: Record<string, string> = {
healthy: '服务正常', healthy: '服务正常',
degraded: '来源异常', degraded: '来源不完整',
offline: '车辆离线', offline: '车辆离线',
no_data: '暂无数据来源', no_data: '暂无数据来源',
identity_required: '身份未绑定' identity_required: '身份未绑定'
@@ -62,7 +62,7 @@ function rowServiceStatus(row: { serviceStatus?: { title: string; severity: stri
return { label: '车辆离线', color: 'red' as const }; return { label: '车辆离线', color: 'red' as const };
} }
if (row.onlineSourceCount < row.sourceCount) { if (row.onlineSourceCount < row.sourceCount) {
return { label: '来源异常', color: 'orange' as const }; return { label: '来源不完整', color: 'orange' as const };
} }
return { label: '服务正常', color: 'green' as const }; return { label: '服务正常', color: 'green' as const };
} }
@@ -312,7 +312,7 @@ export function Dashboard({ onOpenVehicle, onOpenQuality, onOpenVehicles }: { on
</Form.Select> </Form.Select>
<Form.Select field="serviceStatus" label="服务状态" placeholder="全部" style={{ width: 150 }} data-testid="dashboard-service-status-filter"> <Form.Select field="serviceStatus" label="服务状态" placeholder="全部" style={{ width: 150 }} data-testid="dashboard-service-status-filter">
<Select.Option value="healthy"></Select.Option> <Select.Option value="healthy"></Select.Option>
<Select.Option value="degraded"></Select.Option> <Select.Option value="degraded"></Select.Option>
<Select.Option value="offline">线</Select.Option> <Select.Option value="offline">线</Select.Option>
<Select.Option value="no_data"></Select.Option> <Select.Option value="no_data"></Select.Option>
<Select.Option value="identity_required"></Select.Option> <Select.Option value="identity_required"></Select.Option>

View File

@@ -23,7 +23,7 @@ function vehicleServiceStatus(row: VehicleRealtimeRow) {
return { label: '车辆离线', color: 'red' as const }; return { label: '车辆离线', color: 'red' as const };
} }
if (row.onlineSourceCount < row.sourceCount) { if (row.onlineSourceCount < row.sourceCount) {
return { label: '来源异常', color: 'orange' as const }; return { label: '来源不完整', color: 'orange' as const };
} }
return { label: '服务正常', color: 'green' as const }; return { label: '服务正常', color: 'green' as const };
} }
@@ -93,7 +93,7 @@ export function Realtime({
</Form.Select> </Form.Select>
<Form.Select field="serviceStatus" label="服务状态" placeholder="全部" style={{ width: 150 }}> <Form.Select field="serviceStatus" label="服务状态" placeholder="全部" style={{ width: 150 }}>
<Select.Option value="healthy"></Select.Option> <Select.Option value="healthy"></Select.Option>
<Select.Option value="degraded"></Select.Option> <Select.Option value="degraded"></Select.Option>
<Select.Option value="offline">线</Select.Option> <Select.Option value="offline">线</Select.Option>
<Select.Option value="identity_required"></Select.Option> <Select.Option value="identity_required"></Select.Option>
</Form.Select> </Form.Select>

View File

@@ -25,7 +25,7 @@ function vehicleServiceStatus(row: VehicleCoverageRow) {
return { label: '车辆离线', color: 'red' as const }; return { label: '车辆离线', color: 'red' as const };
} }
if (row.onlineSourceCount < row.sourceCount) { if (row.onlineSourceCount < row.sourceCount) {
return { label: '来源异常', color: 'orange' as const }; return { label: '来源不完整', color: 'orange' as const };
} }
return { label: '服务正常', color: 'green' as const }; return { label: '服务正常', color: 'green' as const };
} }
@@ -227,7 +227,7 @@ export function Vehicles({
</Form.Select> </Form.Select>
<Form.Select field="serviceStatus" label="服务状态" placeholder="全部" style={{ width: 150 }} data-testid="service-status-filter"> <Form.Select field="serviceStatus" label="服务状态" placeholder="全部" style={{ width: 150 }} data-testid="service-status-filter">
<Select.Option value="healthy"></Select.Option> <Select.Option value="healthy"></Select.Option>
<Select.Option value="degraded"></Select.Option> <Select.Option value="degraded"></Select.Option>
<Select.Option value="offline">线</Select.Option> <Select.Option value="offline">线</Select.Option>
<Select.Option value="no_data"></Select.Option> <Select.Option value="no_data"></Select.Option>
<Select.Option value="identity_required"></Select.Option> <Select.Option value="identity_required"></Select.Option>

View File

@@ -31,7 +31,7 @@ test('shows vehicle service status distribution on dashboard', async () => {
protocols: [], protocols: [],
serviceStatuses: [ serviceStatuses: [
{ status: 'healthy', title: '服务正常', count: 12 }, { status: 'healthy', title: '服务正常', count: 12 },
{ status: 'degraded', title: '部分来源离线', count: 39 } { status: 'degraded', title: '来源不完整', count: 39 }
], ],
linkHealth: [] linkHealth: []
}, },
@@ -53,7 +53,7 @@ test('shows vehicle service status distribution on dashboard', async () => {
render(<App />); render(<App />);
expect(await screen.findByText('车辆服务状态')).toBeInTheDocument(); expect(await screen.findByText('车辆服务状态')).toBeInTheDocument();
expect(screen.getByText('部分来源离线')).toBeInTheDocument(); expect(screen.getByText('来源不完整')).toBeInTheDocument();
expect(screen.getByText('39')).toBeInTheDocument(); expect(screen.getByText('39')).toBeInTheDocument();
}); });
@@ -94,7 +94,7 @@ test('dashboard renders vehicle service summary metrics', async () => {
identityRequiredVehicles: 9, identityRequiredVehicles: 9,
serviceStatuses: [ serviceStatuses: [
{ status: 'healthy', title: '服务正常', count: 161 }, { status: 'healthy', title: '服务正常', count: 161 },
{ status: 'degraded', title: '部分来源离线', count: 41 } { status: 'degraded', title: '来源不完整', count: 41 }
], ],
protocols: [ protocols: [
{ protocol: 'JT808', online: 157, total: 388 }, { protocol: 'JT808', online: 157, total: 388 },
@@ -310,7 +310,7 @@ test('shows vehicle service result summary on vehicle list filters', async () =>
serviceStatus: { serviceStatus: {
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '部分来源离线', title: '来源不完整',
detail: '1/2 个来源在线', detail: '1/2 个来源在线',
sourceCount: 2, sourceCount: 2,
onlineSourceCount: 1 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('serviceStatus=degraded'), undefined);
}); });
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('missingProtocol=JT808'), 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 () => { 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(); expect(await screen.findByText('车辆服务覆盖')).toBeInTheDocument();
fireEvent.click(screen.getByTestId('dashboard-service-status-filter')); fireEvent.click(screen.getByTestId('dashboard-service-status-filter'));
fireEvent.click(await screen.findByText('来源异常')); fireEvent.click(await screen.findByText('来源不完整'));
fireEvent.click(screen.getByRole('button', { name: '筛选' })); fireEvent.click(screen.getByRole('button', { name: '筛选' }));
await waitFor(() => { await waitFor(() => {
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('serviceStatus=degraded'), undefined); 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 () => { test('filters dashboard coverage by missing source evidence', async () => {
@@ -1322,7 +1322,7 @@ test('opens dashboard coverage from service status distribution', async () => {
kafkaLag: 0, kafkaLag: 0,
protocols: [], protocols: [],
serviceStatuses: [ serviceStatuses: [
{ status: 'degraded', title: '部分来源离线', count: 39 } { status: 'degraded', title: '来源不完整', count: 39 }
], ],
linkHealth: [] linkHealth: []
}, },
@@ -1343,7 +1343,7 @@ test('opens dashboard coverage from service status distribution', async () => {
render(<App />); render(<App />);
fireEvent.click(await screen.findByRole('button', { name: '查看部分来源离线' })); fireEvent.click(await screen.findByRole('button', { name: '查看来源不完整' }));
await waitFor(() => { await waitFor(() => {
expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('serviceStatus=degraded'), undefined); expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('serviceStatus=degraded'), undefined);
@@ -1816,7 +1816,7 @@ test('shows vehicle context when opening detail from shareable hash', async () =
render(<App />); render(<App />);
expect(await screen.findByText('粤AG18312 / VIN001')).toBeInTheDocument(); 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 () => { 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: { serviceStatus: {
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '部分来源离线', title: '来源不完整',
detail: '由实时车辆 API 统一判定', detail: '由实时车辆 API 统一判定',
sourceCount: 2, sourceCount: 2,
onlineSourceCount: 1 onlineSourceCount: 1
@@ -2797,7 +2797,7 @@ test('shows canonical service status in realtime vehicles', async () => {
render(<App />); render(<App />);
expect(await screen.findByText('VIN-RT-DEGRADED')).toBeInTheDocument(); 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 () => { 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: { serviceStatus: {
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '部分来源离线', title: '来源不完整',
detail: '由车辆服务 API 统一判定', detail: '由车辆服务 API 统一判定',
sourceCount: 2, sourceCount: 2,
onlineSourceCount: 1 onlineSourceCount: 1
@@ -3014,7 +3014,7 @@ test('shows vehicle service status in vehicle list', async () => {
expect(await screen.findByText('VIN-DEGRADED-001')).toBeInTheDocument(); expect(await screen.findByText('VIN-DEGRADED-001')).toBeInTheDocument();
expect(screen.getByText('车辆服务状态')).toBeInTheDocument(); expect(screen.getByText('车辆服务状态')).toBeInTheDocument();
expect(screen.getByText('部分来源离线')).toBeInTheDocument(); expect(screen.getByText('来源不完整')).toBeInTheDocument();
}); });
test('shows source consistency diagnosis in vehicle service list', async () => { 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: '车辆服务' }); await screen.findByRole('heading', { name: '车辆服务' });
fireEvent.click(screen.getByTestId('service-status-filter')); fireEvent.click(screen.getByTestId('service-status-filter'));
fireEvent.click(await screen.findByText('来源异常')); fireEvent.click(await screen.findByText('来源不完整'));
fireEvent.click(screen.getByRole('button', { name: '查询' })); fireEvent.click(screen.getByRole('button', { name: '查询' }));
await waitFor(() => { await waitFor(() => {
@@ -3500,7 +3500,7 @@ test('shows unified service overview on vehicle detail', async () => {
serviceStatus: { serviceStatus: {
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '部分来源离线', title: '来源不完整',
detail: '2/3 个来源在线', detail: '2/3 个来源在线',
sourceCount: 3, sourceCount: 3,
onlineSourceCount: 2 onlineSourceCount: 2
@@ -3569,7 +3569,7 @@ test('shows vehicle service evidence chain before source details', async () => {
serviceStatus: { serviceStatus: {
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '部分来源离线', title: '来源不完整',
detail: '2/3 个来源在线', detail: '2/3 个来源在线',
sourceCount: 3, sourceCount: 3,
onlineSourceCount: 2 onlineSourceCount: 2
@@ -3583,7 +3583,7 @@ test('shows vehicle service evidence chain before source details', async () => {
scope: 'vehicle', scope: 'vehicle',
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '部分来源离线', title: '来源不完整',
detail: 'MQTT 离线32960 与 808 仍可支撑车辆服务' detail: 'MQTT 离线32960 与 808 仍可支撑车辆服务'
}, },
sources: ['GB32960', 'JT808', 'YUTONG_MQTT'], sources: ['GB32960', 'JT808', 'YUTONG_MQTT'],
@@ -4145,7 +4145,7 @@ test('shows selected source scope on vehicle detail', async () => {
serviceStatus: { serviceStatus: {
status: 'degraded', status: 'degraded',
severity: 'warning', severity: 'warning',
title: '部分来源离线', title: '来源不完整',
detail: '1/2 个来源在线,车辆服务可用但需要关注离线来源。', detail: '1/2 个来源在线,车辆服务可用但需要关注离线来源。',
sourceCount: 2, sourceCount: 2,
onlineSourceCount: 1 onlineSourceCount: 1
@@ -4178,7 +4178,7 @@ test('shows selected source scope on vehicle detail', async () => {
expect(await screen.findByText('当前查看范围')).toBeInTheDocument(); expect(await screen.findByText('当前查看范围')).toBeInTheDocument();
expect(screen.getByText('单一来源JT808')).toBeInTheDocument(); expect(screen.getByText('单一来源JT808')).toBeInTheDocument();
expect(screen.getByText('车辆服务状态')).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); expect(fetchMock).toHaveBeenCalledWith(expect.stringContaining('/api/vehicle-service?keyword=VIN001&protocol=JT808'), undefined);
}); });