From 85f3cc59d02032cb28e9bfa2b753048027182fba Mon Sep 17 00:00:00 2001 From: Pan Date: Thu, 28 Feb 2019 15:02:23 +0800 Subject: [PATCH] tweak --- src/api/role.js | 4 +- src/components/HeaderSearch/index.vue | 2 +- src/lang/en.js | 2 +- src/lang/es.js | 7 +- src/lang/zh.js | 2 +- src/mock/index.js | 6 +- src/mock/role.js | 150 +---- src/mock/routes.js | 581 ------------------ src/permission.js | 9 +- src/router/index.js | 274 ++++++++- src/store/getters.js | 2 +- src/store/modules/permission.js | 63 +- src/views/layout/components/Sidebar/index.vue | 4 +- src/views/permission/role.vue | 48 +- 14 files changed, 338 insertions(+), 816 deletions(-) delete mode 100644 src/mock/routes.js diff --git a/src/api/role.js b/src/api/role.js index b1720835..4e733e83 100644 --- a/src/api/role.js +++ b/src/api/role.js @@ -1,6 +1,6 @@ import request from '@/utils/request' -export function fetchRoles() { +export function getRoles() { return request({ url: '/roles', method: 'get' @@ -14,7 +14,7 @@ export function deleteRole(id) { }) } -export function newRole(data) { +export function addRole(data) { return request({ url: '/roles', method: 'post', diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue index ab0d556a..3f6a2fd1 100644 --- a/src/components/HeaderSearch/index.vue +++ b/src/components/HeaderSearch/index.vue @@ -34,7 +34,7 @@ export default { }, computed: { routers() { - return this.$store.getters.permission_routers + return this.$store.getters.permission_routes }, lang() { return this.$store.getters.language diff --git a/src/lang/en.js b/src/lang/en.js index 5fcb275f..caed5c5b 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -87,7 +87,7 @@ export default { github: 'Github Repository' }, permission: { - newRole: 'New Role', + addRole: 'New Role', editPermission: 'Edit Permission', roles: 'Your roles', switchRoles: 'Switch roles', diff --git a/src/lang/es.js b/src/lang/es.js index 78844c22..f0d7de41 100755 --- a/src/lang/es.js +++ b/src/lang/es.js @@ -87,9 +87,14 @@ export default { github: 'Repositorio Github' }, permission: { + addRole: 'Nuevo rol', + editPermission: 'Permiso de edición', roles: 'Tus permisos', switchRoles: 'Cambiar permisos', - tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.' + tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.', + delete: 'Borrar', + confirm: 'Confirmar', + cancel: 'Cancelar' }, guide: { description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ', diff --git a/src/lang/zh.js b/src/lang/zh.js index 411d25ab..9bea838e 100644 --- a/src/lang/zh.js +++ b/src/lang/zh.js @@ -87,7 +87,7 @@ export default { github: 'Github 地址' }, permission: { - newRole: '新增角色', + addRole: '新增角色', editPermission: '编辑权限', roles: '你的权限', switchRoles: '切换权限', diff --git a/src/mock/index.js b/src/mock/index.js index 45d64eaf..ab4f5cc2 100644 --- a/src/mock/index.js +++ b/src/mock/index.js @@ -3,7 +3,6 @@ import loginAPI from './login' import articleAPI from './article' import remoteSearchAPI from './remoteSearch' import transactionAPI from './transaction' -import routesAPI from './routes' import roleAPI from './role' // 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题 @@ -20,9 +19,6 @@ 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) @@ -30,7 +26,7 @@ Mock.mock(/\/user\/info\.*/, 'get', loginAPI.getUserInfo) // 角色相关 Mock.mock(/\/roles/, 'get', roleAPI.getRoles) -Mock.mock(/\/roles$/, 'post', roleAPI.newRole) +Mock.mock(/\/roles$/, 'post', roleAPI.addRole) Mock.mock(/\/roles\/[A-Za-z0-9]+/, 'put', roleAPI.updateRole) Mock.mock(/\/roles\/[A-Za-z0-9]+/, 'delete', roleAPI.deleteRole) diff --git a/src/mock/role.js b/src/mock/role.js index 28dcf6ce..1fdf3ad9 100644 --- a/src/mock/role.js +++ b/src/mock/role.js @@ -1,159 +1,13 @@ import Mock from 'mockjs' // admin 角色可以访问所有菜单 -const roles = [ - { - id: 'editor', // 角色id - name: 'editor', - description: '编辑', - accessibleRoutes: [ - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '10', - '11', - '12', - '13', - '14', - '15', - '16', - '17', - '18', - '19', - '20', - '21', - '22', - '23', - '24', - '25', - '26', - '27', - '28', - '29', - '30', - '31', - '32', - '33', - '34', - '35', - '36', - '37', - '38', - '39', - '40', - '41', - '42', - '43', - '44', - '45', - '46', - '47', - '48', - '49', - '50', - '51', - '52', - '53', - '54', - '55', - '56', - '57', - '58', - '59', - '60', - '61', - '62', - '63', - '64', - '65', - '66', - '67' - ] // 可访问的菜单id列表 - }, - { - id: 'operator', // 角色id - name: 'operator', - description: '运营', - accessibleRoutes: [ - '1', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '10', - '11', - '12', - '13', - '14', - '15', - '16', - '17', - '18', - '19', - '20', - '21', - '22', - '23', - '24', - '25', - '26', - '27', - '28', - '29', - '30', - '31', - '32', - '33', - '34', - '35', - '36', - '37', - '38', - '39', - '40', - '41', - '42', - '43', - '44', - '45', - '46', - '47', - '48', - '49', - '50', - '51', - '52', - '53', - '54', - '55', - '56', - '57', - '58', - '59', - '60', - '61', - '62', - '63', - '64', - '65' - ] // 可访问的菜单id列表 - } -] +const roles = [] export default { getRoles() { return roles }, - newRole() { + addRole() { const res = { data: Mock.mock('id') } diff --git a/src/mock/routes.js b/src/mock/routes.js deleted file mode 100644 index 678f4ee9..00000000 --- a/src/mock/routes.js +++ /dev/null @@ -1,581 +0,0 @@ -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: '66', - path: 'role', - component: 'permission/role', - name: 'role', - meta: { - title: 'rolePermission', - roles: ['admin'] - } - } - ] - }, - - { - 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: [ - { - id: '67', - 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 d602582d..a29b18d4 100644 --- a/src/permission.js +++ b/src/permission.js @@ -3,13 +3,13 @@ import store from './store' import { Message } from 'element-ui' import NProgress from 'nprogress' // progress bar import 'nprogress/nprogress.css' // progress bar style -import { getToken } from '@/utils/auth' // getToken from cookie +import { getToken } from '@/utils/auth' // get token from cookie NProgress.configure({ showSpinner: false }) // NProgress Configuration // permission judge function function hasPermission(roles, permissionRoles) { - if (roles.findIndex(role => role === 'admin') >= 0) return true // admin permission passed directly + if (roles.includes('admin')) return true // admin permission passed directly if (!permissionRoles) return true return roles.some(role => permissionRoles.indexOf(role) >= 0) } @@ -20,6 +20,7 @@ router.beforeEach((to, from, next) => { NProgress.start() // start progress bar if (getToken()) { // determine if there has token + /* has token*/ if (to.path === '/login') { next({ path: '/' }) @@ -32,9 +33,9 @@ router.beforeEach((to, from, next) => { .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 => { + store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => { // 根据roles权限生成可访问的路由表 - router.addRoutes(excessRoutes) // 动态添加可访问路由表 + router.addRoutes(accessRoutes) // 动态添加可访问路由表 next({ ...to, replace: true }) // hack方法 确保addRouters已完成 ,set the replace: true so the navigation will not leave a history record }) }) diff --git a/src/router/index.js b/src/router/index.js index a43a22b5..7c49ed06 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -6,7 +6,13 @@ Vue.use(Router) /* Layout */ import Layout from '@/views/layout/Layout' -/** note: Submenu only appear when children.length>=1 +/* Router Modules */ +import componentsRouter from './modules/components' +import chartsRouter from './modules/charts' +import tableRouter from './modules/table' +import nestedRouter from './modules/nested' + +/** note: sub-menu only appear when children.length>=1 * detail see https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html **/ @@ -19,10 +25,11 @@ import Layout from '@/views/layout/Layout' * name:'router-name' the name is used by (must set!!!) * meta : { roles: ['admin','editor'] will control the page roles (you can set multiple roles) - title: 'title' the name show in submenu and breadcrumb (recommend set) + title: 'title' the name show in sub-menu and breadcrumb (recommend set) icon: 'svg-name' the icon show in the sidebar noCache: true if true, the page will no be cached(default is false) breadcrumb: false if false, the item will hidden in breadcrumb(default is true) + affix: true if true, the tag will affix in the tags-view } **/ export const constantRoutes = [ @@ -66,7 +73,7 @@ export const constantRoutes = [ path: 'dashboard', component: () => import('@/views/dashboard/index'), name: 'Dashboard', - meta: { title: 'dashboard', icon: 'dashboard', noCache: true } + meta: { title: 'dashboard', icon: 'dashboard', noCache: true, affix: true } } ] }, @@ -79,7 +86,7 @@ export const constantRoutes = [ path: 'index', component: () => import('@/views/documentation/index'), name: 'Documentation', - meta: { title: 'documentation', icon: 'documentation', noCache: true } + meta: { title: 'documentation', icon: 'documentation', affix: true } } ] }, @@ -98,10 +105,265 @@ export const constantRoutes = [ } ] -export const generalRoutes = [{ path: '*', redirect: '/404', hidden: true }] - export default new Router({ // mode: 'history', // require service support scrollBehavior: () => ({ y: 0 }), routes: constantRoutes }) + +export const asyncRoutes = [ + { + 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/getters.js b/src/store/getters.js index cf314f5c..885ac65b 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -12,7 +12,7 @@ const getters = { status: state => state.user.status, roles: state => state.user.roles, setting: state => state.user.setting, - permission_routers: state => state.permission.routers, + permission_routes: state => state.permission.routes, addRouters: state => state.permission.addRouters, errorLogs: state => state.errorLog.logs } diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js index f52287b8..c05e4522 100644 --- a/src/store/modules/permission.js +++ b/src/store/modules/permission.js @@ -1,15 +1,11 @@ -import { constantRoutes, generalRoutes } from '@/router' -import { fetchAsyncRoutes } from '@/api/routes' +import { asyncRoutes, constantRoutes } from '@/router' -const _import = path => () => import(`@/views/${path}`) /** * 通过meta.role判断是否与当前用户权限匹配 * @param roles * @param route */ function hasPermission(roles, route) { - // 如果是隐藏的菜单, 都是可访问的, 因为隐藏的菜单不会出现在左侧菜单栏, 不可编辑权限 - if (route.hidden) return true if (route.meta && route.meta.roles) { return roles.some(role => route.meta.roles.includes(role)) } else { @@ -17,44 +13,36 @@ 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 asyncRoutes * @param roles */ function filterAsyncRoutes(routes, roles) { - return routes.filter(route => { - if (!hasPermission(roles, route)) { - return false + const res = [] + + routes.forEach(route => { + const tmp = { ...route } + if (hasPermission(roles, tmp)) { + if (tmp.children) { + tmp.children = filterAsyncRoutes(tmp.children, roles) + } + res.push(tmp) } - if (route.children) { - route.children = filterAsyncRoutes(route.children, roles) - } - return true }) + + return res } const permission = { state: { - routers: [], - addRouters: [], - asyncRoutes: [] + routes: [], + addRoutes: [] }, mutations: { - SET_ROUTERS: (state, routes) => { - state.addRouters = routes - state.routers = constantRoutes.concat(routes) + SET_ROUTES: (state, routes) => { + state.addRoutes = routes + state.routes = constantRoutes.concat(routes) } }, actions: { @@ -62,16 +50,13 @@ const permission = { return new Promise(resolve => { const { roles } = data 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) - }) + if (roles.includes('admin')) { + accessedRoutes = asyncRoutes + } else { + accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) + } + commit('SET_ROUTES', accessedRoutes) + resolve(accessedRoutes) }) } } diff --git a/src/views/layout/components/Sidebar/index.vue b/src/views/layout/components/Sidebar/index.vue index 48407286..ee8e11b2 100644 --- a/src/views/layout/components/Sidebar/index.vue +++ b/src/views/layout/components/Sidebar/index.vue @@ -9,7 +9,7 @@ :active-text-color="variables.menuActiveText" mode="vertical" > - + @@ -23,7 +23,7 @@ export default { components: { SidebarItem }, computed: { ...mapGetters([ - 'permission_routers', + 'permission_routes', 'sidebar' ]), variables() { diff --git a/src/views/permission/role.vue b/src/views/permission/role.vue index 53eff624..d2617bad 100644 --- a/src/views/permission/role.vue +++ b/src/views/permission/role.vue @@ -1,6 +1,6 @@