动态菜单和按钮控制-前端权限控制-RBAC模型

动态菜单和按钮控制-前端权限控制-RBAC模型

目录




内容

1、前文回顾

要实现动态菜单和按钮控制,需要菜单和按钮权限数据,这些我们在之前的博文中已实现。
相关博文如下:

  1. 层级菜单生成算法
  2. 菜单和按钮权限数据封装返回

2、动态菜单

2.1、原理

  1. 数据库中给不同用户赋予不同的菜单权限,
  2. 用户登录获取菜单列表
  3. 前端路由加载菜单

2.2、对比发现问题

菜单的生成依赖与前端路由控制。

  • 框架默认路由对象:

      {
      	path: "/zip",
      	component: Layout,
      	redirect: "/zip/download",
      	alwaysShow: true,
      	name: "Zip",
      	meta: { title: "压缩", icon: "zip" },
      	children: [
      	  {
      		path: "download",
      		component: () => import("@/views/zip/index"),
      		name: "ExportZip",
      		meta: { title: "导出压缩" }
      	  }
      	]
        }
    
  • 后端返回的菜单对象:

      {
      	"id": "1352785556979511297",
      	"name": "companyList",
      	"path": "companyList",
      	"type": 1,
      	"orderNum": 1,
      	"pid": "1352785556979511296",
      	"hidden": false,
      	"meta": {
      	  "icon": "company",
      	  "title": "公司管理"
      	}
       }
    

小伙伴们发现了什么不吗?

  1. 是的我们自己构造的菜单对象中缺少路由对应的组件,即component属性。我们需要在控制动态菜单生成的地方自己构建。
  2. 原有路由是通过菜单对象 meta{roles: [角色]}实现动态菜单,而我们通过用户具有的菜单权限来控制。

通过查找我们发现路由对象数组生成方法为generateRoutes,方法位于@/store/modules/permission.js中。

2.3 改造

  • 代码如下:

      generateRoutes({ commit }, menus) {
      	return new Promise(resolve => {
      	  // let accessedRoutes
      	  // if (roles.includes('admin')) {
      	  //   accessedRoutes = asyncRoutes || []
      	  // } else {
      	  //   let accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      	  // // }
      	  // 生成路由
      	  let accessedRoutes
      	  menus.forEach(v => {
      		v.component = Layout
      		if(v.children && v.children.length > 0) {
      		  v.children.forEach(c => {
      			c.component = (resolve) => require(["@/views/" + v.name + "/" + c.name],resolve)
      		  })
      		  // "@/views/" + v.name + "/" + c.name
      		}
      	  })
      	  accessedRoutes = menus
      	  commit('SET_ROUTES', accessedRoutes)
      	  resolve(accessedRoutes)
      	})
        }
    
  • 解析:

    • 原有component通过import 来动态烂加载路由组件,这里我们构建后会报错,具体原理不是很清楚,我们改又ES5语法require实现

3、按钮控制

3.1、原理

  1. 数据库不同用户赋予不同的按钮权限-字符串标志
  2. 用户登录获取按钮权限数组
  3. 判断是否又权限,按钮组件v-if来控制显示与否

3.2、实现

因为登录之后又很多页面,每个页面又很多的按钮,而判断逻辑都一样,所有我们把判断逻辑封装为方法,挂在到Vue示例上,具体代码如下:

import store from './store'
...
Vue.prototype.$hasPerm = (perm) => {
  let btns = store.getters.btns
  if (btns && btns.length > 0) {
   return btns.includes(perm)
  }
  return false
}

这里简单列举一个按钮示例:

 <el-button
		class="filter-item"
		style="margin-left: 10px;"
		type="primary"
		icon="el-icon-edit"
		@click="handleCreate"
		v-if="$hasPerm('sys:company:save')"
	  >
		添加
</el-button>

4、效果展示与问题

4.1、效果展示

  • 管理员用户登录界面:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GpWvi7YQ-1611749770257)(./images/2021-01-27_ret-auth-admin.png)]

  • 其他某个用户登录:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lSQA8v9U-1611749770266)(./images/2021-01-27_ret-auth-normal.png)]

4.2、问题

  1. main.js作为入口,代码越简洁越好,我们把判断按钮显示与否的方法写在main.js中
  2. 按钮权限控制,我们是在具体的每个按钮组件处判断,且与权限标志字符串,比如’sys:company:save’耦合在一起,不利于后期修改

问题2暂时没想到比较好的解决办法,问题1后面有空优化以下。其中非重要的页面列表和详情,默认所有用户都可以查看,即没有加权限。

后记

本项目为参考某马视频开发,相关视频及配套资料可自行度娘或者联系本人。上面为自己编写的开发文档,持续更新。欢迎交流,本人QQ:806797785

后端JAVA源代码地址:https://gitee.com/gaogzhen/ihrm-parent    // 后端项目
前端项目源代码地址:https://gitee.com/gaogzhen/ihrm-vue    // 前端后台管理系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值