2 changed files with 0 additions and 338 deletions
@ -1,48 +0,0 @@ |
|||||
@import (reference) '~antd/es/style/themes/index'; |
|
||||
|
|
||||
.container { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
height: 100vh; |
|
||||
overflow: auto; |
|
||||
background: @layout-body-background; |
|
||||
} |
|
||||
|
|
||||
.lang { |
|
||||
width: 100%; |
|
||||
height: 40px; |
|
||||
line-height: 44px; |
|
||||
text-align: right; |
|
||||
:global(.ant-dropdown-trigger) { |
|
||||
margin-right: 24px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.content { |
|
||||
flex: 1; |
|
||||
padding: 32px 0; |
|
||||
} |
|
||||
|
|
||||
@media (min-width: @screen-md-min) { |
|
||||
.container { |
|
||||
background-image: url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr'); |
|
||||
background-size: cover; |
|
||||
} |
|
||||
|
|
||||
.content { |
|
||||
padding: 32px 0 24px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.icon { |
|
||||
margin-left: 8px; |
|
||||
color: rgba(0, 0, 0, 0.2); |
|
||||
font-size: 24px; |
|
||||
vertical-align: middle; |
|
||||
cursor: pointer; |
|
||||
transition: color 0.3s; |
|
||||
|
|
||||
&:hover { |
|
||||
color: @primary-color; |
|
||||
} |
|
||||
} |
|
||||
@ -1,290 +0,0 @@ |
|||||
import Footer from '@/components/Footer'; |
|
||||
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 { FormattedMessage, history, SelectLang, useIntl, useModel } from '@umijs/max'; |
|
||||
import { Alert, message, Tabs } from 'antd'; |
|
||||
import React, { useState } from 'react'; |
|
||||
import styles from './index.less'; |
|
||||
|
|
||||
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 intl = useIntl(); |
|
||||
|
|
||||
const fetchUserInfo = async () => { |
|
||||
const userInfo = await initialState?.fetchUserInfo?.(); |
|
||||
if (userInfo) { |
|
||||
await setInitialState((s) => ({ |
|
||||
...s, |
|
||||
currentUser: userInfo, |
|
||||
})); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
const handleSubmit = async (values: API.LoginParams) => { |
|
||||
try { |
|
||||
// 登录
|
|
||||
const msg = await login({ ...values, type }); |
|
||||
if (msg.status === 'ok') { |
|
||||
const defaultLoginSuccessMessage = intl.formatMessage({ |
|
||||
id: 'pages.login.success', |
|
||||
defaultMessage: '登录成功!', |
|
||||
}); |
|
||||
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 = intl.formatMessage({ |
|
||||
id: 'pages.login.failure', |
|
||||
defaultMessage: '登录失败,请重试!', |
|
||||
}); |
|
||||
console.log(error); |
|
||||
message.error(defaultLoginFailureMessage); |
|
||||
} |
|
||||
}; |
|
||||
const { status, type: loginType } = userLoginState; |
|
||||
|
|
||||
return ( |
|
||||
<div className={styles.container}> |
|
||||
<div className={styles.lang} data-lang> |
|
||||
{SelectLang && <SelectLang />} |
|
||||
</div> |
|
||||
<div className={styles.content}> |
|
||||
<LoginForm |
|
||||
logo={<img alt="logo" src="/logo.svg" />} |
|
||||
title="Ant Design" |
|
||||
subTitle={intl.formatMessage({ id: 'pages.layouts.userLayout.title' })} |
|
||||
initialValues={{ |
|
||||
autoLogin: true, |
|
||||
}} |
|
||||
actions={[ |
|
||||
<FormattedMessage |
|
||||
key="loginWith" |
|
||||
id="pages.login.loginWith" |
|
||||
defaultMessage="其他登录方式" |
|
||||
/>, |
|
||||
<AlipayCircleOutlined key="AlipayCircleOutlined" className={styles.icon} />, |
|
||||
<TaobaoCircleOutlined key="TaobaoCircleOutlined" className={styles.icon} />, |
|
||||
<WeiboCircleOutlined key="WeiboCircleOutlined" className={styles.icon} />, |
|
||||
]} |
|
||||
onFinish={async (values) => { |
|
||||
await handleSubmit(values as API.LoginParams); |
|
||||
}} |
|
||||
> |
|
||||
<Tabs activeKey={type} onChange={setType}> |
|
||||
<Tabs.TabPane |
|
||||
key="account" |
|
||||
tab={intl.formatMessage({ |
|
||||
id: 'pages.login.accountLogin.tab', |
|
||||
defaultMessage: '账户密码登录', |
|
||||
})} |
|
||||
/> |
|
||||
<Tabs.TabPane |
|
||||
key="mobile" |
|
||||
tab={intl.formatMessage({ |
|
||||
id: 'pages.login.phoneLogin.tab', |
|
||||
defaultMessage: '手机号登录', |
|
||||
})} |
|
||||
/> |
|
||||
</Tabs> |
|
||||
|
|
||||
{status === 'error' && loginType === 'account' && ( |
|
||||
<LoginMessage |
|
||||
content={intl.formatMessage({ |
|
||||
id: 'pages.login.accountLogin.errorMessage', |
|
||||
defaultMessage: '账户或密码错误(admin/ant.design)', |
|
||||
})} |
|
||||
/> |
|
||||
)} |
|
||||
{type === 'account' && ( |
|
||||
<> |
|
||||
<ProFormText |
|
||||
name="username" |
|
||||
fieldProps={{ |
|
||||
size: 'large', |
|
||||
prefix: <UserOutlined className={styles.prefixIcon} />, |
|
||||
}} |
|
||||
placeholder={intl.formatMessage({ |
|
||||
id: 'pages.login.username.placeholder', |
|
||||
defaultMessage: '用户名: admin or user', |
|
||||
})} |
|
||||
rules={[ |
|
||||
{ |
|
||||
required: true, |
|
||||
message: ( |
|
||||
<FormattedMessage |
|
||||
id="pages.login.username.required" |
|
||||
defaultMessage="请输入用户名!" |
|
||||
/> |
|
||||
), |
|
||||
}, |
|
||||
]} |
|
||||
/> |
|
||||
<ProFormText.Password |
|
||||
name="password" |
|
||||
fieldProps={{ |
|
||||
size: 'large', |
|
||||
prefix: <LockOutlined className={styles.prefixIcon} />, |
|
||||
}} |
|
||||
placeholder={intl.formatMessage({ |
|
||||
id: 'pages.login.password.placeholder', |
|
||||
defaultMessage: '密码: ant.design', |
|
||||
})} |
|
||||
rules={[ |
|
||||
{ |
|
||||
required: true, |
|
||||
message: ( |
|
||||
<FormattedMessage |
|
||||
id="pages.login.password.required" |
|
||||
defaultMessage="请输入密码!" |
|
||||
/> |
|
||||
), |
|
||||
}, |
|
||||
]} |
|
||||
/> |
|
||||
</> |
|
||||
)} |
|
||||
|
|
||||
{status === 'error' && loginType === 'mobile' && <LoginMessage content="验证码错误" />} |
|
||||
{type === 'mobile' && ( |
|
||||
<> |
|
||||
<ProFormText |
|
||||
fieldProps={{ |
|
||||
size: 'large', |
|
||||
prefix: <MobileOutlined className={styles.prefixIcon} />, |
|
||||
}} |
|
||||
name="mobile" |
|
||||
placeholder={intl.formatMessage({ |
|
||||
id: 'pages.login.phoneNumber.placeholder', |
|
||||
defaultMessage: '手机号', |
|
||||
})} |
|
||||
rules={[ |
|
||||
{ |
|
||||
required: true, |
|
||||
message: ( |
|
||||
<FormattedMessage |
|
||||
id="pages.login.phoneNumber.required" |
|
||||
defaultMessage="请输入手机号!" |
|
||||
/> |
|
||||
), |
|
||||
}, |
|
||||
{ |
|
||||
pattern: /^1\d{10}$/, |
|
||||
message: ( |
|
||||
<FormattedMessage |
|
||||
id="pages.login.phoneNumber.invalid" |
|
||||
defaultMessage="手机号格式错误!" |
|
||||
/> |
|
||||
), |
|
||||
}, |
|
||||
]} |
|
||||
/> |
|
||||
<ProFormCaptcha |
|
||||
fieldProps={{ |
|
||||
size: 'large', |
|
||||
prefix: <LockOutlined className={styles.prefixIcon} />, |
|
||||
}} |
|
||||
captchaProps={{ |
|
||||
size: 'large', |
|
||||
}} |
|
||||
placeholder={intl.formatMessage({ |
|
||||
id: 'pages.login.captcha.placeholder', |
|
||||
defaultMessage: '请输入验证码', |
|
||||
})} |
|
||||
captchaTextRender={(timing, count) => { |
|
||||
if (timing) { |
|
||||
return `${count} ${intl.formatMessage({ |
|
||||
id: 'pages.getCaptchaSecondText', |
|
||||
defaultMessage: '获取验证码', |
|
||||
})}`;
|
|
||||
} |
|
||||
return intl.formatMessage({ |
|
||||
id: 'pages.login.phoneLogin.getVerificationCode', |
|
||||
defaultMessage: '获取验证码', |
|
||||
}); |
|
||||
}} |
|
||||
name="captcha" |
|
||||
rules={[ |
|
||||
{ |
|
||||
required: true, |
|
||||
message: ( |
|
||||
<FormattedMessage |
|
||||
id="pages.login.captcha.required" |
|
||||
defaultMessage="请输入验证码!" |
|
||||
/> |
|
||||
), |
|
||||
}, |
|
||||
]} |
|
||||
onGetCaptcha={async (phone) => { |
|
||||
const result = await getFakeCaptcha({ |
|
||||
phone, |
|
||||
}); |
|
||||
if (result === false) { |
|
||||
return; |
|
||||
} |
|
||||
message.success('获取验证码成功!验证码为:1234'); |
|
||||
}} |
|
||||
/> |
|
||||
</> |
|
||||
)} |
|
||||
<div |
|
||||
style={{ |
|
||||
marginBottom: 24, |
|
||||
}} |
|
||||
> |
|
||||
<ProFormCheckbox noStyle name="autoLogin"> |
|
||||
<FormattedMessage id="pages.login.rememberMe" defaultMessage="自动登录" /> |
|
||||
</ProFormCheckbox> |
|
||||
<a |
|
||||
style={{ |
|
||||
float: 'right', |
|
||||
}} |
|
||||
> |
|
||||
<FormattedMessage id="pages.login.forgotPassword" defaultMessage="忘记密码" /> |
|
||||
</a> |
|
||||
</div> |
|
||||
</LoginForm> |
|
||||
</div> |
|
||||
<Footer /> |
|
||||
</div> |
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
export default Login; |
|
||||
Loading…
Reference in new issue