feat(platform): add vehicle service decision board
This commit is contained in:
@@ -599,6 +599,53 @@ export function Vehicles({
|
||||
onClick: exportVehicles
|
||||
}
|
||||
], [exportVehicles, filters.keyword, onOpenHistory, onOpenMap, onOpenMileage, onOpenRealtime, rows.length, serviceScopeFilters, summary?.onlineVehicles]);
|
||||
const primaryAction = actionQueue[0];
|
||||
const vehicleDecisionItems = [
|
||||
{
|
||||
title: '在线车辆',
|
||||
value: `${(summary?.onlineVehicles ?? 0).toLocaleString()} 辆`,
|
||||
detail: '先看当前仍在上报的车辆,直接进入地图和实时状态。',
|
||||
color: 'green' as const,
|
||||
primaryAction: '实时监控',
|
||||
secondaryAction: '车辆地图',
|
||||
onPrimary: () => onOpenRealtime?.({ ...serviceScopeFilters, online: 'online' }),
|
||||
onSecondary: () => onOpenMap?.({ ...serviceScopeFilters, online: 'online' }),
|
||||
disabled: !onOpenRealtime
|
||||
},
|
||||
{
|
||||
title: '异常车辆',
|
||||
value: `${(summary?.noDataVehicles ?? 0).toLocaleString()} 无来源`,
|
||||
detail: primaryAction ? primaryAction.detail : '当前没有必须立即处理的车辆服务事项。',
|
||||
color: (summary?.noDataVehicles ?? 0) > 0 || primaryAction ? 'orange' as const : 'green' as const,
|
||||
primaryAction: primaryAction?.label ?? '查看结果',
|
||||
secondaryAction: '告警事件',
|
||||
onPrimary: () => primaryAction ? applyFilters({ ...filters, ...primaryAction.filters }) : applyFilters(filters),
|
||||
onSecondary: () => onOpenQuality?.(serviceScopeFilters),
|
||||
disabled: !primaryAction
|
||||
},
|
||||
{
|
||||
title: '单车服务',
|
||||
value: filters.keyword?.trim() || '输入车辆',
|
||||
detail: filters.keyword?.trim() ? '当前已进入单车范围,可查看车辆详情、轨迹和里程。' : '输入 VIN、车牌或手机号后进入完整车辆服务。',
|
||||
color: filters.keyword?.trim() ? 'blue' as const : 'grey' as const,
|
||||
primaryAction: '车辆详情',
|
||||
secondaryAction: '轨迹回放',
|
||||
onPrimary: () => filters.keyword?.trim() && onOpenVehicle(filters.keyword.trim(), filters.protocol),
|
||||
onSecondary: () => onOpenHistory?.({ ...serviceScopeFilters, tab: 'location' }),
|
||||
disabled: !filters.keyword?.trim()
|
||||
},
|
||||
{
|
||||
title: '数据交付',
|
||||
value: `${rows.length.toLocaleString()} 当前页`,
|
||||
detail: '导出当前车辆清单,继续进入历史页交付轨迹、RAW 和字段证据。',
|
||||
color: rows.length > 0 ? 'blue' as const : 'grey' as const,
|
||||
primaryAction: '导出清单',
|
||||
secondaryAction: '历史导出',
|
||||
onPrimary: exportVehicles,
|
||||
onSecondary: () => onOpenHistory?.({ ...serviceScopeFilters, tab: 'raw', includeFields: 'true' }),
|
||||
disabled: rows.length === 0
|
||||
}
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
setFilters(initialFilters);
|
||||
@@ -742,6 +789,41 @@ export function Vehicles({
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card bordered title="车辆服务决策板" style={{ marginTop: 16 }}>
|
||||
<div className="vp-vehicle-decision-grid">
|
||||
{vehicleDecisionItems.map((item) => (
|
||||
<div key={item.title} className="vp-vehicle-decision-item">
|
||||
<div className="vp-vehicle-decision-head">
|
||||
<Tag color={item.color}>{item.title}</Tag>
|
||||
<strong>{item.value}</strong>
|
||||
</div>
|
||||
<span>{item.detail}</span>
|
||||
<Space wrap>
|
||||
<Button
|
||||
size="small"
|
||||
theme="solid"
|
||||
type="primary"
|
||||
disabled={item.disabled}
|
||||
aria-label={`车辆服务决策 ${item.title} ${item.primaryAction}`}
|
||||
onClick={item.onPrimary}
|
||||
>
|
||||
{item.primaryAction}
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
theme="light"
|
||||
type="primary"
|
||||
disabled={item.title === '单车服务' && item.disabled}
|
||||
aria-label={`车辆服务决策 ${item.title} ${item.secondaryAction}`}
|
||||
onClick={item.onSecondary}
|
||||
>
|
||||
{item.secondaryAction}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
<Card bordered>
|
||||
<Form key={JSON.stringify(filters)} initValues={filters} layout="horizontal" onSubmit={(values) => {
|
||||
const nextFilters = values as Record<string, string>;
|
||||
|
||||
Reference in New Issue
Block a user