合并JWL,WZY,TRM代码
Change-Id: Ifb4fcad3c06733e1e005e7d8d9403e3561010fb4
diff --git a/TRM/front/src/api/posts.js b/TRM/front/src/api/posts.js
index a42e781..012cd00 100644
--- a/TRM/front/src/api/posts.js
+++ b/TRM/front/src/api/posts.js
@@ -13,7 +13,16 @@
body: JSON.stringify({ userid: userId })
})
if (!res.ok) throw new Error(`fetchPosts: ${res.status}`)
- return res.json()
+
+ const json = await res.json()
+ console.log('fetchPosts response:', json) // debug: inspect shape
+
+ // normalize: if it's already an array use it; else pull array out of known keys
+ const list = Array.isArray(json)
+ ? json
+ : json.data || json.posts || []
+
+ return list
}
/**
@@ -59,4 +68,50 @@
})
if (!res.ok) throw new Error(`fetchPost: ${res.status}`)
return res.json()
+}
+
+/**
+ * 获取超级管理员用户列表
+ * POST /sgetuserlist
+ * @param {number|string} userId 平台管理员的用户 ID
+ * @returns Promise<[ {id, name, role}, … ]>
+ */
+export async function fetchUserList(userId) {
+ const res = await fetch(`${BASE}/sgetuserlist`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ userid: userId })
+ })
+ if (!res.ok) throw new Error(`fetchUserList: ${res.status}`)
+ return res.json()
+}
+
+export async function giveAdmin(userId, targetId) {
+ const res = await fetch(`${BASE}/sgiveadmin`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ userid: userId, targetid: targetId })
+ })
+ if (!res.ok) throw new Error(`giveAdmin: ${res.status}`)
+ return res.json()
+}
+
+export async function giveSuperAdmin(userId, targetId) {
+ const res = await fetch(`${BASE}/sgivesuperadmin`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ userid: userId, targetid: targetId })
+ })
+ if (!res.ok) throw new Error(`giveSuperAdmin: ${res.status}`)
+ return res.json()
+}
+
+export async function giveUser(userId, targetId) {
+ const res = await fetch(`${BASE}/sgiveuser`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ userid: userId, targetid: targetId })
+ })
+ if (!res.ok) throw new Error(`giveUser: ${res.status}`)
+ return res.json()
}
\ No newline at end of file
diff --git a/TRM/front/src/components/Admin.js b/TRM/front/src/components/Admin.js
index 75253b8..6d278d5 100644
--- a/TRM/front/src/components/Admin.js
+++ b/TRM/front/src/components/Admin.js
@@ -2,7 +2,7 @@
import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { Layout, Tabs, Input, List, Card, Button, Tag, Spin, Typography, Divider } from 'antd';
import '../style/Admin.css';
-import { fetchPosts, approvePost, rejectPost } from '../api/posts';
+import { fetchPosts, approvePost, rejectPost } from '../../../../Merge/front/src/api/posts';
export default function Admin() {
const ADMIN_USER_ID = 3;
diff --git a/TRM/front/src/components/SuperAdmin.js b/TRM/front/src/components/SuperAdmin.js
index 118ab56..169441e 100644
--- a/TRM/front/src/components/SuperAdmin.js
+++ b/TRM/front/src/components/SuperAdmin.js
@@ -1,8 +1,10 @@
import React from 'react';
import { NavLink, Outlet } from 'react-router-dom';
-import '../style/SuperAdmin.css'; // 可选:自定义样式
+import '../style/SuperAdmin.css';
export default function SuperAdmin() {
+ const SUPERADMIN_USER_ID = 3;
+
return (
<div className="super-admin-container">
<aside className="super-admin-sidebar">
diff --git a/TRM/front/src/components/UserManagement.js b/TRM/front/src/components/UserManagement.js
index 400884b..4bd05c5 100644
--- a/TRM/front/src/components/UserManagement.js
+++ b/TRM/front/src/components/UserManagement.js
@@ -1,42 +1,74 @@
import React, { useState, useEffect } from 'react';
import '../style/Admin.css';
+import { Select, message, Table } from 'antd';
+import { fetchUserList, giveUser, giveAdmin, giveSuperAdmin } from '../api/posts';
-function UserManagement() {
+const { Option } = Select;
+const ROLE_LIST = ['用户', '管理员', '超级管理员'];
+
+function UserManagement({ superAdminId }) {
const [users, setUsers] = useState([]);
useEffect(() => {
- fetch('/api/users')
- .then(res => res.json())
- .then(data => setUsers(data))
- .catch(console.error);
- }, []);
+ async function load() {
+ try {
+ const data = superAdminId
+ ? await fetchUserList(superAdminId)
+ : await fetch('/api/users').then(res => res.json());
+ setUsers(data);
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ load();
+ }, [superAdminId]);
- const handleUserAction = (id, action) => {
- fetch(`/api/users/${id}/${action}`, { method: 'POST' })
- .then(res => res.ok && setUsers(us => us.filter(u => u.id !== id)))
- .catch(console.error);
+ // handle role changes
+ const handleRoleChange = async (userId, newRole) => {
+ try {
+ if (newRole === '用户') await giveUser(superAdminId, userId);
+ else if (newRole === '管理员') await giveAdmin(superAdminId, userId);
+ else if (newRole === '超级管理员') await giveSuperAdmin(superAdminId, userId);
+ setUsers(us => us.map(u => u.id === userId ? { ...u, role: newRole } : u));
+ message.success('修改成功');
+ } catch (e) {
+ console.error(e);
+ message.error('修改失败');
+ }
};
+ // define table columns
+ const columns = [
+ { title: '用户名', dataIndex: 'username', key: 'username' },
+ { title: '角色', dataIndex: 'role', key: 'role' },
+ {
+ title: '操作',
+ key: 'action',
+ render: (_, record) => {
+ const orderedRoles = [record.role, ...ROLE_LIST.filter(r => r !== record.role)];
+ return (
+ <Select
+ value={record.role}
+ style={{ width: 120 }}
+ onChange={value => handleRoleChange(record.id, value)}
+ >
+ {orderedRoles.map(r => (
+ <Option key={r} value={r}>{r}</Option>
+ ))}
+ </Select>
+ );
+ },
+ },
+ ];
+
return (
<div className="admin-container">
- <h2>用户管理</h2>
- <table className="admin-table">
- <thead>
- <tr><th>用户名</th><th>角色</th><th>操作</th></tr>
- </thead>
- <tbody>
- {users.map(u => (
- <tr key={u.id}>
- <td>{u.username}</td>
- <td>{u.role}</td>
- <td>
- <button onClick={() => handleUserAction(u.id, 'ban')}>封禁</button>
- <button onClick={() => handleUserAction(u.id, 'promote')}>提升权限</button>
- </td>
- </tr>
- ))}
- </tbody>
- </table>
+ <Table
+ dataSource={users}
+ columns={columns}
+ rowKey="id"
+ pagination={false}
+ />
</div>
);
}
diff --git a/TRM/front/src/router/App.js b/TRM/front/src/router/App.js
index b9f9ac1..fd10142 100644
--- a/TRM/front/src/router/App.js
+++ b/TRM/front/src/router/App.js
@@ -20,7 +20,7 @@
{/* 超级管理员,只用 SuperAdminLayout */}
<Route path="superadmin" element={<SuperAdmin />}>
<Route index element={<Navigate to="users" replace />} />
- <Route path="users" element={<UserManagement />} />
+ <Route path="users" element={<UserManagement superAdminId={3} />} />
<Route path="dashboard" element={<LogsDashboard />} />
</Route>
</Routes>
diff --git a/TRM/front/src/style/Admin.css b/TRM/front/src/style/Admin.css
index e5dff20..4a5bcb7 100644
--- a/TRM/front/src/style/Admin.css
+++ b/TRM/front/src/style/Admin.css
@@ -369,4 +369,21 @@
.search-input:focus {
outline: none;
border-color: #e61515;
+}
+
+/* 小红书品牌红 */
+:root {
+ --xiaohongshu-red: #e2204f;
+}
+
+/* Antd 表格表头背景小红书红,文字白色 */
+.ant-table-thead > tr > th {
+ background-color: var(--xiaohongshu-red) !important;
+ color: #fff;
+}
+
+/* 侧栏前两项文字变小红书红 */
+.ant-layout-sider .ant-menu-item:nth-child(1),
+.ant-layout-sider .ant-menu-item:nth-child(2) {
+ color: var(--xiaohongshu-red) !important;
}
\ No newline at end of file