antd-vue tree search box automatically expands and changes color


<template>

  <page-header-wrapper>

    <a-row type="flex" justify="space-around">

      <a-col :xl="7" :lg="24" style="border: 1px solid rgba(0, 0, 0, 0.5); box-shadow: 0px 0.5px 10px #888888">

        <a-input-search

          v-model="searchStr"

          placeholder="请搜索公司名称"

          style="width: 100%"

          @search="onSearch"

        ></a-input-search>

        <!-- selectedKeys是选中项key的集合,expandedKeys是展开项key的集合 -->

        <a-tree

          v-model="checkedKeys"

          :treeData="treeData"

          :selectedKeys="selectedKeys"

          :expandedKeys="expandedKeys"

          @expand="onExpand"

          :autoExpandParent="autoExpandParent"

          :replaceFields="replaceFields"

          @select="onSelect"

          style="height: 70vh; overflow-y: auto"

        >

          <template slot="title1" slot-scope="{ name }" style="display: flex; justify-content: space-between">

            <span

              v-html="name.replace(new RegExp(searchValue, 'g'), '<span style=color:#f50>' + searchValue + '</span>')"

            ></span>

            <a-button type="link" style="float: right" size="small" @click="showModal()">公司详情</a-button>

          </template>



          <template

            slot="title"

            slot-scope="{ name }"

            style="display: flex; justify-content: space-between; width: 100%"

          >

            <span

              v-html="name.replace(new RegExp(searchValue, 'g'), '<span style=color:#f50>' + searchValue + '</span>')"

            ></span>

          </template>

        </a-tree>

        <!-- 公司详情模态框 -->

        <a-modal v-model="visible" :title="computedname">

          <!-- 自定义页脚按钮 -->

          <template slot="footer">

            <a-button key="submit" type="primary" @click="handleOk">返回</a-button>

          </template>

          <p>姓名: {
   
   { fname == null ? '纯爱战神爱看动漫' : fname }}</p>

          <p>手机号: {
   
   { fphone == null ? '155xxxxxxxx' : fphone }}</p>

          <p>社会统一代码: {
   
   { code == null ? '12345656632412342345' : code }}</p>

          <p>企业公章号码: {
   
   { seal == null ? '1234234134134134' : seal }}</p>

          <p>账号:{
   
   { lvdao_name == null ? '123456' : lvdao_name }}</p>

          <p>密码:{
   
   { lvdao_pwd == null ? '123456' : lvdao_pwd }}</p>

          <div style="text-align: center">

            <p>执照副本</p>

            <div><img style="width: 240px" :src="business" alt="" /></div>

            <!-- <div><img style="width: 240px" :src="business==''?'@/assets/logo.png':business" alt="" /></div> -->

          </div>

          <div style="text-align: center">

            <p>许可证</p>

            <div><img style="width: 240px" :src="certificates" alt="" /></div>

          </div>

        </a-modal>

      </a-col>

    </a-row>

  </page-header-wrapper>

</template>



<script>

