You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

389 lines
13 KiB

<script setup>
import { onLoad, onReady } from '@dcloudio/uni-app';
import { reactive, ref, computed, watch, nextTick, onMounted, getCurrentInstance } from 'vue';
import { stadiumBookList } from "@/api";
import { venueTypes, bookDate, bookList, orderAdd } from '../api';
import { getNodeMes, showModal } from "@/utils/polish";
import { debounce } from "@/utils";
import siteTable from "../components/site/table.vue";
import siteFooter from "../components/site/footer.vue";
import { get_zh_day, get_zh_date } from "../js/site_select/handle";
const optQuery = ref({});
const siteData = ref([]); // 场地表格数据
const scrollHeight = ref(0); // table 高度
const venueTypeData = ref([]); // 场地类型列表
const currentVenueType = ref({}); // 当前场地类型
const bookDateData = ref([]); // 日期列表
const currentBookDate = ref({}); // 当前选中日期
const isShowTypeRuleTxt = ref(false);
const APPID = tt.getEnvInfoSync()?.microapp?.appId ?? '';
const stadiumInfo = ref({}); // 场馆信息
let ticketInfo = null; // 票券信息
const selectedData = computed(_=>{ // 已选中场地
let _temArr = [];
siteData.value.forEach(e=>{
if(e?.items?.length <= 0)return;
e?.items.forEach(ele=>{
if(!ele?._is_selected)return;
_temArr.push({
...ele,
_venue_id: e?.id ?? 0,
_venue_name: e?.name ?? '',
_class_tag: e?.class_tag ?? '',
})
})
});
return _temArr
})
watch(selectedData, val=>nextTick(setScrollViewSize));
onMounted(() =>{
const instance = getCurrentInstance().proxy
const eventChannel = instance.getOpenerEventChannel();
eventChannel.on('dataFromGrouponStadiums', data => {
console.log(`site select onload dataFromGrouponStadiums-->`, data);
ticketInfo = data?.ticket || {};
stadiumInfo.value = data?.stadium || {};
if(!stadiumInfo.value?.id)return showModal({ content: '无效的场馆信息' });
initPage(data?.stadium?.id);
})
})
async function initPage(stadium_id){
try{
let _vtLs = await getTypeLs(stadium_id);
if(_vtLs?.length <=0)return showModal({ content: '没有场地类型!' });
let _cvt = currentVenueType.value = _vtLs[0];
let _dateLs = await getDateLs({ stadium_id, type_key: _cvt?.key ?? '', });
if(_dateLs?.length <= 0)return showModal({ content: '没有日期列表!' });
let _curDate = currentBookDate.value = _dateLs[0];
nextTick(setScrollViewSize)
getBookList({ stadium_id, type_key: _cvt?.key ?? '', date: _curDate?._date ?? '' });
}catch(err){
console.warn(`site select onload err-->`, err);
}
}
// 类型切换
async function venueTypeChange(e){
let _cvt = venueTypeData.value[e.detail.value];
currentVenueType.value = _cvt;
bookDateData.value = [];
currentBookDate.value = {};
siteData.value = [];
try{
let stadium_id = stadiumInfo?.value?.id ?? '';
let _dateLs = await getDateLs({ stadium_id, type_key: _cvt?.key ?? '', });
if(_dateLs?.length <= 0)return showModal({ content: '没有日期列表!' });
let _curDate = currentBookDate.value = _dateLs[0];
nextTick(setScrollViewSize)
getBookList({ stadium_id, type_key: _cvt?.key ?? '', date: _curDate?._date ?? '' });
}catch(err){
console.warn(`site select venueTypeChange err-->`, err);
}
}
// 日期切换
async function bookDateChange(_date){
currentBookDate.value = _date;
siteData.value = [];
try{
let stadium_id = stadiumInfo?.value?.id ?? '';
let _cvt = currentVenueType.value ?? {}
getBookList({ stadium_id, type_key: _cvt?.key ?? '', date: _date?._date ?? '' });
}catch(err){
console.warn(`site select bookDateChange err-->`, err);
}
}
// 清除已选
function clearSelectedData(){
let stadium_id = stadiumInfo?.value?.id ?? '';
let _key = currentVenueType.value?.key ?? '';
let _date = currentBookDate.value?._date ?? '';
getBookList({ stadium_id, type_key: _key, date: _date });
}
// 类型接口
function getTypeLs(stadium_id){
return venueTypes({ data: { stadium_id }, catch: true })
.then(res=>{
return venueTypeData.value = res?.data ?? [];
})
}
// 添加自定义日期字段
function formateDateLs(dates){
if(dates?.length <= 0)return [];
return dates.map(e=>{
const _date = e.date.substr(0,10);
return {
...e,
_date,
_zh_day: get_zh_day(_date.replace(/\-/g,'/')),
_zh_date: get_zh_date(_date.replace(/\-/g,'/')),
}
})
};
// 日期列表
function getDateLs({ stadium_id, type_key, num = 8 }){
return bookDate({
data: {
stadium_id,
type_key,
num
},
catch: true
})
.then(res=>{
return bookDateData.value = formateDateLs(res?.data ?? []);
});
}
// 可预订场馆,矩阵图 时间+场馆
function getBookList({
stadium_id,
date = '',
type_key = ``
}){
return bookList({ data: {
stadium_id,
date,
type_key,
} })
.then(res=>{
return siteData.value = res?.data;
})
}
// 获取table 高度
async function setScrollViewSize(){
const _sysInfo = uni.getSystemInfoSync();
let _headerInfo = await getNodeMes('#ssHeader');
let _dateBarInfo = await getNodeMes(`#smDates`);
let _footerInfo = await getNodeMes('#ssFooter');
let _otherHeight = _headerInfo?.height + _footerInfo?.height + _dateBarInfo?.height;
scrollHeight.value = _sysInfo?.windowHeight - (_otherHeight || 0);
}
const submitClick = debounce(function(venues){
let _sVal = stadiumInfo.value;
let _vInfo = {
classify: currentVenueType.value?.key ?? '',
typeName: currentVenueType.value?.name ?? '',
date: (currentBookDate.value?.date ?? '').slice(0, 10),
zh_day: currentBookDate.value?._zh_day,
venues: venues.map(e=>({
time: e?.time ?? '',
venue_name: e?._venue_name ?? '',
venue_id: e?._venue_id ?? '',
price: e?.price ?? '',
date: e?.date ?? '',
index: e?.index ?? '',
_class_tag: e?._class_tag ?? '',
}))
}
let _classTags = (_vInfo?.venues ?? []).map(e=>e?._class_tag ?? '');
// 用 add 检查是否存在连场禁止下单
return orderAdd({ data: {
appid: APPID,
brand_id: _sVal?.brand_id ?? '',
stadium_id: _sVal?.id ?? '',
date: _vInfo?.date,
sessions: (_vInfo?.venues || []).map(el=>({
venue_id: el?.venue_id ?? '',
duration: el?.time ?? '',
price: el?.price ?? 0,
tag: el?._class_tag ?? '',
})),
type_key: _vInfo?.classify ?? '',
class_tags_enable: _classTags.filter(e=>e!=='').join(','),
douyin_merchant_pay_amount: ticketInfo?.douyin_merchant_pay_amount ?? 0,
douyin_groupon_coupon_code: ticketInfo?.certificate_id ?? '',
} })
.then(res=>{
if(res?.code === 0 && res?.data?.order_no){
uni.navigateTo({
url: `/subpackage/groupon/pages/confirm_order/venue`,
success: res => {
res.eventChannel.emit('dataFromGrouponSiteSelect', {
stadium: stadiumInfo.value,
ticket: ticketInfo,
venueInfo: _vInfo,
})
}
});
}
})
}, 300, true);
</script>
<template>
<view class="site-select">
<view class="ss-header" id="ssHeader">
<view class="sh-stadium">
<image v-if="stadiumInfo?.logo" mode="aspectFit" class="ss-logo" :src="stadiumInfo.logo"></image>
<view class="ss-name">{{ stadiumInfo?.name ?? '-' }}</view>
</view>
<view class="sh-bottom">
<picker class="sb-classify" mode='selector' :range="venueTypeData" range-key="name" @change="venueTypeChange">
<view class="sc-txt">{{ currentVenueType?.name ?? '-' }}</view>
<view class="sc-icon">&#xe695;</view>
</picker>
<view class="sb-desc">
<view class="sd-txt">{{ currentVenueType?.rule_text ?? '' }}</view>
<view class="sd-arrow-cover" @click="isShowTypeRuleTxt = !isShowTypeRuleTxt" v-if="currentVenueType?.rule_text?.length > 17"><text>&#xe695;</text></view>
<view class="sd-full-txt" v-if="isShowTypeRuleTxt&&currentVenueType?.rule_text?.length > 17">{{ currentVenueType?.rule_text ?? '' }}</view>
</view>
</view>
</view>
<view class="ss-main">
<scroll-view class="sm-dates" id="smDates" scroll-x>
<view
class="sd-item"
:class="{ active: currentBookDate.date === e.date }"
v-for="(e, i) in bookDateData"
:key="i"
@click="bookDateChange(e)"
>
<view class="si-week">{{ e._zh_day ?? '-' }}</view>
<view class="si-day">{{ e._zh_date ?? '-' }}</view>
</view>
</scroll-view>
<site-table
:altitude="scrollHeight"
v-model:sitetable="siteData"
></site-table>
</view>
<view class="ss-footer" id="ssFooter">
<site-footer
:selected-data="selectedData"
@click:clear="clearSelectedData"
@click:submit="submitClick"
></site-footer>
</view>
</view>
</template>
<style lang="scss" scoped>
@include rightArrow;
.site-select{
}
.ss-header{
padding: 24upx;
.sh-stadium{
@include ctf;
.ss-logo{
flex-shrink: 0;
margin-right: 20upx;
width: 36upx;
height: 36upx;
}
.ss-name{
flex-grow: 1;
@include flcw(32upx, 44upx, #333, 500);
@include tHide;
}
}
.sh-bottom{
margin-top: 38upx;
@include ctf(space-between);
.sb-classify{
@include ctf;
.sc-txt{
max-width: 220upx;
@include flcw(36upx, 50upx, #333, 500);
@include tHide;
}
.sc-icon{
margin-left: 10upx;
font-family: rightArrow;
transform: rotateZ(90deg);
@include flcw(36upx, 50upx, #333, 500);
}
}
.sb-desc{
position: relative;
.sd-txt{
max-width: 346upx;
@include flcw(24upx, 34upx, #9B9B9B);
@include tHide;
}
.sd-arrow-cover{
position: absolute;
right: 0;
top: 0;
padding-right: 8upx;
height: 34upx;
width: 76upx;
background-image: linear-gradient(270deg, #FFFFFF 50%, rgba(255,255,255,0.00) 99%);
text-align: right;
@include flcw(24upx, 34upx, #9B9B9B);
>text{
display: inline-block;
font-family: rightArrow;
transform: rotateZ(90deg);
}
}
.sd-full-txt{
position: absolute;
right: 0upx;
top: calc(100% + 10upx);
width: 462upx;
max-height: 300upx;
overflow-y: scroll;
z-index: 30;
padding: 22upx;
border-radius: 6upx;
background-color: #fff;
box-shadow: 0 0 8upx 0 #002c2229;
@include flcw(24upx, 40upx, #333);
}
}
}
}
.ss-main{
.sm-dates{
background-color: #fff;
border-bottom: 1px solid #D8D8D8;
white-space: nowrap;
.sd-item{
display: inline-block;
position: relative;
padding: 30upx 20upx 0;
height: 136upx;
&.active{
&::after{
content: '';
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 70%;
height: 10upx;
border-radius: 6upx;
background-color: $mColor;
}
.si-week, .si-day{
color: $mColor;
font-weight: 500;
}
}
.si-week{
text-align: center;
@include flcw(32upx, 44upx, #9A9A9D);
}
.si-day{
text-align: center;
@include flcw(24upx, 34upx, #9A9A9D);
}
}
}
}
.ss-footer{
position: fixed;
left: 0;
bottom: 0;
width: 100%;
}
</style>