perf(web): pause hidden live polling

This commit is contained in:
lingniu
2026-07-16 08:35:37 +08:00
parent e06778e38c
commit 4c54cfa6ff
9 changed files with 46 additions and 15 deletions

View File

@@ -6,7 +6,7 @@ import { api } from '../../api/client';
import type { HistoryDataResponse, HistoryDataRow, HistoryExportRequest, HistoryMetricDefinition, HistorySeriesResponse } from '../../api/types';
import { buildHistorySeriesPanels, formatExportFileSize, formatHistoryValue, formatSeriesGrain, historyExportPollInterval, parseHistoryKeywords } from '../domain/history';
import { InlineError } from '../shared/AsyncState';
import { QUERY_MEMORY, retainPreviousPageWithinScope } from '../queryPolicy';
import { LIVE_QUERY_POLICY, QUERY_MEMORY, retainPreviousPageWithinScope } from '../queryPolicy';
import { usePlatformSession } from '../auth/AuthGate';
import { canOperate } from '../auth/session';
@@ -50,7 +50,7 @@ function ExportJobsPanel() {
queryKey: ['history-exports'],
queryFn: ({ signal }) => api.historyExports(signal),
refetchInterval: (current) => historyExportPollInterval(current.state.data),
refetchIntervalInBackground: false,
...LIVE_QUERY_POLICY,
gcTime: QUERY_MEMORY.highVolumeGcTime
});
const jobs = query.data ?? [];

View File

