使用vue自定义指令,实现按钮级别权限

本文涉及的功能涵盖,登录权限管理,vue指令,模块化。但是登录注册的模块,本章会一概而括,具体功能会根据需求而开发。本文只是提供一种思路,毕竟每个功能都会有参差。

1.主账号新增子账号

创建:第一步我们可能会创建子账号的个人信息等内容,前端会校验格式,并掉接口去查重,手机号,姓名等,如果重复的话会给出提示。
​编辑

接下来就是配置子账号的权限了,我们这种是树形结构,用的就是el-tree 的组件

接口返回的树形结构,会携带resourceCode,代表新增时会传给后端,后端同学记录当前勾选的权限是哪些。

接口出参:

​编辑

新增权限页面:

​编辑

新增保存函数:

kotlin 复制代码
// 创建子账户
    async saveChild() {
      let validate = true
      try {
        validate = await this.$refs['registerForm'].validate()
      } catch (err) {
        validate = err
      }
      // el-tree 官方api    获取当前勾选的数据
      const temp = this.$refs['tree'].getCheckedNodes(false, true)
      // 数据为空  弹窗提示
      if (!temp.length) {
        this.confirmDialogShow = true
        return
      }
      if (typeof validate === 'boolean') {
        this.addLoading = true
        //resourceCode  遍历出来组成新数组 并用join方法 转换成字符串
        const menuId = temp.map(v => v.resourceCode).join(',')
        const param = { ...this.form, newMenuId: menuId, orderAll: 2 }
        const { code } = await addChildAccount(param)
        if (code === RESPONSE_SUCCESS) {
          this.addLoading = false
          this.noticeSuccessDialog = true
          this.noticeOptions = {
            text: this.$t('账户创建成功'),
            type: 'success'
          }
          this.$router.push({ name: 'UserInfo', params: { addNotice: true }})
          setTimeout(() => {
            this.noticeSuccessDialog = false
          }, 5000)
        } else {
          this.addLoading = false
        }
      }
    }

接口入参:

​编辑

新增成功之后,我们需要重新登录,方可使用子账号登录,并获取权限。

登录成功,接口会返回newMenuId字段,里面的每一项代表菜单或者按钮权限

​编辑

ini 复制代码
newMenuId ="Dashboard,findDashboardData,operationPendingOrders,Order,\r\nchatOperationOrder,OrdersList,OrdersUpdate,OrdersCreate,Product,ProductList_ADD,ProductList_EDIT,ProductList_QUERY"

重点就在这块。

2.路由权限

首先在router 文件夹下配置 menu.js文件

javascript 复制代码
onst menuRoutes = [
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: () => import(/* webpackChunkName: "dashboard" */'@/views/dashboard/index'),
    meta: { title: '概况', icon: 'overview', chat: true, resourceCode: 'findDashboardData' }
  },
  {
    path: '/order',
    name: 'Order',
    component: () => import(/* webpackChunkName: "orderList" */'@/views/order/order-list/index'),
    meta: { title: '订单1', icon: 'order_icon', chat: true, resourceCode: 'OrdersList' }
  },]

登录接口请求成功之后,前端导航栏路由渲染可以根据后端返回的字段进行过滤,当然我们这里是保留导航栏,如果子账号没有权限的话,弹出弹窗提示。

kotlin 复制代码
          this.$store.commit('user/SET_IS_ADMIN', data.useradmin)
          const menuList = menuRoutes // 主菜单  //取自  menu.js
          const settingList = settingRoutes // 系统设置菜单
          this.menuList = { menu: menuList, setting: settingList }
          // 递归权限列表
          localStorage.setItem('YL_SYSTEM_MENU', JSON.stringify(menuList))
          localStorage.setItem('YL_SETTING_MENU', JSON.stringify(settingList))
          this.$store.commit('user/SET_SYSTEM_MENU', this.menuList)
在permission.js router.beforeEach 中 接口出参resoureCode包含与前端 resoureCode一致的话,如果当前菜单会有权限,就会next,如果没有就弹出弹窗提示。​编辑

示例代码:

scss 复制代码
if (permissionMenu.length && !permissionMenu.includes(to.meta.resourceCode)) {
            // 没有权限的页面 禁止跳转
 store.commit('user/permissionDialogShow', true)
 if (from.path === '/') {
   router.go(-1)
  }
   NProgress.done()
  } else {
  next()
 }
好,当前的路由权限是这样的,包括在地址栏上输入进入多会被拦截,具体还需要同学根据自身的需求作出相关的改动哈。

3.按钮权限

根据接口字段判断,子账号的菜单,按钮权限存储处理。

kotlin 复制代码
if (data.useradmin !== 1) {
    // 子账户
    const menuId = data.newMenuId.split(',')
    // 存到vuex中
    this.setPermissionMenu(menuId)   //采用vuex的配置型api的写法   等同于  this.$store.state.setPermissionMenu
    // 跳转权限指定 路由
    const router = [...menuList, ...settingList].find(item => menuId.includes(item.meta.resourceCode)).path
    this.$router.push({ path: router })
  } else {
    this.$router.push({ path: '/dashboard' })
  }

在store 文件夹中使用模块化引入

​编辑

同文件下的state 对象 存储 permissionMenu

css 复制代码
const state = {
  permissionMenu: JSON.parse(localStorage.getItem('permissionMenu')) || []
}

利用vuex的getters 特性进行缓存存储,提高性能优化

ini 复制代码
const getters = {
  permissionMenu: state => state.user.permissionMenu
}

接下来我们去封装用一个vue的指令 全局应用

在directive 文件夹下 新建一个modules

directive ----> modules ---> permission.js(此文件命名会影响,指令的命名哦)

​编辑

permission.js

javascript 复制代码
import store from '../../store'
export default {
  inserted: function(el, binding) {   //el:元素   binding:元素绑定的属性相关数据
    const userPermissions = store.state.user.permissionMenu // 用户的权限列表
    // 获取指令的参数,即所需的权限
    const requiredPermission = binding.value   //对应的就是resouceCode
    // 如果用户的权限列表中不包含所需的权限
    if (userPermissions.length && !userPermissions.includes(requiredPermission)) {
      // 隐藏按钮
      el.style.display = 'none'
      // el.parentNode?.removeChild(el); // 移除元素
    }
  }
}

同级module 文件夹中 index.js

javascript 复制代码
import Vue from 'vue'
const files = require.context(
  // 指定的目录
  './modules',
  // 不查找子目录
  false,
  // js 文件
  /.+.js$/)

// 按模块引入
// files.keys(): 打印出来为['./focus.js','/loadmore.js']
files.keys().forEach(fileName => {
  const directiveConfig = files(fileName) // 获取指令函数

  const directiveName = fileName // 获取指令名
    .replace(/^.//, '') // 去除开头的'./'
    .replace(/.\w+$/, '') // 去除文件扩展名
  Vue.directive(directiveName, directiveConfig.default || directiveConfig)   //vue  全局注册指令
})

main.js 就可直接导入模块化指令

​编辑

我们在其他的文件中

ini 复制代码
  <el-button v-permission="'OrdersUpdate'" />        //OrdersUpdate  对应resouceCode       

其他的按钮 也是同样配置的哦。

封装v-permission的指令,其实同理跟v-if很像哦,但是会使用之中比较优雅的写法。

本篇会提供一种思路和逻辑哦,但是具体的代码实现肯定还是根据当前的项目整体结构做出相应的改变哦。

祝大家国庆节快乐哦。天天无bug哦

相关推荐
new出一个对象26 分钟前
uniapp接入BMapGL百度地图
javascript·百度·uni-app
你挚爱的强哥1 小时前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森2 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy2 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189112 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿3 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡4 小时前
commitlint校验git提交信息
前端
虾球xz5 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇5 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒5 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript