管理后台遇到的问题


一、按钮权限

使用vue自定义事件,全局匹配权限,成功展示,失败删除按钮

1、自定义事件


//directive/hasPermission.js
import Vue from 'vue'
import store from '@/store'

// 校验用户是否拥有按钮权限
function hasPermission(el, binding) {
  // 角色编码权限数组
  const roles = store.getters && store.getters.roles
  // 超级管理员拥有所有的按钮权限
  // console.log('has', roles, this, Vue.prototype.ROOT_ROLE_CODE)
  if (roles.includes(Vue.prototype.ROOT_ROLE_CODE)) {
    return true
  }
  // console.log(vnode, el.parentNode)
  //自定义指令-传过来的值,用于比较按钮权限
  const { value } = binding
  // getUserInfo 获取 当前角色所有按钮权限数组
  const perms = store.getters && store.getters.perms
  if (value && typeof value === 'string') {
    const hasPermission = perms.includes(value)
    // console.log('hasPermission', hasPermission);
    if (!hasPermission) {
      el.parentNode && el.parentNode.removeChild(el)
    }
  } else {
    throw new Error(`按钮标识应该是字符串,错误参数:${value}`)
  }
}

export default {
  inserted(el, binding) {
    hasPermission(el, binding)
  },
  update(el, binding) {
    hasPermission(el, binding)
  },
}

//directive/index.js
import hasPermission from './hasPermission'

const instructions = {}
instructions.install = function(Vue) {
  Vue.directive('hasPermission', hasPermission)
}

export default instructions

//main.js
// 全局指令注册-按钮权限指令
import permission from './directive/index'

2、页面使用

<span v-hasPermission="'system:menu:update'">
  <el-button type="text" size="medium" @click="editMenuInfo(row)"
    >修改</el-button
  >
  <el-divider direction="vertical"></el-divider>
</span>
<!--或者-->
<el-button
  v-hasPermission="'system:menu:create'"
  size="small"
  type="primary"
  plain
  icon="el-icon-circle-plus"
>添加菜单</el-button>

3、问题处理

前提:类似左侧树状图-右侧展示内容存在修改/保存按钮
1、树状图分父/子级(目前只有2级),修改权限拆分两个,使用v-show来隐藏/显示按钮,v-if会与权限冲突,导致修改按钮渲染丢失(图1,2)
2、因为匹配失败会删除该元素的父级中的第一个子级,如果存在按钮互斥(如:修改/保存)的情况,权限按钮外层需要多包裹div,或者在保存按钮同级放置一个空div(图3,4)

角色组-修改权限
角色-修改权限
点击修改权限-正常显示
因为没有角色组权限-导致取消按钮被删除

<div v-if="isDisabled">
  <div>
    <el-button
      v-show="currentData.children"
      v-hasPermission="'system:role:updateGroupPerm'"
      size="small"
      type="primary"
      plain
      :loading="loading"
      icon="iconfont icon-bianji1 icon-margin"
      @click="changeTableState"
      >修改权限</el-button
    >
    <el-button
      v-show="!currentData.children"
      v-hasPermission="'system:role:updateRolePerm'"
      size="small"
      type="primary"
      plain
      :loading="loading"
      icon="iconfont icon-bianji1 icon-margin"
      @click="changeTableState"
      >修改权限</el-button
    >
  </div>
</div>
<div v-else>
  <!--或者-->
  <div></div>
  <el-button size="small" plain @click="cancel">取消</el-button>
  <el-button size="small" type="primary" @click="confirm">
    保存
  </el-button>
</div>

<!--树状图 权限分离处理(支持表达式)-->
<el-dropdown-item
  v-hasPermission="
    data.children
      ? 'system:role:updateGroup'
      : 'system:role:updateRole'
  "
  :command="beforeCommand('edit', data, node)"
  >修改</el-dropdown-item
> 

4、按钮最多四个处理

(互斥按钮,需要设置为同一个权限),否则按钮展示会丢失按钮

<el-table-column
  label="操作"
  align="center"
  fixed="right"
  :width="showList.length * 80"
