本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
一、页面版式修改
/pages/User/Login/index.tsx 登陆页面组件路径
那么我们需要做如下操作改造登陆页面:
-
〈Lang /〉组件是为了实现国际化,可注释掉
-
修改登陆框的主标题和子标题
-
将通过用户密码登陆和手机号登陆根据项目实际情况修改成只支持帐密登陆
-
将忘记密码修改成“ 注册用户” 的连接,点击跳转到/user/register登陆页面
-
注释掉下方的其他登陆方式栏目
最终实现的登陆页面效果如下:
由于此页面主要是调用了ant design pro的模块LoginForm ,具体修改的模块见下方代码。
<div className={containerClassName}>
{/*@umijs/plugin-helmet插件,实现动态修改HTML文档标签*/}
<Helmet>
<title>
{intl.formatMessage({
id: 'menu.login',
defaultMessage: '登录页',
})}
- {Settings.title}
</title>
</Helmet>
{/*实现国际化文字*/}
{/*<Lang/>*/}
<div
style={{
flex: '1',
padding: '32px 0',
}}
>
<LoginForm
contentStyle={{
minWidth: 280,
maxWidth: '75vw',
}}
logo={<img alt="logo" src="/logo.svg"/>}
// title="Ant Design"
title="登陆"
// subTitle={intl.formatMessage({id: 'pages.layouts.userLayout.title'})}
subTitle='基于React+ant design Pro +Ts的企业级应用'
initialValues={{
autoLogin: true,
}}
// actions={[
// <FormattedMessage
// key="loginWith"
// id="pages.login.loginWith"
// defaultMessage="其他登录方式"
// />,
// <ActionIcons key="icons"/>,
// ]}
onFinish={async (values) => {
await handleSubmit(values as API.LoginParams);
}}
>
{/*<Tabs*/}
{/* activeKey={type}*/}
{/* onChange={setType}*/}
{/* centered*/}
{/* items={[*/}
{/* {*/}
{/* key: 'account',*/}
{/* label: intl.formatMessage({*/}
{/* id: 'pages.login.accountLogin.tab',*/}
{/* defaultMessage: '账户密码登录',*/}
{/* }),*/}
{/* },*/}
{/* {*/}
{/* key: 'mobile',*/}
{/* label: intl.formatMessage({*/}
{/* id: 'pages.login.phoneLogin.tab',*/}
{/* defaultMessage: '手机号登录',*/}
{/* }),*/}
{/* },*/}
{/* ]}*/}
{/*/>*/}
{status === 'error' && loginType === 'account' && (
<LoginMessage
content={intl.formatMessage({
id: 'pages.login.accountLogin.errorMessage',
defaultMessage: '账户或密码错误(admin/ant.design)',
})}
/>
)}
{type === 'account' && (
<>
<ProFormText
name="identifier"
fieldProps={{
size: 'large',
prefix: <UserOutlined/>,
}}
placeholder={intl.formatMessage({
id: 'pages.login.identifier.placeholder',
defaultMessage: '请输入用户名',
})}
rules={[ { required: true, message: ( <FormattedMessage id="pages.login.identifier.required" defaultMessage="请输入用户名!" /> ), }, ]}
/>
<ProFormText.Password
name="password"
fieldProps={{
size: 'large',
prefix: <LockOutlined/>,
}}
placeholder={intl.formatMessage({
id: 'pages.login.password.placeholder',
defaultMessage: '请输入密码',
})}
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/>,*/}
{/* }}*/}
{/* 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/>,*/}
{/* }}*/}
{/* 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) {*/}
{/* return;*/}
{/* }*/}
{/* message.success('获取验证码成功!验证码为:1234');*/}
{/* }}*/}
{/* />*/}
{/* </>*/}
{/*)}*/}
<div
style={{
marginBottom: 24,
}}
>
<ProFormCheckbox noStyle name="autoLogin">
<FormattedMessage id="pages.login.rememberMe" defaultMessage="自动登录"/>
</ProFormCheckbox>
<a
style={{
float: 'right',
}}
// 点击跳转注册页面
onClick={() =>
history.push({
pathname: '/user/register',
})}
>
注册用户
</a>
</div>
</LoginForm>
</div>
<Footer/>
</div>
二、对接Strapi实现用户登陆
接下来要对接Strapi登陆模块,主要是点击登陆按钮,触发strapi的login接口,具体为点击登陆按钮后触发handleSubmit函数,此函数逻辑为将用户输入到帐号/密码传入login登陆函数,然后将返回到jwt和user保存到localStorage中去。此后触发fetchUserInfo函数,然后重定向到首页
const handleSubmit = async (values: API.LoginParams) => {
try {
const msg = await login({identifier: values.identifier, password: values.password});
message.success('登陆成功')
localStorage.setItem("token", msg.jwt);
localStorage.setItem("user", msg.user);
await fetchUserInfo();
history.push( '/');
return;
} catch (error) {
const defaultLoginFailureMessage = intl.formatMessage({
id: 'pages.login.failure',
defaultMessage: '登录失败,请重试!',
});
message.error(defaultLoginFailureMessage);
}
};
/** 登录接口 POST /api/login/account */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
return request<API.LoginResult>('/api/auth/local', {
method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// },
data: body,
...(options || {}),
});
}
const fetchUserInfo = async () => {
//修改成从local storage获取用户信息
const userInfo = localStorage.getItem('user')
if (userInfo) {
// @ts-ignore
setInitialState({currentUser: userInfo})
}
};
因此可实现登陆效果