mirror of
https://github.com/PlayEdu/frontend.git
synced 2025-06-29 13:52:44 +08:00
个人信息修改和切花部门
This commit is contained in:
parent
e1ce7d8b47
commit
987c6e21ec
@ -18,3 +18,10 @@ export function courses(depId: number) {
|
||||
dep_id: depId,
|
||||
});
|
||||
}
|
||||
|
||||
// 修改头像
|
||||
export function avatar(file: any) {
|
||||
return client.put("/api/v1/user/avatar", {
|
||||
file: file,
|
||||
});
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import styles from "./index.module.scss";
|
||||
import { Modal, Button, Dropdown, MenuProps } from "antd";
|
||||
import { Modal, Button, Dropdown } from "antd";
|
||||
import type { MenuProps } from "antd";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { logoutAction } from "../../store/user/loginUserSlice";
|
||||
import {
|
||||
logoutAction,
|
||||
saveCurrentDepId,
|
||||
} from "../../store/user/loginUserSlice";
|
||||
import { ChangePasswordModel } from "../change-password";
|
||||
import { UserInfoModel } from "../user-info";
|
||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
||||
@ -20,6 +24,27 @@ export const Header: React.FC = () => {
|
||||
const [changePasswordVisiale, setChangePasswordVisiale] =
|
||||
useState<boolean>(false);
|
||||
const [userInfoVisiale, setUserInfoVisiale] = useState<boolean>(false);
|
||||
const [departmentsMenu, setDepartmentsMenu] = useState<any>([]);
|
||||
const [currentDepartment, setCurrentDepartment] = useState<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentDepartment(departments[0].name);
|
||||
const arr: any = [
|
||||
{
|
||||
key: "1",
|
||||
type: "group",
|
||||
label: "部门",
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
departments.map((item: any) => {
|
||||
arr[0].children.push({
|
||||
key: item.id,
|
||||
label: item.name,
|
||||
});
|
||||
});
|
||||
setDepartmentsMenu(arr);
|
||||
}, [departments]);
|
||||
|
||||
const onClick: MenuProps["onClick"] = ({ key }) => {
|
||||
if (key === "login_out") {
|
||||
@ -75,6 +100,32 @@ export const Header: React.FC = () => {
|
||||
},
|
||||
];
|
||||
|
||||
const depItems: MenuProps["items"] = departmentsMenu;
|
||||
|
||||
const onDepClick: MenuProps["onClick"] = ({ key }) => {
|
||||
let name: string = "";
|
||||
departments.map((item: any) => {
|
||||
if (Number(key) === item.id) {
|
||||
name = item.name;
|
||||
}
|
||||
});
|
||||
confirm({
|
||||
title: "操作确认",
|
||||
icon: <ExclamationCircleFilled />,
|
||||
content: "确认切换部门?",
|
||||
centered: true,
|
||||
okText: "确认",
|
||||
cancelText: "取消",
|
||||
onOk() {
|
||||
setCurrentDepartment(name);
|
||||
dispatch(saveCurrentDepId(Number(key)));
|
||||
},
|
||||
onCancel() {
|
||||
console.log("Cancel");
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles["app-header"]}>
|
||||
<div className={styles["main-header"]}>
|
||||
@ -84,10 +135,15 @@ export const Header: React.FC = () => {
|
||||
</Link>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
{departments.length > 0 && (
|
||||
{departments.length === 1 && (
|
||||
<div className={styles["department-name"]}>{currentDepartment}</div>
|
||||
)}
|
||||
{departments.length > 1 && (
|
||||
<Dropdown menu={{ items: depItems, onClick: onDepClick }}>
|
||||
<div className={styles["department-name"]}>
|
||||
{departments[0].name}
|
||||
{currentDepartment}
|
||||
</div>
|
||||
</Dropdown>
|
||||
)}
|
||||
<Button.Group className={styles["button-group"]}>
|
||||
<Dropdown menu={{ items, onClick }} placement="bottomRight">
|
||||
|
@ -1,7 +1,12 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Modal, Image, Form, Input, message } from "antd";
|
||||
import { Modal, Image, Form, message, Upload, Button } from "antd";
|
||||
import styles from "./index.module.less";
|
||||
import { user } from "../../api/index";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { loginAction } from "../../store/user/loginUserSlice";
|
||||
import type { UploadProps } from "antd";
|
||||
import config from "../../js/config";
|
||||
import { getToken } from "../../utils/index";
|
||||
|
||||
interface PropInterface {
|
||||
open: boolean;
|
||||
@ -9,9 +14,12 @@ interface PropInterface {
|
||||
}
|
||||
|
||||
export const UserInfoModel: React.FC<PropInterface> = ({ open, onCancel }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [avatar, setAvatar] = useState<string>("");
|
||||
const [name, setName] = useState<string>("");
|
||||
const [idCard, setIdCard] = useState<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
getUser();
|
||||
@ -20,21 +28,41 @@ export const UserInfoModel: React.FC<PropInterface> = ({ open, onCancel }) => {
|
||||
const getUser = () => {
|
||||
user.detail().then((res: any) => {
|
||||
setAvatar(res.data.user.avatar);
|
||||
form.setFieldsValue({
|
||||
name: res.data.user.name,
|
||||
});
|
||||
setName(res.data.user.name);
|
||||
setIdCard(res.data.user.id_card);
|
||||
dispatch(loginAction(res.data));
|
||||
});
|
||||
};
|
||||
|
||||
const onFinish = (values: any) => {
|
||||
user.password(avatar, values.name).then((res: any) => {
|
||||
message.success("保存成功!");
|
||||
onCancel();
|
||||
});
|
||||
};
|
||||
|
||||
const onFinishFailed = (errorInfo: any) => {
|
||||
console.log("Failed:", errorInfo);
|
||||
const props: UploadProps = {
|
||||
name: "file",
|
||||
multiple: false,
|
||||
method: "PUT",
|
||||
action: config.app_url + "/api/v1/user/avatar",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
authorization: "Bearer " + getToken(),
|
||||
},
|
||||
beforeUpload: (file) => {
|
||||
const isPNG = file.type === ("image/png" || "image/jpg");
|
||||
if (!isPNG) {
|
||||
message.error(`${file.name}不是图片文件`);
|
||||
}
|
||||
return isPNG || Upload.LIST_IGNORE;
|
||||
},
|
||||
onChange(info: any) {
|
||||
const { status, response } = info.file;
|
||||
if (status === "done") {
|
||||
if (response.code === 0) {
|
||||
message.success(`${info.file.name} 上传成功`);
|
||||
getUser();
|
||||
} else {
|
||||
message.error(response.msg);
|
||||
}
|
||||
} else if (status === "error") {
|
||||
message.error(`${info.file.name} 上传失败`);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
@ -45,25 +73,22 @@ export const UserInfoModel: React.FC<PropInterface> = ({ open, onCancel }) => {
|
||||
forceRender
|
||||
open={open}
|
||||
width={416}
|
||||
onOk={() => form.submit()}
|
||||
onCancel={() => onCancel()}
|
||||
maskClosable={false}
|
||||
footer={null}
|
||||
>
|
||||
<div className="float-left mt-24">
|
||||
<div className="mt-24">
|
||||
<Form
|
||||
form={form}
|
||||
name="user-info"
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
initialValues={{ remember: true }}
|
||||
onFinish={onFinish}
|
||||
onFinishFailed={onFinishFailed}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item
|
||||
label="学员头像"
|
||||
labelCol={{ style: { marginTop: 15, marginLeft: 52 } }}
|
||||
name="avatar"
|
||||
>
|
||||
<div className="d-flex">
|
||||
{avatar && (
|
||||
@ -75,15 +100,18 @@ export const UserInfoModel: React.FC<PropInterface> = ({ open, onCancel }) => {
|
||||
preview={false}
|
||||
/>
|
||||
)}
|
||||
<div className="d-flex ml-16">更换头像</div>
|
||||
<div className="d-flex ml-16">
|
||||
<Upload {...props} showUploadList={false}>
|
||||
<Button>更换头像</Button>
|
||||
</Upload>
|
||||
</div>
|
||||
</div>
|
||||
</Form.Item>
|
||||
<Form.Item label="修改姓名" name="name">
|
||||
<Input
|
||||
style={{ width: 200 }}
|
||||
autoComplete="off"
|
||||
placeholder="请输入姓名"
|
||||
/>
|
||||
<Form.Item label="学员姓名">
|
||||
<div>{name}</div>
|
||||
</Form.Item>
|
||||
<Form.Item label="身份证号" style={{ marginBottom: 16 }}>
|
||||
<div>{idCard}</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
|
3
src/js/config.ts
Normal file
3
src/js/config.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default {
|
||||
app_url: import.meta.env.VITE_APP_URL || "",
|
||||
};
|
@ -19,14 +19,17 @@ const IndexPage = () => {
|
||||
const departments = useSelector(
|
||||
(state: any) => state.loginUser.value.departments
|
||||
);
|
||||
const currentDepId = useSelector(
|
||||
(state: any) => state.loginUser.value.currentDepId
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [tabKey]);
|
||||
}, [tabKey, currentDepId]);
|
||||
|
||||
const getData = () => {
|
||||
setLoading(true);
|
||||
user.courses(departments[0].id).then((res: any) => {
|
||||
user.courses(currentDepId).then((res: any) => {
|
||||
const records = res.data.learn_course_records;
|
||||
setStats(res.data.stats);
|
||||
setLearnCourseRecords(records);
|
||||
|
@ -3,12 +3,14 @@ import { createSlice } from "@reduxjs/toolkit";
|
||||
type UserStoreInterface = {
|
||||
user: null;
|
||||
departments: string[];
|
||||
currentDepId: number;
|
||||
isLogin: boolean;
|
||||
};
|
||||
|
||||
let defaultValue: UserStoreInterface = {
|
||||
user: null,
|
||||
departments: [],
|
||||
currentDepId: 0,
|
||||
isLogin: false,
|
||||
};
|
||||
|
||||
@ -22,16 +24,23 @@ const loginUserSlice = createSlice({
|
||||
stage.value.user = e.payload.user;
|
||||
stage.value.departments = e.payload.departments;
|
||||
stage.value.isLogin = true;
|
||||
if (e.payload.departments.length > 0 && stage.value.currentDepId === 0) {
|
||||
stage.value.currentDepId = e.payload.departments[0].id;
|
||||
}
|
||||
},
|
||||
logoutAction(stage) {
|
||||
stage.value.user = null;
|
||||
stage.value.departments = [];
|
||||
stage.value.isLogin = false;
|
||||
},
|
||||
saveCurrentDepId(stage, e) {
|
||||
stage.value.currentDepId = e.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default loginUserSlice.reducer;
|
||||
export const { loginAction, logoutAction } = loginUserSlice.actions;
|
||||
export const { loginAction, logoutAction, saveCurrentDepId } =
|
||||
loginUserSlice.actions;
|
||||
|
||||
export type { UserStoreInterface };
|
||||
|
Loading…
x
Reference in New Issue
Block a user