let treeData = [

  {

    name: '五等份的花架',

    key: '五等份的花架',

    scopedSlots: { title: 'title1' }, //有此属性的都会被装上插槽名为title的插槽

    children: [

      {

        name: '只能选一个',

        key: '0-0-0',

        scopedSlots: { title: 'title' },

        children: [

          { name: '一花 13388888888', key: '一花 13388888888', scopedSlots: { title: 'title' } },

          { name: '二乃 13388888888', key: '二乃 13388888888', scopedSlots: { title: 'title' } },

          { name: '三玖 13388888888', key: '三玖 13388888888', scopedSlots: { title: 'title' } },

          { name: '四叶 13388888888', key: '四叶 13388888888', scopedSlots: { title: 'title' } },

          { name: '五月 13388888888', key: '五月 13388888888', scopedSlots: { title: 'title' } }

        ]

      }

    ]

  },

  {

    name: '我的青春物语果然有问题',

    key: '我的青春物语果然有问题',

    scopedSlots: { title: 'title1' },

    children: [

      {

        name: '大老师自爆',

        key: '1-0-0',

        scopedSlots: { title: 'title' },

        children: [

          { name: '雪乃 13388888888', key: '雪乃 13388888888', scopedSlots: { title: 'title' } },

          { name: '团子 13388888888', key: '团子 13388888888', scopedSlots: { title: 'title' } },

          { name: '一色 13388888888', key: '一色 13388888888', scopedSlots: { title: 'title' } },

          { name: '平冢静 13388888888', key: '平冢静 13388888888', scopedSlots: { title: 'title' } }

        ]

      }

    ]

  },

  {

    name: '青春猪头少年不可能梦见兔女郎学姐',

    key: '青春猪头少年不可能梦见兔女郎学姐',

    scopedSlots: { title: 'title1' },

    children: [

      {

        name: '麻衣姐姐天下第一',

        key: '2-0-0',

        scopedSlots: { title: 'title' },

        children: [

          { name: '李白 13388888888', key: '李白 13388888888', scopedSlots: { title: 'title' } },

          { name: '杜甫 13388888888', key: '杜甫 13388888888', scopedSlots: { title: 'title' } },

          { name: '王维 13388888888', key: '王维 13388888888', scopedSlots: { title: 'title' } },

          { name: '白居易 13388888888', key: '白居易 13388888888', scopedSlots: { title: 'title' } }

        ]

      }

    ]

  },

  {

    name: '路人女主养成计划',

    key: '路人女主养成计划',

    scopedSlots: { title: 'title1' },

    children: [

      {

        name: '授权子公司',

        key: '3-0-0',

        scopedSlots: { title: 'title' },

        children: [

          { name: '学姐 13444433888', key: '165156165', scopedSlots: { title: 'title' } },

          { name: '双马尾 13354648588', key: '89456541564', scopedSlots: { title: 'title' } },

          { name: '加藤惠 13123132288', key: '65465', scopedSlots: { title: 'title' } }

        ]

      }

    ]

  }

];

