element ui tree 設置父節點與子節點關聯時,如何設置子節點不進行全選時,父節點設置半選狀態


適用情況

1.element ui中tree 如果設置check-strictly 為true 則是父節點和子節點不進行關聯(即點擊選中哪個就是哪個)不方便用戶使用,如果設置為false 則父節點和子節點進行關聯,但是后端數據要求需要提供選中子節點的父節點 就需要我們講半選狀態的菜單ID getHalfCheckedKeys()和選中的ID getCheckedKeys()合並

都給后端,后端詳情返回父節點的ID,如果直接設置選中setCheckedKeys 因為父節點關聯子節點 【因此就會選中在回顯的樹呈現父節點下面的子節點都進行了選中】因此可以想辦法區別一下那個ID是半選的ID,哪些是選中的ID,進行設置,但是文檔上提供了設置全選的方法,但是沒有設置半選的方法;
 
2.下面是解決當前場景的方法(目前是個新增、編輯、簡單的角色,里面的權限樹,方式可以以上問題現象)
 
 
<template>
  <div class="roleManagement" style="min-height:calc(100vh - 95px)">
    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" center width="750px">
      <el-form ref="organizationData" :rules="rules" :model="organizationData">
        <el-form-item label="角色名稱" prop="roleName" :label-width="formLabelWidth">
          <el-input v-model="organizationData.roleName" type="text" placeholder="請輸入角色名稱" maxlength="20" />
        </el-form-item>
        <el-form-item label="角色描述" :label-width="formLabelWidth">
          <el-input v-model="organizationData.roleDesc" type="textarea" :rows="5" maxlength="200" @input="change" />
        </el-form-item>
        <el-form-item label="權限" :label-width="formLabelWidth">
          <!-- <el-tree
            ref="tree"
            style="margin-top:5px"
            :data="privilegeData"
            :default-checked-keys="privilegeUpData"
            :default-expanded-keys="privilegeUpData"
            show-checkbox
            node-key="id"
            default-expanded
            :props="defaultProps"
            @check="handleCheckChangeAuth"
          /> -->
          <el-tree
            ref="tree"
            style="margin-top:5px"
            :data="privilegeData"
            :default-expanded-keys="privilegeUpData"
            show-checkbox
            node-key="id"
            default-expanded
            :props="defaultProps"
            :check-strictly="checkStrictly"
            @check-change="handleCheckChangeAuthNode"
          />
        </el-form-item>
      </el-form>
      <div v-if="dialogStatus ==='Details'" slot="footer" class="dialog-footer">
        <el-button type="primary" @click="dialogFormVisible = false">確定</el-button>
      </div>
      <div v-else slot="footer" class="dialog-footer">
        <el-button @click="backData()">取消</el-button>
        <el-button type="primary" @click="dialogStatus === 'Create' ? createData() : updateData()">提交</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { sysMenuInfo, roleListAdd, roleDetails, roleListEdit } from '@/api/vue-roleManagement'
