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

505 lines
20 KiB
Vue
Raw 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" :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>