<template> <view class="wrap"> <scroll-view @scroll="scroll" style="height: 100%;" scroll-y> <view class="banner"> <u-swiper :list="imgList" @change="e => currentNum = e.current" indicatorStyle="right: 20px;bottom:25px" height="400" circular> <view slot="indicator" class="indicator-num"> <text class="indicator-num__text">{{ currentNum + 1 }}/{{ imgList.length }}</text> </view> </u-swiper> </view> <view class="middle"> <!-- <view class="tabbar" :style="tabbarObj"> <text v-for="(item, index) in tabbar" :key="index" @click="tabbarChange(index)" :class="{ on: active == index }"> {{ item }} </text> </view> --> <swiper :current="active" @animationfinish="animationfinish" class="swiper-box" :style="{ height: swiperHeight + 'px' }"> <swiper-item class="swiper-item"> <checkbox-group @change="checkboxChange" class="checkbox-box"> <view class="merchant" v-for="(item, index) in scenicList" :key="index"> <view class="merchant-title" @click="clikDetail(item.id)"> <view class="title-left"> <text>{{ item.name }}</text> <template v-if="item.couponVoList && item.couponVoList.length > 0"> <image src="@/static/img/scenic/coupon.png"></image> <text class="title-coupon"> 劵惠 </text> </template> </view> <view v-if="showDistance" class="title-right"> 距您{{ item.distance ? parseFloat((item.distance / 1000).toFixed(2)) : 0 }}km <u-icon name="arrow-right" style="margin-left: 4rpx;"></u-icon> </view> </view> <label v-for="(items, a) in item.productListCopy" :key="a" :class="{ off: items.status == 2 }"> <view class="product" :class="{ on: items.ifChangeBg }"> <view class="product-left"> <checkbox style="transform: scale(0.8)" class="blue" :disabled="items.status == 2" :value="JSON.stringify(items)" :checked="items.ifChecked" /> </view> <view class="product-right"> <view class="product-name"> <text>{{ items.name }}</text> <text class="product-status" v-if="items.status == 2">{{ items.statusName }}</text> </view> <view class="product-price"> <view style="font-size: 24rpx;display: flex;"> <text class="product-rule" v-if="items.productRefundRuleVo"> <text v-if="items.productRefundRuleVo.refundType == 0">不可退</text> <text v-if="items.productRefundRuleVo.refundType == 1">有条件退</text> <text v-if="items.productRefundRuleVo.refundType == 2">随时可退</text> </text> <text class="product-rule"> 无需取票 </text> <text @click.stop="showBuyKnow(items)">购买须知</text> <u-icon name="arrow-right"></u-icon> </view> <view> <text class="product-orange"> ¥{{ items.originalPrice }} </text> <text class="product-sell"> <text style="font-size: 28rpx">¥</text>{{ items.sellingPrice }} </text> </view> </view> </view> </view> </label> <view class="product-more" v-if="index > 0 && item.productList.length > 2"> <view style="display: flex;justify-content: center;" v-if="item.productListCopy.length != item.productList.length" @click="showMoreProduct(item)"> 更多 <u-icon name="arrow-down"></u-icon> </view> <view style="display: flex;justify-content: center;" v-else @click="retractProduct(item)"> 收起 <u-icon name="arrow-up"></u-icon> </view> </view> </view> </checkbox-group> <u-empty text="空空如也..." mode="list" v-if="scenicList.length == 0" width="320" height="320"></u-empty> </swiper-item> <swiper-item class="swiper-item"> <u-waterfall v-model="albumList" class="waterfall" style="padding-top: 8rpx;"> <template v-slot:left="{leftList}"> <view v-for="(item, index) in leftList" :key="index" class="album-left" @click="goAlbum(index)"> <view class="album-list-top"> <image :src="item.image" mode="widthFix"></image> </view> <view class="album-list-bottom" :style="{'background': item.color}"> <view>{{item.title}}</view> <view>快来定制吧</view> <view> <view class="album-btn"> 点击定制 <u-icon name="arrow-right" style="margin-left: 4rpx;"></u-icon> </view> <text class="count">{{item.count}}</text> </view> </view> </view> </template> <template v-slot:right="{rightList}"> <view v-for="(item, index) in rightList" :key="index" class="album-right" @click="goAlbum(index)"> <view class="album-list-top"> <image :src="item.image" mode="widthFix"></image> </view> <view class="album-list-bottom" :style="{'background': item.color}"> <view>{{item.title}}</view> <view>快来定制吧</view> <view> <view class="album-btn"> 点击定制 <u-icon name="arrow-right" style="margin-left: 4rpx;"></u-icon> </view> <text class="count">{{item.count}}</text> </view> </view> </view> </template> </u-waterfall> </swiper-item> <swiper-item class="swiper-item"> <u-empty text="空空如也..." mode="list" width="320" height="320"></u-empty> </swiper-item> <swiper-item class="swiper-item"> <u-empty text="空空如也..." mode="list" width="320" height="320"></u-empty> </swiper-item> </swiper> </view> <view class="bottom"> <view class="bottom-left" @click="showCustomer()"> <u-icon name="chat" size="36"></u-icon> 客服 </view> <view class="bottom-middle"> <view class="bottom-more" v-show="chooseProduct.length > 0"> 组合购更优惠 <text class="bottom-three"></text> </view> <view class="bottom-detail" @click="showDetail()" :style="{ top: chooseProduct.length > 0 ? '-28rpx' : '0' }"> <text style="margin-right: 10rpx;"> 明细 </text> <u-icon name="arrow-up" size="32"></u-icon> <text class="bottom-number"> {{ chooseProduct.length }} </text> </view> </view> <view class="bottom-right"> <text class="btn" @click="goFillorder()">去预定</text> </view> </view> <!-- 客服组件 --> <customer :scenicList="scenicList" ref="customer"></customer> <!-- 购买须知 --> <buyKnow :buyKnowData="buyKnowData" ref="buyKnow"></buyKnow> <!-- 产品明细 --> <detail :chooseProduct="chooseProduct" ref="detail"></detail> <!-- 商户详情 --> <merchantDetail :detailData='detailData' ref='merchantDetail'></merchantDetail> <!-- 模态框 --> <u-modal :show="showModal" @confirm="chooseConfirm" @cancel="chooseCancel" title="提示" content="该产品不支持多选" show-cancel-button="true"> </u-modal> </scroll-view> <image class="suodaoImg" v-if="showSuodaoImg" src="https://lx.pangdly.com/img/cjsdFirst.50a2e63.jpg"></image> </view> </template> <script> import customer from '@/components/customer.vue' //客服 import buyKnow from '@/components/buyKnow.vue' //购买须知 import detail from './components/detail.vue' //购买须知 import UWaterfall from '@/uview-ui/components/u-waterfall/u-waterfall.vue' import merchantDetail from '@/components/merchantDetail' //详情弹窗 export default { components: { customer, buyKnow, detail, UWaterfall, merchantDetail }, data() { return { detailData:'',//详情数据 showSuodaoImg:false,//索道耳麦图片是否显示隐藏 companyId:'',//公司Id merchantId: '', //商户Id // tabbar:['热门景点','一日游','摄影/旅拍','文创DIY'],//tabbar标题列表 tabbar: ['热门景点', '摄影/旅拍', '一日游'], //tabbar标题列表 active: 0, //导航栏下标 currentNum:0,//轮播图下标 imgList: [], //图片列表 scenicList: [], //景区数据 showDistance: false, //定位成功显示距离 buyKnowData: '', //购买须知数据 chooseProduct: [], //选中的产品 showModal: false, //是否显示模态框 chooseMerchantProduct: '', //不支持多产品购买时,选中的景区产品 groupId: '', //组合Id groupChannelId: '', //组合渠道Id channelType: 0, //渠道类型 swiperHeight: 0 ,//swiper高度 tabbarObj:'', albumList: [{ title: '精彩瞬间', count: '10W+', image: '../static/scenic/wonderfulMoment.png', color: '#037EFF' }, { title: '网红旅拍', count: '8W+', image: '../static/scenic/travalphoto.png', color: '#826847' }, { title: '抱枕DIY', count: '4W+', image: '../static/scenic/pillow.png', color: '#1175B4' }, { title: '明信片', count: '4W+', image: '../static/scenic/postcard.png', color: '#3478DC' }, { title: '旅游台历定制', count: '4W+', image: '../static/scenic/deskCalender.png', color: '#1A9B45' }, { title: '定制相册', count: '4W+', image: '../static/scenic/customPic.png', color: '#D48D46' } ], } }, watch: { //选中产品的数量变化 chooseProduct: { handler(newValue, oldValue) { //当选中产品时 if (newValue.length > oldValue.length) { //找到当前选中的产品 let product = newValue[newValue.length - 1] //商家一级 let merchant = '' //通过产品一级找到商家一级 this.scenicList.forEach(item => { if (item.id == product.merchantId) { merchant = item } }) //当选中产品的景区有2个以上选中产品时 let number = 0 this.chooseProduct.forEach(item => { if (merchant.id == item.merchantId) { number += 1 } }) if (product.isMoreBuy !== 0) { if (number > 1) { //显示确认弹窗 this.showModal = true //当前选中的景区产品,用于确定以及取消方法取值 this.chooseMerchantProduct = product } } else { //支持多产品购买时,删除该景区其他产品不支持多产品购买的产品 this.chooseProduct.forEach((item, index) => { if (merchant.id == item.merchantId && item.isMoreBuy !== 0) { //取消选中状态和选中背景颜色 this.scenicList.forEach(item2 => { item2.productList.forEach(item3 => { if (item.id == item3.id) { item3.ifChecked = false item3.ifChangeBg = false } }) }) delete this.chooseProduct[index] } }) this.chooseProduct = this.chooseProduct.filter(function (val) { return val }) } } }, deep: true, immediate: false } }, onLoad(option) { //获取公司Id,保存到本地,支付等逻辑需要入口companyId this.companyId=this.$commonjs.getCompanyId(option) this.channelType = option.channelType || 0 this.merchantId = option.merchantId || '' }, onShow() { //如果是索道 if(this.merchantId=='z0015605022691a5945bbe463141668c'){ this.showSuodaoImg=true setTimeout(() => { this.showSuodaoImg = false }, 2500) } //清空之前选中的数据 this.detailData='' this.chooseProduct=[] let token = uni.getStorageSync('token') if (token) { uni.getLocation({ type: 'wgs84', success: res => { let latitude = res.latitude //纬度 let longitude = res.longitude //经度 this.showDistance = true this.initList(latitude, longitude) }, fail: res => { let latitude = '' let longitude = '' this.initList(latitude, longitude) } }) } }, methods: { //---页面滚动事件 scroll(e) { if(e.detail.scrollTop>200){ //固定导航栏 this.tabbarObj='top:0;position:fixed;border-radius:0' }else{ this.tabbarObj='top:-40rpx;position:relative;border-radius:16rpx;' } }, //---导航栏切换 tabbarChange(index) { this.active = index if(index==0){ this.countSwiper() } if(index==1){ this.countSwiper('waterfall') } }, //---swiper滑动结束,分别设置tabs和swiper的状态 animationfinish(e) { let current = e.detail.current this.active = current }, //---展示客服组件 showCustomer() { this.$refs.customer.showPop = true }, //---展示购买须知 showBuyKnow(data) { this.buyKnowData = data this.$refs.buyKnow.showPop = true }, //---点击详情 clikDetail(merchantId){ this.$refs.merchantDetail.showPop=true this.initDetail(merchantId) }, //---初始化详情 initDetail(merchantId){ let data={ userId:uni.getStorageSync('userId')||'', openid:uni.getStorageSync('openid')||'', id:merchantId,//商户id isDetail:1,//商户详情 } this.detailData='' this.$request('scenic/user/merchant/findDetailInfo',data).then((res)=>{ if(res.code=='00'){ this.detailData=res.data }else{ uni.showToast({ title: res.message, icon: 'none' }) } }) }, //---展示明细弹窗 showDetail() { this.$refs.detail.showPop = true }, //计算第一个swiper高度 countSwiper(label){ let labels=label||'checkbox-box' this.$nextTick(() => { const query = uni.createSelectorQuery().in(this) query.select(`.${labels}`).boundingClientRect(data => { this.swiperHeight=data.height }).exec() }) }, //---展示更多产品 showMoreProduct(item) { item.productListCopy = item.productList this.$forceUpdate() this.countSwiper() }, //---收起产品 retractProduct(item) { item.productListCopy = item.productList.slice(0, 2) this.$forceUpdate() this.countSwiper() }, //---多选框变化 checkboxChange(e) { let value = e.detail.value let arr = [] value.forEach(item => { arr.push(JSON.parse(item)) }) this.chooseProduct = arr //判断是否选中产品,选中产品的背景颜色需要变化 this.scenicList.forEach(item => { item.productList.forEach(item2 => { item2.ifChangeBg = false this.chooseProduct.forEach(item3 => { if (item2.id == item3.id) { item2.ifChangeBg = true //解决是否支持多产品购买弹窗2次之后,选中状态错误bug,需要在选中时修改状态 item2.ifChecked = true } }) }) }) }, //---不支持多选产品,选择确定事件 chooseConfirm() { this.chooseProduct.forEach((item, index) => { //删除选中产品以外的其他所有产品 if (this.chooseMerchantProduct.merchantId == item.merchantId && JSON.stringify(item) != JSON.stringify(this.chooseMerchantProduct)) { //取消选中状态和选中背景颜色 this.scenicList.forEach(item2 => { item2.productList.forEach(item3 => { if (item.id == item3.id) { item3.ifChecked = false item3.ifChangeBg = false } }) }) delete this.chooseProduct[index] } }) this.chooseProduct = this.chooseProduct.filter(function (val) { return val }) this.showModal = false }, //---不支持多选产品,选择取消事件 chooseCancel() { //删除选中产品 this.chooseProduct.forEach((item, index) => { if (item.id === this.chooseMerchantProduct.id) { //取消选中状态和选中背景颜色 this.scenicList.forEach(item2 => { item2.productList.forEach(item3 => { if (item.id == item3.id) { item3.ifChecked = false item3.ifChangeBg = false } }) }) this.chooseProduct.splice(index, 1) } }) this.showModal = false }, //---商品列表 initList(latitude, longitude) { let data = { merchantId: this.merchantId, //商户id openid: uni.getStorageSync('openid') || '', channelType: this.channelType, //渠道类型 latitude, longitude } this.$request('/scenic/groupGood/getGroupProducts', data).then(res => { if (res.code == '00') { this.scenicList = res.data.merchantList || [] this.groupId = res.data.groupId || '' this.groupChannelId = res.data.groupChannelId || '' this.scenicList.forEach((item, index) => { //获取当前景区图片,把当前景区放在第一位 if (item.id == this.merchantId) { this.imgList = item.imgList this.scenicList.splice(index, 1) this.scenicList.unshift(item) item.productListCopy = item.productList } else { item.productListCopy = item.productList.slice(0, 2) } //预订时间为当天时,当前时间大于最早预订时间显示未开售,当前时间大于最晚预订时间显示已售罄 let times = new Date().Format('hh:mm:ss') let timeNumber = parseInt(this.$commonjs.changeTime(times)) //将当前时间转化为数字 item.productList.forEach(item2 => { item2.timeNumber1 = parseInt(this.$commonjs.changeTime(item2.earlyBookTime)) item2.timeNumber2 = parseInt(this.$commonjs.changeTime(item2.bookTime)) if (item2.aheadBookDays == 0) { if (item2.status == 2) { item2.statusName = '已售罄' } else { if (timeNumber < item2.timeNumber1) { item2.status = 2 item2.statusName = '未开售' } if (timeNumber > item2.timeNumber2) { item2.status = 2 item2.statusName = '已售罄' } } } }) }) this.$nextTick(() => { this.countSwiper() }) } else { uni.showToast({ title: res.message, icon: 'none' }) } }) }, //---跳转填写订单页面 goFillorder() { for (let i = 0; i < this.chooseProduct.length; i++) { let item = this.chooseProduct[i] if (item.status == 2) { uni.showToast({ title: '售罄产品不能进行购买', icon: 'none' }) return } } if (this.chooseProduct.length == 0) { uni.showToast({ title: '请选择至少一个产品', icon: 'none' }) return } else if (this.chooseProduct.length == 1) { let query = '?merchantId=' + this.chooseProduct[0].merchantId + '&productId=' + this.chooseProduct[0].id + '&orderSource=3' if (this.chooseProduct[0].ticketType == 2) { //联票 uni.navigateTo({ url: '/pages/scenic/scenicJointOrder/scenicJointOrder' + query }) } else { //普通票 uni.navigateTo({ url: '/pages/scenic/scenicSingleOrder/scenicSingleOrder'+ query }) } } else { let productIdList = this.chooseProduct.map(item => { return item.id }) let query ='?productIdList=' + JSON.stringify(productIdList) + '&groupId=' + this.groupId + '&groupChannelId=' + this.groupChannelId + '&orderSource=3' uni.navigateTo({ url: '/pages/scenic/scenicCombiOrder/scenicCombiOrder' + query }) } }, //---跳转影集页面 goAlbum(index){ if(index==0){ let data={ openid: uni.getStorageSync('openid')||'' } this.$request('wechatUser/pdFace/checkScanFace',data).then(res => { if (res.code === '00') { let merchantId = this.merchantId || 'z0015605022691a5945bbe463141668c' // 默认长江索道 if (res.data.isScanFace == 0) { //未扫脸 uni.navigateTo({ url:`/pages/album/getPortrait?merchantId=${merchantId}` }) } else if (res.data.isScanFace == 1) { //已扫脸 let faceIds = JSON.stringify(res.data.faceIds) let companyId = this.companyId uni.navigateTo({ url: `/pages/album/myPhotoAlbum/myPhotoAlbum?faceIds=${faceIds}&companyId=${companyId}&merchantId${merchantId}` }) } } else { uni.showToast({ title: res.message, icon: 'none' }) } }) } }, } } </script> <style lang="scss" scoped> .wrap { height: 100%; display: flex; flex-direction: column; background: #fff; } .middle { padding: 0 24rpx 100rpx 24rpx; display: flex; flex-direction: column; // flex: 1; background: #f7f7f7; } .swiper-box { // flex: 1; position: relative; top: -40rpx; } .tabbar { transition:1s; width: 100%; left: 0; z-index: 1; position: relative; top: -40rpx; background: #fff; box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, 0.08); border-radius: 16rpx; display: flex; justify-content: space-between; font-size: 32rpx; text { padding: 24rpx 32rpx 24rpx 20rpx; border-radius: 16rpx; width: 33.3%; text-align: center; } } .tabbar .on { // background: url('../../../static/img/scenic/tabbar.png') no-repeat; background: $theme; background-size: 100% 100%; color: #fff; font-weight: bold; } .merchant { border-radius: 16rpx; background: #ffffff; margin-top: 24rpx; padding: 24rpx; } .merchant label{ width: 100%; } .merchant label.off .product { background: #f3f3f3; color: #999999; } .merchant label.off .product-name { color: #999999; } .merchant label.off .product-rule { color: #999999; } .merchant-title { display: flex; justify-content: space-between; align-items: center; padding-bottom: 16rpx; } .title-left { font-size: 32rpx; margin-right: 10rpx; font-weight: bold; image { width: 36rpx; height: 36rpx; position: relative; top: 6rpx; margin: 0 8rpx; } } .title-coupon { color: $red; font-size: 24rpx; } .title-right { color: $grey; font-size: 24rpx; display: flex; } .product { padding: 10rpx 16rpx; background: #ffffff; border-radius: 8rpx; display: flex; align-items: center; margin-top: 10rpx; } .product.on { background: #e2eeff; } .product-left { margin-right: 10rpx; } .product-right { flex: 1; } .product-name { font-size: 28rpx; font-weight: bold; color: #191919; display: flex; justify-content: space-between; } .product-status { padding: 6rpx 12rpx; border: 2px solid #f40000; background: #ffffff; color: #f40000; font-size: 24rpx; border-radius: 4rpx; transform: rotate(-25deg); position: relative; top: 30rpx; right: 80rpx; } .product-price { display: flex; justify-content: space-between; align-items: center; } .product-rule { color: $theme; } .product-rule::after { display: inline-block; content: ''; height: 22rpx; margin: 0 10rpx; background: #ccc; width: 1px; } .product-orange { font-size: 20rpx; color: $grey; text-decoration: line-through; } .product-sell { font-size: 40rpx; color: $red; font-weight: bold; margin-left: 10rpx; } .product-more { padding: 10rpx; text-align: center; } .bottom { position: fixed; bottom: 0; width: 100%; height: 100rpx; background: #fff; box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.16); z-index: 10; display: flex; align-items: center; justify-content: space-between; padding: 0 32rpx; } .bottom-left{ display: flex; flex-direction: column; align-items: center; } .bottom-middle { position: relative; padding: 0 40rpx; } .bottom-more { position: relative; top: -40rpx; background: #f40000; border-radius: 28px; opacity: 0.64; padding: 10rpx 20rpx; color: #ffffff; } .bottom-three { width: 14rpx; height: 14rpx; display: inline-block; background: #f40000; opacity: 0.64; position: absolute; right: 42rpx; bottom: -7rpx; transform: rotate(45deg); } .bottom-detail { position: relative; text-align: center; display: flex; justify-content: center; } .bottom-number { display: inline-block; width: 36rpx; height: 36rpx; border-radius: 50%; text-align: center; background: #f40000; color: #ffffff; font-weight: bold; margin-left: 10rpx; } .btn { font-size: 32rpx; width: 200rpx; } //摄影、旅拍 .album-left{ margin:8rpx 6rpx 0 0; } .album-right{ margin: 8rpx 0 0 6rpx; } .album-list-top image { width: 100%; } .album-list-bottom{ border-radius: 0 0 16rpx 16rpx; position: relative; top: -4px; padding: 20rpx 16rpx; color: #fff; view:first-child{ font-weight: bold; } view:nth-child(2){ font-size: 24rpx; margin-top: 16rpx; } view:nth-child(3){ display: flex; justify-content: space-between; margin-top: 20rpx; } } .album-btn{ display: flex; width: 160rpx; height: 44rpx; background: #E1E1D9; border-radius: 20rpx 20rpx 20rpx 20rpx; font-size: 22rpx; color: #333333; align-items: center; justify-content: center; padding-left: 8rpx; } .suodaoImg{ position: fixed; z-index: 9999; width: 100%; height: 100%; } .swiper-item /deep/ .u-waterfall{ padding-top:8rpx; } .swiper-item /deep/ .u-empty{ height: 300px; } </style>