import type { ReactNode } from 'react' import { Activity, Cpu, Database, Film, HardDrive, Radio, Users } from 'lucide-react' import type { Hardware, StatsSnapshot } from '../types' function fmtBytes(n: number): string { if (!n || n <= 0) return '—' const u = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] let v = n let i = 0 while (v >= 1024 && i < u.length - 1) { v /= 1024 i++ } return `${v.toFixed(2)} ${u[i]}` } function fmtHours(seconds: number): string { if (!seconds || seconds <= 0) return '—' const h = Math.floor(seconds / 3600) return `${h.toLocaleString()} h` } export function StatsHeader({ generatedAt, lastMonitorAt, monitorError, }: { generatedAt: string lastMonitorAt: string monitorError: string }) { return (

运行状态

聚合快照:{new Date(generatedAt).toLocaleString()} · 实时监控每 2 秒刷新

{monitorError ? '监控重试中' : '实时监控中'}

最近刷新:{lastMonitorAt ? new Date(lastMonitorAt).toLocaleTimeString() : '—'}

) } export function StatsTiles({ snap, live, memPct, diskPct, }: { snap: StatsSnapshot live: Hardware memPct: number diskPct: number }) { return (
} label="媒体库" value={snap.libraries.toLocaleString()} /> } label="媒体总数" value={snap.media_count.toLocaleString()} /> } label="用户" value={snap.users_count.toLocaleString()} /> } label="入库容量" value={fmtBytes(snap.total_size_bytes)} /> } label="累计时长" value={fmtHours(snap.total_seconds)} /> } label="CPU 占用" value={`${live.cpu_percent.toFixed(1)}%`} meter={live.cpu_percent} /> } label="内存占用" value={`${memPct.toFixed(1)}%`} /> } label="数据盘占用" value={`${diskPct.toFixed(1)}%`} />
) } export function SystemMonitorSection({ live, memPct, diskPct, monitorError, }: { live: Hardware memPct: number diskPct: number monitorError: string }) { return (

系统实时监控

Live
{monitorError &&

实时监控错误:{monitorError}

}
) } export function AggregateStatsSection({ generatedAt }: { generatedAt: string }) { return (

聚合统计

) } function Tile({ icon, label, value, meter, }: { icon: ReactNode label: string value: string meter?: number }) { return (
{icon}

{label}

{value}

{typeof meter === 'number' && }
) } function Meter({ label, value }: { label: string; value: number }) { return (
{label} {value.toFixed(1)}%
) } function Bar({ value }: { value: number }) { const pct = Math.max(0, Math.min(100, value || 0)) const color = pct > 85 ? 'bg-red-500' : pct > 65 ? 'bg-amber-500' : 'bg-emerald-500' return (
) } function Row({ label, value }: { label: string; value: string }) { return (
{label} {value}
) }