1、业务需求

树结构由部门和人员组成,其中部门为树一级节点,人员为树二级节点,要求点选时只能选择一个人。

2、效果展示


3、组件代码

借助于element-ui el-tree

<!-- 人员结构树 -->
<template>
   <el-dialog
    :visible.sync="personTreeViewFlag"
    width="55%"
    :append-to-body="true"
    class="mainContainer personTree"
  >
  <div class="projectTitle"> {{ titleText }}</div>
  <el-input placeholder="输入关键字进行过滤" v-model="filterText" clearable=""></el-input>
  <el-tree :data="treeData" :props="treeProp" 
    show-checkbox
    node-key="department_userId"
    ref="personSelect"
    highlight-current
    class="personSelect"
    :filter-node-method="filterNode"
    :accordion="isMultiple == '1'"
    :check-on-click-node=true
    @check-change="getCheckData"
    ></el-tree>
    <span slot="footer" class="dialog-footer">
     <el-button type="primary" @click="confirmPersonSelect">确认选择</el-button>
     <el-button type="info" @click="cancelPersonSelect">取消选择</el-button>
     <el-button type="info" @click="closePersonTreeView">关闭</el-button>
    </span>
   </el-dialog>
</template>

<script>
export default {
  props: {
    personTreeViewFlag:{
      // 树弹窗显示标识
      type: Boolean,
      required: true
    },
    titleText: {
      // 标题名称
      type: String,
      default: "人员信息"
    },
    isMultiple: {
      // 是否为单选 1是0否
      type: String,
      required: true
    },
    treeData: {
      // 树形结构
      type: Array,
      default: []
    },
    isRequire: {
      // 是否必填,1是0否
      type: String,
      // default: false
    }
  },
  components: {},
  data() {
    return {
      filterText: "", // 关键字过滤
      treeProp: {
           // 树形结构解析树形
          children: 'children',
          label: 'label',
          // id: 'department_userId'
      },
      checkedNodeArr: [], // 选中的人员数组
    };
  },
  computed: {},
  watch: {
    // 实时监听过滤关键字
      filterText(val) {
        this.$refs.personSelect.filter(val);
      }
  },
  methods: {
    // 关键字过滤
    filterNode(value, data) {
        if (!value) return true;
        return data.label.indexOf(value) !== -1;
    },
    // 确认
    confirmPersonSelect() {
      let personSelect = this.$refs.personSelect.getCheckedNodes();
      if(this.isRequire == "1" && personSelect.length === 0) {
        this.$message({
            type: "warning",
            message: "请选择人员"
        })
        return;
      }
      let arr = []; // 人员数组
      personSelect.forEach(item => {
        if(item.parentId != "#") {
          arr.push(item)
        }
      })
      this.$emit("confirmPersonSelect", arr)
    },
    // 关闭
    closePersonTreeView() {
      this.$emit("closePersonTreeView")
    },
    // 选择人员
    getCheckData(data, checked) {
      if(this.isMultiple == "1") {
        let personSelect = this.$refs.personSelect.getCheckedNodes(); 
        let idArr = [];
        if(checked) {
          // 判断是否是选中部门
          if(data.parentId == "#") {
            // 判断部门下人员数量
            if(data.children.length === 0) {
              this.$message({
                type: "warning",
                message: "该部门下不存在人员,请重新选择"
              })
              this.$refs.personSelect.setCheckedNodes([])
            }else if(data.children.length  > 1) {
              // this.$message({
              //   type: "warning",
              //   message: "该部门下存在多个人员,请选择一个"
              // })
              // return;
              idArr = [ data.children[0].department_userId ]
              this.$refs.personSelect.setCheckedNodes(idArr);
              return;
            } 
            else {
              this.$refs.personSelect.setCheckedKeys([])
              idArr.push(data.children[0]["department_userId"]);
              this.$refs.personSelect.setCheckedKeys(idArr)
            }
          } else {
            this.$refs.personSelect.setCheckedKeys([])
            idArr.push(data["department_userId"]);
            this.$refs.personSelect.setCheckedKeys(idArr)
          }
        } 

      }
    },
    // 取消选择
    cancelPersonSelect() {
       this.$refs.personSelect.setCheckedKeys([])
    },
    // 获取树最新展示
    getTreeSelect(selectNode){
      let node = selectNode ? selectNode: [];
      this.$refs.personSelect.setCheckedKeys(node)
    }
  },
  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;
}
.personSelect {
    max-height: 500px;
    overflow: auto;
    margin-top: 15px;
}
</style>
<style lang="scss">
.personTree {
    .el-dialog {
      margin-top: 3vh !important;
    }
}
</style>

4、组件使用

 <!-- 样品关联人树形结构 -->
    <person-tree
    :personTreeViewFlag="sampleRelationTreeViewFlag"
    ref="sampleRelationTree"
    titleText="请选择样品关联人"
    isMultiple="1"
    :treeData="departmentUserList"
    isRequire="0"
    @closePersonTreeView="closeSampleRelationTree"
    @confirmPersonSelect="confirmSampleRelationTree"
    >
    </person-tree>
 import PersonTree from "@/components/PersonTree/personTree_index"; // 部门用户树状结构
 export default {
 	components: { PersonTree },
 	data() {
    	return {
    		sampleRelationTreeViewFlag: false,
    		departmentUserList: [], // 部门人员树结构
    	}
    },
    methods: {
    	// 确认
    	confirmSampleRelationTree() {
    		// 以下代码根据业务要求实现
    	  let arr1 = []; // 人员数组id
          let str = "";
          arr.forEach((item, index) => {
            arr1.push(item.department_userId)
            str += item.label 
            if(index != arr.length - 1) {
              str += ","
            }
          })
          this.sampleMainruleForm.RelatedUserIDs = arr1;
          this.sampleMainruleForm.RelatedUserID = arr1[0].split("_")[1];
          this.sampleMainruleForm.RelationUserName = str;
          this.closeSampleRelationTree();
    	},
    	// 关闭样品关联人树形弹窗
        closeSampleRelationTree() {
          this.sampleRelationTreeViewFlag = false;
        },
    }
 	
 }

5、备注

树结构数据: