vue+element ui树形下拉搜索组件

1、前台组件页

<template>
 <div class="search-item-box">
   <div class="scascader">
       <div class="sleft">科室名称:</div>
       <div class="sright">
        <el-select :value="valueTitle" :clearable="clearable" @clear="clearHandle">
            <el-input 
            class="selectInput"
            :placeholder="placeholder"
            v-model="filterText">
            </el-input>

            <el-option :value="valueId" :label="valueTitle" class="options">
            <el-tree  id="tree-option"
                ref="selectTree"
                :accordion="true"
                :data="options"
                :props="props"
                :node-key="props.value"    
                :default-expanded-keys="defaultExpandedKey"
                :filter-node-method="filterNode"
                @node-click="handleNodeClick">
            </el-tree>
            </el-option>
        </el-select>
       </div>
   </div>
 </div>
</template>

<script>
import sstring from './string'
export default {
  components: { sstring},
  name: "el-tree-select",
  props:{
    /* 配置项 */
    props:{
        // 配置项(必选)
        value: "id",
        label: "name",
        children: "children"
    },
    /* 选项列表数据(树形结构的对象数组) */
    options:{
      type: Array,       
      default: ()=>{ return [] }
    },
    /* 初始值 */
    value:{
      type: String,
      default: ()=>{ return null }
    },
    /* 可清空选项 */
    clearable:{
      type:Boolean,
      default:()=>{ return true }
    },
    /* 自动收起 */
    accordion:{
      type:Boolean,
      default:()=>{ return false }
    },
    placeholder:{
      type:String,
      default:()=>{return "检索关键字"}
    }
  },
  data() {
    return {
      filterText: '',
      valueId:this.value,    // 初始值
      valueTitle:'',
      defaultExpandedKey:[]    
    }
  },
  created(){
    this.initHandle()
  },
  methods: {
    // 初始化值
    initHandle(){
      this.initScroll()
    },
    // 初始化滚动条
    initScroll(){
      this.$nextTick(()=>{
        let scrollWrap = document.querySelectorAll('.el-scrollbar .el-select-dropdown__wrap')[0]
        let scrollBar = document.querySelectorAll('.el-scrollbar .el-scrollbar__bar')
        scrollWrap.style.cssText = 'margin: 0px; max-height: none; overflow: hidden;'
        scrollBar.forEach(ele => ele.style.width = 0)
      })
    },
    // 切换选项
    handleNodeClick(node){
      this.valueTitle = node.label
      this.valueId = node.value
      this.$emit('getValue',this.valueId)
      this.defaultExpandedKey = []
    },
    // 清除选中
    clearHandle(){
      this.valueTitle = ''
      this.valueId = null
      this.defaultExpandedKey = []
      this.clearSelected()
      this.$emit('getValue',null)
    },
    /* 清空选中样式 */
    clearSelected(){
      let allNode = document.querySelectorAll('#tree-option .el-tree-node')
      allNode.forEach((element)=>element.classList.remove('is-current'))
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    }
  },
  watch: {
    value(){
      this.valueId = this.value
      this.initHandle()
    },
    filterText(val) {
      this.$refs.selectTree.filter(val);
    }
  },
};
</script>

<style scoped>
  .el-scrollbar .el-scrollbar__view .el-select-dropdown__item{
    height: auto;
    max-height: 274px;
    padding: 0;
    overflow: hidden;
    overflow-y: auto;
  }
  .el-select-dropdown__item.selected{
    font-weight: normal;
  }
  ul li >>>.el-tree .el-tree-node__content{
    height:auto;
    padding: 0 20px;
  }
  .el-tree-node__label{
    font-weight: normal;
  }
  .el-tree >>>.is-current .el-tree-node__label{
    color: #409EFF;
    font-weight: 700;
  }
  .el-tree >>>.is-current .el-tree-node__children .el-tree-node__label{
    color:#606266;
    font-weight: normal;
  }
  .selectInput{
    padding: 0 5px;
    box-sizing: border-box;
  }
</style>

2、在模块中引用组件使用

