diff --git a/app/(main)/ClientComponents/NetworkChart.tsx b/app/(main)/ClientComponents/NetworkChart.tsx index dce235a..6872d5b 100644 --- a/app/(main)/ClientComponents/NetworkChart.tsx +++ b/app/(main)/ClientComponents/NetworkChart.tsx @@ -17,6 +17,8 @@ import { ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart"; +import { Label } from "@/components/ui/label"; +import { Switch } from "@/components/ui/switch"; import getEnv from "@/lib/env-entry"; import { formatTime, nezhaFetcher } from "@/lib/utils"; import { formatRelativeTime } from "@/lib/utils"; @@ -28,7 +30,7 @@ import useSWR from "swr"; interface ResultItem { created_at: number; - [key: string]: number | null; + [key: string]: number; } export function NetworkChartClient({ @@ -106,6 +108,7 @@ export const NetworkChart = React.memo(function NetworkChart({ const defaultChart = "All"; const [activeChart, setActiveChart] = React.useState(defaultChart); + const [isPeakEnabled, setIsPeakEnabled] = React.useState(false); const handleButtonClick = useCallback( (chart: string) => { @@ -169,6 +172,63 @@ export const NetworkChart = 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 ( @@ -179,6 +239,16 @@ export const NetworkChart = React.memo(function NetworkChart({ {chartDataKey.length} {t("ServerMonitorCount")} +
+ + +
{chartButtons}
@@ -189,11 +259,7 @@ export const NetworkChart = React.memo(function NetworkChart({ > @@ -276,6 +342,7 @@ const formatData = (rawData: NezhaAPIMonitor[]) => { } const timeIndex = created_at.indexOf(time); + // @ts-expect-error - avg_delay is an array result[time][monitor_name] = timeIndex !== -1 ? avg_delay[timeIndex] : null; }); diff --git a/bun.lockb b/bun.lockb index 05958b7..abf3096 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/ui/label.tsx b/components/ui/label.tsx new file mode 100644 index 0000000..090a967 --- /dev/null +++ b/components/ui/label.tsx @@ -0,0 +1,25 @@ +"use client"; + +import { cn } from "@/lib/utils"; +import * as LabelPrimitive from "@radix-ui/react-label"; +import { type VariantProps, cva } from "class-variance-authority"; +import * as React from "react"; + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", +); + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; diff --git a/components/ui/switch.tsx b/components/ui/switch.tsx new file mode 100644 index 0000000..0192541 --- /dev/null +++ b/components/ui/switch.tsx @@ -0,0 +1,28 @@ +"use client"; + +import { cn } from "@/lib/utils"; +import * as SwitchPrimitives from "@radix-ui/react-switch"; +import * as React from "react"; + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +Switch.displayName = SwitchPrimitives.Root.displayName; + +export { Switch }; diff --git a/package.json b/package.json index 15c71fd..4fc6f88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nezha-dash", - "version": "1.7.1", + "version": "1.7.2", "private": true, "scripts": { "dev": "next dev -p 3040", @@ -15,11 +15,13 @@ "@heroicons/react": "^2.2.0", "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.2", + "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-navigation-menu": "^1.2.1", "@radix-ui/react-popover": "^1.1.2", "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-switch": "^1.1.1", "@radix-ui/react-tooltip": "^1.1.4", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@turf/turf": "^7.1.0",