登录
在启动篇中加载全局路由时有一句代码如下,方法返回路径和对应的界面
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/info': {
name: '分步表单(填写转账信息)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step1')),
},
'/form/step-form/confirm': {
name: '分步表单(确认转账信息)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step2')),
},
'/form/step-form/result': {
name: '分步表单(完成)',
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/StepForm/Step3')),
},
'/form/advanced-form': {
component: dynamicWrapper(app, ['form'], () => import('../routes/Forms/AdvancedForm')),
},
'/list/table-list': {
component: dynamicWrapper(app, ['rule'], () => import('../routes/List/TableList')),
},
'/list/basic-list': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/BasicList')),
},
'/list/card-list': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/CardList')),
},
'/list/search': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/List')),
},
'/list/search/projects': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Projects')),
},
'/list/search/applications': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Applications')),
},
'/list/search/articles': {
component: dynamicWrapper(app, ['list'], () => import('../routes/List/Articles')),
},
'/profile/basic': {
component: dynamicWrapper(app, ['profile'], () => import('../routes/Profile/BasicProfile')),
},
'/profile/advanced': {
component: dynamicWrapper(app, ['profile'], () =>
import('../routes/Profile/AdvancedProfile')
),
},
'/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 ;
};
// 登录界面,可以更改为自定义的UI
render() {
const { login, submitting } = this.props;
const { type, autoLogin } = this.state;
return (
{login.status === 'error' &&
login.type === 'account' &&
!submitting &&
this.renderMessage('账户或密码错误(admin/888888)')}
{login.status === 'error' &&
login.type === 'mobile' &&
!submitting &&
this.renderMessage('验证码错误')}
自动登录
忘记密码
登录
其他登录方式
注册账户
);
}
}
登录处理
文件路径: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;
}