通过自定义指令完成按钮级权限控制

1、角色管理 -> 权限分配

(1)、权限分配页面效果:

(2)、后端提供树形结构数据,数据格式;

css 复制代码
[  {    "id": 102,    "value": "0-102",    "label": "user_manage",    "name": "用户管理",    "rightList": [      {        "id": 11,        "name": "分配角色",        "api": "/user/allocationRole",        "label": "user_manage:role:allocation",        "value": "1-11"      },      {        "id": 12,        "name": "启用停用",        "api": "/user/modifyEnable",        "label": "user_manage:role:enable",        "value": "1-12"      }    ]
  },
  {
    "id": 101,
    "value": "0-101",
    "label": "task_manage",
    "name": "任务管理",
    "rightList": [
      {
        "id": 1,
        "name": "创建目标",
        "api": "/target/addOrUpdateTarget",
        "label": "task_manage:target:add",
        "value": "1-1"
      },
      {
        "id": 2,
        "name": "创建任务",
        "api": "/task/addOrUpdateTask",
        "label": "task_manage:task:add",
        "value": "1-2"
      },
      {
        "id": 3,
        "name": "创建工作计划",
        "api": "/plan/addOrUpdatePlan",
        "label": "task_manage:plan:add",
        "value": "1-3"
      },
      {
        "id": 4,
        "name": "添加协作者",
        "api": "/association/addCollaborator",
        "label": "task_manage:collaborator:add",
        "value": "1-4"
      },
      {
        "id": 5,
        "name": "新增进度安排",
        "api": "/schedule/createOrUpdateSchedule",
        "label": "task_manage:schedule:add",
        "value": "1-5"
      },
      {
        "id": 7,
        "name": "新增阶段性成果",
        "api": "/achievement/createOrUpdateAchievement",
        "label": "task_manage:achievement:add",
        "value": "1-7"
      }
    ]
  },
  {
    "id": 103,
    "value": "0-103",
    "label": "role_manage",
    "name": "角色管理",
    "rightList": [
      {
        "id": 13,
        "name": "创建角色",
        "api": "/role/addOrModifyRole",
        "label": "role_manage:role:add",
        "value": "1-13"
      },
      {
        "id": 14,
        "name": "编辑角色",
        "api": "/role/addOrModifyRole",
        "label": "role_manage:role:update",
        "value": "1-14"
      },
      {
        "id": 15,
        "name": "权限分配",
        "api": "/role/modifyPermission",
        "label": "role_manage:permission:modify",
        "value": "1-15"
      },
      {
        "id": 16,
        "name": "删除角色",
        "api": "/role/delRole",
        "label": "role_manage:role:del",
        "value": "1-16"
      }
    ]
  }
]

(3)、前端模块代码:

kotlin 复制代码
主要HTML结构(树形结构)
<t-form-item
    label="菜单可见范围"
    name="menuIds"
    >
    <t-tree
      ref="menuTreeRef"
      v-model="formData.menuIds"
      :data="treeData"
      :checkable="checkable"
      :keys="keys"
      :check-strictly="checkStrictly"
      :value-mode="valueMode"
      hover
      expand-all
    />
</t-form-item>

data数据
data() {
    return {
      valueMode: 'onlyLeaf',
      checkable: true,
      checkStrictly: true,
      keys: { value: 'value', label: 'name', children: 'rightList' }, // 树形结构显示树形配置
      treeData: [
      ],
      formData: {
        permission: '全部数据',
        menuIds: []
      }
    }
  },

方法:
// 权限分配提交
    savePermission() {
      const funcIds = [] // 模块
      const menuIds = [] // 按钮
      const keysArr = this.formData.menuIds
      keysArr.map((item) => {
        const itemArr = item.split('-')
        if (itemArr[0] === '0') {
          funcIds.push(itemArr[1])
        } else if (itemArr[0] === '1') {
          menuIds.push(itemArr[1])
        }
        return item
      })
      // console.log(menuIds, funcIds)
      const data = {
        addOrUpdate: 'add',
        roleId: this.roleInfo.id,
        permission: this.formData.permission,
        funcIds: funcIds.join(','),
        menuIds: menuIds.join(',')
      }
      modifyPermission(data).then((res) => {
        if (res.code === 200) {
          // console.log(res)
          this.$message.success('权限分配成功')
          this.customVisible = false
          this.$parent.search()
        }
      })
    },

2、VueX做状态管理,保存当前用户的权限数据;

(1)、在store文件夹的modules创建一个permission.js文件,内容如下:

javascript 复制代码
import { getUserInfo } from '@/api/user'

const state = {
  codes: []
}
const mutations = {
  SET_CODES: (state, codes) => {
    state.codes = codes.data
  }
}

