沐若清辰
人生如茶,浓也好,淡也好,各有味道

适用情况

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>

  

 
 
 
posted on 2022-03-15 11:22  沐若清辰  阅读(2306)  评论(0编辑  收藏  举报