Преглед изворни кода

首页布局修改、订单搜索页面、签收支付方式

unknown пре 5 месеци
родитељ
комит
459b03a927

+ 1 - 0
App.vue

@@ -34,6 +34,7 @@
 	@import url(@/static/fonts/iconfont.css);
 
 	page {
+		height: 100%;
 		background-color: #f3f4f6;
 	}
 </style>

+ 242 - 0
components/hqs-popup/hqs-popup.vue

@@ -0,0 +1,242 @@
+<style lang="scss">
+.hqs-popup {
+	.qs-con {
+		background: #fff;
+	}
+	.qs-header {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		position: relative;
+	}
+	.qs-title {
+		font-size: 16px;
+		font-weight: bold;
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+	}
+	.hidden { visibility: hidden; }
+	.qs-side {
+		min-width: 60px;
+		padding: 15px 20px;
+		color: #888;
+		flex-shrink: 0;
+		&:active { opacity: .8; }
+	}
+	.qs-h-scroll {
+		height: 100vh;
+		// #ifdef H5
+		margin-top: 44px;
+		height: calc(100vh - 44px);
+		// #endif
+	}
+	.ta-r { text-align: right; }
+}
+</style>
+
+<template>
+<uni-popup ref="popup" 
+	:mask-click="maskClick" @change="onChange"
+	:type="from" class="hqs-popup">
+	<view class="qs-con" 
+		:style="conStyle" 
+		@mousedown="onTouch" @mousemove="onTouch" @mouseup="onTouch"
+		@touchstart="onTouch" @touchmove="onTouch" @touchend="onTouch">
+		<block v-if="isVertical">
+			<view class="qs-header" v-if="from == 'bottom' && showHeader">
+				<view class="qs-side" :class="{'hidden': !showBack && !$slots.back}"
+					@click="onBack">
+					<slot name="back">
+						<text>返回</text>
+					</slot>
+				</view>
+				<slot name="title">
+					<text class="qs-title">{{ title }}</text>
+				</slot>
+				<view class="qs-side ta-r" :class="{'hidden': !showClose}"
+					@click="close">
+					<slot name="close">
+						<u-icon :name="closeIcon" :size="32" v-if="closeIcon"></u-icon>
+						<text v-else>关闭</text>
+					</slot>
+				</view>
+			</view>
+			<slot name="sub-header"></slot>
+			<scroll-view scroll-y :style="{ height }"
+				@scroll="onScroll">
+				<view>
+					<slot></slot>
+				</view>
+			</scroll-view>
+			<slot name="bottom"></slot>
+		</block>
+		<block v-else-if="!isVertical">
+			<scroll-view scroll-y class="qs-h-scroll" :style="{ width }">
+				<slot></slot>
+			</scroll-view>
+		</block>
+	</view>
+</uni-popup>
+</template>
+
+<script>
+import UniPopup from './uni-popup.vue'
+
+export default {
+	components: {
+		UniPopup,
+	},
+	props: {
+		// 弹窗显示可通过v-model控制
+		value: Boolean,
+
+		// 弹窗打开开始方向
+		from: {
+			type: String,
+			default: 'bottom',
+		},
+		
+		// 内容区边缘圆角大小
+		round: {
+			type: Number,
+			default: 10,
+		},
+		// 弹窗内容宽度(当from=left或right时起作用)
+		width: {
+			type: String,
+			default: '60vw',
+		},
+		// 弹窗内容高度(当from=top或bottom时起作用)
+		height: {
+			type: String,
+			default: '50vh',
+		},
+		
+		// 显示默认头部标题栏(仅在底部弹出时有)
+		showHeader: {
+			type: Boolean,
+			default: true,
+		},
+		// 弹窗标题
+		title: String,
+
+		// 显示左侧(返回)按钮,如果v-slot:back存在时,也会显示此按钮
+		showBack: Boolean,
+
+		// 显示关闭按钮,如果是字符串,将作为uview(需另外引入)的u-icon组件的name(如showClose="close",会显示close图标)
+		showClose: {
+			type: [Boolean, String],
+			default: true,
+		},
+
+		// 是否可点击模态背景关闭弹窗
+		maskClick: {
+			type: Boolean,
+			default: true,
+		},
+	},
+	data() {
+		return {
+			scrollTop: 0,
+			panStyle: '',
+			showPopup: false,
+		}
+	},
+	computed: {
+		closeIcon() {
+			if(typeof this.showClose == 'string') return this.showClose
+			return false
+		},
+		isVertical() {
+			return ['bottom', 'top'].includes(this.from)
+		},
+		conStyle() {
+			let style = this.panStyle || ''
+			let r = this.round
+			if(r > 0) {
+				r += 'px'
+				if(this.from == 'bottom') r = [r, r, 0, 0]
+				else if(this.from == 'left') r = [0, r, r, 0]
+				else if(this.from == 'right') r = [r, 0, 0, r]
+				else r = [0, 0, r, r]
+				style += `border-radius: ${r.join(' ')};`
+			}
+			return style
+		},
+	},
+	watch: {
+		value(val) {
+			if(val == this.showPopup) return
+			if(val) this.open()
+			else this.close()
+		},
+		showPopup(val) {
+			this.$emit('input', val)
+		},
+	},
+	mounted() {
+		if(this.value) this.open()
+	},
+	methods: {
+		onScroll(e) {
+			this.scrollTop = e.detail.scrollTop
+		},
+		onTouch(ev) {
+			// if(!this.maskClick) return
+			const { pageX, pageY } = ev.changedTouches[0] || ev
+			if(['touchstart', 'mousedown'].includes(ev.type)) {
+				this.startX = pageX
+				this.startY = pageY
+				this.startTime = ev.timeStamp
+			} else {
+				if(!this.startTime) return
+				const orien = this.isVertical ? 'Y' : 'X'
+				let moveDis = pageY - this.startY
+				if(this.from == 'left') moveDis = this.startX - pageX
+				else if(this.from == 'right') moveDis = pageX - this.startX
+				else if(this.from == 'top') moveDis = -moveDis
+				if(!this.maskClick) moveDis /= 3
+				const duration = (ev.timeStamp - this.startTime)
+				const speed = moveDis/duration
+				if(['touchend', 'mouseup'].includes(ev.type)) {
+					if(this.panStyle) {
+						if(this.maskClick && (moveDis > 120 || speed > 0.25)) {
+							this.close()
+						}
+						else {
+							this.panStyle = `transform: translate${orien}(0); transition: all ease 200ms;`
+						}
+						setTimeout(() => {
+							this.panStyle = ''
+						}, 300)
+					}
+					// conScrollTop = 0
+					this.startTime = 0
+					return
+				}
+				// if(this.scrollTop > 0) return
+				
+				if(moveDis > 0) {
+					if(this.from == 'left' || this.from == 'top') moveDis *= -1
+					this.panStyle = `transform: translate${orien}(${moveDis}px); transition: none;`
+				}
+			}
+		},
+		onChange({ show }) {
+			this.showPopup = show
+		},
+		open() {
+			this.$refs.popup.open()
+			this.showPopup = true
+		},
+		close() {
+			this.$refs.popup.close()
+			this.showPopup = false
+		},
+		onBack() {
+			this.$emit('back')
+		},
+	}
+}
+</script>

+ 284 - 0
components/hqs-popup/uni-popup.vue