export default {

    data() {

      return {

        replaceFields:{title:'name'},

        expandedKeys: [],

        backupsExpandedKeys: [],

        autoExpandParent: false,

        checkedKeys: [],

        selectedKeys: [],

        searchValue: '',

        treeData,

        searchStr: ''

      };

    },

    methods: {

      onSearch(){

        var vm=this;

        //添加这行代码是为了只点击搜索才触发

        vm.searchValue = vm.searchStr;

        //如果搜索值为空,则不展开任何项,expandedKeys置为空

        //如果搜索值不位空,则expandedKeys的值要为搜索值的父亲及其所有祖先

        if(vm.searchValue === ''){

          vm.expandedKeys = [];

        }else{

          //首先将展开项与展开项副本置为空

          vm.expandedKeys = [];

          vm.backupsExpandedKeys = [];

          //获取所有存在searchValue的节点

          let candidateKeysList = vm.getkeyList(vm.searchValue,vm.treeData,[]);

          //遍历满足条件的所有节点

          candidateKeysList.map(

            item=>{

              //获取每个节点的母亲节点

              var key=vm.getParentKey(item,vm.treeData);

              //当item是最高一级,父key为undefined,将不放入到数组中

              //如果母亲已存在于数组中,也不放入到数组中

              if(key && !vm.backupsExpandedKeys.some(item=>item===key))

                vm.backupsExpandedKeys.push(key);

            }

          )

          let length=this.backupsExpandedKeys.length;

          for(let i=0;i<length;i++){

            vm.getAllParentKey(vm.backupsExpandedKeys[i],vm.treeData)

          }

          vm.expandedKeys = vm.backupsExpandedKeys.slice();

        }

      },

      //获取节点中含有value的所有key集合

      getkeyList(value,tree,keyList){

        //遍历所有同一级的树

        for(let i=0;i<tree.length;i++){

          let node = tree[i];

          //如果该节点存在value值则push

          if(node.name.indexOf(value)>-1){

            keyList.push(node.key);

          }

          //如果拥有孩子继续遍历

          if(node.children){

              this.getkeyList(value,node.children,keyList);

          }

        }

        //因为是引用类型,所有每次递归操作的都是同一个数组

        return keyList;

      },

      //该递归主要用于获取key的父亲节点的key值

      getParentKey(key,tree){

        let parentKey,temp;

        //遍历同级节点

        for(let i=0;i<tree.length;i++){

          const node=tree[i];

          if(node.children){

            //如果该节点的孩子中存在该key值,则该节点就是我们要找的父亲节点

            //如果不存在,继续遍历其子节点

            if(node.children.some(item=>item.key===key)){

              parentKey = node.key;

            }else if(temp=this.getParentKey(key,node.children)){

              //parentKey = this.getParentKey(key,node.children)

              //改进,避免二次遍历

              parentKey = temp;

            }

          }

        }

        return parentKey;

      },

      //获取该节点的所有祖先节点

      getAllParentKey(key,tree){

        var parentKey;

        if(key){

          //获得父亲节点

          parentKey = this.getParentKey(key,tree);

          if(parentKey){

            //如果父亲节点存在,判断是否已经存在于展开列表里,不存在就进行push

            if(!this.backupsExpandedKeys.some(item=>item===parentKey)){

              this.backupsExpandedKeys.push(parentKey);

            }

            //继续向上查找祖先节点

            this.getAllParentKey(parentKey,tree);

          }

        }

      },

      onExpand(expandedKeys) {

        //用户点击展开时,取消自动展开效果

        this.expandedKeys = expandedKeys;

        this.autoExpandParent = false;

      },

      onCheck(checkedKeys) {

        console.log('onCheck', checkedKeys);

        this.checkedKeys = checkedKeys;

      },

      onSelect(selectedKeys, info) {

        console.log('onSelect', info);

        this.selectedKeys = selectedKeys;

      },

    },

  };

</script>



<style lang="less" scoped>

::v-deep .ant-tree-node-content-wrapper {

  display: contents !important;

}

</style>

This demo can be used after copying it in the past, but sometimes the search cannot be launched after the network request is initiated and the data is processed. At this time, it is necessary to handle asynchronous operations when processing data. The following is my solution at that time

Among them, async and await are used to solve asynchrony

? In order to judge whether there are following parameters inside

? ? To execute subsequent code if the value is empty or null

async getComputeData() {
      //获取公司列表
     const res = await  this.$mApi.getNodeAction('/company/list', { pageSize: 100000, pageNo: 1 });
        this.companyList = res.result.data;
        // console.log('接口获取的公司列表', res.result.data);
        //将数组进行修改并push到 treeData 里面
        this.treeData = [];
        for (const element of res.result.data) {
          const { result = {} } = await this.$mApi.getNodeAction('/team/company', { id: element.id });
          if (!result.authCompanyList.length) {
              this.treeData.push({
                // name: element.name,
                name: element?.name ?? '暂时公司没名字' ,
                key: element.id,
                scopedSlots: { title: 'title1' }
              });
              // this.generateList(res.result.data); // 必须初始化树结构时执行,否则搜索结果不展开
            } else {
              //遍历子公司
              let childrenList = [];
              for (const item of result.authCompanyList) {
                childrenList.push({
                  name: item.realname || 'haha',
                  key: item.company_id,
                  scopedSlots: { title: 'title' }
                });
              }
              this.treeData.push({
                // name:element.name,
                name: element?.name ?? '暂时公司没名字' ,
                key: element.id,
                scopedSlots: { title: 'title1' },
                children: [
                  {
                    name: '授权子公司',
                    key: element.name + element.id,
                    scopedSlots: { title: 'title' },
                    children: childrenList
                  }
                ]
              });
        }
      }
    },

Show results

 

Guess you like

Origin blog.csdn.net/Sreadfast/article/details/127985906