Files
xiaoxia-saas/apps/web/src/pages/admin/SystemMonitor.tsx
T
CI Test 704d381919
CI/CD Pipeline / Validate Code Quality And Tests (push) Waiting to run
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Waiting to run
feat: V21 design system alignment for admin pages
- Create unified Admin.css with V21 design tokens
- Update Dashboard with stat cards and V21 color scheme
- Update Analytics with V21 chart colors and metrics
- Update UserManagement with V21 table and search styles
- Update LogViewer with V21 filter bar and log level tags
- Update SystemMonitor with V21 progress and resource cards
- Update AdminComingSoon with V21 result styling
- Replace all inline styles with V21 CSS classes
- Apply Indigo/Green/Amber/Purple V21 color palette
2026-06-26 21:40:50 +08:00

225 lines
7.8 KiB
TypeScript

/**
* 系统监控页面
*/
import React, { useState, useEffect } from 'react';
import { Card, Row, Col, Progress, Badge, Table, Tag, Button, Space } from 'antd';
import {
CheckCircleOutlined,
CloseCircleOutlined,
SyncOutlined,
ReloadOutlined,
DatabaseOutlined,
ApiOutlined,
CloudServerOutlined,
ThunderboltOutlined,
} from '@ant-design/icons';
import './Admin.css';
const SystemMonitor: React.FC = () => {
const [refreshTime, setRefreshTime] = useState(new Date());
// 模拟实时数据
const [systemMetrics, setSystemMetrics] = useState({
cpu: 35,
memory: 62,
disk: 48,
network: 28,
});
// 服务健康状态
const services = [
{ name: 'API 服务', status: 'healthy', uptime: '99.98%', responseTime: '45ms' },
{ name: 'PostgreSQL', status: 'healthy', uptime: '99.99%', responseTime: '8ms' },
{ name: 'Redis', status: 'healthy', uptime: '99.97%', responseTime: '2ms' },
{ name: 'Celery Worker', status: 'healthy', uptime: '99.95%', responseTime: '-' },
{ name: 'Object Storage', status: 'warning', uptime: '99.85%', responseTime: '120ms' },
];
// API 请求统计
const apiStats = [
{ endpoint: 'POST /api/v1/auth/login', requests: 15420, avgTime: '48ms', errors: 12 },
{ endpoint: 'GET /api/v1/workspaces', requests: 89340, avgTime: '32ms', errors: 5 },
{ endpoint: 'POST /api/v1/projects', requests: 6780, avgTime: '156ms', errors: 8 },
{ endpoint: 'GET /api/v1/assets', requests: 124560, avgTime: '68ms', errors: 23 },
{ endpoint: 'POST /api/v1/subscriptions/subscribe', requests: 234, avgTime: '890ms', errors: 2 },
];
// 错误日志
const recentErrors = [
{ time: '2024-06-17 16:45:32', level: 'ERROR', service: 'API', message: 'Database connection timeout' },
{ time: '2024-06-17 16:42:15', level: 'WARN', service: 'Object Storage', message: 'Slow response detected (>1s)' },
{ time: '2024-06-17 16:38:41', level: 'ERROR', service: 'Celery', message: 'Task retry limit exceeded' },
];
const serviceColumns = [
{
title: '服务名称',
dataIndex: 'name',
key: 'name',
render: (text: string) => <><CloudServerOutlined /> {text}</>,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => {
const config: Record<string, { color: string; icon: React.ReactNode; text: string }> = {
healthy: { color: 'success', icon: <CheckCircleOutlined />, text: '正常' },
warning: { color: 'warning', icon: <SyncOutlined spin />, text: '警告' },
error: { color: 'error', icon: <CloseCircleOutlined />, text: '故障' },
};
const { color, text } = config[status] || config.healthy;
return <Badge status={color as any} text={text} />;
},
},
{ title: '可用性', dataIndex: 'uptime', key: 'uptime' },
{ title: '响应时间', dataIndex: 'responseTime', key: 'responseTime' },
];
const apiColumns = [
{ title: 'API 端点', dataIndex: 'endpoint', key: 'endpoint' },
{ title: '请求数', dataIndex: 'requests', key: 'requests', sorter: (a: any, b: any) => a.requests - b.requests },
{ title: '平均响应时间', dataIndex: 'avgTime', key: 'avgTime' },
{
title: '错误数',
dataIndex: 'errors',
key: 'errors',
render: (errors: number) => (
<Tag className={errors > 10 ? 'xx-tag error' : errors > 5 ? 'xx-tag warning' : 'xx-tag success'}>{errors}</Tag>
),
},
];
const errorColumns = [
{ title: '时间', dataIndex: 'time', key: 'time', width: 180 },
{
title: '级别',
dataIndex: 'level',
key: 'level',
width: 100,
render: (level: string) => (
<Tag className={level === 'ERROR' ? 'xx-tag error' : 'xx-tag warning'}>{level}</Tag>
),
},
{ title: '服务', dataIndex: 'service', key: 'service', width: 120 },
{ title: '错误信息', dataIndex: 'message', key: 'message' },
];
const refreshMetrics = () => {
setSystemMetrics({
cpu: Math.floor(Math.random() * 30) + 30,
memory: Math.floor(Math.random() * 20) + 55,
disk: Math.floor(Math.random() * 10) + 45,
network: Math.floor(Math.random() * 40) + 20,
});
setRefreshTime(new Date());
};
// 模拟实时更新
useEffect(() => {
const interval = setInterval(refreshMetrics, 5000);
return () => clearInterval(interval);
}, []);
const getProgressColor = (value: number) => {
if (value > 80) return '#ef4444';
if (value > 60) return '#f59e0b';
return '#10b981';
};
const getProgressClass = (value: number) => {
if (value > 80) return 'xx-progress-warning';
if (value > 60) return 'xx-progress-warning';
return 'xx-progress-success';
};
const resourceMetrics = [
{ key: 'cpu', label: 'CPU 使用率', value: systemMetrics.cpu, icon: <ThunderboltOutlined />, bg: 'linear-gradient(135deg, #6366f1, #4f46e5)' },
{ key: 'memory', label: '内存使用率', value: systemMetrics.memory, icon: <DatabaseOutlined />, bg: 'linear-gradient(135deg, #34d399, #10b981)' },
{ key: 'disk', label: '磁盘使用率', value: systemMetrics.disk, icon: <CloudServerOutlined />, bg: 'linear-gradient(135deg, #fbbf24, #f59e0b)' },
{ key: 'network', label: '网络使用率', value: systemMetrics.network, icon: <ApiOutlined />, bg: 'linear-gradient(135deg, #a78bfa, #8b5cf6)' },
];
return (
<div className="system-monitor-page">
<div className="xx-page-head">
<div className="xx-page-head-content">
<h2>系统监控</h2>
<p>服务器资源、服务健康与 API 统计</p>
</div>
<div className="xx-page-head-actions">
<Space>
<span className="xx-refresh-time">上次更新: {refreshTime.toLocaleTimeString()}</span>
<Button icon={<ReloadOutlined />} onClick={refreshMetrics} className="xx-primary-btn">
刷新
</Button>
</Space>
</div>
</div>
{/* 系统资源监控 */}
<Row gutter={24} className="xx-grid-4">
{resourceMetrics.map((metric) => (
<Col span={6} key={metric.key}>
<div className="xx-resource-card">
<div
className="xx-resource-card-icon"
style={{ background: metric.bg, color: 'white' }}
>
{metric.icon}
</div>
<div className="xx-resource-card-label">{metric.label}</div>
<Progress
type="circle"
percent={metric.value}
strokeColor={getProgressColor(metric.value)}
className={getProgressClass(metric.value)}
/>
</div>
</Col>
))}
</Row>
{/* 服务健康状态 */}
<div className="xx-table-wrapper" style={{ marginBottom: 24 }}>
<Card title="服务健康状态" className="xx-card">
<Table
columns={serviceColumns}
dataSource={services}
rowKey="name"
pagination={false}
/>
</Card>
</div>
{/* API 请求统计 */}
<div className="xx-table-wrapper" style={{ marginBottom: 24 }}>
<Card title="API 请求统计 (最近 1 小时)" className="xx-card">
<Table
columns={apiColumns}
dataSource={apiStats}
rowKey="endpoint"
pagination={false}
/>
</Card>
</div>
{/* 最近错误 */}
<div className="xx-table-wrapper">
<Card title="最近错误日志" className="xx-card">
<Table
columns={errorColumns}
dataSource={recentErrors}
rowKey="time"
pagination={false}
/>
</Card>
</div>
</div>
);
};
export default SystemMonitor;
export const Component = SystemMonitor;