Files
zhwl-miniapp/pages/hotelOrder/list.vue
2025-06-26 12:38:35 +08:00

273 lines
10 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="waper">
<u-navbar :autoBack="true" bgColor="#FFFFFF">
<view slot='center' style="font-size: 36rpx; font-weight: bold;">
酒店订单
</view>
</u-navbar>
<view class="menu" :style="'top: ' + navHeight + 'px;'">
<view v-for="(i, index) in menu" :key="index" :class="{ active: menuIndex == index }" @click="tabMenu(index)">{{i.name}}</view>
</view>
<mescroll-body @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption" :top="paddingTop + 'px'">
<view class="content">
<navigator hover-class="none" class="item" v-for="(item, index) in list" :key="index" :url="'/pages/hotelOrder/detail?id=' + item.id">
<view class="title">
<view class="name">{{item.hotelHomestayName}}</view>
<view class="label" v-if="item.refundStatus == '1'">审核中</view>
<view class="label" v-if="item.refundStatus == '100'">已驳回</view>
<view class="label" v-if="item.refundStatus == '2'"><text>退款中</text></view>
<view class="label" v-if="item.refundStatus == '200'">退款成功</view>
<view class="label" v-if="item.refundStatus == '4'">退款失败</view>
<view class="label" v-if="(!item.refundStatus && item.stayStatus == 'BOOKED')">待入住</view>
<view class="label" v-if="item.stayStatus == 'CHECKED_IN'">已入住</view>
<view class="label" v-if="item.stayStatus == 'CHECKED_OUT'">已完成</view>
<view class="label" v-if="(item.stayStatus == 'CANCELED' || item.paymentType == '1') && !item.refundStatus">已取消</view>
<view class="label" v-if="item.paymentType == '0' && item.countDownTime">待付款剩余<text>{{item.countDownTime}}</text></view>
<view class="label" v-if="item.paymentType == '2'">已关闭</view>
</view>
<view class="con">
<image class="img" :src="$utils.setImgUrl(item.zdyHotelHomestayVO.coverImage)" mode=""></image>
<view class="row">
<view>{{item.roomQuantity}}{{item.roomClassifyName}}</view>
<view>{{item.inDateTime.split(' ')[0]}} {{item.outDateTime.split(' ')[0]}}</view>
<view>总价¥{{item.totalAmount}}</view>
</view>
</view>
<view class="btn_box">
<view class="btn pay" v-if="item.refundStatus && item.refundStatus != '200'" @click.stop="refund(item.id)">退款进度</view>
<view class="btn" v-if="item.refundStatus == '200' || item.paymentType == '2' || (item.stayStatus && item.stayStatus != 'BOOKED') || item.paymentType == '1' || (item.paymentType == '0' && !item.countDownTime)" @click.stop="reserve(item.hotelHomestayId)">再次预定</view>
<view class="btn" v-if="(!item.refundStatus && item.stayStatus == 'BOOKED')" @click.stop="contact(item.zdyHotelHomestayVO)">联系酒店</view>
<view class="btn" v-if="(!item.refundStatus && item.stayStatus == 'BOOKED')" @click.stop="openLocation(item.zdyHotelHomestayVO)">酒店导航</view>
<view class="btn" v-if="item.paymentType == '0' && item.countDownTime" @click.stop="cancel(item.id)">取消订单</view>
<view class="btn pay" v-if="item.paymentType == '0' && item.countDownTime" @click.stop="goPay(item)">立即支付</view>
</view>
</navigator>
</view>
</mescroll-body>
<u-popup :show="showPopupDelete" :round="10" mode="center">
<view class="delete_con">
<view class="title">确认取消</view>
<view class="tips">取消后将无法恢复</view>
<view class="btn-box">
<view class="btn cancel" @click="cancellation">取消</view>
<view class="btn confirm" @click="confirmCancel">确认</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
export default {
mixins: [MescrollMixin],
data () {
return {
menu: [
{ name: '全部', key: '' },
{ name: '待付款', key: '1' },
{ name: '待入住', key: '2' },
{ name: '退款', key: '3' }
],
list: [],
menuIndex: 0,
configData: null,
downOption: { auto: false },
navHeight: 0,
paddingTop: 0,
cancelId: '',
showPopupDelete: false
}
},
onShow () {
this.mescroll && this.mescroll.resetUpScroll();
},
onLoad (options) {
this.configData = uni.getStorageSync('configData');
this.navHeight = this.$paddingTop;
this.paddingTop = this.$paddingTop + uni.upx2px(90);
},
onUnload () {
this.list.forEach(e => {
clearInterval(e.timer);
e.timer = null;
})
},
methods: {
async upCallback(page) {
let obj = { pageNum: page.num, pageSize: page.size };
let info = null;
if (this.menuIndex !== '') {
switch (this.menuIndex) {
case 1:
obj.paymentType = 0;
break;
case 2:
obj.stayStatus = 'BOOKED';
break;
case 3:
obj.queryRefundAll = true;
break;
}
}
info = await this.$http.hotelOrderList(obj);
if(page.num == 1) this.list = [];
this.list = this.list.concat(info.rows);
this.mescroll.endBySize(info.rows.length, info.total);
// 给数据每一项增加倒计时,循环调用计时
if (this.list.length > 0) {
for (const i in this.list) {
if (this.list[i].paymentType == '0') {
this.beginTimer(i);
}
}
}
},
// 开始计时
beginTimer(i) {
const that = this;
// 拿到数据每一项
const item = that.list[i];
// 给每一个参数增加时间
item.timer = setInterval(() => {
// 判断是否已结束计时,结束清除定时操作
if (that.countDown(item.createTime, this.configData.expirationTime) === '倒计时结束') {
item.countDownTime = '';
clearInterval(item.timer);
item.paymentType = '2';
} else {
// 自定义字段,给数据赋值,倒计时
that.$set(item,'countDownTime',that.countDown(item.createTime, this.configData.expirationTime));
}
}, 1000)
},
// 计算距离操作的过期时间
countDown(time, val2) {
let now = new Date(time) // 处理开始时间
let minutes = Number(val2) // 处理输入的过期时间
// 计算最后时间
let end = now.setMinutes(now.getMinutes() + minutes)
// 当前时间
let time_now = new Date().getTime()
// 最后时间-当前时间
let msec = end - time_now
if (msec > 0) {
let min = parseInt((msec / 1000 / 60) % 60);
let sec = parseInt((msec / 1000) % 60);
// 补零操作
min = min > 9 ? min : '0' + min;
sec = sec > 9 ? sec : '0' + sec;
return `${min}:${sec}`;
} else {
return '倒计时结束';
}
},
tabMenu(i) {
this.menuIndex = i;
this.list = [];
this.mescroll.resetUpScroll();
},
// 退款进度
refund(id) {
uni.navigateTo({ url: `/pages/hotelOrder/refundProgress?id=${id}` });
},
reserve(id) {
uni.navigateTo({ url: `/pages/hotel/detail?id=${id}` });
},
cancel(id) {
this.cancelId = id;
this.showPopupDelete = true;
},
cancellation() {
this.cancelId = '';
this.showPopupDelete = false;
},
async confirmCancel() {
let params = {
orderId: this.cancelId
}
let info = await this.$http.hotelOrderCancel(params);
this.cancellation();
this.list = [];
this.mescroll.resetUpScroll();
},
contact(e) {
uni.makePhoneCall({ phoneNumber: e.phone, fail: () => {} });
},
openLocation(e) {
if (e.latitude && e.longitude) {
let latitude = e.latitude;
let longitude = e.longitude;
uni.openLocation({
latitude: Number(latitude),
longitude: Number(longitude),
name: e.name,
address: e.address,
})
}
},
goPay(e) {
uni.navigateTo({ url: `/pages/hotel/submitOrder?id=${e.id}&hotelId=${e.hotelHomestayId}&source=order` })
}
}
}
</script>
<style lang="scss">
.waper { min-height: 100vh; background-color: #F6F6F6; }
.menu{
width: 100%; height: 94rpx; position: fixed; left: 0; box-sizing: border-box; padding: 0 32rpx; display: flex; justify-content: space-between; align-items: center; background-color: #fff; z-index: 11;
view{
font-size: 32rpx; color: #333; line-height: 46rpx; height: 46rpx;
&.active{
position: relative; font-weight: 500; color: #03AE80;
&::after{ content: ""; width: 30rpx; height: 4rpx; background: #03AE80; border-radius: 12rpx; position: absolute; left: 50%; transform: translateX(-50%); top: 62rpx; }
}
}
}
.content {
width: 100%; padding: 24rpx; box-sizing: border-box;
.item {
background: #FFFFFF; border-radius: 10rpx; padding: 32rpx 24rpx; box-sizing: border-box; margin-bottom: 20rpx;
.title {
display: flex; justify-content: space-between;
.name { font-weight: 500; font-size: 36rpx; color: #000000; }
.label {
font-size: 28rpx; color: rgba(0,0,0,0.45);
text { color: #E54042; }
}
}
.con {
display: flex; align-items: center; margin-top: 24rpx;
.img { width: 138rpx; height: 138rpx; margin-right: 24rpx; border-radius: 8rpx; }
.row {
flex: 1;
view {
font-size: 28rpx; color: rgba(0,0,0,0.65); margin-bottom: 4rpx;
&:last-child { margin-bottom: 0; }
}
}
}
.btn_box {
display: flex; align-items: center; justify-content: flex-end; margin-top: 24rpx;
.btn {
width: 160rpx; height: 64rpx; border-radius: 51rpx; line-height: 64rpx; text-align: center; font-size: 28rpx; margin-right: 20rpx; border: 1rpx solid rgba(0,0,0,0.45); color: rgba(0,0,0,0.45);
&:last-child { margin-right: 0; }
}
.pay { border: 1rpx solid #E54042; color: #E54042; }
}
}
}
.delete_con {
width: 596rpx; height: 398rpx; background: linear-gradient( 360deg, rgba(71,175,195,0) 0%, rgba(71,175,195,0.3) 100%); border-radius: 20rpx; padding: 64rpx 46rpx; box-sizing: border-box; text-align: center;
.title { font-weight: 500; font-size: 40rpx; color: rgba(0,0,0,0.85); }
.tips { font-size: 28rpx; color: rgba(0,0,0,0.65); margin-top: 24rpx; }
.btn-box {
margin-top: 64rpx; display: flex; align-items: center; justify-content: space-between;
.btn { width: 240rpx; height: 80rpx; line-height: 80rpx; text-align: center; border-radius: 66rpx; font-size: 30rpx; }
.cancel { border: 1rpx solid rgba(0,0,0,0.45); color: rgba(0,0,0,0.45); }
.confirm { color: #FFFFFF; background: #03AE80; }
}
}
</style>