"use client" import * as React from "react" import {useCallback, useEffect, useRef, useState} from "react" import {toast} from "sonner" import {Activity, Cpu, Database, HardDrive, Layers, RefreshCw} from "lucide-react" import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/components/ui/card" import {Button} from "@/components/ui/button" import {Switch} from "@/components/ui/switch" import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from "@/components/ui/select" import {Badge} from "@/components/ui/badge" import {Progress} from "@/components/ui/progress" import {Skeleton} from "@/components/ui/skeleton" import type {SystemStatus} from "@/lib/services" import services from "@/lib/services" /** * 格式化数字,每3位加逗号 */ const formatNumber = (num: number | string) => { if (num === undefined || num === null) return "0" return num.toString().replace(/\B(?=(\d{3})+(?!\B))/g, ",") } /** * 运行时系统状态展示与管理组件 */ export function SystemStatusManager() { const [status, setStatus] = useState(null) const [loading, setLoading] = useState(true) const [wavelet, setWavelet] = useState(false) const [autoRefresh, setAutoRefresh] = useState(true) const [intervalTime, setIntervalTime] = useState("5000") // 默认5秒 const intervalRef = useRef(null) const prevStatusRef = useRef(null) const [changedFields, setChangedFields] = useState>({}) // 获取状态数据 const fetchStatus = useCallback(async (isSilent = false) => { if (!isSilent) setWavelet(true) try { const data = await services.admin.getSystemStatus() // 检测变化的字段用于微动画效果 if (prevStatusRef.current) { const changes: Record = {} Object.keys(data).forEach((key) => { const k = key as keyof SystemStatus if (prevStatusRef.current && prevStatusRef.current[k] !== data[k]) { changes[k] = true } }) setChangedFields(changes) // 1秒后清除变化状态 setTimeout(() => { setChangedFields({}) }, 1000) } setStatus(data) prevStatusRef.current = data } catch (err) { toast.error("获取系统状态失败", { description: err instanceof Error ? err.message : "请求时发生未知错误" }) } finally { setLoading(false) setWavelet(false) } }, []) // 轮询逻辑 useEffect(() => { // 首次加载 fetchStatus() }, [fetchStatus]) useEffect(() => { if (intervalRef.current) { clearInterval(intervalRef.current) } if (autoRefresh) { const time = parseInt(intervalTime, 10) intervalRef.current = setInterval(() => { fetchStatus(true) }, time) } return () => { if (intervalRef.current) { clearInterval(intervalRef.current) } } }, [autoRefresh, intervalTime, fetchStatus]) // 计算内存分配百分比 (Alloc / Sys) const getMemoryUsagePercent = () => { if (!status) return 0 const parseSizeToBytes = (sizeStr: string): number => { const parts = sizeStr.split(" ") if (parts.length < 2) return 0 const value = parseFloat(parts[0]) const unit = parts[1].toLowerCase() if (unit.startsWith("gib")) return value * 1024 * 1024 * 1024 if (unit.startsWith("mib")) return value * 1024 * 1024 if (unit.startsWith("kib")) return value * 1024 return value } const alloc = parseSizeToBytes(status.alloc) const sys = parseSizeToBytes(status.sys) if (sys === 0) return 0 return Math.min(Math.round((alloc / sys) * 100), 100) } // 闪烁动画类 const getPulseClass = (field: string) => { return changedFields[field] ? "animate-pulse text-primary font-bold transition-all duration-300 scale-105 inline-block" : "transition-all duration-300" } const RenderMetricRow = ({ label, value, field }: { label: string; value: string | number; field?: string }) => (
{label} {typeof value === "number" ? formatNumber(value) : value}
) if (loading) { return (
) } return (
{/* 顶部控制栏 */}

系统状态

监控后端服务的核心运行时状态与内存指标

{autoRefresh && ( )}
{status && ( <> {/* 主网格排版 */}
{/* 1. 服务概览 */}
服务概览 服务的基础生命指标
{/* 2. 内存统计 */}
内存统计 主内存消耗概览
{/* 物理内存水位比例 */}
当前使用率 (Alloc / Sys) {getMemoryUsagePercent()}%
{/* 3. 堆/栈详情 */}
堆/栈详情 运行时堆栈内存空间细节
{/* 4. 底层组件与结构体 */}
底层及结构体内存 运行时底层管理结构体开销
{/* 5. 垃圾回收与分配计数 */}
垃圾回收与分配计数 GC 历史数据与分配频次
)}
) }