From b83219bbf2203324d788aad0528a6b13f014fa04 Mon Sep 17 00:00:00 2001
From: hamster1963 <1410514192@qq.com>
Date: Sat, 19 Oct 2024 02:09:04 +0800
Subject: [PATCH] feat: detail info
---
.../ServerDetailChartClient.tsx | 423 ++++++++++++++----
.../ClientComponents/ServerDetailClient.tsx | 179 +++-----
app/[locale]/(main)/detail/[id]/page.tsx | 2 +
bun.lockb | Bin 445857 -> 445857 bytes
.../ui/animated-circular-progress-bar.tsx | 7 +-
lib/utils.ts | 1 +
6 files changed, 399 insertions(+), 213 deletions(-)
diff --git a/app/[locale]/(main)/ClientComponents/ServerDetailChartClient.tsx b/app/[locale]/(main)/ClientComponents/ServerDetailChartClient.tsx
index 74fdcf3e8..5f308580c 100644
--- a/app/[locale]/(main)/ClientComponents/ServerDetailChartClient.tsx
+++ b/app/[locale]/(main)/ClientComponents/ServerDetailChartClient.tsx
@@ -4,10 +4,10 @@ import AnimatedCircularProgressBar from "@/components/ui/animated-circular-progr
import { Card, CardContent } from "@/components/ui/card";
import useSWR from "swr";
import { NezhaAPISafe } from "../../types/nezha-api";
-import { formatRelativeTime, formatTime, nezhaFetcher } from "@/lib/utils";
+import { formatNezhaInfo, formatRelativeTime, formatTime, nezhaFetcher } from "@/lib/utils";
import getEnv from "@/lib/env-entry";
import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart";
-import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts";
+import { Area, AreaChart, CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
import { useEffect, useState } from "react";
@@ -16,6 +16,18 @@ type cpuChartData = {
cpu: number;
}
+type memChartData = {
+ timeStamp: string;
+ mem: number;
+ swap: number;
+}
+
+type networkChartData = {
+ timeStamp: string;
+ upload: number;
+ download: number;
+}
+
export default function ServerDetailChartClient({
server_id,
}: {
@@ -29,22 +41,6 @@ export default function ServerDetailChartClient({
},
);
- const [chartData, setChartData] = useState([] as cpuChartData[]);
-
- useEffect(() => {
- if (data) {
- const timestamp = Date.now().toString();
- const newData = [
- ...chartData,
- { timeStamp: timestamp, cpu: data.status.CPU },
- ];
- if (newData.length > 30) {
- newData.shift();
- }
- setChartData(newData);
- }
- }, [data]);
-
if (error) {
return (
<>
@@ -60,6 +56,33 @@ export default function ServerDetailChartClient({
}
if (!data) return null;
+ return (
+
+ )
+}
+
+function CpuChart({ data }: { data: NezhaAPISafe }) {
+ const [cpuChartData, setCpuChartData] = useState([] as cpuChartData[]);
+
+ const { cpu } = formatNezhaInfo(data);
+
+ useEffect(() => {
+ if (data) {
+ const timestamp = Date.now().toString();
+ const newData = [
+ ...cpuChartData,
+ { timeStamp: timestamp, cpu: cpu },
+ ];
+ if (newData.length > 30) {
+ newData.shift();
+ }
+ setCpuChartData(newData);
+ }
+ }, [data]);
const chartConfig = {
cpu: {
@@ -68,73 +91,303 @@ export default function ServerDetailChartClient({
} satisfies ChartConfig
return (
-
-
-
-
-
-
- CPU
+
+
+
+
+
+ CPU
+
+
+
+ {cpu.toFixed(0)}%
-
-
- {data?.status.CPU.toFixed(0)}%
-
-
-
-
-
-
-
-
- formatRelativeTime(value)}
- />
- `${value}%`}
- />
- {/* {
- return formatTime(Number(payload[0].payload.timeStamp));
- }} />}
- /> */}
-
-
-
-
-
-
-
+
+
+
+
+
+
+ formatRelativeTime(value)}
+ />
+ `${value}%`}
+ />
+
+
+
+
+
+
+ )
+}
+
+function MemChart({ data }: { data: NezhaAPISafe }) {
+ const [memChartData, setMemChartData] = useState([] as memChartData[]);
+
+ const { mem, swap } = formatNezhaInfo(data);
+
+ useEffect(() => {
+ if (data) {
+ const timestamp = Date.now().toString();
+ const newData = [
+ ...memChartData,
+ { timeStamp: timestamp, mem: mem, swap: swap },
+ ];
+ if (newData.length > 30) {
+ newData.shift();
+ }
+ setMemChartData(newData);
+ }
+ }, [data]);
+
+ const chartConfig = {
+ mem: {
+ label: "Mem",
+ },
+ swap: {
+ label: "Swap",
+ },
+ } satisfies ChartConfig
+
+ return (
+
+
+
+
+
+
+
Mem
+
+
+
+ {mem.toFixed(0)}%
+
+
+
+
+
Swap
+
+
+
+ {swap.toFixed(0)}%
+
+
+
+
+
+
+
+
+
+ formatRelativeTime(value)}
+ />
+ `${value}%`}
+ />
+
+
+
+
+
+
+
+ )
+
+}
+
+
+function NetworkChart({ data }: { data: NezhaAPISafe }) {
+ const [networkChartData, setNetworkChartData] = useState([] as networkChartData[]);
+
+ const { up, down } = formatNezhaInfo(data);
+
+ useEffect(() => {
+ if (data) {
+ const timestamp = Date.now().toString();
+ const newData = [
+ ...networkChartData,
+ { timeStamp: timestamp, upload: up, download: down },
+ ];
+ if (newData.length > 30) {
+ newData.shift();
+ }
+ setNetworkChartData(newData);
+ }
+ }, [data]);
+
+ let maxDownload = Math.max(...networkChartData.map((item) => item.download));
+ maxDownload = Math.ceil(maxDownload);
+ if (maxDownload < 1) {
+ maxDownload = 1;
+ }
+
+ const chartConfig = {
+ upload: {
+ label: "Upload",
+ },
+ download: {
+ label: "Download",
+ },
+ } satisfies ChartConfig
+
+ return (
+
+
+
+
+
+
+
Upload
+
+
+
+ {up.toFixed(2)} M/s
+
+
+
+
+
Download
+
+
+
+ {down.toFixed(2)} M/s
+
+
+
+
+
+
+
+
+
+ formatRelativeTime(value)}
+ />
+ `${value.toFixed(0)}M/s`}
+ />
+
+
+
+
+
+
+
)
}
\ No newline at end of file
diff --git a/app/[locale]/(main)/ClientComponents/ServerDetailClient.tsx b/app/[locale]/(main)/ClientComponents/ServerDetailClient.tsx
index 2a076b818..02f1d3769 100644
--- a/app/[locale]/(main)/ClientComponents/ServerDetailClient.tsx
+++ b/app/[locale]/(main)/ClientComponents/ServerDetailClient.tsx
@@ -6,7 +6,7 @@ import AnimatedCircularProgressBar from "@/components/ui/animated-circular-progr
import { Badge } from "@/components/ui/badge";
import { Card, CardContent } from "@/components/ui/card";
import getEnv from "@/lib/env-entry";
-import { cn, nezhaFetcher } from "@/lib/utils";
+import { cn, formatBytes, nezhaFetcher } from "@/lib/utils";
import { useLocale } from "next-intl";
import { useRouter } from "next/navigation";
import useSWR from "swr";
@@ -51,10 +51,10 @@ export default function ServerDetailClient({
{data?.name}
-
+
-
-
+
-
- Uptime
-
+
+ Uptime
+
{" "}
{(data?.status.Uptime / 86400).toFixed(0)} Days{" "}
-
-
-
-
-
-
-
- Arch
-
- {" "}
- {data?.host.Arch || "Unknown"}{" "}
-
+
-
+
-
- Version
-
- {" "}
+
+ Version
+
{data?.host.Version || "Unknown"}{" "}
-
-
-
-
-
-
-
-
-
- System
- {data?.host.Platform ? (
-
- {" "}
- {data?.host.Platform || "Unknown"} -{" "}
- {data?.host.PlatformVersion}{" "}
-
- ) : (
- Unknown
- )}
+
-
+
-
- CPU
- {data?.host.CPU ? (
-
- {" "}
- {data?.host.CPU || "Unknown"}
-
- ) : (
- Unknown
- )}
+
+ Arch
+
+ {data?.host.Arch || "Unknown"}{" "}
+
-
- {/*
-
+
-
- CPU
-
- {data?.status.CPU.toFixed(0)}%
-
-
+
+ Mem
+
+ {formatBytes(data?.host.MemTotal)}
+
-
+
-
- Mem
-
- {((data?.status.MemUsed / data?.host.MemTotal) * 100).toFixed(
- 0,
- )}
- %
-
-
+
+ Disk
+
+ {formatBytes(data?.host.DiskTotal)}
+
-
+
+
+
-
- Swap
-
- {data?.status.SwapUsed
- ? (
- (data?.status.SwapUsed / data?.host.SwapTotal) *
- 100
- ).toFixed(0)
- : 0}
- %
-
-
+
+ System
+ {data?.host.Platform ? (
+
+ {" "}
+ {data?.host.Platform || "Unknown"} -{" "}
+ {data?.host.PlatformVersion}{" "}
+
) : Unknown
}
-
+
-
- Disk
-
- {((data?.status.DiskUsed / data?.host.DiskTotal) * 100).toFixed(
- 0,
- )}
- %
-
-
+
+ CPU
+ {data?.host.CPU ? (
+
+ {" "}
+ {data?.host.CPU}
+
) : Unknown
}
- */}
+
);
}
diff --git a/app/[locale]/(main)/detail/[id]/page.tsx b/app/[locale]/(main)/detail/[id]/page.tsx
index f0254089b..21e17b60d 100644
--- a/app/[locale]/(main)/detail/[id]/page.tsx
+++ b/app/[locale]/(main)/detail/[id]/page.tsx
@@ -1,9 +1,11 @@
import ServerDetailClient from "@/app/[locale]/(main)/ClientComponents/ServerDetailClient";
import ServerDetailChartClient from "@/app/[locale]/(main)/ClientComponents/ServerDetailChartClient";
+import { Separator } from "@/components/ui/separator";
export default function Page({ params }: { params: { id: string } }) {
return
+
;
diff --git a/bun.lockb b/bun.lockb
index 0c25b049f2ee017ee864de29a45eccb04b45d695..35a64c1e5a989e9aebe1b9765fc37b439e990674 100755
GIT binary patch
delta 43
vcmZ2DTYBMa>4p}@7N!>FEi9e^Y)lLwFx_w!i)edF01FVaZchndv#kXH94`z{
delta 39
tcmZ2DTYBMa>4p}@7N!>FEi9e^?2K`SdWL!i?EwKSK+L*5Ab>5f76AQ$3+Mm<
diff --git a/components/ui/animated-circular-progress-bar.tsx b/components/ui/animated-circular-progress-bar.tsx
index bdb7b4a41..dd96fe8d3 100644
--- a/components/ui/animated-circular-progress-bar.tsx
+++ b/components/ui/animated-circular-progress-bar.tsx
@@ -5,12 +5,14 @@ interface Props {
value: number;
min: number;
className?: string;
+ primaryColor?: string;
}
export default function AnimatedCircularProgressBar({
max = 100,
min = 0,
value = 0,
+ primaryColor,
className,
}: Props) {
const circumference = 2 * Math.PI * 45;
@@ -74,9 +76,12 @@ export default function AnimatedCircularProgressBar({
strokeDashoffset="0"
strokeLinecap="round"
strokeLinejoin="round"
- className="opacity-100 stroke-current"
+ className={cn("opacity-100 stroke-current", {
+ "stroke-[var(--stroke-primary-color)]": primaryColor,
+ })}
style={
{
+ "--stroke-primary-color": primaryColor,
"--stroke-percent": currentPercent,
strokeDasharray:
"calc(var(--stroke-percent) * var(--percent-to-px)) var(--circumference)",
diff --git a/lib/utils.ts b/lib/utils.ts
index a65328dd4..4987b0f12 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -14,6 +14,7 @@ export function formatNezhaInfo(serverInfo: NezhaAPISafe) {
down: serverInfo.status.NetInSpeed / 1024 / 1024,
online: serverInfo.online_status,
mem: (serverInfo.status.MemUsed / serverInfo.host.MemTotal) * 100,
+ swap: (serverInfo.status.SwapUsed / serverInfo.host.SwapTotal) * 100,
stg: (serverInfo.status.DiskUsed / serverInfo.host.DiskTotal) * 100,
country_code: serverInfo.host.CountryCode,
};