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、效果图