1、业务要求

树结构有两级,由大类和小类组成。

当大类中不存在大类时,只能选择大类;当大类中存在小类时,只能选择大类中的小类。

当切换大类或者非选中大类中的小类时,清空原有选择数据。

2、效果展示

3、组件代码

<!-- 树形结构 -->
<template>
  <el-dialog
    :visible.sync="testTypeTreeViewFlag"
    width="55%"
    :append-to-body="true"
    class="mainContainer"
  >
    <div class="projectTitle">请选择检测项目</div>
    <el-input placeholder="输入关键字进行过滤" v-model="filterText" clearable></el-input>
    <el-tree
      :data="treeData"
      :props="treeProp"
      show-checkbox
      node-key="id"
      ref="testTypetree"
      highlight-current
      class="testTypeTree"
      :filter-node-method="filterNode"
      :check-on-click-node=true
      :accordion=true
      @check="getCheckData"
    ></el-tree>
    <span slot="footer" class="dialog-footer">
      <el-button type="primary" @click="confirmTestTypeSelect">确认选择</el-button>
      <el-button type="info" @click="closeTestTypeTreeView">关闭</el-button>
    </span>
  </el-dialog>
</template>

<script>
export default {
  name: "TestTypeTree",
  components: {},
  props: {
    testTypeTreeViewFlag: {
      type: Boolean,
      required: true,
    },
    treeData: {
      type: Array,
      default: [],
    },
  },
  data() {
    return {
      itemIndex: 0, // 数组中的第几项
      filterText: "", // 关键字过滤
      checkedNodeArr: [], // 选中的检测项目数组
      treeProp: {
        // 树形结构解析树形
        children: "children",
        label: "label",
      },
      accordion: true, // 是否一级一级展开
    };
  },
  computed: {},
  watch: {
    // 实时监听过滤关键字
    filterText(val) {
      this.$refs.testTypetree.filter(val);
    },
  },
  methods: {
    // 关闭检测信息弹窗
    closeTestTypeTreeView() {
      this.$emit("closeTestTypeTreeView");
    },
    // 关键字过滤
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
    // 确认选择
    confirmTestTypeSelect() {
      if (this.checkedNodeArr.length === 0) {
        this.$message({
          type: "warning",
          message: "请选择检测项目",
        });
        return;
      }
      // 当只存在二级菜单时,this.checkedNodeArr中缺少所对应的一级菜单
      // 由于显示数据需要拼接,当数据中只存在二级菜单需要查找一级菜单一并返回

      // 判断是否存在一级菜单,不存在则flag为false,存在则flag为true
      let flag = false;
      this.checkedNodeArr.some((item) => {
        if (item.parentId == "#") {
          flag = true;
          return true;
        }
      });
      if (!flag) {
        // 当不存在时,获取对应的一级菜单数据,组合后一并发给主页面
        let arr = [];
        let firstItemId = this.checkedNodeArr[0].parentId;
        this.treeData.some((item) => {
          if (item.id == firstItemId) {
            arr.push(item);
            return true;
          }
        });
        arr = [...arr, ...this.checkedNodeArr];
        this.$emit("confirmTestTypeSelect", arr, this.itemIndex, flag);
      } else {
        this.$emit(
          "confirmTestTypeSelect",
          this.checkedNodeArr,
          this.itemIndex,
          flag
        );
      }
    },
    //
    getCheckData(data, node) {
      // console.log(this.$refs.testTypetree.store)
      // 选中节点自动展开

      // 判断点击的是一级节点还是二级节点
      let firstItemId = data.parentId == "#" ? data.id : data.parentId;
      // 判断当前是选中还是取消选中
      let checkedNodes = node.checkedNodes;
      let arr = [];
      checkedNodes.forEach((item) => {
        if (item.id == firstItemId || item.parentId == firstItemId) {
          arr.push(item);
        }
      });
      this.checkedNodeArr = arr;
      if (arr.length > 0) {
        this.$refs.testTypetree.setCheckedNodes(arr);
      }
    },
    // 获取treeData 数据
    getTreeData(index, selectTreeId) {
      this.itemIndex = index;
      if (selectTreeId) {
        this.$refs.testTypetree.setCheckedKeys(selectTreeId);
      }
    },
  },
  created() {},
  mounted() {},
};
</script>
<style lang='scss' scoped>
.projectTitle {
  width: 100%;
  height: 40px;
  line-height: 40px;
  background-color: #7ee697;
  font-size: 1rem;
  padding-left: 20px;
  padding-right: 20px;
  font-weight: bolder;
  margin-bottom: 25px;
  color: #000000;
}
.testTypeTree {
  max-height: 500px;
  overflow: auto;
  margin-top: 15px;
}
</style>

4、组件使用

<!-- 检测信息树形弹窗 -->
<test-type-tree
:testTypeTreeViewFlag="testTypeTreeViewFlag"
:treeData="treeData"
@closeTestTypeTreeView="closeTestTypeTreeView"
@confirmTestTypeSelect="confirmTestTypeSelect"
ref="testTypeTree"
></test-type-tree>
import TestTypeTree from "@/components/TestTypTree"; // 检测信息树形弹窗
export default {
    components: { TestTypeTree },
    data() {
        return {
            testTypeTreeViewFlag: false,
            treeData: [], // 树形数据
            departmentUserList: [], // 部门人员树结构
        }
    },
    methods: {
    	closeTestTypeTreeView() {
    		this.testTypeTreeViewFlag = false;
    	},
    	confirmTestTypeSelect() {
    	  this.testTypeTreeViewFlag = false;
          let arrFrist = [], // 一级菜单数组
          arrSecond = [], // 二级菜单数组
          arrSecondId = [], // 二级菜单id
          selectTreeId = []; // 选中数据,用于数据回显
          arr.forEach((item) => {
            if (item.parentId == "#") {
              if (flag) {
                selectTreeId.push(item.id);
              }
              arrFrist.push(item);
            } else {
              arrSecond.push(item);
              selectTreeId.push(item.id);
              let obj = { ExamineID: item.id };
              arrSecondId.push(obj);
            }
          });
          let str = arrFrist[0].label;
          if (arrSecond.length > 0) {
            str += "(";
            arrSecond.forEach((item, index) => {
              str += item.label;
              if (index != arrSecond.length - 1) {
                str += ",";
              }
            });
            str += ")";
          }
          this.sampleMainruleForm.DetectionTaskItemsList[itemIndex].selectFirstMenuName = arrFrist[0].label;
          this.sampleMainruleForm.DetectionTaskItemsList[itemIndex].selectTreeName = str;
          this.sampleMainruleForm.DetectionTaskItemsList[itemIndex].selectTreeId = selectTreeId;
          this.sampleMainruleForm.DetectionTaskItemsList[itemIndex].ExamineTypeID =arrFrist[0].id;
          this.sampleMainruleForm.DetectionTaskItemsList[itemIndex].Children = arrSecondId;
    	}
    }
}
    

5、备注

树结构数据: