新增后台接口
Change-Id: Ibd8183079a77aad05b2c81658c2d6fe9b648e042
diff --git a/front/src/AdminPage.js b/front/src/AdminPage.js
index 4862449..dac05cb 100644
--- a/front/src/AdminPage.js
+++ b/front/src/AdminPage.js
@@ -1,5 +1,6 @@
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
+import { API_BASE_URL } from "./config";
// 示例数据
const initialConfig = {
@@ -9,19 +10,46 @@
CheatTime: 5,
};
-const cheatUsers = [
- { user_id: "u001", email: "cheat1@example.com", username: "cheater1", account_status: 1 },
- { user_id: "u002", email: "cheat2@example.com", username: "cheater2", account_status: 0 },
-];
-
-const suspiciousUsers = [
- { user_id: "u101", email: "suspect1@example.com", username: "suspect1", account_status: 0 },
- { user_id: "u102", email: "suspect2@example.com", username: "suspect2", account_status: 0 },
-];
-
export default function AdminPage() {
const navigate = useNavigate();
const [config, setConfig] = useState(initialConfig);
+ // state for users fetched from backend
+ const [cheatUsers, setCheatUsers] = useState([]);
+ const [suspiciousUsers, setSuspiciousUsers] = useState([]);
+
+ // helper to get admin userId from cookie
+ const getUserIdFromCookie = () => {
+ const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
+ return match ? match[2] : null;
+ };
+
+ // fetch cheat users list from backend
+ const fetchCheatUsers = async () => {
+ const adminId = getUserIdFromCookie();
+ if (!adminId) return;
+ try {
+ const res = await fetch(`${API_BASE_URL}/api/admin/cheat-users?userid=${adminId}`);
+ if (!res.ok) throw new Error('获取作弊用户失败');
+ const data = await res.json();
+ setCheatUsers(data);
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
+ // fetch suspicious users list from backend
+ const fetchSuspiciousUsers = async () => {
+ const adminId = getUserIdFromCookie();
+ if (!adminId) return;
+ try {
+ const res = await fetch(`${API_BASE_URL}/api/admin/suspicious-users?userid=${adminId}`);
+ if (!res.ok) throw new Error('获取可疑用户失败');
+ const data = await res.json();
+ setSuspiciousUsers(data);
+ } catch (err) {
+ console.error(err);
+ }
+ };
const handleConfigChange = (e) => {
const { name, value } = e.target;
@@ -29,31 +57,129 @@
};
const handleBan = (user) => {
- alert(`已封禁用户:${user.username}`);
+ const adminId = getUserIdFromCookie();
+ if (!adminId) {
+ alert('无法获取用户ID');
+ return;
+ }
+ fetch(`${API_BASE_URL}/api/admin/ban-user`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ userid: user.userid }),
+ })
+ .then((res) => { if (!res.ok) throw new Error('Network response was not ok'); return res.json(); })
+ .then(() => {
+ // 重新获取用户列表,触发页面重新渲染
+ fetchSuspiciousUsers();
+ fetchCheatUsers();
+ })
+ .catch((err) => console.error('封禁用户失败:', err));
+ }
+
+ // 解封作弊用户
+ const handleUnban = (user) => {
+ const adminId = getUserIdFromCookie();
+ if (!adminId) {
+ alert('无法获取用户ID');
+ return;
+ }
+ fetch(`${API_BASE_URL}/api/admin/unban-user`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ userid: user.userid }),
+ })
+ .then((res) => { if (!res.ok) throw new Error('Network response was not ok'); return res.json(); })
+ .then(() => {
+ // 重新获取用户列表,触发页面重新渲染
+ fetchCheatUsers();
+ fetchSuspiciousUsers();
+ })
+ .catch((err) => console.error('解封用户失败:', err));
};
+ // 保存系统参数到后端
+ const handleSave = () => {
+ const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
+ const userId = match ? match[2] : null;
+ if (!userId) {
+ alert('无法获取用户ID');
+ return;
+ }
+ fetch(`${API_BASE_URL}/api/save-config`, {
+ method: 'POST',
+ // credentials: 'include',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ userid: userId, ...config }),
+ })
+ .then((res) => {
+ if (!res.ok) throw new Error('Network response was not ok');
+ return res.json();
+ })
+ .then(() => alert('系统参数已保存'))
+ .catch((err) => console.error('保存系统参数失败:', err));
+ };
+
+ // 初始化时向后端请求系统参数及用户列表
+ useEffect(() => {
+ const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
+ const userId = match ? match[2] : null;
+ // console.log("User ID from cookie:", userId);
+ if (userId) {
+ // fetch config
+ fetch(`${API_BASE_URL}/api/admin/config?userid=${userId}`)
+ .then((res) => {
+ if (!res.ok) throw new Error('Network response was not ok');
+ return res.json();
+ })
+ .then((data) => {
+ // console.log("Fetched system config:", data);
+ setConfig(data);
+ })
+ .catch((err) => console.error('获取系统参数失败:', err));
+
+ // 初始获取用户列表
+ fetchCheatUsers();
+ fetchSuspiciousUsers();
+ }
+ }, []);
+
return (
<div style={{ padding: 40, maxWidth: 900, margin: "0 auto" }}>
<h1 style={{ textAlign: "center", marginBottom: 32 }}>管理员页面</h1>
{/* 参数设置 */}
- <div style={{ marginBottom: 32, padding: 18, background: "#f7faff", borderRadius: 12, display: "flex", gap: 24, alignItems: "center" }}>
+ <div style={{ marginBottom: 32, padding: 18, background: "#f7faff", borderRadius: 12, display: "flex", gap: 24, alignItems: "center", justifyContent: "space-between" }}>
<b>系统参数:</b>
<label>
FarmNumber:
- <input type="number" name="FarmNumber" value={config.FarmNumber} onChange={handleConfigChange} style={{ width: 60, margin: "0 12px" }} />
+ <input type="number" name="FarmNumber" value={config.FarmNumber} onChange={handleConfigChange} disabled style={{ width: 60, margin: "0 12px" }} />
</label>
<label>
FakeTime:
- <input type="number" name="FakeTime" value={config.FakeTime} onChange={handleConfigChange} style={{ width: 60, margin: "0 12px" }} />
+ <input type="number" name="FakeTime" value={config.FakeTime} onChange={handleConfigChange} disabled style={{ width: 60, margin: "0 12px" }} />
</label>
<label>
BegVote:
- <input type="number" name="BegVote" value={config.BegVote} onChange={handleConfigChange} style={{ width: 60, margin: "0 12px" }} />
+ <input type="number" name="BegVote" value={config.BegVote} onChange={handleConfigChange} disabled style={{ width: 60, margin: "0 12px" }} />
</label>
<label>
CheatTime:
- <input type="number" name="CheatTime" value={config.CheatTime} onChange={handleConfigChange} style={{ width: 60, margin: "0 12px" }} />
+ <input type="number" name="CheatTime" value={config.CheatTime} onChange={handleConfigChange} disabled style={{ width: 60, margin: "0 12px" }} />
</label>
+ {/* <button
+ onClick={handleSave}
+ style={{
+ background: '#1976d2',
+ color: '#fff',
+ border: 'none',
+ borderRadius: 6,
+ padding: '6px 18px',
+ cursor: 'pointer',
+ writingMode: 'horizontal-tb',
+ whiteSpace: 'nowrap'
+ }}
+ >
+ 保存
+ </button> */}
</div>
{/* 作弊用户 */}
<div style={{ marginBottom: 32 }}>
@@ -61,7 +187,7 @@
<table style={{ width: "100%", background: "#fff", borderRadius: 10, boxShadow: "0 2px 8px #e0e7ff", marginBottom: 18 }}>
<thead>
<tr style={{ background: "#f5f5f5" }}>
- <th>user_id</th>
+ {/* <th>user_id</th> */}
<th>email</th>
<th>username</th>
<th>account_status</th>
@@ -70,19 +196,19 @@
</thead>
<tbody>
{cheatUsers.map((u) => (
- <tr key={u.user_id}>
- <td>{u.user_id}</td>
+ <tr key={u.userid}>
+ {/* <td>{u.userid}</td> */}
<td>{u.email}</td>
<td>{u.username}</td>
- <td style={{ color: u.account_status === 1 ? "#e53935" : "#43a047" }}>
- {u.account_status === 1 ? "封禁" : "正常"}
+ <td style={{ color: "#e53935" }}>
+ {"封禁" }
</td>
<td>
<button
- style={{ background: "#e53935", color: "#fff", border: "none", borderRadius: 6, padding: "4px 14px", cursor: "pointer" }}
- onClick={() => handleBan(u)}
+ style={{ background: "#13F31E", color: "#fff", border: "none", borderRadius: 6, padding: "4px 14px", cursor: "pointer" }}
+ onClick={() => handleUnban(u)}
>
- 封禁
+ 解封
</button>
</td>
</tr>
@@ -96,7 +222,7 @@
<table style={{ width: "100%", background: "#fff", borderRadius: 10, boxShadow: "0 2px 8px #e0e7ff" }}>
<thead>
<tr style={{ background: "#f5f5f5" }}>
- <th>user_id</th>
+ {/* <th>user_id</th> */}
<th>email</th>
<th>username</th>
<th>account_status</th>
@@ -106,7 +232,7 @@
<tbody>
{suspiciousUsers.map((u) => (
<tr key={u.user_id}>
- <td>{u.user_id}</td>
+ {/* <td>{u.user_id}</td> */}
<td>{u.email}</td>
<td>{u.username}</td>
<td style={{ color: u.account_status === 1 ? "#e53935" : "#43a047" }}>