Uniapp树选择组件

树选择组件

在这里插入图片描述

调用

<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>
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值