@@ -0,0 +1,284 @@
+<template>
+	<view v-if="showPopup" class="uni-popup" @touchmove.stop.prevent="clear">
+		<uni-transition :mode-class="['fade']" :styles="maskClass" 
+			:duration="duration" :show="showTrans" @click="onTap" />
+		<uni-transition :mode-class="ani" :styles="transClass" 
+			:duration="duration" :show="showTrans">
+			<view class="uni-popup__wrapper-box">
+				<slot />
+			</view>
+		</uni-transition>
+	</view>
+</template>
+
+<script>
+	import uniTransition from './uni-transition.vue'
+	
+	/**
+	 * PopUp 弹出层
+	 * @description 弹出层组件,为了解决遮罩弹层的问题
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [top|center|bottom] 弹出方式
+	 * 	@value top 顶部弹出
+	 * 	@value left 左边弹出
+	 * 	@value center 中间弹出
+	 * 	@value bottom 底部弹出
+	 * @property {Boolean} animation = [ture|false] 是否开启动画
+	 * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
+	 * @event {Function} change 打开关闭弹窗触发,e={show: false}
+	 */
+
+	export default {
+		name: 'UniPopup',
+		components: {
+			uniTransition
+		},
+		props: {
+			// 开启动画
+			animation: {
+				type: Boolean,
+				default: true
+			},
+			// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
+			type: {
+				type: String,
+				default: 'center'
+			},
+			// maskClick
+			maskClick: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				duration: 300,
+				ani: [],
+				showPopup: false,
+				showTrans: false,
+				maskClass: {
+					'position': 'fixed',
+					'bottom': 0,
+					'top': 0,
+					'left': 0,
+					'right': 0,
+					'backgroundColor': 'rgba(0, 0, 0, 0.4)'
+				},
+				transClass: {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+				}
+			}
+		},
+		watch: {
+			type: {
+				handler: function(newVal) {
+					switch (this.type) {
+						case 'top':
+							this.ani = ['slide-top']
+							this.transClass = {
+								'position': 'fixed',
+								'left': 0,
+								'right': 0,
+							}
+							break
+						case 'left':
+							this.ani = ['slide-left']
+							this.transClass = {
+								'position': 'fixed',
+								'top': 0,
+								'left': 0,
+								'bottom': 0,
+							}
+							break
+						case 'right':
+							this.ani = ['slide-right']
+							this.transClass = {
+								'position': 'fixed',
+								'top': 0,
+								'right': 0,
+								'bottom': 0,
+							}
+							break
+						case 'bottom':
+							this.ani = ['slide-bottom']
+							this.transClass = {
+								'position': 'fixed',
+								'left': 0,
+								'right': 0,
+								'bottom': 0
+							}
+							break
+						case 'center':
+							this.ani = ['zoom-out', 'fade']
+							this.transClass = {
+								'position': 'fixed',
+								/* #ifndef APP-NVUE */
+								'display': 'flex',
+								'flexDirection': 'column',
+								/* #endif */
+								'bottom': 0,
+								'left': 0,
+								'right': 0,
+								'top': 0,
+								'justifyContent': 'center',
+								'alignItems': 'center'
+							}
+
+							break
+					}
+				},
+				immediate: true
+			}
+		},
+		created() {
+			if (this.animation) {
+				this.duration = 300
+			} else {
+				this.duration = 0
+			}
+		},
+		methods: {
+			clear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			open() {
+				this.showPopup = true
+				this.$nextTick(() => {
+					clearTimeout(this.timer)
+					this.timer = setTimeout(() => {
+						this.showTrans = true
+					}, 50);
+				})
+				this.$emit('change', {
+					show: true
+				})
+			},
+			close(type) {
+				this.showTrans = false
+				this.$nextTick(() => {
+					clearTimeout(this.timer)
+					this.timer = setTimeout(() => {
+						this.$emit('change', {
+							show: false
+						})
+						this.showPopup = false
+					}, 300)
+				})
+			},
+			onTap() {
+				if (!this.maskClick) return
+				this.close()
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-popup {
+		position: fixed;
+		/* #ifdef H5 */
+		top: var(--window-top);
+		/* #endif */
+		/* #ifndef H5 */
+		top: 0;
+		/* #endif */
+		bottom: 0;
+		left: 0;
+		right: 0;
+		/* #ifndef APP-NVUE */
+		z-index: 900;
+		/* #endif */
+	}
+
+	.uni-popup__mask {
+		position: absolute;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		background-color: $uni-bg-color-mask;
+		opacity: 0;
+	}
+
+	.mask-ani {
+		transition-property: opacity;
+		transition-duration: 0.2s;
+	}
+
+	.uni-top-mask {
+		opacity: 1;
+	}
+
+	.uni-bottom-mask {
+		opacity: 1;
+	}
+
+	.uni-center-mask {
+		opacity: 1;
+	}
+
+	.uni-popup__wrapper {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: absolute;
+	}
+
+	.top {
+		top: 0;
+		left: 0;
+		right: 0;
+		transform: translateY(-500px);
+	}
+
+	.bottom {
+		bottom: 0;
+		left: 0;
+		right: 0;
+		transform: translateY(500px);
+	}
+
+	.center {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-direction: column;
+		/* #endif */
+		bottom: 0;
+		left: 0;
+		right: 0;
+		top: 0;
+		justify-content: center;
+		align-items: center;
+		transform: scale(1.2);
+		opacity: 0;
+	}
+
+	.uni-popup__wrapper-box {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: relative;
+	}
+
+	.content-ani {
+		// transition: transform 0.3s;
+		transition-property: transform, opacity;
+		transition-duration: 0.2s;
+	}
+
+
+	.uni-top-content {
+		transform: translateY(0);
+	}
+
+	.uni-bottom-content {
+		transform: translateY(0);
+	}
+
+	.uni-center-content {
+		transform: scale(1);
+		opacity: 1;
+	}
+</style>

+ 279 - 0
components/hqs-popup/uni-transition.vue

@@ -0,0 +1,279 @@
+<template>
+	<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject"
+	 @click="change">
+		 <slot></slot>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const animation = uni.requireNativePlugin('animation');
+	// #endif
+	/**
+	 * Transition 过渡动画
+	 * @description 简单过渡动画组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=985
+	 * @property {Boolean} show = [false|true] 控制组件显示或隐藏
+     * @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
+     *  @value fade 渐隐渐出过渡
+     *  @value slide-top 由上至下过渡
+     *  @value slide-right 由右至左过渡
+     *  @value slide-bottom 由下至上过渡
+     *  @value slide-left 由左至右过渡
+     *  @value zoom-in 由小到大过渡
+     *  @value zoom-out 由大到小过渡
+	 * @property {Number} duration 过渡动画持续时间
+	 * @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
+	 */
+	export default {
+		name: 'uniTransition',
+		props: {
+			show: {
+				type: Boolean,
+				default: false
+			},
+			modeClass: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			duration: {
+				type: Number,
+				default: 300
+			},
+			styles: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {
+				isShow: false,
+				transform: '',
+				ani: { in: '',
+					active: ''
+				}
+			};
+		},
+		watch: {
+			show: {
+				handler(newVal) {
+					if (newVal) {
+						this.open()
+					} else {
+						this.close()
+					}
+				},
+				immediate: true
+			}
+		},
+		computed: {
+			stylesObject() {
+				let styles = {
+					...this.styles,
+					'transition-duration': this.duration / 1000 + 's'
+				}
+				let transfrom = ''
+				for (let i in styles) {
+					let line = this.toLine(i)
+					transfrom += line + ':' + styles[i] + ';'
+				}
+				return transfrom
+			}
+		},
+		created() {
+			// this.timer = null
+			// this.nextTick = (time = 50) => new Promise(resolve => {
+			// 	clearTimeout(this.timer)
+			// 	this.timer = setTimeout(resolve, time)
+			// 	return this.timer
+			// });
+		},
+		methods: {
+			change() {
+				this.$emit('click', {
+					detail: this.isShow
+				})
+			},
+			open() {
+				clearTimeout(this.timer)
+				this.isShow = true
+				this.transform = ''
+				this.ani.in = ''
+				for (let i in this.getTranfrom(false)) {
+					if (i === 'opacity') {
+						this.ani.in = 'fade-in'
+					} else {
+						this.transform += `${this.getTranfrom(false)[i]} `
+					}
+				}
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this._animation(true)
+					}, 50)
+				})
+
+			},
+			close(type) {
+				clearTimeout(this.timer)
+				this._animation(false)
+			},
+			_animation(type) {
+				let styles = this.getTranfrom(type)
+				// #ifdef APP-NVUE
+				if(!this.$refs['ani']) return
+				animation.transition(this.$refs['ani'].ref, {
+					styles,
+					duration: this.duration, //ms
+					timingFunction: 'ease',
+					needLayout: false,
+					delay: 0 //ms
+				}, () => {
+					if (!type) {
+						this.isShow = false
+					}
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				})
+				// #endif
+				// #ifndef APP-NVUE
+				this.transform = ''
+				for (let i in styles) {
+					if (i === 'opacity') {
+						this.ani.in = `fade-${type?'out':'in'}`
+					} else {
+						this.transform += `${styles[i]} `
+					}
+				}
+				this.timer = setTimeout(() => {
+					if (!type) {
+						this.isShow = false
+					}
+					this.$emit('change', {
+						detail: this.isShow
+					})
+
+				}, this.duration)
+				// #endif
+
+			},
+			getTranfrom(type) {
+				let styles = {
+					transform: ''
+				}
+				this.modeClass.forEach((mode) => {
+					switch (mode) {
+						case 'fade':
+							styles.opacity = type ? 1 : 0
+							break;
+						case 'slide-top':
+							styles.transform += `translateY(${type?'0':'-100%'}) `
+							break;
+						case 'slide-right':
+							styles.transform += `translateX(${type?'0':'100%'}) `
+							break;
+						case 'slide-bottom':
+							styles.transform += `translateY(${type?'0':'100%'}) `
+							break;
+						case 'slide-left':
+							styles.transform += `translateX(${type?'0':'-100%'}) `
+							break;
+						case 'zoom-in':
+							styles.transform += `scale(${type?1:0.8}) `
+							break;
+						case 'zoom-out':
+							styles.transform += `scale(${type?1:1.2}) `
+							break;
+					}
+				})
+				return styles
+			},
+			_modeClassArr(type) {
+				let mode = this.modeClass
+				if (typeof(mode) !== "string") {
+					let modestr = ''
+					mode.forEach((item) => {
+						modestr += (item + '-' + type + ',')
+					})
+					return modestr.substr(0, modestr.length - 1)
+				} else {
+					return mode + '-' + type
+				}
+			},
+			// getEl(el) {
+			// 	console.log(el || el.ref || null);
+			// 	return el || el.ref || null
+			// },
+			toLine(name) {
+				return name.replace(/([A-Z])/g, "-$1").toLowerCase();
+			}
+		}
+	}
+</script>
+
+<style>
+	.uni-transition {
+		transition-timing-function: ease;
+		transition-duration: 0.3s;
+		transition-property: transform, opacity;
+	}
+
+	.fade-in {
+		opacity: 0;
+	}
+
+	.fade-active {
+		opacity: 1;
+	}
+
+	.slide-top-in {
+		/* transition-property: transform, opacity; */
+		transform: translateY(-100%);
+	}
+
+	.slide-top-active {
+		transform: translateY(0);
+		/* opacity: 1; */
+	}
+
+	.slide-right-in {
+		transform: translateX(100%);
+	}
+
+	.slide-right-active {
+		transform: translateX(0);
+	}
+
+	.slide-bottom-in {
+		transform: translateY(100%);
+	}
+
+	.slide-bottom-active {
+		transform: translateY(0);
+	}
+
+	.slide-left-in {
+		transform: translateX(-100%);
+	}
+
+	.slide-left-active {
+		transform: translateX(0);
+		opacity: 1;
+	}
+
+	.zoom-in-in {
+		transform: scale(0.8);
+	}
+
+	.zoom-out-active {
+		transform: scale(1);
+	}
+
+	.zoom-out-in {
+		transform: scale(1.2);
+	}
+</style>

