后台管理系统-权限管理
后台管理系统-权限管理
操作权限可以通过后台实现,比如增删查改时调接口,根据接口返回的code码,判断是否有操作权限,然后给用户无权限的提示。
但是此做法对用户来说体验并不好,如果没有权限就不展示对应的操作按钮就行了,要做到这点的话,就需要前后端共同完成了。
需要的接口:
1、接口 :供前端添加菜单导航、按钮等
2、接口: 供前端给对应的操作添加权限
3、接口: 供前端获取有权限的操作按钮
前端操作:
1、获取当前路由及子路由下有权限的按钮,并将其存入sessionStorage
2、根据接口返回的数据,动态的展示有权限的按钮
前端主要代码如下:
1 const state = { 2 menuTree: [], // 菜单列表 3 btnPermission: JSON.parse(sessionStorage.getItem('btnPermission')) || [], // 按钮权限 4 } 5 6 const mutations = { 7 SET_BTN_PERMISSIONS(state, data) { 8 state.btnPermission = data 9 sessionStorage.setItem('btnPermission', JSON.stringify(data)) 10 }, 11 } 12 13 // 判断当前路由是否在资源菜单内 14 const isInMenu = (arr, string) => { 15 let bool = false 16 ;(function getBool(arr, string) { 17 for (const x of arr) { 18 if (x.menuRouterPath === string) { 19 bool = true 20 return 21 } 22 getBool(x.children, string) 23 } 24 })(arr, string) 25 26 return bool 27 } 28 29 // 找到对应资源菜单下的子菜单(按钮)map 30 const filterBtnRoutes = (arr, string) => { 31 let res = [] 32 ;(function gerRoute(arr, string) { 33 for (const x of arr) { 34 if (x.menuRouterPath === string) { 35 res = x.children 36 return res 37 } 38 gerRoute(x.children, string) 39 } 40 })(arr, string) 41 return res 42 } 43 44 // 按钮下级可能还有按钮,循环获取当前路由下的所有按钮 45 const flatten = arr => { 46 const flattend = [] 47 ;(function flat(arr) { 48 arr.forEach(x => { 49 flattend.push(x) 50 if (Array.isArray(x.children) && x.children.length > 0) { 51 flat(x.children) 52 } 53 }) 54 })(arr) 55 return flattend 56 } 57 58 const actions = { 59 getBtnPermissions({ state, commit }, params) { 60 // 判断当前路由是否在资源菜单内 61 const isMenu = isInMenu(state.menuTree, params) 62 63 // 当其在资源菜单内,路由变更更新按钮权限,否则为子页面,保留按钮权限 64 if (isMenu) { 65 // 找到对应资源菜单下的子菜单(按钮)map, 页面对应button,menuType-2 66 const btns = filterBtnRoutes(state.menuTree, params).filter(x => x.menuType === 2) 67 68 const flatBtns = flatten(btns) 69 const btnPermission = flatBtns.map(x => x.buttonCode) 70 commit('SET_BTN_PERMISSIONS', btnPermission) 71 } 72 }, 73 } 74 75 76 77 // 路由卫士:跳转前的操作 78 router.beforeEach(async (to, from, next) => { 79 const appState = store.state.app 80 nProgress.start() 81 if (to.meta.system) { 82 next() 83 } else { 84 if (appState.token) { 85 if (!appState.userInfo?.username) { 86 await store.dispatch('app/getUserInfo') 87 } 88 if (appState.menuTree.length === 0) { 89 await store.dispatch('app/getMenuTree') 90 } 91 // 跳转路由,获取路由下有权限的按钮 92 store.dispatch('app/getBtnPermissions', to.path) 93 if (from.meta.cache) { 94 store.commit('cache/ADD_CACHEDVIEW', from) 95 } 96 next() 97 } else { 98 next(`/login?redirect=${to.path}`) 99 } 100 } 101 }) 102 103 104 105 // 全局判断是否有按钮权限 106 app.config.globalProperties.$hasBtnPermission = key => { 107 const btnPermissions = store.state.app.btnPermission 108 return key ? btnPermissions.includes(key) : false 109 } 110 111 112 // 展示有权限的按钮 113 if="$hasBtnPermission('add')">新增 114 if="$hasBtnPermission('edit')">编辑 115 if="$hasBtnPermission('delete')">删除 116 117 // 侧边或顶部导航菜单,直接根据接口返回的有权限的数据循环出来