mirror of
https://github.com/iczer/vue-antd-admin
synced 2025-04-06 04:00:06 +08:00
refactor: config of async router and guards of router; 🌟
重构:异步路由配置和路由守卫配置;
This commit is contained in:
parent
75f53df1e4
commit
192d4f243d
8
src/bootstrap.js
vendored
8
src/bootstrap.js
vendored
@ -1,5 +1,6 @@
|
|||||||
import {loadRoutes, loginGuard, authorityGuard} from '@/utils/routerUtil'
|
import {loadRoutes, loadGuards} from '@/utils/routerUtil'
|
||||||
import {loadInterceptors} from '@/utils/request'
|
import {loadInterceptors} from '@/utils/request'
|
||||||
|
import guards from '@/router/guards'
|
||||||
import interceptors from '@/utils/axios-interceptors'
|
import interceptors from '@/utils/axios-interceptors'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,9 +15,8 @@ function bootstrap({router, store, i18n, message}) {
|
|||||||
loadInterceptors(interceptors, {router, store, i18n, message})
|
loadInterceptors(interceptors, {router, store, i18n, message})
|
||||||
// 加载路由
|
// 加载路由
|
||||||
loadRoutes({router, store, i18n})
|
loadRoutes({router, store, i18n})
|
||||||
// 添加路由守卫
|
// 加载路由守卫
|
||||||
loginGuard(router)
|
loadGuards(guards, {router, store, i18n, message})
|
||||||
authorityGuard(router, store)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default bootstrap
|
export default bootstrap
|
||||||
|
154
src/router/async/router.map.js
Normal file
154
src/router/async/router.map.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// 视图组件
|
||||||
|
const view = {
|
||||||
|
tabs: () => import('@/layouts/tabs'),
|
||||||
|
blank: () => import('@/layouts/BlankView'),
|
||||||
|
page: () => import('@/layouts/PageView')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 路由组件注册
|
||||||
|
const routerMap = {
|
||||||
|
login: {
|
||||||
|
authority: '*',
|
||||||
|
path: '/login',
|
||||||
|
component: () => import('@/pages/login')
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
path: '/',
|
||||||
|
name: '首页',
|
||||||
|
redirect: '/login',
|
||||||
|
component: view.tabs
|
||||||
|
},
|
||||||
|
dashboard: {
|
||||||
|
name: 'Dashboard',
|
||||||
|
component: view.blank
|
||||||
|
},
|
||||||
|
workplace: {
|
||||||
|
name: '工作台',
|
||||||
|
component: () => import('@/pages/dashboard/workplace')
|
||||||
|
},
|
||||||
|
analysis: {
|
||||||
|
name: '分析页',
|
||||||
|
component: () => import('@/pages/dashboard/analysis')
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
name: '表单页',
|
||||||
|
icon: 'form',
|
||||||
|
component: view.page
|
||||||
|
},
|
||||||
|
basicForm: {
|
||||||
|
path: 'basic',
|
||||||
|
name: '基础表单',
|
||||||
|
component: () => import('@/pages/form/basic')
|
||||||
|
},
|
||||||
|
stepForm: {
|
||||||
|
path: 'step',
|
||||||
|
name: '分步表单',
|
||||||
|
component: () => import('@/pages/form/step')
|
||||||
|
},
|
||||||
|
advanceForm: {
|
||||||
|
path: 'advance',
|
||||||
|
name: '高级表单',
|
||||||
|
component: () => import('@/pages/form/advance')
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
name: '列表页',
|
||||||
|
icon: 'table',
|
||||||
|
component: view.page
|
||||||
|
},
|
||||||
|
queryList: {
|
||||||
|
path: 'query',
|
||||||
|
name: '查询表格',
|
||||||
|
component: () => import('@/pages/list/QueryList')
|
||||||
|
},
|
||||||
|
primaryList: {
|
||||||
|
path: 'primary',
|
||||||
|
name: '标准列表',
|
||||||
|
component: () => import('@/pages/list/StandardList')
|
||||||
|
},
|
||||||
|
cardList: {
|
||||||
|
path: 'card',
|
||||||
|
name: '卡片列表',
|
||||||
|
component: () => import('@/pages/list/CardList')
|
||||||
|
},
|
||||||
|
searchList: {
|
||||||
|
path: 'search',
|
||||||
|
name: '搜索列表',
|
||||||
|
component: () => import('@/pages/list/search/SearchLayout')
|
||||||
|
},
|
||||||
|
article: {
|
||||||
|
name: '文章',
|
||||||
|
component: () => import('@/pages/list/search/ArticleList')
|
||||||
|
},
|
||||||
|
application: {
|
||||||
|
name: '应用',
|
||||||
|
component: () => import('@/pages/list/search/ApplicationList')
|
||||||
|
},
|
||||||
|
project: {
|
||||||
|
name: '项目',
|
||||||
|
component: () => import('@/pages/list/search/ProjectList')
|
||||||
|
},
|
||||||
|
details: {
|
||||||
|
name: '详情页',
|
||||||
|
icon: 'profile',
|
||||||
|
component: view.blank
|
||||||
|
},
|
||||||
|
basicDetails: {
|
||||||
|
path: 'basic',
|
||||||
|
name: '基础详情页',
|
||||||
|
component: () => import('@/pages/detail/BasicDetail')
|
||||||
|
},
|
||||||
|
advanceDetails: {
|
||||||
|
path: 'advance',
|
||||||
|
name: '高级详情页',
|
||||||
|
component: () => import('@/pages/detail/AdvancedDetail')
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
name: '结果页',
|
||||||
|
icon: 'check-circle-o',
|
||||||
|
component: view.page
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
name: '成功',
|
||||||
|
component: () => import('@/pages/result/Success')
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
name: '失败',
|
||||||
|
component: () => import('@/pages/result/Error')
|
||||||
|
},
|
||||||
|
exception: {
|
||||||
|
name: '异常页',
|
||||||
|
icon: 'warning',
|
||||||
|
component: view.blank
|
||||||
|
},
|
||||||
|
exp403: {
|
||||||
|
authority: '*',
|
||||||
|
name: 'exp403',
|
||||||
|
path: '403',
|
||||||
|
component: () => import('@/pages/exception/403')
|
||||||
|
},
|
||||||
|
exp404: {
|
||||||
|
name: 'exp404',
|
||||||
|
path: '404',
|
||||||
|
component: () => import('@/pages/exception/404')
|
||||||
|
},
|
||||||
|
exp500: {
|
||||||
|
name: 'exp500',
|
||||||
|
path: '500',
|
||||||
|
component: () => import('@/pages/exception/500')
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
name: '小组件',
|
||||||
|
icon: 'appstore-o',
|
||||||
|
component: view.page
|
||||||
|
},
|
||||||
|
taskCard: {
|
||||||
|
name: '任务卡片',
|
||||||
|
component: () => import('@/pages/components/TaskCard')
|
||||||
|
},
|
||||||
|
palette: {
|
||||||
|
name: '颜色复选框',
|
||||||
|
component: () => import('@/pages/components/Palette')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default routerMap
|
||||||
|
|
44
src/router/guards.js
Normal file
44
src/router/guards.js
Normal file
@ -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: []
|
||||||
|
}
|
@ -24,7 +24,7 @@ const loginIgnore = {
|
|||||||
* @returns {VueRouter}
|
* @returns {VueRouter}
|
||||||
*/
|
*/
|
||||||
function initRouter(isAsync) {
|
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)
|
formatAuthority(options.routes)
|
||||||
return new Router(options)
|
return new Router(options)
|
||||||
}
|
}
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
// 视图组件
|
|
||||||
const view = {
|
|
||||||
tabs: () => import('@/layouts/tabs'),
|
|
||||||
blank: () => import('@/layouts/BlankView'),
|
|
||||||
page: () => import('@/layouts/PageView')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 路由组件注册
|
|
||||||
const routerMap = {
|
|
||||||
login: {
|
|
||||||
authority: '*',
|
|
||||||
path: '/login',
|
|
||||||
component: () => import('@/pages/login')
|
|
||||||
},
|
|
||||||
demo: {
|
|
||||||
name: '演示页',
|
|
||||||
renderMenu: false,
|
|
||||||
component: () => import('@/pages/demo')
|
|
||||||
},
|
|
||||||
exp403: {
|
|
||||||
authority: '*',
|
|
||||||
name: 'exp403',
|
|
||||||
path: '403',
|
|
||||||
component: () => import('@/pages/exception/403')
|
|
||||||
},
|
|
||||||
exp404: {
|
|
||||||
name: 'exp404',
|
|
||||||
path: '404',
|
|
||||||
component: () => import('@/pages/exception/404')
|
|
||||||
},
|
|
||||||
exp500: {
|
|
||||||
name: 'exp500',
|
|
||||||
path: '500',
|
|
||||||
component: () => import('@/pages/exception/500')
|
|
||||||
},
|
|
||||||
root: {
|
|
||||||
path: '/',
|
|
||||||
name: '首页',
|
|
||||||
redirect: '/login',
|
|
||||||
component: view.tabs
|
|
||||||
},
|
|
||||||
parent1: {
|
|
||||||
name: '父级路由1',
|
|
||||||
icon: 'dashboard',
|
|
||||||
component: view.blank
|
|
||||||
},
|
|
||||||
parent2: {
|
|
||||||
name: '父级路由2',
|
|
||||||
icon: 'form',
|
|
||||||
component: view.page
|
|
||||||
},
|
|
||||||
exception: {
|
|
||||||
name: '异常页',
|
|
||||||
icon: 'warning',
|
|
||||||
component: view.blank
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default routerMap
|
|
||||||
|
|
50
src/utils/authority-utils.js
Normal file
50
src/utils/authority-utils.js
Normal file
@ -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}
|
@ -1,8 +1,6 @@
|
|||||||
import routerMap from '@/router/router.map'
|
import routerMap from '@/router/async/router.map'
|
||||||
import {mergeI18nFromRoutes} from '@/utils/i18n'
|
import {mergeI18nFromRoutes} from '@/utils/i18n'
|
||||||
import Router from 'vue-router'
|
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)
|
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
|
* @param routes
|
||||||
@ -222,4 +140,24 @@ function getI18nKey(path) {
|
|||||||
return keys.join('.')
|
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}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import enquireJs from 'enquire.js'
|
||||||
|
|
||||||
export function isDef (v){
|
export function isDef (v){
|
||||||
return v !== undefined && v !== null
|
return v !== undefined && v !== null
|
||||||
}
|
}
|
||||||
@ -18,4 +20,16 @@ export function isRegExp (v) {
|
|||||||
return _toString.call(v) === '[object RegExp]'
|
return _toString.call(v) === '[object RegExp]'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function enquireScreen(call) {
|
||||||
|
const handler = {
|
||||||
|
match: function () {
|
||||||
|
call && call(true)
|
||||||
|
},
|
||||||
|
unmatch: function () {
|
||||||
|
call && call(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enquireJs.register('only screen and (max-width: 767.99px)', handler)
|
||||||
|
}
|
||||||
|
|
||||||
const _toString = Object.prototype.toString
|
const _toString = Object.prototype.toString
|
||||||
|
Loading…
x
Reference in New Issue
Block a user