322 lines
11 KiB
Vue
322 lines
11 KiB
Vue
<template>
|
||
<view class="waper">
|
||
<u-navbar :autoBack="true" :placeholder="true" bgColor="#FFFFFF">
|
||
<view slot='center' style="font-size: 36rpx; font-weight: bold;">
|
||
提交订单
|
||
</view>
|
||
</u-navbar>
|
||
<view class="content">
|
||
<view class="order">
|
||
<view class="residue">
|
||
<view class="label">支付剩余时间</view>
|
||
<view class="time">{{secondsToTime(timeNum)}}</view>
|
||
</view>
|
||
<view class="price">
|
||
<text class="unit">¥</text>{{detail.totalAmount}}
|
||
</view>
|
||
<view class="specs">
|
||
<view class="tags_box">
|
||
<view class="tag" v-if="detail.roomClassifyName">{{detail.roomClassifyName}}</view>
|
||
<view class="tag" v-if="detail.roomQuantity">{{detail.roomQuantity}}间</view>
|
||
<view class="tag" v-if="detail.inDateTime">{{detail.inDateTime}}入住</view>
|
||
</view>
|
||
<view class="detailed" @click="showPopupDetailed = true">
|
||
<text>订单明细</text>
|
||
<u-icon name="arrow-right" color="#03AE80" size="28rpx"></u-icon>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="pay">
|
||
<view class="item" v-for="(item, index) in payList" :key="index" v-if="getiPass(item)" @click="changePay(item.dictValue)">
|
||
<image :src="'../../static/image/mine/pay' + (item.paymentScene == 'WECHAT_MINI_PROGRAM' ? '2' : item.dictValue) + '.png'" mode=""></image>
|
||
<view class="title">{{item.paymentScene == 'WECHAT_MINI_PROGRAM' ? '微信' : item.dictLabel}}
|
||
<text class="balance" v-if="item.dictValue == 7">(可用¥{{cardInfo.balance}})</text>
|
||
</view>
|
||
<view class="noChange" v-if="payType != item.dictValue"></view>
|
||
<view class="isChange" v-if="payType == item.dictValue">
|
||
<u-icon name="checkmark" color="#fff" size="28rpx"></u-icon>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="footer" :style="'padding-bottom: ' + windowBottom + 'px;'">
|
||
<view class="btn" @click="confirmPay">确认支付</view>
|
||
</view>
|
||
<u-popup :show="showPopupDetailed" :round="10" mode="bottom">
|
||
<view class="detailed_con">
|
||
<view class="head">
|
||
<view class="title">明细</view>
|
||
<view class="close" @click="showPopupDetailed = false">
|
||
<u-icon name="close" color="#000000" size="36rpx" />
|
||
</view>
|
||
</view>
|
||
<view class="add">
|
||
<view class="label">订单合计</view>
|
||
<view class="all">共<text>¥{{detail.totalAmount}}</text></view>
|
||
</view>
|
||
<view class="row">
|
||
<view class="col">
|
||
<view class="key">房费 </view>
|
||
<view class="value">¥{{detail.totalAmount}}</view>
|
||
</view>
|
||
<view class="col" v-for="(item, index) in detail.roomChargeDetails" :key="index">
|
||
<view class="key">{{item.stayDate}}</view>
|
||
<view class="value">{{item.roomQuantity}}x ¥{{item.roomPrice}}</view>
|
||
</view>
|
||
<view class="col" v-if="detail.stayType !== 'HOURLY'">
|
||
<view class="key">{{detail.outDateTime}}</view>
|
||
<view class="value"></view>
|
||
</view>
|
||
</view>
|
||
<view class="footer" :style="'padding-bottom: ' + windowBottom + 'px;'">
|
||
<view class="btn" @click="confirmPay">确认支付</view>
|
||
</view>
|
||
</view>
|
||
</u-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data () {
|
||
return {
|
||
windowBottom: 0,
|
||
id: '',
|
||
hotelId: '',
|
||
detail: {},
|
||
timeNum: 0,
|
||
timer: null,
|
||
payList: [],
|
||
payType: null,
|
||
cardInfo: null,
|
||
showPopupDetailed: false,
|
||
configData: null,
|
||
source: ''
|
||
}
|
||
},
|
||
onLoad (options) {
|
||
this.id = options.id;
|
||
this.hotelId = options.hotelId;
|
||
this.source = options.source;
|
||
this.getDetail();
|
||
this.windowBottom = this.$safeAreaBottom || uni.upx2px(13);
|
||
},
|
||
onUnload () {
|
||
clearInterval(this.timer);
|
||
this.timer = null;
|
||
},
|
||
methods: {
|
||
async getDetail() {
|
||
let res=await this.$http.hotelOrderDetail(this.id);
|
||
res.data.inDateTime = this.$moment(res.data.inDateTime).format("MM月DD日");
|
||
res.data.outDateTime = this.$moment(res.data.outDateTime).format("YYYY-MM-DD");
|
||
this.detail=res.data;
|
||
|
||
this.configData = uni.getStorageSync('configData');
|
||
let creaetdTime = parseInt(new Date(res.data.createTime).getTime() / 1000);
|
||
let nowtime = parseInt(new Date().getTime() / 1000);
|
||
if ((creaetdTime + this.configData.expirationTime * 60) >= nowtime) {
|
||
this.timeNum = (creaetdTime + this.configData.expirationTime * 60) - nowtime;
|
||
this.setIntervalFn()
|
||
}
|
||
|
||
this.payList = this.configData.payConfig;
|
||
if (this.payList.length) {
|
||
this.payType = this.payList[0].dictValue;
|
||
}
|
||
let cardInfo = await this.$http.getPrepaidCard();
|
||
this.cardInfo = cardInfo.data;
|
||
},
|
||
secondsToTime(seconds) {
|
||
const minutes = Math.floor((seconds % 3600) / 60);
|
||
const remainingSeconds = seconds % 60;
|
||
return (minutes >= 10 ? minutes : '0' + minutes) + ":" + (remainingSeconds >= 10 ? remainingSeconds : '0' + remainingSeconds);
|
||
},
|
||
setIntervalFn () {
|
||
clearInterval(this.timer);
|
||
this.timer = setInterval(() => {
|
||
if (this.timeNum <= 0) {
|
||
clearInterval(this.timer)
|
||
uni.redirectTo({ url: `/pages/hotelOrder/detail?id=` + this.detail.id });
|
||
}
|
||
this.timeNum --;
|
||
}, 1000)
|
||
},
|
||
changePay(e) {
|
||
this.payType = e;
|
||
},
|
||
getiPass(e) {
|
||
if (e.dictValue != 7) {
|
||
return true;
|
||
} else {
|
||
if (this.cardInfo) {
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
},
|
||
async confirmPay() {
|
||
uni.showLoading({ mask: true });
|
||
let parmas = {};
|
||
parmas.id = this.detail.id;
|
||
parmas.paymentMethod = this.payType;
|
||
if (this.detail.totalAmount <= 0) {
|
||
parmas.paymentMethod = '4';
|
||
}
|
||
parmas.paymentScene = null;
|
||
let f = this.payList.find(m => m.dictValue == parmas.paymentMethod);
|
||
if (f) parmas.paymentScene = f.paymentScene;
|
||
parmas.authCode = this.cardInfo ? this.cardInfo.accountNo : '';
|
||
let info = await this.$http.hotelPayment(parmas);
|
||
|
||
if (parmas.paymentMethod == '7') {
|
||
uni.hideLoading();
|
||
if (info.data.errorMessage) {
|
||
uni.showToast({ mask: true, title: info.data.errorMessage, icon: 'none' })
|
||
setTimeout(() => {
|
||
this.goPage();
|
||
}, 1500)
|
||
} else {
|
||
uni.showToast({ mask: true, title: '支付成功', icon: 'success' })
|
||
setTimeout(() => {
|
||
uni.redirectTo({ url: `/pages/hotel/paySuccess?id=${this.id}&hotelId=${this.hotelId}&source=${this.source}` })
|
||
}, 1500)
|
||
}
|
||
return false;
|
||
}
|
||
if (info.data.payUrl) {
|
||
uni.hideLoading();
|
||
let str = info.data.payUrl;
|
||
let newStr = str.replace("?", "&");
|
||
uni.showToast({ mask: true, title: '小程序不支持此支付方式', icon: 'none' })
|
||
} else if (info.data.tradeSession) {
|
||
const prepayId = JSON.parse(info.data.tradeSession);
|
||
uni.requestPayment({
|
||
provider: 'wxpay',
|
||
timeStamp: prepayId.timeStamp,
|
||
nonceStr: prepayId.nonceStr,
|
||
package: prepayId.packageValue,
|
||
signType: prepayId.signType,
|
||
paySign: prepayId.paySign,
|
||
success: (res) => {
|
||
uni.hideLoading();
|
||
uni.showToast({ mask: true, title: '支付成功', icon: 'success' })
|
||
setTimeout(() => {
|
||
uni.redirectTo({ url: `/pages/hotel/paySuccess?id=${this.id}&hotelId=${this.hotelId}&source=${this.source}` })
|
||
}, 1500)
|
||
},
|
||
fail: (err) => {
|
||
uni.hideLoading();
|
||
uni.showToast({ mask: true, title: '支付取消', icon: 'none' })
|
||
setTimeout(() => {
|
||
this.goPage();
|
||
}, 1500)
|
||
}
|
||
});
|
||
} else {
|
||
uni.showToast({ mask: true, title: '支付失败', icon: 'none' });
|
||
}
|
||
},
|
||
goPage() {
|
||
if (this.source == 'order') {
|
||
uni.navigateBack();
|
||
} else {
|
||
uni.redirectTo({ url: `/pages/hotelOrder/detail?id=${this.id}` });
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.waper { min-height: 100vh; background-color: #F6F6F6; }
|
||
.content{
|
||
width: 100%; box-sizing: border-box; padding: 24rpx;
|
||
.order {
|
||
background: #FFFFFF; border-radius: 10rpx; padding: 32rpx 24rpx; box-sizing: border-box;
|
||
.residue {
|
||
display: flex; align-items: center;
|
||
.label { font-size: 28rpx; color: rgba(0,0,0,0.45); margin-right: 10rpx; }
|
||
.time { font-weight: 500; font-size: 32rpx; color: rgba(0,0,0,0.85); }
|
||
}
|
||
.price {
|
||
margin: 12rpx 0 0 3rpx; font-weight: bold; font-size: 56rpx; color: #E54042;
|
||
.unit { font-weight: 400; font-size: 28rpx; }
|
||
}
|
||
.specs {
|
||
display: flex; align-items: center; justify-content: space-between; margin-top: 12rpx;
|
||
.tags_box {
|
||
display: flex; align-items: center; flex-wrap: wrap; flex: 1;
|
||
.tag {
|
||
padding: 0 18rpx; position: relative; font-size: 28rpx; color: rgba(0,0,0,0.45);
|
||
&::after{ content: ""; width: 1rpx; height: 23rpx; background: #ECEAEA; position: absolute; right: 0; top: 50%; transform: translateY(-50%); }
|
||
&:first-child { padding-left: 0; }
|
||
&:last-child {
|
||
padding-right: 0;
|
||
&::after {display: none;}
|
||
}
|
||
}
|
||
}
|
||
.detailed {
|
||
display: flex; align-items: center; width: 140rpx;
|
||
text { font-size: 24rpx; color: #03AE80; margin-right: 4rpx; }
|
||
}
|
||
}
|
||
}
|
||
.pay {
|
||
background: #FFFFFF; border-radius: 10rpx; margin-top: 32rpx; padding: 0 24rpx; box-sizing: border-box;
|
||
.item {
|
||
height: 112rpx; border-bottom: 1rpx solid #E8E8E8; display: flex; align-items: center;
|
||
&:last-child { border-bottom: none; }
|
||
image { width: 48rpx; height: 48rpx; margin-right: 16rpx; }
|
||
.title {
|
||
flex: 1; font-size: 30rpx; color: rgba(0,0,0,0.85);
|
||
.balance { font-size: 28rpx; color: rgba(0,0,0,0.45); }
|
||
}
|
||
.noChange { width: 42rpx; height: 42rpx; border-radius: 50%; border: 1rpx solid rgba(0,0,0,0.2); }
|
||
.isChange {
|
||
width: 42rpx; height: 42rpx; border-radius: 50%; background-color: #03AE80; position: relative;
|
||
::v-deep .u-icon {
|
||
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.footer {
|
||
width: 100%; background: #FFFFFF; padding-top: 13rpx; box-sizing: border-box; position: fixed; left: 0; bottom: 0; display: flex; align-items: center; justify-content: center;
|
||
.btn { width: 654rpx; height: 90rpx; background: #03AE80; border-radius: 49rpx; line-height: 90rpx; text-align: center; font-weight: 500; font-size: 32rpx; color: #FFFFFF; }
|
||
}
|
||
.detailed_con {
|
||
padding: 32rpx 0 150rpx; position: relative;
|
||
.head {
|
||
position: relative; text-align: center; margin: 0 32rpx 30rpx;
|
||
.title { font-weight: 500; font-size: 34rpx; color: rgba(0,0,0,0.85); }
|
||
.close { position: absolute; right: 0; top: 50%; transform: translateY(-50%); }
|
||
}
|
||
.add {
|
||
padding: 54rpx 0 24rpx; margin: 0 32rpx; display: flex; align-items: center; justify-content: space-between; border-bottom: 1rpx solid #ECEAEA;
|
||
.label { font-size: 32rpx; color: rgba(0,0,0,0.85); }
|
||
.all {
|
||
font-size: 28rpx; color: rgba(0,0,0,0.85);
|
||
text { font-weight: bold; font-size: 28rpx; color: #E54042; }
|
||
}
|
||
}
|
||
.row {
|
||
padding: 0 32rpx;
|
||
.col {
|
||
display: flex; align-items: center; justify-content: space-between; margin-bottom: 8rpx;
|
||
&:first-child {
|
||
margin: 24rpx 0 13rpx;
|
||
.key, .value { font-weight: 500; font-size: 28rpx; color: rgba(0,0,0,0.85); }
|
||
}
|
||
.key, .value { font-size: 28rpx; color: rgba(0,0,0,0.65); }
|
||
}
|
||
}
|
||
.footer {
|
||
width: 100%; background: #FFFFFF; padding-top: 13rpx; box-sizing: border-box; position: fixed; left: 0; bottom: 0; display: flex; align-items: center; justify-content: center;
|
||
.btn { width: 654rpx; height: 90rpx; background: #03AE80; border-radius: 49rpx; line-height: 90rpx; text-align: center; font-weight: 500; font-size: 32rpx; color: #FFFFFF; }
|
||
}
|
||
}
|
||
</style> |