feat(platform): copy realtime operations summary
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Button, Card, Form, Select, Space, Table, Tabs, Tag, Toast, Typography } from '@douyinfe/semi-ui';
|
||||
import { IconCopy } from '@douyinfe/semi-icons';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { api } from '../api/client';
|
||||
import type { VehicleRealtimeRow } from '../api/types';
|
||||
@@ -105,6 +106,69 @@ function realtimeExportFileName(filters: Record<string, string>) {
|
||||
return `realtime-vehicles-${keyword}-${protocol}-${online}.csv`;
|
||||
}
|
||||
|
||||
function realtimeFilterSummary(filters: Record<string, string>) {
|
||||
return [
|
||||
filters.keyword ? `关键词:${filters.keyword}` : '',
|
||||
filters.protocol ? `数据来源:${filters.protocol}` : '',
|
||||
filters.online ? `在线:${onlineLabel[filters.online] ?? filters.online}` : '',
|
||||
filters.serviceStatus ? `服务状态:${serviceStatusLabel[filters.serviceStatus] ?? filters.serviceStatus}` : ''
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
function realtimeOperationsSummaryText({
|
||||
filters,
|
||||
rows,
|
||||
total,
|
||||
onlineCount,
|
||||
locatedCount,
|
||||
degradedCount,
|
||||
sourceTypeCount,
|
||||
amapConfigured,
|
||||
sourceIssueRows
|
||||
}: {
|
||||
filters: Record<string, string>;
|
||||
rows: VehicleRealtimeRow[];
|
||||
total: number;
|
||||
onlineCount: number;
|
||||
locatedCount: number;
|
||||
degradedCount: number;
|
||||
sourceTypeCount: number;
|
||||
amapConfigured: boolean;
|
||||
sourceIssueRows: VehicleRealtimeRow[];
|
||||
}) {
|
||||
const issueLines = sourceIssueRows.length > 0
|
||||
? sourceIssueRows.map((row, index) => {
|
||||
const status = vehicleServiceStatus(row);
|
||||
return `${index + 1}. ${row.plate || row.vin} / ${row.primaryProtocol || '-'} / ${status.label} / ${row.serviceStatus?.detail || sourceEvidenceText(row)}`;
|
||||
}).join('\n')
|
||||
: '暂无重点车辆';
|
||||
return [
|
||||
'【实时监控摘要】',
|
||||
`当前筛选:${realtimeFilterSummary(filters).join(';') || '全部实时车辆'}`,
|
||||
`车辆总数:${total.toLocaleString()},当前页:${rows.length.toLocaleString()}`,
|
||||
`在线车辆:${onlineCount.toLocaleString()},定位有效:${locatedCount.toLocaleString()}`,
|
||||
`降级服务:${degradedCount.toLocaleString()},来源类型:${sourceTypeCount.toLocaleString()}`,
|
||||
`地图配置:${amapConfigured ? '已配置' : '未配置'}`,
|
||||
'重点车辆:',
|
||||
issueLines,
|
||||
`实时页面:${window.location.origin}${window.location.pathname}${window.location.hash}`
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
async function copyText(value: string, label: string) {
|
||||
const text = value.trim();
|
||||
if (!text) {
|
||||
Toast.warning(`${label}为空`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
Toast.success(`已复制${label}`);
|
||||
} catch {
|
||||
Toast.error(`复制${label}失败`);
|
||||
}
|
||||
}
|
||||
|
||||
export function Realtime({
|
||||
onOpenVehicle,
|
||||
onOpenHistory,
|
||||
@@ -165,12 +229,7 @@ export function Realtime({
|
||||
downloadCsv(realtimeExportFileName(filters), buildCsv(realtimeExportColumns, rows));
|
||||
Toast.success(`已导出 ${rows.length} 条实时车辆`);
|
||||
};
|
||||
const filterSummary = [
|
||||
filters.keyword ? `关键词:${filters.keyword}` : '',
|
||||
filters.protocol ? `数据来源:${filters.protocol}` : '',
|
||||
filters.online ? `在线:${onlineLabel[filters.online] ?? filters.online}` : '',
|
||||
filters.serviceStatus ? `服务状态:${serviceStatusLabel[filters.serviceStatus] ?? filters.serviceStatus}` : ''
|
||||
].filter(Boolean);
|
||||
const filterSummary = realtimeFilterSummary(filters);
|
||||
const onlineCount = rows.filter((row) => row.online).length;
|
||||
const locatedCount = rows.filter(isValidCoordinate).length;
|
||||
const degradedCount = rows.filter((row) => row.onlineSourceCount < row.sourceCount).length;
|
||||
@@ -199,6 +258,17 @@ export function Realtime({
|
||||
online: row.online,
|
||||
title: `${row.plate || row.vin || '-'} ${vehicleServiceStatus(row).label} ${row.primaryProtocol || ''} ${row.lastSeen || ''}`
|
||||
}));
|
||||
const copyRealtimeSummary = () => copyText(realtimeOperationsSummaryText({
|
||||
filters,
|
||||
rows,
|
||||
total: pagination.total,
|
||||
onlineCount,
|
||||
locatedCount,
|
||||
degradedCount,
|
||||
sourceTypeCount: primaryProtocols.size,
|
||||
amapConfigured,
|
||||
sourceIssueRows
|
||||
}), '实时摘要');
|
||||
|
||||
return (
|
||||
<div className="vp-page">
|
||||
@@ -250,6 +320,7 @@ export function Realtime({
|
||||
</Tag>
|
||||
<Tag color="blue">{locatedCount.toLocaleString()} 辆有定位</Tag>
|
||||
<Tag color="green">{onlineCount.toLocaleString()} 辆在线</Tag>
|
||||
<Button size="small" theme="light" icon={<IconCopy />} aria-label="复制实时摘要" onClick={copyRealtimeSummary}>复制实时摘要</Button>
|
||||
</Space>
|
||||
</div>
|
||||
<VehicleMap
|
||||
|
||||
Reference in New Issue
Block a user