feat(platform): sharpen dashboard around customer vehicle workflows

This commit is contained in:
lingniu
2026-07-05 15:19:10 +08:00
parent dd6c63b72b
commit b4bcfbb77a
2 changed files with 56 additions and 56 deletions

View File

@@ -197,7 +197,7 @@ function focusVehicleFromIssue(row: QualityIssueRow): FocusVehicleService {
realtimeEvidence: `来源 ${qualityProtocolLabel(row.protocol)} / 最后 ${row.lastSeen || '-'}`,
historyEvidence: filters.dateFrom ? `${filters.dateFrom}${filters.dateTo}` : '待确认时间窗',
alertEvidence: row.detail || qualityIssueLabel(row.issueType),
statisticEvidence: '里程统计需回溯车辆口径',
statisticEvidence: '统计查询需回溯车辆口径',
issueType: row.issueType
};
}
@@ -411,7 +411,7 @@ export function Dashboard({
onClick: () => onOpenHistory()
},
{
title: '里程统计',
title: '统计查询',
value: `${formatCount(serviceSummary?.totalVehicles)} 辆可统计`,
detail: '按自定义时间查询区间里程、日里程和异常记录。',
action: '查看统计',
@@ -449,9 +449,9 @@ export function Dashboard({
},
{
step: '04',
title: '统计里程',
title: '统计查询',
detail: '用同一时间窗核对区间里程和每日统计。',
action: '里程统计',
action: '统计查询',
onClick: () => onOpenMileage({})
},
{
@@ -525,10 +525,10 @@ export function Dashboard({
{
title: '按时间窗复盘',
value: taskTimeMonitorSummary,
detail: '同一时间窗贯穿轨迹、里程、原始记录和告警,不需要跨页面重复输入。',
detail: '同一时间窗贯穿轨迹、统计、原始记录和告警,不需要跨页面重复输入。',
color: 'blue' as const,
primaryAction: '轨迹回放',
secondaryAction: '里程统计',
secondaryAction: '统计查询',
onPrimary: () => openTimeMonitorHistory(),
onSecondary: () => openTimeMonitorMileage()
},
@@ -595,10 +595,10 @@ export function Dashboard({
onClick: () => onOpenQuality()
},
{
title: '里程统计',
title: '统计查询',
status: `统计车辆 ${formatCount(serviceSummary?.totalVehicles)}`,
color: 'green' as const,
description: '提供里程等运营统计,保证区间总值与每日统计口径闭合。',
description: '提供里程等运营统计查询,保证区间总值与每日统计口径闭合。',
action: '查看统计',
onClick: () => onOpenMileage()
}
@@ -622,7 +622,7 @@ export function Dashboard({
{
title: '一车一统计',
value: formatCount(serviceSummary?.totalVehicles),
detail: '里程等运营指标按车辆口径闭合,再回溯到来源证据。'
detail: '统计指标按车辆口径闭合,再回溯到来源证据。'
}
];
const workflowSteps = [
@@ -670,8 +670,8 @@ export function Dashboard({
title: '统计复核',
value: `${formatCount(serviceSummary?.totalVehicles)} 车辆`,
color: 'green' as const,
detail: '核对里程统计口径,保证区间统计和每日统计闭合。',
action: '里程统计',
detail: '核对统计查询口径,保证区间统计和每日统计闭合。',
action: '统计查询',
onClick: () => onOpenMileage()
}
];
@@ -777,13 +777,13 @@ export function Dashboard({
]
},
{
title: '里程统计',
title: '统计查询',
value: `${formatCount(serviceSummary?.totalVehicles)} 车辆口径`,
meta: '区间闭合复核',
color: 'green' as const,
detail: '里程等指标先按车辆口径闭合,再回溯轨迹和原始记录。',
detail: '统计指标先按车辆口径闭合,再回溯轨迹和原始记录。',
actions: [
{ label: '打开里程统计', onClick: () => onOpenMileage() },
{ label: '打开统计查询', onClick: () => onOpenMileage() },
{ label: '查看车辆中心', onClick: () => onOpenVehicles({}) }
]
}
@@ -831,7 +831,7 @@ export function Dashboard({
{
label: '复盘时间',
value: timeMonitorScope().dateFrom || timeMonitorScope().dateTo ? `${timeMonitorScope().dateFrom || '-'}${timeMonitorScope().dateTo || '-'}` : '全部时间',
detail: '同步带入轨迹、里程、历史证据和告警',
detail: '同步带入轨迹、统计、历史证据和告警',
color: 'blue' as const
},
{
@@ -926,7 +926,7 @@ export function Dashboard({
`范围:${timeMonitorSummary}`,
`交付结论:${timeMonitorDeliveryStatus.label}${timeMonitorDeliveryStatus.detail}`,
`时间窗判定:${dayRangeText(scope.dateFrom, scope.dateTo)}`,
'平台能力:实时地图 / 轨迹回放 / 里程统计 / 历史数据查询 / 告警通知',
'平台能力:实时地图 / 轨迹回放 / 统计查询 / 历史数据查询 / 告警通知',
`车辆范围:${scope.keyword || '全部车辆'}`,
`数据通道:${scope.protocol || '全部数据通道'}`,
`时间范围:${scope.dateFrom || '-'}${scope.dateTo || '-'}`,
@@ -939,7 +939,7 @@ export function Dashboard({
'下一步动作:',
...timeMonitorDeliveryActions.map((item, index) => `${index + 1}. ${item.label}${item.value}${item.detail}`),
`轨迹回放:${appURL(buildAppHash({ page: 'history', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`,
`里程统计:${appURL(buildAppHash({ page: 'mileage', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`,
`统计查询${appURL(buildAppHash({ page: 'mileage', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`,
`历史数据查询:${appURL(buildAppHash({ page: 'history-query', keyword: scope.keyword, protocol: scope.protocol, filters: rawFilters }))}`,
`告警通知:${appURL(buildAppHash({ page: 'alert-events', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`,
`实时地图:${appURL(buildAppHash({ page: 'map', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`
@@ -1032,7 +1032,7 @@ export function Dashboard({
owner: '告警 / 统计',
evidence: `告警 ${formatCount(summary?.issueVehicles)},统计车辆 ${formatCount(serviceSummary?.totalVehicles)}`,
detail: '断链、缺字段、里程异常和离线时长进入通知、统计和复核工作流。',
action: '里程统计',
action: '统计查询',
onClick: () => onOpenMileage()
}
];
@@ -1078,11 +1078,11 @@ export function Dashboard({
onSecondary: () => onOpenQuality(highPriorityIssue?.issueType ? { issueType: highPriorityIssue.issueType } : {})
},
{
title: '里程统计',
title: '统计查询',
objective: '按车辆口径查询里程等指标,保证区间统计和日统计可闭合。',
evidence: `车辆口径 ${formatCount(serviceSummary?.totalVehicles)} / 区间统计可追溯轨迹证据`,
sla: '统计值必须能追溯轨迹和原始记录',
primaryAction: '里程统计',
primaryAction: '统计查询',
secondaryAction: '车辆中心',
onPrimary: () => onOpenMileage(),
onSecondary: () => onOpenVehicles({})
@@ -1109,7 +1109,7 @@ export function Dashboard({
`轨迹回放:${appURL(buildAppHash({ page: 'history', keyword: highPriorityFilters?.keyword, protocol: highPriorityFilters?.protocol, filters: highPriorityFilters }))}`,
`原始记录:${appURL(buildAppHash({ page: 'history-query', keyword: highPriorityFilters?.keyword, protocol: highPriorityFilters?.protocol, filters: { ...highPriorityFilters, tab: 'raw', includeFields: 'true' } }))}`,
`告警事件:${appURL(buildAppHash({ page: 'alert-events', filters: highPriorityIssue?.issueType ? { issueType: highPriorityIssue.issueType } : {} }))}`,
`里程统计:${appURL(buildAppHash({ page: 'mileage', keyword: highPriorityLookupKey, protocol: highPriorityIssue?.protocol }))}`,
`统计查询${appURL(buildAppHash({ page: 'mileage', keyword: highPriorityLookupKey, protocol: highPriorityIssue?.protocol }))}`,
`车辆服务:${appURL(buildAppHash({ page: 'detail', keyword: highPriorityLookupKey, protocol: highPriorityIssue?.protocol }))}`
].filter(Boolean);
copyText(lines.join('\n'), '运营交接摘要');
@@ -1149,7 +1149,7 @@ export function Dashboard({
`轨迹回放:${appURL(buildAppHash({ page: 'history' }))}`,
`历史查询:${appURL(buildAppHash({ page: 'history-query', filters: { tab: 'raw', includeFields: 'true' } }))}`,
`告警事件:${appURL(buildAppHash({ page: 'alert-events' }))}`,
`里程统计:${appURL(buildAppHash({ page: 'mileage' }))}`,
`统计查询${appURL(buildAppHash({ page: 'mileage' }))}`,
`运维质量:${appURL(buildAppHash({ page: 'ops-quality' }))}`
];
copyText(lines.join('\n'), '数据流转图');
@@ -1173,7 +1173,7 @@ export function Dashboard({
`实时监控:${appURL(buildAppHash({ page: 'realtime', keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol }))}`,
`轨迹回放:${appURL(buildAppHash({ page: 'history', keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol }))}`,
`原始记录:${appURL(buildAppHash({ page: 'history-query', keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol, filters: { ...commonFilters, tab: 'raw', includeFields: 'true' } }))}`,
`里程统计:${appURL(buildAppHash({ page: 'mileage', keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol }))}`,
`统计查询${appURL(buildAppHash({ page: 'mileage', keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol }))}`,
`告警事件:${appURL(buildAppHash({ page: 'alert-events', keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol, filters: focusVehicle.issueType ? { issueType: focusVehicle.issueType } : {} }))}`
];
copyText(lines.join('\n'), '重点车辆服务处置卡');
@@ -1274,10 +1274,10 @@ export function Dashboard({
{
title: '自定义时间复盘',
value: taskTimeMonitorSummary,
detail: '一个时间窗贯穿轨迹回放、里程统计、历史查询和告警复盘,适合客户问询与 BI 核对。',
detail: '一个时间窗贯穿轨迹回放、统计查询、历史查询和告警复盘,适合客户问询与 BI 核对。',
color: 'blue' as const,
primaryAction: '轨迹复盘',
secondaryAction: '里程统计',
secondaryAction: '统计查询',
onPrimary: () => openTimeMonitorHistory(),
onSecondary: () => openTimeMonitorMileage()
},
@@ -1312,7 +1312,7 @@ export function Dashboard({
{
title: '复盘时间',
value: dayRangeText(timeMonitorScopeValue.dateFrom, timeMonitorScopeValue.dateTo),
detail: '同一个时间窗贯穿轨迹回放、里程统计、原始记录和告警复盘。',
detail: '同一个时间窗贯穿轨迹回放、统计查询、原始记录和告警复盘。',
action: '轨迹回放',
color: 'blue' as const,
onClick: openTimeMonitorHistory
@@ -1347,13 +1347,13 @@ export function Dashboard({
'客户服务路径:',
'1. 找车:先按 VIN、车牌、手机号或 OEM 锁定车辆。',
'2. 看位置:打开实时地图确认车辆在线、坐标和最新上报。',
'3. 复盘时间:同一时间窗查看轨迹、里程和告警。',
'3. 复盘时间:同一时间窗查看轨迹、统计和告警。',
'4. 交付数据:按车辆、时间、字段导出位置历史、原始记录和字段明细。',
'5. 闭环异常:告警事件进入通知和处置流程。',
`车辆中心:${appURL(buildAppHash({ page: 'vehicles' }))}`,
`实时地图:${appURL(buildAppHash({ page: 'map', filters: { online: 'online' } }))}`,
`轨迹回放:${appURL(buildAppHash({ page: 'history', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`,
`里程统计:${appURL(buildAppHash({ page: 'mileage', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`,
`统计查询${appURL(buildAppHash({ page: 'mileage', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`,
`历史数据:${appURL(buildAppHash({ page: 'history-query', keyword: scope.keyword, protocol: scope.protocol, filters: rawFilters }))}`,
`告警事件:${appURL(buildAppHash({ page: 'alert-events', keyword: scope.keyword, protocol: scope.protocol, filters: scope }))}`
];
@@ -1440,7 +1440,7 @@ export function Dashboard({
{
level: focusVehicle ? '单车' : '范围',
title: focusVehicle ? '复盘重点车辆' : '选择一辆车复盘',
detail: focusVehicle ? `${focusVehicle.label}${focusVehicle.reason}` : '从车辆中心或地图选择车辆后,进入轨迹、里程和历史证据。',
detail: focusVehicle ? `${focusVehicle.label}${focusVehicle.reason}` : '从车辆中心或地图选择车辆后,进入轨迹、统计和历史证据。',
action: focusVehicle ? '车辆服务' : '车辆中心',
color: focusVehicle?.statusColor ?? 'blue' as const,
onClick: () => focusVehicle?.lookupKey ? onOpenVehicle(focusVehicle.lookupKey, focusVehicle.protocol) : onOpenVehicles({})
@@ -1448,7 +1448,7 @@ export function Dashboard({
{
level: '时间窗',
title: '按同一范围交付数据',
detail: `${dayRangeText(timeMonitorScopeValue.dateFrom, timeMonitorScopeValue.dateTo)},同步轨迹、里程、历史和告警。`,
detail: `${dayRangeText(timeMonitorScopeValue.dateFrom, timeMonitorScopeValue.dateTo)},同步轨迹、统计、历史和告警。`,
action: '复制复盘包',
color: 'blue' as const,
onClick: copyTimeMonitorReviewPackage
@@ -1468,13 +1468,13 @@ export function Dashboard({
{
label: '时间窗',
value: dayRangeText(timeMonitorScopeValue.dateFrom, timeMonitorScopeValue.dateTo),
detail: '同一时间范围贯穿轨迹、里程、历史和告警。'
detail: '同一时间范围贯穿轨迹、统计、历史和告警。'
}
];
return (
<div className="vp-page">
<PageHeader title="车辆服务工作台" description="面向客户的车辆地图、实时监控、轨迹回放、里程统计、自定义时间监控、历史查询、告警通知和数据导出" />
<PageHeader title="车辆服务工作台" description="面向客户的车辆地图、实时监控、轨迹回放、统计查询、自定义时间窗复盘、历史查询、告警通知和数据导出" />
<Spin spinning={loading}>
<Card bordered className="vp-fleet-monitor" bodyStyle={{ padding: 0 }}>
<div className="vp-fleet-monitor-map">
@@ -1484,9 +1484,9 @@ export function Dashboard({
<Tag color={amapConfigured ? 'green' : 'orange'}>{amapConfigured ? '高德地图可用' : '坐标预览'}</Tag>
<Tag color={(summary?.issueVehicles ?? 0) > 0 ? 'orange' : 'green'}>{formatCount(summary?.issueVehicles)} </Tag>
</Space>
<Typography.Title heading={3} style={{ margin: 0 }}></Typography.Title>
<Typography.Title heading={3} style={{ margin: 0 }}></Typography.Title>
<Typography.Text type="secondary">
</Typography.Text>
</div>
<VehicleMap
@@ -1563,7 +1563,7 @@ export function Dashboard({
</Card>
<Card
bordered
title={<Space><span></span><Tag color="blue">{timeMonitorSummary}</Tag></Space>}
title={<Space><span></span><Tag color="blue">{timeMonitorSummary}</Tag></Space>}
style={{ marginBottom: 16 }}
>
<Form
@@ -1590,12 +1590,12 @@ export function Dashboard({
</Form>
<div className="vp-time-monitor-actions">
<Button theme="solid" type="primary" onClick={openTimeMonitorHistory}></Button>
<Button theme="light" type="primary" onClick={openTimeMonitorMileage}></Button>
<Button theme="light" type="primary" onClick={openTimeMonitorMileage}></Button>
<Button theme="light" type="primary" onClick={openTimeMonitorRaw}></Button>
<Button theme="light" type="warning" onClick={openTimeMonitorAlerts}></Button>
</div>
<Typography.Text type="secondary">
</Typography.Text>
<div className="vp-time-review-package">
<div className="vp-time-review-summary">
@@ -1605,12 +1605,12 @@ export function Dashboard({
</Space>
<Typography.Title heading={5} style={{ margin: 0 }}>{timeMonitorSummary}</Typography.Title>
<Typography.Text type="secondary">
</Typography.Text>
<Space wrap>
<Button size="small" theme="solid" type="primary" onClick={copyTimeMonitorReviewPackage}></Button>
<Button size="small" theme="light" type="primary" onClick={openTimeMonitorHistory}></Button>
<Button size="small" theme="light" type="primary" onClick={openTimeMonitorMileage}></Button>
<Button size="small" theme="light" type="primary" onClick={openTimeMonitorMileage}></Button>
<Button size="small" theme="light" type="primary" onClick={openTimeMonitorRaw}></Button>
<Button size="small" theme="light" type="warning" onClick={openTimeMonitorAlerts}></Button>
</Space>
@@ -1676,7 +1676,7 @@ export function Dashboard({
</Space>
<strong>{timeMonitorSummary}</strong>
<Typography.Text type="secondary">
BI
BI
</Typography.Text>
</div>
<div className="vp-time-monitor-work-grid">
@@ -1700,7 +1700,7 @@ export function Dashboard({
{[
{ title: '今天车辆轨迹', detail: '查看当天活跃车辆的轨迹、速度和里程断点。', action: '查今天', onClick: openTimeMonitorHistory },
{ title: '历史时间窗', detail: '按任意起止时间查询位置历史、原始记录和字段明细。', action: '自定义查询', onClick: openTimeMonitorRaw },
{ title: '区间里程', detail: '按车辆和时间范围核对区间里程、日统计和异常点。', action: '里程统计', onClick: openTimeMonitorMileage },
{ title: '统计查询', detail: '按车辆和时间范围核对区间里程、日统计和异常点。', action: '统计查询', onClick: openTimeMonitorMileage },
{ title: '告警复盘', detail: '按车辆或事件回放告警发生前后的轨迹和数据证据。', action: '告警事件', onClick: openTimeMonitorAlerts }
].map((item) => (
<button key={item.title} type="button" className="vp-time-monitor-item" onClick={item.onClick} aria-label={`时间监控 ${item.title}`}>
@@ -1911,7 +1911,7 @@ export function Dashboard({
<Button size="small" theme="light" aria-label="重点车辆 实时监控" disabled={!focusVehicle.lookupKey} onClick={() => onOpenRealtime({ keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol ?? '' })}></Button>
<Button size="small" theme="light" aria-label="重点车辆 轨迹回放" disabled={!focusVehicle.lookupKey} onClick={() => onOpenHistory({ keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol ?? '' })}></Button>
<Button size="small" theme="light" aria-label="重点车辆 原始记录" disabled={!focusVehicle.lookupKey} onClick={() => onOpenHistory({ keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol ?? '', tab: 'raw', includeFields: 'true' })}></Button>
<Button size="small" theme="light" aria-label="重点车辆 里程统计" disabled={!focusVehicle.lookupKey} onClick={() => onOpenMileage({ keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol ?? '' })}></Button>
<Button size="small" theme="light" aria-label="重点车辆 统计查询" disabled={!focusVehicle.lookupKey} onClick={() => onOpenMileage({ keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol ?? '' })}></Button>
<Button size="small" theme="light" type="warning" aria-label="重点车辆 告警事件" onClick={() => onOpenQuality({ keyword: focusVehicle.lookupKey, protocol: focusVehicle.protocol ?? '', ...(focusVehicle.issueType ? { issueType: focusVehicle.issueType } : {}) })}></Button>
</Space>
</div>

View File

@@ -798,8 +798,8 @@ 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.getByRole('button', { name: '车辆监控指标 车辆总数 1,033' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆监控指标 在线车辆 208' })).toBeInTheDocument();
expect(screen.getByText('今日先处理')).toBeInTheDocument();
@@ -844,12 +844,12 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
expect(screen.getByRole('button', { name: '车辆服务入口 找车 车辆中心' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: '车辆服务入口 看位置 实时地图' })).toBeInTheDocument();
expect(screen.getAllByRole('button', { name: '复制客户服务说明' }).length).toBeGreaterThanOrEqual(1);
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.getAllByText('复盘时间').length).toBeGreaterThanOrEqual(1);
expect(screen.getByText('统计证据')).toBeInTheDocument();
@@ -866,9 +866,9 @@ 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.getByText('这个范围会同步带入轨迹、里程、历史证据和告警复盘适合客户问询、BI 核对和异常解释。')).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);
@@ -878,7 +878,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
expect(screen.getByRole('button', { name: '时间窗作业 历史证据 导出证据' })).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(screen.getByText('来源覆盖、地图配置、告警预览和实时证据默认收起,客户主流程先看车辆监控、轨迹、统计、告警和导出。')).toBeInTheDocument();
@@ -898,7 +898,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();
@@ -930,7 +930,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();
@@ -967,7 +967,7 @@ test('dashboard exposes vehicle data center capability matrix', async () => {
cleanup();
await renderDashboard();
fireEvent.click(screen.getByRole('button', { name: '统计里程' }));
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();
@@ -1003,7 +1003,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();
@@ -1051,7 +1051,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);
});
@@ -1465,10 +1465,10 @@ test('dashboard exposes end-to-end operations workflow entries', 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();
expect(screen.getAllByText('统计查询').length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText('告警复盘').length).toBeGreaterThanOrEqual(1);
fireEvent.click(screen.getByRole('button', { name: '时间监控 今天车辆轨迹' }));