diff --git a/src/api/routes.js b/src/api/routes.js new file mode 100644 index 00000000..95fc96c9 --- /dev/null +++ b/src/api/routes.js @@ -0,0 +1,8 @@ +import request from '@/utils/request' + +export function fetchAsyncRoutes() { + return request({ + url: '/routes', + method: 'get' + }) +} diff --git a/src/mock/index.js b/src/mock/index.js index 3e00e918..08afec3b 100644 --- a/src/mock/index.js +++ b/src/mock/index.js @@ -3,6 +3,7 @@ import loginAPI from './login' import articleAPI from './article' import remoteSearchAPI from './remoteSearch' import transactionAPI from './transaction' +import routesAPI from './routes' // 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题 // https://github.com/nuysoft/Mock/issues/300 @@ -18,6 +19,9 @@ Mock.XHR.prototype.send = function() { // timeout: '350-600' // }) +// 路由表相关 +Mock.mock(/\/routes/, 'get', routesAPI.getAsyncRoutesMap) + // 登录相关 Mock.mock(/\/login\/login/, 'post', loginAPI.loginByUsername) Mock.mock(/\/login\/logout/, 'post', loginAPI.logout) diff --git a/src/mock/routes.js b/src/mock/routes.js new file mode 100644 index 00000000..330e903f --- /dev/null +++ b/src/mock/routes.js @@ -0,0 +1,570 @@ +const asyncRoutesMap = [ + { + id: '1', + path: '/permission', + component: 'layout/Layout', + redirect: '/permission/index', + alwaysShow: true, // will always show the root menu + meta: { + title: 'permission', + icon: 'lock', + roles: ['admin', 'editor'] // you can set roles in root nav + }, + children: [ + { + id: '2', + path: 'page', + component: 'permission/page', + name: 'PagePermission', + meta: { + title: 'pagePermission', + roles: ['admin'] + } + }, + { + id: '3', + path: 'directive', + component: 'permission/directive', + name: 'DirectivePermission', + meta: { + title: 'directivePermission', + roles: ['admin', 'editor'] + } + } + ] + }, + + { + id: '4', + path: '/icon', + component: 'layout/Layout', + children: [ + { + id: '5', + path: 'index', + component: 'svg-icons/index', + name: 'Icons', + meta: { title: 'icons', icon: 'icon', noCache: true, roles: ['admin', 'editor'] } + } + ] + }, + { + id: '6', + path: '/components', + component: 'layout/Layout', + redirect: 'noredirect', + name: 'ComponentDemo', + meta: { + title: 'components', + icon: 'component', + roles: ['admin', 'editor'] + }, + children: [ + { + id: '7', + path: 'tinymce', + component: 'components-demo/tinymce', + name: 'TinymceDemo', + meta: { title: 'tinymce', roles: ['admin', 'editor'] } + }, + { + id: '8', + path: 'markdown', + component: 'components-demo/markdown', + name: 'MarkdownDemo', + meta: { title: 'markdown', roles: ['admin', 'editor'] } + }, + { + id: '9', + path: 'json-editor', + component: 'components-demo/jsonEditor', + name: 'JsonEditorDemo', + meta: { title: 'jsonEditor', roles: ['admin', 'editor'] } + }, + { + id: '10', + path: 'splitpane', + component: 'components-demo/splitpane', + name: 'SplitpaneDemo', + meta: { title: 'splitPane', roles: ['admin', 'editor'] } + }, + { + id: '11', + path: 'avatar-upload', + component: 'components-demo/avatarUpload', + name: 'AvatarUploadDemo', + meta: { title: 'avatarUpload', roles: ['admin', 'editor'] } + }, + { + id: '12', + path: 'dropzone', + component: 'components-demo/dropzone', + name: 'DropzoneDemo', + meta: { title: 'dropzone', roles: ['admin', 'editor'] } + }, + { + id: '13', + path: 'sticky', + component: 'components-demo/sticky', + name: 'StickyDemo', + meta: { title: 'sticky', roles: ['admin', 'editor'] } + }, + { + id: '14', + path: 'count-to', + component: 'components-demo/countTo', + name: 'CountToDemo', + meta: { title: 'countTo', roles: ['admin', 'editor'] } + }, + { + id: '15', + path: 'mixin', + component: 'components-demo/mixin', + name: 'ComponentMixinDemo', + meta: { title: 'componentMixin', roles: ['admin', 'editor'] } + }, + { + id: '16', + path: 'back-to-top', + component: 'components-demo/backToTop', + name: 'BackToTopDemo', + meta: { title: 'backToTop', roles: ['admin', 'editor'] } + }, + { + id: '17', + path: 'drag-dialog', + component: 'components-demo/dragDialog', + name: 'DragDialogDemo', + meta: { title: 'dragDialog', roles: ['admin', 'editor'] } + }, + { + id: '18', + path: 'drag-select', + component: 'components-demo/dragSelect', + name: 'DragSelectDemo', + meta: { title: 'dragSelect', roles: ['admin', 'editor'] } + }, + { + id: '19', + path: 'dnd-list', + component: 'components-demo/dndList', + name: 'DndListDemo', + meta: { title: 'dndList', roles: ['admin', 'editor'] } + }, + { + id: '20', + path: 'drag-kanban', + component: 'components-demo/dragKanban', + name: 'DragKanbanDemo', + meta: { title: 'dragKanban', roles: ['admin', 'editor'] } + } + ] + }, + { + id: '21', + path: '/charts', + component: 'layout/Layout', + redirect: 'noredirect', + name: 'Charts', + meta: { + title: 'charts', + icon: 'chart', + roles: ['admin', 'editor'] + }, + children: [ + { + id: '22', + path: 'keyboard', + component: 'charts/keyboard', + name: 'KeyboardChart', + meta: { title: 'keyboardChart', noCache: true, roles: ['admin', 'editor'] } + }, + { + id: '23', + path: 'line', + component: 'charts/line', + name: 'LineChart', + meta: { title: 'lineChart', noCache: true, roles: ['admin', 'editor'] } + }, + { + id: '24', + path: 'mixchart', + component: 'charts/mixChart', + name: 'MixChart', + meta: { title: 'mixChart', noCache: true, roles: ['admin', 'editor'] } + } + ] + }, + { + id: '25', + path: '/nested', + component: 'layout/Layout', + redirect: '/nested/menu1/menu1-1', + name: 'Nested', + meta: { + title: 'nested', + icon: 'nested', + roles: ['admin', 'editor'] + }, + children: [ + { + id: '26', + path: 'menu1', + component: 'nested/menu1/index', // Parent router-view + name: 'Menu1', + meta: { title: 'menu1', roles: ['admin', 'editor'] }, + redirect: '/nested/menu1/menu1-1', + children: [ + { + id: '27', + path: 'menu1-1', + component: 'nested/menu1/menu1-1', + name: 'Menu1-1', + meta: { title: 'menu1-1', roles: ['admin', 'editor'] } + }, + { + id: '28', + path: 'menu1-2', + component: 'nested/menu1/menu1-2', + name: 'Menu1-2', + redirect: '/nested/menu1/menu1-2/menu1-2-1', + meta: { title: 'menu1-2', roles: ['admin', 'editor'] }, + children: [ + { + id: '29', + path: 'menu1-2-1', + component: 'nested/menu1/menu1-2/menu1-2-1', + name: 'Menu1-2-1', + meta: { title: 'menu1-2-1', roles: ['admin', 'editor'] } + }, + { + id: '30', + path: 'menu1-2-2', + component: 'nested/menu1/menu1-2/menu1-2-2', + name: 'Menu1-2-2', + meta: { title: 'menu1-2-2', roles: ['admin', 'editor'] } + } + ] + }, + { + id: '31', + path: 'menu1-3', + component: 'nested/menu1/menu1-3', + name: 'Menu1-3', + meta: { title: 'menu1-3', roles: ['admin', 'editor'] } + } + ] + }, + { + id: '32', + path: 'menu2', + name: 'Menu2', + component: 'nested/menu2/index', + meta: { title: 'menu2', roles: ['admin', 'editor'] } + } + ] + }, + { + id: '33', + path: '/table', + component: 'layout/Layout', + redirect: '/table/complex-table', + name: 'Table', + meta: { + title: 'Table', + icon: 'table', + roles: ['admin', 'editor'] + }, + children: [ + { + id: '34', + path: 'dynamic-table', + component: 'table/dynamicTable/index', + name: 'DynamicTable', + meta: { title: 'dynamicTable', roles: ['admin', 'editor'] } + }, + { + id: '35', + path: 'drag-table', + component: 'table/dragTable', + name: 'DragTable', + meta: { title: 'dragTable', roles: ['admin', 'editor'] } + }, + { + id: '36', + path: 'inline-edit-table', + component: 'table/inlineEditTable', + name: 'InlineEditTable', + meta: { title: 'inlineEditTable', roles: ['admin', 'editor'] } + }, + { + id: '37', + path: 'tree-table', + component: 'table/treeTable/treeTable', + name: 'TreeTableDemo', + meta: { title: 'treeTable', roles: ['admin', 'editor'] } + }, + { + id: '38', + path: 'custom-tree-table', + component: 'table/treeTable/customTreeTable', + name: 'CustomTreeTableDemo', + meta: { title: 'customTreeTable', roles: ['admin', 'editor'] } + }, + { + id: '39', + path: 'complex-table', + component: 'table/complexTable', + name: 'ComplexTable', + meta: { title: 'complexTable', roles: ['admin', 'editor'] } + } + ] + }, + { + id: '40', + path: '/example', + component: 'layout/Layout', + redirect: '/example/list', + name: 'Example', + meta: { + title: 'example', + icon: 'example', + roles: ['admin', 'editor'] + }, + children: [ + { + id: '41', + path: 'create', + component: 'example/create', + name: 'CreateArticle', + meta: { title: 'createArticle', icon: 'edit', roles: ['admin', 'editor'] } + }, + { + id: '42', + path: 'edit/:id(\\d+)', + component: 'example/edit', + name: 'EditArticle', + meta: { title: 'editArticle', noCache: true, roles: ['admin', 'editor'] }, + hidden: true + }, + { + id: '43', + path: 'list', + component: 'example/list', + name: 'ArticleList', + meta: { title: 'articleList', icon: 'list', roles: ['admin', 'editor'] } + } + ] + }, + + { + path: '/tab', + component: 'layout/Layout', + children: [ + { + id: '44', + path: 'index', + component: 'tab/index', + name: 'Tab', + meta: { title: 'tab', icon: 'tab', roles: ['admin', 'editor'] } + } + ] + }, + { + id: '45', + path: '/error', + component: 'layout/Layout', + redirect: 'noredirect', + name: 'ErrorPages', + meta: { + title: 'errorPages', + icon: '404', + roles: ['admin', 'editor'] + }, + children: [ + { + id: '46', + path: '401', + component: 'errorPage/401', + name: 'Page401', + meta: { title: 'page401', noCache: true, roles: ['admin', 'editor'] } + }, + { + id: '47', + path: '404', + component: 'errorPage/404', + name: 'Page404', + meta: { title: 'page404', noCache: true, roles: ['admin', 'editor'] } + } + ] + }, + + { + id: '48', + path: '/error-log', + component: 'layout/Layout', + redirect: 'noredirect', + children: [ + { + path: 'log', + component: 'errorLog/index', + name: 'ErrorLog', + meta: { title: 'errorLog', icon: 'bug', roles: ['admin', 'editor'] } + } + ] + }, + + { + id: '49', + path: '/excel', + component: 'layout/Layout', + redirect: '/excel/export-excel', + name: 'Excel', + meta: { + title: 'excel', + icon: 'excel', + roles: ['admin', 'editor'] + }, + children: [ + { + id: '50', + path: 'export-excel', + component: 'excel/exportExcel', + name: 'ExportExcel', + meta: { title: 'exportExcel', roles: ['admin', 'editor'] } + }, + { + id: '51', + path: 'export-selected-excel', + component: 'excel/selectExcel', + name: 'SelectExcel', + meta: { title: 'selectExcel', roles: ['admin', 'editor'] } + }, + { + id: '52', + path: 'upload-excel', + component: 'excel/uploadExcel', + name: 'UploadExcel', + meta: { title: 'uploadExcel', roles: ['admin', 'editor'] } + } + ] + }, + + // { + // id: '53', + // path: '/zip', + // component: 'layout/Layout', + // redirect: '/zip/download', + // alwaysShow: true, + // meta: { title: 'zip', icon: 'zip', roles: ['admin', 'editor'] }, + // children: [ + // { + // id: '54', + // path: 'download', + // component: 'zip/index', + // name: 'ExportZip', + // meta: { title: 'exportZip', roles: ['admin', 'editor'] } + // } + // ] + // }, + + { + id: '55', + path: '/pdf', + component: 'layout/Layout', + redirect: '/pdf/index', + children: [ + { + id: '56', + path: 'index', + component: 'pdf/index', + name: 'PDF', + meta: { title: 'pdf', icon: 'pdf', roles: ['admin', 'editor'] } + } + ] + }, + { + id: '57', + path: '/pdf/download', + component: 'pdf/download', + hidden: true + }, + + { + id: '58', + path: '/theme', + component: 'layout/Layout', + redirect: 'noredirect', + meta: { + roles: ['admin', 'editor'] + }, + children: [ + { + id: '59', + path: 'index', + component: 'theme/index', + name: 'Theme', + meta: { title: 'theme', icon: 'theme', roles: ['admin', 'editor'] } + } + ] + }, + + { + id: '60', + path: '/clipboard', + component: 'layout/Layout', + redirect: 'noredirect', + meta: { + roles: ['admin', 'editor'] + }, + children: [ + { + id: '61', + path: 'index', + component: 'clipboard/index', + name: 'ClipboardDemo', + meta: { title: 'clipboardDemo', icon: 'clipboard', roles: ['admin', 'editor'] } + } + ] + }, + + { + id: '62', + path: '/i18n', + component: 'layout/Layout', + meta: { + roles: ['admin', 'editor'] + }, + children: [ + { + id: '63', + path: 'index', + component: 'i18n-demo/index', + name: 'I18n', + meta: { title: 'i18n', icon: 'international', roles: ['admin', 'editor'] } + } + ] + }, + + { + id: '64', + path: 'external-link', + component: 'layout/Layout', + meta: { + roles: ['admin', 'editor'] + }, + children: [ + { + id: '65', + path: 'https://github.com/PanJiaChen/vue-element-admin', + meta: { title: 'externalLink', icon: 'link', roles: ['admin', 'editor'] } + } + ] + } +] + +export default { + getAsyncRoutesMap() { + return asyncRoutesMap + } +} diff --git a/src/permission.js b/src/permission.js index e556cb00..d602582d 100644 --- a/src/permission.js +++ b/src/permission.js @@ -2,41 +2,48 @@ import router from './router' import store from './store' import { Message } from 'element-ui' import NProgress from 'nprogress' // progress bar -import 'nprogress/nprogress.css'// progress bar style +import 'nprogress/nprogress.css' // progress bar style import { getToken } from '@/utils/auth' // getToken from cookie -NProgress.configure({ showSpinner: false })// NProgress Configuration +NProgress.configure({ showSpinner: false }) // NProgress Configuration // permission judge function function hasPermission(roles, permissionRoles) { - if (roles.indexOf('admin') >= 0) return true // admin permission passed directly + if (roles.findIndex(role => role === 'admin') >= 0) return true // admin permission passed directly if (!permissionRoles) return true return roles.some(role => permissionRoles.indexOf(role) >= 0) } -const whiteList = ['/login', '/auth-redirect']// no redirect whitelist +const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist router.beforeEach((to, from, next) => { NProgress.start() // start progress bar - if (getToken()) { // determine if there has token + if (getToken()) { + // determine if there has token /* has token*/ if (to.path === '/login') { next({ path: '/' }) NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it } else { - if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息 - store.dispatch('GetUserInfo').then(res => { // 拉取user_info - const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop'] - store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表 - router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 - next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + if (store.getters.roles.length === 0) { + // 判断当前用户是否已拉取完user_info信息 + store + .dispatch('GetUserInfo') + .then(res => { + // 拉取user_info + const roles = res.data.roles // note: roles must be a object array! such as: [{id: '1', name: 'editor'}, {id: '2', name: 'developer'}] + store.dispatch('GenerateRoutes', { roles }).then(excessRoutes => { + // 根据roles权限生成可访问的路由表 + router.addRoutes(excessRoutes) // 动态添加可访问路由表 + next({ ...to, replace: true }) // hack方法 确保addRouters已完成 ,set the replace: true so the navigation will not leave a history record + }) }) - }).catch((err) => { - store.dispatch('FedLogOut').then(() => { - Message.error(err) - next({ path: '/' }) + .catch(err => { + store.dispatch('FedLogOut').then(() => { + Message.error(err) + next({ path: '/' }) + }) }) - }) } else { // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓ if (hasPermission(store.getters.roles, to.meta.roles)) { @@ -49,7 +56,8 @@ router.beforeEach((to, from, next) => { } } else { /* has no token*/ - if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入 + if (whiteList.indexOf(to.path) !== -1) { + // 在免登录白名单,直接进入 next() } else { next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 diff --git a/src/router/index.js b/src/router/index.js index dda18156..a43a22b5 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -6,12 +6,6 @@ Vue.use(Router) /* Layout */ import Layout from '@/views/layout/Layout' -/* Router Modules */ -import componentsRouter from './modules/components' -import chartsRouter from './modules/charts' -import tableRouter from './modules/table' -import nestedRouter from './modules/nested' - /** note: Submenu only appear when children.length>=1 * detail see https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html **/ @@ -31,7 +25,7 @@ import nestedRouter from './modules/nested' breadcrumb: false if false, the item will hidden in breadcrumb(default is true) } **/ -export const constantRouterMap = [ +export const constantRoutes = [ { path: '/redirect', component: Layout, @@ -104,265 +98,10 @@ export const constantRouterMap = [ } ] +export const generalRoutes = [{ path: '*', redirect: '/404', hidden: true }] + export default new Router({ // mode: 'history', // require service support scrollBehavior: () => ({ y: 0 }), - routes: constantRouterMap + routes: constantRoutes }) - -export const asyncRouterMap = [ - { - path: '/permission', - component: Layout, - redirect: '/permission/index', - alwaysShow: true, // will always show the root menu - meta: { - title: 'permission', - icon: 'lock', - roles: ['admin', 'editor'] // you can set roles in root nav - }, - children: [ - { - path: 'page', - component: () => import('@/views/permission/page'), - name: 'PagePermission', - meta: { - title: 'pagePermission', - roles: ['admin'] // or you can only set roles in sub nav - } - }, - { - path: 'directive', - component: () => import('@/views/permission/directive'), - name: 'DirectivePermission', - meta: { - title: 'directivePermission' - // if do not set roles, means: this page does not require permission - } - } - ] - }, - - { - path: '/icon', - component: Layout, - children: [ - { - path: 'index', - component: () => import('@/views/svg-icons/index'), - name: 'Icons', - meta: { title: 'icons', icon: 'icon', noCache: true } - } - ] - }, - - /** When your routing table is too long, you can split it into small modules**/ - componentsRouter, - chartsRouter, - nestedRouter, - tableRouter, - - { - path: '/example', - component: Layout, - redirect: '/example/list', - name: 'Example', - meta: { - title: 'example', - icon: 'example' - }, - children: [ - { - path: 'create', - component: () => import('@/views/example/create'), - name: 'CreateArticle', - meta: { title: 'createArticle', icon: 'edit' } - }, - { - path: 'edit/:id(\\d+)', - component: () => import('@/views/example/edit'), - name: 'EditArticle', - meta: { title: 'editArticle', noCache: true }, - hidden: true - }, - { - path: 'list', - component: () => import('@/views/example/list'), - name: 'ArticleList', - meta: { title: 'articleList', icon: 'list' } - } - ] - }, - - { - path: '/tab', - component: Layout, - children: [ - { - path: 'index', - component: () => import('@/views/tab/index'), - name: 'Tab', - meta: { title: 'tab', icon: 'tab' } - } - ] - }, - - { - path: '/error', - component: Layout, - redirect: 'noredirect', - name: 'ErrorPages', - meta: { - title: 'errorPages', - icon: '404' - }, - children: [ - { - path: '401', - component: () => import('@/views/errorPage/401'), - name: 'Page401', - meta: { title: 'page401', noCache: true } - }, - { - path: '404', - component: () => import('@/views/errorPage/404'), - name: 'Page404', - meta: { title: 'page404', noCache: true } - } - ] - }, - - { - path: '/error-log', - component: Layout, - redirect: 'noredirect', - children: [ - { - path: 'log', - component: () => import('@/views/errorLog/index'), - name: 'ErrorLog', - meta: { title: 'errorLog', icon: 'bug' } - } - ] - }, - - { - path: '/excel', - component: Layout, - redirect: '/excel/export-excel', - name: 'Excel', - meta: { - title: 'excel', - icon: 'excel' - }, - children: [ - { - path: 'export-excel', - component: () => import('@/views/excel/exportExcel'), - name: 'ExportExcel', - meta: { title: 'exportExcel' } - }, - { - path: 'export-selected-excel', - component: () => import('@/views/excel/selectExcel'), - name: 'SelectExcel', - meta: { title: 'selectExcel' } - }, - { - path: 'upload-excel', - component: () => import('@/views/excel/uploadExcel'), - name: 'UploadExcel', - meta: { title: 'uploadExcel' } - } - ] - }, - - { - path: '/zip', - component: Layout, - redirect: '/zip/download', - alwaysShow: true, - meta: { title: 'zip', icon: 'zip' }, - children: [ - { - path: 'download', - component: () => import('@/views/zip/index'), - name: 'ExportZip', - meta: { title: 'exportZip' } - } - ] - }, - - { - path: '/pdf', - component: Layout, - redirect: '/pdf/index', - children: [ - { - path: 'index', - component: () => import('@/views/pdf/index'), - name: 'PDF', - meta: { title: 'pdf', icon: 'pdf' } - } - ] - }, - { - path: '/pdf/download', - component: () => import('@/views/pdf/download'), - hidden: true - }, - - { - path: '/theme', - component: Layout, - redirect: 'noredirect', - children: [ - { - path: 'index', - component: () => import('@/views/theme/index'), - name: 'Theme', - meta: { title: 'theme', icon: 'theme' } - } - ] - }, - - { - path: '/clipboard', - component: Layout, - redirect: 'noredirect', - children: [ - { - path: 'index', - component: () => import('@/views/clipboard/index'), - name: 'ClipboardDemo', - meta: { title: 'clipboardDemo', icon: 'clipboard' } - } - ] - }, - - { - path: '/i18n', - component: Layout, - children: [ - { - path: 'index', - component: () => import('@/views/i18n-demo/index'), - name: 'I18n', - meta: { title: 'i18n', icon: 'international' } - } - ] - }, - - { - path: 'external-link', - component: Layout, - children: [ - { - path: 'https://github.com/PanJiaChen/vue-element-admin', - meta: { title: 'externalLink', icon: 'link' } - } - ] - }, - - { path: '*', redirect: '/404', hidden: true } -] diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js index 13f60efb..96038dc2 100644 --- a/src/store/modules/permission.js +++ b/src/store/modules/permission.js @@ -1,5 +1,7 @@ -import { asyncRouterMap, constantRouterMap } from '@/router' +import { constantRoutes, generalRoutes } from '@/router' +import { fetchAsyncRoutes } from '@/api/routes' +const _import = path => () => import(`@/views/${path}`) /** * 通过meta.role判断是否与当前用户权限匹配 * @param roles @@ -13,50 +15,61 @@ function hasPermission(roles, route) { } } +// 将从服务器获得的路由表转换为vue-router的路由表 +function mapAsyncRoutes(asyncRoutes) { + return asyncRoutes.map(route => { + route.component && (route.component = _import(route.component)) + if (route.children) { + route.children = mapAsyncRoutes(route.children) + } + return route + }) +} + /** * 递归过滤异步路由表,返回符合用户角色权限的路由表 - * @param routes asyncRouterMap + * @param routes asyncRoutes * @param roles */ -function filterAsyncRouter(routes, roles) { - const res = [] - - routes.forEach(route => { - const tmp = { ...route } - if (hasPermission(roles, tmp)) { - if (tmp.children) { - tmp.children = filterAsyncRouter(tmp.children, roles) - } - res.push(tmp) +function filterAsyncRoutes(routes, roles) { + return routes.filter(route => { + if (!hasPermission(roles, route)) { + return false } + if (route.children) { + route.children = filterAsyncRoutes(route.children, roles) + } + return true }) - - return res } const permission = { state: { routers: [], - addRouters: [] + addRouters: [], + asyncRoutes: [] }, mutations: { - SET_ROUTERS: (state, routers) => { - state.addRouters = routers - state.routers = constantRouterMap.concat(routers) + SET_ROUTERS: (state, routes) => { + state.addRouters = routes + state.routers = constantRoutes.concat(routes) } }, actions: { GenerateRoutes({ commit }, data) { return new Promise(resolve => { const { roles } = data - let accessedRouters - if (roles.includes('admin')) { - accessedRouters = asyncRouterMap - } else { - accessedRouters = filterAsyncRouter(asyncRouterMap, roles) - } - commit('SET_ROUTERS', accessedRouters) - resolve() + let accessedRoutes + fetchAsyncRoutes().then(res => { + const asyncRoutes = res.data + if (roles.includes('admin')) { + accessedRoutes = mapAsyncRoutes(asyncRoutes).concat(generalRoutes) + } else { + accessedRoutes = mapAsyncRoutes(filterAsyncRoutes(asyncRoutes, roles)).concat(generalRoutes) + } + commit('SET_ROUTERS', accessedRoutes) + resolve(accessedRoutes) + }) }) } }