blob: 218bc9a9b924624f7b19369fdd78c91cc9c61f86 [file] [log] [blame]
223011339e292152025-06-08 00:34:37 +08001import React, { useState, useEffect } from "react";
whtb1e79592025-06-07 16:03:09 +08002import { useNavigate } from "react-router-dom";
223011339e292152025-06-08 00:34:37 +08003import { API_BASE_URL } from "./config";
wht30587822025-06-09 23:33:09 +08004import "./AdminPage.css";
whtb1e79592025-06-07 16:03:09 +08005
6// 示例数据
7const initialConfig = {
8 FarmNumber: 3,
9 FakeTime: 3,
10 BegVote: 3,
11 CheatTime: 5,
12};
13
whtb1e79592025-06-07 16:03:09 +080014export default function AdminPage() {
15 const navigate = useNavigate();
16 const [config, setConfig] = useState(initialConfig);
223011339e292152025-06-08 00:34:37 +080017 // state for users fetched from backend
18 const [cheatUsers, setCheatUsers] = useState([]);
19 const [suspiciousUsers, setSuspiciousUsers] = useState([]);
20
21 // helper to get admin userId from cookie
22 const getUserIdFromCookie = () => {
23 const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
24 return match ? match[2] : null;
25 };
26
27 // fetch cheat users list from backend
28 const fetchCheatUsers = async () => {
29 const adminId = getUserIdFromCookie();
30 if (!adminId) return;
31 try {
32 const res = await fetch(`${API_BASE_URL}/api/admin/cheat-users?userid=${adminId}`);
33 if (!res.ok) throw new Error('获取作弊用户失败');
34 const data = await res.json();
35 setCheatUsers(data);
36 } catch (err) {
37 console.error(err);
38 }
39 };
40
41 // fetch suspicious users list from backend
42 const fetchSuspiciousUsers = async () => {
43 const adminId = getUserIdFromCookie();
44 if (!adminId) return;
45 try {
46 const res = await fetch(`${API_BASE_URL}/api/admin/suspicious-users?userid=${adminId}`);
47 if (!res.ok) throw new Error('获取可疑用户失败');
48 const data = await res.json();
49 setSuspiciousUsers(data);
50 } catch (err) {
51 console.error(err);
52 }
53 };
whtb1e79592025-06-07 16:03:09 +080054
whtb1e79592025-06-07 16:03:09 +080055 const handleBan = (user) => {
223011339e292152025-06-08 00:34:37 +080056 const adminId = getUserIdFromCookie();
57 if (!adminId) {
58 alert('无法获取用户ID');
59 return;
60 }
61 fetch(`${API_BASE_URL}/api/admin/ban-user`, {
62 method: 'POST',
63 headers: { 'Content-Type': 'application/json' },
64 body: JSON.stringify({ userid: user.userid }),
65 })
66 .then((res) => { if (!res.ok) throw new Error('Network response was not ok'); return res.json(); })
67 .then(() => {
68 // 重新获取用户列表,触发页面重新渲染
69 fetchSuspiciousUsers();
70 fetchCheatUsers();
71 })
72 .catch((err) => console.error('封禁用户失败:', err));
73 }
74
75 // 解封作弊用户
76 const handleUnban = (user) => {
77 const adminId = getUserIdFromCookie();
78 if (!adminId) {
79 alert('无法获取用户ID');
80 return;
81 }
82 fetch(`${API_BASE_URL}/api/admin/unban-user`, {
83 method: 'POST',
84 headers: { 'Content-Type': 'application/json' },
85 body: JSON.stringify({ userid: user.userid }),
86 })
87 .then((res) => { if (!res.ok) throw new Error('Network response was not ok'); return res.json(); })
88 .then(() => {
89 // 重新获取用户列表,触发页面重新渲染
90 fetchCheatUsers();
91 fetchSuspiciousUsers();
92 })
93 .catch((err) => console.error('解封用户失败:', err));
whtb1e79592025-06-07 16:03:09 +080094 };
95
223011339e292152025-06-08 00:34:37 +080096 // 初始化时向后端请求系统参数及用户列表
97 useEffect(() => {
98 const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
99 const userId = match ? match[2] : null;
100 // console.log("User ID from cookie:", userId);
101 if (userId) {
102 // fetch config
103 fetch(`${API_BASE_URL}/api/admin/config?userid=${userId}`)
104 .then((res) => {
105 if (!res.ok) throw new Error('Network response was not ok');
106 return res.json();
107 })
108 .then((data) => {
109 // console.log("Fetched system config:", data);
110 setConfig(data);
111 })
112 .catch((err) => console.error('获取系统参数失败:', err));
113
114 // 初始获取用户列表
115 fetchCheatUsers();
116 fetchSuspiciousUsers();
117 }
118 }, []);
119
whtb1e79592025-06-07 16:03:09 +0800120 return (
wht30587822025-06-09 23:33:09 +0800121 <div className="admin-page-container">
122 <div className="admin-main-content">
123 <h1 className="admin-title">管理员页面</h1>
124 {/* 参数设置 */}
125 <div className="admin-config-card">
126 <span className="admin-config-label">系统参数:</span>
127 <span className="admin-config-item">FarmNumber: {config.FarmNumber}</span>
128 <span className="admin-config-item">FakeTime: {config.FakeTime}</span>
129 <span className="admin-config-item">BegVote: {config.BegVote}</span>
130 <span className="admin-config-item">CheatTime: {config.CheatTime}</span>
131 </div>
132 {/* 作弊用户 */}
133 <div className="admin-section">
134 <h2 className="admin-section-title cheat">作弊用户</h2>
135 <div className="admin-table-container">
136 <table className="admin-table">
137 <thead>
138 <tr>
139 <th>邮箱</th>
140 <th>用户名</th>
141 <th>账户状态</th>
142 <th>操作</th>
143 </tr>
144 </thead>
145 <tbody>
146 {cheatUsers.map((u) => (
147 <tr key={u.userid}>
148 <td>{u.email}</td>
149 <td>{u.username}</td>
150 <td className="status-banned">
151 封禁
152 </td>
153 <td>
154 <button
155 className="admin-btn admin-btn-unban"
156 onClick={() => handleUnban(u)}
157 >
158 解封
159 </button>
160 </td>
161 </tr>
162 ))}
163 </tbody>
164 </table>
165 </div>
166 </div>
167 {/* 可疑用户 */}
168 <div className="admin-section">
169 <h2 className="admin-section-title suspicious">可疑用户</h2>
170 <div className="admin-table-container">
171 <table className="admin-table">
172 <thead>
173 <tr>
174 <th>邮箱</th>
175 <th>用户名</th>
176 <th>账户状态</th>
177 <th>操作</th>
178 </tr>
179 </thead>
180 <tbody>
181 {suspiciousUsers.map((u) => (
182 <tr key={u.user_id}>
183 <td>{u.email}</td>
184 <td>{u.username}</td>
185 <td className={u.account_status === 1 ? "status-banned" : "status-normal"}>
186 {u.account_status === 1 ? "封禁" : "正常"}
187 </td>
188 <td>
189 <button
190 className="admin-btn admin-btn-ban"
191 onClick={() => handleBan(u)}
192 >
193 封禁
194 </button>
195 </td>
196 </tr>
197 ))}
198 </tbody>
199 </table>
200 </div>
201 </div>
202 {/* 跳转按钮 */}
203 <div className="admin-nav-buttons">
204 <button
205 className="admin-nav-btn appeal"
206 onClick={() => navigate("/appeal-review")}
207 >
208 用户申诉
209 </button>
210 <button
211 className="admin-nav-btn migration"
212 onClick={() => navigate("/migration-review")}
213 >
214 用户迁移
215 </button>
216 <button
217 className="admin-nav-btn promotion"
218 onClick={() => navigate("/seed-promotion")}
219 >
220 促销管理
221 </button>
222 </div>
whtb1e79592025-06-07 16:03:09 +0800223 </div>
224 </div>
225 );
226}