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.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.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 }}
+ />
-
+
-
+
-
+
- } disabled>应用过滤暂未开放
- } disabled>导出日志暂未开放
-
-
+ } disabled className="xx-ghost-btn">
+ 应用过滤暂未开放
+
+ } disabled className="xx-ghost-btn">
+ 导出日志暂未开放
+
+
-
+
{
}}
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()}
- } onClick={refreshMetrics}>刷新
-
+
+
+
+
系统监控
+
服务器资源、服务健康与 API 统计
+
+
+
+ 上次更新: {refreshTime.toLocaleTimeString()}
+ } onClick={refreshMetrics} className="xx-primary-btn">
+ 刷新
+
+
+
{/* 系统资源监控 */}
-
-
-
-
-
-
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 }}
+ />
+
+
+
+
);
};