登录
在启动篇中加载全局路由时有一句代码如下,方法返回路径和对应的界面
const routerData = getRouterData(app);
路由配置对象
const routerConfig = {
'/': {
component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')),
},
'/dashboard/analysis': {
component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Analysis')),
},
'/dashboard/monitor': {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')),
},
'/dashboard/workplace': {
component: dynamicWrapper(app, ['project', 'activities', 'chart'], () =>
import('../routes/Dashboard/Workplace')
),
// hideInBreadcrumb: true,
// name: '工作台',
// authority: 'admin',
},
'/test/test': {
component: dynamicWrapper(app, [], () =>
import('../routes/test/NormalLoginForm')
),
// hideInBreadcrumb: true,
// name: '工作台',
// authority: 'admin',
},
'/form/basic-form': {
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/BasicForm')),
},
'/form/step-form': {
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm')),
},
'/form/step-form/result': {
name: '分步表单(完成)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step3')),
},
'/list/card-list': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/CardList')),
},
'/list/search': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/List')),
},
'/result/success': {
component: dynamicWrapper(app, [], () => import('../routes/Result/Success')),
},
'/result/fail': {
component: dynamicWrapper(app, [], () => import('../routes/Result/Error')),
},
'/exception/403': {
component: dynamicWrapper(app, [], () => import('../routes/Exception/403')),
},
'/exception/404': {
component: dynamicWrapper(app, [], () => import('../routes/Exception/404')),
},
'/exception/500': {
component: dynamicWrapper(app, [], () => import('../routes/Exception/500')),
},
'/exception/trigger': {
component: dynamicWrapper(app, ['error'], () =>
import('../routes/Exception/triggerException')
),
},
'/user': {
component: dynamicWrapper(app, [], () => import('../layouts/UserLayout')),
},
'/user/login': {
component: dynamicWrapper(app, ['login'], () => import('../routes/User/Login')),
},
'/user/register': {
component: dynamicWrapper(app, ['register'], () => import('../routes/User/Register')),
},
'/user/register-result': {
component: dynamicWrapper(app, [], () => import('../routes/User/RegisterResult')),
},
// '/user/:id': {
// component: dynamicWrapper(app, [], () => import('../routes/User/SomeComponent')),
// },
};
根据默认路由/user/login找到对应的登录界面app/src/routes/User/Login.js
import React, { Component } from 'react';
import { connect } from 'dva';
import { Link } from 'dva/router';
import { Checkbox, Alert, Icon } from 'antd';
import Login from 'components/Login';
import styles from './Login.less';
const { Tab, UserName, Password, Mobile, Captcha, Submit } = Login;
// 此操作符连接命名空间为login的model层
@connect(({ login, loading }) => ({
login,
submitting: loading.effects['login/login'],
}))
export default class LoginPage extends Component {
state = {
type: 'account',
autoLogin: true,
};
onTabChange = type => {
this.setState({ type });
};
handleSubmit = (err, values) => {
const { type } = this.state;
const { dispatch } = this.props;
if (!err) {
// 调用loigin命名空间下的login方法
dispatch({
type: 'login/login',
payload: {
...values,
type,
},
});
}
};
changeAutoLogin = e => {
this.setState({
autoLogin: e.target.checked,
});
};
renderMessage = content => {
return <Alert style={{ marginBottom: 24 }} message={content} type="error" showIcon />;
};
// 登录界面,可以更改为自定义的UI
render() {
const { login, submitting } = this.props;
const { type, autoLogin } = this.state;
return (
<div className={styles.main}>
<Login defaultActiveKey={type} onTabChange={this.onTabChange} onSubmit={this.handleSubmit}>
<Tab key="account" tab="账户密码登录">
{login.status === 'error' &&
login.type === 'account' &&
!submitting &&
this.renderMessage('账户或密码错误(admin/888888)')}
<UserName name="userName" placeholder="admin/user" />
<Password name="password" placeholder="888888/123456" />
</Tab>
<Tab key="mobile" tab="手机号登录">
{login.status === 'error' &&
login.type === 'mobile' &&
!submitting &&
this.renderMessage('验证码错误')}
<Mobile name="mobile" />
<Captcha name="captcha" />
</Tab>
<div>
<Checkbox checked={autoLogin} onChange={this.changeAutoLogin}>
自动登录
</Checkbox>
<a style={{ float: 'right' }} href="">
忘记密码
</a>
</div>
<Submit loading={submitting}>登录</Submit>
<div className={styles.other}>
其他登录方式
<Icon className={styles.icon} type="alipay-circle" />
<Icon className={styles.icon} type="taobao-circle" />
<Icon className={styles.icon} type="weibo-circle" />
<Link className={styles.register} to="/user/register">
注册账户
</Link>
</div>
</Login>
</div>
);
}
}
登录处理
文件路径:app/src/model/login.js
import { routerRedux } from 'dva/router';
import { stringify } from 'qs';
import { fakeAccountLogin } from '../services/api';
import { setAuthority } from '../utils/authority';
import { reloadAuthorized } from '../utils/Authorized';
import { getPageQuery } from '../utils/utils';
export default {
namespace: 'login',
state: {
status: undefined,
},
effects: {
*login({ payload }, { call, put }) {
const response = yield call(fakeAccountLogin, payload);
yield put({
type: 'changeLoginStatus',
payload: response,
});
// Login successfully
if (response.status === 'ok') {
reloadAuthorized();
const urlParams = new URL(window.location.href);
const params = getPageQuery();
let { redirect } = params;
if (redirect) {
const redirectUrlParams = new URL(redirect);
if (redirectUrlParams.origin === urlParams.origin) {
redirect = redirect.substr(urlParams.origin.length);
if (redirect.startsWith('/#')) {
redirect = redirect.substr(2);
}
} else {
window.location.href = redirect;
return;
}
}
yield put(routerRedux.replace(redirect || '/'));
}
},
*logout(_, { put }) {
yield put({
type: 'changeLoginStatus',
payload: {
status: false,
currentAuthority: 'guest',
},
});
reloadAuthorized();
yield put(
routerRedux.push({
pathname: '/user/login',
search: stringify({
redirect: window.location.href,
}),
})
);
},
},
reducers: {
changeLoginStatus(state, { payload }) {
setAuthority(payload.currentAuthority);
return {
...state,
status: payload.status,
type: payload.type,
};
},
},
};
调用rest接口
文件目录:app/src/services/api.js
// 方法名:fakeAccountLogin
export async function fakeAccountLogin(params) {
return request('/api/login/account', {
method: 'POST',
body: params,
});
}
登录默认路径
ant登录主要是看有没有上次登录地址,如果没有则重定向根目录/,也就是会定向到路由数组的第一个值
在登录完成处理中的定义返回的首次登录路由,更改如下:
// Login successfully
if (response.status === 'ok') {
reloadAuthorized();
const urlParams = new URL(window.location.href);
const params = getPageQuery();
// gxg 如果是用户登录时返回登录路径,则以用户登录路径为准
let defaultPath = response.path;
if(defaultPath){
yield put(
routerRedux.push({
pathname: defaultPath,
search: stringify({
redirect: window.location.href,
}),
})
);
}else{
let { redirect } = params;
if (redirect) {
const redirectUrlParams = new URL(redirect);
if (redirectUrlParams.origin === urlParams.origin) {
redirect = redirect.substr(urlParams.origin.length);
if (redirect.startsWith('/#')) {
redirect = redirect.substr(2);
}
} else {
window.location.href = redirect;
return;
}
}
// 重定向路径
yield put(routerRedux.replace(redirect || '/'));
}
}
.roadhogrc.mock.js模拟rest api要进行更改
'POST /api/login/account': (req, res) => {
const { password, userName, type } = req.body;
if (password === '888888' && userName === 'admin') {
res.send({
status: 'ok',
type,
currentAuthority: 'admin',
path: '/profile/basic',
});
return;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/gosenkle/article/details/81627611
网友评论