export default {
  name: 'RoleManagement',
  data() {
    const tagNameReg = (rule, value, callback) => {
      if (value.length === 0) {
        callback(new Error('請輸入角色名稱'))
      } else if (value.length > 20) {
        callback(new Error('角色名稱必須要在20個字以內'))
      } else {
        callback()
      }
    }
    return {
      textMap: {
        update: 'Edit',
        create: 'Create',
        detail: 'Details'
      },
      dialogFormVisible: false, // 新增、編輯彈出框是否展示
      formLabelWidth: '120px', // 彈出框form表單寬度展示
      dialogStatus: '',
      readonly: false,
      organizationData: {
        roleName: '', // 角色名稱
        roleDesc: '' // 角色描述
      },
      rules: {
        roleName: [
          { required: true, validator: tagNameReg, trigger: 'blur' }
        ]
      },
      privilegeData: [], // 菜單權限
      privilegeUpData: null,
      defaultProps: {
        children: 'childMenus',
        label: 'menuName'
      },
      menuIdsObj: [], // 菜單選中的權限限制
      ids: '' // 編輯ID
    }
  },
  created() {
    this.getList()
  },
  methods: {
    /**
     * 選中的節點展示
     */
    handleCheckChangeAuthNode() {
      this.menuIdsObj = []
      // this.menuIdsObj = this.$refs.tree.getCheckedNodes() // 全選
      this.menuIdsObj = this.$refs.tree.getCheckedNodes().concat(this.$refs.tree.getHalfCheckedNodes())
    },
    /**
     * 新增事件
     */
    AddEvent() {
      this.dialogStatus = 'Create'
      this.dialogFormVisible = true
      this.resetForm('organizationData')
      Object.keys(this.organizationData).forEach((key) => {
        this.organizationData[key] = ''
      })
      // 菜單權限接口
      this.privilegeData = []
      this.privilegeUpData = []
      this.sysMenuInfo()
    },
    /**
      * 菜單權限展示  用於新增
    */
    sysMenuInfo() {
      sysMenuInfo().then((res) => {
        if (res.code === 0 || res.code === '0') {
          this.privilegeData = res.data
        } else {
          this.$message({
            type: 'error',
            message: res.message
          })
        }
      }).catch((err) => {
        console.log(err)
      })
    },
    /**
     * 新增保存接口
     */
    createData() {
      this.$refs['organizationData'].validate((valid) => {
        if (valid) {
          const params = {
            roleName: this.organizationData.roleName, // 角色名稱
            roleDesc: this.organizationData.roleDesc, // 角色描述
            menuIds: [] // 選中的菜單數據
          }
          this.menuIdsObj.forEach(function(item) {
            const obj = {
              type: item.type,
              parentId: item.parentId,
              id: item.id
            }
            params.menuIds.push(obj)
          })
          roleListAdd(params).then((res) => {
            if (res.code === '0' || res.code === 0) {
              this.$message({
                type: 'success',
                message: '創建成功'
              })
              this.dialogFormVisible = false
              this.pageNum = 1
              this.pageSize = 10
              this.getList()
            } else {
              this.$message({
                type: 'error',
                message: res.message
              })
            }
          })
        }
      })
    },
    /**
     * 點擊編輯的時間
     */
    handleUpdate(row) {
      this.dialogStatus = 'Edit'
      this.dialogFormVisible = true
      this.resetForm('organizationData')
      Object.keys(this.organizationData).forEach((key) => {
        this.organizationData[key] = ''
      })
      this.ids = row.id
      this.privilegeData = [] // 菜單接口
      this.privilegeUpData = []
      // 調用詳情接口
      this.roleDetailsList(row.id)
    },
    /**
     * 菜單獲取接口 用於編輯接口展示
     */
    getPartsysMenuInfo() {
      return new Promise(function(resolve) {
        sysMenuInfo().then((res) => resolve(res))
      })
    },
    /**
     * 詳情展示接口用於編輯展示
     */
    getPartRoleDetails(id) {
      return new Promise(function(resolve) {
        roleDetails({ id: id }).then((res) => resolve(res))
      })
    },
    roleDetailsList(id) {
      if (id === '' || id === null || id === '{}' || id === undefined) {
        return false
      }
      const _this = this
      return Promise.all([this.getPartsysMenuInfo(), this.getPartRoleDetails(id)])
        .then((results) => {
          // 處理數據
          if (results[0].code === '0' || results[0].code === 0) { // 菜單接口
            _this.privilegeData = results[0].data
          } else {
            _this.$message({
              message: results[0].message,
              type: 'error'
            })
            _this.privilegeData = []
          }
          if (results[1].code === '0' || results[1].code === 0) { // 代表詳情接口
            _this.organizationData.roleName = results[1].data.roleName // 角色名稱
            _this.organizationData.roleDesc = results[1].data.roleDesc // 角色描述
            if (results[1].data.roleMenus === null && results[1].data.roleButtons === null || results[1].data.roleMenus.length <= 0 && results[1].data.roleButtons.length <= 0) {
              _this.privilegeUpData = null
            } else {
              const arr = []
              const brr = [] // 用於渲染編輯回顯的內容
              // 菜單存放的數組
              results[1].data.roleMenus.forEach(function(element) {
                arr.push(element.menuId)
                const brrObj1 = {
                  type: 1,
                  parentId: element.parentId,
                  id: element.menuId
                }
                brr.push(brrObj1)
              })
              results[1].data.roleButtons.forEach(function(element) {
                arr.push(element.buttonId)
                const brrObj2 = {
                  type: 2,
                  parentId: element.parentId,
                  id: element.buttonId
                }
                brr.push(brrObj2)
              })
              _this.menuIdsObj = brr // 渲染是否選中問題 [樹]
              const checkTreeNode = [] // 存放選中的節點
              const parentNodes = []
              _this.$nextTick(() => {
                for (const item of arr) {
                  const node = _this.$refs.tree.getNode(item)
                  if (node && node.isLeaf) {
                    checkTreeNode.push(item)
                  } else if (node) {
                    parentNodes.push(node)
                  }
                }
                // 設置所有子節點選中,自動回填父節點
                _this.$refs.tree.setCheckedKeys(checkTreeNode)
                // 未回填的父節點單獨設置
                for (let node of parentNodes) {
                  do {
                    // 應當有狀態的父節點在未選中時設置為半選中狀態
                    if (!node.checked && !node.indeterminate) {
                      node.indeterminate = true
                    }
                    // node.indeterminate = true 僅對一個節點進行半選中狀態設置,其父節點不能自動級聯設置,所以這里循環設置級聯父節點狀態
                    node = node.parent
                  } while (node)
                }
              })
              _this.privilegeUpData = arr // 用於需要渲染的ID數據
            }
          } else {
            _this.$message({
              message: results[1].message,
              type: 'error'
            })
          }
        })
    },
    /**
     * 編輯接口
    */
    updateData() {
      this.$refs['organizationData'].validate((valid) => {
        if (valid) {
          const params = {
            roleName: this.organizationData.roleName, // 角色名稱
            roleDesc: this.organizationData.roleDesc, // 角色描述
            menuIds: [], // 選中的菜單數據
            id: this.ids
          }
          // 處理選中需要的數據
          this.menuIdsObj.forEach(function(item) {
            const obj = {
              type: item.type,
              parentId: item.parentId,
              id: item.id
            }
            params.menuIds.push(obj)
          })
          roleListEdit(params).then((res) => {
            if (res.code === '0' || res.code === 0) {
              this.$message({
                type: 'success',
                message: '編輯成功'
              })
              this.dialogFormVisible = false
              this.pageNum = 1
              this.pageSize = 10
              this.getList()
            } else {
              this.$message({
                type: 'error',
                message: res.message
              })
            }
          })
        }
      })
    },
    /**
     * 點擊返回
     */
    backData() {
      this.dialogFormVisible = false
    }
  }
}
</script>
<style lang="scss" scoped>
 .roleManagement {
  .header_btn {
     width:100%;
     height:50px;
   }
   .loading_btnInfo{font-size:36px;color:#409EFF;margin:auto;width:36px;height:36px;display:block;margin-top:200px}
   .loading_p1{width:100%;text-align:center;height:50px;line-height:50px;font-size:14px;}
   .box-card {
     margin:20px;
   }
   .box-card_serch {
    margin:20px 20px 0px 20px;
   }
   .search-button {
     border-radius: 4px;
   }
   /**-----------------添加成員 成員編輯權限樣式調整---------------------------; */
    /deep/ .el-tree-node__content{
      height:35px !important;
    }
     .main_app {
      .main_left {
        background: #FFFFFF;
        border: 1px solid #DDDEE3;
        border-radius: 4px;
        width: 440px;
        height: 430px;
        float: left;
        overflow-y:auto;
        .div1 {
          width: 440px;
          height: 40px;
          padding: 11px 19.9px 9px 20.5px;
          color: #4A4A4A;
          border-bottom: 1px solid #DDDEE3;
          cursor: pointer;
        }
        .treeStyle {
          padding: 20px;
          .p1 {
            font-size: 16px;
            color: #2B3642;
            margin-top: 15px;
            margin-bottom: 15px;
            img {
              width: 4px;
              height: 16px;
              margin-right: 12px;
              vertical-align: middle;
            }
            span {
              vertical-align: middle;
            }
            time {
              float: right;
            }
          }
        }
      }
    }
 }
</style>

  

 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM