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: ,