登录页面和我的页面初步

This commit is contained in:
禺狨
2023-06-25 15:19:43 +08:00
parent f93467db13
commit 5486507b3e
19 changed files with 349 additions and 32 deletions

View File

@@ -41,7 +41,6 @@ export class HttpClient {
return Promise.resolve(response);
} else {
Toast.show({
icon: "fail",
content: msg,
});
}
@@ -52,7 +51,6 @@ export class HttpClient {
let status = error.response.status;
if (status === 401) {
Toast.show({
icon: "fail",
content: "请重新登录",
});
GoLogin();

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

@@ -21,7 +21,7 @@ export const TabBarFooter: React.FC = () => {
) : (
<i
style={{ fontSize: 30, color: "#cccccc" }}
className="iconfont icon-waterprint"
className="iconfont icon-icon-shouye"
></i>
),
},

View File

@@ -35,6 +35,12 @@ code {
height: 30px;
}
.main-body {
width: 100%;
float: left;
height: auto;
}
.adm-tab-bar-item-title {
font-size: 11px;
font-weight: 400;

View File

@@ -0,0 +1,117 @@
.login-content {
position: fixed;
bottom: 0;
left: 0;
right: 0;
top: 0;
background-image: url("../../assets//images/login/bg.png");
background-size: 100% 100%;
.top-content {
width: 100%;
height: 150px;
box-sizing: border-box;
padding: 0px 20px;
display: flex;
justify-content: space-between;
align-items: center;
.title {
font-size: 24px;
font-weight: 600;
color: rgba(0, 0, 0, 0.88);
line-height: 24px;
}
}
.form-box {
width: 100%;
float: left;
height: auto;
box-sizing: border-box;
padding: 0px 20px;
margin-top: 30px;
.input-box {
width: 100%;
height: 109px;
background: #ffffff;
border-radius: 8px;
.input-item {
width: 100%;
height: 54px;
font-size: 16px;
font-weight: 400;
color: rgba(0, 0, 0, 0.3);
line-height: 54px;
box-sizing: border-box;
padding: 0px 15px;
}
.line {
width: auto;
height: 1px;
background: rgba(0, 0, 0, 0.05);
margin: 0px 15px;
}
}
.captcha-box {
width: 100%;
height: 54px;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
.input-item {
width: 200px;
height: 54px;
background: #ffffff;
border-radius: 8px;
box-sizing: border-box;
padding: 0px 15px;
font-size: 16px;
font-weight: 400;
color: rgba(0, 0, 0, 0.3);
line-height: 54px;
}
.captcha-button {
width: 125px;
height: 54px;
border-radius: 4px;
overflow: hidden;
.catpcha-loading-box {
width: 125px;
height: 54px;
display: flex;
align-items: center;
justify-content: center;
}
.captcha {
width: 125px;
height: 54px;
border-radius: 4px;
}
}
}
.button-box {
width: 100%;
height: 54px;
margin-top: 30px;
.primary-button {
width: 100%;
height: 54px;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
}
}
.support-box {
position: fixed;
bottom: 90px;
left: 0;
right: 0;
font-size: 12px;
font-weight: 400;
color: rgba(0, 0, 0, 0.3);
line-height: 12px;
margin-top: 200px;
}
}
}

View File

@@ -1,39 +1,165 @@
import { Button } from "antd-mobile";
import React, { useState, useEffect } from "react";
import { Button, Toast, SpinLoading, Input, Image } from "antd-mobile";
import styles from "./index.module.scss";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { login, system, user } from "../../api/index";
import { setToken } from "../../utils/index";
import { loginAction, logoutAction } from "../../store/user/loginUserSlice";
import banner from "../../assets/images/login/banner.png";
const LoginPage = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const [loading, setLoading] = useState<boolean>(false);
const [image, setImage] = useState<string>("");
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [captchaVal, setCaptchaVal] = useState<string>("");
const [captchaKey, setCaptchaKey] = useState<string>("");
const [captchaLoading, setCaptchaLoading] = useState(true);
const loginState = useSelector((state: any) => {
return state.loginUser.value;
});
return (
<>
<Button
onClick={() => {
dispatch(
loginAction({
user: {
name: "霸王",
},
})
);
}}
>
</Button>
useEffect(() => {
fetchImageCaptcha();
document.title = "登录";
}, []);
{loginState.isLogin && (
<Button
onClick={() => {
dispatch(logoutAction());
}}
>
{loginState.user.name}
</Button>
)}
</>
const fetchImageCaptcha = () => {
setCaptchaLoading(true);
system.imageCaptcha().then((res: any) => {
setImage(res.data.image);
setCaptchaKey(res.data.key);
setCaptchaLoading(false);
});
};
const loginSubmit = (e: any) => {
if (!email) {
Toast.show({
content: "请输入学员邮箱账号",
});
return;
}
if (!password) {
Toast.show({
content: "请输入密码",
});
return;
}
if (!captchaVal) {
Toast.show({
content: "请输入图形验证码",
});
return;
}
if (captchaVal.length < 4) {
Toast.show({
content: "图形验证码错误",
});
return;
}
if (loading) {
return;
}
handleSubmit();
};
const handleSubmit = () => {
if (loading) {
return;
}
setLoading(true);
login
.login(email, password, captchaKey, captchaVal)
.then((res: any) => {
const token = res.data.token;
setToken(token);
getUser();
})
.catch((e) => {
setLoading(false);
setCaptchaVal("");
fetchImageCaptcha();
});
};
const getUser = () => {
user.detail().then((res: any) => {
const data = res.data;
dispatch(loginAction(data));
setLoading(false);
navigate("/member", { replace: true });
});
};
return (
<div className={styles["login-content"]}>
<div className={styles["top-content"]}>
<div className={styles["title"]}></div>
<Image src={banner} width={150} height={150} />
</div>
<div className={styles["form-box"]}>
<div className={styles["input-box"]}>
<Input
className={styles["input-item"]}
placeholder="请输入学员邮箱账号"
value={email}
onChange={(val) => {
setEmail(val);
}}
/>
<div className={styles["line"]}></div>
<Input
type="password"
className={styles["input-item"]}
placeholder="请输入密码"
value={password}
onChange={(val) => {
setPassword(val);
}}
/>
</div>
<div className={styles["captcha-box"]}>
<Input
value={captchaVal}
className={styles["input-item"]}
placeholder="请输入图形验证码"
onChange={(val) => {
setCaptchaVal(val);
}}
/>
<div className={styles["captcha-button"]}>
{captchaLoading && (
<div className={styles["catpcha-loading-box"]}>
<SpinLoading color="primary" />
</div>
)}
{!captchaLoading && (
<Image
className={styles["captcha"]}
onClick={fetchImageCaptcha}
src={image}
/>
)}
</div>
</div>
<div className={styles["button-box"]}>
<Button
className={styles["primary-button"]}
disabled={captchaVal === "" || email === "" || password === ""}
color="primary"
loading={loading}
onClick={loginSubmit}
>
</Button>
</div>
<div className={styles["support-box"]}>PlayEdu提供技术支持</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,11 @@
.support-box {
position: fixed;
bottom: 90px;
left: 0;
right: 0;
font-size: 12px;
font-weight: 400;
color: rgba(0, 0, 0, 0.3);
line-height: 12px;
margin-top: 200px;
}

View File

@@ -0,0 +1,32 @@
import { useEffect, useState } from "react";
import { user } from "../../api/index";
import styles from "./index.module.scss";
import { useSelector } from "react-redux";
import { TabBarFooter } from "../../components";
import moreIcon from "../../assets/images/commen/icon-more.png";
const MemberPage = () => {
const systemConfig = useSelector((state: any) => state.systemConfig.value);
const [loading, setLoading] = useState<boolean>(false);
const [tabKey, setTabKey] = useState(0);
const departments = useSelector(
(state: any) => state.loginUser.value.departments
);
const currentDepId = useSelector(
(state: any) => state.loginUser.value.currentDepId
);
useEffect(() => {
document.title = "我的";
}, []);
return (
<div className="main-body">
<div className={styles["content-box"]}></div>
<div className={styles["support-box"]}>PlayEdu提供技术支持</div>
<TabBarFooter></TabBarFooter>
</div>
);
};
export default MemberPage;

View File

@@ -6,6 +6,7 @@ import { getToken } from "../utils";
import { InitPage } from "../pages/init";
import IndexPage from "../pages/index/index";
import LoginPage from "../pages/login";
import MemberPage from "../pages/member/index";
import PrivateRoute from "../components/private-route";
let RootPage: any = null;
@@ -36,12 +37,16 @@ const routes: RouteObject[] = [
children: [
{
path: "/",
element: <IndexPage />,
element: <PrivateRoute Component={<IndexPage />} />,
},
{
path: "/login",
element: <LoginPage />,
},
{
path: "/member",
element: <PrivateRoute Component={<MemberPage />} />,
},
],
},
];