feat(platform): add fleet service journey strip

This commit is contained in:
lingniu
2026-07-06 05:39:57 +08:00
parent 0cb1763326
commit fe005a8296
3 changed files with 184 additions and 0 deletions

View File

@@ -1840,6 +1840,62 @@ export function Realtime({
selectedProtocol: selectedVehicleProtocol,
amapConfigured
}), '客户车辆地图总控包');
const copyMapFleetJourneyPackage = () => copyText([
'【车队服务旅程交付包】',
`当前筛选:${realtimeFilterSummary(filters).join('') || '全部车辆'}`,
`实时找车:${onlineCount.toLocaleString()} 在线 / ${rows.length.toLocaleString()} 当前页 / ${pagination.total.toLocaleString()} 总计`,
`轨迹复盘:${selectedMapRow ? `${selectedMapRow.plate || '-'} / ${selectedMapRow.vin || '-'} / ${selectedVehicleProtocol || selectedMapRow.primaryProtocol || '-'}` : '未选择车辆'}`,
`里程核对:${selectedMapRow?.totalMileageKm != null ? `${selectedMapRow.totalMileageKm} km` : '待核对'}`,
`导出通知:${mapAttentionRows.length.toLocaleString()} 关注 / ${staleCount.toLocaleString()} 更新超时`,
`实时地图:${appURL(buildAppHash({ page: 'map', protocol: filters.protocol, filters }))}`,
selectedMapRow && canOpenVehicle(selectedMapRow.vin) ? `车辆服务:${appURL(buildAppHash({ page: 'detail', keyword: selectedMapRow.vin, protocol: selectedVehicleProtocol }))}` : '',
selectedMapRow && canOpenVehicle(selectedMapRow.vin) ? `轨迹回放:${appURL(buildAppHash({ page: 'history', keyword: selectedMapRow.vin, protocol: selectedVehicleProtocol }))}` : '',
selectedMapRow && canOpenVehicle(selectedMapRow.vin) ? `里程统计:${appURL(buildAppHash({ page: 'mileage', keyword: selectedMapRow.vin, protocol: selectedVehicleProtocol }))}` : '',
selectedMapRow && canOpenVehicle(selectedMapRow.vin) ? `历史导出:${appURL(buildAppHash({ page: 'history-query', keyword: selectedMapRow.vin, protocol: selectedVehicleProtocol, filters: { tab: 'raw', includeFields: 'true' } }))}` : '',
`告警通知:${appURL(buildAppHash({ page: 'alert-events', filters: { serviceStatus: 'degraded', ...(filters.protocol ? { protocol: filters.protocol } : {}) } }))}`
].filter(Boolean).join('\n'), '车队服务旅程交付包');
const mapFleetJourneyItems = [
{
step: '1',
title: '实时找车',
value: `${onlineCount.toLocaleString()} 在线`,
detail: `${locatedCount.toLocaleString()} 辆有定位,先让客户知道当前能看到哪些车。`,
color: onlineCount > 0 ? 'green' as const : 'orange' as const,
disabled: false,
onClick: () => applyFilters({ ...filters, online: 'online' })
},
{
step: '2',
title: '轨迹复盘',
value: selectedVehicleLabel,
detail: selectedMapRow ? `${dataFreshness(selectedMapRow).detail},进入轨迹复盘位置、速度和里程断点。` : '先从地图或车辆列表选择一辆车。',
color: selectedMapRow ? 'blue' as const : 'grey' as const,
disabled: !selectedMapRow || !canOpenVehicle(selectedMapRow.vin),
onClick: () => selectedMapRow && onOpenHistory?.(selectedMapRow.vin, selectedVehicleProtocol)
},
{
step: '3',
title: '里程核对',
value: selectedMapRow?.totalMileageKm != null ? `${selectedMapRow.totalMileageKm} km` : '待核对',
detail: '进入同一车辆的里程统计,核对区间差值、日统计和总里程。',
color: selectedMapRow?.totalMileageKm != null ? 'blue' as const : 'orange' as const,
disabled: !selectedMapRow || !canOpenVehicle(selectedMapRow.vin),
onClick: () => selectedMapRow && (window.location.hash = buildAppHash({
page: 'mileage',
keyword: selectedMapRow.vin,
protocol: selectedVehicleProtocol
}))
},
{
step: '4',
title: '导出通知',
value: `${mapAttentionRows.length.toLocaleString()} 关注`,
detail: `${staleCount.toLocaleString()} 辆更新超时,交付前进入告警通知或复制交付包。`,
color: mapAttentionRows.length > 0 ? 'orange' as const : 'green' as const,
disabled: false,
onClick: () => mapAttentionRows.length > 0 && onOpenQuality ? onOpenQuality({ serviceStatus: 'degraded', protocol: filters.protocol }) : copyMapFleetJourneyPackage()
}
];
const copyMapCustomerDecision = () => copyText(mapCustomerDecisionText({
filters,
rows,
@@ -2412,6 +2468,46 @@ export function Realtime({
</aside>
</section>
<section className="vp-map-fleet-journey" aria-label="车队服务旅程条">
<div className="vp-map-fleet-journey-copy">
<Space wrap>
<Tag color="blue"></Tag>
<Tag color={mapAttentionRows.length > 0 ? 'orange' : 'green'}>
{mapAttentionRows.length > 0 ? `${mapAttentionRows.length.toLocaleString()} 关注` : '态势稳定'}
</Tag>
<Tag color={selectedMapRow ? vehicleServiceStatus(selectedMapRow).color : 'grey'}>
{selectedMapRow ? selectedVehicleLabel : '未选车'}
</Tag>
</Space>
<Typography.Title heading={5} style={{ margin: 0 }}>
</Typography.Title>
<Typography.Text type="secondary">
32960808MQTT 沿
</Typography.Text>
<Button size="small" theme="solid" type="primary" icon={<IconCopy />} onClick={copyMapFleetJourneyPackage}>
</Button>
</div>
<div className="vp-map-fleet-journey-steps">
{mapFleetJourneyItems.map((item) => (
<button
key={item.step}
type="button"
className="vp-map-fleet-journey-step"
disabled={item.disabled}
onClick={item.onClick}
aria-label={`车队服务旅程条 ${item.step} ${item.title} ${item.value}`}
>
<Tag color={item.color}>{item.step}</Tag>
<strong>{item.title}</strong>
<span>{item.value}</span>
<small>{item.detail}</small>
</button>
))}
</div>
</section>
<div className="vp-map-service-rail" aria-label="客户车辆地图总控">
<div className="vp-map-service-rail-summary">
<Space wrap>