186 lines
7.3 KiB
TypeScript
186 lines
7.3 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { Card, Col, Row, message, Typography, Descriptions, Progress, Table, Space } from 'antd';
|
|
import type { TableColumnsType } from 'antd';
|
|
import {
|
|
SettingOutlined,
|
|
FileTextOutlined,
|
|
DesktopOutlined,
|
|
CoffeeOutlined,
|
|
HddOutlined,
|
|
} from '@ant-design/icons';
|
|
import dayjs from 'dayjs';
|
|
import { getServerInfo } from '../../api/monitor/server';
|
|
import type { ServerDiskInfo, ServerInfoResponse } from '@/types/api';
|
|
import './server-monitor.css';
|
|
|
|
const { Text } = Typography;
|
|
|
|
const defaultServerInfo: ServerInfoResponse = {
|
|
cpu: {},
|
|
mem: {},
|
|
jvm: {},
|
|
sys: {},
|
|
sysFiles: [],
|
|
};
|
|
|
|
const parseTime = (time?: string | number | Date, pattern = 'YYYY-MM-DD HH:mm:ss'): string => {
|
|
return time ? dayjs(time).format(pattern) : '';
|
|
};
|
|
|
|
const toNumber = (value: unknown): number => {
|
|
if (typeof value === 'number') {
|
|
return Number.isFinite(value) ? value : 0;
|
|
}
|
|
if (typeof value === 'string') {
|
|
const parsed = Number.parseFloat(value);
|
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
const renderUsageProgress = (usage: unknown) => {
|
|
const percent = Math.floor(toNumber(usage));
|
|
let status: 'normal' | 'exception' | 'active' | 'success' = 'normal';
|
|
if (percent > 80) {
|
|
status = 'exception';
|
|
} else if (percent > 60) {
|
|
status = 'active';
|
|
}
|
|
return <Progress percent={percent} status={status} />;
|
|
};
|
|
|
|
const ServerMonitorPage = () => {
|
|
const [serverInfo, setServerInfo] = useState<ServerInfoResponse>(defaultServerInfo);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const getList = async () => {
|
|
setLoading(true);
|
|
const hide = message.loading('正在加载服务监控数据,请稍候!', 0);
|
|
try {
|
|
const response = await getServerInfo();
|
|
setServerInfo(response);
|
|
} catch (error: unknown) {
|
|
console.error('Failed to fetch server info:', error);
|
|
message.error('获取服务监控数据失败');
|
|
} finally {
|
|
setLoading(false);
|
|
hide();
|
|
}
|
|
};
|
|
|
|
void getList();
|
|
}, []);
|
|
|
|
const diskColumns: TableColumnsType<ServerDiskInfo> = [
|
|
{ title: '盘符路径', dataIndex: 'dirName', align: 'center' },
|
|
{ title: '文件系统', dataIndex: 'sysTypeName', align: 'center' },
|
|
{ title: '盘符类型', dataIndex: 'typeName', align: 'center' },
|
|
{ title: '总大小', dataIndex: 'total', align: 'center' },
|
|
{ title: '可用大小', dataIndex: 'free', align: 'center' },
|
|
{ title: '已用大小', dataIndex: 'used', align: 'center' },
|
|
{
|
|
title: '已用百分比',
|
|
dataIndex: 'usage',
|
|
align: 'center',
|
|
render: (usage) => (
|
|
<Text type={toNumber(usage) > 80 ? 'danger' : 'secondary'}>
|
|
{toNumber(usage)}% {renderUsageProgress(usage)}
|
|
</Text>
|
|
),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div className="app-container server-monitor-container">
|
|
<Row gutter={[16, 16]}>
|
|
<Col span={12} className="card-box">
|
|
<Card title={<Space><SettingOutlined /> CPU</Space>} loading={loading}>
|
|
<Descriptions column={1} bordered size="small">
|
|
<Descriptions.Item label="核心数">{serverInfo.cpu?.cpuNum}</Descriptions.Item>
|
|
<Descriptions.Item label="用户使用率">
|
|
{serverInfo.cpu?.used}% {renderUsageProgress(serverInfo.cpu?.used)}
|
|
</Descriptions.Item>
|
|
<Descriptions.Item label="系统使用率">
|
|
{serverInfo.cpu?.sys}% {renderUsageProgress(serverInfo.cpu?.sys)}
|
|
</Descriptions.Item>
|
|
<Descriptions.Item label="当前空闲率">
|
|
{serverInfo.cpu?.free}% {renderUsageProgress(serverInfo.cpu?.free)}
|
|
</Descriptions.Item>
|
|
</Descriptions>
|
|
</Card>
|
|
</Col>
|
|
|
|
<Col span={12} className="card-box">
|
|
<Card title={<Space><FileTextOutlined /> 内存</Space>} loading={loading}>
|
|
<Descriptions column={2} bordered size="small">
|
|
<Descriptions.Item label="属性">总内存</Descriptions.Item>
|
|
<Descriptions.Item label="内存">{serverInfo.mem?.total}G</Descriptions.Item>
|
|
<Descriptions.Item label="JVM">{serverInfo.jvm?.total}M</Descriptions.Item>
|
|
|
|
<Descriptions.Item label="已用内存">
|
|
<Text type={toNumber(serverInfo.mem?.usage) > 80 ? 'danger' : 'secondary'}>
|
|
{serverInfo.mem?.used}G
|
|
</Text>
|
|
</Descriptions.Item>
|
|
<Descriptions.Item label="已用内存">
|
|
<Text type={toNumber(serverInfo.jvm?.usage) > 80 ? 'danger' : 'secondary'}>
|
|
{serverInfo.jvm?.used}M
|
|
</Text>
|
|
</Descriptions.Item>
|
|
|
|
<Descriptions.Item label="剩余内存">{serverInfo.mem?.free}G</Descriptions.Item>
|
|
<Descriptions.Item label="剩余内存">{serverInfo.jvm?.free}M</Descriptions.Item>
|
|
|
|
<Descriptions.Item label="使用率">{renderUsageProgress(serverInfo.mem?.usage)}</Descriptions.Item>
|
|
<Descriptions.Item label="使用率">{renderUsageProgress(serverInfo.jvm?.usage)}</Descriptions.Item>
|
|
</Descriptions>
|
|
</Card>
|
|
</Col>
|
|
|
|
<Col span={24} className="card-box">
|
|
<Card title={<Space><DesktopOutlined /> 服务器信息</Space>} loading={loading}>
|
|
<Descriptions column={2} bordered size="small">
|
|
<Descriptions.Item label="服务器名称">{serverInfo.sys?.computerName}</Descriptions.Item>
|
|
<Descriptions.Item label="操作系统">{serverInfo.sys?.osName}</Descriptions.Item>
|
|
<Descriptions.Item label="服务器IP">{serverInfo.sys?.computerIp}</Descriptions.Item>
|
|
<Descriptions.Item label="系统架构">{serverInfo.sys?.osArch}</Descriptions.Item>
|
|
</Descriptions>
|
|
</Card>
|
|
</Col>
|
|
|
|
<Col span={24} className="card-box">
|
|
<Card title={<Space><CoffeeOutlined /> Java虚拟机信息</Space>} loading={loading}>
|
|
<Descriptions column={2} bordered size="small">
|
|
<Descriptions.Item label="Java名称">{serverInfo.jvm?.name}</Descriptions.Item>
|
|
<Descriptions.Item label="Java版本">{serverInfo.jvm?.version}</Descriptions.Item>
|
|
<Descriptions.Item label="启动时间">{parseTime(serverInfo.jvm?.startTime)}</Descriptions.Item>
|
|
<Descriptions.Item label="运行时长">{serverInfo.jvm?.runTime}</Descriptions.Item>
|
|
<Descriptions.Item label="安装路径" span={2}>{serverInfo.jvm?.home}</Descriptions.Item>
|
|
<Descriptions.Item label="项目路径" span={2}>{serverInfo.sys?.userDir}</Descriptions.Item>
|
|
<Descriptions.Item label="运行参数" span={2}>{serverInfo.jvm?.inputArgs}</Descriptions.Item>
|
|
</Descriptions>
|
|
</Card>
|
|
</Col>
|
|
|
|
<Col span={24} className="card-box">
|
|
<Card title={<Space><HddOutlined /> 磁盘状态</Space>} loading={loading}>
|
|
<Table
|
|
dataSource={serverInfo.sysFiles ?? []}
|
|
rowKey={(record) =>
|
|
`${record.dirName ?? 'disk'}-${record.sysTypeName ?? ''}-${record.typeName ?? ''}`
|
|
}
|
|
pagination={false}
|
|
size="small"
|
|
bordered
|
|
columns={diskColumns}
|
|
/>
|
|
</Card>
|
|
</Col>
|
|
</Row>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ServerMonitorPage;
|