Browse Source

筛选人员

renmy 3 months ago
parent
commit
6941d3a230

+ 383 - 0
components/search/SelectView.vue

@@ -0,0 +1,383 @@
+<template>
+	<view class='layout-column'>
+		<view id="parent" style="width:100%;">
+			<slot></slot>
+		</view>
+		<view
+			:style="'width:100%;max-height: 560rpx;z-index: 9999;position: absolute;right: 0;margin-top:'+slotH+';'+(isShow ? '' : 'display:none;')+
+			'; background: #e5f8ff;box-shadow: 0px 2px 6px 1px rgba(0,0,0,0.16);padding-bottom: 30rpx;' "
+			:class="(dataList.length > 0 ? 'data-box-shadow ' : 'data-box ') + animate">
+			
+			<block v-if="dataList.length > 0">
+				<view class="data-box-scroll"
+					:style="'max-height: 500rpx;'">
+					<text v-for="(item,index) in dataList" :key="item[identifier]"
+						:class="'layout-row less-center list-item '+(item.enable === false ? '' : 'active')"
+						:style="'color:'+(item.enable === false ? '#dedede' : (checkedIndex.indexOf(index) >= 0 ? itemSelectColor : itemColor))+';font-size:'+itemFontsize+'rpx;text-align: center;'"
+						@click="handleListItem(index, item)">{{item.nickName}}</text>
+				</view>
+				<view class="layout-row opera-btns less-center" v-if="mode == 'multiple'">
+					<view class="opera-cancel layout-row center" @click='handelCancel'>取消</view>
+					<view class="opera-sure layout-row center" @click='handelSure'>确定</view>
+				</view>
+			</block>
+			<view v-else :style="'width:'+slotW+';'" class='status-text'>暂无数据</view>
+		</view>
+		<view class="mask" v-show="isShow" @click="handelCancel"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "down-select",
+		props: {
+			//要显示的字段
+			showKey: {
+				type: String,
+				default: '',
+			},
+			mode: {
+				type: String,
+				default: 'single', //multiple
+				// default: 'multiple'
+			},
+			dataList: {
+				type: Array,
+				default: []
+			},
+			//选中的列表,用作显示列表是展示已选中项
+			checkedDataList: {
+				type: Array,
+				default: []
+			},
+			//最多展示几项后开始滑动
+			max: {
+				type: Number,
+				default: 4
+			},
+			//数据项每个item高度rpx
+			itemHeight: {
+				type: Number,
+				default: 80
+			},
+			//唯一标识符字段,用来比对选中项和维持v-for列表中的key,不填此项无选中效果
+			identifier: {
+				type: String,
+				default: ''
+			},
+			itemSelectColor: {
+				type: String,
+				default: '#00aaff'
+			},
+			itemColor: {
+				type: String,
+				default: 'black'
+			},
+			itemFontsize: {
+				type: Number,
+				default: 30
+			}
+		},
+		computed: {
+			getListContentHei() {
+				let len = this.dataList.length
+				let signleH = len < this.max ? this.itemHeight * len : this.itemHeight * this.max
+				if (this.mode == 'single') {
+					return len <= 0 ? this.itemHeight : signleH
+				} else {
+					return len <= 0 ? this.itemHeight : (signleH + this.itemHeight)
+				}
+			}
+		},
+		watch: {
+			dataList: {
+				handler: function(newVal, oldVal) {
+					if (this.checkedDataList.length >= 0 && this.identifier) {
+						this.checkedIndex = []
+						this.checkedDataList.forEach(ele => {
+							let index = newVal.findIndex(ele1 => ele[this.identifier] === ele1[this
+								.identifier])
+							if (index >= 0) {
+								this.checkedIndex.push(index)
+							}
+						})
+					}
+				},
+				immediate: true, // 组件创建时立即触发
+				deep: true // 对象内部属性变化时也触发
+			},
+			checkedDataList: {
+				handler: function(newVal, oldVal) {
+					if (newVal.length >= 0 && this.identifier) {
+						this.checkedIndex = []
+						newVal.forEach(ele => {
+							let index = this.dataList.findIndex(ele1 => ele[this.identifier] === ele1[this
+								.identifier])
+							if (index >= 0) {
+								this.checkedIndex.push(index)
+							}
+						})
+					}
+				},
+				immediate: true, // 组件创建时立即触发
+				deep: true // 对象内部属性变化时也触发
+			}
+		},
+		mounted() {
+			this.$nextTick(() => {
+				uni.createSelectorQuery().in(this).select('#parent').boundingClientRect(res => {
+					if (res.width) {
+						this.slotW = `${res.width}px`
+						this.slotH = `${res.height+5}px`
+					}
+				}).exec()
+			})
+		},
+		data() {
+			return {
+				slotW: '0px',
+				slotH: '0px',
+				isShow: false,
+				checkedIndex: [],
+				animate: '',
+				//传进来选中项,后又改成未选中并确认,多选模式生效
+				checkedDels: []
+			};
+		},
+		methods: {
+			open() {
+				if (this.checkedDataList.length >= 0 && this.identifier) {
+					this.checkedIndex = []
+					this.checkedDataList.forEach(ele => {
+						let index = this.dataList.findIndex(ele1 => ele[this.identifier] === ele1[this
+							.identifier])
+						if (index >= 0) {
+							this.checkedIndex.push(index)
+						}
+					})
+				}
+				this.isShow = true
+				this.animate = 'show-animate'
+			},
+			close() {
+				this.animate = 'hide-animate'
+				this.checkedIndex = []
+				this.checkedDels = []
+				this.isShow = false
+			},
+			handleListItem(index, obj) {
+				// if(obj.enable === false){
+				// 	return
+				// }
+				if (this.mode === 'single') {
+					this.checkedIndex = []
+					this.checkedIndex.push(index)
+					this.handelSure()
+				} else {
+					let sindex = this.checkedIndex.indexOf(index)
+					if (sindex >= 0) {
+						if (this.identifier) {
+							//判断未选中的项在传进来的已选项中是否存在
+							let contain = this.checkedDataList.filter(ele => ele[this.identifier] === this.dataList[index][
+								this.identifier
+							])
+							if (contain.length > 0) {
+								//传进来的已选项中是否存在选择为未选中的内容
+								let contain1 = this.checkedDels.filter(ele => ele[this.identifier] === contain[0][this
+									.identifier
+								])
+								if (contain1.length <= 0) {
+									this.checkedDels.push(contain[0])
+								}
+							}
+						}
+						this.checkedIndex.splice(sindex, 1);
+					} else {
+						if (this.identifier) {
+							let contain2 = this.checkedDels.filter(ele => ele[this.identifier] === this.dataList[index][
+								this.identifier
+							])
+							if (contain2.length > 0) {
+								let tempIndex = this.checkedDels.findIndex(ele => ele[this.identifier] === this.dataList[
+									index][this.identifier])
+								if (tempIndex >= 0) {
+									this.checkedDels.splice(tempIndex, 1)
+								}
+							}
+						}
+						this.checkedIndex.push(index)
+					}
+				}
+			},
+			handelCancel() {
+				this.close()
+				this.$emit('cancelDimss', '')
+			},
+			handelSure() {
+				let results = []
+				if (this.checkedIndex.length <= 0) {
+					uni.showToast({
+						title: '请选择至少一项',
+						icon: 'none'
+					});
+					return
+				}
+
+				this.checkedIndex.forEach(ele => {
+					if (this.dataList[ele]) {
+						results.push(this.dataList[ele])
+					}
+				})
+				//将本次选中结果清除
+				this.checkedIndex = []
+				this.$emit('resultBack', results, this.checkedDels)
+				this.close()
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.active {}
+
+	.active:active {
+		opacity: 0.6;
+	}
+
+	.layout-row {
+		display: flex;
+		flex-direction: row;
+	}
+
+	.layout-column {
+		display: flex;
+		flex-direction: column;
+	}
+
+	/* 整体方向居中 */
+	.center {
+		align-items: center;
+		justify-content: center;
+	}
+
+	/* 主轴方向居中 */
+	.main-center {
+		justify-content: center;
+	}
+
+	/* 侧轴方向居中 */
+	.less-center {
+		align-items: center;
+	}
+
+	.data-box-scroll {
+		width: 100%;
+		overflow-y: scroll;
+	}
+
+	.data-box-scroll::-webkit-scrollbar {
+		display: none
+	}
+
+	.data-box {
+		background: white;
+		border-radius: 8rpx;
+		box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
+		z-index: 9999;
+	}
+
+	.data-box-shadow {
+		background: white;
+		border-radius: 8rpx;
+		box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
+		z-index: 9999;
+	}
+
+	.list-item {
+		width: 100%;
+		height: 80rpx;
+		margin-left: 20rpx;
+		margin-right: 20rpx;
+		border-bottom: 1rpx solid #D8DFEC;
+		text-align: right;
+	}
+
+	.opera-btns {
+		width: 100%;
+		height: 80rpx;
+		justify-content: flex-end;
+	}
+
+	.opera-cancel {
+		width: 100rpx;
+		height: 50rpx;
+		background-color: white;
+		box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
+		border-radius: 5rpx;
+		font-size: 26rpx;
+	}
+
+	.opera-sure {
+		width: 100rpx;
+		height: 50rpx;
+		background-color: #58a2e4;
+		box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
+		border-radius: 5rpx;
+		font-size: 26rpx;
+		color: white;
+		margin-right: 30rpx;
+		margin-left: 30rpx;
+	}
+
+	.status-text {
+		text-align: center;
+		font-size: 28rpx;
+		font-weight: 600;
+		color: #c2c2c2;
+		padding-top: 20rpx;
+		padding-bottom: 20rpx;
+	}
+
+	.mask {
+		position: fixed;
+		background: transparent;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		z-index: 1;
+	}
+
+	.show-animate {
+		animation-name: open;
+		animation-duration: 1s;
+		animation-iteration-count: 1;
+	}
+
+	@keyframes open {
+		0% {
+			height: 0rpx;
+		}
+
+		100% {
+			height: 100%;
+		}
+	}
+
+	.hide-animate {
+		animation-name: close;
+		animation-duration: 1s;
+		animation-iteration-count: 1;
+		animation-fill-mode: forwards;
+	}
+
+	@keyframes close {
+		0% {
+			height: 100%;
+		}
+
+		100% {
+			height: 0rpx;
+		}
+	}
+</style>

+ 254 - 0
components/search/formSelect.vue

@@ -0,0 +1,254 @@
+<template>
+	<view class="form-select">
+		<view class="uni_select">
+			<view class="uni_select_input_box" @click="toggleSelector">
+				<view v-if="!current" class="uni_select_input_text_tips" :class="disabled?'_disabled':''">{{placeholder}}</view>
+				<view v-if="current" class="uni_select_input_text" :class="disabled?'_disabled':''">{{current}}</view>
+				<view v-if="icon" class="iconfont" :class="showSelector ? 'icon-to-up'+(disabled?' _disabled':'') : 'icon-to-down'+(disabled?' _disabled':'')"></view>
+			</view>
+			<view class="uni_select_mask" v-if="showSelector" @click="toggleSelector" />
+			<view class="uni_select_selector" v-if="showSelector" :style="selectStyle">
+				<scroll-view scroll-y="true" class="uni_select_selector_scroll">
+					<view style="height: 4px;"></view>
+					<view class="uni_select_selector_empty" v-if="localdata.length === 0">
+						<view class="select-text" style="word-break: break-all;font-size:12px;">{{emptyTips}}</view>
+					</view>
+					<view v-else class="uni_select_selector_item" :class="item.userId == selectedId ? '_selected' : (item.disabled?'_disabled':'')" v-for="(item,index) in localdata"
+						:key="index" @click="change(item)">
+						<view class="select-text" style="word-break: break-all;">{{item.nickName}}</view>
+						<view v-if="item.icon" :class="item.icon" :style="item.color?'color:'+item.color:''"></view>
+					</view>
+					<view style="height: 4px;"></view>
+				</scroll-view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * DataChecklist 数据选择器
+	 * @description 通过数据渲染的下拉框组件
+	 * @property {Array} localdata 本地数据 ,格式 [{id:'',title:''}]
+	 * @property {String, Number} selectedId 默认选项id
+	 * @property {String} placeholder 表单placeholder
+	 * @property {String} emptyText 没有数据时显示的文字 ,本地数据无效
+	 * @property {Boolean} icon 是否显示下拉图标
+	 * @property {Boolean} disabled 是否禁止选择
+	 * @property {String, Number} tag 标签,对于一个页面同时使用多次该组件时,并且选择后的回调为相同的函数时,可使用该标签进行区分
+	 * @event {Function} change  选中发生变化触发
+	 */
+	export default {
+		name:"formSelect",
+		props: {
+			localdata: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			selectedId: {
+				type: [String, Number],
+				default: ''
+			},
+			placeholder: {
+				type: String,
+				default: '请选择'
+			},
+			emptyTips: {
+				type: String,
+				default: '没有更多选项了'
+			},
+			icon: {
+				type: Boolean,
+				default: false
+			},
+			disabled:{
+				type: Boolean,
+				default: false
+			},
+			tag: {
+				type: [String, Number],
+				default: ''
+			},
+		},
+		data() {
+			return {
+				current:'',
+				showSelector:false,
+				selectStyle:'',
+				maxHeight:288,
+			};
+		},
+		mounted(){
+			this.update();
+			this.$nextTick(() => {
+				this.setPosition();
+			});
+		},
+		methods:{
+			setPosition() {
+				let that = this;
+				if(this.$props.localdata.length < 8){
+					if(this.$props.localdata.length > 0){
+						this.maxHeight = (this.$props.localdata.length*36)+10;
+					}
+				}
+				const query = uni.createSelectorQuery().in(this);
+				query.select('.uni_select_input_box').boundingClientRect(data => {
+					if (data) {
+					  // 获取当前窗口的高度
+					  const windowHeight = uni.getSystemInfoSync().windowHeight;
+					  // 元素顶部到窗口顶部的距离
+					  const elementTop = data.top;
+					  // 元素的高度
+					  const elementHeight = data.height;
+					  // 元素距离底部的位置 = 窗口高度 - 元素顶部距离窗口顶部距离 - 元素高度
+					  const bottomPosition = windowHeight - elementTop - elementHeight;
+					  if(bottomPosition < that.maxHeight){
+						  that.selectStyle = "bottom:"+(elementHeight + 4)+"px;top:auto;max-height:"+that.maxHeight+"px;";
+					  }else{
+						  that.selectStyle = "bottom:auto;top:calc(100% + 4px);max-height:"+that.maxHeight+"px;";
+					  }
+					}
+				  }).exec();
+			},
+			update(){
+				this.$data.current = '';
+				if(this.$props.selectedId !== ''){
+					for(var i in this.$props.localdata){
+						if(this.$props.localdata[i].userId == this.$props.selectedId){
+							this.$data.current = this.$props.localdata[i].nickName;
+						}
+					}
+				}
+			},
+			toggleSelector() {
+				if(!this.disabled){
+					let that = this;
+					this.setPosition();
+					setTimeout(function(){
+						that.showSelector = !that.showSelector
+					},20);
+				}
+			},
+			change(item){
+				if(!item.disabled){
+					this.$data.current = item.nickName;
+					item.tag = this.$props.tag;
+					this.$emit('change',item);
+					this.showSelector = false;
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+	@import "./iconfont/iconfont.css";
+	.form-select{
+		display: flex;
+		justify-content: flex-end;
+		align-items: center;
+		width:100%;
+		cursor: pointer;
+	}
+	.uni_select {
+		font-size: 14px;
+		box-sizing: border-box;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		user-select: none;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: space-between;
+		width:100%;
+		padding:0 12px;
+	}
+	.uni_select_input_box{
+		width: 100%;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+	}
+	.uni_select_mask {
+		position: fixed;
+		top: 0;
+		bottom: 0;
+		right: 0;
+		left: 0;
+	}
+	.uni_select_selector {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+		position: absolute;
+		left: 0;
+		width: 100%;
+		background-color: #FFFFFF;
+		border: 0.5px solid #DFE7E1;
+		border-radius: 4px;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+		z-index: 2;
+		overflow: hidden;
+	}
+	.uni_select_input_text_tips{
+		overflow: hidden;
+		height:40px;
+		line-height: 40px;
+		color:#7d7a7a;
+	}
+	.uni_select_input_text{
+		height:40px;
+		line-height: 40px;
+		overflow: hidden;
+		color:black;
+	}
+	.uni_select_selector_scroll {
+		/* #ifndef APP-NVUE */
+		max-height: 288px;
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	.uni_select_selector_empty,
+	.uni_select_selector_item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		cursor: pointer;
+		/* #endif */
+		line-height: 36px;
+		
+		font-size: 14px;
+		text-align: center;
+		/* border-bottom: solid 1px #DDDDDD; */
+		padding: 0px 10px;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+	}
+	.select-text{
+		line-height: 36px;
+		height: 36px;
+		word-break: break-all;
+		overflow: hidden;
+	}
+	.uni_select_selector_item_this {
+		background-color: rgb(21, 197, 206);
+	}
+
+	.uni_select_selector_empty:last-child,
+	.uni_select_selector_item:last-child {
+		/* #ifndef APP-NVUE */
+		border-bottom: none;
+		/* #endif */
+	}
+	._selected{
+		background-color: #e6e6e6;
+	}
+	._disabled{
+		color:#c7c4c4;
+	}
+</style>

+ 85 - 0
components/search/iconfont/iconfont.css

@@ -0,0 +1,85 @@
+@font-face {
+  font-family: "iconfont";
+  src: url('~@/components/search/iconfont/iconfont.ttf');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-bianji:before {
+  content: "\e63b";
+}
+
+.icon-suoding:before {
+  content: "\e7cb";
+}
+
+.icon-yijiesuo:before {
+  content: "\e615";
+}
+
+.icon-collect:before {
+  content: "\e60b";
+}
+
+.icon-hot:before {
+  content: "\e604";
+}
+
+.icon-star:before {
+  content: "\e661";
+}
+
+.icon-warn:before {
+  content: "\e62b";
+}
+
+.icon-close:before {
+  content: "\e639";
+}
+
+.icon-to-left:before {
+  content: "\e6f1";
+}
+
+.icon-to-right:before {
+  content: "\e9cc";
+}
+
+.icon-to-up:before {
+  content: "\e81b";
+}
+
+.icon-nor-select:before {
+  content: "\e633";
+}
+
+.icon-add:before {
+  content: "\e6ab";
+}
+
+.icon-to-down:before {
+  content: "\e77b";
+}
+
+.icon-select:before {
+  content: "\e76b";
+}
+
+.icon-lower:before {
+  content: "\e9cb";
+}
+
+.icon-right:before {
+  content: "\e60a";
+}
+
+.icon-error:before {
+  content: "\e698";
+}
+

BIN
components/search/iconfont/iconfont.ttf


+ 22 - 2
pages/index/orderDetail.vue

@@ -118,8 +118,8 @@
 								v-model="form.statusText" @click="dealSelectShow = true" />
 						</u-form-item>
 						<u-form-item label="*处理人员" prop="nextPerson" v-if="form.status == 3">
-							<u-input type="select" :select-open="showPerson" placeholder="请选择处理人员"
-								v-model="form.nextPerson" @click="showPerson = true" />
+							<qiaoSelect :dataList="personSelectList" phText="请选择处理人员" phColor="#999999" showField="nickName" searchKey="nickName"
+								:showBorder="false" :disabled="false" @change="selectChange" @input='inputChange'></qiaoSelect>
 						</u-form-item>
 						<u-form-item label="*处理记录" prop="info" :label-position="'top'">
 							<u-input type="textarea" placeholder="请输入问题记录 不超过200个字" :maxlength="200"
@@ -189,7 +189,9 @@
 </template>
 
 <script>
+	import qiaoSelect from '@/uni_modules/qiao-select/components/qiao-select/qiaoSelect.vue'
 	export default {
+		components: {qiaoSelect},
 		data() {
 			return {
 				//当前选中下标
@@ -268,6 +270,18 @@
 			this.getDetailData();
 		},
 		methods: {
+			selectChange(item) {//返回选择的对象,如果输入框清空,返回null
+				if(item) {
+					this.form.nextPerson = item.nickName
+					this.form.nextId = item.userId
+				} else {
+					this.form.nextPerson = null
+					this.form.nextId = null
+				}
+			},
+			inputChange(e) {//返回搜索结果集合,一般用不到
+				
+			},
 			//tab选择
 			tabHandle(type) {
 				this.currIndex = type;
@@ -492,6 +506,12 @@
 					if (form.img && form.img.length > 0) {
 						form.attachment = form.img.join(',')
 					}
+					if(!form.nextId && form.status == 3) {
+						return uni.showToast({
+							title: "请选择处理人员",
+							icon: "none"
+						})
+					}
 					_that.$http.orderDeal(_that.form).then(res => {
 						_that.isClick = false;
 						if (res.code == 200) {

+ 60 - 8
pages/index/orderUp.vue

@@ -25,9 +25,9 @@
 					<u-input type="select" :select-open="show" placeholder="请选择发生时间" v-model="form.occurrenceTime"
 						@click="show = true" />
 				</u-form-item>
-				<u-form-item label="处理人员">
-					<u-input type="select" :select-open="showPerson" placeholder="请选择处理人员" v-model="form.nextPerson"
-						@click="personHandle" />
+				<u-form-item label="处理人员">
+					<qiaoSelect :dataList="personSelectList" phText="请选择处理人员" phColor="#999999" showField="nickName" searchKey="nickName" 
+					:showBorder="false" :disabled="false" @change="selectChange" @input='inputChange'></qiaoSelect>
 				</u-form-item>
 				<u-form-item label="*问题描述" prop="problemTitle" :label-position="'top'">
 					<u-input placeholder="请输入问题描述 不超过15个字" :maxlength="15" v-model="form.problemTitle" />
@@ -66,8 +66,11 @@
 	</view>
 </template>
 
-<script>
-	export default {
+<script>
+	import downSelect from "@/components/search/SelectView"
+	import qiaoSelect from '@/uni_modules/qiao-select/components/qiao-select/qiaoSelect.vue'
+	export default {
+		components: {downSelect, qiaoSelect},
 		data() {
 			return {
 				//表单对象
@@ -169,7 +172,9 @@
 				//是否显示设备名称弹窗
 				nameSelectShow: false,
 				//设备名称列表
-				nameSelectList: [],
+				nameSelectList: [],
+				//检索完陈用户列表
+				userList: [],
 			}
 		},
 		computed: {
@@ -198,7 +203,51 @@
 			this.getDictTypeData();
 			this.getlevelListData();
 		},
-		methods: {
+		methods: {
+			selectChange(item) {//返回选择的对象,如果输入框清空,返回null
+				if(item) {
+					this.form.nextPerson = item.nickName
+					this.form.nextId = item.userId
+				} else {
+					this.form.nextPerson = null
+					this.form.nextId = null
+				}
+			},
+			inputChange(e) {//返回搜索结果集合,一般用不到
+				
+			},
+			handleInputHandle(val) {
+				if(!val) {
+					this.userList = this.personSelectList
+				} else {
+					this.userList = [];
+					let list = this.personSelectList
+					list.forEach(item => {
+						if(item.nickName.indexOf(val) > -1) {
+							this.userList.push(item)
+						}
+					})
+				}
+			},
+			outHandle() {
+				// this.$refs.selectRef4.close()
+			},
+			handleInput(e){
+				if (!this.form.stationCode) {
+					return uni.showToast({
+						title: '请先选择站点',
+						icon: 'none',
+					})
+				}
+				this.$refs.selectRef4.open()
+				this.userList = this.personSelectList
+			},
+			result4(result){
+				let item = result[0]
+				this.form.nextPerson = item.nickName
+				this.form.nextId = item.userId
+				this.$refs.selectRef4.close()
+			},
 			//获取站点列表
 			getSites() {
 				this.datalist = [];
@@ -310,7 +359,10 @@
 				let form = _that.form;
 				if (form.img && form.img.length > 0) {
 					form.attachment = form.img.join(',')
-				}
+				}
+				if(!form.nextId) {
+					form.nextPerson = null
+				}
 				_that.$refs.uform.validate(valid => {
 					if (!valid) {
 						_that.isClick = false;

+ 22 - 0
uni_modules/qiao-select/changelog.md

@@ -0,0 +1,22 @@
+## 1.0.8(2023-12-26)
+修改h5端样式报错
+## 1.0.7(2023-07-04)
+优化宽度太窄的时候显示效果;
+## 1.0.6(2023-06-16)
+优化;
+## 1.0.5(2023-06-16)
+新增支持禁用;
+## 1.0.4(2023-06-16)
+优化;
+## 1.0.3(2023-06-15)
+1、可设置展示字段;
+2、可设置默认值;
+## 1.0.0(2023-06-15)
+1、可设置默认值;
+2、可设置展示字段;
+## 1.0.2(2023-06-15)
+优化
+## 1.0.1(2023-06-15)
+修改问题;
+## 1.0.0(2023-06-15)
+初版提交

+ 315 - 0
uni_modules/qiao-select/components/qiao-select/qiaoSelect.vue

@@ -0,0 +1,315 @@
+<template>
+	<view class="qiaoSelect" :class="{'ban':disabled}">
+		<input type="text" class="input" :class="{'input-border':showBorder}" @input="watchInput" @focus="focus"
+			@blur="blur" :placeholder="phText" :placeholder-style="'color:'+phColor" @tap="open" 
+			v-model="inputText" />
+		<view class="icon">
+			<uni-icons type="close" size="20" color="#515151" class="img-close" @click="clickClear"
+				v-if="inputText!==''&&!disabled"></uni-icons>
+			<!-- <uni-icons v-show="popupShow" type="bottom" size="15" color="#515151"></uni-icons>
+			<uni-icons v-show="!popupShow" type="right" size="15" color="#515151"></uni-icons> -->
+		</view>
+		<view class="select" v-show="popupShow">
+			<view class="box">
+				<view style="color: #515151;font-size: 30rpx;text-align: center;" v-if="dataList.length==0">暂无数据</view>
+				<view style="color: #515151;font-size: 30rpx;text-align: center;" v-if="filPersons.length==0&&dataList.length!=0">
+					暂无数据
+				</view>
+				<view @touchstart="touchst" v-for="(item,index) in filPersons" :key="index">
+					<view @click.stop="Check(item)" style="text-align: left;" class="li"
+						:class="item.qiaoSelectKey==inputText?'blue':''">
+						{{item[showField]}}
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="popup" v-show="popupShow" @click="close">
+			<view>
+
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			//下拉数据
+			dataList: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			//唯一键,用于多个关闭
+			keyId: Number | String,
+			//提示语
+			phText: String,
+			//提示语颜色
+			phColor: {
+				type: String,
+				default: '#999999',
+			},
+			//指定搜索的属性
+			searchKey: {
+				type: String,
+				default: 'name'
+			},
+			//是否显示边框
+			showBorder: {
+				type: Boolean,
+				default: true,
+			},
+			//默认显示的条目
+			showObj: {
+				type: Object,
+				default: null,
+			},
+			//展示的字段
+			showField: {
+				type: String,
+				default: 'name'
+			},
+			//是否禁用
+			disabled: {
+				type: Boolean,
+				default: false,
+			},
+		},
+		data() {
+			return {
+				timer: '', //定时器
+				popupShow: false,
+				inputText: '',
+				isInput: true, //是否输入,如果输入开始模糊查询
+			}
+		},
+		onLoad() {},
+		computed: {
+			filPersons: {
+				get() {
+					if (!this.isInput) {
+						return this.dataList
+					} else {
+						return this.dataList.filter((item) => {
+							if (item.qiaoSelectKey) {
+								return item.qiaoSelectKey.indexOf(this.inputText) != -1
+							} else {
+								return []
+							}
+						})
+					}
+				},
+				set(val) {}
+			}
+
+		},
+		watch: {
+			inputText: {
+				immediate: true,
+				handler(val) {
+					this.filPersons = this.dataList.filter((item) => {
+						if (!item.qiaoSelectKey) return
+						return item.qiaoSelectKey.indexOf(val) != -1
+					})
+				}
+			},
+			dataList: {
+				immediate: true,
+				handler(val) {
+					if (this.dataList.length > 0) {
+						this.dataList.forEach(item => {
+							Object.keys(item).map((key) => {
+								if (item[this.searchKey]) {
+									item.qiaoSelectKey = item[this.searchKey].toString()
+								} else if (item[this.showField]) { //没有指定搜索字段,默认搜索展示字段
+									item.qiaoSelectKey = item[this.showField].toString()
+								}
+							})
+						})
+						this.inputText = ''
+					}
+				}
+			},
+			//监听赋值
+			showObj: {
+				handler(val) {
+					if (val) {
+						this.inputText = val[this.showField]
+						this.$emit('input', [val])
+						this.$emit('change', val)
+					} else {
+						this.inputText = ''
+						this.$emit('input', [])
+						this.$emit('change', null)
+					}
+				},
+				deep: true,
+				immediate: true,
+			},
+		},
+		methods: {
+			clickClear() {
+				this.inputText = ''
+				this.$emit('input', [])
+				this.$emit('change', null)
+			},
+			touchst() {
+				if (this.disabled) return;
+				this.popupShow = true
+			},
+			focus() {
+				this.isInput = false
+			},
+			watchInput(e) { //键盘输入
+				this.isInput = true
+				if (this.inputText) {
+					this.$emit('input', this.filPersons)
+				}
+				if (this.inputText === '') {
+					this.$emit('input', [])
+					this.$emit('change', null)
+				}
+			},
+			Check(i) { //选择选项
+				this.inputText = i[this.showField]
+				this.isInput = false
+				this.close()
+				this.$emit('change', i)
+			},
+			open() {
+				if (this.disabled) return;
+				uni.setStorageSync('keyId', this.keyId)
+				this.popupShow = true
+			},
+			close() { //关闭
+				this.popupShow = false
+			},
+			blur() {
+				this.timer = setInterval(() => {
+					if (this.popupShow && uni.getStorageSync('keyId') != this.keyId) {
+						this.popupShow = false
+					}
+					setTimeout(() => {
+						clearInterval(this.timer)
+					}, 100)
+				}, 200)
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	$height: 60rpx;
+
+	.ban {
+		background: #F7F7F6;
+	}
+
+	.qiaoSelect {
+		margin: 0;
+		padding: 0;
+		position: relative;
+		height: $height;
+		display: flex;
+		align-items: center;
+
+		.img-close {
+			margin: 0 10rpx;
+		}
+
+		.icon {
+			z-index: 99;
+		}
+
+		.input {
+			flex: 1;
+			border-radius: 10rpx;
+			height: $height;
+			padding: 0;
+			font-size: 30rpx;
+			word-break: break-all;
+			text-overflow: ellipsis;
+			display: -webkit-box;
+			-webkit-box-orient: vertical;
+			-webkit-line-clamp: 1;
+			overflow: hidden;
+		}
+
+		.input-border {
+			border: 1rpx solid #ECECEC;
+			padding-left: 20rpx;
+		}
+
+		.select {
+			padding: 20rpx;
+			color: #515151;
+			position: absolute;
+			top: 90rpx;
+			left: 0;
+			right: 0;
+			z-index: 100;
+			background-color: white;
+			border: 2px #f3f3f3 solid;
+			font-size: 30rpx;
+			background-color: #fff;
+			border-radius: 10rpx;
+
+			.box {
+				max-height: 300rpx;
+				overflow: scroll;
+			}
+
+			.li {
+				padding: 10rpx 0;
+			}
+
+			.blue {
+				color: #55aaff;
+			}
+		}
+
+		.select::after {
+			width: 0px;
+			height: 0px;
+			position: absolute;
+			bottom: 100%;
+			left: 10%;
+			padding: 0;
+			border: 16rpx solid transparent;
+			border-color: transparent transparent #fff transparent;
+			content: '';
+		}
+
+		.select::before {
+			width: 0px;
+			height: 0px;
+			position: absolute;
+			bottom: 100%;
+			left: 10%;
+			padding: 0;
+			border: 20rpx solid transparent;
+			border-color: transparent transparent #f3f3f3 transparent;
+			transform: translate(-4rpx, 0);
+			content: '';
+		}
+
+		.popup {
+			position: absolute;
+			z-index: 9;
+			left: 0;
+			top: 0;
+			right: 0;
+			bottom: 0;
+
+			view {
+				position: fixed;
+				left: 0;
+				top: 0;
+				right: 0;
+				bottom: 0;
+			}
+		}
+
+	}
+</style>

+ 66 - 0
uni_modules/qiao-select/introduce.md

@@ -0,0 +1,66 @@
+示例代码:
+
+1、引入:
+
+	import qiaoSelect from '@/uni_modules/qiao-select/components/qiao-select/qiaoSelect.vue'
+
+2、添加:
+
+	components: {
+		qiaoSelect
+	},
+
+3、使用:
+
+	组件默认展示的是【name】字段,可通过showField设置,最终@change返回整个选择的对象
+	
+	如果需要设置初始默认值,通过showObj设置,赋值要展示的条目对象
+	
+	组件外层View可以给个宽度
+
+	<view style="width: 300rpx;">
+		<qiaoSelect :keyId="1" :dataList="orgArray" phText="选择机构名称" phColor="#999999" showField="name" searchKey="name"
+			:showObj="showObj" :showBorder="false" :disabled="false" @change="selectChange" @input='inputChange'></qiaoSelect>
+	</view>
+					
+	selectChange(e) {//返回选择的对象,如果输入框清空,返回null
+		if (e) {
+			this.mechId = e.id
+		} else {
+			this.mechId = ''
+		}
+	},
+	inputChange(e) {//返回搜索结果集合,一般用不到
+		console.log(e)
+	},
+	
+	可以通过以下2种方法清空指定的组件:
+	1、加上 showObj 字段,然后将它设置为null,就清空了
+	2、给组件加一个ref='xxx',然后通过this.$refs.xxx.clickClear()清空
+					
+					
+【属性介绍】:
+
+	dataList:			下拉数据
+
+	keyId:				唯一键,用于多个关闭
+	
+	showField:		要展示的字段,默认name
+	
+	showObj:			设置展示的条目对象,可用来设置默认值
+
+	phText:				提示语
+
+	phColor:			提示语颜色
+
+	searchKey:		指定搜索的字段,不设置使用展示字段showField搜索
+
+	showBorder:		是否显示边框
+	
+	disabled:			是否禁用
+
+	@change:			返回选择的对象,如果输入框清空,返回null
+
+	@input:				返回搜索结果集合
+	
+	

+ 27 - 0
uni_modules/qiao-select/package.json

@@ -0,0 +1,27 @@
+{
+	"id": "qiao-select",
+	"name": "搜索下拉选择器",
+	"displayName": "qiao-select带input模糊搜索的下拉选择框",
+	"version": "1.0.8",
+	"description": "搜索下拉选择器,支持输入框模糊搜索下拉数据,支持小程序,h5,可自行配置搜索项",
+	"keywords": [
+        "select",
+        "下拉搜索",
+        "选择器",
+        "选择框",
+        "搜索下拉"
+    ],
+	"dcloudext": {
+		"contact": {
+			"qq": "1450294898"
+		},
+		"declaration": {
+			"ads": "无",
+			"data": "无",
+			"permissions": "无"
+		},
+		"npmurl": "",
+		"type": "component-vue"
+	},
+	"repository": ""
+}