feat: 实现用户信息管理页面
This commit is contained in:
parent
57505a0b40
commit
7cb14c7ef5
@ -1,4 +1,8 @@
|
|||||||
import { DesktopOutlined, UnorderedListOutlined } from "@ant-design/icons";
|
import {
|
||||||
|
DesktopOutlined,
|
||||||
|
UnorderedListOutlined,
|
||||||
|
UserOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
const menuConfig = [
|
const menuConfig = [
|
||||||
{
|
{
|
||||||
@ -13,6 +17,12 @@ const menuConfig = [
|
|||||||
icon: UnorderedListOutlined,
|
icon: UnorderedListOutlined,
|
||||||
roles: ["USER"],
|
roles: ["USER"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/user/userdetail",
|
||||||
|
label: "个人信息",
|
||||||
|
icon: UserOutlined,
|
||||||
|
roles: ["USER"],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default menuConfig;
|
export default menuConfig;
|
||||||
|
@ -69,7 +69,10 @@ export default function CommonLayout() {
|
|||||||
style={{ padding: 0, background: colorBgContainer }}
|
style={{ padding: 0, background: colorBgContainer }}
|
||||||
className="flex justify-end"
|
className="flex justify-end"
|
||||||
>
|
>
|
||||||
<Dropdown menu={{ items: dropDownItems, onClick: handleMenuClick }}>
|
<Dropdown
|
||||||
|
menu={{ items: dropDownItems, onClick: handleMenuClick }}
|
||||||
|
className="p-4"
|
||||||
|
>
|
||||||
<Space>
|
<Space>
|
||||||
{userName}
|
{userName}
|
||||||
<DownOutlined />
|
<DownOutlined />
|
||||||
|
151
src/pages/user/UserDetail.jsx
Normal file
151
src/pages/user/UserDetail.jsx
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import { Button, Col, Form, Input, message, Row } from "antd";
|
||||||
|
import { useForm } from "antd/es/form/Form";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import axiosInstance from "../../api/axios";
|
||||||
|
import { selectUserId } from "../../features/auth/authSlice";
|
||||||
|
|
||||||
|
export default function UserDetail() {
|
||||||
|
const [form] = useForm();
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
const [user, setUser] = useState({
|
||||||
|
username: "",
|
||||||
|
team: "",
|
||||||
|
name: "",
|
||||||
|
phone: "",
|
||||||
|
});
|
||||||
|
const userId = useSelector(selectUserId);
|
||||||
|
|
||||||
|
const fetchUser = async (userId) => {
|
||||||
|
const user = await axiosInstance.get(`/userdetail/${userId}`);
|
||||||
|
setUser(user);
|
||||||
|
form.setFieldsValue(user);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchUser(userId);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
form.resetFields();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (values) => {
|
||||||
|
if (values.password && values.password !== values.confirmPassword) {
|
||||||
|
message.error("两次输入的密码不一致");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const changedFields = {};
|
||||||
|
for (const key in values) {
|
||||||
|
if (values[key] !== user[key] && values[key] !== undefined) {
|
||||||
|
changedFields[key] = values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete changedFields.confirmPassword;
|
||||||
|
|
||||||
|
const newUser = await axiosInstance.patch(`/user/${userId}`, changedFields);
|
||||||
|
setUser(newUser);
|
||||||
|
form.setFieldsValue(newUser);
|
||||||
|
message.success("修改成功");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-6">
|
||||||
|
<Form
|
||||||
|
requiredMark={false}
|
||||||
|
variant="borderless"
|
||||||
|
form={form}
|
||||||
|
initialValues={user}
|
||||||
|
onFinish={handleSubmit}
|
||||||
|
>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item label="账号">
|
||||||
|
<Input disabled value={user.username} />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item label="所属团队">
|
||||||
|
<Input disabled value={user.team} />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="name"
|
||||||
|
label="姓名"
|
||||||
|
rules={[{ required: true, message: "请输入姓名" }]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="phone"
|
||||||
|
label="联系电话"
|
||||||
|
rules={[{ required: true, message: "请输入联系电话" }]}
|
||||||
|
>
|
||||||
|
<Input value={user.phone} />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
{showPassword && (
|
||||||
|
<>
|
||||||
|
<Row gutter={16}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="password"
|
||||||
|
label="新密码"
|
||||||
|
rules={[{ required: true, message: "请输入新密码" }]}
|
||||||
|
>
|
||||||
|
<Input.Password />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="confirmPassword"
|
||||||
|
label="确认新密码"
|
||||||
|
dependencies={["password"]}
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: "请再次输入新密码" },
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(_, value) {
|
||||||
|
if (!value || getFieldValue("password") === value) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error("两次输入密码不一致"));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.Password />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Row justify="center" gutter={8}>
|
||||||
|
<Col>
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
>
|
||||||
|
{showPassword ? "取消修改密码" : "修改密码"}
|
||||||
|
</Button>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<Button onClick={handleReset}>重置修改</Button>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<Form.Item>
|
||||||
|
<Button type="primary" htmlType="submit">
|
||||||
|
保存修改
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -4,6 +4,7 @@ import ProtectedRoute from "./ProtectedRoute";
|
|||||||
import CommonLayout from "../layouts/CommonLayout";
|
import CommonLayout from "../layouts/CommonLayout";
|
||||||
import Reserve from "../pages/user/Reserve";
|
import Reserve from "../pages/user/Reserve";
|
||||||
import MyReservation from "../pages/user/MyReservation";
|
import MyReservation from "../pages/user/MyReservation";
|
||||||
|
import UserDetail from "../pages/user/UserDetail";
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@ -30,6 +31,10 @@ const router = createBrowserRouter([
|
|||||||
path: "my-reservation",
|
path: "my-reservation",
|
||||||
element: <MyReservation />,
|
element: <MyReservation />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "userdetail",
|
||||||
|
element: <UserDetail />,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user