EVA-Tea/src/pages/User/Login/index.tsx

283 lines
7.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { PageFooter } from '@/components';
import { login } from '@/services/ant-design-pro/api';
import { getFakeCaptcha } from '@/services/ant-design-pro/login';
import {
AlipayCircleOutlined,
LockOutlined,
MobileOutlined,
TaobaoCircleOutlined,
UserOutlined,
WeiboCircleOutlined,
} from '@ant-design/icons';
import {
LoginForm,
ProFormCaptcha,
ProFormCheckbox,
ProFormText,
} from '@ant-design/pro-components';
import { Helmet, history, useModel } from '@umijs/max';
import { Alert, Tabs, message } from 'antd';
import { createStyles } from 'antd-style';
import React, { useState } from 'react';
import { flushSync } from 'react-dom';
import Settings from '../../../../config/defaultSettings';
const useStyles = createStyles(({ token }) => {
return {
action: {
marginLeft: '8px',
color: 'rgba(0, 0, 0, 0.2)',
fontSize: '24px',
verticalAlign: 'middle',
cursor: 'pointer',
transition: 'color 0.3s',
'&:hover': {
color: token.colorPrimaryActive,
},
},
lang: {
width: 42,
height: 42,
lineHeight: '42px',
position: 'fixed',
right: 16,
borderRadius: token.borderRadius,
':hover': {
backgroundColor: token.colorBgTextHover,
},
},
container: {
display: 'flex',
flexDirection: 'column',
height: '100vh',
overflow: 'auto',
backgroundImage:
"url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
backgroundSize: '100% 100%',
},
};
});
const ActionIcons = () => {
const { styles } = useStyles();
return (
<>
<AlipayCircleOutlined key="AlipayCircleOutlined" className={styles.action} />
<TaobaoCircleOutlined key="TaobaoCircleOutlined" className={styles.action} />
<WeiboCircleOutlined key="WeiboCircleOutlined" className={styles.action} />
</>
);
};
const LoginMessage: React.FC<{
content: string;
}> = ({ content }) => {
return (
<Alert
style={{
marginBottom: 24,
}}
message={content}
type="error"
showIcon
/>
);
};
const Login: React.FC = () => {
const [userLoginState, setUserLoginState] = useState<API.LoginResult>({});
const [type, setType] = useState<string>('account');
const { initialState, setInitialState } = useModel('@@initialState');
const { styles } = useStyles();
const fetchUserInfo = async () => {
const userInfo = await initialState?.fetchUserInfo?.();
if (userInfo) {
flushSync(() => {
setInitialState((s) => ({
...s,
currentUser: userInfo,
}));
});
}
};
const handleSubmit = async (values: API.LoginParams) => {
try {
// 登录
const msg = await login({
...values,
type,
});
if (msg.status === 'ok') {
const defaultLoginSuccessMessage = '登录成功!';
message.success(defaultLoginSuccessMessage);
await fetchUserInfo();
const urlParams = new URL(window.location.href).searchParams;
history.push(urlParams.get('redirect') || '/');
return;
}
console.log(msg);
// 如果失败去设置用户错误信息
setUserLoginState(msg);
} catch (error) {
const defaultLoginFailureMessage = '登录失败,请重试!';
console.log(error);
message.error(defaultLoginFailureMessage);
}
};
const { status, type: loginType } = userLoginState;
return (
<div className={styles.container}>
<Helmet>
<title>
{'登录'}- {Settings.title}
</title>
</Helmet>
<div
style={{
flex: '1',
padding: '32px 0',
}}
>
<LoginForm
contentStyle={{
minWidth: 280,
maxWidth: '75vw',
}}
logo={<img alt="logo" src="/logo.svg" />}
title="Ant Design"
subTitle={'Ant Design 是西湖区最具影响力的 Web 设计规范'}
initialValues={{
autoLogin: true,
}}
actions={['其他登录方式 :', <ActionIcons key="icons" />]}
onFinish={async (values) => {
await handleSubmit(values as API.LoginParams);
}}
>
<Tabs
activeKey={type}
onChange={setType}
centered
items={[
{
key: 'account',
label: '账户密码登录',
},
{
key: 'mobile',
label: '手机号登录',
},
]}
/>
{status === 'error' && loginType === 'account' && (
<LoginMessage content={'错误的用户名和密码(admin/ant.design)'} />
)}
{type === 'account' && (
<>
<ProFormText
name="username"
fieldProps={{
size: 'large',
prefix: <UserOutlined />,
}}
placeholder={'用户名: admin or user'}
rules={[
{
required: true,
message: '用户名是必填项!',
},
]}
/>
<ProFormText.Password
name="password"
fieldProps={{
size: 'large',
prefix: <LockOutlined />,
}}
placeholder={'密码: ant.design'}
rules={[
{
required: true,
message: '密码是必填项!',
},
]}
/>
</>
)}
{status === 'error' && loginType === 'mobile' && <LoginMessage content="验证码错误" />}
{type === 'mobile' && (
<>
<ProFormText
fieldProps={{
size: 'large',
prefix: <MobileOutlined />,
}}
name="mobile"
placeholder={'请输入手机号!'}
rules={[
{
required: true,
message: '手机号是必填项!',
},
{
pattern: /^1\d{10}$/,
message: '不合法的手机号!',
},
]}
/>
<ProFormCaptcha
fieldProps={{
size: 'large',
prefix: <LockOutlined />,
}}
captchaProps={{
size: 'large',
}}
placeholder={'请输入验证码!'}
captchaTextRender={(timing, count) => {
if (timing) {
return `${count} ${'秒后重新获取'}`;
}
return '获取验证码';
}}
name="captcha"
rules={[
{
required: true,
message: '验证码是必填项!',
},
]}
onGetCaptcha={async (phone) => {
const result = await getFakeCaptcha({
phone,
});
if (!result) {
return;
}
message.success('获取验证码成功验证码为1234');
}}
/>
</>
)}
<div
style={{
marginBottom: 24,
}}
>
<ProFormCheckbox noStyle name="autoLogin">
</ProFormCheckbox>
<a
style={{
float: 'right',
}}
>
?
</a>
</div>
</LoginForm>
</div>
<PageFooter />
</div>
);
};
export default Login;