diff --git a/src/App.css b/src/App.css index 7770020..25dcdd4 100644 --- a/src/App.css +++ b/src/App.css @@ -34,7 +34,7 @@ --bg-secondary: #ffffff; --panel: #ffffff; --panel-solid: #ffffff; - --soft: #f1f3f7; + --soft: #f8f9fc; --text: #171a1f; --text-secondary: #4d5562; --muted: #6b7280; @@ -51,8 +51,9 @@ --bad: #b6404a; --border: #e5e7ef; --border-subtle: #f0f1f5; - --shadow: 0 10px 25px rgba(10,16,25,.08); - --shadow-lg: 0 20px 40px rgba(10,16,25,.12); + --shadow: 0 2px 8px rgba(10,16,25,.04); + --shadow-md: 0 4px 12px rgba(10,16,25,.06); + --shadow-lg: 0 8px 20px rgba(10,16,25,.08); --shadow-colored: 0 10px 30px rgba(102, 126, 234, 0.15); --glow: 0 0 20px rgba(102, 126, 234, 0.2); } @@ -233,14 +234,67 @@ a{color:inherit; text-decoration:none} background:var(--panel); color:var(--text); box-shadow:var(--shadow); } -.content{padding:28px 24px; display:flex; flex-direction:column; gap:20px; flex:1; overflow-y:auto; min-height:0; box-sizing:border-box} +.content{ + padding:32px 28px; + display:flex; + flex-direction:column; + gap:24px; + flex:1; + overflow-y:auto; + min-height:0; + box-sizing:border-box; + max-width: 1600px; + margin: 0 auto; + width: 100%; +} + +/* 页面标题样式 */ +.page-header { + margin-bottom: 8px; +} + +.page-header h1 { + font-size: 24px; + font-weight: 700; + color: var(--text); + margin: 0 0 8px 0; + letter-spacing: -0.02em; +} + +.page-header .page-description { + font-size: 14px; + color: var(--text-secondary); + margin: 0; + line-height: 1.5; +} .panel{ - background:var(--panel); border:1px solid var(--border); border-radius:16px; padding:18px; box-shadow:var(--shadow); + background:var(--panel); + border:1px solid var(--border); + border-radius:12px; + padding:20px 24px; + box-shadow:var(--shadow); width:100%; + transition: box-shadow 0.2s ease; +} + +.panel:hover { + box-shadow: var(--shadow-md); +} + +.panel h2{ + margin:0 0 12px 0; + font-size:16px; + font-weight:600; + color:var(--text); +} + +.panel .desc{ + color:var(--text-secondary); + font-size:13px; + margin-bottom:16px; + line-height: 1.5; } -.panel h2{margin:0 0 8px 0; font-size:16px} -.panel .desc{color:var(--muted); font-size:13px; margin-bottom:10px} .flex-2{display:grid; grid-template-columns: 1fr 1fr; gap:16px} .flex-3{display:grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap:16px} @@ -251,7 +305,7 @@ a{color:inherit; text-decoration:none} background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0.7) 100%); border:1px solid rgba(102, 126, 234, 0.1); border-radius:16px; - padding:18px; + padding:20px; position: relative; overflow: hidden; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); @@ -280,21 +334,22 @@ a{color:inherit; text-decoration:none} .kpi:nth-child(2)::before { background: var(--success-gradient); } .kpi:nth-child(3)::before { background: var(--warning-gradient); } .kpi:nth-child(4)::before { background: var(--secondary-gradient); } -.kpi h3{margin:0; font-size:13px; color:var(--muted); font-weight: 600; letter-spacing: 0.3px;} +.kpi h3{margin:0; font-size:12px; color:var(--muted); font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase;} .kpi .num{ - font-size:28px; - font-weight:900; - margin-top:8px; + font-size:32px; + font-weight:800; + margin-top:12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; + letter-spacing: -0.02em; } .kpi .delta{font-size:12px; margin-left:8px; padding:2px 6px; border-radius:8px; background:var(--panel); border:1px solid var(--border)} .table{width:100%; border-collapse:collapse; font-size:14px; min-width:800px; table-layout:fixed; box-sizing:border-box} -.table th, .table td{padding:10px 12px; border-bottom:1px solid var(--border); text-align:left; white-space:nowrap; overflow:hidden; text-overflow:ellipsis} -.table thead th{color:var(--muted); font-weight:600} +.table th, .table td{padding:12px 16px; border-bottom:1px solid var(--border); text-align:left; white-space:nowrap; overflow:hidden; text-overflow:ellipsis} +.table thead th{color:var(--muted); font-weight:600; font-size:13px; text-transform: uppercase; letter-spacing: 0.5px;} .table-container{overflow-x:auto; width:100%; max-width:100%; -webkit-overflow-scrolling:touch; box-sizing:border-box} .table th:nth-child(1), .table td:nth-child(1){width:8%} .table th:nth-child(2), .table td:nth-child(2){width:15%} diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 5ca7496..91dcc86 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -165,6 +165,9 @@ const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) => { + {/* 间隔区域 - 将登出按钮推到底部 */} +
+ {/* 用户登录状态和登出按钮 */}
= ({ children }) => { )}
- -
- {!collapsed ? 'v1.1 · React Admin' : 'v1.1'} -
{/* 主内容区 */} diff --git a/src/pages/Finance.tsx b/src/pages/Finance.tsx index 0401a7d..3f9bd71 100644 --- a/src/pages/Finance.tsx +++ b/src/pages/Finance.tsx @@ -2,10 +2,12 @@ import React from 'react'; const Finance: React.FC = () => { return ( -
-

财务管理

-
收入统计、成本分析、财务报表
- +
+
+

财务管理

+

收入统计、成本分析、财务报表

+
+

本月收入

@@ -40,7 +42,7 @@ const Finance: React.FC = () => {

财务报表

详细财务报表占位
-
+ ); }; diff --git a/src/pages/FinanceTransactionLogs.tsx b/src/pages/FinanceTransactionLogs.tsx index 3b30937..20eae8e 100644 --- a/src/pages/FinanceTransactionLogs.tsx +++ b/src/pages/FinanceTransactionLogs.tsx @@ -64,7 +64,7 @@ const FinanceTransactionLogs: React.FC = () => { style={{ marginBottom: 20 }} >
- {/* 第一行:用户ID、订单编号、流水类型、状态、时间范围 */} + {/* 第一行:用户ID、订单编号、流水类型 */}
@@ -73,7 +73,7 @@ const FinanceTransactionLogs: React.FC = () => { - { ]} /> -
- - {/* 第二行:时间范围和按钮 */} -
diff --git a/src/pages/InviteCodes.tsx b/src/pages/InviteCodes.tsx index 537826e..174e576 100644 --- a/src/pages/InviteCodes.tsx +++ b/src/pages/InviteCodes.tsx @@ -550,7 +550,7 @@ const InviteCodes: React.FC = () => { ]; return ( -
+
{/* 统计信息 */} {statistics && ( diff --git a/src/pages/Monitoring.tsx b/src/pages/Monitoring.tsx index 82487e4..ab0b64e 100644 --- a/src/pages/Monitoring.tsx +++ b/src/pages/Monitoring.tsx @@ -1,63 +1,21 @@ -import React, { useState, useEffect } from 'react'; -import { QuotaApiService } from '../services/api'; - -interface QuotaHistoryItem { - id: number; - user_id: string; - api_group: string; - project_id: string; - day: string; - account: string; - model: string; - quota_used: number; - quota_used_text?: string; - created_at: string; -} +import React from 'react'; const Monitoring: React.FC = () => { - const [quotaData, setQuotaData] = useState([]); - const [startDate, setStartDate] = useState(''); - const [endDate, setEndDate] = useState(''); - - // 初始化日期范围(最近30天) - useEffect(() => { - const today = new Date(); - const thirtyDaysAgo = new Date(); - thirtyDaysAgo.setDate(today.getDate() - 30); - - setEndDate(today.toISOString().split('T')[0]); - setStartDate(thirtyDaysAgo.toISOString().split('T')[0]); - }, []); - - // 计算统计数据 - const stats = React.useMemo(() => { - if (quotaData.length === 0) { - return { - totalQuota: 0, - totalUsers: 0, - totalProjects: 0, - totalModels: 0, - }; - } - - const totalQuota = quotaData.reduce((sum, item) => sum + item.quota_used, 0); - const uniqueUsers = new Set(quotaData.map(item => item.user_id)).size; - const uniqueProjects = new Set(quotaData.map(item => item.project_id)).size; - const uniqueModels = new Set(quotaData.map(item => item.model)).size; - - return { - totalQuota, - totalUsers: uniqueUsers, - totalProjects: uniqueProjects, - totalModels: uniqueModels, - }; - }, [quotaData]); + // 静态统计数据 + const stats = { + totalQuota: 0, + totalUsers: 0, + totalProjects: 0, + totalModels: 0, + }; return ( -
-

Token 使用概览

-
总使用量、活跃用户、项目数量、模型统计
- +
+
+

Token 使用概览

+

总使用量、活跃用户、项目数量、模型统计

+
+

总 Token 使用量

@@ -76,7 +34,7 @@ const Monitoring: React.FC = () => {
{stats.totalModels}
-
+
); }; diff --git a/src/pages/Operations.tsx b/src/pages/Operations.tsx index 8970abe..8107bae 100644 --- a/src/pages/Operations.tsx +++ b/src/pages/Operations.tsx @@ -5,12 +5,14 @@ import { useNavigate } from 'react-router-dom'; const Operations: React.FC = () => { const navigate = useNavigate(); return ( -
-

运营管理

-
用户运营、内容管理、活动推广
- -
- +
+
+

运营管理

+

用户运营、内容管理、活动推广

+
+ +
+
-
+
); }; diff --git a/src/pages/Overview.tsx b/src/pages/Overview.tsx index f208756..dae7deb 100644 --- a/src/pages/Overview.tsx +++ b/src/pages/Overview.tsx @@ -2,10 +2,12 @@ import React from 'react'; const Overview: React.FC = () => { return ( -
-

系统总览

-
系统整体运行状态、关键指标概览
- +
+
+

系统总览

+

系统整体运行状态、关键指标概览

+
+

总用户数

@@ -21,10 +23,10 @@ const Overview: React.FC = () => {

系统状态

-
正常
+
正常
- +

最近7天用户活跃度

@@ -35,7 +37,7 @@ const Overview: React.FC = () => {
模型使用量排行占位
-
+
); }; diff --git a/src/pages/UserFeedback.tsx b/src/pages/UserFeedback.tsx index 6291c43..827ca81 100644 --- a/src/pages/UserFeedback.tsx +++ b/src/pages/UserFeedback.tsx @@ -305,7 +305,7 @@ const UserFeedback: React.FC = () => { ]; return ( -
+
用户反馈管理 {/* 统计卡片 */} diff --git a/src/pages/UserManagement.tsx b/src/pages/UserManagement.tsx index 01533d1..02727cf 100644 --- a/src/pages/UserManagement.tsx +++ b/src/pages/UserManagement.tsx @@ -378,8 +378,13 @@ const UserManagement: React.FC = () => { return (
+
+

用户管理

+

后台用户账号管理、权限分配、状态控制

+
+ {/* 统计卡片 */} - + { {/* 操作栏 */} -
-

用户管理

- -
+ +
+

用户列表

+ +
+
{/* 用户表格 */} - +
{ fetchUsers(current, size); } }} - /> + /> + {/* 用户表单弹窗 */}