diff --git a/src/main.js b/src/main.js index c4224f2c..c9b3f995 100644 --- a/src/main.js +++ b/src/main.js @@ -20,7 +20,6 @@ import Sticky from 'components/Sticky'; // 粘性header组件 import vueWaves from './directive/waves';// 水波纹指令 import errLog from 'store/errLog';// error log组件 import './mock/index.js'; // 该项目所有请求使用mockjs模拟 -import permission from 'store/permission'; // 权限控制 // register globally Vue.component('multiselect', Multiselect); @@ -36,6 +35,7 @@ Object.keys(filters).forEach(key => { // permissiom judge function hasPermission(roles, permissionRoles) { if (roles.indexOf('admin') >= 0) return true; // admin权限 直接通过 + if (!permissionRoles) return true; return roles.some(role => permissionRoles.indexOf(role) >= 0) } @@ -47,42 +47,24 @@ router.beforeEach((to, from, next) => { if (to.path === '/login') { next({ path: '/' }); } else { - if (to.meta && to.meta.role) { // 判断即将进入的页面是否需要权限 - if (store.getters.roles.length !== 0) { // 判断当前用户是否已拉取完info信息 - if (hasPermission(store.getters.roles, to.meta.role)) { // 判断权限 - next(); // 有权限 - } else { - next({ path: '/401', query: { noGoBack: true } }); // 无权限 - } - } else { // 未拉取info信息 - store.dispatch('GetInfo').then(() => { // 拉取info - permission.init({ // 初始化权限 - roles: store.getters.roles, - router: router.options.routes - }); - if (hasPermission(store.getters.roles, to.meta.role)) { // 判断权限 - next();// 有权限 - } else { - next({ path: '/401', query: { noGoBack: true } }); // 无权限 - } - }).catch(err => { - console.log(err); - }); - } - } else { // 页面不需要权限 直接进入 - if (store.getters.roles.length !== 0) { - next(); + if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完info信息 + store.dispatch('GetInfo').then(res => { // 拉取info + const roles = res.data.role; + store.dispatch('GenerateRoutes', { roles }).then(() => { // 生成可访问的路由表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + next(to); // hack方法 确保addRoutes已完成 + }) + }).catch(err => { + console.log(err); + }); + } else { + // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓ + if (hasPermission(store.getters.roles, to.meta.role)) { + next();// } else { - store.dispatch('GetInfo').then(() => { - permission.init({ - roles: store.getters.roles, - router: router.options.routes - }); - next(); - }).catch(err => { - console.log(err); - }); + next({ path: '/401', query: { noGoBack: true } }); } + // 可删 ↑ } } } else { @@ -95,6 +77,7 @@ router.beforeEach((to, from, next) => { } }); + router.afterEach(() => { NProgress.done(); // 结束Progress }); diff --git a/src/router/index.js b/src/router/index.js index 76204649..d566cc9a 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -70,49 +70,56 @@ Vue.use(Router); * noDropdown : if noDropdown:true will not has submenu * meta : { role: ['admin'] } will control the page role */ -export default new Router({ - // mode: 'history', //后端支持可开 - scrollBehavior: () => ({ y: 0 }), - routes: [ + +export const constantRouterMap = [ { path: '/login', component: Login, hidden: true }, { path: '/authredirect', component: authRedirect, hidden: true }, { path: '/sendpwd', component: sendPWD, hidden: true }, { path: '/reset', component: reset, hidden: true }, { path: '/404', component: Err404, hidden: true }, { path: '/401', component: Err401, hidden: true }, - { - path: '/', - component: Layout, - redirect: '/dashboard', - name: '首页', - hidden: true, - children: [{ path: 'dashboard', component: dashboard }] - }, - { - path: '/introduction', - component: Layout, - redirect: '/introduction/index', - icon: 'xinrenzhinan', - noDropdown: true, - children: [{ path: 'index', component: Introduction, name: '简述' }] - }, - { - path: '/permission', - component: Layout, - redirect: '/permission/index', - name: '权限测试', - icon: 'quanxian', - meta: { role: ['admin'] }, - noDropdown: true, - children: [{ path: 'index', component: Permission, name: '权限测试页', meta: { role: ['admin'] } }] - }, - { - path: '/components', - component: Layout, - redirect: '/components/index', - name: '组件', - icon: 'zujian', - children: [ + { + path: '/', + component: Layout, + redirect: '/dashboard', + name: '首页', + hidden: true, + children: [{ path: 'dashboard', component: dashboard }] + }, + { + path: '/introduction', + component: Layout, + redirect: '/introduction/index', + icon: 'xinrenzhinan', + noDropdown: true, + children: [{ path: 'index', component: Introduction, name: '简述' }] + } +] + +export default new Router({ + // mode: 'history', //后端支持可开 + scrollBehavior: () => ({ y: 0 }), + routes: constantRouterMap +}); + +export const asyncRouterMap = [ + { + path: '/permission', + component: Layout, + redirect: '/permission/index', + name: '权限测试', + icon: 'quanxian', + meta: { role: ['admin'] }, + noDropdown: true, + children: [{ path: 'index', component: Permission, name: '权限测试页', meta: { role: ['admin'] } }] + }, + { + path: '/components', + component: Layout, + redirect: '/components/index', + name: '组件', + icon: 'zujian', + children: [ { path: 'index', component: componentsIndex, name: '介绍 ' }, { path: 'tinymce', component: Tinymce, name: '富文本编辑器' }, { path: 'markdown', component: Markdown, name: 'Markdown' }, @@ -124,75 +131,73 @@ export default new Router({ { path: 'sticky', component: Sticky, name: 'Sticky' }, { path: 'countto', component: CountTo, name: 'CountTo' }, { path: 'mixin', component: Mixin, name: '小组件' } - ] - }, - { - path: '/charts', - component: Layout, - redirect: '/charts/index', - name: '图表', - icon: 'tubiaoleixingzhengchang', - children: [ + ] + }, + { + path: '/charts', + component: Layout, + redirect: '/charts/index', + name: '图表', + icon: 'tubiaoleixingzhengchang', + children: [ { path: 'index', component: chartIndex, name: '介绍' }, { path: 'keyboard', component: KeyboardChart, name: '键盘图表' }, { path: 'keyboard2', component: KeyboardChart2, name: '键盘图表2' }, { path: 'line', component: LineMarker, name: '折线图' }, { path: 'mixchart', component: MixChart, name: '混合图表' } - ] - }, - { - path: '/errorpage', - component: Layout, - redirect: 'noredirect', - name: '错误页面', - icon: '404', - children: [ + ] + }, + { + path: '/errorpage', + component: Layout, + redirect: 'noredirect', + name: '错误页面', + icon: '404', + children: [ { path: '401', component: Err401, name: '401' }, { path: '404', component: Err404, name: '404' } - ] - }, - { - path: '/errlog', - component: Layout, - redirect: 'noredirect', - name: 'errlog', - icon: 'bug', - noDropdown: true, - children: [{ path: 'log', component: ErrorLog, name: '错误日志' }] - }, - { - path: '/excel', - component: Layout, - redirect: 'noredirect', - name: 'excel', - icon: 'EXCEL', - noDropdown: true, - children: [{ path: 'download', component: ExcelDownload, name: '导出excel' }] - }, - { - path: '/theme', - component: Layout, - redirect: 'noredirect', - name: 'theme', - icon: 'theme', - noDropdown: true, - children: [{ path: 'index', component: Theme, name: '换肤' }] - }, - { - path: '/example', - component: Layout, - redirect: 'noredirect', - name: '综合实例', - icon: 'zonghe', - children: [ + ] + }, + { + path: '/errlog', + component: Layout, + redirect: 'noredirect', + name: 'errlog', + icon: 'bug', + noDropdown: true, + children: [{ path: 'log', component: ErrorLog, name: '错误日志' }] + }, + { + path: '/excel', + component: Layout, + redirect: 'noredirect', + name: 'excel', + icon: 'EXCEL', + noDropdown: true, + children: [{ path: 'download', component: ExcelDownload, name: '导出excel' }] + }, + { + path: '/theme', + component: Layout, + redirect: 'noredirect', + name: 'theme', + icon: 'theme', + noDropdown: true, + children: [{ path: 'index', component: Theme, name: '换肤' }] + }, + { + path: '/example', + component: Layout, + redirect: 'noredirect', + name: '综合实例', + icon: 'zonghe', + children: [ { path: 'dynamictable', component: DynamicTable, name: '动态table' }, { path: 'dragtable', component: DragTable, name: '拖拽table' }, { path: 'inline_edit_table', component: InlineEditTable, name: 'table内编辑' }, { path: 'table', component: Table, name: '综合table' }, { path: 'form1', component: Form1, name: '综合form1' } - ] - }, - - { path: '*', redirect: '/404', hidden: true } - ] -}); + ] + }, + { path: '*', redirect: '/404', hidden: true } +]; diff --git a/src/store/getters.js b/src/store/getters.js index 55acbc9c..4677e6d6 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -1,6 +1,5 @@ const getters = { sidebar: state => state.app.sidebar, - livenewsChannels: state => state.app.livenewsChannels, token: state => state.user.token, avatar: state => state.user.avatar, name: state => state.user.name, @@ -10,6 +9,8 @@ const getters = { auth_type: state => state.user.auth_type, status: state => state.user.status, roles: state => state.user.roles, - setting: state => state.user.setting + setting: state => state.user.setting, + permission_routers: state => state.permission.routers, + addRouters: state => state.permission.addRouters }; export default getters diff --git a/src/store/index.js b/src/store/index.js index d3121d07..ee7d313e 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import Vuex from 'vuex'; import app from './modules/app'; import user from './modules/user'; +import permission from './modules/permission'; import getters from './getters'; Vue.use(Vuex); @@ -9,7 +10,8 @@ Vue.use(Vuex); const store = new Vuex.Store({ modules: { app, - user + user, + permission }, getters }); diff --git a/src/store/modules/app.js b/src/store/modules/app.js index ae336fa8..83049ff5 100644 --- a/src/store/modules/app.js +++ b/src/store/modules/app.js @@ -16,21 +16,11 @@ const app = { Cookies.set('sidebarStatus', 0); } state.sidebar.opened = !state.sidebar.opened; - }, - SET_LIVENEWS_CHANNELS: (status, channels) => { - status.livenewsChannels = JSON.stringify(channels); - Cookies.set('livenewsChannels', JSON.stringify(channels)); } }, actions: { ToggleSideBar: ({ commit }) => { commit('TOGGLE_SIDEBAR') - }, - setTheme: ({ commit }, theme) => { - commit('SET_THEME', theme) - }, - setlivenewsChannels: ({ commit }, channels) => { - commit('SET_LIVENEWS_CHANNELS', channels) } } }; diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js new file mode 100644 index 00000000..e1d74371 --- /dev/null +++ b/src/store/modules/permission.js @@ -0,0 +1,51 @@ +import { asyncRouterMap, constantRouterMap } from 'src/router'; + +function hasPermission(roles, route) { + if (route.meta && route.meta.role) { + return roles.some(role => route.meta.role.indexOf(role) >= 0) + } else { + return true + } +} + +const permission = { + state: { + routers: constantRouterMap, + addRouters: [] + }, + + mutations: { + SET_ROUTERS: (state, routers) => { + state.addRouters = routers; + state.routers = constantRouterMap.concat(routers); + } + }, + + actions: { + // s + GenerateRoutes({ commit }, data) { + const { roles } = data; + const accessedRouters = asyncRouterMap.filter(v => { + if (roles.indexOf('admin') >= 0) return true; + if (hasPermission(roles, v)) { + if (v.children && v.children.length > 0) { + v.children = v.children.filter(child => { + if (hasPermission(roles, child)) { + return child + } + return false; + }); + return v + } else { + return v + } + } + return false; + }); + commit('SET_ROUTERS', accessedRouters); + } + } +}; + + +export default permission; diff --git a/src/store/permission.js b/src/store/permission.js deleted file mode 100644 index 7972f2b4..00000000 --- a/src/store/permission.js +++ /dev/null @@ -1,38 +0,0 @@ -const permission = { - state: { - permissionRoutes: [] - }, - init(data) { - const { roles, router } = data; - const permissionRoutes = router.filter(v => { - if (roles.indexOf('admin') >= 0) return true; - if (this.hasPermission(roles, v)) { - if (v.children && v.children.length > 0) { - v.children = v.children.filter(child => { - if (this.hasPermission(roles, child)) { - return child - } - return false; - }); - return v - } else { - return v - } - } - return false; - }); - this.state.permissionRoutes = permissionRoutes; - }, - get() { - return this.state.permissionRoutes - }, - hasPermission(roles, route) { - if (route.meta && route.meta.role) { - return roles.some(role => route.meta.role.indexOf(role) >= 0) - } else { - return true - } - } -}; - -export default permission; diff --git a/src/views/errlog/index.vue b/src/views/errlog/index.vue index 55c7870e..bc0be8fc 100644 --- a/src/views/errlog/index.vue +++ b/src/views/errlog/index.vue @@ -28,4 +28,8 @@ } }; - + diff --git a/src/views/layout/Navbar.vue b/src/views/layout/Navbar.vue index abc18e77..9ac58aa2 100644 --- a/src/views/layout/Navbar.vue +++ b/src/views/layout/Navbar.vue @@ -26,7 +26,7 @@