vue本地搜索-递归查询列表-封装树结构列表

vue本地搜索-递归查询列表-封装树结构列表

tableSearch.vue-界面
<template>
  <div class="container">
    <div>
      <SearchTree
        style="flex: 1"
        :dataList="treeData"
        :isEdit="false"
        :isSearch="true"
        :isDrag="true"
        v-show="!isShowInfo"
        @treeSearch="treeSearch"
        :treeProps="{
          label: 'settingtypename',
          children: 'seatTypeList',
        }"
      ></SearchTree>
    </div>
    <div>
      <!-- row-key="myID"    更换唯一标识   避免index或id有相同的,产生冲突 -->
      <el-table
        stripe
        :data="tableData"
        style="width: 100%; margin-bottom: 20px"
        row-key="myID"
      ></el-table>
    </div>
  </div>
</template>
<script>
import SearchTree from "./SearchTree";
export default {
  components: {
    SearchTree,
  },
  data() {
    return {
      isShowwInfo: false,
      tableDataMergeInfo: [],
    };
  },
  created() {
    var tableDataMerge = [];
    var oneSeatPlan = {};
    oneSeatPlan = this.tableDataResult;
    tableDataMerge.push(oneSeatPlan);
    this.recursion(tableDataMerge);
    this.tableDataMergeInfo = tableDataMerge;
    this.tableData = this.tableDataMergeInfo;
  },
  methods: {
    // 递归添加字段
    recursion(arr) {
      arr.forEach((el) => {
        let myID = Math.random().toString(36).substr(2);
        this.$set(el, "myID", myID);
        if (el.children && el.children.length) {
          this.recursion(el.children);
        }
      });
    },
    // 递归搜索数据
    recursion2(arr, filterWords) {
      arr.forEach((el) => {
        if (el.seattingtypename.includes(filterWords)) {
          this.midellTreeArr.push(el);
          return;
        }
        if (el.seatTypeList && el.seatTypeList.length) {
          this.recursion2(el.seatTypeList, filterWords);
        }
      });
      this.treeData = this.midellTreeArr;
    },
    treeSearch(val) {
      if (!val) {
        this.treeData = this.initTreeData;
        return;
      }
      let filterData = [...this.initTreeData];
      this.midellTreeArr = [];
      console.log(this.initTreeData);
      this.recursion2(filterData, val);
    },
  },
};
</script>
<style scoped lang="less">
// 树结构菜单
.search-tree-warp {
  border-top: none;
  box-sizing: border-box;
  position: relative;
  margin-top: 2vw;
  margin-right: 2vw;
  height: 53vh;
  flex: 1;
}
</style>
SearchTree.vue-组件
<template>
  <div class="search-tree-warp">
    <slot></slot>
    <div class="search-tree-title" v-if="title">{{ title }}</div>
    <el-input
      v-if="isSearch"
      class="tree-search-input"
      placeholder="请搜索相关内容"
      size="mini"
      suffix-icon="el-icon-search"
      clearable
      v-model="treeSearch"
    ></el-input>
    <el-tree
      :data="dataList"
      :props="treeProps"
      :filter-node-method="treeFilter"
      :allow-drag="allowDrag"
      :allow-drop="allowDrop"
      :default-expanded-keys="myTreeExpandData"
      highlight-current
      node-key="id"
      @node-drag-start="handleDragStart"
      @node-click="handleNodeClick"
      accordion
      draggable
      ref="tree"
      :class="isSearch ? 'tree-heigth' : ''"
      v-on="$listeners"
    >
      <span
        class="train-class-tree"
        slot-scope="{ node, data }"
        @drop="handleDrop($event, node, data)"
      >
        <i class="tree-round"></i>
        <i class="tree-my-icon" v-if="data.icon" :class="data.icon"></i>
        <span>{{ node.label }}</span>
        <div class="tree-btn-warp" v-if="isEdit">
          <span
            @click="editTree(data, node)"
            class="el-icon-edit"
            v-if="node.level != 1 || rootEdit"
          ></span>
          <span @click="addTree(data, node)" class="el-icon-plus"></span>
          <i
            @click.stop="delTree(data, node)"
            class="el-icon-minus"
            v-if="node.level != 1|| rootEdit"
          ></i>
        </div>
      </span>
    </el-tree>
  </div>
</template>

