import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { formatBytes, formatUptime, getOSImage, formatTrafficLimit, } from "@/utils"; import type { NodeWithStatus } from "@/types/node"; import { Link } from "react-router-dom"; import { CpuIcon, MemoryStickIcon, HardDriveIcon } from "lucide-react"; import Flag from "./Flag"; import { Tag } from "../ui/tag"; import { useNodeCommons } from "@/hooks/useNodeCommons"; import { ProgressBar } from "../ui/progress-bar"; import { CircleProgress } from "../ui/circle-progress"; interface NodeCardProps { node: NodeWithStatus; enableSwap: boolean | undefined; } export const NodeCard = ({ node, enableSwap }: NodeCardProps) => { const { stats, isOnline, tagList, cpuUsage, memUsage, swapUsage, diskUsage, load, expired_at, trafficPercentage, } = useNodeCommons(node); const getProgressBarClass = (percentage: number) => { if (percentage > 90) return "bg-red-600"; if (percentage > 50) return "bg-yellow-400"; return "bg-green-500"; }; return (
{node.os} {node.name}
{node.cpu_cores} Cores
{formatBytes(node.mem_total)}
{formatBytes(node.disk_total)}
CPU
{cpuUsage.toFixed(0)}%
内存
{memUsage.toFixed(0)}%
{enableSwap && (
SWAP
{node.swap_total > 0 ? ( {swapUsage.toFixed(0)}% ) : ( OFF )}
)}
硬盘
{diskUsage.toFixed(0)}%
网络:
↑ {stats ? formatBytes(stats.network.up, true) : "N/A"} ↓ {stats ? formatBytes(stats.network.down, true) : "N/A"}
流量
{node.traffic_limit !== 0 && isOnline && stats && ( )}
↑ {stats ? formatBytes(stats.network.totalUp) : "N/A"} ↓ {stats ? formatBytes(stats.network.totalDown) : "N/A"}
{node.traffic_limit !== 0 && isOnline && stats && (
{formatTrafficLimit( node.traffic_limit, node.traffic_limit_type )}
)}
负载 {load}
到期:
{expired_at}
在线: {isOnline && stats ? formatUptime(stats.uptime) : "离线"}
); };