feat(platform): add realtime auto refresh controls
This commit is contained in:
@@ -71,6 +71,15 @@ function realtimeMapPointId(row: VehicleRealtimeRow, index = 0) {
|
||||
return row.vin?.trim() || `${row.primaryProtocol || 'source'}-${index}`;
|
||||
}
|
||||
|
||||
function formatRefreshTime(date: Date) {
|
||||
return date.toLocaleTimeString('zh-CN', {
|
||||
hour12: false,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
}
|
||||
|
||||
function amapMarkerURL(row: VehicleRealtimeRow) {
|
||||
const name = encodeURIComponent(row.plate || row.vin || '车辆位置');
|
||||
return `https://uri.amap.com/marker?position=${row.longitude},${row.latitude}&name=${name}&src=lingniu-vehicle-platform`;
|
||||
@@ -200,6 +209,9 @@ export function Realtime({
|
||||
const [pagination, setPagination] = useState({ currentPage: 1, pageSize: 50, total: 0 });
|
||||
const [opsHealth, setOpsHealth] = useState<OpsHealth | null>(null);
|
||||
const [selectedMapPointId, setSelectedMapPointId] = useState('');
|
||||
const [lastRefreshAt, setLastRefreshAt] = useState('');
|
||||
const [autoRefresh, setAutoRefresh] = useState(true);
|
||||
const refreshIntervalSeconds = 15;
|
||||
const amapConfig = getAMapConfig();
|
||||
const runtime = opsHealth?.runtime;
|
||||
const amapConfigured = runtime?.amapWebJsConfigured ?? isAMapConfigured(amapConfig);
|
||||
@@ -214,10 +226,11 @@ export function Realtime({
|
||||
if (values?.protocol) params.set('protocol', values.protocol);
|
||||
if (values?.online) params.set('online', values.online);
|
||||
if (values?.serviceStatus) params.set('serviceStatus', values.serviceStatus);
|
||||
api.vehicleRealtime(params)
|
||||
return api.vehicleRealtime(params)
|
||||
.then((nextPage) => {
|
||||
setRows(nextPage.items);
|
||||
setPagination({ currentPage: page, pageSize, total: nextPage.total });
|
||||
setLastRefreshAt(formatRefreshTime(new Date()));
|
||||
})
|
||||
.catch((error: Error) => Toast.error(error.message))
|
||||
.finally(() => setLoading(false));
|
||||
@@ -231,6 +244,16 @@ export function Realtime({
|
||||
.catch(() => setOpsHealth(null));
|
||||
}, [JSON.stringify(initialFilters)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!autoRefresh) {
|
||||
return undefined;
|
||||
}
|
||||
const timer = window.setInterval(() => {
|
||||
load(filters, pagination.currentPage, pagination.pageSize);
|
||||
}, refreshIntervalSeconds * 1000);
|
||||
return () => window.clearInterval(timer);
|
||||
}, [autoRefresh, JSON.stringify(filters), pagination.currentPage, pagination.pageSize]);
|
||||
|
||||
const applyFilters = (nextFilters: Record<string, string>) => {
|
||||
setFilters(nextFilters);
|
||||
onFiltersChange?.(nextFilters);
|
||||
@@ -367,6 +390,18 @@ export function Realtime({
|
||||
}}>重置</Button>
|
||||
</Space>
|
||||
</Form>
|
||||
<div className="vp-table-toolbar">
|
||||
<Space wrap>
|
||||
<Tag color={autoRefresh ? 'green' : 'grey'}>自动刷新 {refreshIntervalSeconds}秒</Tag>
|
||||
<Typography.Text type="secondary">最后刷新:{lastRefreshAt || '等待首次刷新'}</Typography.Text>
|
||||
<Button size="small" theme="light" aria-label="刷新实时数据" loading={loading} onClick={() => load(filters, pagination.currentPage, pagination.pageSize)}>
|
||||
刷新实时数据
|
||||
</Button>
|
||||
<Button size="small" theme="light" aria-label={autoRefresh ? '暂停自动刷新' : '开启自动刷新'} onClick={() => setAutoRefresh((value) => !value)}>
|
||||
{autoRefresh ? '暂停自动刷新' : '开启自动刷新'}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
{filterSummary.length > 0 ? (
|
||||
<Card bordered title="当前实时筛选" style={{ marginBottom: 12 }}>
|
||||
<Space wrap>
|
||||
|
||||
Reference in New Issue
Block a user