feat(platform): add realtime operations impact board
This commit is contained in:
@@ -396,6 +396,46 @@ function realtimeDutyHandoffText({
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function realtimeImpactReportText({
|
||||
filters,
|
||||
rows,
|
||||
total,
|
||||
onlineCount,
|
||||
locatedCount,
|
||||
degradedCount,
|
||||
staleCount,
|
||||
pageCoverageRate,
|
||||
amapConfigured,
|
||||
runtimeRelease
|
||||
}: {
|
||||
filters: Record<string, string>;
|
||||
rows: VehicleRealtimeRow[];
|
||||
total: number;
|
||||
onlineCount: number;
|
||||
locatedCount: number;
|
||||
degradedCount: number;
|
||||
staleCount: number;
|
||||
pageCoverageRate: number;
|
||||
amapConfigured: boolean;
|
||||
runtimeRelease?: string;
|
||||
}) {
|
||||
const offlineCount = Math.max(0, rows.length - onlineCount);
|
||||
const impactLevel = degradedCount > 0 || staleCount > 0 || offlineCount > 0 ? '需要处置' : '实时稳定';
|
||||
return [
|
||||
'【实时运营影响】',
|
||||
`当前筛选:${realtimeFilterSummary(filters).join(';') || '全部实时车辆'}`,
|
||||
`运行版本:${runtimeRelease || '未标记'}`,
|
||||
`影响等级:${impactLevel}`,
|
||||
`车辆范围:当前页 ${rows.length.toLocaleString()} / 总计 ${total.toLocaleString()},覆盖率 ${formatPercent(pageCoverageRate)}`,
|
||||
`在线状态:${onlineCount.toLocaleString()} 在线 / ${offlineCount.toLocaleString()} 离线`,
|
||||
`定位影响:${locatedCount.toLocaleString()} 辆有有效坐标`,
|
||||
`服务影响:${degradedCount.toLocaleString()} 辆降级 / ${staleCount.toLocaleString()} 辆超时`,
|
||||
`地图能力:${amapConfigured ? '高德地图可用' : '高德地图未配置,使用坐标预览'}`,
|
||||
`建议动作:${impactLevel === '实时稳定' ? '保持监控并关注告警队列' : '优先处理离线、超时和来源不完整车辆,并回到轨迹/RAW证据复核'}`,
|
||||
`实时监控:${appURL(buildAppHash({ page: 'realtime', protocol: filters.protocol, filters }))}`
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
function buildRealtimeSourceCoverage(rows: VehicleRealtimeRow[]) {
|
||||
const sourceMap = new Map<string, RealtimeSourceCoverage>();
|
||||
rows.forEach((row) => {
|
||||
@@ -624,6 +664,52 @@ export function Realtime({
|
||||
amapConfigured,
|
||||
runtimeRelease: runtime?.platformRelease
|
||||
}), '实时值班交接包');
|
||||
const realtimeImpactLevel = degradedCount > 0 || staleCount > 0 || rows.length - onlineCount > 0 ? '需要处置' : '实时稳定';
|
||||
const realtimeImpactColor = realtimeImpactLevel === '实时稳定' ? 'green' as const : degradedCount > 0 || staleCount > 0 ? 'orange' as const : 'blue' as const;
|
||||
const realtimeImpactItems = [
|
||||
{
|
||||
label: '车辆范围',
|
||||
value: `${rows.length.toLocaleString()} / ${pagination.total.toLocaleString()}`,
|
||||
detail: `当前页覆盖 ${formatPercent(pageCoverageRate)}`,
|
||||
color: pageCoverageRate >= 100 ? 'green' as const : 'grey' as const
|
||||
},
|
||||
{
|
||||
label: '在线影响',
|
||||
value: `${onlineCount.toLocaleString()} 在线`,
|
||||
detail: `${(rows.length - onlineCount).toLocaleString()} 辆离线`,
|
||||
color: rows.length - onlineCount > 0 ? 'orange' as const : 'green' as const
|
||||
},
|
||||
{
|
||||
label: '定位影响',
|
||||
value: `${locatedCount.toLocaleString()} 辆`,
|
||||
detail: `有效定位率 ${formatPercent(locatedRate)}`,
|
||||
color: locatedCount > 0 ? 'blue' as const : 'orange' as const
|
||||
},
|
||||
{
|
||||
label: '服务影响',
|
||||
value: `${degradedCount.toLocaleString()} 降级`,
|
||||
detail: `${staleCount.toLocaleString()} 辆更新超时`,
|
||||
color: degradedCount > 0 || staleCount > 0 ? 'orange' as const : 'green' as const
|
||||
},
|
||||
{
|
||||
label: '地图能力',
|
||||
value: amapConfigured ? '可用' : '坐标预览',
|
||||
detail: amapConfigured ? '高德地图配置就绪' : '高德未配置,页面降级展示坐标。',
|
||||
color: amapConfigured ? 'green' as const : 'orange' as const
|
||||
}
|
||||
];
|
||||
const copyRealtimeImpact = () => copyText(realtimeImpactReportText({
|
||||
filters,
|
||||
rows,
|
||||
total: pagination.total,
|
||||
onlineCount,
|
||||
locatedCount,
|
||||
degradedCount,
|
||||
staleCount,
|
||||
pageCoverageRate,
|
||||
amapConfigured,
|
||||
runtimeRelease: runtime?.platformRelease
|
||||
}), '实时运营影响');
|
||||
const selectRealtimeRow = (row: VehicleRealtimeRow) => {
|
||||
const index = rows.indexOf(row);
|
||||
if (index < 0) return;
|
||||
@@ -931,6 +1017,35 @@ export function Realtime({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Card
|
||||
bordered
|
||||
title={<Space><span>实时运营影响</span><Button size="small" icon={<IconCopy />} onClick={copyRealtimeImpact}>复制影响报告</Button></Space>}
|
||||
style={{ marginBottom: 16 }}
|
||||
>
|
||||
<div className="vp-realtime-impact-board">
|
||||
<div className="vp-realtime-impact-summary">
|
||||
<Tag color={realtimeImpactColor}>{realtimeImpactLevel}</Tag>
|
||||
<div className="vp-monitor-metric-value">{pagination.total.toLocaleString()} 辆</div>
|
||||
<Typography.Text type="secondary">
|
||||
当前页 {rows.length.toLocaleString()} 辆,在线 {onlineCount.toLocaleString()} 辆,定位有效 {locatedCount.toLocaleString()} 辆,降级 {degradedCount.toLocaleString()} 辆,超时 {staleCount.toLocaleString()} 辆。
|
||||
</Typography.Text>
|
||||
<Space wrap>
|
||||
<Tag color={pageCoverageRate >= 100 ? 'green' : 'grey'}>覆盖 {formatPercent(pageCoverageRate)}</Tag>
|
||||
<Tag color={amapConfigured ? 'green' : 'orange'}>{amapConfigured ? '高德可用' : '坐标预览'}</Tag>
|
||||
<Tag color={rows.length - onlineCount > 0 ? 'orange' : 'green'}>{(rows.length - onlineCount).toLocaleString()} 辆离线</Tag>
|
||||
</Space>
|
||||
</div>
|
||||
<div className="vp-realtime-impact-grid">
|
||||
{realtimeImpactItems.map((item) => (
|
||||
<div key={item.label} className="vp-realtime-impact-item">
|
||||
<Tag color={item.color}>{item.label}</Tag>
|
||||
<strong>{item.value}</strong>
|
||||
<Typography.Text type="secondary">{item.detail}</Typography.Text>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card bordered title="实时覆盖判读" style={{ marginBottom: 16 }}>
|
||||
<div className="vp-stat-insight-grid">
|
||||
{[
|
||||
|
||||
Reference in New Issue
Block a user