zhwl-miniapp/pages/my/refund.vue
2025-06-26 12:38:35 +08:00

545 lines
19 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="uni-container">
<u-navbar :autoBack="true" left-icon-color="#fff" :placeholder="true" bgColor="#03AE80">
<view slot='center' style="font-size: 36rpx; font-weight: 500; color: #fff;">申请退款</view>
</u-navbar>
<view class="banner"></view>
<view class="waper_box" v-if="detail">
<view class="sum-box">
<view class="handle">
<view class="label">{{detail.orderItemList[0].ticketName}}</view>
<view class="price"><text class="unit">¥</text>{{detail.orderItemList[0].totalPrice}}</view>
</view>
<view class="box">
<view class="validity-box">
<view class="validity" v-if="detail.orderItemList[0].ticketOrderDetailList.length">有效期:
<text v-if="detail.orderItemList[0].ticketValidityPeriod == '1'">
<text class="date">{{detail.orderItemList[0].ticketOrderDetailList[0].availableEndTime.split(" ")[0]}}</text>当天有效
</text>
<text v-if="detail.orderItemList[0].ticketValidityPeriod == '2'">
<text class="date">{{detail.orderItemList[0].ticketOrderDetailList[0].availableEndTime.split(" ")[0]}}</text>之前有效
</text>
<text v-if="detail.orderItemList[0].ticketValidityPeriod == '3'">
<text class="date">{{detail.orderItemList[0].validityStartTime}}</text>至
<text class="date">{{detail.orderItemList[0].validityEndTime}}</text>有效
</text>
<text v-if="detail.orderItemList[0].ticketValidityPeriod == '4'">
激活后<text class="date">{{detail.orderItemList[0].buyPeriodDay}}</text>天有效
</text>
</view>
</view>
</view>
<view class="time">订单数量:¥{{detail.orderItemList[0].ticketOrderDetailList[0].ticketPrice}} x{{detail.orderItemList[0].ticketOrderDetailList.length}}</view>
</view>
<view class="refundNum">
<view class="row">
<view class="label1">可退款数量</view>
<view class="num">{{ticketOrderDetailList.length}}张</view>
</view>
<view class="row row1" v-if="detail.orderItemList[0].qrcodeRule == 2">
<view class="label2">退款数量</view>
<u-number-box :min="1" :max="ticketOrderDetailList.length" :step="1" v-model="buyNum" @change="buyNumChange"></u-number-box>
</view>
</view>
<view class="tourist-box" v-if="detail.orderItemList[0].qrcodeRule == 1">
<view class="label">可退游客</view>
<u-checkbox-group
v-model="touristChecked"
iconPlacement="right"
placement="row"
@change="checkboxChange1">
<u-checkbox activeColor="#01be69" :label="item.userName + ' ' + item.identityCard" :name="item.id" v-for="(item, index) in ticketOrderDetailList" :key="index"></u-checkbox>
</u-checkbox-group>
</view>
<view class="price-box">
<view class="box1">
<view class="label">可退金额</view>
<view class="price"><text class="unit">¥</text>{{refundAmount.toFixed(2)}}</view>
</view>
<view class="box1">
<view class="label1">手续费</view>
<view class="price1">¥{{serviceCharge}}</view>
</view>
</view>
<view class="tourist-box">
<view class="label">个人原因</view>
<u-checkbox-group
v-model="personChecked"
iconPlacement="right"
placement="row"
@change="checkboxChange2">
<u-checkbox activeColor="#01be69" :label="item.dictLabel" :name="item.dictValue" v-for="(item, index) in personalRefundList" :key="index"></u-checkbox>
</u-checkbox-group>
</view>
<view class="tourist-box">
<view class="label">商家/景区原因</view>
<u-checkbox-group
v-model="merchantChecked"
iconPlacement="right"
placement="row"
@change="checkboxChange3">
<u-checkbox activeColor="#01be69" :label="item.dictLabel" :name="item.dictValue" v-for="(item, index) in businessRefundList" :key="index"></u-checkbox>
</u-checkbox-group>
</view>
<view class="bottom" :style="'padding-bottom: ' + safeAreaBottom + 'px'">
<view class="bottom_waper">
<view class="active" @click="goRefund">申请退款</view>
</view>
</view>
</view>
<uni-popup class="popupRefund" ref="popup" background-color="#fff">
<view class="popup-content">
<image class="bgImg" src="https://common/refundPopup.png" mode=""></image>
<view class="con">
<view class="title">温馨提示</view>
<view class="text">一旦提交将无法撤销确定退款吗</view>
<view class="btn-box">
<view class="close" @click="close">取消</view>
<view class="save" @click="onRefund">确认</view>
</view>
</view>
</view>
</uni-popup>
<u-toast ref="uToast"></u-toast>
</view>
</template>
<script>
export default {
data() {
return {
id: '',
windowBottom: 0,
safeAreaBottom: 0,
bgColor: '#FBFBFB',
detail: null,
buyNum: 1,
refundAmount: 0,
serviceCharge: 0,
ticketOrderDetailList: [],
touristChecked: [],
personalRefundList: [],
personChecked: [],
businessRefundList: [],
merchantChecked: [],
};
},
onLoad(options) {
this.id = options.id
this.windowBottom = this.$safeAreaBottom + uni.upx2px(152);
this.safeAreaBottom = this.$safeAreaBottom || uni.upx2px(10);
this.getData()
this.commonSj()
this.commonGr()
},
methods: {
async getData() {
let info = await this.$http.getTicketOrderDetailPrepay(this.id);
this.detail = info.data;
let list = []
info.data.orderItemList[0].ticketOrderDetailList.forEach((item) => {
// 判断是否可退款
if (this.detail.orderItemList[0].refundRule != '0' && item.paymentType == '200' && item.verificationType == '0' && (item.refundStatus == '0' || item.refundStatus == '100')) {
let creaetd = parseInt(new Date(this.$utils.formatDate('Y-M-D', item.paymentTime) + ' 00:00:00').getTime() / 1000);
if (this.detail.orderItemList[0].classify == '1') {// 普通票
// 判断是否再有效期
switch (this.detail.orderItemList[0].refundRule) {
case '3':// 有效期可退
// let startTime = parseInt(new Date(this.$utils.formatDate('Y-M-D', this.detail.orderItemList[0].ticketOrderDetailList[0].availableStartTime) + ' 00:00:00').getTime() / 1000);
let endTime = parseInt(new Date(this.$utils.formatDate('Y-M-D', this.detail.orderItemList[0].ticketOrderDetailList[0].availableEndTime) + ' 23:59:59').getTime() / 1000);
let nowtime = parseInt(new Date().getTime() / 1000);
// 当前日期大于等于开始时间并且当前日期小于等于结束时间,门票可退
if (nowtime <= endTime) list.push(item);
break;
case '4':// 几天内可退
let nowdate = parseInt(new Date().getTime() / 1000);
// 当前时间减下单时间如果小于等于后台设定天数。门票可退
if (((nowdate - creaetd) / 60 / 60 / 24) <= this.detail.orderItemList[0].refundDay) list.push(item);
break;
}
} else if (this.detail.orderItemList[0].classify == '2') {// 套票
let num = 0;// 大于0代表已经使用过
// 判断是否再有效期
switch (this.detail.orderItemList[0].refundRule) {
case '3':// 有效期可退
item.orderDetailChildList.forEach((child, childIndex) => {
if (child.verificationNum > 0) num ++;
})
if (num == 0) {
// let startTime = parseInt(new Date(this.$utils.formatDate('Y-M-D', this.detail.orderItemList[0].ticketOrderDetailList[0].availableStartTime) + ' 00:00:00').getTime() / 1000);
let endTime = parseInt(new Date(this.$utils.formatDate('Y-M-D', this.detail.orderItemList[0].ticketOrderDetailList[0].availableEndTime) + ' 23:59:59').getTime() / 1000);
let nowtime = parseInt(new Date().getTime() / 1000);
// 当前日期大于等于开始时间并且当前日期小于等于结束时间,门票可退
if (nowtime <= endTime) list.push(item);
}
break;
case '4':// 几天内可退
item.orderDetailChildList.forEach((child, childIndex) => {
if (child.verificationNum > 0) num ++;
})
if (num == 0) {
let nowdate = parseInt(new Date().getTime() / 1000);
// 当前时间减下单时间如果小于等于后台设定天数。门票可退
if (((nowdate - creaetd) / 60 / 60 / 24) <= this.detail.orderItemList[0].refundDay) list.push(item);
}
break;
}
} else if (this.detail.orderItemList[0].classify == '4' || this.detail.orderItemList[0].classify == '5') {// 年卡
if (item.activationStatus == 0) list.push(item);
}
}
})
if (!list.length) {
uni.showToast({ title: '当前没有可退门票', icon: 'none', mask: true })
setTimeout(() => {
uni.navigateBack()
}, 1500)
return false;
}
this.ticketOrderDetailList = list
if (this.ticketOrderDetailList.length === 1 && !this.touristChecked.length) {
this.touristChecked = [this.ticketOrderDetailList[0].id]
}
this.calculateFee()
console.log('可退门票:')
console.log(list)
},
async commonSj() {
const params = { dictType: 'business_refund_type' }
let info = await this.$http.common(params)
if (info.code === 200) {
this.businessRefundList = info.data
} else {
uni.$u.toast(info.msg);
}
},
async commonGr() {
const params = { dictType: 'personal_refund_type' }
let info = await this.$http.common(params)
this.personalRefundList = info.data
},
async calculateFee() {
let num = 0;
if (this.detail.orderItemList[0].qrcodeRule == 1) {
num = this.touristChecked.length
} else {
num = this.buyNum
}
if (this.detail.orderItemList[0].isFee == 1) {
let availableEndTime = this.detail.orderItemList[0].ticketOrderDetailList[0].availableEndTime + ' 23:59:59';
const params = {
orderItemId: this.detail.orderItemList[0].id,
sale: this.detail.orderItemList[0].ticketOrderDetailList[0].ticketPrice,
availableEndTime: availableEndTime,
num: num
}
let info = await this.$http.calculateFee(params)
if (info.code === 200) {
this.serviceCharge = info.data
this.refundAmount = params.num * this.detail.orderItemList[0].ticketOrderDetailList[0].ticketPrice - this.serviceCharge;
} else {
uni.$u.toast(info.msg);
}
} else {
this.refundAmount = num * this.detail.orderItemList[0].ticketOrderDetailList[0].ticketPrice;
}
},
buyNumChange (e) {
this.buyNum = e.value;
this.calculateFee();
},
checkboxChange1(n) {
this.touristChecked = n
this.calculateFee()
},
checkboxChange2(n) {
this.personChecked = n
},
checkboxChange3(n) {
this.merchantChecked = n
},
goRefund() {
if (this.detail.orderItemList[0].qrcodeRule == 1) {
if (!this.touristChecked.length) {
uni.showToast({ mask: true, title: '请选择游客', icon: 'none' });
return false;
}
} else {
if (!this.buyNum) {
uni.showToast({ mask: true, title: '请选择退款数量', icon: 'none' });
return false;
}
}
if (!this.personChecked.length && !this.merchantChecked.length) {
uni.showToast({ mask: true, title: '请选择退款原因', icon: 'none' });
return false;
}
this.$refs.popup.open('center')
},
close() {
this.$refs.popup.close()
},
async onRefund() {
let data = {
orderId: this.detail.id,
totalPrice: this.refundAmount,
userId: this.detail.userId,
userName: this.detail.userName,
personalRefundType: '',
businessRefundType: '',
orderItemList: [{
orderItemId: this.detail.orderItemList[0].id,
ticketOrderDetailList: []
}]
};
if (this.personChecked.length) data.personalRefundType = this.personChecked.join(',');
if (this.merchantChecked.length) data.businessRefundType = this.merchantChecked.join(',');
if (this.detail.orderItemList[0].qrcodeRule == '2') {
data.refundQuantity = this.buyNum;
data.orderItemList[0].refundQuantity = this.buyNum;
this.detail.orderItemList[0].ticketOrderDetailList.forEach(e => {
if (data.orderItemList[0].ticketOrderDetailList.length < this.buyNum) {
if (e.refundStatus == '0' || e.refundStatus == '100') {
data.orderItemList[0].ticketOrderDetailList.push({ orderDetailId: e.id })
}
}
})
} else {
data.refundQuantity = this.touristChecked.length;
data.orderItemList[0].refundQuantity = this.touristChecked.length;
this.touristChecked.forEach(e => {
data.orderItemList[0].ticketOrderDetailList.push({ orderDetailId: e })
})
}
let info = await this.$http.toRefund(data)
if (info.code === 200) {
this.close()
uni.showToast({ title: '提交成功', mask: true, icon: 'success' });
let pages = getCurrentPages();
let prevPage = pages[pages.length - 2];
setTimeout(() => {
uni.navigateBack()
prevPage.onLoad(prevPage.options);
}, 1500)
} else uni.showToast({ title: info.msg, mask: true, icon: 'none' });
},
}
}
</script>
<style lang="scss" scoped>
.uni-container {
width: 100%;
min-height: 100vh;
box-sizing: border-box;
background: #FBFBFB;
padding-bottom: 200rpx;
.banner{ width: 100%; height: 320rpx; background: #03AE80; position: absolute; left: 0; top: 0; }
.waper_box {
width: 100%; box-sizing: border-box; padding: 32rpx; position: relative; z-index: 3;
}
.sum-box {
padding: 32rpx 24rpx;
background: #FFFFFF;
border-radius: 10rpx;
.handle {
min-height: 54rpx; box-sizing: border-box; padding-right: 180rpx; position: relative;
.label {
font-weight: 500;
font-size: 32rpx;
color: #333333;
line-height: 54rpx;
}
.price {
position: absolute; right: 0; top: 0;
font-weight: bold;
font-size: 42rpx;
color: #FF5833;
.unit {
font-weight: 400;
font-size: 24rpx;
color: #FF5833;
}
}
}
.box {
margin-top: 35rpx;
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
.validity-box {
min-width: 400rpx;
.validity {
font-weight: 400;
font-size: 28rpx;
color: #666666;
.date {
color: #01BE69;
}
}
}
.num {
font-weight: 400;
font-size: 28rpx;
color: #999999;
text:first-child {
margin-right: 10rpx;
}
}
}
.time {
margin-top: 12rpx;
font-weight: 400;
font-size: 28rpx;
color: #666666;
}
}
.refundNum {
margin-top: 19rpx;
padding: 32rpx 24rpx;
background: #FFFFFF;
border-radius: 10rpx;
.row {
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
.label1 {
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.num {
font-weight: 400;
font-size: 28rpx;
color: #666666;
}
.label2 {
font-weight: 400;
font-size: 28rpx;
color: #666666;
}
/deep/.u-number-box{
width: 198rpx; height: 100%; border-radius: 50rpx; box-sizing: border-box; border: 2rpx solid #E1E1E1;
.u-number-box__input{ width: 66rpx; margin: 0; background: transparent !important; border: 2rpx solid #E1E1E1; box-sizing: border-box; border-top: 0; border-bottom: 0; }
.u-number-box__minus, .u-number-box__plus{
background: transparent !important; width: 64rpx; height: 100% !important; padding: 0 !important;
.u-icon__icon{ font-size: 20rpx !important; color: #01BE69 !important; }
}
.u-number-box__minus--disabled .u-icon__icon{ color: #c8c9cc !important; }
}
}
.row1 {
margin-top: 32rpx;
}
}
.tourist-box {
margin-top: 24rpx;
padding: 32rpx 24rpx;
background: #FFFFFF;
border-radius: 10rpx;
.label {
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.tourist-item {
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
margin-top: 30rpx;
&:first-child {
margin-top: 32rpx;
}
.name {
font-weight: 400;
font-size: 28rpx;
color: #666666;
}
}
/deep/.u-checkbox-group {
width: 100%;
flex-direction: column !important;
.u-checkbox {
width: 100%;
margin-top: 30rpx;
&:first-child {
margin-top: 32rpx;
}
.u-checkbox__icon-wrap + text {
font-weight: 400;
font-size: 28rpx !important;
color: #666666 !important;
}
}
}
}
.price-box {
margin-top: 24rpx;
padding: 32rpx 24rpx;
background: #FFFFFF;
border-radius: 10rpx;
.box1 {
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
&:last-child {
margin-top: 32rpx;
}
.label {
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.price {
font-weight: bold;
font-size: 42rpx;
color: #FF5833;
.unit {
font-weight: 400;
font-size: 24rpx;
color: #FF5833;
}
}
.label1, .price1 {
font-weight: 500;
font-size: 28rpx;
color: #999999;
}
}
}
.bottom{
width: 100%;
position: fixed;
left: 0;
bottom: 0;
background: #FBFBFB;
.bottom_waper{
width: 100%;
box-sizing: border-box;
padding: 10rpx 32rpx 0;
.active {
width: 686rpx;
height: 100rpx;
line-height: 100rpx;
border-radius: 64rpx;
box-sizing: border-box;
text-align: center;
background: #03AE80;
font-weight: 400;
font-size: 42rpx;
color: #FFFFFF;
}
}
}
.popupRefund {
.btn-box {
margin-top: 63rpx;
}
}
}
</style>