zhwl-miniapp/pages/scenic/otherTick.vue

505 lines
20 KiB
Vue
Raw Permalink Normal View History

2025-06-26 12:38:35 +08:00
<template>
<view class="waper" :style="'padding-bottom: ' + windowBottom + 'px;'">
<u-navbar :autoBack="true" :bgColor="scrollTop > 20 ? '#fff' : 'transparent'" :leftIconColor="scrollTop > 20 ? '#303133' : '#fff'">
<view slot='center' class="navbar_title">{{scrollTop > 20 ? '购票详情' : ''}}</view>
</u-navbar>
<view class="banner" v-if="detail">
<swiper :autoplay="true" :interval="5000" circular :duration="1000">
<swiper-item v-for="(i, index) in detail.ticketInfo.image43 ? detail.ticketInfo.image43.split(',') : []" :key="index">
<image :src="$utils.setImgUrl(i)" mode=""></image>
</swiper-item>
</swiper>
</view>
<view class="waper_box" v-if="detail">
<view class="header">
<view class="title">{{detail.ticketInfo.name}}{{detail.ticketInfo.classifyName ? `(${detail.ticketInfo.classifyName})` : ''}}</view>
<view class="sub-title">
<view class="tel">电话{{configData && configData.phone}}</view>
<view class="call-tel" @click="callTel">
<image src="https://common/callTel.png" mode=""></image>
</view>
</view>
</view>
<view class="show">
<view class="tab">
<view :class="{active: tabActive == 0}" @click="tabActive = 0">演出预定</view>
<view :class="{active: tabActive == 1}" @click="tabActive = 1">演出详情</view>
</view>
<view class="reserve" v-if="tabActive == 0">
<view class="reserve-tit">选择日期</view>
<view class="box">
<view :class="'border-box' + (dateActive === index ? ' active' : '')" v-for="(i, index) in dateList" :key="index" @click="tabDate(index)">
<view class="border-box-tit">{{i.date}}</view>
<image src="https://common/date_active.png" mode="scaleToFill" />
</view>
<view class="border-more" @click="showDate = true;">
<view class="left">
更多日期
</view>
<view class="right">
<u-icon name="arrow-right" color="rgba(0,0,0,0.45)" size="32rpx"></u-icon>
</view>
</view>
</view>
<template v-if="detail.saleInfo.length > 0">
<view class="reserve-tit">选择场次</view>
<view class="box">
<view class="time-border-box" :class="{active: index === saleActive}" v-for="(item, index) in detail.saleInfo[0].itemList" :key="index" @click="tabSaleActive(index)">
<view class="time-border-box-tit">{{item.itemBeginTime}}-{{item.itemEndTime}}</view>
<view class="time-border-box-sub-tit">{{item.itemName}}</view>
<view class="time-border-box-sub-tit">{{item.hallName}}</view>
<image src="https://common/date_active.png" mode="scaleToFill" />
</view>
</view>
</template>
</view>
<view class="detail" v-if="tabActive == 1">
<view class="text-box" v-if="detail.ticketInfo.cpsm">
<view class="label">产品说明</view>
<view class="text-content">{{detail.ticketInfo.cpsm}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.qpxx">
<view class="label">取票信息</view>
<view class="text-content">{{detail.ticketInfo.qpxx}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.sysm">
<view class="label">使用说明</view>
<view class="text-content">{{detail.ticketInfo.sysm}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.wxts">
<view class="label">温馨提示</view>
<view class="text-content">{{detail.ticketInfo.wxts}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.refundRuleName">
<view class="label">退改规则</view>
<view class="text-content">{{detail.ticketInfo.refundRuleName}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.movieName">
<view class="label">剧目名称</view>
<view class="text-content">{{detail.ticketInfo.movieName}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.movieLength">
<view class="label">演出时长</view>
<view class="text-content">{{detail.ticketInfo.movieLength}}分钟</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.movieCategoryName">
<view class="label">剧目类型</view>
<view class="text-content">{{detail.ticketInfo.movieCategoryName}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.movieAdvise">
<view class="label">观看建议</view>
<view class="text-content">{{detail.ticketInfo.movieAdvise}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.moviePerformer">
<view class="label">剧目演员</view>
<view class="text-content">{{detail.ticketInfo.moviePerformer || ''}}</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.movieIntroduction">
<view class="label">剧情介绍</view>
</view>
<view class="text-box" v-if="detail.ticketInfo.movieIntroduction">
<view class="text-content">{{detail.ticketInfo.movieIntroduction}}</view>
</view>
</view>
</view>
<view class="btn" v-if="tabActive == 0" @click="toNext">座位预定</view>
</view>
<!-- 日期选择 -->
<u-popup :show="showDate" bgColor="white" mode="bottom">
<view class="data_waper">
<view class="data_waper-title">
请选择日期
<view class="icon" @click="showDate = false;">
<u-icon name="close" color="rgba(0,0,0,0.85)" size="30rpx"></u-icon>
</view>
</view>
<wn-calendar
:isText="false"
v-if="showDate && detail"
ref="calendar"
:data="records"
:isBorder="false"
:isLess="false"
:colors="['#03AE80']"
:isEn="false"
:activeDate="dateList[dateActive].date"
format="-"
@choose="dateChoose"
:isOrder="detail.isOrder"
:beforeDay="detail.beforeDay"
></wn-calendar>
</view>
</u-popup>
</view>
</template>
<script>
export default {
data () {
return {
ticketId: null,
windowBottom: 0,
scrollTop: 0,
configData: null,
detail: null,
showDate: false,
records: [],
dateList: [],
dateActive: 0,
tabActive: 0,
saleActive: null
}
},
onLoad (options) {
uni.showLoading({ mask: true })
this.ticketId = options.id;
this.windowBottom = this.$safeAreaBottom + uni.upx2px(152);
this.configData = uni.getStorageSync('configData');
this.dateList = [];
this.$nextTick(() => {
let arr = this.$utils.getDateList(this.$utils.formatDate('Y-M-D'));
arr.forEach((item) => {
this.dateList.push({ date: item })
})
uni.hideLoading();
})
this.getTicketInfo(this.$utils.formatDate('Y-M-D'));
},
methods: {
async toNext () {
let user = await this.$http.getUserInfo();
if (user.data.isBlack == 1) {
uni.showToast({ title: '您是黑名单用户,禁止购票', icon: 'none', mask: true })
return false;
}
if (!user.data.name || !user.data.mobile || !user.data.idCard) {
uni.showToast({ title: '请完善个人信息后操作', icon: 'none', mask: true })
setTimeout(() => {
uni.navigateTo({ url: '/pages/my/myProfile' })
}, 1500)
return false;
}
if (this.dateActive === null) {
uni.showToast({ mask: true, title: '请选择日期', icon: 'none' });
return false;
}
if (this.saleActive === null) {
uni.showToast({ mask: true, title: '请选择场次', icon: 'none' });
return false;
}
let saleInfo = this.detail.saleInfo[0].itemList[this.saleActive];
console.log(saleInfo)
let obj = {
ticketId: this.detail.ticketInfo.id,
qrcodeRule: this.detail.ticketInfo.qrcodeRule,
hallId: saleInfo.saleInfo,
itemId: saleInfo.itemId,
itemName: saleInfo.itemName,
hallName: saleInfo.hallName,
hallTime: `${this.dateList[this.dateActive].date} ${saleInfo.itemBeginTime}-${saleInfo.itemEndTime}`,
limit: this.detail.ticketInfo.verifySettings == 1 ? (this.detail.ticketInfo.isOrderQuantity == 1 ? this.detail.ticketInfo.orderQuantity : null) : null,
ticketName: this.detail.ticketInfo.name,
authenticationType: this.detail.ticketInfo.authenticationType,
ticketChildren: this.detail.saleInfo[0].childList,
movieName: this.detail.ticketInfo.movieName,
movieId: this.detail.ticketInfo.movieId,
saleTime: this.dateList[this.dateActive].date
}
let str = `/pages/scenic/seat?itemId=${saleInfo.itemId}&hallId=${saleInfo.hallId}&pageData=${encodeURIComponent(JSON.stringify(obj))}`
uni.navigateTo({ url: str })
},
tabSaleActive (index) {
let nowTime = new Date().getTime();
let start = new Date(this.dateList[this.dateActive].date + ' ' + this.detail.saleInfo[0].itemList[index].itemBeginTime + ':00').getTime();
// let arr = this.detail.saleInfo[0].itemList[index].itemBeginTime.split(':');
// let start = Number(arr[0] * 60) + Number(arr[1]);
// let arr1 = this.$utils.formatDate('h:m').split(':');
// let end = Number(arr1[0] * 60) + Number(arr1[1]);
if (nowTime > start) {
uni.showToast({ mask: true, title: '当前时间大于开场时间', icon: 'none' });
return false;
}
this.saleActive = index;
},
tabDate (index) {
this.saleActive = null;
this.dateActive = index;
this.getTicketInfo(this.dateList[index].date);
},
async getTicketInfo (searchTime) {
let info = await this.$http.cinemaTicketDetail({ id: this.ticketId, searchTime: searchTime });
this.detail = info.data;
},
callTel () {
uni.makePhoneCall({ phoneNumber: this.configData.phone }).catch((e) => {});
},
dateChoose (e) {
this.saleActive = null;
this.getTicketInfo(e.date);
let arr = this.$utils.getNewDate(this.$utils.formatDate('Y-M-D', e.date), this.detail.isPurchaseDate, this.detail.beforeDay);
this.dateList = [];
arr.forEach((item, index) => {
this.dateList.push({ date: item })
if (this.$utils.formatDate('Y-M-D', e.date) == item) this.dateActive = index;
})
this.showDate = false;
},
},
onPageScroll (e) {
this.scrollTop = e.scrollTop;
}
}
</script>
<style lang="scss">
page{
background: #F6F6F6;
}
</style>
<style lang="scss" scoped>
.banner{
width: 100%;
height: 562rpx;
position: relative;
swiper{
width: 100%;
height: 100%;
}
}
.waper_box{
width: 100%;
margin-top: -96rpx;
position: relative;
z-index: 3;
.header{
background: white;
border-radius: 40rpx 40rpx 0 0;
box-sizing: border-box;
padding: 32rpx;
margin-bottom: 20rpx;
.title{
height: 50rpx;
font-weight: 600;
font-size: 36rpx;
color: rgba(0,0,0,0.85);
line-height: 42rpx;
margin-bottom: 32rpx;
}
.sub-title{
display: flex;
justify-content: space-between;
align-items: center;
.tel{
height: 39rpx;
font-size: 28rpx;
color: rgba(0,0,0,0.65);
line-height: 33rpx;
}
.call-tel{
width: 50rpx;
min-width: 50rpx;
height: 50rpx;
&>image{
width: 100%;
height: 100%;
}
}
}
}
.show{
padding: 24rpx 32rpx 37rpx 32rpx;
background: white;
.tab{
display: flex;
align-items: center;
border-bottom: 1px solid rgba(0,0,0,0.05);
box-sizing: border-box;
padding-bottom: 26rpx;
font-size: 28rpx;
color: rgba(0,0,0,0.45);
line-height: 33rpx;
&>view{
margin-right: 40rpx;
}
.active{
height: 45rpx;
font-weight: 600;
font-size: 32rpx;
color: rgba(0,0,0,0.85);
line-height: 38rpx;
position: relative;
&::after{
content: '';
width: 42rpx;
height: 6rpx;
background: #03AE80;
border-radius: 13rpx 13rpx 13rpx 13rpx;
position: absolute;
bottom: -10rpx;
left: 50%;
transform: translate(-50%, 0);
}
}
}
.reserve{
.reserve-tit{
height: 45rpx;
font-size: 32rpx;
color: rgba(0,0,0,0.85);
line-height: 38rpx;
margin-top: 24rpx;
}
.box{
display: flex;
align-items: center;
flex-wrap: wrap;
.border-box{
width: 182rpx;
height: 106rpx;
border-radius: 10rpx 10rpx 10rpx 10rpx;
border: 1rpx solid rgba(0,0,0,0.1);
margin-right: 20rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
margin-top: 20rpx;
box-sizing: border-box;
.border-box-tit{
font-weight: 500;
font-size: 24rpx;
color: rgba(0,0,0,0.65);
line-height: 28rpx;
}
image{
width: 40rpx;
height: 40rpx;
position: absolute;
right: 0;
bottom: 0;
z-index: -1;
}
}
.time-border-box{
width: 215rpx;
// height: 104rpx;
border-radius: 10rpx 10rpx 10rpx 10rpx;
border: 1rpx solid rgba(0,0,0,0.1);
margin-right: 20rpx;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
position: relative;
overflow: hidden;
margin-top: 20rpx;
box-sizing: border-box;
padding: 16rpx 12rpx;
.time-border-box-tit{
height: 34rpx;
font-size: 24rpx;
color: rgba(0,0,0,0.65);
line-height: 28rpx;
}
.time-border-box-sub-tit{
height: 34rpx;
font-size: 24rpx;
color: rgba(0,0,0,0.45);
line-height: 28rpx;
margin-top: 4px;
}
image{
width: 40rpx;
height: 40rpx;
position: absolute;
right: 0;
bottom: 0;
z-index: -1;
}
}
.time-border-box:nth-child(3n){
margin-right: 0;
}
.active{
border: 1rpx solid #03AE80;
image{
z-index: 1;
}
}
.border-more{
width: 80rpx;
display: flex;
align-items: center;
justify-content: center;
.left{
width: 48rpx;
font-size: 24rpx;
color: rgba(0,0,0,0.45);
line-height: 28rpx;
}
}
}
}
.detail{
padding: 10rpx 0;
.text-box{
display: flex;
align-items: flex-start;
margin-top: 20rpx;
.label{
width: 112rpx;
min-width: 112rpx;
margin-right: 48rpx;
height: 39rpx;
font-size: 28rpx;
color: rgba(0,0,0,0.65);
line-height: 33rpx;
}
.text-content{
font-size: 28rpx;
color: rgba(0,0,0,0.85);
line-height: 36rpx;
}
}
}
}
.btn{
width: 686rpx;
height: 100rpx;
text-align: center;
line-height: 100rpx;
border-radius: 50rpx;
font-weight: 500;
font-size: 32rpx;
color: #FFFFFF;
background: #03AE80;
margin: 106rpx auto 61rpx;
}
}
::v-deep .u-popup__content{
border-radius: 40rpx 40rpx 0 0;
}
.data_waper{
.data_waper-title{
margin-top: 32rpx;
font-weight: 500;
font-size: 34rpx;
color: rgba(0,0,0,0.85);
line-height: 40rpx;
height: 48rpx;
text-align: center;
position: relative;
.icon{
position: absolute;
right: 40rpx;
top: 0;
}
}
}
</style>