import { useState } from 'react' import { useQuery, useQueryClient } from '@tanstack/react-query' import { Card, Row, Col, Progress, Table, Tag, Typography, Button, Space, Tooltip, App } from 'antd' import { CloudServerOutlined, ReloadOutlined, CopyOutlined, GlobalOutlined } from '@ant-design/icons' import { getServerMetrics, type ServerInfo, type ProcessInfo } from '@/services/server-api' const { Text, Title } = Typography function CopyTag({ text, icon, color }: { text: string; icon?: React.ReactNode; color?: string }) { const { message } = App.useApp() return ( { try { await navigator.clipboard.writeText(text); message.success(`已复制: ${text}`) } catch { message.error('复制失败') } }}> {icon}{text} ) } function ServerCard({ server }: { server: ServerInfo }) { const cpuColor = server.cpu.usagePercent > 80 ? '#ff4d4f' : server.cpu.usagePercent > 50 ? '#faad14' : '#52c41a' const memColor = server.memory.percent > 80 ? '#ff4d4f' : server.memory.percent > 50 ? '#faad14' : '#52c41a' return ( {server.name}{server.role}} style={{ height: '100%' }}> {/* IP & domains — fixed height */}
{server.network.domains.map(d => ( } color="blue" /> ))}
{/* Metrics — fixed height grid */}
CPU · {server.cpu.cores}核 `${p}%`} /> 内存 {server.memory.percent}% {server.memory.used}/{server.memory.total} 磁盘 {(server.disks || []).map(d => (
{d.mount} 80 ? '#ff4d4f' : '#1677ff'} style={{ flex: 1, margin: 0 }} /> {d.used}
))}
{/* Uptime */}
🕐 {server.uptime}
{/* Process table — fixed height */} ( {name} )}, { title: '说明', dataIndex: 'desc', width: 90, ellipsis: true, render: (d: string) => {d || '-'} }, { title: 'CPU', dataIndex: 'cpu', width: 50 }, { title: 'MEM', dataIndex: 'mem', width: 50 }, ]} locale={{ emptyText: '暂无' }} /> ) } function ServersContent() { const qc = useQueryClient() const [refreshing, setRefreshing] = useState(false) const { data } = useQuery({ queryKey: ['servers', 'metrics'], queryFn: getServerMetrics, staleTime: 30_000, }) const handleRefresh = async () => { setRefreshing(true) await qc.invalidateQueries({ queryKey: ['servers', 'metrics'] }) setTimeout(() => setRefreshing(false), 800) } return (
<CloudServerOutlined /> 服务器运维
{(data?.servers || []).map(s => (
))} ) } export default function ServersPage() { return }