@@ -8,7 +8,7 @@ import { FleetMap } from '../map/FleetMap';
import { EmptyState, InlineError } from '../shared/AsyncState';
import { formatNumber, relativeFreshness, statusLabel, vehicleStatus } from '../domain/monitor';
import { MAX_MONITOR_SEARCH_TERMS, MONITOR_REFRESH, monitorFilterScope, monitorQueryParams, parseMonitorSearchTerms, useMonitorData, useMonitorVehicleCard, type MonitorViewport } from '../hooks/useMonitorData';
import { QUERY_MEMORY, retainPreviousPageWithinScope } from '../queryPolicy';
import { LIVE_QUERY_POLICY, QUERY_MEMORY, retainPreviousPageWithinScope } from '../queryPolicy';
const protocols = ['', 'GB32960', 'JT808', 'YUTONG_MQTT'];
const statuses = ['', 'online', 'offline', 'driving', 'idle'];
@@ -251,7 +251,8 @@ export default function MonitorPage() {
queryKey: ['monitor', 'vehicle-list', listScope, listLimit, listOffset],
queryFn: ({ signal }) => api.vehicleRealtime(listParams, signal),
enabled: mode === 'list', placeholderData: retainPreviousPageWithinScope<Page<VehicleRealtimeRow>>(listScope, 2), refetchInterval: mode === 'list' ? MONITOR_REFRESH.fleet : false,
gcTime: QUERY_MEMORY.highVolumeGcTime
gcTime: QUERY_MEMORY.highVolumeGcTime,
...LIVE_QUERY_POLICY
});
const rows = useMemo(() => {
const data = vehicles.data?.items ?? [];

View File

@@ -22,6 +22,12 @@ test('reconciles service identities with bound and identity-required vehicles',
render(<QueryClientProvider client={client}><OperationsPage /></QueryClientProvider>);
expect(await screen.findByText('1035 / 234')).toBeInTheDocument();
for (const key of [['ops-health-v2'], ['ops-source-readiness-v2']]) {
const query = client.getQueryCache().find({ queryKey: key });
const liveOptions = query?.options as { refetchIntervalInBackground?: boolean; refetchOnWindowFocus?: boolean };
expect(liveOptions.refetchIntervalInBackground).toBe(false);
expect(liveOptions.refetchOnWindowFocus).toBe(true);
}
expect(screen.getByText('服务身份 / 在线')).toBeInTheDocument();
expect(screen.getByText('已绑定 1024 · 待绑定 11')).toBeInTheDocument();
expect(screen.queryByText('统一车辆视角')).not.toBeInTheDocument();

View File

@@ -2,14 +2,15 @@ import { IconRefresh } from '@douyinfe/semi-icons';
import { useQuery } from '@tanstack/react-query';
import { api } from '../../api/client';
import { InlineError } from '../shared/AsyncState';
import { LIVE_QUERY_POLICY, QUERY_MEMORY } from '../queryPolicy';
function statusLabel(status: string) {
return { ok: '正常', warning: '关注', error: '异常' }[status] ?? status;
}
export default function OperationsPage() {
const health = useQuery({ queryKey: ['ops-health-v2'], queryFn: ({ signal }) => api.opsHealth(signal), refetchInterval: 15_000, staleTime: 8_000 });
const readiness = useQuery({ queryKey: ['ops-source-readiness-v2'], queryFn: ({ signal }) => api.sourceReadiness(signal), refetchInterval: 30_000, staleTime: 15_000 });
const health = useQuery({ queryKey: ['ops-health-v2'], queryFn: ({ signal }) => api.opsHealth(signal), refetchInterval: 15_000, staleTime: 8_000, gcTime: QUERY_MEMORY.summaryGcTime, ...LIVE_QUERY_POLICY });
const readiness = useQuery({ queryKey: ['ops-source-readiness-v2'], queryFn: ({ signal }) => api.sourceReadiness(signal), refetchInterval: 30_000, staleTime: 15_000, gcTime: QUERY_MEMORY.summaryGcTime, ...LIVE_QUERY_POLICY });
const data = health.data; const sources = readiness.data;
const refresh = () => Promise.all([health.refetch(), readiness.refetch()]);
return <div className="v2-ops-page">

View File

@@ -9,7 +9,7 @@ import { api } from '../../api/client';
import type { LatestTelemetryResponse, QualityIssueRow, VehicleDetail, VehicleProfileSyncItem, VehicleProfileSyncResult } from '../../api/types';
import { usePlatformSession } from '../auth/AuthGate';
import { canAdminister } from '../auth/session';
import { QUERY_MEMORY } from '../queryPolicy';
import { LIVE_QUERY_POLICY, QUERY_MEMORY } from '../queryPolicy';
import { formatTelemetryTime, formatTelemetryValue, telemetryQualityLabel } from '../domain/telemetry';
import { formatZhNumber } from '../domain/formatters';
import { parseVehicleProfileSyncCSV, vehicleProfileSyncCSVHeader } from '../domain/profileSync';
@@ -198,7 +198,7 @@ function VehicleRecord({ detail, telemetry, telemetryPending, telemetryError, on
export default function VehiclePage() {
const { vin } = useParams();
const query = useQuery({ queryKey: ['vehicle-detail', vin], enabled: Boolean(vin), queryFn: ({ signal }) => api.vehicleDetail(new URLSearchParams({ keyword: vin!, limit: '20' }), signal), gcTime: QUERY_MEMORY.summaryGcTime });
const telemetry = useQuery({ queryKey: ['vehicle-latest-telemetry', vin], enabled: Boolean(vin), queryFn: ({ signal }) => api.latestTelemetry(vin!, signal), staleTime: 10_000, gcTime: QUERY_MEMORY.summaryGcTime, refetchInterval: 20_000, refetchIntervalInBackground: false });
const telemetry = useQuery({ queryKey: ['vehicle-latest-telemetry', vin], enabled: Boolean(vin), queryFn: ({ signal }) => api.latestTelemetry(vin!, signal), staleTime: 10_000, gcTime: QUERY_MEMORY.summaryGcTime, refetchInterval: 20_000, ...LIVE_QUERY_POLICY });
if (!vin) return <VehicleSearch />;
if (query.isPending) return <PageLoading />;
if (query.isError) return <div className="v2-page-error"><InlineError message={query.error instanceof Error ? query.error.message : '车辆档案加载失败'} onRetry={() => query.refetch()} /></div>;