import type { MonitorNodeApiItem } from "@/api/types"; import { useCallback, useEffect, useMemo, useState } from "react"; import toast from "react-hot-toast"; import { RefreshCw, LayoutGrid, List, Server, ArrowRightLeft } from "lucide-react"; import { AnimatedPage } from "@/components/animated-page"; import { Button } from "@/shadcn-bridge/heroui/button"; import { Card, CardBody, CardHeader } from "@/shadcn-bridge/heroui/card"; import { getMonitorNodes } from "@/api"; import { MonitorView } from "@/pages/node/monitor-view"; import { TunnelMonitorView } from "@/pages/node/tunnel-monitor-view"; type MonitorNode = { id: number; name: string; connectionStatus: "online" | "offline"; version?: string; }; type MonitorTab = "nodes" | "tunnels"; export default function MonitorPage() { const [nodes, setNodes] = useState([]); const [nodesLoading, setNodesLoading] = useState(false); const [nodesError, setNodesError] = useState(null); const [viewMode, setViewMode] = useState<"list" | "grid">("list"); const [activeTab, setActiveTab] = useState("nodes"); const loadNodes = useCallback(async (options?: { silent?: boolean }) => { const silent = options?.silent ?? false; if (!silent) setNodesLoading(true); try { const response = await getMonitorNodes(); if (response.code === 0 && Array.isArray(response.data)) { setNodesError(null); setNodes(response.data); return; } if (response.code === 403) { setNodes([]); setNodesError(response.msg || "暂无监控权限,请联系管理员授权"); return; } if (!silent) toast.error(response.msg || "加载节点失败"); } catch { if (!silent) toast.error("加载节点失败"); } finally { if (!silent) setNodesLoading(false); } }, []); useEffect(() => { void loadNodes(); }, [loadNodes]); useEffect(() => { const timer = window.setInterval(() => { void loadNodes({ silent: true }); }, 30_000); return () => window.clearInterval(timer); }, [loadNodes]); const nodeMap = useMemo(() => { const list: MonitorNode[] = nodes .filter((n) => Number(n.id) > 0) .map((n) => ({ id: Number(n.id), name: String(n.name ?? ""), connectionStatus: n.status === 1 ? "online" : "offline", version: n.version, })); return new Map(list.map((n) => [n.id, n])); }, [nodes]); return (

监控

实时节点状态 + 隧道质量检测 + 历史指标图表 + 服务监控(TCP/ICMP)
{activeTab === "nodes" && ( )}
{/* Tab Switcher */}
{nodesError && activeTab === "nodes" ? (

节点列表

{nodesError}
) : null}
{activeTab === "nodes" ? ( ) : ( )}
); }