hmp 4 роки тому
батько
коміт
2681033170

+ 445 - 0
components/amountInput/amountInput.vue

@@ -0,0 +1,445 @@
+<template>
+	<view class="keyboard-main" :style="{height:height+'px'}">
+		<view class="mask" @click.stop="hide" v-if="isShow"></view>
+		<view class='keyboard' :style="'margin-bottom:'+safeAreaBottom+'rpx'" :class="{noPadding:!isShow}">
+			<view class='key-row' v-if="isShow">
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(1)'>1</view>
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(2)'>2</view>
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(3)'>3</view>
+				<view class='key-cell  last-child' @click.stop="_handleKeyPress('delete')">
+					<image class="icon" src="../../static/icon/del.png" mode="aspectFill"></image>
+				</view>
+			</view>
+			<view class='key-row' v-if="isShow">
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(4)'>4</view>
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(5)'>5</view>
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(6)'>6</view>
+				<view class='key-cell last-child'></view>
+			</view>
+			<view class='key-row' v-if="isShow">
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(7)'>7</view>
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(8)'>8</view>
+				<view class='key-cell key-cell-num' @click.stop='_handleKeyPress(9)'>9</view>
+				<view class='key-cell last-child '></view>
+			</view>
+			<view class="key-zero-and-point" v-if="isShow">
+				<view class="a zero" @click.stop='_handleKeyPress(0)'>0</view>
+				<view class="a point" @click.stop="_handleKeyPress('.')">.</view>
+				<view class='a last-child'>
+				</view>
+			</view>
+
+			<view class='key-confirm' :class="{big:isShow,frist:fristShow}" :style="{'background':btnColor}"
+				@click.stop="_handleKeyPress('confirm')">
+				{{confirmText}}
+			</view>
+
+			<view v-if="!isShow">
+				<view class="" style="height: 90rpx;"></view>
+				<view  class="footer-fixed center" style="bottom: 14%;">
+					<view @click="_handleKeyPress('confirm')" class="cu-btn df radius " :style="{'background':btnColor}" style="color: #FFFFFF;width: 90%;height: 90rpx;">
+						付款
+					</view>
+				</view>
+			</view>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "keyBoard",
+		props: {
+			confirmText: {
+				default: '充值',
+				type: String
+			},
+			btnColor: {
+				default: '#2B76EF',
+				type: String
+			},
+			placeholder: {
+				default: '请输入充值金额',
+				type: String
+			},
+			currency: {
+				default: '¥',
+				type: String
+			},
+			maxNumber: {
+				default: 100000000000,
+				type: Number
+			},
+			fontSize: {
+				type: [String, Number],
+				default: 30
+			},
+			isBold: {
+				type: Boolean,
+				default: true
+			},
+			isFilter: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				fristShow: true,
+				isShow: true,
+				size: 0,
+				height: 0,
+				allWidth: 0,
+				money: ''
+			}
+		},
+		created() {
+
+		},
+		computed: {
+			//ios底部安全区域
+			safeAreaBottom() {
+				let info = uni.getSystemInfoSync()
+				let safe = 20
+				if (
+					info && ['devtools', 'ios'].includes(info.platform) &&
+					info.statusBarHeight > safe
+				) {
+					return info.statusBarHeight - safe
+				}
+				return 0
+			}
+		},
+		watch: {
+			money(val) {
+				this.$emit('change', val);
+			}
+		},
+		methods: {
+			show() {
+				this.isShow = true;
+			},
+			hide() {
+				this.isShow = false;
+			},
+			//处理按键
+			_handleKeyPress(num) {
+				uni.vibrateShort();
+				if (num == -1) return false;
+				switch (String(num)) {
+					//小数点
+					case '.':
+						this._handleDecimalPoint();
+						break;
+						//删除键
+					case 'delete':
+						this._handleDeleteKey();
+						break;
+						//确认键
+					case 'confirm':
+						this._handleConfirmKey();
+						break;
+					default:
+						this._handleNumberKey(num);
+						break;
+				}
+			},
+			//处理小数点函数
+			_handleDecimalPoint() {
+				//如果包含小数点,直接返回
+				if (this.money.indexOf('.') > -1) return false;
+				//如果小数点是第一位,补0
+				if (!this.money.length) {
+					this.money = '0.'
+				} else {
+					this.money = this.money + '.';
+				}
+			},
+			//处理删除键
+			_handleDeleteKey() {
+				let S = this.money;
+				//如果没有输入,直接返回
+				if (!S.length) return false;
+				//否则删除最后一个
+				this.money = S.substring(0, S.length - 1);
+			},
+			//处理数字
+			_handleNumberKey(num) {
+				if (Number(this.money + num) > this.maxNumber) {
+					return
+				}
+				let S = this.money;
+				//如果有小数点且小数点位数不小于2
+				if (S.indexOf('.') > -1 && S.substring(S.indexOf('.') + 1).length < 2)
+					this.money = S + num;
+				if (S.indexOf('.') > -1 && S.substring(S.indexOf('.') + 1).length >= 2)
+					return
+				//没有小数点
+				if (!(S.indexOf('.') > -1)) {
+					//如果第一位是0,只能输入小数点
+					if (num == 0 && S.length == 0)
+						this.money = '0.';
+					else {
+						if (S.length && Number(S.charAt(0)) === 0) return;
+						this.money = S + num;
+					}
+				}
+			},
+
+			//提交
+			_handleConfirmKey() {
+				let S = this.money;
+				//未输入
+				if (!S.length || S == 0) {
+					uni.showToast({
+						title: this.placeholder,
+						icon: 'none',
+						duration: 1000
+					});
+					return false;
+				}
+				//将 8. 这种转换成 8.00
+				if (S.indexOf('.') > -1 && S.indexOf('.') == (S.length - 1))
+					S = Number(S.substring(0, S.length - 1)).toFixed(2);
+				//保留两位
+				S = Number(S).toFixed(2);
+				this.$emit('confirm', parseFloat(S)); //提交参数
+			}
+		}
+	}
+</script>
+
+<style lang="less" scoped>
+	.data-content {
+		font-size: 32rpx;
+		font-weight: 800;
+		padding: 50rpx;
+	}
+
+	.keyboard-main {
+		width: 100%;
+		display: flex;
+		justify-content: flex-start;
+		align-items: flex-end;
+		padding: 20rpx 0;
+		box-sizing: initial;
+		color: #1B1B1B;
+
+		text {
+			font-size: 24px;
+			margin-right: 10px;
+		}
+	}
+
+	.keyboard-content {
+		width: 100%;
+		height: 30px;
+		position: relative;
+
+		.placeholder {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 100%;
+			color: #c0c4cc;
+			display: flex;
+			justify-content: flex-start;
+			align-items: flex-end;
+		}
+
+		.input {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 100%;
+			display: flex;
+			justify-content: flex-start;
+			align-items: flex-end;
+			font-size: 30px;
+			font-weight: bold;
+
+			&.zIndex {
+				z-index: 999;
+			}
+
+			#text {
+				display: flex;
+				justify-content: flex-start;
+				align-items: flex-end;
+			}
+
+			.line {
+				display: inline-block;
+				width: 4rpx;
+				height: 30px;
+				border: 2rpx;
+				background-color: #0063E5;
+				margin-left: 8rpx;
+				animation: cursorImg 1s infinite steps(1, start);
+
+				@keyframes cursorImg {
+
+					0%,
+					100% {
+						opacity: 0;
+					}
+
+					50% {
+						opacity: 1;
+					}
+				}
+			}
+		}
+	}
+
+	.mask {
+		position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		z-index: 1;
+	}
+
+	.keyboard {
+		flex: 1;
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		width: 100%;
+		background-color: #f6f6f6;
+		padding: 20rpx;
+		transition: all 0.6s;
+		z-index: 9;
+		box-sizing: border-box;
+
+		&.noPadding {
+			padding: 0;
+			bottom: -100%;
+		}
+	}
+
+	.keyboard .key-row {
+		display: flex;
+		justify-content: space-between;
+		display: -webkit-flex;
+		position: relative;
+		box-sizing: border-box;
+	}
+
+	.keyboard .key-cell {
+		font-size: 18px;
+		width: 160rpx;
+		font-weight: 800;
+		height: 90rpx;
+		/* margin-right: 20rpx; */
+		margin-bottom: 20rpx;
+		background-color: #fff;
+		border-radius: 4rpx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+
+		&.last-child {
+			/* margin-right: 0px; */
+			width: 170rpx;
+		}
+
+		.icon {
+			width: 50rpx;
+			height: 40rpx;
+		}
+	}
+
+	.keyboard .key-confirm {
+		position: fixed;
+		text-align: center;
+		/* min-height: 100rpx; */
+		width: 170rpx;
+		padding: 20rpx 30rpx;
+		border-radius: 6rpx;
+		box-sizing: border-box;
+		color: #FFFFFF;
+		z-index: 10;
+		right: 20rpx;
+		top: calc(100vh - 280rpx);
+		bottom: 200rpx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		font-size: 20px;
+		letter-spacing: 4px;
+		font-weight: bold;
+		transition: all 0.3s;
+
+		&.big {
+			right: 20rpx;
+			bottom: 20rpx;
+			padding: 0 30rpx;
+			bottom: 20rpx;
+		}
+
+		&.frist {
+			position: absolute;
+			top: auto;
+			right: 20rpx;
+			height: 304rpx;
+			bottom: 18rpx;
+		}
+	}
+
+	.key-zero-and-point {
+		display: flex;
+		height: 80rpx;
+		justify-content: space-between;
+		align-items: center;
+		font-size: 20px;
+		font-weight: 800;
+
+		.zero {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 340rpx;
+			text-align: center;
+			background-color: #fff;
+			border-radius: 4rpx;
+			height: 100%;
+		}
+
+		.point {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			background-color: #fff;
+			border-radius: 4rpx;
+			width: 160rpx;
+			height: 100%;
+		}
+
+		.last-child {
+			background-color: #fff;
+			border-radius: 8rpx;
+			width: 170rpx;
+			height: 100%;
+		}
+	}
+
+	.key-cell-num:active {
+		color: white;
+		background: black; //黑色
+		opacity: 0.1; //这里重要,就是通过这个透明度来设置
+	}
+
+	// .a:active,.key-confirm2:active{
+	// 	color: white;
+	// 	background: black;  //黑色
+	// 	opacity: 0.1;    //这里重要,就是通过这个透明度来设置
+	// }
+	#input-text {
+		width: max-content;
+		position: fixed;
+		bottom: -200%;
+	}
+</style>

