history minor changes. autorefresh not interrupt zoom.

This commit is contained in:
Первов Артем
2026-06-19 09:05:58 +03:00
parent 26ef325ac1
commit dbda8ee613
2 changed files with 46 additions and 5 deletions

View File

@@ -9,6 +9,7 @@ import * as echarts from 'echarts/core';
import { CanvasRenderer } from 'echarts/renderers';
import ReactEChartsCore from 'echarts-for-react/esm/core.js';
import type { EChartsOption, SeriesOption } from 'echarts';
import { useMemo, useRef } from 'react';
import type { HistoryResponse } from '../api/cloud';
echarts.use([
@@ -48,6 +49,17 @@ type TooltipParam = {
value?: unknown;
};
type DataZoomState = {
start?: number;
end?: number;
startValue?: number;
endValue?: number;
};
type DataZoomEventBatch = DataZoomState & {
batch?: DataZoomState[];
};
/** Подбирает подпись оси времени под текущий масштаб графика. */
function formatAxisDate(value: number, spanMs?: number): string {
const date = new Date(value);
@@ -206,12 +218,17 @@ function createSeriesOptions(
/** Рисует исторические ряды: avg соединяется линией, min/max показываются точками и вертикальным диапазоном. */
export function HistoryChart({ data, loading, from, to, tagLabels = {} }: HistoryChartProps) {
const dataZoomRef = useRef<DataZoomState | null>(null);
const xMin = from ? new Date(from).getTime() : undefined;
const xMax = to ? new Date(to).getTime() : undefined;
const xSpan = Number.isFinite(xMin) && Number.isFinite(xMax) ? Number(xMax) - Number(xMin) : undefined;
const legendData = data?.series.map((series) => tagLabels[series.tag] ?? series.tag) ?? [];
const legendData = useMemo(
() => data?.series.map((series) => tagLabels[series.tag] ?? series.tag) ?? [],
[data?.series, tagLabels],
);
const dataZoomState = dataZoomRef.current ?? {};
const option: EChartsOption = {
const option: EChartsOption = useMemo(() => ({
color: SERIES_COLORS,
animation: false,
backgroundColor: 'transparent',
@@ -260,6 +277,10 @@ export function HistoryChart({ data, loading, from, to, tagLabels = {} }: Histor
{
type: 'inside',
throttle: 80,
start: dataZoomState.start,
end: dataZoomState.end,
startValue: dataZoomState.startValue,
endValue: dataZoomState.endValue,
},
{
type: 'slider',
@@ -272,13 +293,32 @@ export function HistoryChart({ data, loading, from, to, tagLabels = {} }: Histor
borderColor: '#e8c9a0',
},
textStyle: { color: '#94a3b8' },
start: dataZoomState.start,
end: dataZoomState.end,
startValue: dataZoomState.startValue,
endValue: dataZoomState.endValue,
},
],
series:
data?.series.flatMap((series, index) =>
createSeriesOptions(series, index, tagLabels[series.tag] ?? series.tag),
) ?? [],
}), [data?.series, dataZoomState.end, dataZoomState.endValue, dataZoomState.start, dataZoomState.startValue, legendData, tagLabels, xMax, xMin, xSpan]);
const onChartEvents = useMemo(
() => ({
datazoom: (event: DataZoomEventBatch) => {
const state = event.batch?.[0] ?? event;
dataZoomRef.current = {
start: state.start,
end: state.end,
startValue: state.startValue,
endValue: state.endValue,
};
},
}),
[],
);
if (loading) {
return <div className="chart-placeholder">Загрузка графика...</div>;
@@ -288,5 +328,5 @@ export function HistoryChart({ data, loading, from, to, tagLabels = {} }: Histor
return <div className="chart-placeholder">Нет данных для выбранного диапазона</div>;
}
return <ReactEChartsCore echarts={echarts} option={option} className="history-chart" notMerge lazyUpdate />;
return <ReactEChartsCore echarts={echarts} option={option} className="history-chart" onEvents={onChartEvents} lazyUpdate />;
}

View File

@@ -157,7 +157,7 @@ export function EdgeDetailPage({ view }: EdgeDetailPageProps) {
targetPoints: 1600,
}),
enabled: Boolean(edgeId && selectedTags.length),
refetchInterval: 5_000,
refetchInterval: false,
});
/** Переключает выбранный тег для отображения на историческом графике. */
@@ -556,6 +556,7 @@ function ArchiveView({
{selectedTags.length ? (
<HistoryChart
key={`${range.from}:${range.to}:${selectedTags.join(',')}`}
data={history}
loading={historyLoading}
from={toIsoFromInput(range.from)}