使用el-checkbox实现树形数据权限配置功能

1、效果

2、组件代码

<template>
  <ul :class="'level'+level" class="tree-container">
    <li v-for="(item, Index) in menuData" :id="item.menLevel === 1 ? `key${Index+2}` : ''" :key="item.menu_id" :class="'level'+item.menLevel" style="list-style: none;">
      <div :class="'level'+ item.menLevel" class="tree-node-title">
        <el-checkbox :value="item.isChecked === 1 ? true : false" :indeterminate="item.isIndeterminate" @change="nodeClick(item, Index)">
          {{ item.menu_name }}
          <!-- -level{{ item.menLevel }} -->
        </el-checkbox>
      </div>
      <div :class="'level'+item.menLevel" class="tree-childnode-container ">
        <CheckBox :menu-data="item.child" :level="item.menLevel" />
      </div>
    </li>
  </ul>

</template>

<script>
export default {
  name: 'CheckBox',
  // props: ['menuData', 'level'],
  props: {
    menuData: {
      type: Array,
      default: function() {
        return []
      }
    },
    level: {
      type: Number,
      default: null
    }
  },
  data() {
    return {
      checkedVal: []
    }
  },
  created() {

  },
  mounted() {

  },
  methods: {
    nodeClick(node, index) {
      // 通过isChecked判断是否为选中状态
      if (node.isChecked === 1) {
        this.$set(node, 'isChecked', 0)
        this.$set(node, 'isIndeterminate', false)
      } else {
        this.$set(node, 'isChecked', 1)
        this.$set(node, 'isIndeterminate', false)
      }
      this.refreshAllParentNodes(this)
      this.refreshAllSonNodes(this.$children[index], node.isChecked, node)
    },
    refreshAllSonNodes(node, status, item) {
      // if (node && node.$children.length) {
      item.child.map((meunItem, j) => {
        this.$set(meunItem, 'isChecked', status)
        this.$set(meunItem, 'isIndeterminate', false)
        this.refreshAllSonNodes([], status, meunItem)
      })
      // }
    },
    refreshAllParentNodes(node) {
      if (node) {
        var status = 0
        var nullCount = 0
        var fullCount = 0
        var isIndeterminate
        var isIndeterminateCount = 0
        if (node.menuData && node.$parent.menuData) {
          node.menuData.map((meunItem, j) => {
            if (typeof meunItem.isChecked === 'undefined') {
              nullCount++
            } else if (meunItem.isChecked === 0) {
              nullCount++
            } else if (meunItem.isChecked === 1) {
              fullCount++
            }
            if (meunItem.isIndeterminate === true) {
              isIndeterminateCount++
            }
          })
          if (fullCount === node.menuData.length) {
            // 该状态说明当前点击层级和兄弟层级都没选中,所以父级也是未选中状态
            status = 1
          } else {
            // 该状态说明当前点击层级和兄弟层级只要有一个选中,父级也是选中状态
            status = 0
          }
          if (fullCount > 0 && fullCount < node.menuData.length || isIndeterminateCount > 0) {
            isIndeterminate = true
          } else {
            isIndeterminate = false
          }
          node.$parent.menuData.map(child => {
            node.menuData.map((meunItem, j) => {
              if (child.menu_id === meunItem.parent_id) {
                // 根据父级id和子级的parentId是否相等,来确定当前点击的层级的父级是哪一个
                this.$set(child, 'isChecked', status)
                this.$set(child, 'isIndeterminate', isIndeterminate)
              }
            })
          })
        }
        // 递归计算父级
        this.refreshAllParentNodes(node.$parent)
      }
    }
  }
}
</script>

