diff --git a/apps/web/src/pages/admin/AdminComingSoon.tsx b/apps/web/src/pages/admin/AdminComingSoon.tsx index 33c52e335..e2a8abd46 100644 --- a/apps/web/src/pages/admin/AdminComingSoon.tsx +++ b/apps/web/src/pages/admin/AdminComingSoon.tsx @@ -1,24 +1,32 @@ import React from 'react'; import { Button, Card, Result } from 'antd'; import { useNavigate } from 'react-router-dom'; +import './Admin.css'; const AdminComingSoon: React.FC = () => { const navigate = useNavigate(); return ( -
- - navigate('/workspaces')}> - 返回工作空间 - , - ]} - /> - +
+
+ + navigate('/workspaces')} + className="xx-primary-btn" + > + 返回工作空间 + , + ]} + /> + +
); }; diff --git a/apps/web/src/pages/admin/Analytics.tsx b/apps/web/src/pages/admin/Analytics.tsx index f2c14b852..186e6e67a 100644 --- a/apps/web/src/pages/admin/Analytics.tsx +++ b/apps/web/src/pages/admin/Analytics.tsx @@ -24,9 +24,22 @@ import { DollarOutlined, ProjectOutlined, } from '@ant-design/icons'; +import './Admin.css'; const { RangePicker } = DatePicker; +// V21 配色 +const V21_COLORS = { + primary: '#4f46e5', + primaryLight: '#6366f1', + success: '#10b981', + successLight: '#34d399', + warning: '#f59e0b', + warningLight: '#fbbf24', + purple: '#8b5cf6', + purpleLight: '#a78bfa', +}; + const Analytics: React.FC = () => { // 模拟用户增长数据 const userGrowthData = [ @@ -50,17 +63,17 @@ const Analytics: React.FC = () => { // 订阅计划分布 const planDistribution = [ - { name: 'Free', value: 485, color: '#8884d8' }, - { name: 'Pro', value: 120, color: '#82ca9d' }, - { name: 'Enterprise', value: 15, color: '#ffc658' }, + { name: 'Free', value: 485, color: '#a78bfa' }, + { name: 'Pro', value: 120, color: '#34d399' }, + { name: 'Enterprise', value: 15, color: '#fbbf24' }, ]; // 活跃度统计 const activityStats = [ - { metric: '日活跃用户 (DAU)', value: 892, growth: '+12.5%', icon: }, - { metric: '月活跃用户 (MAU)', value: 3456, growth: '+8.3%', icon: }, - { metric: '本月收入', value: 13365, prefix: '¥', growth: '+51.6%', icon: }, - { metric: '活跃项目数', value: 2341, growth: '+18.2%', icon: }, + { metric: '日活跃用户 (DAU)', value: 892, growth: '+12.5%', icon: , colorClass: 'primary' }, + { metric: '月活跃用户 (MAU)', value: 3456, growth: '+8.3%', icon: , colorClass: 'success' }, + { metric: '本月收入', value: 13365, prefix: '¥', growth: '+51.6%', icon: , colorClass: 'warning' }, + { metric: '活跃项目数', value: 2341, growth: '+18.2%', icon: , colorClass: 'purple' }, ]; // 用户留存表格 @@ -80,107 +93,149 @@ const Analytics: React.FC = () => { { title: 'Day 90', dataIndex: 'day90', key: 'day90' }, ]; + const colorMap: Record = { + primary: '#4f46e5', + success: '#10b981', + warning: '#f59e0b', + purple: '#8b5cf6', + }; + return ( -
-
-

数据分析

- - - +
+
+
+

数据分析

+

用户增长、营收趋势与留存分析

