实现 select 中嵌套 tree 外加搜索

实现 select 中嵌套 tree 外加搜索

参考地址实现地址
在这里插入图片描述

代码

<el-form-item label="考核人员" prop="userIdArr" v-if="title == '发起考核'">
  <el-popover v-model="popoverVisible" placement="bottom" trigger="click" ref="popover">
     // click:点击select时弹出框显示
     // popover+tree用于选择,树形控件放在弹出框中
    <el-input class="input" placeholder="此处键入'关键词'搜索查询" prefix-icon="el-icon-search" v-model="treeFilter"
      size="mini" v-focus clearable />
    <!-- 通过 checkbox 进行选择,通过 checkChange 来进行保存值 -->
    <el-tree :data="deptOptions" :props="defaultProps" show-checkbox @check="checkChange"
      :default-checked-keys="this.form.userIdArr" ref="tree" node-key="iid" :filter-node-method="filterNode"
      :default-expand-all="false" :style="`max-height: ${treeMaxHeight}px; overflow-y: auto;`" />
    // select展示选择结果,储存选择值typeValue
    <el-select slot="reference" multiple collapse-tags v-model="form.userIdArr" placeholder="请选择"
      popper-class="hiddenSel" clearable @clear="clearTag" @remove-tag="removeTag">
      <el-option v-for="item in typeOption" :key="item.iid" :label="item.label" :value="item.iid" />
    </el-select>
  </el-popover>
</el-form-item>

data 数据

// 需把数据整理成以下结构
// tree数据(children的id第一位为父级id,用于在select中清除某一点,可找到其父级去掉全选)
deptOptions: [], // tree 的数据
typeOption: [], // select 选择框一维数据
defaultProps: {
  // tree 的显示类名
  children: "children",
  label: "label",
},
treeFilter: "", // 搜索框绑定值,用作过滤
// 选中数组
  ids: [],

methods 方法:

watch: {
  // 搜索过滤,监听input搜索框绑定的treeFilter
  treeFilter(val) {
    this.$refs.tree.filter(val);
    // 当搜索框键入值改变时,将该值作为入参执行树形控件的过滤事件filterNode
  },
}
methods: {
// 发起考核
 // select 框部分
 /** 查询部门下拉树结构 */
 getDeptTree() {
   userTreeList().then((response) => {
     // 将数据 user 添加进 children,并且将字段名更改下
     this.deptOptions = this.copyAndRenameFieldsInArray(response.data);

     // 对数据进行添加 iid
     this.deptOptions = this.addIid(this.deptOptions);

     // 处理好的数据 进行扁平化
     this.typeOption = this.flattenData(this.deptOptions);
   });
 },
 // 将部门tree进行扁平化
 flattenData(data) {
   const result = [];

   function flatten(item) {
     result.push({ id: item.id, label: item.label, iid: item.iid });

     if (item.children) {
       item.children.forEach((child) => {
         flatten(child);
       });
     }
   }

   data.forEach((item) => {
     flatten(item);
   });

   return result;
 },
 // 将 user 添加进 children
 copyAndRenameFieldsInArray(data) {
   data.forEach((node) => {
     if (node.users && node.users.length > 0) {
       node.children = node.children || [];
       // 将复制并重命名字段的数据拼接到 children 数组的最前面
       node.children.unshift(
         ...node.users.map((user) => ({
           userId: user.userId,
           id: user.userId,
           userName: user.userName,
           label: user.nickName,
           deptId: user.deptId,
           nickName: user.nickName,
         }))
       );
       node.users = [];
     }

     if (node.children && node.children.length > 0) {
       this.copyAndRenameFieldsInArray(node.children);
     }
   });
   return data;
 },
 // 加字段 iid
 addIid(data, iidPrefix = "") {
   return data.map((item) => {
     const iid = iidPrefix + item.id;
     const newItem = { ...item, iid };

     if (item.children) {
       newItem.children = this.addIid(item.children, iid + "-");
     }

     return newItem;
   });
 },
 // tree选择值修改时
 checkChange() {
   this.form.userIdArr = [];
   // 将tree选择的id赋值给select
   this.$refs["tree"]?.getCheckedNodes(true).forEach((value) => {
     // 父级在select中不展示
     if (value.iid.indexOf("-") > 0) {
       this.form.userIdArr.push(value.iid);
     }
   });
 },
 // 模糊查询(搜索过滤),实质为筛选出树形控件中符合输入条件的选项,过滤掉其他选项
 filterNode(value, data) {
   if (!value) return true;
   let filterRes =
     data.label.toLowerCase().indexOf(value.toLowerCase()) !== -1;
   return filterRes;
 },
 // 清空select
 clearTag() {
   // 清空tree选择
   this.$refs["tree"].setCheckedKeys([]);
 },
 // 从select中单个移除时,保持tree选择值同步移除
 removeTag(data) {
   // 获取tree目前选择的值
   var chooseData = this.$refs["tree"].getCheckedKeys(true);
   var deleteIndex = "";
   // 找到chooseData中与清除的data相同的值
   chooseData.forEach((value, index) => {
     if (value === data) {
       deleteIndex = index;
     }
   });
   // 从tree目前选择值中去掉
   chooseData.splice(deleteIndex, 1);
   // 若有全选情况,tree的选择值中有父级id,而select中无父级id,需用children的id找到父级id并去掉
   // 查找其父级id是否在chooseData中(即原来此父级是否全选),若在则去掉
   var findFatherData = chooseData.find(
     (element) => element === data.split("-")[0]
   );
   if (findFatherData) {
     chooseData.splice(chooseData.indexOf(findFatherData), 1);
   }
   // 将修改后的值再赋给tree
   this.$refs["tree"].setCheckedKeys(chooseData);
 },
 // 时间戳转化为时间
 formatDate(dateString) {
   const date = new Date(dateString);

   const year = date.getFullYear();
   const month = ("0" + (date.getMonth() + 1)).slice(-2);
   const day = ("0" + date.getDate()).slice(-2);
   const hours = ("0" + date.getHours()).slice(-2);
   const minutes = ("0" + date.getMinutes()).slice(-2);
   const seconds = ("0" + date.getSeconds()).slice(-2);

   const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;

   return formattedDate;
 },
}
  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值