<template>
  <div class="panel-search-filter push-down-20 cl-after search">
    <div class="search-item-container">
          <ksmcselect
            :props="propsforselect"
            :options="optionDatas"
            :clearable="true"
            :accordion="true"
            @getValue="getValue($event)"
            height="200"
          ></ksmcselect>
    
      <div class="search-btn-container search-item-box" style="float:right">
        <a class="btn btn-primary" @click="btnGetValue">检索</a>
        <a class="btn btn-link" style="margin-left:5px" @click="btnReset">重置</a>
      </div>
    </div>
  </div>
</template>
<script>


import ksmcselect from '@/views/ksgl/ksmcselect.vue'
import ksgl from '@/api/ksgl/ksgl'

import '@/assets/css/hk/hk-style.css'
import '@/assets/css/hk/swiper/swiper.min.css'

export default {
  components: { sstring,ksmcselect},
  data() {
    return {
         propsforselect : {},
         optionDatas: [],
         valueId : "" //选择的科室id
    }
  },
  watch: {
  },
  created() {
    //初始化科室信息树形结构数据
    this.optionData();
  },
  methods: {
    // 查询
    btnGetValue() {
      var para = {
        KSID: this.valueId,//选择的科室id
      }
    //参数传到父组件查询数据
      this.$emit('searchClickRecord', para)
    },
    optionData() {
        //初始化科室信息树形结构数据
          ksgl.getKsxxListForTree({}).then(ksxxdata => {
            this.optionDatas = []
            this.optionDatas = ksxxdata;
          })
    },
    // 重置
    btnReset() {
      for (var key in this.$refs) {
        this.$refs[key].reset()
      }
      this.tjsj =[]
      this.$emit('searchClickRecord',{})
    },
     // 取值
    getValue(value) {
      this.valueId = value;
      console.log(value)
    }
  }
}
</script>

<style>
.searchBox {
  display: none;
}
.search .userGrades {
  display: flex;
}
.search .userGrades .uleft {
  line-height: 30px;
  min-width: 30px;
  margin-right: 3px;
}
.search .userGrades .umiddle {
  display: flex;
  flex-wrap: wrap;
}
.search .userGrades .umiddle div {
  height: 30px;
  line-height: 28px;
  border-radius: 3px;
  border: 1px solid #dcdfe6;
  padding: 0px 25px;
  margin: 0 10px 15px 0px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  box-sizing: border-box;
}
.search .userGrades .umiddle .active {
  border-color: #5290d9;
  color: #5290d9;
}
.noSearchBox {
  display: block;
}
.panel-search-filter .search-btn-container {
  display: flex;
  max-width: 244px;
}

.scascader {
  display: flex;
}
.scascader .sleft {
  line-height: 30px;
}
.scascader .el-cascader {
  height: 30px;
  line-height: 30px;
}
.scascader .el-input__icon {
  line-height: 30px;
}
.sstring {
  display: flex;
}
.sleft {
  line-height: 30px;
  margin-right: 5px;
}
.sstring .el-select {
  width: 80px;
  margin-right: 3px;
}
.yearCss .el-input {
  width: 150px;
}

.yearCss .el-input--suffix .el-input__inner {
  padding-right: 20px;
}
.search-item-container .el-select .el-input .el-select__caret {
  font-size: 12px;
  color: #000 !important;
}
.facultyCss .el-input {
  width: 150px;
}
.smiddle .el-select .el-input__icon {
  line-height: 0;
}
.sright .el-input {
  width: 150px;
}
.sint {
  display: flex;
}
.sint .sleft {
  line-height: 30px;
}
.sint .el-select > .el-input {
  width: 100px;
  margin-right: 3px;
}
.sbool {
  display: flex;
}
.sbool .sright {
  line-height: 30px;
  margin-left: 10px;
}
.sdatetime {
  display: flex;
}
.sdatetime .el-date-editor--daterange {
  width: 260px;
  padding-right: 0;
}
.sdatetime .el-date-editor .el-range__close-icon {
  line-height: 25px;
}
.sdatetime .sright .el-date-editor .el-range__icon {
  line-height: 25px;
}
.sdatetime .sright .el-date-editor .el-range-separator {
  line-height: 23px;
  padding: 0 15px 0 0;
}
.moreBox {
  color: #409eff;
  height: 30px;
  line-height: 30px;
  font-size: 14px;
  width: 100px;
  text-align: center;
}
.moreBox span {
  display: inline-block;
  height: 100%;
}
.moreBox i {
  margin-left: 5px;
  font-size: 16px;
}
.moreBox span:hover {
  color: #f73131;
  cursor: pointer;
}