+
+
+ + + +
{/* 关键指标 */} - + {activityStats.map((stat, index) => ( - - -
+
+
+
+ {stat.icon} +
+
+
{stat.metric}
+
+ {stat.prefix}{stat.value.toLocaleString()} +
+
{stat.growth} vs 上月
- +
))} {/* 图表区域 */} - + {/* 用户增长趋势 */} - - - - - - - - - - - - - +
+ + + + + + + + + + + + + +
{/* 订阅计划分布 */} - - - - `${entry.name}: ${entry.value}`} - outerRadius={80} - fill="#8884d8" - dataKey="value" - > - {planDistribution.map((entry, index) => ( - - ))} - - - - - +
+ + + + `${entry.name}: ${entry.value}`} + outerRadius={80} + fill="#8884d8" + dataKey="value" + > + {planDistribution.map((entry, index) => ( + + ))} + + + + + +
{/* 营收趋势 */} - + - - - - - - - - - - - - +
+ + + + + + + + + + + + +
{/* 用户留存表 */} - - - +
+ +
+ + ); }; diff --git a/apps/web/src/pages/admin/Dashboard.tsx b/apps/web/src/pages/admin/Dashboard.tsx index e508e7ad7..469b6c2d7 100644 --- a/apps/web/src/pages/admin/Dashboard.tsx +++ b/apps/web/src/pages/admin/Dashboard.tsx @@ -9,14 +9,15 @@ import { DollarOutlined, RiseOutlined, } from '@ant-design/icons'; +import './Admin.css'; const Dashboard: React.FC = () => { // 模拟数据 const stats = [ - { title: '总用户数', value: 1234, icon: , color: '#1890ff' }, - { title: '付费用户', value: 156, icon: , color: '#52c41a' }, - { title: '月收入', value: 15444, prefix: '¥', icon: , color: '#faad14' }, - { title: '活跃用户', value: 892, icon: , color: '#722ed1' }, + { title: '总用户数', value: 1234, icon: , colorClass: 'primary' }, + { title: '付费用户', value: 156, icon: , colorClass: 'success' }, + { title: '月收入', value: 15444, prefix: '¥', icon: , colorClass: 'warning' }, + { title: '活跃用户', value: 892, icon: , colorClass: 'purple' }, ]; const recentUsers = [ @@ -31,34 +32,51 @@ const Dashboard: React.FC = () => { { title: '注册时间', dataIndex: 'created_at', key: 'created_at' }, ]; + const colorMap: Record = { + primary: '#4f46e5', + success: '#10b981', + warning: '#f59e0b', + purple: '#8b5cf6', + }; + return ( -
-

Dashboard

+
+
+

Dashboard

+

系统数据总览与关键指标

+
- + {stats.map((stat, index) => (
- - - +
+
+
+ {stat.icon} +
+
+
{stat.title}
+
+ {stat.prefix}{stat.value.toLocaleString()} +
+
))} - -
- +
+ +
+ + ); }; diff --git a/apps/web/src/pages/admin/LogViewer.tsx b/apps/web/src/pages/admin/LogViewer.tsx index 39bcb98e3..af0d6d527 100644 --- a/apps/web/src/pages/admin/LogViewer.tsx +++ b/apps/web/src/pages/admin/LogViewer.tsx @@ -10,6 +10,7 @@ import { EyeOutlined, } from '@ant-design/icons'; import type { ColumnsType } from 'antd/es/table'; +import './Admin.css'; const { Search } = Input; const { RangePicker } = DatePicker; @@ -118,14 +119,14 @@ const LogViewer: React.FC = () => { }, ]; - const getLevelColor = (level: string) => { - const colors: Record = { - INFO: 'blue', - WARN: 'orange', - ERROR: 'red', - DEBUG: 'default', + const getLevelTagClass = (level: string) => { + const classes: Record = { + INFO: 'xx-tag info', + WARN: 'xx-tag warning', + ERROR: 'xx-tag error', + DEBUG: 'xx-tag debug', }; - return colors[level] || 'default'; + return classes[level] || 'xx-tag debug'; }; const handleViewDetails = (log: LogEntry) => { @@ -146,7 +147,7 @@ const LogViewer: React.FC = () => { dataIndex: 'level', key: 'level', width: 100, - render: (level: string) => {level}, + render: (level: string) => {level}, filters: [ { text: 'INFO', value: 'INFO' }, { text: 'WARN', value: 'WARN' }, @@ -205,53 +206,61 @@ const LogViewer: React.FC = () => { ]; return ( -
-

日志查看器

+
+
+

日志查看器

+

系统日志查询与监控

+
- - - } - style={{ width: 300 }} - /> +
+ } + className="xx-search-input" + style={{ width: 280 }} + /> - + - + - + - - - - + + +
- +
{ }} scroll={{ x: 1200 }} /> - + {/* 日志详情抽屉 */} { width={600} open={drawerVisible} onClose={() => setDrawerVisible(false)} + className="xx-drawer" > {selectedLog && (
-
- 时间: -
{selectedLog.timestamp}
+
+
时间
+
{selectedLog.timestamp}
-
- 级别: -
- {selectedLog.level} +
+
级别
+
+ {selectedLog.level}
-
- 服务: -
{selectedLog.service}
+
+
服务
+
{selectedLog.service}
{selectedLog.user && ( -
- 用户: -
{selectedLog.user}
+
+
用户
+
{selectedLog.user}
)} -
- 操作: -
{selectedLog.action}
+
+
操作
+
{selectedLog.action}
-
- 详细信息: -
- {selectedLog.details} -
+
+
详细信息
+
{selectedLog.details}
{selectedLog.ip && ( -
- IP 地址: -
{selectedLog.ip}
+
+
IP 地址
+
{selectedLog.ip}
)} {selectedLog.request_id && ( -
- Request ID: -
- {selectedLog.request_id} -
+
+
Request ID
+
{selectedLog.request_id}
)}
diff --git a/apps/web/src/pages/admin/SystemMonitor.tsx b/apps/web/src/pages/admin/SystemMonitor.tsx index 680bea4d7..9d9109bbc 100644 --- a/apps/web/src/pages/admin/SystemMonitor.tsx +++ b/apps/web/src/pages/admin/SystemMonitor.tsx @@ -13,6 +13,7 @@ import { CloudServerOutlined, ThunderboltOutlined, } from '@ant-design/icons'; +import './Admin.css'; const SystemMonitor: React.FC = () => { const [refreshTime, setRefreshTime] = useState(new Date()); @@ -84,7 +85,7 @@ const SystemMonitor: React.FC = () => { dataIndex: 'errors', key: 'errors', render: (errors: number) => ( - 10 ? 'red' : errors > 5 ? 'orange' : 'green'}>{errors} + 10 ? 'xx-tag error' : errors > 5 ? 'xx-tag warning' : 'xx-tag success'}>{errors} ), }, ]; @@ -97,7 +98,7 @@ const SystemMonitor: React.FC = () => { key: 'level', width: 100, render: (level: string) => ( - {level} + {level} ), }, { title: '服务', dataIndex: 'service', key: 'service', width: 120 }, @@ -117,111 +118,103 @@ const SystemMonitor: React.FC = () => { // 模拟实时更新 useEffect(() => { const interval = setInterval(refreshMetrics, 5000); - return () => clearInterval(interval); }, []); const getProgressColor = (value: number) => { - if (value > 80) return '#ff4d4f'; - if (value > 60) return '#faad14'; - return '#52c41a'; + 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: , bg: 'linear-gradient(135deg, #6366f1, #4f46e5)' }, + { key: 'memory', label: '内存使用率', value: systemMetrics.memory, icon: , bg: 'linear-gradient(135deg, #34d399, #10b981)' }, + { key: 'disk', label: '磁盘使用率', value: systemMetrics.disk, icon: , bg: 'linear-gradient(135deg, #fbbf24, #f59e0b)' }, + { key: 'network', label: '网络使用率', value: systemMetrics.network, icon: , bg: 'linear-gradient(135deg, #a78bfa, #8b5cf6)' }, + ]; + return ( -
-
-

系统监控

- - 上次更新: {refreshTime.toLocaleTimeString()} - - +
+
+
+

系统监控

+

服务器资源、服务健康与 API 统计

+
+
+ + 上次更新: {refreshTime.toLocaleTimeString()} + + +
{/* 系统资源监控 */} - -
- -
- -
CPU 使用率
+ + {resourceMetrics.map((metric) => ( +
+
+
+ {metric.icon} +
+
{metric.label}
- - - - -
- -
内存使用率
- -
-
- - - -
- -
磁盘使用率
- -
-
- - - -
- -
网络使用率
- -
-
- + + ))} {/* 服务健康状态 */} - -
- +
+ +
+ + {/* API 请求统计 */} - -
- +
+ +
+ + {/* 最近错误 */} - -
- +
+ +
+ + ); }; diff --git a/apps/web/src/pages/admin/UserManagement.tsx b/apps/web/src/pages/admin/UserManagement.tsx index e8d25e75a..18d3ac53b 100644 --- a/apps/web/src/pages/admin/UserManagement.tsx +++ b/apps/web/src/pages/admin/UserManagement.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { Table, Button, Space, Tag, Input, Card } from 'antd'; import { SearchOutlined, LockOutlined, UnlockOutlined } from '@ant-design/icons'; +import './Admin.css'; const { Search } = Input; @@ -44,7 +45,7 @@ const UserManagement: React.FC = () => { dataIndex: 'is_email_verified', key: 'is_email_verified', render: (verified: boolean) => ( - + {verified ? '已验证' : '未验证'} ), @@ -54,7 +55,7 @@ const UserManagement: React.FC = () => { dataIndex: 'status', key: 'status', render: (status: string) => ( - + {status === 'active' ? '正常' : '已封禁'} ), @@ -87,19 +88,26 @@ const UserManagement: React.FC = () => { ]; return ( -
-

用户管理

- -
- } - style={{ width: 300 }} - /> -
-
- +
+
+

用户管理

+

管理系统用户与账户状态

+
+ +
+ +
+ } + className="xx-search-input" + style={{ width: 320 }} + /> +
+
+ + ); };