<style lang="scss">
  .tree-container {
    $borderColor: #C6E2FF;
    width: 100%;
    padding: 0;

    &.level3 {
      display: flex;
      flex-wrap: wrap;

      & > .level4 {
        width: 25%;
        padding: 0 20px 0 40px;
        .level5 {
          // background:#f7ffff;
          width: 25%;
          padding: 0 20px 0 10px;
        }
      }
    }

    & > .level2 {
      display: flex;
      align-items: center;
      border: 1px solid $borderColor;
      line-height: 45px;

      .tree-node-title {
        &.level2 {
          width: 160px;
          text-align: center;
        }

      }
    }

    .level3 {
      .level3 + .level3 {
        border-top: 1px solid $borderColor;
      }
    }

    .tree-node-title {
      &.level3 {
        background-color: #f2f2f2;
        width: 100%;
        padding: 0 20px;
      }

      &.level1 {
        padding: 20px 0;
      }

    }

    .level2 + .level2 {
      border-top: none;
    }

    .tree-childnode-container {
      width: 100%;

      &.level2 {
        border-left: 1px solid $borderColor;
      }
    }

    input {
      margin-right: 5px;
    }

    label {
      cursor: pointer;
    }

  }
</style>

3、template

    <tree-table :menu-data="menuList" :level="1" />

4、data

 menuList: [
        // {
        //   isChecked: 1,
        //   menLevel: 1,
        //   menu_id: 239,
        //   menu_name: '数据报表',
        //   parent_id: 0,
        //   child: [
        //     {
        //       isChecked: 1,
        //       menLevel: 2,
        //       menu_id: 262,
        //       menu_name: '经纪人每日汇报(简)',
        //       parent_id: 239,
        //       child: []
        //     },
        //     {
        //       isChecked: '',
        //       menLevel: 2,
        //       menu_id: 265,
        //       menu_name: '数据报表详情',
        //       parent_id: 239,
        //       child: []
        //     }
        //   ]
        // }
],
 odlMenu: [],
newMenu:[],
 id:[]

5、methods

    // 获取所有权限列表,用于渲染列表
    getMenuList2() {
      this.menuList = []
      Users.getMenuData().then(res => {
        this.menuList = this.changeData(res.data, 1)
      })
        .then(res => {
          this.getRoleMenuAndUser()
        })
    },

//数据格式化
   changeData(data, level) {
      return data.map(item => {
        const newItem = {
          menu_id: item.id,
          ...item,
          isChecked: null,
          menLevel: level
        }
        if (item.child && Array.isArray(item.child) && item.child.length) {
          newItem.child = this.changeData(item.child, level + 1)
        } else {
          newItem.child = []
        }
        return newItem
      })
    },

    // 获取角色列表下  权限  列表
    getRoleMenuAndUser() {
      const params = {
        id: this.params.id ? this.params.id : 1,
        type: 1
      }
      this.odlMenu.splice(0)
      System.getRoleMenuAndUser(params).then(res => {
        res.data.forEach((item, index) => {
          this.odlMenu.push(item.menu_id)
        })
        this.odlMenu.forEach(odl_menu_id => {
          this.recursion(odl_menu_id, this.menuList)
        })
      })
    },

        // 判断是否选中
    recursion(menu_id, data) {
      for (let i = 0, len = data.length; i < len; i++) {
        if (data[i].menu_id === menu_id) {
          data[i].isChecked = 1
          return
        }
        if (data[i].child) {
          this.recursion(menu_id, data[i].child)
        }
      }
    },

  // 权限修改保存
    save() {
      const newMenuArr = this.getId(this.menuList)
      // 添加角色权限关联
      this.newMenu = Array.from(new Set(newMenuArr))

      const pramas = {
        menu_id: this.newMenu,    
        id: this.params.id
      }
      System.saveRoleToMenuRelation(pramas).then(res => {
        this.$message({
          type: 'success',
          message: '权限数据保存成功'
        })
        this.getRoleMenuAndUser()
      })
    },

    //获取需要传给后端的id
   getId(data, result = []) {
      data.forEach(item => {
        if (item.isChecked === 1 || item.isIndeterminate) {
          result.push(item.menu_id, item.parent_id)
        }
        if (item.child && Array.isArray(item.child) && item.child.length) {
          this.getId(item.child, result)
        }
      })
      return result
    },

 6.mounted

  mounted() {
    this.getMenuList2()
  },

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值