fix: process desc + disk display + Chinese uptime + copy toast
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 8s

This commit is contained in:
WangDL 2026-05-22 13:51:12 +08:00
parent ed1e78c5c2
commit 795ef9676d
2 changed files with 29 additions and 29 deletions

View File

@ -6,40 +6,38 @@ import { getServerMetrics, type ServerInfo, type ProcessInfo } from '@/services/
const { Text, Title } = Typography const { Text, Title } = Typography
function CopyTag({ text, icon, color }: { text: string; icon?: React.ReactNode; color?: string }) {
return (
<Tag color={color || 'default'} style={{ cursor: 'pointer' }}
onClick={async () => { await navigator.clipboard.writeText(text); message.success(`已复制: ${text}`) }}>
{icon}{text} <CopyOutlined style={{ fontSize: 10 }} />
</Tag>
)
}
function ServerCard({ server }: { server: ServerInfo }) { function ServerCard({ server }: { server: ServerInfo }) {
const cpuColor = server.cpu.usagePercent > 80 ? '#ff4d4f' : server.cpu.usagePercent > 50 ? '#faad14' : '#52c41a' 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' const memColor = server.memory.percent > 80 ? '#ff4d4f' : server.memory.percent > 50 ? '#faad14' : '#52c41a'
return ( return (
<Card <Card title={<Space><CloudServerOutlined />{server.name}<Tag color="blue">{server.role}</Tag></Space>} style={{ height: '100%' }}>
title={<Space><CloudServerOutlined />{server.name}<Tag color="blue">{server.role}</Tag></Space>}
style={{ height: '100%' }}
>
{/* Network info */}
<Row gutter={[12, 8]} style={{ marginBottom: 16 }}> <Row gutter={[12, 8]} style={{ marginBottom: 16 }}>
<Col span={24}> <Col span={24}>
<Space wrap size="small"> <Space wrap size={[4, 4]}>
<Tag color="default" style={{ cursor: 'pointer' }} onClick={() => { navigator.clipboard.writeText(server.network.publicIp); message.success('已复制') }}> <CopyTag text={server.network.publicIp} icon="🌐 " color="cyan" />
🌐 {server.network.publicIp} <CopyOutlined /> <CopyTag text={server.network.privateIp} icon="🔒 " />
</Tag>
<Tag color="default" style={{ cursor: 'pointer' }} onClick={() => { navigator.clipboard.writeText(server.network.privateIp); message.success('已复制') }}>
🔒 {server.network.privateIp} <CopyOutlined />
</Tag>
{server.network.domains.map(d => ( {server.network.domains.map(d => (
<Tag key={d} color="blue" style={{ cursor: 'pointer' }} onClick={() => { navigator.clipboard.writeText(d); message.success('已复制') }}> <CopyTag key={d} text={d} icon={<GlobalOutlined style={{ marginRight: 2 }} />} color="blue" />
<GlobalOutlined /> {d} <CopyOutlined />
</Tag>
))} ))}
</Space> </Space>
</Col> </Col>
</Row> </Row>
{/* Metrics */}
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
<Col xs={12} sm={6}> <Col xs={12} sm={6}>
<Text type="secondary" style={{ fontSize: 11 }}>CPU ({server.cpu.cores})</Text> <Text type="secondary" style={{ fontSize: 11 }}>CPU · {server.cpu.cores}</Text>
<Progress percent={server.cpu.usagePercent} strokeColor={cpuColor} size="small" format={p => `${p}%`} /> <Progress percent={server.cpu.usagePercent} strokeColor={cpuColor} size="small" format={p => `${p}%`} />
<Text style={{ fontSize: 10 }} type="secondary">{server.cpu.model?.slice(0, 30)}</Text> <Text style={{ fontSize: 10 }} type="secondary">{server.cpu.model?.slice(0, 28)}</Text>
</Col> </Col>
<Col xs={12} sm={6}> <Col xs={12} sm={6}>
<Text type="secondary" style={{ fontSize: 11 }}></Text> <Text type="secondary" style={{ fontSize: 11 }}></Text>
@ -47,13 +45,14 @@ function ServerCard({ server }: { server: ServerInfo }) {
<Text style={{ fontSize: 10 }} type="secondary">{server.memory.used}/{server.memory.total}</Text> <Text style={{ fontSize: 10 }} type="secondary">{server.memory.used}/{server.memory.total}</Text>
</Col> </Col>
<Col xs={24} sm={12}> <Col xs={24} sm={12}>
<Text type="secondary" style={{ fontSize: 11 }}></Text> <Text type="secondary" style={{ fontSize: 11, marginBottom: 2, display: 'block' }}></Text>
{server.disks.map(d => ( {server.disks.filter(d => d.total !== '-').length === 0 && <Text type="secondary" style={{ fontSize: 11 }}></Text>}
<div key={d.mount} style={{ marginBottom: 4 }}> {server.disks.filter(d => d.total !== '-').map(d => (
<Space size={4}> <div key={d.mount} style={{ marginBottom: 3 }}>
<Text style={{ fontSize: 10 }} type="secondary">{d.mount}</Text> <Space size={4} style={{ width: '100%' }}>
<Text style={{ fontSize: 10, minWidth: 36 }} type="secondary">{d.mount}</Text>
<Progress percent={d.percent} size="small" strokeColor={d.percent > 80 ? '#ff4d4f' : '#1677ff'} style={{ flex: 1, margin: 0 }} /> <Progress percent={d.percent} size="small" strokeColor={d.percent > 80 ? '#ff4d4f' : '#1677ff'} style={{ flex: 1, margin: 0 }} />
<Text style={{ fontSize: 10 }}>{d.used}/{d.total}</Text> <Text style={{ fontSize: 10, whiteSpace: 'nowrap' }}>{d.used}/{d.total}</Text>
</Space> </Space>
</div> </div>
))} ))}
@ -64,16 +63,17 @@ function ServerCard({ server }: { server: ServerInfo }) {
</Col> </Col>
</Row> </Row>
{/* Processes */}
<Table <Table
dataSource={server.processes} dataSource={server.processes}
rowKey="pid" size="small" pagination={false} rowKey="pid" size="small" pagination={false}
style={{ marginTop: 12 }} style={{ marginTop: 12 }}
columns={[ columns={[
{ title: 'PID', dataIndex: 'pid', width: 60 }, { title: '进程', dataIndex: 'name', width: 140, ellipsis: true, render: (name: string, r: ProcessInfo) => (
{ title: '进程', dataIndex: 'name', ellipsis: true, render: (name: string, r: ProcessInfo) => ( <Tooltip title={r.desc ? `${r.desc}\n命令: ${r.command}` : `命令: ${r.command}`}>
<Tooltip title={r.command}>{name}</Tooltip> <span>{name}</span>
</Tooltip>
)}, )},
{ title: '说明', dataIndex: 'desc', width: 120, ellipsis: true, render: (d: string) => <Text type="secondary" style={{ fontSize: 12 }}>{d || '-'}</Text> },
{ title: 'CPU', dataIndex: 'cpu', width: 55 }, { title: 'CPU', dataIndex: 'cpu', width: 55 },
{ title: 'MEM', dataIndex: 'mem', width: 55 }, { title: 'MEM', dataIndex: 'mem', width: 55 },
]} ]}

View File

@ -1,7 +1,7 @@
import { api } from './http-client' import { api } from './http-client'
export interface DiskInfo { mount: string; total: string; used: string; free: string; percent: number } export interface DiskInfo { mount: string; total: string; used: string; free: string; percent: number }
export interface ProcessInfo { pid: number; cpu: string; mem: string; name: string; command: string } export interface ProcessInfo { pid: number; cpu: string; mem: string; name: string; desc: string; command: string }
export interface ServerInfo { export interface ServerInfo {
name: string; role: string; hostname: string; name: string; role: string; hostname: string;
cpu: { model: string; cores: number; usagePercent: number }; cpu: { model: string; cores: number; usagePercent: number };