>
  <template slot-scope="{ row }">
    <div class="split-btns">
      <div
        v-for="(item, i) in showList"
        :key="item.key"
        class="contentBox"
      >
        <el-button
          type="text"
          size="medium"
          :disabled="item.isDisabled && item.isDisabled(row)"
          @click="item.fn(row)"
          >{{
            typeof item.label === 'string'
              ? item.label
              : item.label(row)
          }}</el-button
        >
        <el-divider
          v-if="
            (i < showList.length - 1 && !moreList.length) ||
            moreList.length
          "
          direction="vertical"
        ></el-divider>
      </div>
      <!--更多-->
      <el-dropdown v-if="moreList.length" trigger="click">
        <span class="el-dropdown-link">
          <i class="el-icon-more menuActiveText"></i>
        </span>
        <el-dropdown-menu slot="dropdown">
          <template v-for="item in moreList">
            <el-dropdown-item
              :class="{
                'dropdown-item': !(
                  item.isDisabled && item.isDisabled(row)
                ),
              }"
              :key="item.key"
              :disabled="item.isDisabled && item.isDisabled(row)"
              @click.native="item.fn(row)"
              >{{
                typeof item.label === 'string'
                  ? item.label
                  : item.label(row)
              }}</el-dropdown-item
            >
          </template>
        </el-dropdown-menu>
      </el-dropdown>
    </div>
  </template>
</el-table-column>
import { mapGetters } from 'vuex'

data(){
  return {
    permissionList: [
        {
          label: '查看',
          key: 'system:staff:detail',
          fn: (row) => {
            this.handleEditStaff(row, 'view')
          },
        },
        {
          label: '角色权限',
          key: 'system:staff:updateRole',
          fn: (row) => {
            this.handleEditRole(row)
          },
        },
        {
          label: '数据权限',
          key: 'system:staff:dataRole',
          fn: (row) => {
            this.handleEditData(row)
          },
        },
        {
          label: '修改',
          key: 'system:staff:edit',
          fn: (row) => {
            this.handleEditStaff(row, 'edit')
          },
        },
        {
          label: (row) => {
            return row.accountState === 1 ? '停用' : '启用'
          },
          key: 'system:staff:isEnable',
          isDisabled: ({ fromType }) => {
            return !fromType
          },
          fn: (row) => {
            return row.accountState === 1
              ? this.handleDisable(row)
              : this.handleEnable(row)
          },
        },
        // {
        //   label: '删除',
        //   key: 'system:staff:delete',
        //   isDisabled: ({ fromType }) => {
        //     return !fromType
        //   },
        //   fn: (row) => {
        //     this.handleDel(row)
        //   },
        // },
      ],
      // 展示的四个按钮
      showList: [],
      // 超过四个隐藏的
      moreList: [],
  }
},
computed: {
  // roles 角色权限 perms 按钮权限数组
  ...mapGetters(['perms', 'roles']),
},
created() {
  this.fetchPermList()
},
methods: {
  // 初始化按钮权限
  fetchPermList() {
    const perms = this.perms
    let perms1 = []
    // 如果是超级管理员角色,不校验按钮权限
    if (this.roles.includes(Vue.prototype.ROOT_ROLE_CODE)) {
      perms1 = this.permissionList
    } else {
      this.permissionList.forEach((item) => {
        if (perms.includes(item.key)) {
          perms1.push(item)
        }
      })
    }

    const perms2 = perms1.splice(0, 3)
    this.showList = perms2
    this.moreList = perms1
  },
}

5、遗留问题

1、树状图如果层级不确定,处理方案后端配合简单些(未验证),纯前端不建议做拆分,否则需要大量的判断逻辑

2、按钮标识设置自动带出路由来区分页面,应该保证按钮标识的唯一性,目前后端将所有数据返回在一个数组中,会出现:在A页面路由中设置了B页面的按钮标识,会影响B页面按钮展示,数据应以页面路由为单位,而不是返回在一个大数组中,这样处理也可以减少循环

3、按钮标识配置修改,前端未及时对应修改,引发的按钮丢失的问题

持续更新中…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冷眸同学(waim)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值