Browse Source

🏰 chore: fix deploy error

pull/8726/head
chenshuai2144 5 years ago
parent
commit
39560f0513
  1. 114
      src/pages/User/Login/index.less
  2. 318
      src/pages/User/Login/index.tsx

114
src/pages/User/Login/index.less

@ -0,0 +1,114 @@
@import '~antd/es/style/themes/default.less';
.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://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg');
background-repeat: no-repeat;
background-position: center 110px;
background-size: 100%;
}
.content {
padding: 32px 0 24px;
}
}
.top {
text-align: center;
}
.header {
height: 44px;
line-height: 44px;
a {
text-decoration: none;
}
}
.logo {
height: 44px;
margin-right: 16px;
vertical-align: top;
}
.title {
position: relative;
top: 2px;
color: @heading-color;
font-weight: 600;
font-size: 33px;
font-family: Avenir, 'Helvetica Neue', Arial, Helvetica, sans-serif;
}
.desc {
margin-top: 12px;
margin-bottom: 40px;
color: @text-color-secondary;
font-size: @font-size-base;
}
.main {
width: 328px;
margin: 0 auto;
@media screen and (max-width: @screen-sm) {
width: 95%;
max-width: 328px;
}
:global {
.@{ant-prefix}-tabs-nav-list {
margin: auto;
font-size: 16px;
}
}
.icon {
margin-left: 16px;
color: rgba(0, 0, 0, 0.2);
font-size: 24px;
vertical-align: middle;
cursor: pointer;
transition: color 0.3s;
&:hover {
color: @primary-color;
}
}
.other {
margin-top: 24px;
line-height: 22px;
text-align: left;
.register {
float: right;
}
}
.prefixIcon {
color: @primary-color;
font-size: @font-size-base;
}
}

318
src/pages/User/Login/index.tsx

@ -0,0 +1,318 @@
import {
AlipayCircleOutlined,
LockOutlined,
MobileOutlined,
TaobaoCircleOutlined,
UserOutlined,
WeiboCircleOutlined,
} from '@ant-design/icons';
import { Alert, Space, message, Tabs } from 'antd';
import React, { useState } from 'react';
import ProForm, { ProFormCaptcha, ProFormCheckbox, ProFormText } from '@ant-design/pro-form';
import { useIntl, Link, history, FormattedMessage, SelectLang, useModel } from 'umi';
import Footer from '@/components/Footer';
import { login } from '@/services/ant-design-pro/api';
import { getFakeCaptcha } from '@/services/ant-design-pro/login';
import styles from './index.less';
const LoginMessage: React.FC<{
content: string;
}> = ({ content }) => (
<Alert
style={{
marginBottom: 24,
}}
message={content}
type="error"
showIcon
/>
);
/** 此方法会跳转到 redirect 参数所在的位置 */
const goto = () => {
if (!history) return;
setTimeout(() => {
const { query } = history.location;
const { redirect } = query as { redirect: string };
history.push(redirect || '/');
}, 10);
};
const Login: React.FC = () => {
const [submitting, setSubmitting] = useState(false);
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) {
setInitialState({
...initialState,
currentUser: userInfo,
});
}
};
const handleSubmit = async (values: API.LoginParams) => {
setSubmitting(true);
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();
goto();
return;
}
// 如果失败去设置用户错误信息
setUserLoginState(msg);
} catch (error) {
const defaultloginFailureMessage = intl.formatMessage({
id: 'pages.login.failure',
defaultMessage: '登录失败,请重试!',
});
message.error(defaultloginFailureMessage);
}
setSubmitting(false);
};
const { status, type: loginType } = userLoginState;
return (
<div className={styles.container}>
<div className={styles.lang} data-lang>
{SelectLang && <SelectLang />}
</div>
<div className={styles.content}>
<div className={styles.top}>
<div className={styles.header}>
<Link to="/">
<img alt="logo" className={styles.logo} src="/logo.svg" />
<span className={styles.title}>Ant Design</span>
</Link>
</div>
<div className={styles.desc}>
{intl.formatMessage({ id: 'pages.layouts.userLayout.title' })}
</div>
</div>
<div className={styles.main}>
<ProForm
initialValues={{
autoLogin: true,
}}
submitter={{
searchConfig: {
submitText: intl.formatMessage({
id: 'pages.login.submit',
defaultMessage: '登录',
}),
},
render: (_, dom) => dom.pop(),
submitButtonProps: {
loading: submitting,
size: 'large',
style: {
width: '100%',
},
},
}}
onFinish={async (values) => {
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>
</ProForm>
<Space className={styles.other}>
<FormattedMessage id="pages.login.loginWith" defaultMessage="其他登录方式" />
<AlipayCircleOutlined className={styles.icon} />
<TaobaoCircleOutlined className={styles.icon} />
<WeiboCircleOutlined className={styles.icon} />
</Space>
</div>
</div>
<Footer />
</div>
);
};
export default Login;
Loading…
Cancel
Save