This commit is contained in:
Pan 2019-02-28 15:02:23 +08:00
parent b65962d7e5
commit 85f3cc59d0
14 changed files with 338 additions and 816 deletions

View File

@ -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',

View File

@ -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

View File

@ -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',

View File

@ -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 ',

View File

@ -87,7 +87,7 @@ export default {
github: 'Github 地址'
},
permission: {
newRole: '新增角色',
addRole: '新增角色',
editPermission: '编辑权限',
roles: '你的权限',
switchRoles: '切换权限',

View File

@ -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)

View File

@ -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')
}

View File

@ -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
}
}

View File

@ -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
})
})

View File

@ -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 <keep-alive> (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 }
]

View File

@ -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
}

View File

@ -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)
})
}
}

View File

@ -9,7 +9,7 @@
:active-text-color="variables.menuActiveText"
mode="vertical"
>
<sidebar-item v-for="route in permission_routers" :key="route.path" :item="route" :base-path="route.path"/>
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path"/>
</el-menu>
</el-scrollbar>
</template>
@ -23,7 +23,7 @@ export default {
components: { SidebarItem },
computed: {
...mapGetters([
'permission_routers',
'permission_routes',
'sidebar'
]),
variables() {

View File

@ -1,6 +1,6 @@
<template>
<div class="app-container wrapper">
<el-button type="primary" @click="handleNewRole">{{ $t('permission.newRole') }}</el-button>
<el-button type="primary" @click="handleaddRole">{{ $t('permission.addRole') }}</el-button>
<el-table :data="rolesData" style="width: 100%" class="roles-table">
<el-table-column label="Role Id" width="220">
@ -20,18 +20,18 @@
</el-table-column>
</el-table>
<el-dialog :visible.sync="newRoleDialogVisible" title="New Role">
<el-form :model="newRole" class="new-role-form">
<el-dialog :visible.sync="addRoleDialogVisible" title="New Role">
<el-form :model="addRole" class="new-role-form">
<el-form-item label="Role Name">
<el-input v-model="newRole.name" placeholder="role name"/>
<el-input v-model="addRole.name" placeholder="role name"/>
</el-form-item>
<el-form-item label="Role Description">
<el-input v-model="newRole.describe" placeholder="role Description"/>
<el-input v-model="addRole.describe" placeholder="role Description"/>
</el-form-item>
</el-form>
<el-button type="primary" @click="confirmNewRole">{{ $t('permission.confirm') }}</el-button>
<el-button type="danger" @click="cancleNewRole">{{ $t('permission.cancel') }}</el-button>
<el-button type="primary" @click="confirmaddRole">{{ $t('permission.confirm') }}</el-button>
<el-button type="danger" @click="cancleaddRole">{{ $t('permission.cancel') }}</el-button>
</el-dialog>
<el-dialog :visible.sync="permissionDialogVisible" :title="$t('permission.editPermission')">
@ -55,7 +55,7 @@
<script>
import { deepClone } from '@/utils'
import { generateTitle } from '@/utils/i18n'
import { newRole, deleteRole, updateRole, fetchRoles } from '@/api/role'
import { addRole, deleteRole, updateRole, getRoles } from '@/api/role'
import { fetchAsyncRoutes } from '@/api/routes'
export default {
@ -63,13 +63,13 @@ export default {
return {
checkStrictly: false,
routesData: [],
newRoleDialogVisible: false,
addRoleDialogVisible: false,
permissionDialogVisible: false,
defaultProps: {
children: 'children',
label: 'name'
},
newRole: {
addRole: {
id: '',
name: '',
describe: '',
@ -106,7 +106,7 @@ export default {
fetchAsyncRoutes().then(res => {
this.routesData = res.data
})
fetchRoles().then(res => {
getRoles().then(res => {
console.log(res)
this.rolesData = res.data
})
@ -142,8 +142,8 @@ export default {
return false
},
handleNewRole() {
this.newRoleDialogVisible = true
handleaddRole() {
this.addRoleDialogVisible = true
},
handleEdit(scope) {
this.checkedRole.index = scope.$index
@ -207,25 +207,25 @@ export default {
canclePermission() {
this.permissionDialogVisible = false
},
resetNewRole() {
this.newRole = {
resetaddRole() {
this.addRole = {
id: '',
name: '',
describe: '',
accessibleRoutes: []
}
},
confirmNewRole() {
newRole(this.newRole).then(res => {
this.newRole.id = res.data.id
this.rolesData.push(deepClone(this.newRole))
this.resetNewRole()
this.newRoleDialogVisible = false
confirmaddRole() {
addRole(this.addRole).then(res => {
this.addRole.id = res.data.id
this.rolesData.push(deepClone(this.addRole))
this.resetaddRole()
this.addRoleDialogVisible = false
})
},
cancleNewRole() {
this.resetNewRole()
this.newRoleDialogVisible = false
cancleaddRole() {
this.resetaddRole()
this.addRoleDialogVisible = false
}
}
}