mirror of
https://github.com/Buriburizaem0n/nezha-dash-v1.git
synced 2026-02-04 20:50:08 +00:00
feat: chart peak cut switch
This commit is contained in:
@@ -25,10 +25,12 @@ import { useTranslation } from "react-i18next";
|
||||
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
|
||||
import NetworkChartLoading from "./NetworkChartLoading";
|
||||
import { NezhaMonitor, ServerMonitorChart } from "@/types/nezha-api";
|
||||
import { Switch } from "./ui/switch";
|
||||
import { Label } from "./ui/label";
|
||||
|
||||
interface ResultItem {
|
||||
created_at: number;
|
||||
[key: string]: number | null;
|
||||
[key: string]: number;
|
||||
}
|
||||
|
||||
export function NetworkChart({
|
||||
@@ -112,6 +114,7 @@ export const NetworkChartClient = React.memo(function NetworkChart({
|
||||
const defaultChart = "All";
|
||||
|
||||
const [activeChart, setActiveChart] = React.useState(defaultChart);
|
||||
const [isPeakEnabled, setIsPeakEnabled] = React.useState(false);
|
||||
|
||||
const handleButtonClick = useCallback(
|
||||
(chart: string) => {
|
||||
@@ -175,6 +178,63 @@ export const NetworkChartClient = React.memo(function NetworkChart({
|
||||
));
|
||||
}, [activeChart, defaultChart, chartDataKey, getColorByIndex]);
|
||||
|
||||
const processedData = useMemo(() => {
|
||||
if (!isPeakEnabled) {
|
||||
return activeChart === defaultChart
|
||||
? formattedData
|
||||
: chartData[activeChart];
|
||||
}
|
||||
|
||||
// 如果开启了削峰,对数据进行处理
|
||||
const data = (
|
||||
activeChart === defaultChart ? formattedData : chartData[activeChart]
|
||||
) as ResultItem[];
|
||||
const windowSize = 7; // 增加到7个点的移动平均
|
||||
const weights = [0.1, 0.1, 0.15, 0.3, 0.15, 0.1, 0.1]; // 加权平均的权重
|
||||
|
||||
return data.map((point, index) => {
|
||||
if (index < windowSize - 1) return point;
|
||||
|
||||
const window = data.slice(index - windowSize + 1, index + 1);
|
||||
const smoothed = { ...point } as ResultItem;
|
||||
|
||||
if (activeChart === defaultChart) {
|
||||
// 处理所有线路的数据
|
||||
chartDataKey.forEach((key) => {
|
||||
const values = window
|
||||
.map((w) => w[key])
|
||||
.filter((v) => v !== undefined && v !== null) as number[];
|
||||
if (values.length === windowSize) {
|
||||
smoothed[key] = values.reduce(
|
||||
(acc, val, idx) => acc + val * weights[idx],
|
||||
0,
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 处理单条线路的数据
|
||||
const values = window
|
||||
.map((w) => w.avg_delay)
|
||||
.filter((v) => v !== undefined && v !== null) as number[];
|
||||
if (values.length === windowSize) {
|
||||
smoothed.avg_delay = values.reduce(
|
||||
(acc, val, idx) => acc + val * weights[idx],
|
||||
0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return smoothed;
|
||||
});
|
||||
}, [
|
||||
isPeakEnabled,
|
||||
activeChart,
|
||||
formattedData,
|
||||
chartData,
|
||||
chartDataKey,
|
||||
defaultChart,
|
||||
]);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="flex flex-col items-stretch space-y-0 p-0 sm:flex-row">
|
||||
@@ -185,6 +245,16 @@ export const NetworkChartClient = React.memo(function NetworkChart({
|
||||
<CardDescription className="text-xs">
|
||||
{chartDataKey.length} {t("monitor.monitorCount")}
|
||||
</CardDescription>
|
||||
<div className="flex items-center mt-0.5 space-x-2">
|
||||
<Switch
|
||||
id="Peak"
|
||||
checked={isPeakEnabled}
|
||||
onCheckedChange={setIsPeakEnabled}
|
||||
/>
|
||||
<Label className="text-xs" htmlFor="Peak">
|
||||
Peak cut
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-wrap w-full">{chartButtons}</div>
|
||||
</CardHeader>
|
||||
@@ -195,11 +265,7 @@ export const NetworkChartClient = React.memo(function NetworkChart({
|
||||
>
|
||||
<LineChart
|
||||
accessibilityLayer
|
||||
data={
|
||||
activeChart === defaultChart
|
||||
? formattedData
|
||||
: chartData[activeChart]
|
||||
}
|
||||
data={processedData}
|
||||
margin={{ left: 12, right: 12 }}
|
||||
>
|
||||
<CartesianGrid vertical={false} />
|
||||
@@ -282,6 +348,7 @@ const formatData = (rawData: NezhaMonitor[]) => {
|
||||
}
|
||||
|
||||
const timeIndex = created_at.indexOf(time);
|
||||
// @ts-expect-error - avg_delay is an array
|
||||
result[time][monitor_name] =
|
||||
timeIndex !== -1 ? avg_delay[timeIndex] : null;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user