实现系统运维页面:服务状态看板、系统负载、API请求监控、操作日志、平台公告
This commit is contained in:
+140
-4
@@ -1,6 +1,142 @@
|
||||
const Ops = () => (
|
||||
<div className="h-full flex items-center justify-center text-neutral-400 text-center">
|
||||
<div><div className="text-lg mb-1">系统运维</div><div className="text-sm">开发中...</div></div>
|
||||
import { Card, Table, Tag, Button, Badge, Progress, Space, message } from 'antd'
|
||||
import { PlusOutlined, EditOutlined, DeleteOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { Line } from '@ant-design/charts'
|
||||
|
||||
const services = [
|
||||
{ name: 'API 服务', status: 'normal' as const },
|
||||
{ name: 'WebSocket 服务', status: 'normal' as const },
|
||||
{ name: '数据库', status: 'warning' as const },
|
||||
{ name: '消息队列', status: 'normal' as const },
|
||||
{ name: 'CDN', status: 'normal' as const },
|
||||
]
|
||||
|
||||
const statusDisplay = { normal: { color: 'green', text: '正常' }, warning: { color: 'orange', text: '告警' }, error: { color: 'red', text: '故障' } }
|
||||
|
||||
const loadData = [
|
||||
{ type: 'CPU 使用率', percent: 45 },
|
||||
{ type: '内存使用率', percent: 62 },
|
||||
{ type: '磁盘使用率', percent: 38 },
|
||||
]
|
||||
|
||||
const apiData = [
|
||||
{ time: '10:00', requests: 1250, errors: 2 }, { time: '10:10', requests: 1380, errors: 3 },
|
||||
{ time: '10:20', requests: 1420, errors: 1 }, { time: '10:30', requests: 1560, errors: 5 },
|
||||
{ time: '10:40', requests: 1320, errors: 2 }, { time: '10:50', requests: 1480, errors: 0 },
|
||||
{ time: '11:00', requests: 1620, errors: 3 },
|
||||
]
|
||||
|
||||
const logs = [
|
||||
{ time: '2026-07-14 10:30', operator: '管理员A', action: '开通新租户', detail: '赵六科技', ip: '192.168.1.100' },
|
||||
{ time: '2026-07-14 09:15', operator: '管理员B', action: '套餐修改', detail: '专业版 → 企业版', ip: '192.168.1.101' },
|
||||
{ time: '2026-07-13 16:20', operator: '管理员A', action: '公告发布', detail: '系统维护通知', ip: '192.168.1.100' },
|
||||
{ time: '2026-07-13 14:00', operator: '管理员B', action: '租户暂停', detail: '孙八信息', ip: '192.168.1.101' },
|
||||
{ time: '2026-07-13 10:45', operator: '管理员A', action: '套餐上架', detail: '专业版', ip: '192.168.1.100' },
|
||||
]
|
||||
|
||||
const announcements = [
|
||||
{ id: '1', title: '系统维护通知', content: '平台将于7月20日 02:00-04:00 进行例行维护', time: '2026-07-13', status: 'published' },
|
||||
{ id: '2', title: '新功能上线', content: '知识库批量导入功能已上线', time: '2026-07-10', status: 'published' },
|
||||
{ id: '3', title: '版本更新预告', content: 'V3.0 版本即将发布,新增 AI 助手功能', time: '2026-07-15', status: 'draft' },
|
||||
]
|
||||
|
||||
const Ops = () => {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold text-neutral-800 mb-5">系统运维</h2>
|
||||
|
||||
{/* 服务状态 + 系统负载 */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 mb-6">
|
||||
<Card title="服务状态看板" className="!rounded-lg" bordered={false} extra={<ReloadOutlined className="cursor-pointer text-neutral-400 hover:text-blue-500" />}>
|
||||
<div className="space-y-3">
|
||||
{services.map(s => (
|
||||
<div key={s.name} className="flex items-center justify-between py-2 px-3 bg-neutral-50 rounded-lg">
|
||||
<span className="text-sm text-neutral-700">{s.name}</span>
|
||||
<Space>
|
||||
<Badge status={s.status === 'normal' ? 'success' : s.status === 'warning' ? 'warning' : 'error'} />
|
||||
<Tag color={statusDisplay[s.status].color}>{statusDisplay[s.status].text}</Tag>
|
||||
</Space>
|
||||
</div>
|
||||
)
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card title="系统负载" className="!rounded-lg" bordered={false}>
|
||||
<div className="space-y-5">
|
||||
{loadData.map(l => (
|
||||
<div key={l.type}>
|
||||
<div className="flex justify-between text-sm mb-1.5">
|
||||
<span className="text-neutral-600">{l.type}</span>
|
||||
<span className={`font-medium ${l.percent > 80 ? 'text-red-500' : l.percent > 60 ? 'text-orange-500' : 'text-green-600'}`}>{l.percent}%</span>
|
||||
</div>
|
||||
<Progress percent={l.percent} showInfo={false} strokeColor={l.percent > 80 ? '#dc2626' : l.percent > 60 ? '#d97706' : '#16a34a'} />
|
||||
</div>
|
||||
))}
|
||||
<div className="text-xs text-neutral-400 mt-3">数据刷新频率:30秒 · 超过 80% 触发告警</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* API 请求图表 */}
|
||||
<Card title="API 请求监控" className="!rounded-lg mb-6" bordered={false}>
|
||||
<div style={{ height: 260 }}>
|
||||
<Line
|
||||
data={apiData}
|
||||
xField="time"
|
||||
yField="requests"
|
||||
height={260}
|
||||
color="#2563eb"
|
||||
smooth
|
||||
point={{ size: 2 }}
|
||||
axis={{ y: { grid: true, gridStroke: '#f1f5f9' } }}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* 操作日志 + 公告 */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<Card title="操作日志" className="!rounded-lg" bordered={false}>
|
||||
<Table
|
||||
dataSource={logs}
|
||||
rowKey="time"
|
||||
pagination={{ pageSize: 5 }}
|
||||
size="small"
|
||||
columns={[
|
||||
{ title: '时间', dataIndex: 'time', key: 'time', render: (t: string) => <span className="text-xs text-neutral-500">{t}</span> },
|
||||
{ title: '操作人', dataIndex: 'operator', key: 'operator' },
|
||||
{ title: '操作', dataIndex: 'action', key: 'action' },
|
||||
{ title: '详情', dataIndex: 'detail', key: 'detail', render: (d: string) => <span className="text-neutral-500">{d}</span> },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="平台公告"
|
||||
className="!rounded-lg"
|
||||
bordered={false}
|
||||
extra={<Button type="primary" size="small" icon={<PlusOutlined />} onClick={() => message.info('公告编辑')}>新建公告</Button>}
|
||||
>
|
||||
<div className="space-y-3">
|
||||
{announcements.map(a => (
|
||||
<div key={a.id} className="p-3 border border-neutral-100 rounded-lg">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-sm font-medium text-neutral-700">{a.title}</span>
|
||||
<Tag color={a.status === 'published' ? 'green' : 'default'} className="text-xs">{a.status === 'published' ? '已发布' : '草稿'}</Tag>
|
||||
</div>
|
||||
<p className="text-xs text-neutral-400 mb-2">{a.content}</p>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs text-neutral-300">{a.time}</span>
|
||||
<Space size={0}>
|
||||
<Button type="link" size="small" icon={<EditOutlined />}>编辑</Button>
|
||||
<Button type="link" size="small" danger icon={<DeleteOutlined />}>删除</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Ops
|
||||
|
||||
Reference in New Issue
Block a user