</style>

3、后台方法返回数据示例

 

 4、后台方法实现类

查出科室信息,将list转换为树形结构数据的JSONArray

/**
     * 获取科室信息树形结构数据
     *
     * @param map
     * @return
     */
    @Override
    public JSONArray getKsxxListForTree(Map<String, Object> map) {
        List<Map<String, Object>>  ssxylistall = new ArrayList<>();
        List<Map<String, Object>>  kslist = ksglmapper.getKsxxList(map);
        for (int i = 0; i < kslist.size(); i++) {
            Map<String, Object> temp= new HashMap<>();
            temp.put("id",kslist.get(i).get("SSXY"));
            temp.put("name",kslist.get(i).get("SSXY_NAME"));
            temp.put("parentId","0");
            temp.put("rank",Integer.parseInt(kslist.get(i).get("DEPT_SORT").toString()));
            temp.put("value",kslist.get(i).get("SSXY"));
            temp.put("label",kslist.get(i).get("SSXY_NAME"));
            ssxylistall.add(temp);
            String sssjks = PtpUtils.objToString(kslist.get(i).get("SSSJKS"));
            if("".equals(sssjks)){
                kslist.get(i).put("parentId",kslist.get(i).get("SSXY"));
            } else {
                kslist.get(i).put("parentId",sssjks);
            }
            kslist.get(i).put("value",kslist.get(i).get("RESOURCE_ID"));
            kslist.get(i).put("label",kslist.get(i).get("NAME"));
            kslist.get(i).put("name",kslist.get(i).get("NAME"));
        }
        //去重
        Set<Map<String, Object>> middleHashSet = new HashSet<Map<String, Object>>(ssxylistall);
        //去重之后的学院信息集合
        List<Map<String, Object>> ssxylist = new ArrayList<Map<String, Object>>(middleHashSet);
        //将学院作为科室信息放入科室list
        for (int i = 0; i < ssxylist.size(); i++) {
            kslist.add(ssxylist.get(i));
        }
        JSONArray result = listToTree(JSONArray.parseArray(JSON.toJSONString(kslist)),"id","parentId","children");
        return result;
    }


public static JSONArray listToTree(JSONArray arr, String id, String pid, String child) {
        JSONArray r = new JSONArray();
        JSONObject hash = new JSONObject();
        //将数组转为Object的形式,key为数组中的id
        for (int i = 0; i < arr.size(); i++) {
            JSONObject json = (JSONObject) arr.get(i);
            hash.put(json.getString(id), json);
        }
        //遍历结果集
        for (int j = 0; j < arr.size(); j++) {
            //单条记录
            JSONObject aVal = (JSONObject) arr.get(j);
            //在hash中取出key为单条记录中pid的值
            String pidStr = "";
            Object pidObj = aVal.get(pid);
            if (aVal.get(pid) != null) {
                pidStr = aVal.get(pid).toString();
            }
            JSONObject hashVP = (JSONObject) hash.get(pidStr);
            //如果记录的pid存在,则说明它有父节点,将她添加到孩子节点的集合中
            if (hashVP != null) {
                //检查是否有child属性
                if (hashVP.get(child) != null) {
                    JSONArray ch = (JSONArray) hashVP.get(child);
                    ch.add(aVal);
                    hashVP.put(child, ch);
                } else {
                    JSONArray ch = new JSONArray();
                    ch.add(aVal);
                    hashVP.put(child, ch);
                }
            } else {
                r.add(aVal);
            }
        }
        return r;
    }

 5、效果图

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值