diff --git a/src/bootstrap.js b/src/bootstrap.js index 6f779af..a101681 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -1,5 +1,6 @@ -import {loadRoutes, loginGuard, authorityGuard} from '@/utils/routerUtil' +import {loadRoutes, loadGuards} from '@/utils/routerUtil' import {loadInterceptors} from '@/utils/request' +import guards from '@/router/guards' import interceptors from '@/utils/axios-interceptors' /** @@ -14,9 +15,8 @@ function bootstrap({router, store, i18n, message}) { loadInterceptors(interceptors, {router, store, i18n, message}) // 加载路由 loadRoutes({router, store, i18n}) - // 添加路由守卫 - loginGuard(router) - authorityGuard(router, store) + // 加载路由守卫 + loadGuards(guards, {router, store, i18n, message}) } export default bootstrap diff --git a/src/router/config.async.js b/src/router/async/config.async.js similarity index 100% rename from src/router/config.async.js rename to src/router/async/config.async.js diff --git a/src/router/router.map.js b/src/router/async/router.map.js similarity index 100% rename from src/router/router.map.js rename to src/router/async/router.map.js diff --git a/src/router/guards.js b/src/router/guards.js new file mode 100644 index 0000000..b8719f9 --- /dev/null +++ b/src/router/guards.js @@ -0,0 +1,44 @@ +import {hasPermission, hasRole} from '@/utils/authority-utils' +import {loginIgnore} from '@/router/index' +import {checkAuthorization} from '@/utils/request' + +/** + * 登录守卫 + * @param to + * @param form + * @param next + * @param options + */ +const loginGuard = (to, from, next, options) => { + const {message} = options + if (!loginIgnore.includes(to) && !checkAuthorization()) { + message.warning('登录已失效,请重新登录') + next({path: '/login'}) + } else { + next() + } +} + +/** + * 权限守卫 + * @param to + * @param form + * @param next + * @param options + */ +const authorityGuard = (to, from, next, options) => { + const {store, message} = options + const permissions = store.getters['account/permissions'] + const roles = store.getters['account/roles'] + if (!hasPermission(to, permissions) && !hasRole(to, roles)) { + message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`) + next({path: '/403'}) + } else { + next() + } +} + +export default { + beforeEach: [loginGuard, authorityGuard], + afterEach: [] +} diff --git a/src/router/index.js b/src/router/index.js index 06b0ea3..3bdcc3c 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -24,7 +24,7 @@ const loginIgnore = { * @returns {VueRouter} */ function initRouter(isAsync) { - const options = isAsync ? require('./config.async').default : require('./config').default + const options = isAsync ? require('./async/config.async').default : require('./config').default formatAuthority(options.routes) return new Router(options) } diff --git a/src/utils/authority-utils.js b/src/utils/authority-utils.js new file mode 100644 index 0000000..48dd2ea --- /dev/null +++ b/src/utils/authority-utils.js @@ -0,0 +1,50 @@ +/** + * 判断是否有路由的权限 + * @param route 路由 + * @param permissions 用户权限集合 + * @returns {boolean|*} + */ +function hasPermission(route, permissions) { + const authority = route.meta.authority || '*' + let required = '*' + if (typeof authority === 'string') { + required = authority + } else if (typeof authority === 'object') { + required = authority.permission + } + return required === '*' || (permissions && permissions.findIndex(item => item === required || item.id === required) !== -1) +} + +/** + * 判断是否有路由需要的角色 + * @param route 路由 + * @param roles 用户角色集合 + */ +function hasRole(route, roles) { + const authority = route.meta.authority || '*' + let required = undefined + if (typeof authority === 'object') { + required = authority.role + } + return authority === '*' || hasAnyRole(required, roles) +} + +/** + * 判断是否有需要的任意一个角色 + * @param required {String | Array[String]} 需要的角色,可以是单个角色或者一个角色数组 + * @param roles 拥有的角色 + * @returns {boolean} + */ +function hasAnyRole(required, roles) { + if (!required) { + return false + } else if(Array.isArray(required)) { + return roles.findIndex(role => { + return required.findIndex(item => item === role || item === role.id) !== -1 + }) !== -1 + } else { + return roles.findIndex(role => role === required || role.id === required) !== -1 + } +} + +export {hasPermission, hasRole} diff --git a/src/utils/routerUtil.js b/src/utils/routerUtil.js index 39355a1..7fc9160 100644 --- a/src/utils/routerUtil.js +++ b/src/utils/routerUtil.js @@ -1,8 +1,6 @@ -import routerMap from '@/router/router.map' +import routerMap from '@/router/async/router.map' import {mergeI18nFromRoutes} from '@/utils/i18n' import Router from 'vue-router' -import {loginIgnore} from '@/router' -import {checkAuthorization} from '@/utils/request' /** * 根据 路由配置 和 路由组件注册 解析路由 @@ -97,86 +95,6 @@ function mergeRoutes(target, source) { return Object.values(routesMap) } -/** - * 登录守卫 - * @param router 应用路由实例 - */ -function loginGuard(router) { - router.beforeEach((to, from, next) => { - if (!loginIgnore.includes(to) && !checkAuthorization()) { - next({path: '/login'}) - } else { - next() - } - }) -} - -/** - * 权限守卫 - * @param router 应用路由实例 - * @param store 应用的 vuex.store 实例 - */ -function authorityGuard(router, store) { - router.beforeEach((to, form, next) => { - const permissions = store.getters['account/permissions'] - const roles = store.getters['account/roles'] - if (!hasPermission(to, permissions) && !hasRole(to, roles)) { - next({path: '/403'}) - } else { - next() - } - }) -} - -/** - * 判断是否有路由的权限 - * @param route 路由 - * @param permissions 用户权限集合 - * @returns {boolean|*} - */ -function hasPermission(route, permissions) { - const authority = route.meta.authority || '*' - let required = '*' - if (typeof authority === 'string') { - required = authority - } else if (typeof authority === 'object') { - required = authority.permission - } - return required === '*' || (permissions && permissions.findIndex(item => item === required || item.id === required) !== -1) -} - -/** - * 判断是否有路由需要的角色 - * @param route 路由 - * @param roles 用户角色集合 - */ -function hasRole(route, roles) { - const authority = route.meta.authority || '*' - let required = undefined - if (typeof authority === 'object') { - required = authority.role - } - return authority === '*' || hasAnyRole(required, roles) -} - -/** - * 判断是否有需要的任意一个角色 - * @param required {String | Array[String]} 需要的角色,可以是单个角色或者一个角色数组 - * @param roles 拥有的角色 - * @returns {boolean} - */ -function hasAnyRole(required, roles) { - if (!required) { - return false - } else if(Array.isArray(required)) { - return roles.findIndex(role => { - return required.findIndex(item => item === role || item === role.id) !== -1 - }) !== -1 - } else { - return roles.findIndex(role => role === required || role.id === required) !== -1 - } -} - /** * 格式化路由的权限配置 * @param routes @@ -222,4 +140,24 @@ function getI18nKey(path) { return keys.join('.') } -export {parseRoutes, loadRoutes, loginGuard, authorityGuard, formatAuthority, getI18nKey} +/** + * 加载导航守卫 + * @param guards + * @param options + */ +function loadGuards(guards, options) { + const {beforeEach, afterEach} = guards + const {router} = options + beforeEach.forEach(guard => { + if (guard && typeof guard === 'function') { + router.beforeEach((to, from, next) => guard(to, from, next, options)) + } + }) + afterEach.forEach(guard => { + if (guard && typeof guard === 'function') { + router.afterEach((to, from) => guard(to, from, options)) + } + }) +} + +export {parseRoutes, loadRoutes, formatAuthority, getI18nKey, loadGuards}