Commit cac682b4 authored by 智勇's avatar 智勇

路由权限

parent 7c64a533
...@@ -16,6 +16,11 @@ router.beforeEach((to, from, next) => { ...@@ -16,6 +16,11 @@ router.beforeEach((to, from, next) => {
if (sessionStorage.getItem('qahome_env')) { if (sessionStorage.getItem('qahome_env')) {
if (store.getters.roles.length === 0) { if (store.getters.roles.length === 0) {
store.dispatch('GetInfo').then(res => { store.dispatch('GetInfo').then(res => {
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
})
next() next()
}).catch((err) => { }).catch((err) => {
store.dispatch('FedLogOut').then(() => { store.dispatch('FedLogOut').then(() => {
......
...@@ -22,6 +22,7 @@ import Layout from '../views/layout/Layout' ...@@ -22,6 +22,7 @@ import Layout from '../views/layout/Layout'
breadcrumb: false if false, the item will hidden in breadcrumb(default is true) breadcrumb: false if false, the item will hidden in breadcrumb(default is true)
} }
**/ **/
export const constantRouterMap = [ export const constantRouterMap = [
{ path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/login', component: () => import('@/views/login/index'), hidden: true },
{ path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '/404', component: () => import('@/views/404'), hidden: true },
...@@ -76,6 +77,27 @@ export const constantRouterMap = [ ...@@ -76,6 +77,27 @@ export const constantRouterMap = [
] ]
}, },
{
path: '/',
name: 'Dashboard',
component: Layout,
hidden: true,
children: [{
path: 'dashboard',
component: () => import('@/views/dashboard/index')
}]
},
{ path: '*', redirect: '/404', hidden: true }
]
export default new Router({
mode: 'history', // 后端支持可开
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap
})
export const asyncRouterMap = [
{ {
path: '/user', path: '/user',
component: Layout, component: Layout,
...@@ -85,8 +107,8 @@ export const constantRouterMap = [ ...@@ -85,8 +107,8 @@ export const constantRouterMap = [
}, },
children: [ children: [
{ {
path: '', path: 'op',
name: 'User', name: 'op',
component: () => import('@/views/user/index'), component: () => import('@/views/user/index'),
meta: { title: '常用操作' } meta: { title: '常用操作' }
}, },
...@@ -94,33 +116,14 @@ export const constantRouterMap = [ ...@@ -94,33 +116,14 @@ export const constantRouterMap = [
path: 'userManager', path: 'userManager',
name: 'userManager', name: 'userManager',
component: () => import('@/views/user/manager'), component: () => import('@/views/user/manager'),
meta: { title: '用户管理' } meta: { title: '用户管理', roles: ['admin'] }
}, },
{ {
path: 'roleManager', path: 'roleManager',
name: 'roleManager', name: 'roleManager',
component: () => import('@/views/user/roleManager'), component: () => import('@/views/user/roleManager'),
meta: { title: '角色管理' } meta: { title: '角色管理', roles: ['admin'] }
} }
] ]
}, }
{
path: '/',
name: 'Dashboard',
component: Layout,
hidden: true,
children: [{
path: 'dashboard',
component: () => import('@/views/dashboard/index')
}]
},
{ path: '*', redirect: '/404', hidden: true }
] ]
export default new Router({
mode: 'history', // 后端支持可开
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap
})
...@@ -5,6 +5,8 @@ const getters = { ...@@ -5,6 +5,8 @@ const getters = {
avatar: state => state.user.avatar, avatar: state => state.user.avatar,
name: state => state.user.name, name: state => state.user.name,
roles: state => state.user.roles, roles: state => state.user.roles,
permission_routers: state => state.permission.routers,
addRouters: state => state.permission.addRouters,
env: state => state.env.name env: state => state.env.name
} }
export default getters export default getters
...@@ -4,6 +4,7 @@ import app from './modules/app' ...@@ -4,6 +4,7 @@ import app from './modules/app'
import user from './modules/user' import user from './modules/user'
import env from './modules/env' import env from './modules/env'
import getters from './getters' import getters from './getters'
import permission from './modules/permission'
Vue.use(Vuex) Vue.use(Vuex)
...@@ -11,6 +12,7 @@ const store = new Vuex.Store({ ...@@ -11,6 +12,7 @@ const store = new Vuex.Store({
modules: { modules: {
app, app,
user, user,
permission,
env env
}, },
getters getters
......
import { asyncRouterMap, constantRouterMap } from '@/router'
/**
* 通过meta.role判断是否与当前用户权限匹配
* @param roles
* @param route
*/
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
/**
* 递归过滤异步路由表,返回符合用户角色权限的路由表
* @param routes asyncRouterMap
* @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)
}
})
return res
}
const permission = {
state: {
routers: [],
addRouters: []
},
mutations: {
SET_ROUTERS: (state, routers) => {
state.addRouters = routers
state.routers = constantRouterMap.concat(routers)
}
},
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()
})
}
}
}
export default permission
...@@ -37,8 +37,8 @@ const user = { ...@@ -37,8 +37,8 @@ const user = {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
getInfo().then(response => { getInfo().then(response => {
const data = response.data const data = response.data
// data.roles = data.roleInfo && data.roleInfo.foleInfos && data.roleInfo.foleInfos[0] && data.roleInfo.foleInfos[0].roleId === 1 ? ['admin'] : ['channel'] data.roles = data.roleInfo.roleInfos && data.roleInfo.roleInfos[0] && data.roleInfo.roleInfos[0].roleId === 1 ? ['admin'] : ['channel']
data.roles = data.rank.indexOf('CHANNEL') !== -1 ? ['channel'] : ['admin'] // data.roles = data.rank.indexOf('CHANNEL') !== -1 ? ['channel'] : ['admin']
if (data.roles && data.roles.length > 0) { if (data.roles && data.roles.length > 0) {
commit('SET_ROLES', data.roles) commit('SET_ROLES', data.roles)
} else { } else {
......
...@@ -3,18 +3,17 @@ export default { ...@@ -3,18 +3,17 @@ export default {
name: 'MenuItem', name: 'MenuItem',
functional: true, functional: true,
props: { props: {
meta: { icon: {
type: Object, type: String,
default: () => { default: ''
return { },
title: '', title: {
icon: '' type: String,
} default: ''
}
} }
}, },
render(h, context) { render(h, context) {
const { icon, title } = context.props.meta const { icon, title } = context.props
const vnodes = [] const vnodes = []
if (icon) { if (icon) {
......
<template> <template>
<div v-if="!item.hidden" class="menu-wrapper"> <div v-if="!item.hidden&&item.children" class="menu-wrapper">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"> <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link :to="resolvePath(onlyOneChild.path)"> <app-link :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :meta="Object.assign({},item.meta,onlyOneChild.meta)" /> <item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon||item.meta.icon" :title="onlyOneChild.meta.title" />
</el-menu-item> </el-menu-item>
</app-link> </app-link>
</template> </template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body> <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)">
<template slot="title"> <template slot="title">
<item :meta="item.meta" /> <item v-if="item.meta" :icon="item.meta.icon" :title="item.meta.title" />
</template>
<template v-for="child in item.children">
<template v-if="!child.hidden">
<sidebar-item
v-if="child.children&&child.children.length>0"
:is-nest="true"
:item="child"
:key="child.path"
:base-path="resolvePath(child.path)"
class="nest-menu" />
<app-link v-else :to="resolvePath(child.path)" :key="child.name">
<el-menu-item :index="resolvePath(child.path)">
<item v-if="child.meta" :icon="child.meta.icon" :title="child.meta.title" />
</el-menu-item>
</app-link>
</template>
</template> </template>
<sidebar-item
v-for="child in item.children"
:is-nest="true"
:item="child"
:key="child.path"
:base-path="resolvePath(child.path)"
class="nest-menu" />
</el-submenu> </el-submenu>
</div> </div>
...@@ -50,13 +61,12 @@ export default { ...@@ -50,13 +61,12 @@ export default {
} }
}, },
data() { data() {
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237 return {
// TODO: refactor with render function onlyOneChild: null
this.onlyOneChild = null }
return {}
}, },
methods: { methods: {
hasOneShowingChild(children = [], parent) { hasOneShowingChild(children, parent) {
const showingChildren = children.filter(item => { const showingChildren = children.filter(item => {
if (item.hidden) { if (item.hidden) {
return false return false
...@@ -81,10 +91,13 @@ export default { ...@@ -81,10 +91,13 @@ export default {
return false return false
}, },
resolvePath(routePath) { resolvePath(routePath) {
if (isExternal(routePath)) { if (this.isExternalLink(routePath)) {
return routePath return routePath
} }
return path.resolve(this.basePath, routePath) return path.resolve(this.basePath, routePath)
},
isExternalLink(routePath) {
return isExternal(routePath)
} }
} }
} }
......
...@@ -9,25 +9,23 @@ ...@@ -9,25 +9,23 @@
:collapse-transition="false" :collapse-transition="false"
mode="vertical" mode="vertical"
> >
<sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path"/> <sidebar-item v-for="route in permission_routers" :key="route.path" :item="route" :base-path="route.path"/>
</el-menu> </el-menu>
</el-scrollbar> </el-scrollbar>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import variables from '@/styles/variables.scss'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'
export default { export default {
components: { SidebarItem }, components: { SidebarItem },
computed: { computed: {
...mapGetters([ ...mapGetters([
'permission_routers',
'sidebar' 'sidebar'
]), ]),
routes() {
return this.$router.options.routes
},
variables() { variables() {
return variables return variables
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment