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

文章介绍了在Vue项目中如何实现登录权限管理,包括创建子账号、配置权限树、路由权限过滤以及利用Vue指令控制按钮显示。重点讲解了如何通过Vuex管理和动态显示权限受限的界面元素。
摘要由CSDN通过智能技术生成

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

1.主账号新增子账号

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

接下来就是配置子账号的权限了,我们这种是树形结构,用的就是el-tree 的组件
接口返回的树形结构,会携带resourceCode,代表新增时会传给后端,后端同学记录当前勾选的权限是哪些。

接口出参:


新增权限页面:


新增保存函数:

// 创建子账户
    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字段,里面的每一项代表菜单或者按钮权限

newMenuId ="Dashboard,findDashboardData,operationPendingOrders,Order,\r\nchatOperationOrder,OrdersList,OrdersUpdate,OrdersCreate,Product,ProductList_ADD,ProductList_EDIT,ProductList_QUERY"

重点就在这块。

2.路由权限

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

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' }
  },]

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

          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,如果没有就弹出弹窗提示。

 示例代码:

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

3.按钮权限

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

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

const state = {
  permissionMenu: JSON.parse(localStorage.getItem('permissionMenu')) || []
}

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

const getters = {
  permissionMenu: state => state.user.permissionMenu
}

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

在directive 文件夹下 新建一个modules

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

permission.js

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

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 就可直接导入模块化指令

我们在其他的文件中

  <el-button v-permission="'OrdersUpdate'" />        //OrdersUpdate  对应resouceCode       

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

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

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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值