feat(platform): add vehicle scenario navigation
This commit is contained in:
@@ -504,6 +504,58 @@ export function Dashboard({
|
||||
]
|
||||
}
|
||||
];
|
||||
const scenarioNavigation = [
|
||||
{
|
||||
title: '实时监控',
|
||||
objective: '确认车辆是否在线、位置是否可信、三类来源是否齐全。',
|
||||
evidence: `Redis 在线态 / 最新定位 / 有效坐标 ${commandLocatedCount.toLocaleString()}`,
|
||||
sla: '目标 0-1 秒内进入实时视图',
|
||||
primaryAction: '实时监控',
|
||||
secondaryAction: '地图态势',
|
||||
onPrimary: () => onOpenRealtime({ online: 'online' }),
|
||||
onSecondary: () => onOpenMap({ online: 'online' })
|
||||
},
|
||||
{
|
||||
title: '轨迹回放',
|
||||
objective: '按车辆复盘位置、速度、里程和断点,定位平台转发或车辆异常。',
|
||||
evidence: `高德轨迹底座 / 今日活跃 ${formatCount(summary?.activeToday)}`,
|
||||
sla: '支持按车辆和时间窗快速回放',
|
||||
primaryAction: '轨迹回放',
|
||||
secondaryAction: 'RAW证据',
|
||||
onPrimary: () => onOpenHistory(),
|
||||
onSecondary: () => onOpenHistory({ tab: 'raw', includeFields: 'true' })
|
||||
},
|
||||
{
|
||||
title: '历史数据查询',
|
||||
objective: '围绕车辆查询位置、RAW、解析字段,给 BI、运维和业务复盘提供证据。',
|
||||
evidence: `TDengine / 今日帧 ${formatCount(summary?.frameToday)} / Kafka Lag ${formatLag(summary?.kafkaLag)}`,
|
||||
sla: '优先返回必要字段,避免大 JSON 拖慢查询',
|
||||
primaryAction: '历史查询',
|
||||
secondaryAction: '字段证据',
|
||||
onPrimary: () => onOpenHistory({ tab: 'location' }),
|
||||
onSecondary: () => onOpenHistory({ tab: 'raw', includeFields: 'true' })
|
||||
},
|
||||
{
|
||||
title: '告警事件触发和通知',
|
||||
objective: '把断链、无来源、VIN 缺失、字段缺失转换为可通知、可闭环事件。',
|
||||
evidence: `告警车辆 ${formatCount(summary?.issueVehicles)} / 最高优先级 ${highPriorityIssue ? qualityIssueLabel(highPriorityIssue.issueType) : '暂无'}`,
|
||||
sla: 'P0 进入通知队列,超时升级',
|
||||
primaryAction: '告警事件',
|
||||
secondaryAction: '通知规则',
|
||||
onPrimary: () => onOpenQuality(),
|
||||
onSecondary: () => onOpenQuality(highPriorityIssue?.issueType ? { issueType: highPriorityIssue.issueType } : {})
|
||||
},
|
||||
{
|
||||
title: '统计查询',
|
||||
objective: '按车辆口径查询里程等指标,保证区间统计和日统计可闭合。',
|
||||
evidence: `车辆口径 ${formatCount(serviceSummary?.totalVehicles)} / 多源覆盖 ${formatCount(serviceSummary?.multiSourceVehicles)}`,
|
||||
sla: '统计值必须能追溯轨迹和 RAW 证据',
|
||||
primaryAction: '统计查询',
|
||||
secondaryAction: '车辆中心',
|
||||
onPrimary: () => onOpenMileage(),
|
||||
onSecondary: () => onOpenVehicles({})
|
||||
}
|
||||
];
|
||||
const copyOperationsHandoff = () => {
|
||||
const unhealthyLinks = (summary?.linkHealth ?? []).filter((item) => item.status !== 'ok');
|
||||
const priorityAction = serviceActionQueue[0];
|
||||
@@ -532,6 +584,24 @@ export function Dashboard({
|
||||
].filter(Boolean);
|
||||
copyText(lines.join('\n'), '运营交接摘要');
|
||||
};
|
||||
const copyScenarioBlueprint = () => {
|
||||
const lines = [
|
||||
'【车辆数据中台功能蓝图】',
|
||||
'定位:32960 / 808 / 宇通 MQTT 都只是车辆服务证据源,最终围绕一辆车提供实时、轨迹、历史、告警、统计能力。',
|
||||
`高德地图:${amapConfigured ? '已配置,前端只使用运行时配置和安全代理' : '待配置'}`,
|
||||
`车辆规模:${formatCount(serviceSummary?.totalVehicles)};在线:${formatCount(serviceSummary?.onlineVehicles ?? summary?.onlineVehicles)};告警:${formatCount(summary?.issueVehicles)}`,
|
||||
'',
|
||||
...scenarioNavigation.map((item, index) => [
|
||||
`${index + 1}. ${item.title}`,
|
||||
` 目标:${item.objective}`,
|
||||
` 证据:${item.evidence}`,
|
||||
` SLA:${item.sla}`
|
||||
].join('\n')),
|
||||
'',
|
||||
`入口:${appURL(buildAppHash({ page: 'dashboard' }))}`
|
||||
];
|
||||
copyText(lines.join('\n'), '功能蓝图');
|
||||
};
|
||||
const buildDashboardSnapshotRows = () => {
|
||||
const unhealthyLinks = (summary?.linkHealth ?? []).filter((item) => item.status !== 'ok');
|
||||
const priorityAction = serviceActionQueue[0];
|
||||
@@ -707,6 +777,32 @@ export function Dashboard({
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
<Card
|
||||
bordered
|
||||
title={<Space><span>车联网场景导航</span><Button size="small" onClick={copyScenarioBlueprint}>复制功能蓝图</Button></Space>}
|
||||
style={{ marginBottom: 16 }}
|
||||
>
|
||||
<div className="vp-scenario-grid">
|
||||
{scenarioNavigation.map((item) => (
|
||||
<div key={item.title} className="vp-scenario-item">
|
||||
<div className="vp-scenario-main">
|
||||
<Typography.Title heading={6} style={{ margin: 0 }}>{item.title}</Typography.Title>
|
||||
<Typography.Text type="secondary">{item.objective}</Typography.Text>
|
||||
</div>
|
||||
<div className="vp-scenario-evidence">{item.evidence}</div>
|
||||
<Tag color="blue">{item.sla}</Tag>
|
||||
<Space wrap>
|
||||
<Button size="small" theme="solid" type="primary" aria-label={`场景导航 ${item.title} ${item.primaryAction}`} onClick={item.onPrimary}>
|
||||
{item.primaryAction}
|
||||
</Button>
|
||||
<Button size="small" theme="light" aria-label={`场景导航 ${item.title} ${item.secondaryAction}`} onClick={item.onSecondary}>
|
||||
{item.secondaryAction}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
<Card bordered title="全链路值班闭环" style={{ marginBottom: 16 }}>
|
||||
<div className="vp-operation-flow">
|
||||
{workflowSteps.map((item, index) => (
|
||||
|
||||
Reference in New Issue
Block a user