树选择组件
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/4e5b14b3ae2143d08ac710d762610b21.png)
调用
<lsTreeSelect :show="showTreeSelect" :dataArray="tree" @close="showTreeSelect = false" v-model="selectItem">
</lsTreeSelect>
component
<template>
<uni-popup ref="lsDateSelect" type="bottom" border-radius="10px 10px 0 0" @maskClick="maskClick" @touchmove.stop>
<view class="container">
<view style="width: 100%;height: 100rpx;display: flex;flex-direction: row;justify-content: flex-end;">
<view class="closeBtn" @click="closeAction">关闭</view>
</view>
<view class="searchInputBack">
<input class="input" confirm-type="search" :value="searchText" @confirm="confirmInput"
@input="searchInput" placeholder="请输入检索关键字"> </input>
<view v-if="searchText.length > 0" class="clearArea" @click="clearBtnClick">
<image src="/static/images/close.png" class="clearIcon" mode="aspectFill"></image>
</view>
</view>
<view class="body">
<view v-if="!searchFlag" class="tabArea">
<scroll-view class="scroll-view_H" scroll-x="true" :scroll-into-view="tabScrollToIndex">
<view class="scroll-view-item_H" v-for="(item, index) in dataTabList">
<view class="tabContent" @click="tabItemClick(index)">
<view :id="`id_${index}`" v-if="index != dataTabList.length-1" class="tab">
{{item[props.label]}}
</view>
<view :id="`id_${index}`" v-else class="tabLast">
{{item[props.label]}}
</view>
<image v-if="index != dataTabList.length-1" src="/static/images/cell_arrow.png"
class="tabArrow" mode="aspectFill"></image>
</view>
</view>
</scroll-view>
</view>
<view v-if="!searchFlag" class="gap">
</view>
<scroll-view scroll-y="true" class="scroll-view_V">
<view v-if="!searchFlag" class="view">
<view class="viewBack">
<view class="item" v-for="(item, index) in dataList">
<image src="/static/images/org.png" class="orgImage" mode="aspectFill"></image>
<text class="orgName" :style="item.disabled?'color:#666666':'color:#333333'"
@click="dataItmeNameClick(item)">{{item[props.label]}}</text>
<view v-if="item[props.child] && item[props.child].length>0" class="arrowImage2"
@click="dataShowChildClick(item)">
<image src="/static/images/cell_arrow.png" class="arrowImage" mode="aspectFill">
</image>
</view>
</view>
</view>
</view>
<view v-else class="view">
<view class="viewBack" v-if="searchDefaultStr.includes(searchText)">
<view class="item" v-for="(item, index) in searchDataAry"
v-if="(item[props.label].includes(searchText))">
<image src="/static/images/org.png" class="orgImage" mode="aspectFill"></image>
<text class="orgName" :style="item.disabled?'color:#666666':'color:#333333'"
@click="dataItmeNameClick(item)">{{item[props.label]}}</text>
</view>
</view>
<view class="viewBack" v-else>
<view class="searchEmpty" style="padding-top: 30vh;">
未搜索到匹配的结果~
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</uni-popup>
</template>
<!-- 'common/arrow_right.png' -->
<script>
export default {
name: "lsTreeSelect",
props: {
value: {
type: String,
default: [],
},
show: {
type: Boolean,
default: false,
},
dataArray: {
type: Array,
default: []
},
props: {
type: Object,
default: {
label: 'dictLabel',
value: 'dictValue',
child: 'child'
}
}
},
data() {
return {
searchText: '',
dataTabList: [],
searchDefaultStr: '',
tabScrollToIndex: '',
dataList: [],
searchDataAry: [],
searchFlag: false
}
},
mounted() {},
watch: {
show: {
handler(v) {
if (v) {
this.dataTabList = []
this.dataList = this.dataArray
this.searchDataAry = this.searchTree(this.dataArray)
this.searchDataAry.forEach(item => {
this.searchDefaultStr += item[this.props.label]
})
this.$refs.lsDateSelect.open()
}
}
},
},
created() {
},
methods: {
closeAction() {
this.searchText = ''
this.searchFlag = false
this.dataTabList = []
this.$emit('close')
this.$refs.lsDateSelect.close()
},
bindChange: function(e) {
console.log(111, e.detail.value)
const val = e.detail.value
this.year = this.years[val[0]]
this.month = this.months[val[1]].toString().padStart(2, '0');
this.day = this.days[val[2]].toString().padStart(2, '0');
console.log(333, this.realValue)
this.$emit('input', this.year + '-' + this.month + '-' + this.day)
},
maskClick() {
this.closeAction()
},
dataItmeNameClick(item) {
if (item.disabled) {
return
}
this.$emit('input', item)
this.closeAction()
},
dataShowChildClick(item) {
this.dataList = item.child
this.dataTabList.push(item)
this.tabScrollToIndex = `id_${this.dataTabList.length -1}`
},
searchTree(tree, arr = []) {
tree.forEach(item => {
let temp = {
...item
}
temp.child = undefined
// 添加除了children的属性
arr.push(temp)
if (item.child) {
// 递归将所有节点加入到结果集中
this.searchTree(item.child, arr)
}
})
return arr
},
tabItemClick(index) {
this.dataTabList = this.dataTabList.slice(0, index + 1)
this.dataList = this.dataTabList[this.dataTabList.length - 1].child
},
confirmInput: function(event) {
this.searchFlag = true
},
searchInput(event) {
this.searchText = event.detail.value
},
clearBtnClick() {
this.searchText = ''
this.searchFlag = false
}
}
}
</script>
<style scoped lang="scss">
.container {
height: 90vh;
width: 100vw;
margin-left: 0rpx;
background-color: #F5F5F5;
border-top-right-radius: 24rpx;
border-top-left-radius: 24rpx;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
.closeBtn {
height:100rpx;
width: 96rpx;
// background-color: white;
font-size: 28rpx;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: 400;
text-align: center;
color: #666666;
line-height: 100rpx;
}
.searchInputBack {
width: 686rpx;
height: 90rpx;
background-color: white;
margin-top: 0rpx;
border-radius: 24rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
.input {
flex-grow: 1;
width: 620rpx;
margin-left: 16rpx;
height: 90rpx;
}
.clearArea {
width: 50rpx;
height: 90rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.clearIcon {
width: 30rpx;
height: 30rpx;
}
}
.searchResultView {
height: 90rpx;
border-radius: 24rpx;
background: white;
margin-left: 32rpx;
width: 686rpx;
margin-top: 10rpx;
overflow: hidden;
}
.body {
width: 686rpx;
height: 90rpx;
background-color: white;
margin-top: 10rpx;
border-radius: 24rpx;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
flex-grow: 1;
.gap {
width: 686rpx;
height: 16rpx;
background: #F5F5F5;
}
.scroll-view_V {
white-space: nowrap;
width: 686rpx;
height: 65vh;
.view {
width: 686rpx;
.viewBack {
width: 654rpx;
background-color: rgba(245, 245, 245, 1);
margin-left: 16rpx;
}
.searchEmpty {
width: 654rpx;
height: 100%;
font-size: 32rpx;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
text-align: center;
color: #999999;
line-height: 90rpx;
flex-grow: 1;
background-color: white;
}
}
.item {
height: 100rpx;
width: 654rpx;
background-color: white;
margin-bottom: 1rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
.raidoImage {
width: 30rpx;
height: 30rpx;
}
.orgImage {
width: 64rpx;
height: 64rpx;
}
.arrowImage2 {
width: 70rpx;
height: 100rpx;
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
.arrowImage {
width: 10rpx;
height: 20rpx;
margin-right: 16rpx;
}
}
.orgName {
height: 100rpx;
width: 424rpx;
font-size: 32rpx;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
text-align: left;
color: #333333;
line-height: 100rpx;
flex-grow: 1;
margin-left: 8rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
}
.tabArea {
height: 90rpx;
width: 622rpx;
padding: 0 32rpx;
}
.scroll-view_H {
white-space: nowrap;
width: 100%;
.scroll-view-item_H {
display: inline-block;
line-height: 300rpx;
text-align: center;
font-size: 36rpx;
.tabContent {
display: flex;
flex-direction: row;
justify-content: left;
align-items: center;
.tabArrow {
width: 10rpx;
height: 20rpx;
margin-left: 16rpx;
margin-right: 16rpx;
}
}
.tab {
height: 90rpx;
font-size: 30rpx;
max-width: 300rpx;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
text-align: center;
color: #0076ff;
line-height: 90rpx;
margin-left: 20rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.tabLast {
height: 90rpx;
font-size: 30rpx;
max-width: 300rpx;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: Regular;
text-align: left;
color: #666666;
line-height: 90rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
}
}
}
</style>