feat: 实现管理员用户管理页面
This commit is contained in:
parent
c9d0bb88b3
commit
00085874c9
@ -3,6 +3,7 @@ import {
|
|||||||
ExperimentOutlined,
|
ExperimentOutlined,
|
||||||
FileDoneOutlined,
|
FileDoneOutlined,
|
||||||
UnorderedListOutlined,
|
UnorderedListOutlined,
|
||||||
|
UsergroupAddOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
@ -38,11 +39,17 @@ const menuConfig = [
|
|||||||
icon: ExperimentOutlined,
|
icon: ExperimentOutlined,
|
||||||
roles: ["DEVICE_ADMIN"],
|
roles: ["DEVICE_ADMIN"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/admin/user-manage",
|
||||||
|
label: "用户管理",
|
||||||
|
icon: UsergroupAddOutlined,
|
||||||
|
roles: ["ADMIN"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/userdetail",
|
path: "/userdetail",
|
||||||
label: "个人信息",
|
label: "个人信息",
|
||||||
icon: UserOutlined,
|
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("编辑成功");
|
message.success("编辑成功");
|
||||||
} else {
|
} else {
|
||||||
device = await axiosInstance.post(`/device/${userId}`, data);
|
device = await axiosInstance.post(`/device/${userId}`, data);
|
||||||
console.log(device);
|
|
||||||
|
|
||||||
message.success("添加成功");
|
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 Column from "antd/es/table/Column";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
@ -132,14 +141,15 @@ export default function DeviceManage() {
|
|||||||
>
|
>
|
||||||
编辑
|
编辑
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Popconfirm
|
||||||
color="red"
|
title="删除设备"
|
||||||
variant="solid"
|
description="确认要删除该设备吗?"
|
||||||
size="small"
|
onConfirm={() => handleDelete(record.deviceId)}
|
||||||
onClick={() => handleDelete(record.deviceId)}
|
|
||||||
>
|
>
|
||||||
|
<Button color="red" variant="solid" size="small">
|
||||||
删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@ -154,7 +164,10 @@ export default function DeviceManage() {
|
|||||||
setSelectedDevice(null);
|
setSelectedDevice(null);
|
||||||
}}
|
}}
|
||||||
onSuccess={async () => {
|
onSuccess={async () => {
|
||||||
await fetchData(pagination);
|
await fetchData({
|
||||||
|
...pagination,
|
||||||
|
current: 1,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -9,6 +9,7 @@ export default function UserDetail() {
|
|||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [user, setUser] = useState({
|
const [user, setUser] = useState({
|
||||||
|
userId: "",
|
||||||
username: "",
|
username: "",
|
||||||
team: "",
|
team: "",
|
||||||
name: "",
|
name: "",
|
||||||
@ -43,7 +44,7 @@ export default function UserDetail() {
|
|||||||
}
|
}
|
||||||
delete changedFields.confirmPassword;
|
delete changedFields.confirmPassword;
|
||||||
|
|
||||||
const newUser = await axiosInstance.patch(`/user/${userId}`, changedFields);
|
const newUser = await axiosInstance.put(`/user/${userId}`, changedFields);
|
||||||
setUser(newUser);
|
setUser(newUser);
|
||||||
form.setFieldsValue(newUser);
|
form.setFieldsValue(newUser);
|
||||||
message.success("修改成功");
|
message.success("修改成功");
|
||||||
|
@ -8,6 +8,7 @@ import MyReservation from "../pages/user/MyReservation";
|
|||||||
import Reserve from "../pages/user/Reserve";
|
import Reserve from "../pages/user/Reserve";
|
||||||
import ProtectedRoute from "./ProtectedRoute";
|
import ProtectedRoute from "./ProtectedRoute";
|
||||||
import DeviceManage from "../pages/deviceAdmin/DeviceManage";
|
import DeviceManage from "../pages/deviceAdmin/DeviceManage";
|
||||||
|
import UserManage from "../pages/admin/UserManage";
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@ -59,6 +60,16 @@ const router = createBrowserRouter([
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "admin",
|
||||||
|
element: <ProtectedRoute allowedRoles={["ADMIN"]} />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "user-manage",
|
||||||
|
element: <UserManage />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "userdetail",
|
path: "userdetail",
|
||||||
element: <UserDetail />,
|
element: <UserDetail />,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user