Commit 032b6c96 authored by 前端-许佳敏's avatar 前端-许佳敏

加入权限控制

parent e9e3714b
...@@ -36,10 +36,14 @@ const router = [ ...@@ -36,10 +36,14 @@ const router = [
component: '@/pages/home', component: '@/pages/home',
icon: 'BarChartOutlined' icon: 'BarChartOutlined'
}, },
...routeList ...routeList,
{
path: '/noAuth',
hidePageHeader: true,
component: '@/pages/403'
}
] ]
}, },
] ]
export default router export default router
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
"mobx": "^5.15.4", "mobx": "^5.15.4",
"mobx-react": "^6.2.2", "mobx-react": "^6.2.2",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"query-string": "^6.13.1",
"react": "^16.12.0", "react": "^16.12.0",
"react-dom": "^16.12.0", "react-dom": "^16.12.0",
"umi": "^3.2.0", "umi": "^3.2.0",
......
...@@ -8,12 +8,19 @@ import '@/global/styles/global.less'; // 导入全局样式 ...@@ -8,12 +8,19 @@ import '@/global/styles/global.less'; // 导入全局样式
// 默认引入所有的ant样式, 不引入css因为无法做到变量覆盖 // 默认引入所有的ant样式, 不引入css因为无法做到变量覆盖
import 'antd/dist/antd.less'; import 'antd/dist/antd.less';
import { setup } from '@formily/antd-components'; import { setup } from '@formily/antd-components';
import { getAuth, setAuth, setRouters } from './utils/auth'; import { getAuth, setAuth, setRouters, removeAuth, removeRouters, asyncRouter, getRouters } from './utils/auth';
import { PublicApi } from './services/api'; import { PublicApi } from './services/api';
import { isDev } from './constants';
import queryString from 'query-string';
setup(); setup();
let extraRoutes: never[] = []; let extraRoutes: never[] = [];
const whiteLists = [
'/',
'/login',
'/noAuth'
]
/** /**
* @description 配置函数,对已配置的路由做修改, 一般与render函数一起结合可根据接口动态配置路由 * @description 配置函数,对已配置的路由做修改, 一般与render函数一起结合可根据接口动态配置路由
* @author xjm * @author xjm
...@@ -28,9 +35,12 @@ let extraRoutes: never[] = []; ...@@ -28,9 +35,12 @@ let extraRoutes: never[] = [];
* }); * });
* *
*/ */
// export function patchRoutes({ routes }: IRoutes) { export function patchRoutes({ routes }: IRoutes) {
// routes.concat(extraRoutes as []) if (isDev) {
// } return;
}
asyncRouter(getRouters(), routes)
}
/** /**
* @description 用于渲染前所做的事, 比如动态路由,权限校验等 * @description 用于渲染前所做的事, 比如动态路由,权限校验等
...@@ -42,17 +52,25 @@ export function render(oldRender:Function) { ...@@ -42,17 +52,25 @@ export function render(oldRender:Function) {
const authInfo = getAuth() const authInfo = getAuth()
if (authInfo) { if (authInfo) {
PublicApi.getMemberManageLoginReget().then(res => { PublicApi.getMemberManageLoginReget().then(res => {
const { data } = res const { data, code } = res
setAuth({ if (code === 1000) {
memberId: data.memberId, setAuth({
userId: data.userId, memberId: data.memberId,
token: data.token userId: data.userId,
}) token: data.token
setRouters(data.urls) })
setRouters(data.urls)
} else {
removeAuth()
removeRouters()
history.push('/login')
}
oldRender()
}) })
} else {
oldRender()
} }
oldRender()
} }
/** /**
...@@ -62,9 +80,39 @@ export function render(oldRender:Function) { ...@@ -62,9 +80,39 @@ export function render(oldRender:Function) {
* @export * @export
* @param {*} { routes, matchedRoutes, location, action } * @param {*} { routes, matchedRoutes, location, action }
*/ */
// export function onRouteChange({ routes, matchedRoutes, location, action }) { export function onRouteChange({ routes, matchedRoutes, location, action }) {
// console.log(routes, matchedRoutes, location, action) console.log('onRouteChange')
// }
// if (isDev) {
// return;
// }
if (whiteLists.includes(location.pathname)) return;
const routeAuthUrls = getRouters()
// 是否登录
if (getAuth()) {
const { query, pathname } = location
// 固定配置, 出现此参数说明需携带参数校验权限路由
if (query.page_type && routeAuthUrls.find(authPath => {
const parseUrl = queryString.parseUrl(authPath)
const { query: selfQuery, url } = parseUrl
// 当页面出现参数page_type时, 需进入深度校验, 即对应的参数和路径匹配
return url === pathname && selfQuery.page_type === query.page_type
})) {
// 深度匹配成功, 可正常访问
return ;
}
// 是否在路由权限列表里
if (routeAuthUrls.includes(pathname)) {
return ;
}
// 无权限访问时
history.replace('/noAuth')
} else {
history.replace('/login')
}
}
/** /**
* @description 可对最外层做容器包裹 * @description 可对最外层做容器包裹
......
export const NOT_CHANGE_VALUE = 'hello, world' export const NOT_CHANGE_VALUE = 'hello, world'
// 本地环境跳过权限校验 // 本地环境跳过权限校验
export const isDev = process.env.NODE_ENV === "development" export const isDev = process.env.NODE_ENV === "development"
\ No newline at end of file // export const isDev = false
\ No newline at end of file
...@@ -7,7 +7,7 @@ const { onFormInit$ } = FormEffectHooks ...@@ -7,7 +7,7 @@ const { onFormInit$ } = FormEffectHooks
* @param name 待处理的表单路径 * @param name 待处理的表单路径
* @param service 触发的异步函数, 需返回一个{label: any, value: any}形式的数组 * @param service 触发的异步函数, 需返回一个{label: any, value: any}形式的数组
*/ */
export const useAsyncInitSelect = (name: string[], service?: () => Promise<any>) => { export const useAsyncInitSelect = (name: string[], service: () => Promise<any>) => {
const { dispatch, setFieldState } = createFormActions() const { dispatch, setFieldState } = createFormActions()
const linkage = useLinkageUtils() const linkage = useLinkageUtils()
onFormInit$().subscribe(() => { onFormInit$().subscribe(() => {
...@@ -21,7 +21,7 @@ export const useAsyncInitSelect = (name: string[], service?: () => Promise<any>) ...@@ -21,7 +21,7 @@ export const useAsyncInitSelect = (name: string[], service?: () => Promise<any>)
linkage.enum(v, res[v]) linkage.enum(v, res[v])
}) })
//请求结束可以dispatch一个自定义事件收尾,方便后续针对该事件做联动 //请求结束可以dispatch一个自定义事件收尾,方便后续针对该事件做联动
dispatch('requestAsyncSelect', { dispatch && dispatch('requestAsyncSelect', {
name, name,
payload: res payload: res
}) })
......
...@@ -6,6 +6,8 @@ import MenuUtil from '@/utils/menu' ...@@ -6,6 +6,8 @@ import MenuUtil from '@/utils/menu'
import { useIntl } from 'umi' import { useIntl } from 'umi'
import { MenuDataItem } from '@/utils/typing' import { MenuDataItem } from '@/utils/typing'
import { getMatchMenu } from '@umijs/route-utils' import { getMatchMenu } from '@umijs/route-utils'
import { isDev } from '@/constants'
import { getRouters } from '@/utils/auth'
// 获取当前的选中菜单 // 获取当前的选中菜单
export const getSelectedMenuKeys = ( export const getSelectedMenuKeys = (
pathname: string, pathname: string,
...@@ -38,7 +40,14 @@ const MenuSlider = (props) => { ...@@ -38,7 +40,14 @@ const MenuSlider = (props) => {
const menuUtil = new MenuUtil({ const menuUtil = new MenuUtil({
formatMessage, formatMessage,
}) })
console.log(menuData)
// 本地可无权限访问所有路由
if (!isDev) {
menuData
}
const dispatchRoutes = menuData.filter(v => getRouters().includes(v.path))
return ( return (
<Slider className={styles.lxSlider} collapsed={props.collapseState} width={240}> <Slider className={styles.lxSlider} collapsed={props.collapseState} width={240}>
<Logo /> <Logo />
...@@ -49,7 +58,7 @@ const MenuSlider = (props) => { ...@@ -49,7 +58,7 @@ const MenuSlider = (props) => {
defaultOpenKeys={defaultOpenKeysRef.current} defaultOpenKeys={defaultOpenKeysRef.current}
className={styles.lxSliderMenu} className={styles.lxSliderMenu}
> >
{menuUtil.getNavMenuItems(menuData)} {menuUtil.getNavMenuItems(dispatchRoutes)}
</Menu> </Menu>
</Slider> </Slider>
) )
......
import React from 'react';
import { history } from 'umi';
import { Button, Row, Col } from 'antd';
import { GlobalConfig } from '@/global/config';
import styles from './index.less'
import Img from '../../static/illus.png'
const NoFoundPage: React.FC<{}> = () => {
const handleReturn = () => {
history.replace('/home')
}
return (
<div className={styles.wrapper}>
<div className={styles.errorBox}>
<Row>
<Col span={12}>
<div className={styles.desc}>
<h1>您当前无权访问该页面</h1>
<Button
type="primary"
size="large"
style={{marginTop: 100}}
onClick={handleReturn}
>回到首页</Button>
</div>
</Col>
<Col span={12}>
<img className={styles.image} src={Img} alt="数商云服务"/>
</Col>
</Row>
</div>
</div>
)
}
export default NoFoundPage;
.normal {
}
.title {
font-size: 24px;
color: #666;
}
// 500 error
// .wrapper{
// }
.errorBox{
width: 100%;
.desc{
width: 400px;
margin: 200px auto 0;
}
.image {
display: block;
width: 100%;
height: 100%;
}
}
...@@ -87,7 +87,7 @@ class Index extends Component<{}, IndexState> { ...@@ -87,7 +87,7 @@ class Index extends Component<{}, IndexState> {
token: data.token token: data.token
}) })
setRouters(data.urls) setRouters(data.urls)
history.push('/') window.location.href = '/home'
}).catch(error => { }).catch(error => {
console.error(error) console.error(error)
}); });
......
import { isDev } from '@/constants'
export interface AuthInfo { export interface AuthInfo {
userId: number, userId: number,
memberId: number, memberId: number,
...@@ -10,20 +12,21 @@ export const setAuth = (info: AuthInfo) => { ...@@ -10,20 +12,21 @@ export const setAuth = (info: AuthInfo) => {
export const getAuth = () => { export const getAuth = () => {
try { try {
return JSON.parse(window.localStorage.getItem('auth') || '') || null const localAuth = window.localStorage.getItem('auth')
return localAuth ? JSON.parse(localAuth) : null
} catch (error) { } catch (error) {
return {} return {}
} }
} }
export const setRouters = (routers: any[]) => { export const setRouters = (routers: any[]) => {
window.sessionStorage.setItem('rt', JSON.stringify(routers)) window.sessionStorage.setItem('rt', JSON.stringify(routers))
} }
export const getRouters = () => { export const getRouters = () => {
try { try {
return JSON.parse(window.sessionStorage.getItem('rt') || '') || [] const sessionRt = window.sessionStorage.getItem('rt')
return sessionRt ? JSON.parse(sessionRt) : []
} catch (error) { } catch (error) {
return [] return []
} }
......
...@@ -3,7 +3,7 @@ import responseCode from '@/constants/responseCode' ...@@ -3,7 +3,7 @@ import responseCode from '@/constants/responseCode'
import { IRequestError, IRequestSuccess } from '..'; import { IRequestError, IRequestSuccess } from '..';
import { history } from 'umi' import { history } from 'umi'
import { message } from 'antd' import { message } from 'antd'
import { getAuth, removeAuth } from './auth'; import { getAuth, removeAuth, removeRouters } from './auth';
import { isDev } from '@/constants'; import { isDev } from '@/constants';
export type CtlType = 'none' | 'message' export type CtlType = 'none' | 'message'
...@@ -96,6 +96,7 @@ class ApiRequest { ...@@ -96,6 +96,7 @@ class ApiRequest {
return ; return ;
} }
removeAuth() removeAuth()
removeRouters()
history.replace('/login') history.replace('/login')
return false return false
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment