feat: 实现用户信息管理页面

This commit is contained in:
BenjaminNH 2025-06-25 16:43:40 +08:00
parent 57505a0b40
commit 7cb14c7ef5
4 changed files with 171 additions and 2 deletions

View File

@ -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;

View File

@ -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 />

View 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>
);
}

View File

@ -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 />,
},
], ],
}, },
], ],