const actions = {
  getGrantCodes({ commit }) {
    return getUserInfo().then(codes => {
      commit('SET_CODES', codes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

(2)、在store文件夹中的index.js文件中引入:

php 复制代码
import Vue from 'vue'
import Vuex from 'vuex'
import permission from './modules/permission'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {},
  modules: { permission }
})

3、调用store中的获取权限数据方法,并完成自定义指令;

(1)、调用store中的方法获取权限数据:(这里是直接在APP.vue文件中调用)

xml 复制代码
<template>
  <div id="app">
    <router-view />
  </div>
</template>

<script>
export default {
  async created() {
    await this.$store.dispatch('permission/getGrantCodes')
  },
  mounted() {}
}
</script>

(2)、自定义指令:

在utils文件夹中,创建directive文件夹,并创建index.js和acl.js文件

index.js文件代码:

javascript 复制代码
import Vue from 'vue'
import acl from './acl'
Vue.directive('acl', acl)
Vue.prototype.$rules = {
  role: {
    add: 'role_manage:role:add', // 创建角色
    edit: 'role_manage:role:update', // 编辑角色
    del: 'role_manage:role:del', // 删除角色
    modify: 'role_manage:permission:modify' // 权限分配
  },
  user: {
    allocation: 'user_manage:role:allocation', // 分配角色
    enable: 'user_manage:role:enable'// 启用停用
  },
  task: {
    targetadd: 'task_manage:target:add', // 创建目标
    taskadd: 'task_manage:task:add', // 创建任务
    planadd: 'task_manage:plan:add', // 创建工作计划
    collaboratoradd: 'task_manage:collaborator:add', // 添加协作者
    scheduleadd: 'task_manage:schedule:add', // 新增进度安排
    achievementadd: 'task_manage:achievement:add' // 新增阶段性成果
  }
}

acl.js文件代码

javascript 复制代码
import store from '@/store/index'

export default {
  inserted(el, binding, vnode) {
    const { value } = binding
    // console.log(binding)
    if (!store.state.permission.codes.buttonList.includes(value)) {
      if (binding.arg === 'disabled') {
        el.disabled = true
        el.setAttribute('class', el.getAttribute('class') + ' is-disabled')
      } else {
        el.style.display = 'none'
      }
    }
  }
}

这是和后端约定好的返回的按钮权限数据:store.state.permission.codes.buttonList,格式如下:

css 复制代码
[  "user_manage:role:allocation",  "user_manage:role:enable",  "task_manage:target:add",  "task_manage:task:add",  "task_manage:plan:add",  "task_manage:collaborator:add",  "task_manage:schedule:add",  "task_manage:achievement:add",  "role_manage:role:add",  "role_manage:role:update",  "role_manage:permission:modify",  "role_manage:role:del"]

(3)、全局引入自定义指令:

在main.js中进行引入

arduino 复制代码
import '@/utils/directive' // 全局引入自定义指令

4、使用自定义指令,完成按钮权限控制;

在相关的权限按钮上加上v-acl="$rules.xxx.xxxxx"即可,例子:v-acl="$rules.user.allocation"、v-acl="$rules.user.enable"

ini 复制代码
<t-table
  row-key="index"
  :data="userList"
  :columns="columns"
  :loading="tableLoading"
>
  <template #op="{ row }">
    <t-button
      v-acl="$rules.user.allocation"
      variant="text"
      size="small"
      theme="primary"
      @click="assigningRolesFun(row)"
    >分配角色</t-button>
    <t-popconfirm
      v-if="row.enable==1"
      theme="warning"
      content="您确定停用该用户吗?"
      @confirm="stopEnableConfirm(row)"
    >
      <t-button
        v-acl="$rules.user.enable"
        variant="text"
        size="small"
        theme="danger"
      >停用</t-button>
    </t-popconfirm>
    <t-button
      v-else
      v-acl="$rules.user.enable"
      variant="text"
      size="small"
      theme="primary"
      @click="stopEnableConfirm(row)"
    >启用</t-button>
  </template>
</t-table>
相关推荐
漫天转悠3 小时前
Vue3项目中引入TailwindCSS(图文详情)
vue.js
qq_589568104 小时前
Echarts+vue电商平台数据可视化——后台实现笔记
vue.js·信息可视化·echarts
5hand5 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL5 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js
z千鑫6 小时前
【前端】详解前端三大主流框架:React、Vue与Angular的比较与选择
前端·vue.js·react.js
苹果醋37 小时前
React系列(八)——React进阶知识点拓展
运维·vue.js·spring boot·nginx·课程设计
王小王和他的小伙伴8 小时前
解决 vue3 中 echarts图表在el-dialog中显示问题
javascript·vue.js·echarts
好名字08218 小时前
前端取Content-Disposition中的filename字段与解码(vue)
前端·javascript·vue.js·前端框架
隐形喷火龙9 小时前
element ui--下拉根据拼音首字母过滤
前端·vue.js·ui
Simaoya10 小时前
【vue】css模拟玻璃球体效果(带高光)
前端·css·vue.js