feat: 实现管理员用户管理页面
This commit is contained in:
parent
c9d0bb88b3
commit
00085874c9
@ -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"],
|
||||
},
|
||||
];
|
||||
|
||||
|
132
src/pages/admin/UserDetailModal.jsx
Normal file
132
src/pages/admin/UserDetailModal.jsx
Normal file
@ -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 (
|
||||
<Modal
|
||||
title={mode === "edit" ? "编辑用户" : "添加用户"}
|
||||
open={visiable}
|
||||
onCancel={() => {
|
||||
onclose();
|
||||
}}
|
||||
onOk={handleOk}
|
||||
okText="保存"
|
||||
>
|
||||
<Form form={form} layout="vertical" initialValues={initialValues}>
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="用户账号"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
{mode === "create" && (
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="初始密码"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input.Password />
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item name="name" label="姓名" rules={[{ required: true }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="phone" label="联系电话">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="teamId"
|
||||
label="所属团队"
|
||||
rules={[{ required: true, message: "请选择所属团队" }]}
|
||||
>
|
||||
<Select options={teams} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="roleId"
|
||||
label="用户角色"
|
||||
rules={[{ required: true, message: "请选择用户角色" }]}
|
||||
>
|
||||
<Select options={roles} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
147
src/pages/admin/UserManage.jsx
Normal file
147
src/pages/admin/UserManage.jsx
Normal file
@ -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 (
|
||||
<>
|
||||
<Flex justify="space-between">
|
||||
<Input.Search
|
||||
placeholder="请输入用户姓名"
|
||||
onSearch={handleSearch}
|
||||
style={{ width: "200px" }}
|
||||
className="m-4"
|
||||
/>
|
||||
<Button
|
||||
className="m-4"
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setModalMode("create");
|
||||
setSelectedUser(null);
|
||||
setModalOpen(true);
|
||||
}}
|
||||
>
|
||||
添加用户
|
||||
</Button>
|
||||
</Flex>
|
||||
<Table
|
||||
rowKey="userId"
|
||||
dataSource={users}
|
||||
pagination={pagination}
|
||||
onChange={handlePageChange}
|
||||
>
|
||||
<Column title="姓名" key="name" dataIndex="name" />
|
||||
<Column title="账号" key="username" dataIndex="username" />
|
||||
<Column title="联系电话" key="phone" dataIndex="phone" />
|
||||
<Column title="所属团队" key="team" dataIndex="team" />
|
||||
<Column
|
||||
title="操作"
|
||||
render={(_, record) => {
|
||||
return (
|
||||
<Space>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setSelectedUser(record);
|
||||
setModalOpen(true);
|
||||
setModalMode("edit");
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title="删除用户"
|
||||
description="确认要删除该用户吗?"
|
||||
onConfirm={() => handleDelete(record)}
|
||||
>
|
||||
<Button danger size="small">
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Table>
|
||||
<UserDetailModal
|
||||
visiable={modalOpen}
|
||||
mode={modalMode}
|
||||
user={selectedUser}
|
||||
onclose={() => {
|
||||
setModalOpen(false);
|
||||
setSelectedUser(null);
|
||||
}}
|
||||
onSuccess={async () => {
|
||||
await fetchData({
|
||||
...pagination,
|
||||
current: 1,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
@ -68,7 +68,6 @@ export default function DeviceDetailModal({
|
||||
message.success("编辑成功");
|
||||
} else {
|
||||
device = await axiosInstance.post(`/device/${userId}`, data);
|
||||
console.log(device);
|
||||
|
||||
message.success("添加成功");
|
||||
}
|
||||
|
@ -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() {
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
color="red"
|
||||
variant="solid"
|
||||
size="small"
|
||||
onClick={() => handleDelete(record.deviceId)}
|
||||
<Popconfirm
|
||||
title="删除设备"
|
||||
description="确认要删除该设备吗?"
|
||||
onConfirm={() => handleDelete(record.deviceId)}
|
||||
>
|
||||
<Button color="red" variant="solid" size="small">
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
}}
|
||||
@ -154,7 +164,10 @@ export default function DeviceManage() {
|
||||
setSelectedDevice(null);
|
||||
}}
|
||||
onSuccess={async () => {
|
||||
await fetchData(pagination);
|
||||
await fetchData({
|
||||
...pagination,
|
||||
current: 1,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
@ -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("修改成功");
|
||||
|
@ -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: <ProtectedRoute allowedRoles={["ADMIN"]} />,
|
||||
children: [
|
||||
{
|
||||
path: "user-manage",
|
||||
element: <UserManage />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "userdetail",
|
||||
element: <UserDetail />,
|
||||
|
Loading…
x
Reference in New Issue
Block a user