+ 47 - 6
components/x-orderManagement.vue

@@ -34,10 +34,24 @@
 			<view class="center_in title_sign">{{signRejection}}</view>
 			<view class="card_sign_for">
 				<view class="img_sign_rejection">运单号: {{orderNumber}}</view>
-				<view class="card_image_sign">
-					<view class="img_sign_rejection">{{signRejection}}图片</view>
-					<u-upload :fileList="fileList1" name="1" multiple :maxCount="10" @afterRead="afterRead"
-						@delete="deletePic"></u-upload>
+				<view v-if="!rejectionFlag">
+					<u-radio-group v-model="value">
+						<span style="font-size: 30rpx;margin: 0rpx 20rpx 15rpx 0rpx;">支付方式:</span>
+						<u-radio style="margin: 0rpx 20rpx 15rpx 0rpx;" v-for="(item, index) in radiolist" :key="index"
+							:label="item.name" :name="item.value"></u-radio>
+					</u-radio-group>
+				</view>
+				<view style="display: flex;">
+					<view class="card_image_sign">
+						<view class="img_sign_rejection center_in">{{signRejection}}图片</view>
+						<u-upload :fileList="fileList1" name="1" multiple :maxCount="10" @afterRead="afterRead"
+							@delete="deletePic"></u-upload>
+					</view>
+					<view class="card_image_sign">
+						<view class="img_sign_rejection center_in" @click="goSignature('client')">客户签字</view>
+						<u-image :showLoading="true" :src="imageData" width="200rpx" height="155rpx"
+							@click="goSignature('client')"></u-image>
+					</view>
 				</view>
 				<view class="rejection_card" v-if="rejectionFlag">
 					<view class="img_sign_rejection">拒收原因</view>
@@ -103,6 +117,23 @@
 					},
 				},
 				antiList: {},
+				imageData: '',
+				radiolist: [{
+					name: '现金',
+					value: 0,
+				}, {
+					name: '线上支付',
+					value: 1,
+				}, {
+					name: '银行卡',
+					value: 2,
+				}, {
+					name: '医保',
+					value: 3,
+				}, {
+					name: '其他',
+					value: 4,
+				}]
 			}
 		},
 		mounted() {
@@ -296,6 +327,12 @@
 				})
 				this.imageUrl = arr.join()
 			},