+ 253 - 0
pages/checkstand/index1.vue

@@ -0,0 +1,253 @@
+<template>
+	<view class="">
+		<!-- #ifdef  MP-WEIXIN-->
+		<view class="">
+			<u-navbar title="收银台"></u-navbar>
+		</view>
+		<!-- #endif -->
+
+		<view class="check-panel flex-direction">
+			<image :src="shopDetail.cover" class="buyer-logo"></image>
+			<view class="title center">{{shopDetail.name}}</view>
+			<view class="input-content">
+				<view class="tips">交易金额</view>
+				<view class="input-bar center" @tap="show=true">
+					<view class="icon center">¥</view>
+					<view class="input center">
+						<view :style="!$isEmpty(orderAmount)?'margin-left: -15%;':''">{{orderAmount}}</view>
+						<view class="cusor" :style="$isEmpty(orderAmount)?'margin-left: -15%;':''"></view>
+					</view>
+				</view>
+				<view style="height: 50rpx;"></view>
+				<view class="" style="z-index: 99;">
+					<u-button throttle-time="1200"  class="button" type="warning" @click="pay">付款</u-button>
+				</view>
+			</view>
+
+			<view class="bottom-line center"> -- 联兑通提供技术支持 --</view>
+			<u-keyboard z-index="9" ref="uKeyboard" :show-tips="false" :safe-area-inset-bottom="true" :mask="false"
+				v-model="show" @change="handleInput" @confirm="pay" @backspace="handleDelete"></u-keyboard>
+		</view>
+		
+		<u-modal v-model="payModalShow" :showCancelButton="true" confirm-color="#FF9447">
+			<view class="center flex-direction text-df" style="padding: 30rpx 40rpx;">
+				<view>您的积分可足额抵扣支付</view>
+				<view class="padding-top-10">本次支付不会扣除您的现金</view>
+			</view>
+		</u-modal>
+
+		<u-modal v-model="modalShow"  :showCancelButton="true" @cancel="payOfh5"  @confirm="jumpLDT" cancel-text="直接付款" confirm-color="#FF9447"
+			confirmText="去联兑通支付" content="去联兑通小程序付款会有更多优惠哟~"></u-modal>
+	</view>
+</template>
+
+<script>
+	export default {
+		onLoad(option) {},
+		data() {
+			return {
+				payModalShow:false,
+				modalShow: false,
+				show: false,
+				logo: "/static/bank/CMBCHINA.png",
+				buyer: "联兑通",
+				orderAmount: '',
+				shopId: '',
+				shopDetail: {}
+			}
+		},
+		onLoad(options) {
+			this.shopId = options.id
+			if (this.$isEmpty(this.shopId)) {
+				this.$dialog.showModal('商户id不能为空', false).then(() => {
+					uni.navigateBack()
+				})
+				return
+			}
+			this.fetchShopDetail()
+		},
+		methods: {
+			fetchShopDetail() {
+				this.$api.shop.detail({
+					id: this.shopId
+				}).then(res => {
+					if (this.$isEmpty(res.data)) {
+						this.$dialog.showModal('获取不到商户信息', false).then(() => {
+							this.show = false
+							uni.navigateBack({
+								delta: 1
+							})
+						})
+					} else {
+						this.show = true
+						this.shopDetail = res.data
+					}
+				}).catch(err => {
+					this.$dialog.showModal('获取不到商户信息', false).then(() => {
+						uni.navigateBack({
+							delta: 1
+						})
+					})
+				})
+			},
+			handleInput(num) {
+				if (this.orderAmount.length > 12) {
+					return
+				}
+				this.orderAmount = this.orderAmount + num
+			},
+			handleDelete() {
+				if (this.$isEmpty(this.orderAmount)) {
+					return
+				}
+				this.orderAmount = this.orderAmount.substr(0, this.orderAmount.length - 1)
+			},
+			jumpLDT() {
+				location.href = "weixin://dl/business/?t=X2CyIQDbgtm"
+			},
+			async payOfh5() {
+				let expireTime=this.$dateTime.getExpireTime(5)
+				let params={
+					money:this.orderAmount,
+					shopId:this.shopId,
+					billsTitle:'用户微信扫码支付',
+					expireTime
+				}
+				let resp=await this.$api.loginUser.payBeforeForNormal(params)
+				let payObj={
+					orderType:this.$global.orderType.USER_PAY,
+					orderId:resp.data.id
+				}
+				let res=await this.$api.pay.payOrderOfscanCode(payObj)
+				if (!this.$isEmpty(res.data.qrCodeUrl)) {
+					location.href=res.data.qrCodeUrl
+				}
+				this.$u.toast('支付失败')
+			},
+			async pay() {
+				if (this.$isEmpty(this.orderAmount)) {
+					this.$u.toast('请输入交易金额')
+					return
+				}
+				// #ifdef  H5
+				this.modalShow = true
+				// #endif
+
+				// #ifdef MP-WEIXIN
+				let flag=false
+				if (flag) {
+					//可以足额支付
+					this.payModalShow=true
+				}else{
+					//积分不足额支付,调易宝支付
+					this.toWXPay()
+				}
+				// #endif
+			},
+			async toWXPay(){
+				let expireTime = this.$dateTime.getExpireTime(5)
+				let params = {
+					shopId: this.shopId,
+					loginUserId: this.vuex_userId,
+					money: this.orderAmount,
+					billsTitle: '用户支付',
+					expireTime,
+					appId: this.$global.wxParams.APPID,
+					openId: this.$cache.get('userInfo').openId,
+					type: 1 //type: 1-用户扫商户收款码支付 2-商户扫用户付款码支付
+				}
+				let resp = await this.$api.loginUser.payBefore(params)
+				if (!resp.success) {
+					this.$u.toast(resp.msg)
+					return
+				}
+				let obj = {
+					orderType: this.$global.orderType.USER_PAY,
+					orderId: resp.data.id,
+					payStatus: this.$global.payStatus.IS_WAIT
+				}
+				let res = await this.$api.pay.payOrder(obj)
+				let prePayTn = JSON.parse(res.data.prePayTn)
+				await this.$mpi.requestPayment(prePayTn)
+				uni.navigateTo({
+					url: "/pages/checkstand/order-res?orderId=" + resp.data.id
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.check-panel {
+		.buyer-logo {
+			width: 130rpx;
+			height: 130rpx;
+			margin-top: 50rpx;
+			margin-left: calc(50% - 65rpx);
+			border-radius: 50%;
+		}
+
+		.title {
+			font-weight: 800;
+			height: 70rpx;
+			letter-spacing: 3rpx;
+			color: #5D5D5D;
+		}
+
+		.input-content {
+			margin-top: 50rpx;
+			padding: 50rpx;
+			background-color: #FFFFFF;
+			width: 100%;
+			border-radius: 25rpx 25rpx 0 0;
+
+			.tips {
+				height: 100rpx;
+				font-size: 30rpx;
+				display: flex;
+				justify-content: left;
+				align-items: center;
+			}
+
+			.input-bar {
+				height: 150rpx;
+				border-bottom: 1rpx solid #DDDDDD;
+
+				.icon {
+					width: 15%;
+					font-size: 70rpx;
+					font-weight: 900;
+					height: 100%;
+				}
+
+				.input {
+					width: 85%;
+					height: 100%;
+					overflow: hidden;
+					font-size: 70rpx;
+				}
+
+				.cusor {
+					width: 2rpx;
+					height: 80%;
+					background-color: #FD711B;
+					animation: blink 1500ms infinite ease-in-out;
+				}
+			}
+		}
+	}
+
+	.bottom-line {
+		position: absolute;
+		bottom: 50rpx;
+		left: 0;
+		width: 100%;
+		color: #dddddd;
+	}
+
+	@keyframes blink {
+		from {
+			opacity: 0;
+		}
+	}
+</style>

BIN
static/icon/backspace.png


BIN
static/icon/del.png