element+plus级联表格父级子级选择

element+plus级联表格父级子级选择

存在的问题(使用的是"element-plus": “^2.2.28”,“vue”: “^3.2.45”,)

使用this.$refs.selectTable.toggleRowSelection(j, true);去勾选父级时,会将子级即子级以下的全部勾选;
但是我想要的只是勾选父级,但是又不想去除勾选父级时,勾选子级的功能!
解决思路,勾选父级时先将父级以下的全部子级取消勾选,再将原本勾选了的一个一个勾选!

最终效果

在这里插入图片描述

废话不多说,上代码

<template>
  <el-dialog
    :title="titleShow"
    destroy-on-close
    :model-value="roleDialogVisible"
    :close-on-click-modal="false"
    @close="roleDialogToClose(false)"
    width="40%"
    top="10vh"
  >
    <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
      <el-tab-pane label="角色信息" name="first">
        <el-form ref="formRef" label-width="120px" :model="formModelRole" :rules="formRules">
          <input type="text" name="account" style="display: none" />
          <input type="password" name="password" style="display: none" />
          <el-form-item label="角色标识" prop="roleCode">
            <el-input
              v-model.trim="formModelRole.roleCode"
              placeholder="请输入角色标识"
              clearable
              maxlength="20"
              :show-word-limit="true"
            ></el-input>
          </el-form-item>
          <el-form-item label="角色名称" prop="roleName">
            <el-input
              v-model.trim="formModelRole.roleName"
              placeholder="请输入角色名称"
              clearable
              maxlength="20"
              :show-word-limit="true"
            ></el-input>
          </el-form-item>
          <el-form-item label="状态" prop="status">
            <el-radio-group v-model="formModelRole.status">
              <el-radio-button label="0">禁用</el-radio-button>
              <el-radio-button label="1">启用</el-radio-button>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="描述" prop="roleDesc">
            <el-input
              type="textarea"
              rows="2"
              placeholder="请输入描述信息"
              resize="none"
              maxlength="100"
              :show-word-limit="true"
              v-model.trim="formModelRole.roleDesc"
            ></el-input>
          </el-form-item>
        </el-form>
      </el-tab-pane>
      <el-tab-pane label="分配权限" name="second" :disabled="type === 'add'">
        <el-form ref="formRefJurisdiction" label-width="120px" :model="formModelJurisdiction">
          <el-form-item label="过期时间" prop="timeOut">
            <el-badge :value="messageTell" class="item">
              <el-date-picker
                v-model="formModelJurisdiction.timeOut"
                format="YYYY-MM-DD HH:mm:ss"
                type="datetime"
                placeholder="请选择过期时间!"
              >
              </el-date-picker>
            </el-badge>
          </el-form-item>
          <el-form-item label="功能菜单" prop="roleCode">
            <el-table
              ref="selectTable"
              :data="tableData"
              style="width: 100%; max-height: 500px; margin-bottom: 20px; overflow: auto"
              @select="selectbox"
              @select-all="select_All"
              row-key="id"
              border
              default-expand-all
              height="345px"
              size="small"
              @selection-change="selectChange"
            >
              <el-table-column type="selection" width="50" />
              <el-table-column prop="menuName" label="菜单" width="200"></el-table-column>
              <el-table-column prop="actionList" width="500" label="操作">
                <template #default="scope">
                  <el-checkbox-group v-model="formModelJurisdiction.grantActions">
                    <el-checkbox
                      v-for="(item, index) in scope.row.actionList"
                      @change="(checked) => log(checked, scope.row)"
                      :key="index"
                      :label="item.authorityId"
                      name="type"
                    >
                      <span :title="item.actionDesc">{{ item.actionName }}</span>
                    </el-checkbox>
                  </el-checkbox-group>
                </template>
              </el-table-column>
            </el-table>
          </el-form-item>
        </el-form>
      </el-tab-pane>
      <el-tab-pane label="角色成员" name="third" :disabled="type === 'add'">
        <el-transfer
          v-model="selectRole"
          :titles="['选择用户', '已选择用户']"
          filterable
          :props="{
            key: 'userId'
          }"
          :filter-method="filterMethod"
          :render-content="transferRender"
          :data="data"
        ></el-transfer>
      </el-tab-pane>
    </el-tabs>
    <template #footer>
      <el-button @click="roleDialogToClose(false)">取 消</el-button>
      <el-button type="primary" @click="save()">保 存</el-button>
    </template>
  </el-dialog>
</template>

<script lang="ts">
import dayjs from 'dayjs';
import _ from 'lodash-es';
import { defineComponent } from 'vue';
import {
  addRole,
  updateRole,
  GetUserToRole,
  allUserInfo,
  addRoleToUser,
  getJurisdictionRole,
  getJurisdiction,
  addJurisdictionRole
} from '../service/index';

export default defineComponent({
  name: 'editorRoleDialog',
  props: {
    type: {
      type: String,
      default: 'add'
    },
    roleDialogVisible: {
      type: Boolean
    },
    formModel: {
      type: Object
    }
  },
  emits: ['roleDialogClose', 'save'],
  watch: {
    formModel(val) {
      this.formModelRole = val;
    },
    formModelJurisdiction(val) {
      if (val.timeOut && new Date(val.timeOut) < new Date()) {
        this.messageTell = '授权已过期';
      } else {
        this.messageTell = '授权已过期';
      }
    }
  },
  data() {
    return {
      activeName: 'first',
      titleShow: '角色信息',
      formModelRole: {
        roleCode: '',
        roleName: '',
        status: '1',
        roleDesc: ''
      },
      selectRole: [],
      showRight: [],
      data: [],
      formModelJurisdiction: {
        timeOut: '',
        grantActions: []
      },
      tableData: [],
      selectJurisdiction: [],
      clickSelects: [],
      formRules: {
        roleCode: [
          { required: true, message: '角色标识不能为空', trigger: 'blur' },
          {
            required: true,
            validator: (rule: any, value: any, callback: any) => {
              const reg = /[^a-zA-Z]/g;
              if (reg.test(value) && value.indexOf('_') != -1) {
                let reg1 = /[0-9]/g;
                value.split().map((v) => {
                  if (reg1.test(v)) {
                    return callback(new Error('角色标识为字母下划线的组合'));
                  }
                });
                return callback();
              } else {
                return callback(new Error('角色标识为字母下划线的组合'));
              }
            },
            trigger: 'blur'
          }
        ],
        roleName: [
          { required: true, message: '角色名称不能为空', trigger: 'blur' },
          {
            required: true,
            validator: (rule: any, value: any, callback: any) => {
              const reg = /[^u4e00-u9fa5\w]/g;
              if (!reg.test(value)) {
                callback(new Error('角色名称必须为中文'));
              } else {
                return callback();
              }
            },
            trigger: 'blur'
          }
        ]
      },
      checkedJson: [],
      messageTell: '',
      status_checked: true,
      fatherSelectArray: []
    };
  },
  mounted() {},
  methods: {
    roleDialogToClose(refresh: boolean) {
      this.$refs.formRef.resetFields();
      this.$emit('roleDialogClose', refresh);
      this.selectJurisdiction = [];
      this.formModelJurisdiction = {};
      this.activeName = 'first';
      this.titleShow = '角色信息';
      // this.$refs.selectTable.clearAll()
      this.$refs.selectTable.clearSelection();
      this.formModelJurisdiction.grantActions = [];
      this.selectJurisdiction = [];
      this.checkedJson = [];
    },
    transferRender(h, option) {
      return option.userName + '(' + option.nickName + ')';
    },
    selectChange(selection) {
      // console.log();
      this.clickSelects = _.cloneDeep(selection);
    },
    toggleRowSelection() {},
    log(item, value) {
      // eslint-disable-next-line @typescript-eslint/no-this-alias
      // let that = this
      if (item) {
        this.checkedJson = [];
        this.$refs.selectTable.toggleRowSelection(value, true);
        let json = _.cloneDeep(this.clickSelects);
        let array = json.map((v) => {
          return v.authorityId;
        });
        this.tableData.map((v) => {
          if (v.children && v.children.length > 0) {
            this.pdDeep(v, value, array);
            if (this.checkedJson.length > 0) {
              this.checkedJson = this.Deduplication(this.checkedJson, 'id');

              this.checkedJson.map((j) => {
                this.$refs.selectTable.toggleRowSelection(j, true);
                this.soloveProblem(j, array);
              });
            }
            return;
          }
        });
      } else {
        //表格内部选择框,行内全部取消,取消右侧选中
        // if (!this.pdInArray(value, this.formModelJurisdiction.grantActions)) {
        //   this.$refs.selectTable.toggleRowSelection(value, false)
        //   // 如果右侧只有当前行选中,取消父级选中
        //   this.status_checked = true
        //   this.tableData.map((v) => {
        //     if (v.children && v.children.length > 0) {
        //       v.children.map((j) => {
        //         if (j.menuName === value.menuName) {
        //           let array = []
        //           this.clickSelects.map((v) => {
        //             array.push(v.authorityId)
        //           })
        //           for (let n = 0; n < v.children.length; n++) {
        //             if (array.includes(v.children[n].authorityId)) {
        //               this.status_checked = false
        //             }
        //           }
        //           if (this.status_checked) {
        //             this.$refs.selectTable.toggleRowSelection(v, false)
        //           }
        //         }
        //       })
        //     }
        //   })
        // }
      }
    },
    //用来判断需要选中的父级元素,
    /*array是用来判断的数组,里面包含了需要选中的父级
    *value1时选中的子级元素
    *array1是已经选中的元素的key的数组
    * */
    pdDeep(array, value1, array1) {
      if (array.children && array.children.length > 0) {
        for (let i = 0; i < array.children.length; i++) {
          if (array.children[i].id === value1.parentId) { //找到所选子级的父级
            if (array1 && array1.length > 0) {
              if (!array1.includes(array.children[i].authorityId)) { //如果当前父级被选中就不放入this.checkedJson中
                this.checkedJson.unshift(array.children[i]);
                this.tableData.map((v) => { //这里是再去向上找到该父级的父级,逐层向上
                  this.pdDeep(v, array.children[i], array1);
                });
              }
            } else { //如果已经选中的数组为空,则直接推入父级,然后逐层向上
              this.checkedJson.unshift(array.children[i]);
              this.tableData.map((v) => {
                this.pdDeep(v, array.children[i], array1);
              });
            }
          } else if (array.id === value1.parentId) { //直接判断array是否为所选子级的父级
            if (array1 && array1.length > 0) {
              if (!array1.includes(array.authorityId)) {
                this.checkedJson.unshift(array);
              }
            } else {
              this.checkedJson.unshift(array);
            }
          } else if (array.children[i]) { //这里是逐层向下,找到直接父级
            this.pdDeep(array.children[i], value1, array1);
          }
        }
      }
    },
    //递归的全部选择与全部取消,逐级向下操作
    selectAll(array, status) {
      try {
        if (array.children && array.children.length > 0) {
          array.children.map((v) => {
            setTimeout(() => {
              this.$refs.selectTable.toggleRowSelection(v, status);
              v.actionList.map((j) => {
                if (status) {
                  if (this.formModelJurisdiction.grantActions.indexOf(j.authorityId) === -1) {
                    this.formModelJurisdiction.grantActions.push(j.authorityId);
                  }
                } else {
                  if (this.formModelJurisdiction.grantActions.indexOf(j.authorityId) !== -1)
                    this.formModelJurisdiction.grantActions.splice(
                      this.formModelJurisdiction.grantActions.indexOf(j.authorityId),
                      1
                    );
                }
              });
              this.selectAll(v, status);
            }, 10);
          });
        } else if (array.actionList && array.actionList.length) {
          array.actionList.map((m) => {
            if (status) {
              if (this.formModelJurisdiction.grantActions.indexOf(m.authorityId) === -1) {
                this.formModelJurisdiction.grantActions.push(m.authorityId);
              }
            } else {
              if (this.formModelJurisdiction.grantActions.indexOf(m.authorityId) !== -1)
                this.formModelJurisdiction.grantActions.splice(
                  this.formModelJurisdiction.grantActions.indexOf(m.authorityId),
                  1
                );
            }
          });
        }
      } catch (e) {
        console.log(e);
      }
    },
    //表格头的全选与取消
    select_All(selection) {
      if (selection && selection.length > this.tableData.length) {
        this.tableData.map((v) => {
          this.selectAll(v, true);
        });
      } else {
        this.formModelJurisdiction.grantActions = [];
        this.tableData.map((v) => {
          this.selectAll(v, false);
        });
      }
    },
    pdChildren() {},
    selectbox(selection, row) {
      setTimeout(() => {
        this.checkedJson = [];
        if (selection.includes(row)) {
          this.$refs.selectTable.toggleRowSelection(row, true);
          let json = _.cloneDeep(this.clickSelects);
          let array = json.map((v) => {
            return v.authorityId;
          });
          console.log(array, 'array');
          this.tableData.map((v) => {
            if (v.children && v.children.length > 0) {
              this.pdDeep(v, row, array);
              if (this.checkedJson.length > 0) {
                this.checkedJson = this.Deduplication(this.checkedJson, 'id');
                this.checkedJson.map((j) => {
                  this.$refs.selectTable.toggleRowSelection(j, true);
                  this.soloveProblem(j, array);
                });
              }
            }
          });
          if (row.actionList && row.actionList.length > 0) {
            row.actionList.map((v) => {
              if (this.formModelJurisdiction.grantActions.indexOf(v.authorityId + '') === -1) {
                this.formModelJurisdiction.grantActions.push(v.authorityId);
              }
            });
          }
          if (row.children && row.children.length > 0) {
            this.selectAll(row, true);
          } else {
            if (row.actionList && row.actionList.length > 0) {
              row.actionList.map((v) => {
                if (this.formModelJurisdiction.grantActions.indexOf(v.authorityId + '') === -1) {
                  this.formModelJurisdiction.grantActions.push(v.authorityId);
                }
              });
            }
          }
        } else {
          if (row.actionList && row.actionList.length > 0) {
            row.actionList.map((v) => {
              if (this.formModelJurisdiction.grantActions.indexOf(v.authorityId + '') !== -1) {
                this.formModelJurisdiction.grantActions.splice(
                  this.formModelJurisdiction.grantActions.indexOf(v.authorityId + ''),
                  1
                );
              }
            });
          }
          if (row.children && row.children.length > 0) {
            this.selectAll(row, false);
          } else {
            if (row.actionList && row.actionList.length > 0) {
              row.actionList.map((v) => {
                if (this.formModelJurisdiction.grantActions.indexOf(v.authorityId + '') !== -1) {
                  this.formModelJurisdiction.grantActions.splice(
                    this.formModelJurisdiction.grantActions.indexOf(v.authorityId + ''),
                    1
                  );
                }
              });
            }
          }
          //表格取消选择子级时,全部取消,取消父级
          if (row) {
            setTimeout(() => {
              let Array = this.clickSelects.map((v) => {
                return v.authorityId;
              });

              console.log(Array, 'Array');
              this.fatherSelectArray = [];
              this.closeSelect(row, this.tableData);

              if (this.fatherSelectArray && this.fatherSelectArray.length > 0) {
                this.fatherSelectArray = this.Deduplication(this.fatherSelectArray, 'id');
                this.fatherSelectArray.map((q) => {
                  let status = false;
                  q.children.map((m) => {
                    if (Array.includes(m.authorityId)) {
                      status = true;
                    }
                  });
                  if (!status) {
                    this.$refs.selectTable.toggleRowSelection(q, false);
                  }
                });
              }
            }, 100);
          }
        }
      }, 200);
    },
    async save() {
      switch (this.activeName) {
        case 'first':
          if (this.type == 'add') {
            this.$refs.formRef.validate(async (valid) => {
              if (!valid) return;
              try {
                await addRole({
                  roleCode: this.formModelRole.roleCode,
                  roleName: this.formModelRole.roleName,
                  status: this.formModelRole.status,
                  roleDesc: this.formModelRole.roleDesc
                });
                this.$message({
                  type: 'success',
                  message: '添加角色成功'
                });
                this.roleDialogToClose(true);
              } catch (error) {
                console.log(error);
              }
            });
          } else {
            this.$refs.formRef.validate(async (valid) => {
              if (!valid) return;
              try {
                await updateRole({
                  roleId: this.formModelRole.roleId,
                  roleCode: this.formModelRole.roleCode,
                  roleName: this.formModelRole.roleName,
                  status: this.formModelRole.status,
                  roleDesc: this.formModelRole.roleDesc
                });
                this.$message({
                  type: 'success',
                  message: '修改角色成功'
                });
                this.roleDialogToClose(true);
              } catch (error) {
                console.log(error);
              }
            });
          }
          break;
        case 'second': {
          let array = [];
          this.clickSelects.map((v) => {
            array.push(v.authorityId);
          });
          array.push(...this.formModelJurisdiction.grantActions);
          let string = array.join(',');
          console.log(string, 'string');
          try {
            await addJurisdictionRole({
              roleId: this.formModelRole.roleId,
              expireTime: this.formModelJurisdiction.timeOut
                ? dayjs(this.formModelJurisdiction.timeOut).format('YYYY-MM-DD HH:mm:ss')
                : '',
              authorityIds: string
            });
            this.$message({
              type: 'success',
              message: '授权成功'
            });
            this.roleDialogToClose(true);
          } catch (error) {
            console.log(error);
          }
          break;
        }
        case 'third':
          try {
            await addRoleToUser({
              roleId: this.formModelRole.roleId,
              userIds: this.selectRole.join(',')
            });
            this.$message({
              type: 'success',
              message: '修改成功'
            });
            this.selectRole = [];
            this.roleDialogToClose(true);
          } catch (error) {
            console.log(error);
          }
          break;
        default:
          break;
      }
      // this.$refs.selectTable.clearSelection();
      this.formModelJurisdiction.grantActions = [];
      this.selectJurisdiction = [];
      this.checkedJson = [];
    },
    //切换tab时
    async handleClick(tab) {
      this.titleShow = tab.props.label;
      this.$nextTick(async () => {
        switch (this.activeName) {
          //权限组装树以及选中该选中的
          case 'second':
            try {
              let data1 = await getJurisdiction();
              let { data } = await getJurisdictionRole({
                roleId: this.formModelRole.roleId
              });
              this.formModelJurisdiction.grantActions = [];
              this.selectJurisdiction = [];
              this.formModelJurisdiction.timeOut = data[0] ? data[0].expireTime : '';
              if (new Date(this.formModelJurisdiction.timeOut) < new Date()) {
                this.messageTell = '授权已过期';
              } else {
                this.messageTell = '';
              }
              let array = [];
              let array2 = [];
              let array3 = [];
              data1.data.map((v) => {
                array3.push(v.authorityId);
                v.id = v.menuId;
                array.push(v.menuId);
              });
              //组装数据
              data1.data.map((v) => {
                if (array.includes(v.parentId) && v.parentId != '0') {
                  array2.push(v);
                  if (data1.data[array.indexOf(v.parentId)].children) {
                    console.log(1);
                  } else {
                    data1.data[array.indexOf(v.parentId)].children = [];
                  }
                  data1.data[array.indexOf(v.parentId)].children.push(v);
                }
              });
              array2.map((v) => {
                data1.data.splice(data1.data.indexOf(v), 1);
              });
              this.tableData = data1.data;
              data.map((v) => {
                v.id = v.authorityId;
                if (!array3.includes(v.authorityId)) this.formModelJurisdiction.grantActions.push(v.authorityId);
                this.selectJurisdiction.push(v.authorityId);
              });
              this.checkedJson = [];
              this.BackShow(this.selectJurisdiction, this.tableData);
              this.Deduplication(this.checkedJson, 'id');
              this.$nextTick(function () {
                this.checkedJson.map((j) => {
                  this.$refs.selectTable.toggleRowSelection(j, true);
                  this.soloveProblem(j, this.checkedJson);
                });
              });
            } catch (error) {
              console.log(error);
            }
            break;
          case 'third':
            try {
              let userinfo = await allUserInfo();
              let userall = userinfo.data;

              let { data } = await GetUserToRole({
                roleId: this.formModelRole.roleId
              });
              data.map((v) => {
                this.selectRole.push(v.userId);
              });
              this.data = userall;
            } catch (error) {
              console.log(error);
            }
            break;
          default:
            break;
        }
      });
      this.checkedJson = [];
    },
    filterMethod(query, item) {
      return item.userName.includes(query);
    },
    //取消时判断id是否在数组中,不在返回false
    pdInArray(idarray, array) {
      let status = false;
      if (idarray && array && array.length > 0) {
        for (let i = 0; i < idarray.actionList.length; i++) {
          if (array.includes(idarray.actionList[i].authorityId)) {
            status = true;
          }
        }
        return status;
      } else {
        return status;
      }
    },
    //  取消选中,解决选中父级其子级也被选中的问题
    /*
    * parent为传入的父级元素
    * array已经选中的key组成的数组
    * */
    soloveProblem(parent, array) {
      // eslint-disable-next-line @typescript-eslint/no-this-alias
      let that = this;
      function dgselect(parent, array) {
        //如果本身是选中的就继续选中
        if (parent.children && parent.children.length > 0) {
          if (array && array.length > 0) {
            parent.children.map((j) => {
              if (array.indexOf(j.authorityId) != -1) {
                that.$refs.selectTable.toggleRowSelection(j, true);
              } else if (j.children && j.children.length > 0) {
                dgselect(j, array); //逐级向下去判断选择与否
              }
            });
          }
        }
      }
      //先全部取消子级,及子子级的选中
      if (parent.children && parent.children.length > 0) {
        parent.children.map((v) => {
          this.$refs.selectTable.toggleRowSelection(v, false);
        });
      }
      dgselect(parent, array);
    },
    // 去重
    Deduplication(array, byWhat) {
      if (array.length > 0) {
        for (let i = array.length - 1; i >= 1; i--) {
          for (let j = i - 1; j >= 0; j--) {
            if (array[i][byWhat] === array[j][byWhat]) {
              array.splice(i, 1);
              i = i - 1;
            }
          }
        }
        return array;
      }
    },
    // 回显问题
    /* array需要选中的key组成的数组
    *  array1为树形表格的全部数据
    * */
    BackShow(array, array1) {
      if (array && array.length > 0) {
        array.map((id) => {
          array1.map((v) => {
            if (id === v.authorityId) {
              this.checkedJson.push(v);
            } else if (v.children && v.children.length > 0) {
              v.children.map((j) => {
                this.BackShow([id], v.children);
              });
            }
          });
        });
      }
    },
    // 级联取消
    closeSelect(row, table, father = null) {
      if (table && table.length > 0) {
        table.map((v) => {
          if (v.id === row.parentId) {
            this.fatherSelectArray.push(v);
            if (father) {
              this.fatherSelectArray.push(father);
            }
          } else if (v.children && v.children.length > 0) {
            this.closeSelect(row, v.children, v);
          }
        });
      }
    }
  }
});
</script>

<style lang="scss" scoped>
:deep(.el-divider) {
  margin: 0 !important;
}

:deep(.el-transfer) {
  width: 100% !important;
  --el-transfer-panel-width: 38%;
}

.item {
  margin-top: 6px;
  margin-right: 40px;
}
</style>

功能尚未完善,勿喷!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值