mirror of
https://github.com/Buriburizaem0n/nezha-dash-v1.git
synced 2026-02-05 13:10:09 +00:00
feat: server page
This commit is contained in:
148
src/lib/logo-class.tsx
Normal file
148
src/lib/logo-class.tsx
Normal file
@@ -0,0 +1,148 @@
|
||||
import type { SVGProps } from "react";
|
||||
|
||||
export function GetFontLogoClass(platform: string): string {
|
||||
if (
|
||||
[
|
||||
"almalinux",
|
||||
"alpine",
|
||||
"aosc",
|
||||
"apple",
|
||||
"archlinux",
|
||||
"archlabs",
|
||||
"artix",
|
||||
"budgie",
|
||||
"centos",
|
||||
"coreos",
|
||||
"debian",
|
||||
"deepin",
|
||||
"devuan",
|
||||
"docker",
|
||||
"elementary",
|
||||
"fedora",
|
||||
"ferris",
|
||||
"flathub",
|
||||
"freebsd",
|
||||
"gentoo",
|
||||
"gnu-guix",
|
||||
"illumos",
|
||||
"kali-linux",
|
||||
"linuxmint",
|
||||
"mageia",
|
||||
"mandriva",
|
||||
"manjaro",
|
||||
"nixos",
|
||||
"openbsd",
|
||||
"opensuse",
|
||||
"pop-os",
|
||||
"raspberry-pi",
|
||||
"redhat",
|
||||
"rocky-linux",
|
||||
"sabayon",
|
||||
"slackware",
|
||||
"snappy",
|
||||
"solus",
|
||||
"tux",
|
||||
"ubuntu",
|
||||
"void",
|
||||
"zorin",
|
||||
].indexOf(platform) > -1
|
||||
) {
|
||||
return platform;
|
||||
}
|
||||
if (platform == "darwin") {
|
||||
return "apple";
|
||||
}
|
||||
if (["openwrt", "linux", "immortalwrt"].indexOf(platform) > -1) {
|
||||
return "tux";
|
||||
}
|
||||
if (platform == "amazon") {
|
||||
return "redhat";
|
||||
}
|
||||
if (platform == "arch") {
|
||||
return "archlinux";
|
||||
}
|
||||
if (platform.toLowerCase().includes("opensuse")) {
|
||||
return "opensuse";
|
||||
}
|
||||
return "tux";
|
||||
}
|
||||
|
||||
export function GetOsName(platform: string): string {
|
||||
if (
|
||||
[
|
||||
"almalinux",
|
||||
"alpine",
|
||||
"aosc",
|
||||
"apple",
|
||||
"archlinux",
|
||||
"archlabs",
|
||||
"artix",
|
||||
"budgie",
|
||||
"centos",
|
||||
"coreos",
|
||||
"debian",
|
||||
"deepin",
|
||||
"devuan",
|
||||
"docker",
|
||||
"fedora",
|
||||
"ferris",
|
||||
"flathub",
|
||||
"freebsd",
|
||||
"gentoo",
|
||||
"gnu-guix",
|
||||
"illumos",
|
||||
"linuxmint",
|
||||
"mageia",
|
||||
"mandriva",
|
||||
"manjaro",
|
||||
"nixos",
|
||||
"openbsd",
|
||||
"opensuse",
|
||||
"pop-os",
|
||||
"redhat",
|
||||
"sabayon",
|
||||
"slackware",
|
||||
"snappy",
|
||||
"solus",
|
||||
"tux",
|
||||
"ubuntu",
|
||||
"void",
|
||||
"zorin",
|
||||
].indexOf(platform) > -1
|
||||
) {
|
||||
return platform.charAt(0).toUpperCase() + platform.slice(1);
|
||||
}
|
||||
if (platform == "darwin") {
|
||||
return "macOS";
|
||||
}
|
||||
if (["openwrt", "linux", "immortalwrt"].indexOf(platform) > -1) {
|
||||
return "Linux";
|
||||
}
|
||||
if (platform == "amazon") {
|
||||
return "Redhat";
|
||||
}
|
||||
if (platform == "arch") {
|
||||
return "Archlinux";
|
||||
}
|
||||
if (platform.toLowerCase().includes("opensuse")) {
|
||||
return "Opensuse";
|
||||
}
|
||||
return "Linux";
|
||||
}
|
||||
|
||||
export function MageMicrosoftWindows(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M2.75 7.189V2.865c0-.102 0-.115.115-.115h8.622c.128 0 .14 0 .14.128V11.5c0 .128 0 .128-.14.128H2.865c-.102 0-.115 0-.115-.116zM7.189 21.25H2.865c-.102 0-.115 0-.115-.116V12.59c0-.128 0-.128.128-.128h8.635c.102 0 .115 0 .115.115v8.57c0 .09 0 .103-.116.103zM21.25 7.189v4.31c0 .116 0 .116-.116.116h-8.557c-.102 0-.128 0-.128-.115V2.865c0-.09 0-.102.115-.102h8.48c.206 0 .206 0 .206.205zm-8.763 9.661v-4.273c0-.09 0-.115.103-.09h8.621c.026 0 0 .09 0 .142v8.518a.06.06 0 0 1-.017.06a.06.06 0 0 1-.06.017H12.54s-.09 0-.077-.09V16.85z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
119
src/lib/utils.ts
119
src/lib/utils.ts
@@ -1,6 +1,123 @@
|
||||
import { clsx, type ClassValue } from "clsx";
|
||||
import { NezhaAPI } from "@/types/nezha-api";
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
export function formatNezhaInfo(serverInfo: NezhaAPI) {
|
||||
const lastActiveTime = parseISOTimestamp(serverInfo.last_active);
|
||||
return {
|
||||
...serverInfo,
|
||||
cpu: serverInfo.state.cpu || 0,
|
||||
process: serverInfo.state.process_count || 0,
|
||||
up: serverInfo.state.net_out_speed / 1024 / 1024 || 0,
|
||||
down: serverInfo.state.net_in_speed / 1024 / 1024 || 0,
|
||||
online: Date.now() - lastActiveTime <= 300000,
|
||||
tcp: serverInfo.state.tcp_conn_count || 0,
|
||||
udp: serverInfo.state.udp_conn_count || 0,
|
||||
mem: (serverInfo.state.mem_used / serverInfo.host.mem_total) * 100 || 0,
|
||||
swap: (serverInfo.state.swap_used / serverInfo.host.swap_total) * 100 || 0,
|
||||
disk: (serverInfo.state.disk_used / serverInfo.host.disk_total) * 100 || 0,
|
||||
stg: (serverInfo.state.disk_used / serverInfo.host.disk_total) * 100 || 0,
|
||||
country_code: serverInfo.host.country_code,
|
||||
};
|
||||
}
|
||||
|
||||
export function formatBytes(bytes: number, decimals: number = 2) {
|
||||
if (!+bytes) return "0 Bytes";
|
||||
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = [
|
||||
"Bytes",
|
||||
"KiB",
|
||||
"MiB",
|
||||
"GiB",
|
||||
"TiB",
|
||||
"PiB",
|
||||
"EiB",
|
||||
"ZiB",
|
||||
"YiB",
|
||||
];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
export function getDaysBetweenDates(date1: string, date2: string): number {
|
||||
const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数
|
||||
const firstDate = new Date(date1);
|
||||
const secondDate = new Date(date2);
|
||||
|
||||
// 计算两个日期之间的天数差异
|
||||
return Math.round(
|
||||
Math.abs((firstDate.getTime() - secondDate.getTime()) / oneDay),
|
||||
);
|
||||
}
|
||||
|
||||
export const fetcher = (url: string) =>
|
||||
fetch(url)
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error(res.statusText);
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => data.data)
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw err;
|
||||
});
|
||||
|
||||
export const nezhaFetcher = async (url: string) => {
|
||||
const res = await fetch(url);
|
||||
|
||||
if (!res.ok) {
|
||||
const error = new Error("An error occurred while fetching the data.");
|
||||
// @ts-expect-error - res.json() returns a Promise<any>
|
||||
error.info = await res.json();
|
||||
// @ts-expect-error - res.status is a number
|
||||
error.status = res.status;
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export function parseISOTimestamp(isoString: string): number {
|
||||
return new Date(isoString).getTime();
|
||||
}
|
||||
|
||||
export function formatRelativeTime(timestamp: number): string {
|
||||
const now = Date.now();
|
||||
const diff = now - timestamp;
|
||||
const hours = Math.floor(diff / (1000 * 60 * 60));
|
||||
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
|
||||
|
||||
if (hours > 24) {
|
||||
const days = Math.floor(hours / 24);
|
||||
return `${days}d`;
|
||||
} else if (hours > 0) {
|
||||
return `${hours}h`;
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}m`;
|
||||
} else if (seconds >= 0) {
|
||||
return `${seconds}s`;
|
||||
}
|
||||
return "0s";
|
||||
}
|
||||
|
||||
export function formatTime(timestamp: number): string {
|
||||
const date = new Date(timestamp);
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const hours = date.getHours().toString().padStart(2, "0");
|
||||
const minutes = date.getMinutes().toString().padStart(2, "0");
|
||||
const seconds = date.getSeconds().toString().padStart(2, "0");
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { createContext, useContext } from "react";
|
||||
import { WebSocketHook } from "../hooks/use-websocket";
|
||||
|
||||
export const WebSocketContext = createContext<WebSocketHook | undefined>(undefined);
|
||||
|
||||
export const useWebSocketContext = (): WebSocketHook => {
|
||||
const context = useContext(WebSocketContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"useWebSocketContext must be used within a WebSocketProvider",
|
||||
);
|
||||
}
|
||||
return context;
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
import { ReactNode } from "react";
|
||||
import useWebSocket from "../hooks/use-websocket";
|
||||
import { WebSocketContext } from "./websocketContext";
|
||||
|
||||
interface WebSocketProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export const WebSocketProvider = ({ children }: WebSocketProviderProps) => {
|
||||
const ws = useWebSocket('/api/v1/ws/server');
|
||||
return (
|
||||
<WebSocketContext.Provider value={ws}>{children}</WebSocketContext.Provider>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user