目录
一、系统菜单栏权限
二、系统页面按钮权限
在企业开发中,不同的用户所扮演的角色不一样,角色拥有权限,所以用户拥有角色,就会有角色对应的权限。例如,张三是系统管理员角色,登录后就拥有整个系统的权限;李四是财务角色,登录后就拥有薪资相关的权限。员工拥有角色,角色拥有权限。那么如何控制系统导航栏的左侧菜单是否显示呢?这就涉及到动态路由了。
一、系统菜单栏权限
不同用户拥有的菜单栏权限不一样
静态路由:将所有人员共有的页面设置成静态路由,如登录页,注册页,个人信息页
动态路由:需要权限才能访问的都设置成动态路由。这里把动态路由都是模块化的
在哪个位置筛选用户所拥有的权限呢?
在路由前置守卫中获取,因为这里每跳转一个页面都会请求用户信息
如何匹配呢?
用户登录后,会携带相关的信息,其中包含了自身所拥有的权限名。只需要为每个一级路由设置 name 属性,过滤掉动态路由中用户没有拥有的权限,剩下的就是用户拥有的权限,再将这些权限重新添加到路由信息中即可。
步骤:
1. Vuex 的用户模块返回用户信息
2. 在派发用户信息的时候,就会接收到一个返回值,这个返回值就是用户信息
注:dispatch('模块名/派发方法'),模块名前面不能加 /
3. 为所有动态路由的一级路由添加 name 名称,这里的 name 名称和用户携带的权限名必须要一致。
4. 在前置路由中筛选出用户拥有的路由权限
5. 使用 addRoutes 动态添加路由,添加完后必须要转发一下,这是已知的缺点
6. 为了解决 404 问题,动态添加 404 页面,然后去 /router/index 文件中找到静态路由,将 404 路由删除
权限应用整体代码
// 如果没有获取到userId, 则发请求
if (!store.getters.userId) {
const { roles } = await store.dispatch('user/getUserInfo')
// console.log(roles.menus) // 数组 不确定 可能是8个 1个 0个
// console.log(asyncRoutes) // 数组 8个
// 筛选用户所拥有的权限, 如果 是 true则会返回数据,false 不返回
const filterRoutes = asyncRoutes.filter(item => {
// return true/false
return roles.menus.includes(item.name)
}) // 筛选后的路由
store.commit('user/setRoutes', filterRoutes) // 调用了 user.js 中的 action
router.addRoutes([...filterRoutes, { path: '*', redirect: '/404', hidden: true }]) // 添加动态路由信息到路由表
// router添加动态路由之后 需要转发一下
next(to.path) // 目的是让路由拥有信息 router的已知缺陷
} else {
next() // 放过
}
这样我们就已经筛选好路由了,但是登录系统发现菜单栏并没有显示响应的路由菜单。原来是动态添加的路由不具备响应式,需要使用 Vuex 共享路由信息。
1. Vuex 用户模块声明 state 和 mutation
mutation
2. 使用 getters 简化 state 属性
3. 左侧菜单栏引用 gettes (Layout/components/Sidebar/index.vue)
但是会有一个bug, 张三登录后有10个权限,退出后李四登录,张三的10个权限还在。虽然在系统的菜单栏是正常的,但在浏览器中输入一个张三没有的权限却能访问。
需要在退出登录时调用清除路由的方法。
二、系统页面按钮权限
虽然上面已经做过权限,但只是对菜单栏的权限。在一些场景中,不同用户对页面中的操作权限也有控制。例如在员工列表页面,管理员可以新增用户,但普通的用户不能新增。
那用户权限标识从何而来呢?
可以在添加权限时进行判断为其区分,当 type = 1 时为页面路由权限,当 type = 2 时为 按钮权限。
自定义指令封装按钮功能权限
在 vue 入口文件自定义指令,
// 封装自定义指令, 用于控制操作权
Vue.directive('permission', {
// 在使用指令的元素插入到页面后生效
// el 是当前指令作用的元素对象
// binding 是 v-permission="表达式" 表达式的信息
inserted(el, binding) {
// console.log(el, binding)
// store.state.user.userInfo?.roles?.points 的 ? 表示 可选链,防止为空
// || [] 表示如果前面的表达式为空,还是可以让 points 这个变量是个 数组
const points = store.state.user.userInfo?.roles?.points || [] // 当前用户信息的操作权
if (!points.includes(binding.value)) {
// 不存在就要删除或者禁用
el.remove() // 删除元素
// el.disabled = true
// 线上的权限数据和线下的代码进行对应
}
}
})
在页面上对需要添加权限的按钮使用自定义指令。这样就设置好了。
有权限
无权限