+			// 签字
+			goSignature(title) {
+				uni.navigateTo({
+					url: '/pages/order/signatureBoard'
+				});
+			},
 			uploadFilePromise(url) {
 				return new Promise((resolve, reject) => {
 					let a = uni.uploadFile({
@@ -394,8 +431,8 @@
 	}
 
 	.card_sign_for {
-		width: 600rpx;
-		padding: 10rpx 20rpx 20rpx 20rpx;
+		width: 640rpx;
+		padding: 10rpx 30rpx 30rpx 30rpx;
 	}
 
 	.rejection_card {
@@ -427,4 +464,8 @@
 		margin-bottom: 15rpx;
 		align-items: center;
 	}
+
+	::v-deep .u-radio-group--row {
+		flex-wrap: wrap;
+	}
 </style>

+ 2 - 2
manifest.json

@@ -2,8 +2,8 @@
     "name" : "冷链送药",
     "appid" : "__UNI__49186F9",
     "description" : "",
-    "versionName" : "1.1.1",
-    "versionCode" : 111,
+    "versionName" : "1.1.2",
+    "versionCode" : 112,
     "transformPx" : false,
     /* 5+App特有相关 */
     "app-plus" : {

+ 15 - 0
pages.json

@@ -7,6 +7,11 @@
 		}
 	},
 	"pages": [{
+		"path": "pages/homePage",
+		"style": {
+			"navigationStyle": "custom"
+		}
+	}, {
 		"path": "pages/indexRouter",
 		"style": {
 			"navigationStyle": "custom"
@@ -77,6 +82,11 @@
 			"navigationStyle": "custom"
 		}
 	}, {
+		"path": "pages/order/signatureBoard",
+		"style": {
+			"navigationStyle": "custom"
+		}
+	}, {
 		"path": "pages/mine/password",
 		"style": {
 			"navigationStyle": "custom"
@@ -91,6 +101,11 @@
 		"style": {
 			"navigationStyle": "custom"
 		}
+	}, {
+		"path": "pages/order/orderSearch",
+		"style": {
+			"navigationStyle": "custom"
+		}
 	}],
 	"globalStyle": {
 		"navigationBarTextStyle": "black",

+ 5 - 3
pages/codeLogin.vue

@@ -116,12 +116,13 @@
 						phone: this.formList.phone,
 						verifyCode: this.formList.verifyCode
 					}).then((res) => {
-						console.log(res,4443)
+						console.log(res, 4443)
 						if (res.code == 200) {
 							this.$cache.setToken(res.data.token)
 							// this.getUserInfo()
 							uni.redirectTo({
-								url: '/pages/indexRouter'
+								url: '/pages/homePage'
+								// url: '/pages/indexRouter'
 							})
 						} else {
 							uni.showToast({
@@ -139,7 +140,8 @@
 						this.userInfo = res.data
 						this.$cache.setCache('userInfo', this.userInfo)
 						uni.redirectTo({
-							url: '/pages/indexRouter'
+							url: '/pages/homePage'
+							// url: '/pages/indexRouter'
 						})
 					} else {
 						uni.showToast({

+ 10 - 1
pages/home/index.vue

@@ -59,6 +59,11 @@
 					title: '添加运单',
 					icon: 'icon-tianjiadingdan',
 					color: '#1cc723',
+				}, {
+					id: 'home',
+					title: '首页',
+					icon: 'icon-tianjiadingdan',
+					color: '#1cc723',
 				}],
 			}
 		},
@@ -85,6 +90,10 @@
 						uni.navigateTo({
 							url: '/pages/home/IceManagement'
 						});
+					} else if (value.id == 'home') {
+						uni.navigateTo({
+							url: '/pages/homePage'
+						});
 					}
 				} else {
 					uni.$u.toast('请先登录')
@@ -98,7 +107,7 @@
 	.card_index_bgc {
 		padding-top: constant(safe-area-inset-top);
 		padding-top: env(safe-area-inset-top);
-		background-image: linear-gradient(#a9e3f1, #f3f4f6);
+		// background-image: linear-gradient(#a9e3f1, #f3f4f6);
 	}
 
 	.company_name {

+ 516 - 0
pages/homePage.vue

@@ -0,0 +1,516 @@
+<template>
+	<view>
+		<u-navbar placeholder bgColor="#a9e3f1" leftIcon="" @rightClick="rightClick">
+			<view class="u-nav-slot" slot="right">
+				<u-icon name="list-dot" size="30" color="#fff"></u-icon>
+			</view>
+		</u-navbar>
+		<view class="column_center_card">
+			<view class="mine_bg_card">
+				<view class="card_mine">
+					<view class="card_avatar" v-if="token != ''">
+						<image class="mine_image" src="../static/portrait.png" mode=""></image>
+						<view class="card_user_title">
+							<view class="mine_phone">{{userInfo.username}}</view>
+							<view class="mine_phone1">{{userInfo.nickName}}</view>
+						</view>
+					</view>
+					<view class="card_avatar" v-else @click="login">
+						<image class="mine_image" src="../static/portrait.png" mode=""></image>
+						<view class="mine_title">登录/注册</view>
+					</view>
+				</view>
+				<view class="order_card_home">
+					<view class="order_title_head" @click="getOperate('order',0)">
+						<span>我的订单</span>
+						<u-icon name="arrow-right-double" size="20" color="#000"></u-icon>
+					</view>
+					<view class="card_order">
+						<view class="item_order" v-for="(item,index) in tableList" :key="index"
+							@click="getOperate('order',index)">
+							<view class="card_tab_image center_in"
+								:style="{background: item.bgColor,backgroundColor:item.colorBg}">
+								<span class="iconfont icon_image" :class="item.icon"></span>
+							</view>
+							<view class="order_title">{{item.title}}</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="bp_Card_width">
+				<view class="bpzs_card" @click="getOperate('manage')">
+					<span class="iconfont image_bp icon-bingpaiguanli"></span>
+					<span class="title_bpzs">冰排追溯管理</span>
+				</view>
+				<view class="right_bpzs_card">
+					<view class="bpcrk_card" @click="getOperate('enter','冰排入库')">
+						<span class="iconfont image_cr icon-bingpairuku"></span>
+						<span class="title_bpzs">冰排入库</span>
+					</view>
+					<view class="bpcrk_card" @click="getOperate('out','冰排出库')">
+						<span class="iconfont image_cr icon-bingpaichuku"></span>
+						<span class="title_bpzs">冰排出库</span>
+					</view>
+				</view>
+			</view>
+			<view class="card_bottom_add" @click="getOperate('add')">
+				<view style="display: flex;align-items: center;">
+					<span class="iconfont icon-tianjiadingdan icon_bottom"></span>
+					<span>添加订单</span>
+				</view>
+				<u-icon name="arrow-right" size="20"></u-icon>
+			</view>
+			<view class="card_bottom_add" @click="getOperate('book')">
+				<view style="display: flex;align-items: center;">
+					<span class="iconfont icon-dizhibu icon_bottom"></span>
+					<span>地址簿</span>
+				</view>
+				<u-icon name="arrow-right" size="20"></u-icon>
+			</view>
+		</view>
+		<clh-popup position="right" round="0rpx" v-model="personalShow">
+			<view :style="{paddingTop:height + 'px'}">
+				<view class="head_mine">
+					<view class="card_mine_message">
+						<view class="card_rectangle">
+							<view class="card_circle"></view>
+							<view class="left_order_head" @click="getOperate('order',0)">
+								<u-icon name="order" size="30" color="#5ac725"></u-icon>
+							</view>
+							<view class="right_exit_head" @click="getOperate('wait')">
+								<u-icon name="edit-pen" size="30" color="#5ac725"></u-icon>
+							</view>
+							<view class="card_content_area">
+								<view class="card_name">姓名: <span>{{userInfo.username}}</span></view>
+								<view class="card_name">账号: <span>{{userInfo.nickName}}</span></view>
+							</view>
+						</view>
+					</view>
+					<image class="card_mine_image" src="../static/portrait.png" mode=""></image>
+				</view>
+				<view class="classify_card" @click="getOperate('book')">
+					<span>地址簿</span>
+					<u-icon name="arrow-right"></u-icon>
+				</view>
+				<view class="classify_card" @click="getOperate('password')">
+					<span>修改密码</span>
+					<u-icon name="arrow-right"></u-icon>
+				</view>
+				<view class="btn_exit" @click="logOut">
+					<u-button text="退出登录"></u-button>
+				</view>
+			</view>
+		</clh-popup>
+		<u-modal :show="logoutShow" showCancelButton :title="title" :content='content' @cancel="cancel"
+			@confirm="confirm"></u-modal>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				personalShow: false,
+				token: '',
+				userInfo: {},
+				tableList: [{
+					title: '全部',
+					icon: 'icon-dingdan',
+					colorBg: '#4bc7fc',
+					bgColor: 'linear-gradient(to right, #84d4f6, #4bc7fc)',
+				}, {
+					title: '已下单',
+					icon: 'icon-cancel',
+					colorBg: '#9ddd54',
+					bgColor: 'linear-gradient(to right, #b9f377, #9ddd54)',
+				}, {
+					title: '配送中',
+					icon: 'icon-delivery',
+					colorBg: '#4bc7fc',
+					bgColor: 'linear-gradient(to right, #84d4f6, #4bc7fc)',
+				}, {
+					title: '已送达',
+					icon: 'icon-yisongda',
+					colorBg: '#1cc723',
+					bgColor: 'linear-gradient(to right, #54ef5a, #1cc723)',
+				}, {
+					title: '已拒收',
+					icon: 'icon-yiquxiao',
+					colorBg: '#fe880e',
+					bgColor: 'linear-gradient(to right, #f69f45, #fe880e)',
+				}],
+				logoutShow: false,
+				title: '确定退出?',
+				content: '退出登录后将无法查看运单,重新登录后即可查看',
+				height: '',
+			}
+		},
+		onShow() {
+			const arr = uni.getSystemInfoSync().statusBarHeight
+			this.height = arr
+			var token = this.$cache.getToken()
+			this.token = token
+			var userInfo = this.$cache.getCache('userInfo')
+			if (userInfo) {
+				this.userInfo = userInfo
+			} else {
+				this.userInfo = {}
+			}
+		},
+		mounted() {
+			this.getUserInfo()
+		},
+		methods: {
+			getUserInfo() {
+				this.$api.get('/api/user/profile').then(res => {
+					if (res.code == 200) {
+						this.userInfo = res.data.user
+						this.$cache.setCache('userInfo', this.userInfo)
+					} else {
+						this.$cache.removeToken()
+						this.$cache.removeCache('userInfo')
+						uni.showToast({
+							title: '当前用户不存在',
+							icon: 'none'
+						});
+					}
+				})
+			},
+			rightClick() {
+				this.personalShow = true
+			},
+			// 登录注册
+			login() {
+				uni.navigateTo({
+					url: '/pages/login'
+				});
+			},
+			getOperate(type, value) {
+				console.log(type, value, 6655)
+				if (this.token) {
+					if (type == 'book') {
+						uni.navigateTo({
+							url: '/pages/order/addressBook'
+						});
+					} else if (type == 'add') {
+						uni.navigateTo({
+							url: '/pages/order/addWaybill?title=添加运单&type=1'
+						});
+					} else if (type == 'password') {
+						uni.navigateTo({
+							url: '/pages/mine/password'
+						});
+					} else if (['truck', 'unload', 'signfor', 'enter', 'out'].includes(type)) {
+						uni.navigateTo({
+							url: '/pages/order/delivery?id=' + type + '&title=' + value
+						});
+					} else if (type == 'manage') {
+						uni.navigateTo({
+							url: '/pages/home/IceManagement'
+						});
+					} else if (type == 'order') {
+						uni.navigateTo({
+							url: '/pages/order/index?current=' + value
+						});
+					} else if (type == 'wait') {
+						uni.$u.toast('敬请期待!')
+					}
+				} else {
+					uni.$u.toast('请先登录')
+				}
+			},
+			// 退出登录
+			logOut() {
+				if (this.token) {
+					this.logoutShow = true
+				} else {
+					uni.$u.toast('请先登录')
+				}
+			},
+			// 确定退出登录
+			confirm() {
+				this.$cache.removeToken()
+				this.$cache.removeCache('userInfo')
+				uni.redirectTo({
+					url: '/pages/login'
+				})
+			},
+			// 取消
+			cancel() {
+				this.logoutShow = false
+			},
+			close() {
+				this.personalShow = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-image: linear-gradient(#a9e3f1, #a9e3f1, #f3f4f6);
+	}
+
+	.column_center_card {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+	}
+
+	.mine_bg_card {
+		width: 95%;
+		border-radius: 10rpx;
+		background-image: url(../static/task/mine.jpg);
+		background-repeat: no-repeat;
+		background-position: center top;
+		background-size: cover;
+		background-attachment: scroll;
+		// background-color: #fff;
+		// background-image: linear-gradient(#7edfe4, #ffffff);
+	}
+
+	.card_mine {
+		padding: 0rpx 20rpx;
+		border-bottom: 1rpx solid #f4f4f5;
+	}
+
+	.mine_image {
+		width: 100rpx;
+		height: 100rpx;
+		border-radius: 50%;
+	}
+
+	.mine_phone {
+		margin-left: 20rpx;
+		font-size: 35rpx;
+		color: #fff;
+	}
+
+	.mine_phone1 {
+		margin-left: 20rpx;
+		font-size: 30rpx;
+		color: #f4f4f5;
+	}
+
+	.mine_title {
+		margin-left: 20rpx;
+		font-size: 40rpx;
+		font-weight: bold;
+	}
+
+	.card_avatar {
+		display: flex;
+		align-items: center;
+		padding-top: 30rpx;
+		padding-bottom: 30rpx;
+	}
+
+	.order_title_head {
+		display: flex;
+		align-items: center;
+
+		span {
+			color: #000;
+			font-weight: bold;
+			font-size: 30rpx;
+			padding: 15rpx 0rpx 8rpx 20rpx;
+		}
+	}
+
+	.order_card_home {
+		margin: 20rpx;
+		padding-bottom: 20rpx;
+		border-radius: 10rpx;
+		background-color: rgba(255, 255, 255, 0.5);
+	}
+
+	.card_order {
+		position: relative;
+		margin-top: 20rpx;
+		display: flex;
+		justify-content: space-around;
+	}
+
+	.item_order {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+	}
+
+	.card_tab_image {
+		width: 80rpx;
+		height: 80rpx;
+		border-radius: 50%;
+	}
+
+	.order_title {
+		color: #000;
+		margin-top: 6rpx;
+		font-size: 25rpx;
+	}
+
+	.icon_image {
+		color: #fff;
+		font-size: 37rpx;
+	}
+
+	.bp_Card_width {
+		display: flex;
+		width: calc(100% - 40rpx);
+		margin: 20rpx;
+	}
+
+	.bpzs_card {
+		display: flex;
+		align-items: center;
+		flex-direction: column;
+		justify-content: center;
+		width: 45%;
+		height: 300rpx;
+		// background-color: #fff;
+		border-radius: 10rpx;
+		background-image: linear-gradient(-225deg, #7edfe4 0%, #ffffff 48%, #7edfe4 100%);
+	}
+
+	.image_bp {
+		font-size: 70px;
+		color: #19be6b;
+		margin-bottom: 10rpx;
+	}
+
+	.title_bpzs {
+		font-size: 36rpx;
+		color: #19be6b;
+	}
+
+	.right_bpzs_card {
+		display: flex;
+		width: 55%;
+		flex-direction: column;
+		justify-content: space-between;
+		align-items: flex-end;
+	}
+
+	.bpcrk_card {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		width: 97%;
+		height: 145rpx;
+		border-radius: 10rpx;
+		background-image: linear-gradient(-225deg, #7edfe4 0%, #ffffff 48%, #7edfe4 100%);
+	}
+
+	.image_cr {
+		margin-right: 20rpx;
+		font-size: 30px;
+		color: #19be6b;
+	}
+
+	.card_bottom_add {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		width: calc(100% - 80rpx);
+		margin: 10rpx 20rpx;
+		padding: 30rpx 20rpx;
+		border-radius: 10rpx;
+		background-color: rgba(255, 255, 255, 0.5);
+	}
+
+	.icon_bottom {
+		font-size: 40rpx;
+		margin-right: 10rpx;
+	}
+
+	.head_mine {
+		position: relative;
+		height: 378rpx;
+		margin-bottom: 10rpx;
+	}
+
+	.card_mine_image {
+		position: absolute;
+		width: 125rpx;
+		height: 125rpx;
+		border-radius: 50%;
+		top: 68rpx;
+		left: calc(50% - 59rpx);
+	}
+
+	.card_mine_message {
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		overflow: hidden;
+		margin-top: 130rpx;
+		border-bottom: 1rpx solid #f4f4f5;
+		padding: 0rpx 50rpx 30rpx 50rpx;
+	}
+
+	.card_rectangle {
+		position: relative;
+		width: 100%;
+		height: 200rpx;
+		border: 2rpx solid #5ac725;
+	}
+
+	.card_circle {
+		position: absolute;
+		top: -73rpx;
+		left: calc(50% - 70rpx);
+		width: 140rpx;
+		height: 140rpx;
+		border-radius: 50%;
+		background-color: #fff;
+		border: 2rpx solid #5ac725;
+	}
+
+	.left_order_head {
+		position: absolute;
+		top: 10rpx;
+		left: 10rpx;
+	}
+
+	.right_exit_head {
+		position: absolute;
+		top: 10rpx;
+		right: 20rpx;
+	}
+
+	.card_content_area {
+		position: absolute;
+		top: 80rpx;
+		left: 20rpx;
+		right: 0;
+		bottom: 0;
+		display: flex;
+		flex-direction: column;
+	}
+
+	.card_name {
+		margin-top: 10rpx;
+		font-size: 30rpx;
+
+		span {
+			margin-left: 10rpx;
+		}
+	}
+
+	.classify_card {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding: 20rpx;
+	}
+
+	.btn_exit {
+		position: absolute;
+		bottom: 30rpx;
+		left: 30rpx;
+		right: 30rpx;
+		padding-bottom: env(safe-area-inset-bottom);
+	}
+</style>

+ 4 - 2
pages/login.vue

@@ -121,7 +121,8 @@
 							// this.getUserInfo()
 
 							uni.redirectTo({
-								url: '/pages/indexRouter'
+								url: '/pages/homePage'
+								// url: '/pages/indexRouter'
 							})
 						} else {
 							uni.showToast({
@@ -141,7 +142,8 @@
 						this.userInfo = res.data.user
 						this.$cache.setCache('userInfo', this.userInfo)
 						uni.redirectTo({
-							url: '/pages/indexRouter'
+							url: '/pages/homePage'
+							// url: '/pages/indexRouter'
 						})
 					} else {
 						uni.showToast({

+ 1 - 1
pages/mine/password.vue

@@ -108,7 +108,7 @@
 	}
 </script>
 
-<style lang="scss" scoped>
+<style lang="scss">
 	page {
 		background-color: #fff !important;
 	}

+ 49 - 19
pages/order/delivery.vue

@@ -27,13 +27,13 @@
 						@focus="focus(false)"></u-input> -->
 				</view>
 			</view>
-			<view class="card_search" v-if="selectiveType == 'enter'">
+			<!-- <view class="card_search" v-if="selectiveType == 'enter'">
 				<view class="details_title">冷冻要求 <span class="line_title">*</span></view>
 				<view class="card_input">
 					<u-input placeholder="请输入" border="surround" v-model="freezingDuration"></u-input>
 				</view>
 				<view class="title_hour">小时</view>
-			</view>
+			</view> -->
 			<view class="card_search">
 				<view class="details_title">冰排编号 <span class="line_title">*</span></view>
 				<view class="card_input">
@@ -232,8 +232,8 @@
 			leftClick() {
 				uni.$emit('refresh');
 			},
-			submit() {
-				this.getEntering()
+			async submit() {
+				await this.getEntering()
 				if (this.list.length > 0) {
 					if (this.typeFlag) {
 						// 入库
@@ -292,14 +292,24 @@
 				}
 			},
 			// 扫码录入
-			getEntering() {
+			async getEntering() {
 				if (this.frequencyCoding) {
-					this.list.push(this.frequencyCoding)
+					await this.$api.get('/api/ice-raft/code/' + this.frequencyCoding).then(res => {
+						if (res.code == 200) {
+							this.list.push(this.frequencyCoding)
 
-					function methods1(arr) {
-						return Array.from(new Set(arr));
-					}
-					this.list = methods1(this.list)
+							function methods1(arr) {
+								return Array.from(new Set(arr));
+							}
+							this.list = methods1(this.list)
+						} else {
+							uni.showToast({
+								icon: 'none',
+								title: res.msg,
+								duration: 3000
+							});
+						}
+					})
 				}
 			},
 			// 扫一扫
@@ -314,12 +324,22 @@
 						if (res.result) {
 							let url = res.result;
 							this.frequencyCoding = url
-							this.list.push(url)
-
-							function methods1(arr) {
-								return Array.from(new Set(arr));
-							}
-							this.list = methods1(this.list)
+							this.$api.get('/api/ice-raft/code/' + this.frequencyCoding).then(res => {
+								if (res.code == 200) {
+									this.list.push(url)
+
+									function methods1(arr) {
+										return Array.from(new Set(arr));
+									}
+									this.list = methods1(this.list)
+								} else {
+									uni.showToast({
+										icon: 'none',
+										title: res.msg,
+										duration: 3000
+									});
+								}
+							})
 						} else {
 							console.log('请重新扫描');
 							return false;
@@ -333,9 +353,19 @@
 			// 添加冰排 
 			addIce() {
 				if (this.frequencyCoding) {
-					this.list.push(this.frequencyCoding)
-					this.list = this.uniqueArray(this.list)
-					this.frequencyCoding = ''
+					this.$api.get('/api/ice-raft/code/' + this.frequencyCoding).then(res => {
+						if (res.code == 200) {
+							this.list.push(this.frequencyCoding)
+							this.list = this.uniqueArray(this.list)
+							this.frequencyCoding = ''
+						} else {
+							uni.showToast({
+								icon: 'none',
+								title: res.msg,
+								duration: 3000
+							});
+						}
+					})
 				}
 			},
 			// 去重

+ 76 - 4
pages/order/index.vue

@@ -1,16 +1,25 @@
 <template>
 	<!-- 运单页面 -->
 	<view>
-		<u-navbar title="我的运单" autoBack placeholder></u-navbar>
+		<u-navbar title="" autoBack placeholder>
+			<view class="u-nav-slot nav_center" slot="center" @click="openCenter">
+				<view style="width: calc(100% - 90rpx);">
+					<u-search shape="square" :disabled="false" :showAction="false" placeholder="请输入运单号搜索"></u-search>
+				</view>
+			</view>
+		</u-navbar>
 		<view class="tab_order">
 			<u-tabs :list="tableList" lineColor="#333333" lineWidth="60" :scrollable="false" :current="current"
 				@change="tabClick"></u-tabs>
 		</view>
 		<view class="card_order_mangement" v-if="orderList.length > 0">
-			<x-orderManagement :orderList="orderList" :userInfo="userInfo" @sendOrders="sendOrders"
+			<x-orderManagement ref="order" :orderList="orderList" @sendOrders="sendOrders"
 				@operateSuccessfully="operateSuccessfully" @proofRenewal="proofRenewal"
-				:key="Math.random()"></x-orderManagement>
-			<view v-if="loadingMore" style="width: 50%;"><u-divider :text="loading"></u-divider></view>
+				:key="keyId"></x-orderManagement>
+			<view style="width: 50%;">
+				<u-loadmore :status="loadStatus" :key="Math.random()" />
+				<!-- <u-divider v-if="loadingMore" :text="loading"></u-divider> -->
+			</view>
 		</view>
 		<u-empty mode="order" marginTop="50" v-else></u-empty>
 		<u-popup :show="sendShow" closeable round="8" :closeOnClickOverlay="false" @close="close">
@@ -81,6 +90,7 @@
 </template>
 
 <script>
+	const ENV = require('@/.env.js')
 	export default {
 		data() {
 			return {
@@ -123,6 +133,10 @@
 					id: null,
 					name: '',
 				},
+				imageData: '',
+				loadStatus: 'loadmore', //loading 、nomore
+				keyId: 0,
+				waybillId: null,
 			}
 		},
 		beforeDestroy() {
@@ -142,6 +156,13 @@
 			}
 		},
 		onLoad(value) {
+			//注册监听事件签字图片
+			uni.$on('sign', (data) => {
+				if (this.$refs.order) {
+					this.$refs.order.imageData = data.replace(/[\r\n]/g, "");
+				}
+				this.getUpload(data)
+			})
 			if (value.current) {
 				this.current = Number(value.current)
 			}
@@ -157,6 +178,11 @@
 			this.getList()
 		},
 		methods: {
+			openCenter() {
+				uni.navigateTo({
+					url: '/pages/order/orderSearch'
+				});
+			},
 			getempty() {
 				this.iceList = []
 				this.incubator.id = ''
@@ -173,6 +199,7 @@
 			},
 			// 获取司机和仓管运单列表
 			getList() {
+				this.loadStatus = 'loading'
 				this.loadingMore = true;
 				this.$api.get('/api/waybill', {
 					page: this.currentPage,
@@ -187,12 +214,17 @@
 						if (data.length < this.pageSize) {
 							this.loadingMore = true
 							this.loading = '没有更多了'
+							this.loadStatus = 'nomore'
 						} else {
 							this.loading = '加载中'
+							this.loadStatus = 'loading'
 							this.loadingMore = false
 							this.currentPage++
 						}
 					}
+				}).catch(() => {
+					this.loadingMore = true
+					this.loadStatus = 'nomore'
 				})
 			},
 			// 防拆更新
@@ -280,6 +312,9 @@
 			},
 			// tab运单
 			tabClick(row) {
+				this.loadStatus = 'loading'
+				this.keyId = row.index
+				this.loadingMore = true
 				this.currentPage = 1
 				this.orderList = []
 				if (row) {
@@ -405,8 +440,37 @@
 							this.scrollTop = data.height;
 						}).exec();
 					});
+					this.iceNumber = ''
+				}
+			},
+			// 签名板
+			async getUpload(file) {
+				const result = await this.uploadFilePromise(file)
+				// this.ruleForm.customerImg = result
+				if (this.$refs.order) {
+					// this.$refs.order.imageData = result
 				}
 			},
+			uploadFilePromise(url) {
+				return new Promise((resolve, reject) => {
+					let a = uni.uploadFile({
+						url: ENV.APP_DEV_URL + '/api/upload', // 仅为示例,非真实的接口地址
+						filePath: url,
+						name: 'file',
+						header: {
+							'Authorization': 'Bearer ' + uni.getStorageSync('access_token'),
+						},
+						success: (res) => {
+							let state = JSON.parse(res.data)
+							setTimeout(() => {
+								if (state.code == 200) {
+									resolve(state.data)
+								}
+							}, 100)
+						}
+					});
+				})
+			},
 			// 去重
 			uniqueArray(arr) {
 				return [...new Set(arr)];
@@ -416,6 +480,14 @@
 </script>
 
 <style lang="scss">
+	.nav_center {
+		display: flex;
+		align-items: center;
+		justify-content: flex-end;
+		padding-right: 30rpx;
+		width: 100%;
+	}
+
 	.tab_order {
 		background-color: #fff;
 	}

+ 408 - 0
pages/order/orderSearch.vue

@@ -0,0 +1,408 @@
+<template>
+	<!-- 订单搜索 -->
+	<view>
+		<u-navbar title="" autoBack placeholder>
+			<view class="u-nav-slot nav_center" slot="center">
+				<view style="width: calc(100% - 90rpx);">
+					<u-search v-model="keyword" :focus="true" shape="square" placeholder="请输入运单号搜索" @custom="searchBank"
+						@search="searchBank" @clear="clear"></u-search>
+				</view>
+			</view>
+		</u-navbar>
+		<view v-if="orderList.length > 0">
+			<x-orderManagement ref="order" :orderList="orderList" @sendOrders="sendOrders"
+				@operateSuccessfully="operateSuccessfully" @proofRenewal="proofRenewal"
+				:key="keyId"></x-orderManagement>
+		</view>
+		<u-empty mode="search" marginTop="50" v-else></u-empty>
+		<u-popup :show="sendShow" closeable round="8" :closeOnClickOverlay="false" @close="close">
+			<view class="card_send">
+				<view class="send_title">派单</view>
+				<view class="card_input_send">
+					<view class="incubator_title"><span>*</span>保温箱</view>
+					<view class="card_search_gray frame" @click="focus(false)">
+						<span v-if="incubator.name">{{incubator.name}}</span>
+						<span class="title_gray" v-else>请选择保温箱</span>
+						<u-icon name="arrow-down" color="#c8c9cc" size="18"></u-icon>
+					</view>
+				</view>
+				<view class="card_input_send">
+					<view class="incubator_title"><span>*</span>冰排编号</view>
+					<u-input placeholder="请输入冰排编号" border="surround" v-model="iceNumber" @blur="iceRaftBlur">
+						<template slot="suffix">
+							<u-icon name="scan" size="24" @click="sweep"></u-icon>
+						</template>
+					</u-input>
+					<view class="add_card center_in" @click="addIce">
+						<u-icon name="plus" size="18"></u-icon>
+					</view>
+				</view>
+				<view class="card_frequency">
+					<view class="card_high space_between">
+						<view class="card_frequency_title">已扫冰排编号</view>
+						<view class="card_bottle">已扫<span>{{iceList.length}}</span></view>
+					</view>
+					<scroll-view :scroll-top="scrollTop" scroll-y="true" class="swept_card">
+						<view class="scrollView" style="width: 100%;" v-if="iceList.length > 0">
+							<view class="item_coding" v-for="(item,index) in iceList" :key="index">
+								<view style="display: flex;align-items: center;">
+									<view class="num_index">{{index + 1}}</view>
+									<view class="title_coding">{{item}}</view>
+								</view>
+								<u-icon name="close-circle-fill" color="#c0c4cc" size="20"
+									@click="removeWaybill(item)"></u-icon>
+							</view>
+						</view>
+					</scroll-view>
+				</view>
+				<view style="width: 100%;height: 120rpx;"></view>
+				<view class="card_btn">
+					<u-button type="primary" text="确定" @click="confirm"></u-button>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				keyword: '',
+				loadingMore: true,
+				orderList: [],
+				incubator: {
+					id: null,
+					name: '',
+				},
+				sendShow: false,
+				iceNumber: '',
+				iceList: [],
+				scrollTop: null,
+				keyId: 0,
+				waybillId: null,
+			}
+		},
+		beforeDestroy() {
+			// console.log('页面销毁')
+			this.getempty()
+		},
+		onShow() {
+			let incubator = uni.getStorageSync('incubatorValue')
+			if (incubator) {
+				this.incubator.id = incubator.id
+				this.incubator.name = incubator.name
+			}
+		},
+		methods: {
+			getempty() {
+				this.iceList = []
+				this.incubator.id = ''
+				this.incubator.name = ''
+				this.iceNumber = ''
+				uni.removeStorageSync('incubatorValue');
+				this.hintTitle = '请选择保温箱'
+				this.sendShow = false
+				this.incubatorMore = true
+				this.thermostatList = []
+			},
+			searchBank(event) {
+				this.orderList = []
+				this.loadingMore = true;
+				this.$api.get('/api/waybill', {
+					waybillNo: this.keyword,
+				}).then(res => {
+					if (res.code == 200) {
+						const data = res.data.list
+						if (this.loadingMore == true && data) {
+							this.orderList = this.orderList.concat(data);
+						}
+						if (data.length < this.pageSize) {
+							this.loadingMore = true
+						} else {
+							this.loadingMore = false
+						}
+					}
+				}).catch(() => {
+					this.loadingMore = true
+				})
+			},
+			// 移除错误运单号
+			removeWaybill(value) {
+				if (this.iceNumber == value) {
+					this.iceNumber = ''
+				}
+				const arr = deleteElementById(this.iceList, value)
+				this.iceList = arr
+
+				function deleteElementById(arr, key) {
+					return arr.filter((item) => item !== key);
+				}
+			},
+			// 添加冰排 
+			addIce() {
+				if (this.iceNumber) {
+					this.iceList.push(this.iceNumber)
+					this.iceList = this.uniqueArray(this.iceList)
+					this.$nextTick(() => {
+						// 获取scroll-view的高度
+						const query = uni.createSelectorQuery().in(this);
+						query.select('.scrollView').boundingClientRect(data => {
+							this.scrollTop = data.height;
+						}).exec();
+					});
+					this.iceNumber = ''
+				}
+			},
+			// 冰排失去焦点
+			iceRaftBlur(value) {
+				if (value) {
+					this.iceList.push(value)
+					this.iceList = this.uniqueArray(this.iceList)
+				}
+			},
+			// 去重
+			uniqueArray(arr) {
+				return [...new Set(arr)];
+			},
+			// 确定派单
+			confirm() {
+				if (this.incubator.id) {
+					if (this.iceList.length > 0) {
+						const arr = []
+						arr.push(this.waybillId)
+						this.$api.post('/api/waybill/delivery', {
+							waybillIds: arr,
+							coolerBoxId: this.incubator.id,
+							iceRaftCode: this.iceList,
+						}).then(res => {
+							if (res.code == 200) {
+								uni.$u.toast(res.msg)
+								this.sendShow = false
+								this.tabClick()
+							} else if (res.code == 2000) {
+								let arrTitle = res.data
+								let title = ' ,请将冰排' + arrTitle.toString() + '重新入库'
+								uni.$u.toast(res.msg + title)
+								this.sendShow = false
+								this.tabClick()
+							} else {
+								uni.$u.toast(res.msg)
+							}
+						})
+					} else {
+						uni.$u.toast('请先扫描冰排')
+					}
+				} else {
+					uni.$u.toast('请先选择保温箱')
+				}
+			},
+			// tab运单
+			tabClick(row) {
+				this.keyId = row.index
+				this.loadingMore = true
+				this.orderList = []
+				this.searchBank()
+				this.getempty()
+			},
+			// 扫一扫
+			sweep() {
+				// 允许从相机和相册扫码
+				uni.scanCode({
+					scanType: ['barCode'],
+					// scanType: ['qrCode'],
+					autoZoom: false,
+					success: (res) => {
+						console.log(res);
+						if (res.result) {
+							let url = res.result;
+							this.iceNumber = url
+							this.iceList.push(url)
+
+							function methods1(arr) {
+								return Array.from(new Set(arr));
+							}
+							this.iceList = methods1(this.iceList)
+						} else {
+							console.log('请重新扫描');
+							return false;
+						}
+					},
+					fail: (res) => {
+						console.log('未识别到二维码');
+					}
+				})
+			},
+			// 鼠标聚焦
+			focus() {
+				uni.navigateTo({
+					url: '/pages/order/Incubator'
+				});
+			},
+			// 派单
+			sendOrders(value) {
+				this.waybillId = value.id
+				this.sendShow = true
+			},
+			// 重新获取列表
+			operateSuccessfully() {
+				this.orderList = []
+				this.searchBank()
+			},
+			// 防拆更新
+			proofRenewal() {
+				this.orderList = []
+				this.searchBank()
+			},
+			clear() {
+				console.log(2)
+				this.keyword = ''
+			},
+			close() {
+				this.getempty()
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.nav_center {
+		display: flex;
+		align-items: center;
+		justify-content: flex-end;
+		padding-right: 30rpx;
+		width: 100%;
+	}
+
+	.card_send {
+		padding: 20rpx;
+		min-height: 600rpx;
+	}
+
+	.send_title {
+		text-align: center;
+		margin: 10px;
+	}
+
+	.card_input_send {
+		position: relative;
+		display: flex;
+		align-items: center;
+		margin-bottom: 20rpx;
+	}
+
+	.incubator_title {
+		width: 150rpx;
+		margin-right: 10rpx;
+		font-size: 30rpx;
+
+		span {
+			color: red;
+		}
+	}
+
+	.add_card {
+		margin-left: 10rpx;
+		width: 50rpx;
+		height: 46rpx;
+		border-radius: 8rpx;
+		padding: 6px 9px;
+		border: 1px solid #dadbde;
+	}
+
+	.card_btn {
+		position: absolute;
+		bottom: 20rpx;
+		left: 30rpx;
+		right: 30rpx;
+		padding: 20rpx 0rpx;
+	}
+
+	.scroll-view {
+		transition: max-height 1s ease-out;
+		max-height: 0;
+		overflow: hidden;
+	}
+
+	.card_frequency {
+		display: flex;
+		flex-wrap: wrap;
+	}
+
+	.swept_card {
+		padding: 0rpx 20rpx;
+		width: calc(100% - 40rpx);
+		max-height: 600rpx;
+		// overflow-y: auto;
+	}
+
+	.card_high {
+		margin-bottom: 20rpx;
+	}
+
+	.card_frequency_title {
+		font-size: 32rpx;
+	}
+
+	.card_bottle {
+		font-size: 30rpx;
+
+		span {
+			color: red;
+		}
+	}
+
+	.item_coding {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		width: 100%;
+		padding: 20rpx 0rpx;
+	}
+
+	.num_index {
+		font-size: 30rpx;
+		margin-right: 10rpx;
+	}
+
+	.title_coding {
+		font-size: 30rpx;
+	}
+
+
+	.card_search_gray {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: space-between;
+		flex: 1;
+		padding: 12rpx 18rpx;
+		border-radius: 8rpx;
+		line-height: 48rpx;
+	}
+
+	.title_gray {
+		font-size: 30rpx;
+		color: #c8c9cc;
+	}
+
+	// 伪元素1rpx边框
+	.frame {
+		position: relative; //重要
+	}
+
+	.frame::after {
+		position: absolute;
+		content: '';
+		border: 2rpx solid #e7e6e4;
+		border-radius: 16rpx;
+		width: 200%;
+		height: 200%;
+		top: 0;
+		left: 0;
+		transform: scale(0.5);
+		transform-origin: 0 0;
+		pointer-events: none;
+		/* 使伪元素不会阻止鼠标事件 */
+	}
+</style>

+ 287 - 0
pages/order/signatureBoard.vue

@@ -0,0 +1,287 @@
+<template>
+	<view>
+		<view class="sign-content">
+			<view>
+				<view class="reset" @click="backClick" style="position:fixed;bottom: 466rpx;background:#fff;">返回</view>
+				<view class="reset" @click="clearClick" style="position:fixed;bottom: 266rpx;background:#fff;">重写</view>
+				<view class="reset" @click="saveClick"
+					style="position:fixed;bottom: 66rpx;background: #39b54a;color:#fff;">确定</view>
+			</view>
+			<canvas class="sign" canvas-id="sign" @touchmove="move" @touchstart="start" @touchend="end"
+				@touchcancel="cancel" @longtap="tap" disable-scroll="true" @error="error"></canvas>
+			<view>
+				<view
+					style="transform: rotate(90deg);text-align: center;position:fixed;width:130rpx;right:-14rpx;top:46%;">
+					签名板</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	let content = null;
+	let touchs = [];
+
+	export default {
+		data() {
+			return {
+				isMove: false,
+				createCanvas: false,
+				outW: 0,
+				outH: 0,
+				windowsH: 0,
+				windowsW: 0
+			};
+		},
+		onLoad: function(options) {
+			//获得Canvas的上下文
+			content = uni.createCanvasContext('sign');
+			this.windowsH = uni.getSystemInfoSync().windowHeight;
+			this.windowsW = uni.getSystemInfoSync().windowWidth;
+			//设置线的颜色
+			content.setStrokeStyle('#000000');
+			//设置线的宽度
+			content.setLineWidth(5);
+			//设置线两端端点样式更加圆润
+			content.setLineCap('round');
+			//设置两条线连接处更加圆润
+			content.setLineJoin('round');
+			// content.setFillStyle('white')
+			// content.fillRect(0, 0, 750, 700)
+			// content.draw()
+		},
+		methods: {
+			backClick: function() {
+				uni.navigateBack({
+					delta: 1
+				});
+			},
+			// 画布的触摸移动开始手势响应
+			start: function(event) {
+				// console.log("触摸开始" + event.changedTouches[0].x);
+				// console.log("触摸开始" + event.changedTouches[0].y);
+				//获取触摸开始的 x,y
+				let point = {
+					x: event.changedTouches[0].x,
+					y: event.changedTouches[0].y
+				};
+				touchs.push(point);
+			},
+			// 画布的触摸移动手势响应
+			move: function(e) {
+				let point = {
+					x: e.touches[0].x,
+					y: e.touches[0].y
+				};
+				touchs.push(point);
+				if (touchs.length >= 2) {
+					this.isMove = true;
+					this.draw(touchs);
+				}
+			},
+			// 画布的触摸移动结束手势响应
+			end: function(e) {
+				console.log('触摸结束' + e);
+				//清空轨迹数组
+				for (let i = 0; i < touchs.length; i++) {
+					touchs.pop();
+				}
+			},
+			// 画布的触摸取消响应
+			cancel: function(e) {
+				console.log('触摸取消' + e);
+			},
+			// 画布的长按手势响应
+			tap: function(e) {
+				console.log('长按手势' + e);
+			},
+			error: function(e) {
+				console.log('画布触摸错误' + e);
+			},
+			//绘制
+			draw: function(touchs) {
+				let point1 = touchs[0];
+				let point2 = touchs[1];
+				touchs.shift();
+				content.moveTo(point1.x, point1.y);
+				content.lineTo(point2.x, point2.y);
+				content.stroke();
+				content.draw(true);
+			},
+			//清除操作
+			clearClick: function() {
+				//清除画布
+				content.clearRect(0, 0, this.windowsW, this.windowsH);
+				content.draw(true);
+				this.isMove = false;
+			},
+			//保存图片
+			saveClick: function() {
+				if (this.isMove == false) {
+					uni.showToast({
+						icon: 'none',
+						title: '请绘制签名'
+					})
+					return
+				}
+				var that = this;
+				uni.showLoading({
+					title: '请稍等'
+				});
+				uni.canvasToTempFilePath({
+					canvasId: 'sign',
+					success: function(res) {
+						uni.getImageInfo({
+							src: res.tempFilePath,
+							fail() {
+								uni.hideLoading();
+								uni.showToast({
+									title: '获取图片信息失败'
+								});
+							},
+							success: function(image) {
+								//要先设置在获取 ,加载问题
+								image.height = parseInt(image.height);
+								image.width = parseInt(image.width);
+								that.outW = image.width;
+								that.outH = image.height;
+								//修复大屏手机无法生成图片问题
+								let maxWidth = that.windowsW - uni.upx2px(240);
+								let base = that.outH / that.outW;
+								if (that.outH > maxWidth) {
+									that.outH = maxWidth;
+									that.outW = Math.floor(that.outH / base);
+								}
+								content.rotate(-Math.PI / 2);
+								content.translate(-that.outW, 0);
+								content.drawImage(image.path, 0, 0, that.outW, that.outH);
+								content.translate(that.outW, 0);
+								content.rotate(Math.PI / 2);
+								content.draw(false, () => {
+									uni.canvasToTempFilePath({
+										canvasId: 'sign',
+										fileType: 'jpg',
+										width: that.outH,
+										height: that.outW,
+										sdestWidth: image.height,
+										sdestHeight: image.width,
+										fail(res) {
+											uni.hideLoading();
+											uni.showToast({
+												title: '签名失败',
+												icon: 'none'
+											});
+										},
+										success: function(resss) {
+											uni.hideLoading();
+											that.clearClick()
+											uni.$emit('sign', resss
+												.tempFilePath);
+											uni.navigateBack();
+											// let imgArr = [];
+											// imgArr.push(resss.tempFilePath);
+											// uni.previewImage({
+											// 	urls: imgArr,
+											// 	success(response) {
+											// 		console.log(response);
+											// 	}
+											// });
+										}
+									});
+								});
+							}
+						});
+					},
+					fail() {
+						uni.hideLoading();
+					}
+				});
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	.sign-content {
+		display: flex;
+		height: 100vh;
+		background: #f1f1f1;
+		/*  #ifdef  H5  */
+		// height: calc(100vh - 44px);
+		/*  #endif  */
+		padding: 20rpx 0;
+		box-sizing: border-box;
+
+		.reset {
+			color: #333;
+			background-color: rgb(248, 248, 248);
+			border: 1px solid #ddd;
+			transform: rotate(90deg);
+			margin-top: 20rpx;
+			padding: 20rpx 40rpx;
+			font-size: 30rpx;
+			border-radius: 28rpx;
+			border: none;
+		}
+
+		.tips {
+			width: 600rpx;
+			color: red;
+			transform: rotate(90deg);
+			height: 10px;
+			position: fixed;
+			left: -233rpx;
+			top: 326rpx;
+			/*  #ifdef  H5  */
+			top: calc(326rpx + 88rpx);
+			/*  #endif  */
+			font-size: 34rpx;
+		}
+
+		.sign {
+			flex: 1;
+			height: 100%;
+			margin-right: 100rpx;
+			margin-left: 120rpx;
+			border: 1px dashed #ddd;
+			background-color: #fff;
+		}
+	}
+
+	.g-btns {
+		text-align: center;
+		margin-top: 1rem;
+		transform: rotate(90deg);
+		-ms-transform: rotate(90deg);
+		/* IE 9 */
+		-moz-transform: rotate(90deg);
+		/* Firefox */
+		-webkit-transform: rotate(90deg);
+		/* Safari 和 Chrome */
+		-o-transform: rotate(90deg);
+		position: absolute;
+		top: 12rem;
+		left: -6rem;
+	}
+
+	.g-btns {
+		width: 7.5rem;
+		height: 2.25rem;
+		font-size: 0.9rem;
+		font-weight: bold;
+		border: none;
+		border-radius: 1rem;
+	}
+
+	.u-reset {
+		background: #ddd;
+		color: #666;
+		margin-right: 0.5rem;
+	}
+
+	.u-submit {
+		background: #fc4949;
+		color: #fff;
+		margin-left: 0.5rem;
+	}
+</style>

BIN
static/task/mine.jpg