Files
2025-08-26 16:17:24 +08:00

711 lines
26 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" :placeholder="true" bgColor="#03AE80" leftIconColor="#fff">
<view slot='center' style="font-size: 36rpx; font-weight: bold; color: #fff;">核销</view>
</u-navbar>
<view class="colorLump"></view>
<view class="con-box" v-if="detData">
<view class="info">
<image class="bgm" src="../../static/img/hxxq.png" mode=""></image>
<view class="top">
<view class="img">
<image :src="$utils.getJointImg(detData.image11)" mode=""></image>
</view>
<view class="text-box">
<view class="title">
<view class="label">{{detData.ticketName}}</view>
<view class="status" v-if="detData.historyList && detData.historyList.length > 0">已核销</view>
</view>
<view class="price">{{detData.price}}</view>
</view>
</view>
<view class="bottom" v-if="detailList">
<view class="row">
<view class="key">订单编号</view>
<view class="value">{{detData.orderCodeZdd}}</view>
</view>
<view class="row">
<view class="key">下单时间</view>
<view class="value">{{detData.paymentTime}}</view>
</view>
<view class="row" v-if="detailList.availableStartTime && detailList.availableEndTime">
<view class="key">有效期</view>
<view class="value">{{detailList.availableStartTime.split(' ')[0]}}{{detailList.availableEndTime.split(' ')[0]}}</view>
</view>
<view class="row">
<view class="key">联系人</view>
<view class="value">{{!detailList.userName ? '窗口售票' : (detailList.userName + ' ' + (detailList.mobilePhone ? detailList.mobilePhone : ''))}}</view>
</view>
<view class="row">
<view class="key">出行人</view>
<view class="value">{{!detailList.userName ? '不实名' : (detailList.userName + ' ' + (detailList.identityCard ? detailList.identityCard : ''))}}</view>
</view>
<view class="row">
<view class="key">适用时间段</view>
<view class="value">{{detData.weekLabel + ((detData.weekLabel && detData.classify == '4') ? '不可用' : '')}}</view>
</view>
</view>
</view>
<!-- 可核销 -->
<template v-if="!detData.historyList || detData.historyList.length == 0">
<!-- 普通票 -->
<template v-if="detData.classify == '1'">
<!-- 一票一码 -->
<template v-if="detData.qrcodeRule == '1'">
<view class="information" v-if="detailList">
<view class="item">
<view class="num">{{detailList.canVerificationMun}}</view>
<view class="label">总次数</view>
</view>
<view class="item">
<view class="num">{{detailList.verificationMun}}</view>
<view class="label">已核销</view>
</view>
<view class="item">
<view class="num">{{detailList.canVerificationMun - detailList.verificationMun}}</view>
<view class="label">未核销</view>
</view>
</view>
<view class="quantity" v-if="detailList">
<view class="title">本次核销次数</view>
<view class="card-box">
<view class="card" :class="{'active': activeCard == item}" v-for="(item,index) in getNumbers(0, (detailList.canVerificationMun - detailList.verificationMun - 1))" :key="index" @click="selectCard(item, '1')">{{(detailList.canVerificationMun - detailList.verificationMun) - item}}</view>
</view>
</view>
</template>
<!-- 多票一码 -->
<template v-else>
<view class="information">
<view class="item">
<view class="num">{{detData.buyQuantity}}</view>
<view class="label">总张数</view>
</view>
<view class="item">
<view class="num">{{detData.buyQuantity - detData.verificationMunTotal}}</view>
<view class="label">已核销</view>
</view>
<view class="item">
<view class="num">{{detData.verificationMunTotal}}</view>
<view class="label">未核销</view>
</view>
</view>
<view class="quantity">
<view class="title">本次核销张数</view>
<view class="card-box">
<!-- #ifdef APP-PLUS -->
<view class="card" :class="{'active': activeCard == item}" v-for="(item,index) in detData.verificationMunTotal" :key="index" @click="selectCard((item - 1), '2')">
{{detData.verificationMunTotal - (item - 1)}}
</view>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<view class="card" :class="{'active': activeCard == item}" v-for="(item,index) in detData.verificationMunTotal" :key="index" @click="selectCard(item, '2')">
{{detData.verificationMunTotal - item}}
</view>
<!-- #endif -->
</view>
</view>
</template>
</template>
<template v-else>
<view class="classify" v-if="detailList">
<view class="classify_title">选择核销门票</view>
<view class="classify_waper">
<view v-for="(i, index) in detailList.orderDetailChildList" :key="index" :class="'classify_list' + (i.active ? ' active' : '')" @click="tabActive(i, index)">
<view class="top">{{i.ticketName}}</view>
<view class="bottom">
<view>
<text>出行人</text>
<text>{{detailList.userName ? detailList.userName : '不实名'}} {{detailList.identityCard ? detailList.identityCard : ''}}</text>
</view>
<view>
<text>总核销次数</text>
<text>{{i.canVerificationNum > 0 ? i.canVerificationNum : '不限次数'}}</text>
</view>
<view>
<text>已核销次数</text>
<text>{{i.verificationNum}}</text>
</view>
<view v-if="detData.classify == '4' || detData.classify == '5'">
<text>当日核销次数</text>
<text>{{i.dayCount}}</text>
</view>
<view v-if="detData.classify == '4' || detData.classify == '5'">
<text>当月核销次数</text>
<text>{{i.monthCount}}</text>
</view>
</view>
<image src="../../static/img/active.png" mode="" v-if="i.active"></image>
</view>
</view>
</view>
<view class="classify_btn" @click="submitClassify">确认核销</view>
</template>
</template>
<!-- 不可核销 -->
<template v-else>
<view class="log_waper">
<view class="title">
<view>核销记录</view>
<view>剩余次数{{detData.verificationMunTotal}}</view>
</view>
<view class="cont">
<view class="list" v-for="(i, index) in detData.historyList" :key="index">
<view class="left">
<view v-if="detData.classify == '1'">已核销</view>
<view v-else>{{i.childTicketName}} - 已核销</view>
<view>{{i.createTime}}</view>
</view>
<view class="right">{{i.verificationNum}}</view>
</view>
</view>
</view>
</template>
</view>
<u-popup :show="show" round="10" mode="center">
<view class="popup_waper" v-if="detData">
<u-icon name="close" color="#333" size="42rpx" @click="closePopup"></u-icon>
<view v-if="result && result.code == 200">
<view class="status">
<image class="icon" src="../../static/img/hx11.png" mode=""></image>
</view>
<view class="text">核销成功</view>
<view class="msg" v-if="detData.classify == '1'">
{{detData.ticketName}}
{{num}}
<text v-if="detData.qrcodeRule == '1'"></text>
<text v-if="detData.qrcodeRule == '2'"></text>
({{detData.price}}/)
</view>
<view class="msg" v-if="detailList && activeCard">
{{activeCard.ticketName}}
{{num}}
<text></text>
</view>
<view class="popup_btn" @click="closePopup">确认</view>
</view>
<view v-if="result && result.code != 200">
<view class="status">
<image class="icon" src="../../static/img/hx12.png" mode=""></image>
</view>
<view class="text">核销失败</view>
<view class="msg">{{result.msg}}</view>
<view class="popup_btn" @click="closePopup">确认</view>
</view>
</view>
</u-popup>
<u-popup :show="show1" round="10" mode="center">
<view class="popup_waper1" v-if="detData">
<view class="title">确认核销</view>
<view class="msg" v-if="detData.qrcodeRule == '1'">确认是否核销{{num}}次门票</view>
<view class="msg" v-if="detData.qrcodeRule == '2'">确认是否核销{{num}}张门票</view>
<view class="btn-box">
<view class="default" @click="closePopup1">取消</view>
<view class="active" @click="submit">确定</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
data () {
return {
id: '',
code: '',
activeCard: null,
detData: null,
show: false,
show1: false,
result: null,
num: 0,
detailList: null
}
},
onLoad(options) {
this.code = options.code
this.getVerificationDetail()
},
methods: {
getNumbers(start, end) {
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
},
tabActive (info, index) {
if (info.canVerificationNum == 0) {
this.detailList.orderDetailChildList.forEach((i, ind) => {
this.detailList.orderDetailChildList[ind].active = false;
})
this.detailList.orderDetailChildList[index].active = true;
this.$forceUpdate();
} else {
if (this.detData.classify == '4') {// 年卡
if (info.dayCount < info.dayVerificationNum && info.monthCount < info.monthVerificationNum) {
this.detData.orderChildList.forEach((i, ind) => {
this.detData.orderChildList[ind].active = false;
})
this.detData.orderChildList[index].active = true;
this.$forceUpdate();
} else uni.showToast({ mask: true, title: '当前门票当日/当月已无核销次数', icon: 'none' });
} else {
if (info.canVerificationNum - info.verificationNum > 0) {
this.detailList.orderDetailChildList.forEach((i, ind) => {
this.detailList.orderDetailChildList[ind].active = false;
})
this.detailList.orderDetailChildList[index].active = true;
this.$forceUpdate();
} else uni.showToast({ mask: true, title: '当前门票已无核销次数', icon: 'none' })
}
}
},
submitClassify () {
let info = this.detailList.orderDetailChildList.find((item) => {
return item.active
})
if (!info) {
uni.showToast({ mask: true, title: '请选择核销门票', icon: 'none' })
return false;
}
this.show1 = true;
this.num = 1;
this.activeCard = info;
},
async getVerificationDetail() {
let info = await this.$http.getVerificationDetail({ verificationCode: this.code, serialNo: this.$AppSerialNumber })
if (info.code == 200) {
this.detData = info.data
if (info.data.classify == '2') {
info.data.ticketOrderDetailList[0].orderDetailChildList.forEach((item, index) => {
info.data.ticketOrderDetailList[0].orderDetailChildList[index].active = false;
})
}
this.detailList = info.data.ticketOrderDetailList[0];
if (new Date().getTime() / 1000 > new Date(this.detData.availableEndTime + ' 23:59:59').getTime() / 1000) {
this.detData.timeActive = true;
} else this.detData.timeActive = false;
let time = [];
let weekLabel = '';
if (this.detData.applicablePeriod) {
this.detData.applicablePeriod.split(",").forEach((item) => {
time.push(Number(item));
})
if (this.detData.classify == '4') {
let arr = [];
time.forEach((item) => {
if (item > 0) arr.push(this.getDay(item))
})
weekLabel = arr.join(',');
} else {
if (time.length > 0) {
if (this.isContinuous(time)) {// 数组连续
weekLabel = this.getWeek(time[0]) + '至' + this.getWeek(time[time.length - 1]);
} else {
let arr = [];
time.forEach((item) => {
arr.push(this.getWeek(item))
})
weekLabel = arr.join(',');
}
} else weekLabel = '周一至周日';
}
}
this.detData.weekLabel = weekLabel ? weekLabel : '不限';
} else {
uni.$u.toast(info.msg);
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
},
getDay (key) {
let str = '';
switch (key) {
case 1:
str = '周末';
break;
case 2:
str = '元旦';
break;
case 3:
str = '春节';
break;
case 4:
str = '清明';
break;
case 5:
str = '劳动';
break;
case 6:
str = '端午';
break;
case 7:
str = '中秋';
break;
case 8:
str = '国庆';
break;
}
return str;
},
isContinuous (nums) {
nums.sort((a, b) => a - b);
for (let i = 1; i < nums.length; i++) {
if (nums[i] !== nums[i - 1] + 1) {
return false;
}
}
return true;
},
getWeek (key) {
let str = '';
switch (key) {
case 1:
str = '周一';
break;
case 2:
str = '周二';
break;
case 3:
str = '周三';
break;
case 4:
str = '周四';
break;
case 5:
str = '周五';
break;
case 6:
str = '周六';
break;
case 7:
str = '周日';
break;
}
return str;
},
selectCard(e, type) {
if (type == '1') {
this.num = (this.detailList.canVerificationMun - this.detailList.verificationMun) - e;
} else {
this.num = this.detData.verificationMunTotal - e;
}
this.activeCard = e;
this.show1 = true;
},
closePopup () {
this.show = false;
this.activeCard = null;
uni.reLaunch({ url: '/pages/index/index' })
},
closePopup1() {
this.activeCard = null;
this.show1 = false;
},
async submit () {
let params = {}
if (this.detData.classify == '1') {// 普通票
if (this.detData.qrcodeRule == '1') {// 一票一码
params = { qrcodeRule: '1', detailId: this.detailList.id, num: this.num, ticketClassify: this.detData.classify, orderItemId: this.detData.id };
} else params = { qrcodeRule: '2', detailId: this.detailList.id, num: this.num, ticketClassify: this.detData.classify, orderItemId: this.detData.id };
} else {// 套票
params = { qrcodeRule: '1', childId: this.activeCard.id, num: 1, ticketClassify: this.detData.classify, orderItemId: this.detData.id };
}
// if (this.detData.classify == '1') {
// params = {
// qrcodeRule: this.detData.qrcodeRule,
// num: this.num,
// ticketClassify: this.detData.classify
// }
// if (this.detData.qrcodeRule == '1') {
// params.id = this.detData.id
// } else if (this.detData.qrcodeRule == '2') {
// params.orderId = this.detData.orderId
// }
// } else {
// params = { qrcodeRule: '1', id: this.activeCard.id, num: 1, ticketClassify: this.detData.classify };
// }
let info = null;
// #ifdef APP-PLUS
params.serialNo = this.$AppSerialNumber;
params.ticketId = this.detData.classify == '1' ? this.detData.ticketId : this.activeCard.ticketId;
// params.ticketId = this.detData.orderChildList.length == 0 ? this.detData.ticketId : this.activeCard.ticketId;
info = await this.$http.handheldVerification(params)
// #endif
// #ifndef APP-PLUS
info = await this.$http.toVerification(params)
// #endif
this.result = info;
if (this.detData.classify == '1') {
this.closePopup1()
} else this.show1 = false;
this.show = true;
},
}
}
</script>
<style lang="scss">
.waper{
width: 100%; box-sizing: border-box;
.colorLump {
width: 750rpx;
height: 228rpx;
background: #03AE80;
}
.con-box {
margin-top: -196rpx;
padding: 0 32rpx 32rpx;
}
.info{
width: 686rpx; height: 644rpx; box-sizing: border-box; padding: 24rpx 24rpx 32rpx; position: relative;
.bgm {
position: absolute;
left: 0;
top: 0;
}
.top{
width: 638rpx;
margin: 24rpx 24rpx 0;
padding-bottom: 32rpx;
position: absolute;
left: 0;
top: 0;
border-bottom: 1rpx dashed rgba(0,0,0,0.2);
display: flex;
.img{
width: 140rpx; height: 140rpx; margin-right: 20rpx;
image{ border-radius: 10rpx; }
}
.text-box{
flex: 1;
.title {
display: flex;
align-items: center;
justify-content: space-between;
.label {
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
.status {
font-weight: 400;
font-size: 28rpx;
color: #FF5833;
}
}
.price {
margin-top: 20rpx;
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
}
}
.bottom{
width: 638rpx;
margin: 32rpx 24rpx;
position: absolute;
left: 0;
bottom: 0;
.row {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 30rpx;
&:first-child {
margin-top: 0;
}
.key {
font-weight: 400;
font-size: 28rpx;
color: #666666;
}
.value {
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
}
}
}
.information {
margin-top: 20rpx;
width: 686rpx;
height: 222rpx;
background: #FFFFFF;
border-radius: 10rpx;
padding: 32rpx 24rpx;
box-sizing: border-box;
display: flex;
align-items: center;
.item {
width: 200rpx;
height: 159rpx;
background: #FBFBFB;
border-radius: 10rpx;
text-align: center;
margin-right: 19rpx;
&:last-child {
margin-right: 0;
}
.num {
margin-top: 24rpx;
font-weight: bold;
font-size: 48rpx;
color: #333333;
}
.label {
margin-top: 8rpx;
font-weight: 400;
font-size: 28rpx;
color: #666666;
}
}
}
.quantity {
margin-top: 20rpx;
width: 686rpx;
background: #FFFFFF;
border-radius: 10rpx;
padding: 32rpx 24rpx;
box-sizing: border-box;
.title {
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.card-box {
padding-top: 8rpx;
.card {
display: inline-block;
width: 142rpx;
height: 100rpx;
background: #FBFBFB;
border-radius: 10rpx;
line-height: 100rpx;
text-align: center;
font-weight: 500;
font-size: 32rpx;
color: #333333;
margin: 16rpx 23rpx 0 0;
&:nth-child(4n) {
margin-right: 0;
}
}
.active {
background: #03AE80;
color: #fff;
}
}
}
.classify{
width: 100%; margin-top: 20rpx; background: #fff; border-radius: 10rpx; box-sizing: border-box; padding: 32rpx 24rpx;
.classify_title{ line-height: 46rpx; color: #333; font-size: 32rpx; color: #333; font-weight: 500; }
.classify_waper{
width: 100%; margin-top: 24rpx;
.classify_list{
width: 100%; background: #FBFBFB; box-sizing: border-box; border: 2rpx solid #FBFBFB; border-radius: 10rpx; padding: 24rpx; margin-bottom: 16rpx;
&:last-child{ margin-bottom: 0; }
.top{ line-height: 40rpx; color: #333; font-size: 28rpx; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bottom{
width: 100%; margin-top: 20rpx;
view{
font-size: 0; height: 40rpx; line-height: 40rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-bottom: 16rpx;
&:last-child{ margin-bottom: 0; }
text{
color: #666; font-size: 28rpx;
&:last-child{ color: #333; }
}
}
}
&.active{
border-color: #03AE80; position: relative;
image{ width: 90rpx; height: 90rpx; position: absolute; right: 0; bottom: 0; }
}
}
}
}
.classify_btn{ width: 100%; margin-top: 36rpx; border-radius: 100rpx; background: #03AE80; color: #fff; font-size: 32rpx; font-weight: 500; text-align: center; line-height: 90rpx; height: 90rpx; }
}
/deep/.u-safe-bottom {
display: none;
}
.popup_waper1 {
width: 638rpx;
height: 350rpx;
background: linear-gradient( 180deg, #E8F8F4 0%, rgba(232,248,244,0) 100%);
border-radius: 20rpx;
padding: 64rpx 32rpx 39rpx;
box-sizing: border-box;
text-align: center;
.title {
font-weight: 500;
font-size: 40rpx;
color: #000000;
}
.msg {
margin-top: 24rpx;
font-weight: 400;
font-size: 28rpx;
color: #333333;
}
.btn-box {
margin-top: 48rpx;
display: flex;
align-items: center;
justify-content: space-between;
.default {
width: 274rpx;
height: 78rpx;
border-radius: 80rpx;
border: 1rpx solid #999999;
line-height: 78rpx;
text-align: center;
font-weight: 400;
font-size: 30rpx;
color: #666666;
}
.active {
width: 276rpx;
height: 80rpx;
background: #03AE80;
border-radius: 80rpx;
line-height: 80rpx;
text-align: center;
font-weight: 500;
font-size: 30rpx;
color: #FFFFFF;
}
}
}
.log_waper{
width: 100%; margin-top: 20rpx; background: #fff; box-sizing: border-box; padding: 32rpx 24rpx 20rpx; border-radius: 10rpx;
.title{
height: 46rpx; display: flex; justify-content: space-between; align-items: center;
view{
&:nth-child(1){ color: #333; font-size: 32rpx; font-weight: 500; }
&:nth-child(2){ color: #999; font-size: 24rpx; }
}
}
.cont{
width: 100%; margin-top: 4rpx;
.list{
width: 100%; padding: 20rpx 0; display: flex; justify-content: space-between; align-items: center; border-bottom: 2rpx solid #E8E8E8;
&:last-child{ border-bottom: 0; }
.left{
view{
&:nth-child(1){ color: #333; font-size: 28rpx; font-weight: 500; line-height: 40rpx; }
&:nth-child(2){ color: #999; font-size: 24rpx; line-height: 34rpx; margin-top: 8rpx; }
}
}
.right{ line-height: 50rpx; color: #FF3333; font-size: 36rpx; font-weight: 600; }
}
}
}
</style>