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