From 650803bcd921face297848cb4042ac3a9bc5aeeb Mon Sep 17 00:00:00 2001 From: wwlleo0730 Date: Thu, 14 Feb 2019 16:14:06 +0800 Subject: [PATCH] feat: menus get from remote --- src/api/menu.js | 11 + src/mock/index.js | 4 + src/mock/menu.js | 72 +++++++ src/permission.js | 10 +- src/router/index.js | 37 ++-- src/store/modules/permission.js | 89 +++++++- src/utils/validate.js | 16 ++ src/views/console/dept/index.vue | 9 + src/views/console/dict/index.vue | 5 + src/views/console/menu/index.vue | 19 ++ src/views/console/role/index.vue | 5 + src/views/console/user/index.vue | 355 +++++++++++++++++++++++++++++++ 12 files changed, 604 insertions(+), 28 deletions(-) create mode 100644 src/api/menu.js create mode 100644 src/mock/menu.js create mode 100644 src/views/console/dept/index.vue create mode 100644 src/views/console/dict/index.vue create mode 100644 src/views/console/menu/index.vue create mode 100644 src/views/console/role/index.vue create mode 100644 src/views/console/user/index.vue diff --git a/src/api/menu.js b/src/api/menu.js new file mode 100644 index 00000000..a79ec419 --- /dev/null +++ b/src/api/menu.js @@ -0,0 +1,11 @@ +import request from '@/utils/request' +/** + *根据角色获得可见菜单 + */ +export function getMenuByRole(query) { + return request({ + url: '/menus/role', + method: 'get', + params: query + }) +} diff --git a/src/mock/index.js b/src/mock/index.js index 3e00e918..9f876f18 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 menuAPI from './menu' // 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题 // https://github.com/nuysoft/Mock/issues/300 @@ -23,6 +24,9 @@ Mock.mock(/\/login\/login/, 'post', loginAPI.loginByUsername) Mock.mock(/\/login\/logout/, 'post', loginAPI.logout) Mock.mock(/\/user\/info\.*/, 'get', loginAPI.getUserInfo) +// 角色相关 +Mock.mock(/\/menus\/role/, 'get', menuAPI.getMenuByRole) + // 文章相关 Mock.mock(/\/article\/list/, 'get', articleAPI.getList) Mock.mock(/\/article\/detail/, 'get', articleAPI.getArticle) diff --git a/src/mock/menu.js b/src/mock/menu.js new file mode 100644 index 00000000..6e3622d9 --- /dev/null +++ b/src/mock/menu.js @@ -0,0 +1,72 @@ +const menuData = +[ + { + 'id': 1, + 'path': '/console', + 'redirect': 'noredirect', + 'component': 'Layout', + 'name': 'console', + 'title': '系统管理', + 'icon': 'component', + 'parentId': -1, + 'children': [ + { + 'children': [], + 'name': 'user', + 'component': 'console/user/index', + 'id': 7, + 'title': '用户管理', + 'icon': 'user', + 'parentId': 1, + 'path': 'user' + }, + { + 'children': [], + 'name': 'menu', + 'component': 'console/menu/index', + 'id': 8, + 'title': '菜单管理', + 'icon': 'documentation', + 'parentId': 1, + 'path': 'menu' + }, + { + 'children': [], + 'name': 'role', + 'component': 'console/role/index', + 'id': 9, + 'title': '角色管理', + 'icon': 'documentation', + 'parentId': 1, + 'path': 'role' + }, + { + 'children': [], + 'name': 'dict', + 'component': 'console/dict/index', + 'id': 10, + 'title': '字典管理', + 'icon': 'documentation', + 'parentId': 1, + 'path': 'dict' + }, + { + 'children': [], + 'name': 'dept', + 'component': 'console/dept/index', + 'id': 11, + 'title': '部门管理', + 'icon': 'documentation', + 'parentId': 1, + 'path': 'dept' + } + ] + } + +] + +export default { + getMenuByRole: config => { + return menuData + } +} diff --git a/src/permission.js b/src/permission.js index e556cb00..6465b472 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,7 +4,7 @@ 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 { validatenull } from '@/utils/validate' NProgress.configure({ showSpinner: false })// NProgress Configuration // permission judge function @@ -27,8 +27,12 @@ router.beforeEach((to, from, next) => { 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) // 动态添加可访问路由表 + store.dispatch('GenerateRoutes', { roles }).then((accessedRouters) => { // 根据roles权限生成可访问的路由表 + if (!validatenull(accessedRouters)) { + router.addRoutes(accessedRouters) + } else { + next({ path: '/401', replace: true, query: { noGoBack: true }}) + } // 动态添加可访问路由表 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record }) }).catch((err) => { diff --git a/src/router/index.js b/src/router/index.js index dda18156..f7d34ba8 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -75,7 +75,16 @@ export const constantRouterMap = [ meta: { title: 'dashboard', icon: 'dashboard', noCache: true } } ] - }, + } +] + +export default new Router({ + // mode: 'history', // require service support + scrollBehavior: () => ({ y: 0 }), + routes: constantRouterMap +}) + +let localRoutermap = [ { path: '/documentation', component: Layout, @@ -101,16 +110,7 @@ export const constantRouterMap = [ meta: { title: 'guide', icon: 'guide', noCache: true } } ] - } -] - -export default new Router({ - // mode: 'history', // require service support - scrollBehavior: () => ({ y: 0 }), - routes: constantRouterMap -}) - -export const asyncRouterMap = [ + }, { path: '/permission', component: Layout, @@ -142,7 +142,6 @@ export const asyncRouterMap = [ } ] }, - { path: '/icon', component: Layout, @@ -193,7 +192,6 @@ export const asyncRouterMap = [ } ] }, - { path: '/tab', component: Layout, @@ -206,7 +204,6 @@ export const asyncRouterMap = [ } ] }, - { path: '/error', component: Layout, @@ -366,3 +363,15 @@ export const asyncRouterMap = [ { path: '*', redirect: '/404', hidden: true } ] + +const routerGetType = 'local' + +if (routerGetType === 'server') { + localRoutermap = [ + { path: '*', redirect: '/404', hidden: true } + ] +} + +export const routerMode = routerGetType + +export const asyncRouterMap = localRoutermap diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js index 13f60efb..77994881 100644 --- a/src/store/modules/permission.js +++ b/src/store/modules/permission.js @@ -1,4 +1,9 @@ -import { asyncRouterMap, constantRouterMap } from '@/router' +import { asyncRouterMap, constantRouterMap, routerMode } from '@/router' + +import { validatenull } from '@/utils/validate' +// for get menus from server +import { getMenuByRole } from '@/api/menu' +import Layout from '@/views/layout/Layout' /** * 通过meta.role判断是否与当前用户权限匹配 @@ -47,19 +52,81 @@ const permission = { }, actions: { GenerateRoutes({ commit }, data) { - return new Promise(resolve => { + // default routerMode is local + if (routerMode === 'local') { + return new Promise(resolve => { + const { roles } = data + let accessedRouters + if (roles.includes('admin')) { + accessedRouters = asyncRouterMap + } else { + accessedRouters = filterAsyncRouter(asyncRouterMap, roles) + } + commit('SET_ROUTERS', accessedRouters) + // return for add to router + resolve(accessedRouters) + }) + } else { const { roles } = data - let accessedRouters - if (roles.includes('admin')) { - accessedRouters = asyncRouterMap - } else { - accessedRouters = filterAsyncRouter(asyncRouterMap, roles) - } - commit('SET_ROUTERS', accessedRouters) - resolve() - }) + return new Promise((resolve, reject) => { + getMenuByRole(roles[0]).then(response => { + if (!response.data) { + reject('GenerateRoutesFromServer failed, please try later again.') + } + + const menus = response.data + + if (menus.length === 0) { + reject('menus data is null') + } + const accessedRouters = buildRouter(menus) + // final add 404 + accessedRouters.push({ path: '*', redirect: '/404', hidden: true }) + // commit to stores + commit('SET_ROUTERS', accessedRouters) + // return for add to router + resolve(accessedRouters) + }) + }) + } } } } +/** ************************************ + * build Router by menu api + * add 20190213 +***************************************/ +function buildRouter(aMenu) { + const aRouter = [] + aMenu.forEach(item => { + if (!validatenull(item.component)) { + const oRouter = { + meta: { 'title': '', 'icon': '' }, + children: [] + } + + if (item.component === 'Layout') { + oRouter.component = Layout + } else { + oRouter.component = require('@/views/' + item.component + '.vue').default + } + + oRouter.path = item.path + oRouter.name = item.name + oRouter.id = item.id || null + oRouter.redirect = item.redirect || null + oRouter.meta.icon = item.icon + oRouter.meta.title = item.title + oRouter.meta.noCache = item.noCache || false + oRouter.meta.breadcrumb = item.breadcrumb || true + oRouter.children = validatenull(item.children) ? [] : buildRouter(item.children) + + aRouter.push(oRouter) + } + }) + + return aRouter +} + export default permission diff --git a/src/utils/validate.js b/src/utils/validate.js index ada0e7e2..69764506 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -40,3 +40,19 @@ export function validateEmail(email) { const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ return re.test(email) } + +/** + * validate null + * @param {*} val + */ +export function validatenull(val) { + if (val instanceof Array) { + if (val.length === 0) return true + } else if (val instanceof Object) { + if (JSON.stringify(val) === '{}') return true + } else { + if (val === 'null' || val === null || val === 'undefined' || val === undefined || val === '') return true + return false + } + return false +} diff --git a/src/views/console/dept/index.vue b/src/views/console/dept/index.vue new file mode 100644 index 00000000..2add1eec --- /dev/null +++ b/src/views/console/dept/index.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/views/console/dict/index.vue b/src/views/console/dict/index.vue new file mode 100644 index 00000000..796fce64 --- /dev/null +++ b/src/views/console/dict/index.vue @@ -0,0 +1,5 @@ + diff --git a/src/views/console/menu/index.vue b/src/views/console/menu/index.vue new file mode 100644 index 00000000..0ce24abf --- /dev/null +++ b/src/views/console/menu/index.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/views/console/role/index.vue b/src/views/console/role/index.vue new file mode 100644 index 00000000..445e4f03 --- /dev/null +++ b/src/views/console/role/index.vue @@ -0,0 +1,5 @@ + diff --git a/src/views/console/user/index.vue b/src/views/console/user/index.vue new file mode 100644 index 00000000..cac935e4 --- /dev/null +++ b/src/views/console/user/index.vue @@ -0,0 +1,355 @@ + + +