From 00085874c9c1c132d9a7f591a4123346bb6b20ef Mon Sep 17 00:00:00 2001
From: BenjaminNH <1249376374@qq.com>
Date: Wed, 2 Jul 2025 17:06:52 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E5=91=98=E7=94=A8=E6=88=B7=E7=AE=A1=E7=90=86=E9=A1=B5=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/config/menuConfig.js | 9 +-
src/pages/admin/UserDetailModal.jsx | 132 ++++++++++++++++++
src/pages/admin/UserManage.jsx | 147 ++++++++++++++++++++
src/pages/deviceAdmin/DeviceDetailModal.jsx | 1 -
src/pages/deviceAdmin/DeviceManage.jsx | 31 +++--
src/pages/shared/UserDetail.jsx | 3 +-
src/router/index.jsx | 11 ++
7 files changed, 322 insertions(+), 12 deletions(-)
create mode 100644 src/pages/admin/UserDetailModal.jsx
create mode 100644 src/pages/admin/UserManage.jsx
diff --git a/src/config/menuConfig.js b/src/config/menuConfig.js
index 70e6eb7..8328944 100644
--- a/src/config/menuConfig.js
+++ b/src/config/menuConfig.js
@@ -3,6 +3,7 @@ import {
ExperimentOutlined,
FileDoneOutlined,
UnorderedListOutlined,
+ UsergroupAddOutlined,
UserOutlined,
} from "@ant-design/icons";
@@ -38,11 +39,17 @@ const menuConfig = [
icon: ExperimentOutlined,
roles: ["DEVICE_ADMIN"],
},
+ {
+ path: "/admin/user-manage",
+ label: "用户管理",
+ icon: UsergroupAddOutlined,
+ roles: ["ADMIN"],
+ },
{
path: "/userdetail",
label: "个人信息",
icon: UserOutlined,
- roles: ["USER", "LEADER", "DEVICE_ADMIN", "ADMIN"],
+ roles: ["USER", "LEADER", "DEVICE_ADMIN"],
},
];
diff --git a/src/pages/admin/UserDetailModal.jsx b/src/pages/admin/UserDetailModal.jsx
new file mode 100644
index 0000000..18ea8b8
--- /dev/null
+++ b/src/pages/admin/UserDetailModal.jsx
@@ -0,0 +1,132 @@
+import { Form, Input, message, Modal, Select } from "antd";
+import { useEffect, useState } from "react";
+import axiosInstance from "../../api/axios";
+import Password from "antd/es/input/Password";
+
+export default function UserDetailModal({
+ visiable,
+ mode = "create",
+ user,
+ onclose,
+ onSuccess,
+}) {
+ const [form] = Form.useForm();
+ const [initialValues, setInitialValues] = useState();
+ const [teams, setTeams] = useState([]);
+ const [roles, setRoles] = useState([]);
+
+ const fetchTeams = async () => {
+ const data = await axiosInstance.get("/teams");
+ setTeams(data);
+ };
+
+ const fetchRoles = async () => {
+ const data = await axiosInstance.get("/role");
+ setRoles(data);
+ };
+
+ useEffect(() => {
+ fetchTeams();
+ fetchRoles();
+ }, []);
+
+ useEffect(() => {
+ if (visiable) {
+ if (mode === "edit") {
+ const values = {
+ username: user.username,
+ name: user.name,
+ phone: user.phone,
+ teamId: user.teamId,
+ roleId: user.roleId,
+ };
+
+ setInitialValues(values);
+ form.setFieldsValue(values);
+ } else {
+ const values = {
+ username: undefined,
+ password: undefined,
+ name: undefined,
+ phone: undefined,
+ teamId: undefined,
+ roleId: undefined,
+ };
+ setInitialValues(values);
+ form.setFieldsValue(values);
+ }
+ }
+ }, [visiable, mode, user, form]);
+
+ const handleOk = async () => {
+ const values = await form.validateFields();
+ const data = {};
+ Object.keys(initialValues).forEach((key) => {
+ if (values[key] !== initialValues[key]) {
+ data[key] = values[key];
+ }
+ });
+
+ if (Object.keys(data).length > 0) {
+ if (mode === "edit") {
+ await axiosInstance.put(`/user/${user.userId}`, data);
+ message.success("编辑成功");
+ } else {
+ await axiosInstance.post(`/user`, data);
+ message.success("添加成功");
+ }
+ }
+ onSuccess();
+ onclose();
+ };
+ return (
+ {
+ onclose();
+ }}
+ onOk={handleOk}
+ okText="保存"
+ >
+
+
+
+ {mode === "create" && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/admin/UserManage.jsx b/src/pages/admin/UserManage.jsx
new file mode 100644
index 0000000..4f85b3d
--- /dev/null
+++ b/src/pages/admin/UserManage.jsx
@@ -0,0 +1,147 @@
+import { Button, Flex, Input, Popconfirm, Space, Table } from "antd";
+import Column from "antd/es/table/Column";
+import { useEffect, useState } from "react";
+import axiosInstance from "../../api/axios";
+import DeviceDetailModal from "../deviceAdmin/DeviceDetailModal";
+import UserDetailModal from "./UserDetailModal";
+
+export default function UserManage() {
+ const [users, setUsers] = useState([]);
+ const [teams, setTeams] = useState([]);
+ const [modalMode, setModalMode] = useState();
+ const [selectedUser, setSelectedUser] = useState();
+ const [modalOpen, setModalOpen] = useState(false);
+ const [pagination, setPagination] = useState({
+ current: 1,
+ pageSize: 10,
+ total: 0,
+ });
+
+ const fetchData = async (pagination, name) => {
+ const data = await axiosInstance.get("/user", {
+ params: {
+ page: pagination.current,
+ size: pagination.pageSize,
+ name: name,
+ },
+ });
+ setUsers(data.records);
+ setPagination({
+ ...pagination,
+ total: data.total,
+ });
+ };
+
+ const fetchTeams = async () => {
+ const data = await axiosInstance.get("/teams");
+ setTeams(data);
+ };
+
+ useEffect(() => {
+ // fetchTeams();
+ fetchData({
+ current: 1,
+ pageSize: 10,
+ });
+ }, []);
+
+ const handlePageChange = async (pagination) => {
+ await fetchData(pagination);
+ };
+
+ const handleSearch = async (value) => {
+ await fetchData(
+ {
+ ...pagination,
+ current: 1,
+ },
+ value
+ );
+ };
+
+ const handleDelete = async (record) => {
+ await axiosInstance.delete(`/user/${record.userId}`);
+ fetchData({
+ current: 1,
+ pageSize: 10,
+ });
+ };
+ // 姓名、账号、联系电话、所属团队、操作
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {
+ return (
+
+
+ handleDelete(record)}
+ >
+
+
+
+ );
+ }}
+ />
+
+ {
+ setModalOpen(false);
+ setSelectedUser(null);
+ }}
+ onSuccess={async () => {
+ await fetchData({
+ ...pagination,
+ current: 1,
+ });
+ }}
+ />
+ >
+ );
+}
diff --git a/src/pages/deviceAdmin/DeviceDetailModal.jsx b/src/pages/deviceAdmin/DeviceDetailModal.jsx
index 6472288..0289ecc 100644
--- a/src/pages/deviceAdmin/DeviceDetailModal.jsx
+++ b/src/pages/deviceAdmin/DeviceDetailModal.jsx
@@ -68,7 +68,6 @@ export default function DeviceDetailModal({
message.success("编辑成功");
} else {
device = await axiosInstance.post(`/device/${userId}`, data);
- console.log(device);
message.success("添加成功");
}
diff --git a/src/pages/deviceAdmin/DeviceManage.jsx b/src/pages/deviceAdmin/DeviceManage.jsx
index c686581..ba44d3d 100644
--- a/src/pages/deviceAdmin/DeviceManage.jsx
+++ b/src/pages/deviceAdmin/DeviceManage.jsx
@@ -1,4 +1,13 @@
-import { Button, Flex, Input, message, Space, Table, Tag } from "antd";
+import {
+ Button,
+ Flex,
+ Input,
+ message,
+ Popconfirm,
+ Space,
+ Table,
+ Tag,
+} from "antd";
import Column from "antd/es/table/Column";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
@@ -132,14 +141,15 @@ export default function DeviceManage() {
>
编辑
-
+
+
);
}}
@@ -154,7 +164,10 @@ export default function DeviceManage() {
setSelectedDevice(null);
}}
onSuccess={async () => {
- await fetchData(pagination);
+ await fetchData({
+ ...pagination,
+ current: 1,
+ });
}}
/>
>
diff --git a/src/pages/shared/UserDetail.jsx b/src/pages/shared/UserDetail.jsx
index a1ba4bc..0e7aab9 100644
--- a/src/pages/shared/UserDetail.jsx
+++ b/src/pages/shared/UserDetail.jsx
@@ -9,6 +9,7 @@ export default function UserDetail() {
const [form] = Form.useForm();
const [showPassword, setShowPassword] = useState(false);
const [user, setUser] = useState({
+ userId: "",
username: "",
team: "",
name: "",
@@ -43,7 +44,7 @@ export default function UserDetail() {
}
delete changedFields.confirmPassword;
- const newUser = await axiosInstance.patch(`/user/${userId}`, changedFields);
+ const newUser = await axiosInstance.put(`/user/${userId}`, changedFields);
setUser(newUser);
form.setFieldsValue(newUser);
message.success("修改成功");
diff --git a/src/router/index.jsx b/src/router/index.jsx
index 5415b36..68fe1bc 100644
--- a/src/router/index.jsx
+++ b/src/router/index.jsx
@@ -8,6 +8,7 @@ import MyReservation from "../pages/user/MyReservation";
import Reserve from "../pages/user/Reserve";
import ProtectedRoute from "./ProtectedRoute";
import DeviceManage from "../pages/deviceAdmin/DeviceManage";
+import UserManage from "../pages/admin/UserManage";
const router = createBrowserRouter([
{
@@ -59,6 +60,16 @@ const router = createBrowserRouter([
},
],
},
+ {
+ path: "admin",
+ element: ,
+ children: [
+ {
+ path: "user-manage",
+ element: ,
+ },
+ ],
+ },
{
path: "userdetail",
element: ,