<script>
export default {
  name: "SearchTree",
  props: {
    isSearch: {
      type: Boolean,
      default: false,
    },
    treeProps: {
      type: Object,
      default: function () {
        return {
          label: "label",
          children: "children",
        };
      },
    },
    isEdit: {
      type: Boolean,
      default: true,
    },
    isRootEdit: {
      type: Boolean,
      default: true,
    },
    rootEdit:{
      type: Boolean,
      default: false,
    },
    dataList: {
      type: Array,
      default: function () {
        return [];
      },
    },
    myTreeExpandData: {
      type: Array,
      default: function () {
        return ["0"];
      },
    },
    title: {
      type: String,
      default: "",
    },
    isDrop: {
      type: Boolean,
      default: false,
    },
    isDrag: {
      type: Boolean,
      default: false,
    },
    isDragRoot: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      treeSearch: "",
    };
  },
  watch: {
    treeSearch(val) {
      this.$emit("treeSearch", val);
    },
  },
  methods: {
    /**
     * 自定义按钮
     */
    editTree(data, node) {
      // this.myTreeExpandData = [];
      // this.myTreeExpandData.push(data.id);
      let subData = Object.assign({}, data);
      this.$emit("editTree", subData);
    },
    addTree(data, node) {
      this.$emit("addTree", data);
    },
    delTree(data, node) {
      this.$confirm("是否要删除?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        this.$emit("delTree", data, node);
      });
    },
    // tree
    treeFilter(value, data) {
      if (!value) return true;
      return data[this.treeProps.label].indexOf(value) !== -1;
    },
    allowDrag(node, ev) {
      // ev.dataTransfer.setData("itemData", str);
      if (this.isDragRoot) {
        // 默认只能最底层节点拖拽
        return this.isDrag && node.childNodes.length === 0;
      } else {
        return this.isDrag;
      }
    },
    allowDrop(draggingNode, dropNode, type) {
      return this.isDrop;
    },
    handleNodeClick(obj, dom, com) {
      dom.expanded = true;
      this.$emit("clickTree", obj, dom, com);
    },
    handleDragStart(node, ev) {
      /* console.log(node)
				console.log(ev) */
      let str = JSON.stringify(node.data);
      ev.dataTransfer.setData("itemData", str);
    },
    handleDrop(ev, node, dropData) {
      if (!this.isDrop) {
        this.$message({
          message: "此处不能被放置",
          type: "error",
        });
        return;
      }
      // console.log(789,)
      let droped = false;
      if (
        this.$refs.tree.getCurrentNode() &&
        this.$refs.tree.getCurrentNode().id == dropData.id
      ) {
        droped = true;
      }
      this.$refs.tree.setCurrentNode(dropData);
      let strData = ev.dataTransfer.getData("itemData");
      let dragData = JSON.parse(strData);
      this.$emit("drop", dragData, node, dropData,droped);
    },
    handleDragOver(node, dropNode, ev) {
      ev.preventDefault();
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss">
.search-tree-warp {
  border-top: none;
  box-sizing: border-box;
  position: relative;
  margin-top: 2vw;
  margin-right: 2vw;
  flex: 1;
  .search-tree-title {
    font-size: 14px;
    color: #fff;
    border-radius: 8px;
    text-align: center;
    margin-bottom: 20px;
  }
  /*搜索框*/
  .tree-search-input {
    margin: 0vw 0.39rem;
    margin-bottom: 1vw;
    width: calc(100% - 0.39rem - 8px);
    box-sizing: border-box;

    > input {
      background-color: #104769;
      border: solid 0.05vw #2685b3;
      font-size: 0.14rem;
      color: #fff;

      &::-webkit-input-placeholder {
        color: #82c5e8;
      }
    }
  }
  .is-current {
    > .el-tree-node__content {
      background-image: linear-gradient(
        90deg,
        rgba(38, 133, 179, 0),
        rgba(38, 133, 179, 1),
        rgba(38, 133, 179, 0)
      ) !important;
    }
  }
  .el-tree {
    width: 100%;
    // position: absolute;
    height: 100% !important;
    overflow: auto;
    background: transparent;

    .el-tree-node__expand-icon {
      margin-right: 5px;
    }

    &::-webkit-scrollbar-button {
      display: none;
      // background-image: url();
    }

    &::-webkit-scrollbar-track {
      border-radius: 10px;
      background-color: #184660;
    }

    .el-tree-node {
      .el-icon-caret-right {
        padding: 0px;
        margin-left: 0.39rem;
      }

      .el-tree-node__content {
        background-color: transparent !important;
        padding: 20px;
        &:hover {
          background-image: linear-gradient(
            90deg,
            rgba(38, 133, 179, 0),
            rgba(38, 133, 179, 1),
            rgba(38, 133, 179, 0)
          );
        }
      }
    }

    .el-tree-node__expand-icon {
      color: #39baf8;
      margin-right: 0.1rem;
    }

    .el-tree-node__expand-icon.is-leaf {
      color: transparent !important;
    }

    div[role="group"] {
      //非根节点
      .tree-round {
        display: none;
      }

      .tree-my-icon {
        margin-right: 0.1rem;
        display: inline-block;
      }

      .tree-btn-warp {
        display: inline-block;
      }
    }
  }
  .tree-heigth {
    height: calc(100% - 3vw - 60px) !important;
  }

  .train-class-tree {
    font-size: 0.14rem;
    color: #daf0fc;
    display: flex;
    align-items: center;
    cursor: pointer;
    padding: 0.12rem 0px;

    /* 席位类别树形结构按钮包裹盒子 */
    .tree-btn-warp {
      margin-left: 0.1rem;
      span {
        color: #39baf8;
      }

      i {
        color: #d9374e;
      }

      span,
      i {
        padding: 0px 0.05rem;
      }
    }

    > .tree-round {
      margin-right: 0.1rem;
    }

    .tree-round {
      display: block;
      width: 0.1rem;
      height: 0.1rem;
      background: #42cfaf;
      border: 0.04rem solid #1c4f56;
      border-radius: 50%;
    }
  }
}
</style>

效果图

1.1-搜索子级携带父级

在这里插入图片描述

1.2

在这里插入图片描述

2.1-搜索菜单组件

在这里插入图片描述

2.2

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值