jiazhipeng 4 months ago
parent
commit
1bd90ff715
  1. 2
      manifest.json
  2. 6
      pages.json
  3. 4
      static/css/base.css
  4. 575
      subPackages/ticket/detail.vue
  5. 9
      subPackages/ticket/index.vue

2
manifest.json

@ -88,7 +88,7 @@
"disableHostCheck" : true, "disableHostCheck" : true,
"proxy" : { "proxy" : {
"/api" : { "/api" : {
"target" : "https://changyoutaihuadmin.xmainc.com/", // "target" : "https://api.cloud.sz-trip.com/", //
"changeOrigin" : true, // "changeOrigin" : true, //
"secure" : true, // https "secure" : true, // https
"pathRewrite" : { "pathRewrite" : {

6
pages.json

@ -53,6 +53,12 @@
"navigationBarTitleText": "采摘" "navigationBarTitleText": "采摘"
} }
}, },
{
"path": "ticket/detail",
"style": {
"navigationBarTitleText": "详情"
}
},
{ {

4
static/css/base.css

@ -72,7 +72,9 @@ view {
padding: 30upx 0; padding: 30upx 0;
color: #999999; color: #999999;
} }
.flex{
display: flex;
}
.flex-shrink-0{ .flex-shrink-0{
flex-shrink: 0; flex-shrink: 0;
} }

575
subPackages/ticket/detail.vue

@ -1,22 +1,9 @@
<template> <template>
<view class="bg"> <view class="bg" v-if="info">
<view class="swipe-box"> <view class="swipe-box">
<swiper class="swiper" :autoplay="true" :interval="3000" :duration="1000" @change="swiperChange"> <swiper class="swiper" :autoplay="true" :interval="3000" :duration="1000"
<swiper-item v-for="(item, index) in info.list_images.split(',')" :key="item.id"> @change="swiperChange" circular>
<swiper-item v-if="info && info.videourl"> <swiper-item v-for="(item, index) in info.listimg" :key="item.id">
<video
:src="showImg(info.videourl)"
id="detailVideo"
:poster="
showImg(info.image)
"
@play="play"
@error="videoErrorCallback"
controls
style="width: 100%;height: 100%;"
object-fit="cover"
></video>
</swiper-item>
<view class="swiper-item"> <view class="swiper-item">
<image class="item-img" :src="showImg(item)" mode="aspectFill"></image> <image class="item-img" :src="showImg(item)" mode="aspectFill"></image>
</view> </view>
@ -24,7 +11,7 @@
</swiper> </swiper>
<view class="swiper-pointer"> <view class="swiper-pointer">
{{swiperCurrent}}/{{info.list_images.split(',').length}} <view :class="['cricle',swiperCurrent==i?'active':'']" v-for="(item,i) in info.listimg" :key="i"></view>
</view> </view>
</view> </view>
@ -32,99 +19,77 @@
<view class="common-container info-container"> <view class="common-container info-container">
<view class="flex-between"> <view class="flex-between">
<view class="info-title text-overflowRows">{{info.title}}</view> <view class="info-title text-overflowRows">{{info.title}}</view>
<!-- <view class="collect" @click="collect">
<image :src="showImg('/uploads/20240827/8a55a8936b9324fa1c7b85c2da9c015b.png')" mode="" v-if="info.is_collect == 0"></image>
<image v-else :src="showImg('/uploads/20240827/6bf73216f19c756961496031f8aed053.png')" mode="" ></image>
<view>收藏</view>
</view> -->
</view> </view>
<view class="flex-between time-container"> <view class="tags flex text-overflow" style="overflow: hidden" v-if="info.display_tags">
<view class="flex flex-1 flex-shrink-0 flex-items-center"> <view class="tag" v-for="(tagItem, tagIndex) in info.display_tags.split(',').slice(0, 2)"
<image class="address-icon flex-shrink-0" :src="showImg('/uploads/20241024/7fe2f8f89aec55a4009b66032b7a3f7e.png')" mode=""></image> :key="tagIndex">
<view class="title text-overflowRows"> <text>{{ tagItem }}</text>
<text style="margin-right: 28rpx;">营业时间</text> <view class="tip"></view>
{{info.open_description}}
</view>
</view> </view>
<view></view>
</view> </view>
<view class="flex" style="margin: 30rpx 0;">
<text class="flex-shrink-0">开园时间</text>
<text class="flex-1 w-1rpx">{{info.open_time}}</text>
</view>
<view class="flex-between" style="align-items: flex-start;"> <view class="flex-between" style="align-items: flex-start;">
<view class="flex flex-1 flex-shrink-0 flex-items-center" style="align-items: flex-start;"> <view class="flex flex-1 w-1rpx">
<image class="address-icon flex-shrink-0" style="margin-top: 5rpx;" :src="showImg('/uploads/20241023/3d357e6e562de9395f373dc380a790a7.png')" mode=""></image> <text class="flex-shrink-0">地址</text>
<view class="title address-title text-overflowRows"> <text class="flex-1 w-1rpx">{{info.address}}</text>
<text class="flex-shrink-0" style="margin-right: 28rpx;">景区地址</text>
<text class="address-detail flex-1">{{info.address}}</text>
</view>
</view> </view>
<view @click="goMap" class="map-icon"> <view @click="goMap" class="flex-shrink-0">
<img style="width: 50rpx;height: 50rpx;" :src="showImg('/uploads/20241104/07d3dce7ad780dc9f207142887e938e8.png')"> <img style="width: 34.67rpx;height: 34.67rpx;" src="https://static.ticket.sz-trip.com/uploads/20250610/aefe5ce619ba00f6f1906d229effd686.png">
<view>去这里</view>
</view> </view>
</view> </view>
</view> </view>
<view class="box-title" v-if="currentAudio.multimedia_url">语音讲解</view>
<view class="common-container info-container" v-if="currentAudio.multimedia_url">
<view class="info-title text-overflowRows" style="font-weight: normal;">{{info.title}}</view>
<view class='flex flex-between audio' >
<view class='flex-shrink-0'>{{getTime(Math.round(currentAudio.currentTime.toFixed(0)))}}</view>
<Voice-play :duration="133" :play="false"></Voice-play>
<view class='flex-1' style="width: 10rpx;padding:0 30rpx">
<slider @change="audioSeek" @changing="audioChanging" style="width: 100%;margin: 0;" :block-size="12" backgroundColor='#E4F1F5'
activeColor='#12293C' :min='0' :max='currentAudio.video_length.toFixed(0)' :value='currentAudio.currentTime.toFixed(0)' :step='0.1'></slider>
<view class="w-full flex" v-if="sku.length>0">
<scroll-view class="left-container no-scrollbar" scroll-y scroll-with-animation>
<view :class="['type-item',current ==i?'active':'']"
v-for="(item,i) in sku" :key="i" @click="changeType(item,i)">
{{item.title}}
</view> </view>
<view class='flex-shrink-0'> {{getTime(Math.round(currentAudio.video_length))}}</view> </scroll-view>
<view class='play-icon' style="height:59rpx" > <scroll-view class="right-container no-scrollbar" scroll-y scroll-with-animation>
<image v-if="!curPlay" @tap.stop="playVoice" :src="showImg('/uploads/20241104/d5e0afc30007b693b1880dfe49fa329e.png')" ></image> <view style="height: 20rpx;"></view>
<image v-else @tap.stop="pauseVoice" :src="showImg('/uploads/20241104/986b741dfc323cf6175c34e2ca751a9a.png')" class='icon'></image> <view class="scenic-list" v-for="(item, index) in sku" :key="index">
</view> <view class="scenic-title">{{item.title}}</view>
</view> <view class="scenic-item " v-for="(itemSku, indexSku) in item.sku" :key="indexSku">
</view> <view class="title text-overflow">{{ itemSku.sku_name }}</view>
<view class="flex flex-1 h-1rpx flex-between">
<view class="box-title" v-if="sku.length>0">门票预定</view> <view class="w-1rpx flex-1">
<view class="w-full" v-if="sku.length>0"> <view class="tags-box">
<view class="scenic-list" v-for="(item, index) in sku" :key="index"> <view class="tags text-overflow" v-if="itemSku.display_tags">
<view class="scenic-item " v-for="(itemSku, indexSku) in item.specifications" :key="indexSku"> {{ itemSku.display_tags.split(',').join(" | ") }}
<view class="w-1rpx flex-1 item-left"> </view>
<view class="title text-overflow">{{ itemSku.title }}</view> </view>
<view>
<view class="tags-box"> <view style="color: #FF944C;" class="notice" @click="showSkuInfo(itemSku, item)">
<view class="tags text-overflow" v-if="itemSku.specifications_new_tag"> 预订须知 >>
<view v-for="(tagSku,tagSkuIndex) in itemSku.specifications_new_tag.split(',').slice(0, 2)"
:key="tagSkuIndex">{{ tagSku }}</view>
</view> </view>
</view> </view>
<view class="item-right flex-shrink-0">
<view style="color: #12293C;" class="notice" @click="showSkuInfo(itemSku, item)"> <view class="price">{{showNoPriceNew(itemSku.price)}}</view>
预订须知 > <view class="btn" @click="changeSku(itemSku, item)">预订</view>
</view> </view>
</view> </view>
</view>
<view class="item-right flex-shrink-0">
<view class="price">
{{showNoPriceNew(itemSku.price)}}
</view>
<view class="btn" @click="changeSku(itemSku, item)">
购买
</view>
</view> </view>
</view> </view>
</view> <view style="height: 20rpx;"></view>
</scroll-view>
</view> </view>
<view class="box-title">景点简介</view> <view class="common-container" style="padding: 30rpx 20rpx;background: white;">
<view class="common-container" style="padding: 30rpx;"> <view class="box-title">景点简介</view>
<view class="" id="cpts" v-html="formateRichText(info.feature_content)"></view> <view class="" id="cpts" v-html="formateRichText(info.feature_content)"></view>
</view> </view>
<!-- <template v-if="id">
<userReviewsVue :goodsId="id" goodsType="scenicId"></userReviewsVue>
<moreGoodsVue :goodsId="id"></moreGoodsVue>
</template> -->
</view> </view>
@ -204,18 +169,17 @@
</template> </template>
<script> <script>
import userReviewsVue from '../../compoents/userReviews.vue';
import moreGoodsVue from '../../compoents/moreGoods.vue'
let innerAudioContext2 = null
export default { export default {
components: {userReviewsVue,moreGoodsVue},
data() { data() {
return { return {
headImg: null, headImg: null,
swiperCurrent: 1, swiperCurrent: 0,
id: null, id: null,
info: {list_images:'', times_list_info: {start:'',end:''}}, info: null,
current: 0,
sku: [], sku: [],
skuInfo: {}, // skuInfo: {}, //
selectGoods: {}, // selectGoods: {}, //
@ -229,10 +193,6 @@
stratDate:'',endDate: '', selected: [] stratDate:'',endDate: '', selected: []
}, },
currentAudio: {multimedia_url:'', video_length: 0, currentTime: 0},
curPlay: false,
curPlayCopy: false,
} }
}, },
onShow(options) { onShow(options) {
@ -241,92 +201,22 @@
onLoad(options) { onLoad(options) {
this.id = options.id; this.id = options.id;
this.getInfo(); this.getInfo();
this.getGoodsList() // this.getGoodsList()
this.initPlayer() },
},
onHide () {
if (innerAudioContext2) {
try {
innerAudioContext2.pause();
innerAudioContext2.destroy()
innerAudioContext2 = null
} catch (e) {
//TODO handle the exception
}
}
},
onUnload () {
if (innerAudioContext2) {
try {
innerAudioContext2.pause();
innerAudioContext2.destroy()
innerAudioContext2 = null
} catch (e) {
//TODO handle the exception
}
}
},
methods: { methods: {
swiperChange (e) { swiperChange (e) {
this.swiperCurrent = e.detail.current+1 this.swiperCurrent = e.detail.current
}, },
// //
getInfo() { getInfo() {
this.Post({id: this.id},'/api/scenic/getScenicById').then(res => { this.Post({id: this.id},'/api/scene/detail').then(res => {
if (res.data.flag == 0) { this.info = res.data
uni.showToast({title: '商品不存在或已下架',icon: 'none'}) this.sku = this.info.product || []
setTimeout(() => {this.goBack()}, 2000)
}
let info = res.data;
try {
info.times_list_info = JSON.parse(info.times_list)[0]
} catch(e) {
console.log(e)
info.times_list_info = {start:'',end:''}
}
if(Array.isArray(info.multimedia)&&info.multimedia.length>0) {
this.currentAudio.multimedia_url = this.showImg(info.multimedia[0].multimedia_url)
this.currentAudio.video_length = info.multimedia[0].video_length
this.currentAudio.currentTime = 0
}
this.info = info
console.log(info)
let param = {
sku_id: this.info.id,
sku_name: this.info.title,
sku_price: this.info.price/100,
category_id: this.info.scenic_type_id,
category_name:this.info.scenic_type_text,
visitSource: this.getVisitSource()
}
this.qdTracker('viewProductDetail', param)
});
},
// id
getGoodsList(){
this.Post({
scenic_id: this.id
},'/api/scenic/getGoodsByScenicId').then(res => {
this.sku = res.data || []
})
},
// 2
collect() {
this.Post({type: 2,id: this.id},'/api/scenic/collect').then(res => {
if (res) {
uni.showToast({title: res.msg,icon: 'none'});
this.info.is_collect = !this.info.is_collect
}
}); });
}, },
goMap () { goMap () {
if (!this.info.tengxun_map) { if (!this.info.lat || !this.info.lon) {
uni.showToast({ uni.showToast({
title: '暂未配置地理位置', title: '暂未配置地理位置',
icon: 'none' icon: 'none'
@ -335,8 +225,8 @@
} }
uni.openLocation({ uni.openLocation({
latitude: Number(this.info.tengxun_map.lat), latitude: Number(this.info.lat),
longitude: Number(this.info.tengxun_map.lon), longitude: Number(this.info.lon),
name: this.info.title, name: this.info.title,
address: this.info.address, address: this.info.address,
success: function () { success: function () {
@ -345,6 +235,10 @@
}); });
}, },
changeType (item,i) {
},
showSkuInfo (itemSku,goods) { showSkuInfo (itemSku,goods) {
this.skuInfo = itemSku this.skuInfo = itemSku
this.selectGoods = goods this.selectGoods = goods
@ -450,7 +344,7 @@
seldDateIndex: this.seldDateIndex, seldDateIndex: this.seldDateIndex,
timesArr: this.timesArr, timesArr: this.timesArr,
seldTimeIndex: this.seldTimeIndex, seldTimeIndex: this.seldTimeIndex,
} };
uni.setStorageSync('ticketOrder', JSON.stringify(param)); uni.setStorageSync('ticketOrder', JSON.stringify(param));
// that.gotoBuy(pInfo, sInfo); // that.gotoBuy(pInfo, sInfo);
uni.navigateTo({ uni.navigateTo({
@ -467,9 +361,7 @@
sInfo.is_third_stock == 0 sInfo.is_third_stock == 0
) )
return; return;
// that.buryPoint("scene_order");
// that.checkIsCanBuy(that.detail.title,
// function() {
let params = { let params = {
pInfo: pInfo, pInfo: pInfo,
sInfo: sInfo, sInfo: sInfo,
@ -500,13 +392,6 @@
sInfo.price; sInfo.price;
} }
} }
// },
// );
}, },
closePopup() { closePopup() {
@ -530,67 +415,7 @@
} }
}, },
//
initPlayer () {
let that = this;
if (innerAudioContext2) {
try {
innerAudioContext.pause();
innerAudioContext.destroy()
innerAudioContext = null
} catch (e) {
//TODO handle the exception
}
}
innerAudioContext2 = uni.createInnerAudioContext();
innerAudioContext2.autoplay = false;
innerAudioContext2.onPlay(() => {
that.curPlay = true
console.log('play')
});
innerAudioContext2.onError((res) => {
console.log('error',res.errMsg,res.errCode);
});
innerAudioContext2.onEnded(() => {
that.pauseVoice()
that.curPlay = false
});
innerAudioContext2.onTimeUpdate(() => {
console.log('timeUpdate')
that.currentAudio.video_length = innerAudioContext2.duration;
that.currentAudio.currentTime = innerAudioContext2.currentTime;
})
},
//
playVoice(){
innerAudioContext2.src = this.currentAudio.multimedia_url
innerAudioContext2.play()
},
//
pauseVoice(){
innerAudioContext2.pause()
this.curPlay = false
},
//
audioSeek (event) {
let value = event.detail.value
innerAudioContext2.seek(value)
if (this.curPlayCopy) {
innerAudioContext2.play()
this.curPlay = this.curPlayCopy
this.curPlayCopy = false
}
},
//
audioChanging () {
//
if (this.curPlay) {
this.curPlayCopy = this.curPlay
this.pauseVoice()
}
},
getTime(time) { getTime(time) {
let m = parseInt(time / 60); let m = parseInt(time / 60);
@ -613,6 +438,13 @@
*{ *{
box-sizing: border-box; box-sizing: border-box;
} }
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
.bg{ .bg{
min-height: 100vh; min-height: 100vh;
background: #F8F8F8; background: #F8F8F8;
@ -621,58 +453,43 @@
.swipe-box { .swipe-box {
height: 413rpx; height: 413rpx;
position: relative; position: relative;
.swiper {
height: 413rpx;
position: relative;
.swiper-item {
width: 100%;
height: 413rpx;
.item-img {
width: 750rpx;
height: 413rpx;
}
}
}
.swiper-pointer{ .swiper-pointer{
position: absolute; position: absolute;
right: 26rpx; right: 10rpx;
bottom: 46rpx; bottom: 40rpx;
background: rgba(22,22,22,0.5); display: flex;
border-radius: 23rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
padding: 6rpx 14rpx;
} }
.cricle{
.swiper-item-num { width: 14rpx;
width: 90rpx; height: 14rpx;
height: 40rpx; background: rgba(255,255,255,0.3);
background: rgba(0, 0, 0, 0.5); border-radius: 50%;
border-radius: 20rpx; margin-left: 10rpx;
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
text-align: center;
line-height: 40rpx;
position: absolute;
right: 30rpx;
bottom: 50rpx;
} }
} .cricle.active{
background: white;
.swiper {
height: 413rpx;
position: relative;
.swiper-item {
width: 100%;
height: 413rpx;
.item-img {
width: 750rpx;
height: 413rpx;
}
} }
} }
.detail-container{ .detail-container{
width: 100%; width: 100%;
z-index: 2; z-index: 2;
padding: 26rpx; padding: 26rpx 0;
position: relative; position: relative;
top: -52rpx; top: -52rpx;
} }
@ -688,33 +505,72 @@
font-family: PingFang; font-family: PingFang;
font-weight: 500; font-weight: 500;
font-size: 27rpx; font-size: 27rpx;
color: #000000; color: #666;
.time-container{
padding: 22rpx 0;
}
.info-title{ .info-title{
width: 100%; width: 100%;
font-family: PingFang SC; font-family: PingFang SC;
font-size: 31rpx; font-size: 33rpx;
height: 80rpx; height: 80rpx;
font-weight: bold; font-weight: bold;
color: #000;
} }
.collect{
font-size: 23rpx; .tags .tag {
image{ margin-right: 20rpx;
width: 48rpx; font-size: 24rpx;
height: 48rpx; color: #6A8A27;
display: inline-block;
position: relative;
.tip{
position: absolute;
left: 0;
bottom: 4rpx;
width: 100%;
background: #EFF7DF;
height: 8rpx;
z-index: 2;
}
text{
position: relative;
z-index: 5;
} }
}
}
.left-container{
width: 147rpx;
flex-shrink: 0;
.type-item{
font-weight: 500;
font-size: 24rpx;
color: #000000;
width: 100%;
height: 133rpx;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.type-item.active{
font-weight: bold;
font-size: 24rpx;
color: #6A8A27;
background: #FFFFFF;
} }
} }
.right-container{
flex: 1;
width: 1rpx;
background: white;
max-height: 1000rpx;
}
.box-title { .box-title {
margin: 60rpx 12rpx 28rpx; font-weight: normal;
font-size: 37rpx; font-size: 35rpx;
color: #000000; color: #6A8A27;
font-family: PingFang SC;
font-weight: bold;
} }
.address-icon{ .address-icon{
@ -723,83 +579,76 @@
height: 26rpx; height: 26rpx;
} }
.scenic-list{ .scenic-list{
padding: 10rpx 10rpx 0;
.scenic-title{
font-weight: bold;
font-size: 35rpx;
color: #000000;
padding-bottom: 20rpx;
}
.scenic-item { .scenic-item {
width: 100%; width: 100%;
height: 187rpx; height: 187rpx;
background: #FFFFFF; background: rgba(239, 247, 223, 0.5);
border-radius: 13rpx; border-radius: 13rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;
padding: 26rpx; padding: 19rpx 22rpx 10rpx;
display: flex; display: flex;
font-family: PingFang SC; font-family: PingFang SC;
font-weight: 500; font-weight: 500;
font-size: 23rpx; font-size: 23rpx;
color: #666666; color: #666666;
flex-direction: column;
.item-left{ justify-content: space-between;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-left: 20rpx;
}
.title { .title {
width: 100%; width: 100%;
font-family: PingFang SC; font-family: PingFang SC;
font-weight: bold; font-weight: 500;
font-size: 31rpx; font-size: 31rpx;
color: #000000; color: #000000;
} }
.tags-box { .tags-box {
overflow: hidden; overflow: hidden;
padding-bottom: 6rpx; padding-bottom: 17rpx;
.tags { padding-left: 6rpx;
display: flex; font-weight: 500;
flex-wrap: nowrap; font-size: 23rpx;
flex: 1; color: #666666;
}
.tags view::after {
content: '丨'
}
.tags view:last-of-type:after {
display: none;
}
} }
.item-right { .item-right {
width: 133rpx; flex-shrink: 0;
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
} }
.price { .price {
font-family: PingFangSC; font-family: PingFangSC;
font-weight: bold; font-weight: 500;
font-size: 36rpx; font-size: 36rpx;
color: #C3282E; color: #D62828;
} font-weight: bold;
.price::before { &::before {
display: inline-block; display: inline-block;
content: "¥"; content: "¥";
font-size: 24rpx; font-size: 24rpx;
font-weight: bold; }
color: #C3282E;
} }
.btn { .btn {
margin-top: 20rpx; width: 93rpx;
width: 133rpx; height: 80rpx;
height: 53rpx; background: #6A8A27;
background: #C3282E; border-radius: 13rpx;
border-radius: 27rpx;
text-align: center; text-align: center;
line-height: 53rpx; line-height: 80rpx;
font-weight: 500; font-weight: 500;
font-family: PingFang SC; font-size: 31rpx;
font-weight: bold; color: #FFFFFF;
font-size: 31rpx; margin-left: 12rpx;
color: #FFFFFF;
} }
} }
} }
@ -990,27 +839,7 @@
padding-right: 40rpx; padding-right: 40rpx;
} }
} }
.map-icon{
flex-direction: column;
height: 80rpx;
align-items: center;
justify-content: space-between;
font-weight: 500;
font-size: 20rpx;
color: #12293C;
}
.audio{
.play-icon{
height: 51rpx;
padding-left: 49rpx;
width: 100rpx;
image{
width: 51rpx;
height: 51rpx;
}
}
}
/deep/ .uni-calendar-item--extra{ /deep/ .uni-calendar-item--extra{
color: #333 !important; color: #333 !important;
} }

9
subPackages/ticket/index.vue

@ -82,12 +82,9 @@
}, },
viewDetail (item) { viewDetail (item) {
this.goOtherDetail(item) uni.navigateTo({
if(!item.link_type) { url:'/subPackages/ticket/detail?id='+item.id
uni.navigateTo({ })
url:'/subPackages/ticketBooking/detail?id='+item.id
})
}
}, },
}, },
onReachBottom() { onReachBottom() {

Loading…
Cancel
Save