1646 lines
56 KiB
Vue
1646 lines
56 KiB
Vue
<template>
|
||
<view>
|
||
<!-- #ifdef APP-PLUS -->
|
||
<simple-watermark ref="watermark"></simple-watermark>
|
||
<!-- #endif -->
|
||
<view>
|
||
<view class="hz-page">
|
||
<view class="u-navbar" :show="showNavbar" :style="{ opacity: navbarOpacity }">
|
||
<view class="u-navbar__placeholder" :style="{
|
||
height: navbarHeight+'px',
|
||
backgroundColor: bgColor,
|
||
}"></view>
|
||
<view :class="[true && 'u-navbar--fixed']">
|
||
<u-status-bar :bgColor="bgColor"></u-status-bar>
|
||
<view class="u-navbar__content" :style="{
|
||
height: navbarHeight,
|
||
backgroundColor: bgColor,
|
||
}">
|
||
<view class="u-navbar__content__left">
|
||
<slot name="left">
|
||
<u-icon
|
||
size="28px" v-if="showTrashIcon()" @click="setCalendar()" name="../../static/images/filter-clear.svg"
|
||
></u-icon>
|
||
</slot>
|
||
</view>
|
||
<slot name="center">
|
||
<text class="u-line-1 u-navbar__content__title">{{ $t('todo.title') }}</text>
|
||
</slot>
|
||
<view class="u-navbar__content__right">
|
||
<slot name="right">
|
||
<p-checkbox :isOpen="isOpen" @toggle="switchFilterType"></p-checkbox>
|
||
</slot>
|
||
</view>
|
||
</view>
|
||
<view class="hz-flex-row" style="height:30px;line-height:44px;" :style="{
|
||
backgroundColor: bgColor,
|
||
}">
|
||
<view class="hz-flex-row" style="justify-content: center;align-items: center;" :style="{width: currentIndex==2 || currentIndex==3? '100%':'90%'}">
|
||
<view class="tabs-container">
|
||
<view class="tabs-row">
|
||
<view v-for="(tab, index) in tabs" :key="index" class="tab"
|
||
:class="{active: currentIndex === index}" :data-index="index"
|
||
@tap="switchTab(index)" :id="'tab'+index">
|
||
<view @click="handlerGetToDoList(index)">{{tab.name}}</view>
|
||
</view>
|
||
</view>
|
||
<view class="slider-container" id="slider-container">
|
||
<view class="slider" :style="{
|
||
left: sliderPosition + 'px',
|
||
backgroundColor: tabs[currentIndex].color
|
||
}"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view v-if="currentIndex==2 || currentIndex==3? false:true" @click="openCalendar()" class="hz-flex-row" style="width:10%;justify-content: center;align-items: center;">
|
||
<u-icon name="calendar" :size="30" :color="calendarIconColor"></u-icon>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!--content begin-->
|
||
<view v-if="showTodoListView" class="hz-spacing" style="position: relative;top:44px;">
|
||
<view v-if="currentIndex !== 3" v-for="(record,index) in listData"
|
||
:key="'record'+index" style="margin-bottom:8px;">
|
||
<view class="hz-date-title">{{record.date}}</view>
|
||
<uni-swipe-action v-for="(rowRecord,index) in record.dateRecords" :key="'row'+index"
|
||
:style="{marginTop: index==0? '6px':'0px'}">
|
||
<uni-swipe-action-item ref="swipeAction" :show="rowRecord.itemOpen" :autoClose="false" @change="changeTest(rowRecord,1,$event)">
|
||
<uni-card @click="fetchTodoDetail(rowRecord)"
|
||
style="margin-left:4rpx;margin-right:4rpx;margin-top:4px;margin-bottom:4px;padding:12px;position:relative;">
|
||
<!-- ETA标签 -->
|
||
<!-- <view class="conner-label conner-label-eta"> -->
|
||
<view v-show="showETA(rowRecord)"
|
||
class="conner-label" :style="{ backgroundColor: getETAColor(rowRecord) }">
|
||
<view class="conner-label-text" :style="{color: getTextColor(rowRecord)}">{{getETALable(rowRecord)}}</view>
|
||
</view>
|
||
<u-row>
|
||
<u-col span="11">
|
||
<view class="hz-font-color-dark hz-font-md text-truncate">
|
||
<template v-if="rowRecord.playerId">{{ rowRecord.playerId }}</template>
|
||
<template v-if="rowRecord.englishName"><span style="color: gray;">/</span>{{ rowRecord.englishName }}
|
||
</template>
|
||
<template v-if="rowRecord.tierName"><span style="color: gray;">/</span>({{ rowRecord.tierName }})
|
||
</template>
|
||
<span v-if="rowRecord.hasArrivalRecord == 1" class="dot-arrival"></span>
|
||
<span v-if="rowRecord.hasDepartureRecord == 1" class="dot-departure"></span>
|
||
<span v-if="rowRecord.hasInhouseRecord == 1" class="dot-inhouse"></span>
|
||
<span v-if="rowRecord.hasOthersRecord == 1" class="dot-other"></span>
|
||
</view>
|
||
</u-col>
|
||
<u-col span="1" align="flex-end" justify="flex-end" textAlign="right">
|
||
<u-icon :name="rowRecord.arrowName"
|
||
v-if="!rowRecord.showDetailLoading"></u-icon>
|
||
<u-loading-icon mode="circle" :size="18"
|
||
v-if="rowRecord.showDetailLoading"></u-loading-icon>
|
||
</u-col>
|
||
</u-row>
|
||
<view class="hz-flex-row" style="align-items: flex-start;">
|
||
<view class="text-container" v-if="!rowRecord.showDetail">
|
||
<span v-for="(itemRecord,index) in rowRecord.descriptions" :key="'item'+index"
|
||
class="hz-date-des"
|
||
style="display:flex;flex-direction:row;align-items:center;">{{getItemDescription(itemRecord)}}
|
||
<image
|
||
v-show="index == 0 && currentIndex !== 2 && rowRecord.hasFlightRecord ===1"
|
||
src="../../static/images/flight_line.svg" class="icon-img-flight">
|
||
</image>
|
||
<image
|
||
v-show="index == 0 && currentIndex !== 2 && rowRecord.hasLimoRecord ===1"
|
||
src="../../static/images/limo_line.svg" class="icon-img-limo"></image>
|
||
<image v-show="getItemShowSharerIcon(itemRecord)"
|
||
src="../../static/images/sharer_line.svg" class="icon-img-sharer">
|
||
</image>
|
||
<span v-show="itemRecord.isQueue"> (In Queue) </span>
|
||
<span v-show="itemRecord.roomReady"> (Room Ready) </span>
|
||
</span>
|
||
</view>
|
||
<!-- 直接使用v-if配合CSS动画类 -->
|
||
<view v-if="rowRecord.showDetail" class="detail-content"
|
||
:class="{'detail-show': rowRecord.showDetail, 'detail-ide': !rowRecord.showDetail}"
|
||
style="width:100%;">
|
||
<view>Location: {{rowRecord.detailData.location}}</view>
|
||
<view v-show="filterType==='IM'">Active Prg Id: {{rowRecord.detailData.activePrgId}}</view>
|
||
<u-row customStyle="margin-top:10px;" v-show="filterType=='MASS'">
|
||
<u-col
|
||
v-show="(currentIndex === 1 || currentIndex === 2)"
|
||
span="6">
|
||
<view class="hz-font-12px">Today TPD : {{formatNumber(rowRecord.detailData.todayTPD)}}
|
||
</view>
|
||
<view class="hz-font-12px">Today Win : {{formatNumber(rowRecord.detailData.todayWin)}}
|
||
</view>
|
||
<view v-show="currentIndex === 2 && filterType ==='MASS'" class="hz-font-12px">Today Theo : {{formatNumber(rowRecord.detailData.todayTheo)}}
|
||
</view>
|
||
</u-col>
|
||
<u-col v-show="currentIndex === 2" span="6">
|
||
<view class="hz-font-12px">Trip TPD: {{formatNumber(rowRecord.detailData.tripTPD)}}</view>
|
||
<view class="hz-font-12px">Trip Win: {{formatNumber(rowRecord.detailData.tripWin)}}</view>
|
||
<view class="hz-font-12px">Trip RI%: {{getPercentFormat(rowRecord.detailData.tripRIPercentage)}}
|
||
</view>
|
||
<view v-show="currentIndex === 2 && filterType ==='MASS'" class="hz-font-12px">Trip Theo : {{formatNumber(rowRecord.detailData.tripTheo)}}
|
||
</view>
|
||
</u-col>
|
||
</u-row>
|
||
<u-row v-show="filterType==='IM'&¤tIndex===0" customStyle="margin-top:10px;">
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">Prg T/O : {{formatNumber(rowRecord.detailData.prgTO)}}
|
||
</view>
|
||
<view class="hz-font-12px">Prg Win : {{formatNumber(rowRecord.detailData.prgWin)}}
|
||
</view>
|
||
</u-col>
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">Front Money: {{formatNumber(rowRecord.detailData.frontMoney)}}</view>
|
||
<view class="hz-font-12px">TTO: {{formatNumber(rowRecord.detailData.tto)}}</view>
|
||
<view class="hz-font-12px">0.1Comp Balance: {{formatNumber(rowRecord.detailData.comBalance)}}
|
||
</view>
|
||
</u-col>
|
||
</u-row>
|
||
|
||
<u-row v-show="filterType==='IM'&¤tIndex===1" customStyle="margin-top:10px;">
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">Prg T/O : {{formatNumber(rowRecord.detailData.prgTO)}}
|
||
</view>
|
||
<view class="hz-font-12px">Prg Win : {{formatNumber(rowRecord.detailData.prgWin)}}
|
||
</view>
|
||
<view class="hz-font-12px">Exp comm : {{formatNumber(rowRecord.detailData.expComm)}}
|
||
</view>
|
||
<view class="hz-font-12px">Unsettled Expenses : {{formatNumber(rowRecord.detailData.unsettledExpenses)}}
|
||
</view>
|
||
</u-col>
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">Front Money: {{formatNumber(rowRecord.detailData.frontMoney)}}</view>
|
||
<view class="hz-font-12px">TTO: {{formatNumber(rowRecord.detailData.tto)}}</view>
|
||
<view class="hz-font-12px">0.1Comp Balance: {{formatNumber(rowRecord.detailData.comBalance)}}
|
||
</view>
|
||
<view class="hz-font-12px">Net Credit outstanding: {{formatNumber(rowRecord.detailData.netCreditOutstanding)}}
|
||
</view>
|
||
</u-col>
|
||
</u-row>
|
||
|
||
<u-row v-show="filterType==='IM'&¤tIndex===2" customStyle="margin-top:10px;">
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">Today T/O : {{formatNumber(rowRecord.detailData.todayTo)}}
|
||
</view>
|
||
<view class="hz-font-12px">Today Win : {{formatNumber(rowRecord.detailData.todayWin)}}
|
||
</view>
|
||
</u-col>
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">Yesterday T/O: {{formatNumber(rowRecord.detailData.yesterdayTO)}}</view>
|
||
<view class="hz-font-12px">Yesterday Win: {{formatNumber(rowRecord.detailData.yesterdayWin)}}</view>
|
||
<view class="hz-font-12px">Yesterday Playhour: {{formarHour(rowRecord.detailData.yesterdayPlayHour)}}
|
||
</view>
|
||
</u-col>
|
||
</u-row>
|
||
<u-row v-show="filterType==='IM'&¤tIndex===2" customStyle="margin-top:10px;">
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">Prg T/O : {{formatNumber(rowRecord.detailData.prgTO)}}
|
||
</view>
|
||
<view class="hz-font-12px">Prg Win : {{formatNumber(rowRecord.detailData.prgWin)}}
|
||
</view>
|
||
<view class="hz-font-12px">Prg Avg PlayHour : {{formarHour(rowRecord.detailData.averagePlayHour)}}
|
||
</view>
|
||
<view class="hz-font-12px">Exp comm : {{formatNumber(rowRecord.detailData.expComm)}}
|
||
</view>
|
||
<view class="hz-font-12px">Unsettled Expenses : {{formatNumber(rowRecord.detailData.unsettledExpenses)}}
|
||
</view>
|
||
</u-col>
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">Front Money: {{formatNumber(rowRecord.detailData.frontMoney)}}</view>
|
||
<view class="hz-font-12px">TTO: {{formatNumber(rowRecord.detailData.tto)}}</view>
|
||
<view class="hz-font-12px">0.1Comp Balance: {{formatNumber(rowRecord.detailData.comBalance)}}
|
||
</view>
|
||
<view class="hz-font-12px">Net Credit outstanding: {{formatNumber(rowRecord.detailData.netCreditOutstanding)}}
|
||
</view>
|
||
</u-col>
|
||
</u-row>
|
||
|
||
|
||
<u-row customStyle="margin-top:10px;" v-show="filterType==='MASS'">
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">R3M TPD: {{formatNumber(rowRecord.detailData.r3MTPD)}}</view>
|
||
<view class="hz-font-12px">R3M Win: {{formatNumber(rowRecord.detailData.r3MWin)}}</view>
|
||
<view class="hz-font-12px">R3M RI%:
|
||
{{getPercentFormat(rowRecord.detailData.r3MRIPercentage)}}</view>
|
||
<view v-show="currentIndex === 2 && filterType ==='MASS'" class="hz-font-12px">R3M Theo : {{formatNumber(rowRecord.detailData.r3MTheo)}}
|
||
</view>
|
||
</u-col>
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">R6M TPD: {{formatNumber(rowRecord.detailData.r6MTPD)}}</view>
|
||
<view class="hz-font-12px">R6M Win: {{formatNumber(rowRecord.detailData.r6MWin)}}</view>
|
||
<view class="hz-font-12px">R6M RI%:
|
||
{{getPercentFormat(rowRecord.detailData.r6MRIPercentage)}}</view>
|
||
<view v-show="currentIndex === 2 && filterType ==='MASS'" class="hz-font-12px">R6M Theo : {{formatNumber(rowRecord.detailData.r6MTheo)}}
|
||
</view>
|
||
</u-col>
|
||
</u-row>
|
||
<u-row customStyle="margin-top:10px;" v-show="filterType==='IM'">
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">R3M T/O: {{formatNumber(rowRecord.detailData.r3MTO)}}</view>
|
||
<view class="hz-font-12px">R3M T/O /D: {{formatNumber(rowRecord.detailData.r3MTOD)}}</view>
|
||
<view class="hz-font-12px">R3M Win:
|
||
{{formatNumber(rowRecord.detailData.r3MWin)}}</view>
|
||
</u-col>
|
||
<u-col span="6">
|
||
<view class="hz-font-12px">R6M T/O: {{formatNumber(rowRecord.detailData.r6MTO)}}</view>
|
||
<view class="hz-font-12px">R6M T/O /D: {{formatNumber(rowRecord.detailData.r6MTOD)}}</view>
|
||
<view class="hz-font-12px">R6M Win:
|
||
{{formatNumber(rowRecord.detailData.r6MWin)}}</view>
|
||
</u-col>
|
||
</u-row>
|
||
<view class="hz-split" style="margin-top:10px;"></view>
|
||
<view v-show="rowRecord.showOffer">
|
||
<view class="hz-font-color-dark hz-font-md">Available & Unredeem Offer</view>
|
||
<view v-for="(record,index) in rowRecord.detailData.descriptions"
|
||
:key="'offer-'+index" class="hz-font-12px">{{getOfferDescription(record)}}
|
||
</view>
|
||
<view class="hz-split"></view>
|
||
</view>
|
||
<view class="hz-font-color-dark hz-font-md" style="margin-top:10px;">Bookings
|
||
</view>
|
||
<view class="hz-flex-row" style="align-items: flex-start;"
|
||
v-show="hasFlightRecord(rowRecord.detailData.descriptions)">
|
||
<view class="icon-group" style="margin-top:5px;margin-left:0px;">
|
||
<image src="../../static/images/flight_line_2.svg"
|
||
class="icon-img-flight" style="margin-left:0px;margin-right:4px;">
|
||
</image>
|
||
</view>
|
||
<view class="hz-flex-col">
|
||
<view v-for="(record,index) in rowRecord.detailData.descriptions"
|
||
:key="'flight'+index" class="hz-flex-row"
|
||
style="align-items: flex-start;">
|
||
<span class="hz-font-12px">{{getFlightDescription(record)}}</span>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="hz-flex-row" style="align-items: flex-start;"
|
||
v-show="hasLimoRecord(rowRecord.detailData.descriptions)">
|
||
<view class="icon-group" style="margin-top:3px;margin-left:0px;">
|
||
<image src="../../static/images/limo_line_2.svg" class="icon-img-limo"
|
||
style="margin-left:0px;margin-right:4px;"></image>
|
||
</view>
|
||
<view class="hz-flex-col">
|
||
<view v-for="(record,index) in rowRecord.detailData.descriptions"
|
||
:key="'limo'+index" class="hz-flex-row"
|
||
style="align-items: flex-start;">
|
||
<span class="hz-font-12px">{{getLimoDescription(record)}}</span>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="hz-flex-row" style="align-items: flex-start;"
|
||
v-show="hasRoomRecord(rowRecord.detailData.descriptions)">
|
||
<view class="icon-group-room">
|
||
<image src="../../static/images/room_line_2.svg" class="icon-img-room"
|
||
style="margin-top:2px;margin-right:3px;"></image>
|
||
</view>
|
||
<view class="hz-flex-col">
|
||
<view v-for="(record,index) in rowRecord.detailData.descriptions"
|
||
:key="'room'+index" class="hz-flex-row"
|
||
style="align-items: flex-start;">
|
||
<span class="hz-font-12px">{{getRoomDescription(record)}}</span>
|
||
<!-- <view v-show="showSharerIcon(record)" class="icon-group"> -->
|
||
<view v-show="getItemShowSharerIcon(record.itemRecordDescription)" class="icon-group">
|
||
<image src="../../static/images/sharer_line_2.svg"
|
||
class="icon-img-limo"></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uni-card>
|
||
<template v-slot:right>
|
||
<view v-if="currentIndex === 0" class="hz-flex-row" style="height:100%;align-items: center;margin-left:15px;"
|
||
|
||
@click.stop="openETA(rowRecord)" @touchstart.stop @touchend.stop>
|
||
<view class="slot-button slot-button-eta"><text class="slot-button-text">ETA</text>
|
||
</view>
|
||
</view>
|
||
<view v-else class="hz-flex-row" style="height:100%;align-items: center;margin-left:15px;"
|
||
@click.stop="openBookingRecord(rowRecord)" @touchstart.stop @touchend.stop>
|
||
<view class="slot-button slot-button-eta"><text class="slot-button-text">EXT</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="currentIndex === 0" class="hz-flex-row" style="height:100%;align-items: center;margin-left:15px;"
|
||
@click.stop="openBookingRecord(rowRecord)" @touchstart.stop @touchend.stop>
|
||
<view class="slot-button slot-button-cancel">
|
||
<u-icon name="close" color="#ffffff" :size="16"></u-icon>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
</uni-swipe-action-item>
|
||
</uni-swipe-action>
|
||
</view>
|
||
|
||
<view v-if="currentIndex === 3" v-for="(record,index) in listData" :key="'record'+index" style="margin-bottom:8px;">
|
||
<view class="hz-date-title">{{record.date}}</view>
|
||
<uni-card v-for="(rowRecord,index) in record.dateRecords" :key="'rowRecord'+index" style="margin-left:4rpx;margin-right:4rpx;padding:12px;">
|
||
<u-row v-for="(rowDescription,index) in getOtherDescription(rowRecord.descriptions)" :key="'rowDescription'+index">
|
||
<u-col span="12">
|
||
<view class="hz-font-color-dark hz-font-md" style="margin-bottom:6px;">
|
||
<span v-if="index !== 0">•</span> {{getEmojiDescription(rowDescription)}}
|
||
</view>
|
||
</u-col>
|
||
</u-row>
|
||
</uni-card>
|
||
</view>
|
||
|
||
</view>
|
||
<!--content end-->
|
||
</view>
|
||
|
||
<u-modal :show="showETAMsg" :confirmText="yesText" @confirm="submitETA()" confirmColor="#C39A4B" :closeOnClickConfirm="false"
|
||
@cancel="showETAMsg=false;" @close="showETAMsg=false;" :cancelText="cancelText" showCancelButton>
|
||
<view class="slot-content hz-flex-col" style="align-items: center;">
|
||
<image src="../../static/images/time_line.svg" class=" hz-mr-b-30" style="width:48px;height:48px;">
|
||
</image>
|
||
<view class="hz-font-xl hz-font-bolder">Estimate Time Arrival</view>
|
||
<view class="hz-font-md hz-mr-b-30" style="margin-top:8px;color:#666666;">{{etaPlayerId}} / {{etaPlayerName}}</view>
|
||
<view class="hz-flex-row" style="align-items: center;">
|
||
<u-code-input v-model="etaTime" :maxlength="4" :isColon="true" space="14" :focus="true" color="#333333" :fontSize="26"
|
||
:bold="true"></u-code-input>
|
||
</view>
|
||
<view class="hz-font-12px hz-mr-b-30" style="margin-top:12px;color:#666666;">( 24h, format: 02:30 )
|
||
</view>
|
||
</view>
|
||
</u-modal>
|
||
<u-modal :content="msgStr" :show="showMsg" :confirmText="okText" :showCancelButton="false" closeOnClickOverlay @confirm="showMsg=false" confirmColor="#C39A4B" @close="showMsg=false"></u-modal>
|
||
<u-popup
|
||
:safeAreaInsetBottom="true"
|
||
:safeAreaInsetTop="true"
|
||
:mode="'center'"
|
||
:round="12"
|
||
:show="showMsgBox"
|
||
:customStyle="'width:' + windowWidth + 'px;'"
|
||
>
|
||
<view
|
||
:style="'width:100%;max-width:' + windowWidth + 'px;'"
|
||
style="padding-top:30px;padding-bottom: 30px;"
|
||
>
|
||
<view class="hz-flex-row" style="justify-content:center;align-items:center;width:100%;">
|
||
<image :src="iconPath" style="width:64px;height:64px;"></image>
|
||
</view>
|
||
<view class="hz-font-md hz-font-bold hz-text-center" style="margin-top:20px;margin-bottom: 20px;">
|
||
<rich-text v-html="popMsgStr" style="line-height:26px;"></rich-text>
|
||
</view>
|
||
<view @click="showMsgBox = false" class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center" style="width: 90%;margin: 0 auto;">
|
||
{{$t("common.ok").toUpperCase()}}
|
||
</view>
|
||
</view>
|
||
</u-popup>
|
||
<u-calendar closeOnClickOverlay :confirmText="confirmText" :confirmDisabledText="confirmText" color="#C39A4B"
|
||
title="" :startText="startText" :endText="endText" :show="showCalendar" :allowSameDay="true"
|
||
:maxDate="maxDate" :minDate="minDate" mode="range" :monthNum="monthNum" :maxRange="maxRange" :footerInfo="footerInfo"
|
||
@close="cancelDate" @confirm="confirmDate" @rangeSelected="rangeSelected" :showMark="false"
|
||
:showRangePrompt="showRangePrompt" :defaultDate="calendarSave" :rangePrompt="rangeTip">
|
||
</u-calendar>
|
||
</view>
|
||
<view v-if="!showTodoListView">
|
||
<view class="hz-flex-row" style="justify-content: center;margin-top:40px;">
|
||
<image src="/static/images/datanull.png" style="width:160px;height:160px;"></image>
|
||
</view>
|
||
<view class="hz-flex-row hz-font-bolder hz-font-md" style="justify-content: center;margin:20px;">
|
||
{{dataNull}}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import mgmHeader from '@/components/header/header.vue' // 引入头部组件
|
||
// #ifdef APP-PLUS
|
||
import SimpleWatermark from '@/components/simple-watermark/simple-watermark.vue'
|
||
// #endif
|
||
import {
|
||
playerLookup
|
||
} from '../../api/mgmApi.js'
|
||
import {
|
||
getTodoDetail,
|
||
getTodoList,
|
||
submitETA
|
||
} from '../../api/todoApi';
|
||
import list from '../../uni_modules/uview-ui/libs/config/props/list';
|
||
import {
|
||
getProperties,
|
||
getBookingTypes,
|
||
getRooms,
|
||
getRoomTypes,
|
||
getSpecials,
|
||
getBedTypes,
|
||
getCriterias,
|
||
getAvailableRoom,
|
||
getSetting,
|
||
getExtendBooking
|
||
} from '../../api/configApi.js';
|
||
export default {
|
||
components: {
|
||
mgmHeader, // 注册组件
|
||
// #ifdef APP-PLUS
|
||
SimpleWatermark
|
||
// #endif
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
isOpen: true,
|
||
filterType: '',
|
||
deviceData: null,
|
||
siteData: null,
|
||
listData: [],
|
||
etaTime: '',
|
||
comfList: [],
|
||
etaPlayerId:null,
|
||
isYesterday:false,
|
||
etaPlayerName:null,
|
||
//界面变量
|
||
// itemOpen: 'none',
|
||
showETAMsg: false,
|
||
showMsgBox:false,
|
||
popMsgStr:'',
|
||
iconPath:'',
|
||
etaConfNo:[],
|
||
cancelText: this.$t("common.cancel"),
|
||
okText: this.$t("common.ok"),
|
||
yesText: this.$t("common.submit"),
|
||
confirmText: this.$t("common.confirm").toUpperCase(),
|
||
inText: this.$t("common.in"),
|
||
outText: this.$t("common.out"),
|
||
startText: this.$t("common.start"),
|
||
endText: this.$t("common.end"),
|
||
dataNull:'',
|
||
showDetail: false,
|
||
showRangePrompt:true,
|
||
startDate:new Date(),
|
||
endDate:new Date(),
|
||
todayDate:new Date(),
|
||
yesterdayDate:new Date(),
|
||
tomorrowDate:new Date(),
|
||
minDate:'',
|
||
maxDate: '',
|
||
monthNum: 0,
|
||
maxRange: 0,
|
||
footerInfo: "",
|
||
showDetailLoading: false,
|
||
arrowName: 'arrow-down',
|
||
isProcessing: false,
|
||
navbarHeight: 0,
|
||
windowWidth:0,
|
||
bgColor: '#ffffff',
|
||
etaBackgroundClolor: null,
|
||
height: 44,
|
||
showNavbar: true,
|
||
showCalendar: false,
|
||
lastScrollPosition: 0, // 记录上次滚动位置
|
||
hideThreshold: 100, // 开始隐藏的滚动阈值
|
||
showThreshold: 100, // 修改为100px,向下滑动100px就显示
|
||
isHiding: false, // 是否正在隐藏过程中
|
||
isShowing: false, // 是否正在显示过程中
|
||
minScrollPosition: 0, // 记录页面最小滚动位置
|
||
downScrollStart: 0, // 记录向下滑动的起始位置
|
||
isDownScrolling: false, // 是否正在向下滚动
|
||
tabbarVisible: true,
|
||
navbarOpacity: 1, // 控制navbar的透明度
|
||
lastScrollTop: 0,
|
||
currentIndex: 0,
|
||
sliderPosition: 0,
|
||
userData: null,
|
||
msgStr:null,
|
||
showMsg:false,
|
||
handleETA:false,
|
||
ETATime: 0,
|
||
showTodoListView:false,
|
||
etaData: [],
|
||
playerData: {
|
||
playerId: "",
|
||
playerName: "",
|
||
tireName: ""
|
||
},
|
||
todoRecord: {
|
||
playerId: "11010001",
|
||
playerName: "IVAN LAU",
|
||
other: "Other Test"
|
||
},
|
||
todoDetailData: [],
|
||
tabs: [{
|
||
name: this.$t("todo.arrival"),
|
||
color: '#4a6da7' // 到达
|
||
},
|
||
{
|
||
name: this.$t("todo.departure"),
|
||
color: '#5b8a72' // 离开
|
||
},
|
||
{
|
||
name: this.$t("todo.inhouse"),
|
||
color: '#8e6f50' // 在住
|
||
},
|
||
{
|
||
name: this.$t("todo.others"),
|
||
color: '#333333' // 其他
|
||
}
|
||
],
|
||
|
||
calendarSave: [null, null],
|
||
rangeTip: this.$t("common.rangeTip"),
|
||
calendarIconColor: "#000000",
|
||
currentTask: null
|
||
}
|
||
},
|
||
|
||
watch: {
|
||
// 深度监听 tabs 数组的变化
|
||
tabs: {
|
||
handler(newVal, oldVal) {
|
||
// 只有当 tabs 内容实际变化时才调用(避免初始化时重复调用)
|
||
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
|
||
this.listData = [];
|
||
this.setCalendar();
|
||
}
|
||
},
|
||
deep: true // 设置为深度监听
|
||
},
|
||
// 同时监听 currentIndex 变化(切换 tab 时触发)
|
||
currentIndex() {
|
||
this.listData = [];
|
||
this.setCalendar();
|
||
}
|
||
},
|
||
|
||
onLoad() {
|
||
// 初始化界面
|
||
this.initUI();
|
||
this.siteData = uni.getStorageSync("siteData");
|
||
// 确保tabbarVisible被正确初始化
|
||
this.tabbarVisible = true;
|
||
},
|
||
mounted() {
|
||
// 在组件挂载后初始化滑块位置
|
||
this.$nextTick(() => {
|
||
setTimeout(() => {
|
||
this.updateSliderPosition();
|
||
}, 100); // 添加一点延迟确保DOM已经渲染完成
|
||
});
|
||
},
|
||
onReady() {
|
||
// onReady生命周期在页面渲染完成后触发,也可以在这里初始化滑块位置
|
||
this.updateSliderPosition();
|
||
|
||
|
||
// 页面首次渲染完成后,延迟触发水印更新
|
||
setTimeout(() => {
|
||
console.log('[TodoList] Triggering watermark update on ready');
|
||
const watermarkStore = require('@/store/watermark.js');
|
||
if (watermarkStore && watermarkStore.updateWatermark) {
|
||
watermarkStore.updateWatermark(true);
|
||
}
|
||
}, 1200);
|
||
},
|
||
onShow() {
|
||
this.setCalendar();
|
||
this.userData = uni.getStorageSync("userData");
|
||
this.playerData = uni.getStorageSync("playerData");
|
||
if(this.userData!==null && this.userData!==undefined)
|
||
this.showTabbarByPermission(this.userData);
|
||
this.listData = [];
|
||
// 确保每次页面显示时tabbar状态正确
|
||
if (this.tabbarVisible === undefined) {
|
||
this.tabbarVisible = true;
|
||
}
|
||
if(uni.getStorageSync('todoSwitch') === "true"){
|
||
if(this.userData.division !== 'VIP Marketing'){
|
||
console.log(this.userData.division);
|
||
this.isOpen = true;
|
||
this.filterType = "MASS";
|
||
}else{
|
||
console.log(this.userData.division);
|
||
this.isOpen = false;
|
||
this.filterType = 'IM';
|
||
}
|
||
uni.setStorageSync('todoSwitch',"false");
|
||
}
|
||
// 如果需要,可以强制显示tabbar
|
||
if (this.tabbarVisible) {
|
||
uni.showTabBar();
|
||
}
|
||
// 手动触发水印更新,确保水印在页面显示时正确显示
|
||
this.$nextTick(() => {
|
||
setTimeout(() => {
|
||
console.log('[TodoList] Manually triggering watermark update on show');
|
||
const watermarkStore = require('@/store/watermark.js');
|
||
if (watermarkStore && watermarkStore.updateWatermark) {
|
||
watermarkStore.updateWatermark(true);
|
||
}
|
||
}, 500);
|
||
});
|
||
|
||
this.tabs=[{
|
||
name: this.$t("todo.arrival"),
|
||
color: '#4a6da7' // 到达
|
||
},
|
||
{
|
||
name: this.$t("todo.departure"),
|
||
color: '#5b8a72' // 离开
|
||
},
|
||
{
|
||
name: this.$t("todo.inhouse"),
|
||
color: '#8e6f50' // 在住
|
||
},
|
||
{
|
||
name: this.$t("todo.others"),
|
||
color: '#333333' // 其他
|
||
}
|
||
]
|
||
},
|
||
onPageScroll(e) {
|
||
const scrollTop = e.scrollTop;
|
||
const scrollDelta = scrollTop - this.lastScrollPosition;
|
||
|
||
// 添加节流,避免频繁触发
|
||
if (this.isHiding || this.isShowing) {
|
||
this.lastScrollPosition = scrollTop;
|
||
return;
|
||
}
|
||
|
||
// 1. 检测滚动方向并跟踪向下滚动
|
||
if (scrollDelta < 0) {
|
||
// 向下滚动
|
||
if (!this.isDownScrolling) {
|
||
this.isDownScrolling = true;
|
||
this.downScrollStart = scrollTop; // 记录向下滑动的起始位置
|
||
}
|
||
} else {
|
||
// 向上滚动
|
||
this.isDownScrolling = false;
|
||
}
|
||
|
||
// 2. 处理向下滚动超过100px的情况
|
||
if (this.isDownScrolling) {
|
||
const downScrollDistance = this.downScrollStart - scrollTop;
|
||
|
||
if (downScrollDistance > this.showThreshold) {
|
||
if (!this.showNavbar || this.navbarOpacity < 1) {
|
||
this.showElements();
|
||
}
|
||
// 重置向下滚动状态,避免重复触发
|
||
this.isDownScrolling = false;
|
||
}
|
||
}
|
||
|
||
// 3. 主要显示/隐藏逻辑
|
||
if (scrollTop > this.hideThreshold && scrollDelta > 0 && !this.isHiding) {
|
||
this.hideElements();
|
||
}
|
||
// 4. 接近顶部时强制显示
|
||
else if (scrollTop <= 50 && !this.showNavbar && !this.isShowing) {
|
||
this.showElements();
|
||
}
|
||
|
||
// 5. 更新滚动位置
|
||
this.lastScrollPosition = scrollTop;
|
||
},
|
||
methods: {
|
||
swipeChange(e, index) {
|
||
console.log('返回:', e);
|
||
console.log('当前索引:', index);
|
||
},
|
||
|
||
changeTest(record,action,event){
|
||
// 滑动时候转换,handleETA时转换
|
||
if(action===1 && !(this.handleETA)){
|
||
if(record.itemOpen=='none'){
|
||
record.itemOpen = event;
|
||
}else{
|
||
record.itemOpen = event;
|
||
}
|
||
}
|
||
// 当点击ETA按钮时,在关闭滑块后将handleETA改为false
|
||
this.handleETA = false;
|
||
},
|
||
formatNumber(num) {
|
||
return num?.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") || "0";
|
||
},
|
||
formarHour(num){
|
||
let hourStr = num > 1 ? num + ' hours' : num + ' hour';
|
||
return hourStr;
|
||
},
|
||
checkPassEtaTime(record) {
|
||
// 获取当前日期(不含时间)
|
||
let today = new Date();
|
||
let currentDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
|
||
|
||
// 解析actionDate并创建纯日期对象
|
||
let actionDateObj = new Date(record.actionDate);
|
||
let actionDate = new Date(actionDateObj.getFullYear(), actionDateObj.getMonth(), actionDateObj.getDate());
|
||
|
||
// 获取当前时间
|
||
let currentTime = new Date().toTimeString().slice(0, 5);
|
||
let currentHour = parseInt(currentTime.split(":")[0]);
|
||
let currentMinute = currentTime.split(":")[1];
|
||
|
||
// 解析ETA时间
|
||
let etaHour = parseInt(record.eta.split(":")[0]);
|
||
let etaMinute = record.eta.split(":")[1];
|
||
|
||
// 如果ETA小时小于6,将actionDate加一天
|
||
if (etaHour < 6) {
|
||
actionDate.setDate(actionDate.getDate() + 1);
|
||
}
|
||
|
||
// 如果当前小时小于6,将当前日期加一天
|
||
if (currentHour < 6) {
|
||
currentDate.setDate(currentDate.getDate() + 1);
|
||
}
|
||
// 比较纯日期(时间部分都是00:00:00)
|
||
if (actionDate < currentDate) {
|
||
return true; // actionDate在当前日期之前
|
||
} else if (actionDate > currentDate) {
|
||
return false; // actionDate在当前日期之后
|
||
} else {
|
||
// 日期相同,比较时间
|
||
if (currentHour > etaHour) {
|
||
return true;
|
||
} else if (currentHour === etaHour) {
|
||
if (currentMinute > etaMinute) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
},
|
||
openETA(e) {
|
||
this.etaData = [];
|
||
// 将handleETA改为true避免死循环
|
||
// this.handleETA = true ;
|
||
// e.itemOpen = 'none';
|
||
this.etaPlayerId = e.playerId;
|
||
this.etaPlayerName = e.englishName;
|
||
// 阻止事件冒泡和默认行为
|
||
if (e && e.stopPropagation) {
|
||
e.stopPropagation();
|
||
}
|
||
if (e && e.preventDefault) {
|
||
e.preventDefault();
|
||
}
|
||
|
||
// 重置状态变量
|
||
|
||
this.etaData = e;
|
||
// this.itemOpen = 'none';
|
||
this.etaConfNo = (e.operaConfirmationNo).split(",");
|
||
|
||
// 使用父组件的closeAll方法关闭滑块
|
||
this.$nextTick(() => {
|
||
// 查找uni-swipe-action父组件
|
||
let parent = this.$refs.swipeAction.$parent;
|
||
while (parent && parent.$options.name !== 'uniSwipeAction') {
|
||
parent = parent.$parent;
|
||
}
|
||
if (parent && parent.closeAll) {
|
||
parent.closeAll();
|
||
}
|
||
// 直接设置组件状态
|
||
if (this.$refs.swipeAction) {
|
||
this.$refs.swipeAction.is_show = 'none';
|
||
}
|
||
});
|
||
// 延迟执行以确保滑块动画完成
|
||
if(this.etaData.operaConfirmationNo !== undefined && this.etaData.operaConfirmationNo !== ';' && this.etaData.operaConfirmationNo !== null){
|
||
setTimeout(() => {
|
||
this.etaTime = '';
|
||
this.showETAMsg = true;
|
||
}, 100);
|
||
}else{
|
||
uni.showToast({
|
||
title:this.$t("todo.notConfNo"),
|
||
icon: "none"
|
||
});
|
||
}
|
||
},
|
||
async openBookingRecord(record) {
|
||
// 阻止事件冒泡和默认行为
|
||
// if (e && e.stopPropagation) {
|
||
// e.stopPropagation();
|
||
// }
|
||
// if (e && e.preventDefault) {
|
||
// e.preventDefault();
|
||
// }
|
||
|
||
// 重置状态变量
|
||
// this.itemOpen = 'none';
|
||
|
||
let params = {
|
||
playerId: record.playerId,
|
||
userId: this.userData.userId
|
||
};
|
||
try{
|
||
uni.showLoading({
|
||
title: this.$t("common.loading")
|
||
});
|
||
const res = await playerLookup(params);
|
||
if (res.success == true) {
|
||
if (res.data !== null) {
|
||
if(res.data.codedFlag==1){
|
||
uni.setStorageSync("playerData",res.data);
|
||
uni.hideLoading();
|
||
this.navTo("/booking/bookingRecord/bookingRecord",0,false);
|
||
}else{
|
||
uni.showToast({
|
||
title:this.$t("findPlayer.noPermission"),
|
||
icon: "none"
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}catch(e){
|
||
|
||
}finally{
|
||
uni.hideLoading();
|
||
}
|
||
|
||
// 使用父组件的closeAll方法关闭滑块
|
||
this.$nextTick(() => {
|
||
// 查找uni-swipe-action父组件
|
||
let parent = this.$refs.swipeAction.$parent;
|
||
while (parent && parent.$options.name !== 'uniSwipeAction') {
|
||
parent = parent.$parent;
|
||
}
|
||
if (parent && parent.closeAll) {
|
||
parent.closeAll();
|
||
}
|
||
|
||
// 直接设置组件状态
|
||
if (this.$refs.swipeAction) {
|
||
this.$refs.swipeAction.is_show = 'none';
|
||
}
|
||
});
|
||
|
||
},
|
||
|
||
// 点击头部tab刷新todoList数据,如果点击了其他的tab,则不执行该方法
|
||
handlerGetToDoList(index) {
|
||
if (this.currentIndex == index) {
|
||
this.getTodoListByData();
|
||
}
|
||
},
|
||
|
||
isValid24HourTime(timeStr) {
|
||
if (!timeStr) return false;
|
||
const regex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/;
|
||
return regex.test(timeStr);
|
||
},
|
||
|
||
async submitETA() {
|
||
|
||
let paramData = {
|
||
items:[]
|
||
};
|
||
let hotelName = null;
|
||
// 获取接口参数
|
||
paramData = this.getparamData(this.etaData);
|
||
// 关闭模态框
|
||
uni.showLoading({
|
||
title: this.$t("common.loading")
|
||
});
|
||
|
||
let params = {};
|
||
|
||
// 获取用户输入的时间字符串
|
||
const etaTimeStr = this.etaTime;
|
||
|
||
// 檢驗etaTime不能為空
|
||
if (!etaTimeStr || etaTimeStr.trim() === '') {
|
||
uni.hideLoading();
|
||
uni.showToast({ title: this.$t("todo.etaRequired"), icon: "none" });
|
||
this.etaTime = '';
|
||
return;
|
||
}
|
||
|
||
params.ETATime = `${etaTimeStr.slice(0, 2)}:${etaTimeStr.slice(2)}`;
|
||
|
||
// 檢驗輸入時間格式是否為24小時制
|
||
if (!this.isValid24HourTime(params.ETATime)) {
|
||
uni.hideLoading();
|
||
uni.showToast({ title: this.$t("todo.etaFormatError"), icon: "none" });
|
||
this.etaTime = '';
|
||
return;
|
||
}
|
||
|
||
try{
|
||
params.recordInfo = paramData.items;
|
||
|
||
params.playerId = this.etaData.playerId;
|
||
|
||
// this.itemOpen = 'none';
|
||
const res = await submitETA(params);
|
||
|
||
if(res.success!==null && res.success == true){
|
||
this.iconPath = '../../static/images/ico_suc.png';
|
||
this.popMsgStr = this.$t("todo.etaSuccess");
|
||
// 重新获取数据,刷新eta
|
||
this.getTodoListByData();
|
||
// for(let i = 0 ; i < this.listData.length ; i++){
|
||
// console.log(i);
|
||
// for(let j = 0 ; j < this.listData[i].dateRecords.length ; j++){
|
||
// console.log(j);
|
||
// console.log(this.listData[i].dateRecords[j].itemOpen);
|
||
// }
|
||
// }
|
||
}else{
|
||
this.iconPath = '../../static/images/ico_err.png';
|
||
if(res.errorCode == 'NO_RECORD'){
|
||
this.popMsgStr = this.$t("todo.etaFail")+":"+this.$t("common.errorMsg")+":"+ this.$t("todo.notRecord");
|
||
}else if(res.errorCode == 'MISS_PARAMETER'){
|
||
this.popMsgStr = this.$t("todo.etaFail")+":"+this.$t("common.errorMsg")+":"+ this.$t("todo.missParams");
|
||
}else{
|
||
this.popMsgStr = this.$t("todo.etaFail")+":"+this.$t("common.errorMsg")+":"+ res.errorCode;
|
||
}
|
||
}
|
||
this.showMsgBox = true;
|
||
}catch(e){
|
||
console.error(e);
|
||
if(e.data!==null&&e.data!==undefined&&e.data.message!==undefined){
|
||
this.iconPath = '../../static/images/ico_err.png';
|
||
this.popMsgStr = this.$t("todo.etaFail")+":"+this.$t("common.errorMsg")+":"+ e.data.error;
|
||
this.showMsgBox = true;
|
||
}else{
|
||
this.iconPath = '../../static/images/ico_err.png';
|
||
this.popMsgStr = this.$t("todo.etaFail")+":"+this.$t("common.errorMsg")+":"+ e;
|
||
this.showMsgBox = true;
|
||
}
|
||
}finally{
|
||
this.showETAMsg = false;
|
||
uni.hideLoading();
|
||
this.etaTime = '';
|
||
}
|
||
|
||
// 使用父组件的closeAll方法关闭所有滑块
|
||
this.$nextTick(() => {
|
||
const swipeRef = this.$refs.swipeAction;
|
||
if (!swipeRef) return;
|
||
|
||
// 查找uni-swipe-action父组件
|
||
let parent = this.$refs.swipeAction.$parent;
|
||
while (parent && parent.$options.name !== 'uniSwipeAction') {
|
||
parent = parent.$parent;
|
||
}
|
||
if (parent && parent.closeAll) {
|
||
parent.closeAll();
|
||
}
|
||
|
||
// 直接设置组件状态
|
||
if (this.$refs.swipeAction) {
|
||
this.$refs.swipeAction.is_show = 'none';
|
||
}
|
||
});
|
||
},
|
||
initUI() {
|
||
this.deviceData = uni.getStorageSync("deviceData");
|
||
let device = this.deviceData;
|
||
let statusBarHeight = device.statusBarHeight;
|
||
this.navbarHeight = statusBarHeight + 44;
|
||
this.windowWidth = this.deviceData.windowWidth*0.95;
|
||
},
|
||
openCalendar(){
|
||
this.showCalendar = true;
|
||
|
||
},
|
||
async setCalendar(){
|
||
const today = new Date();
|
||
const tomorrow = new Date(today);
|
||
const nextMonth = new Date(today);
|
||
const yesterday = new Date(today);
|
||
|
||
let timeStart,timeEnd = '';
|
||
let dbStart = '';
|
||
let dbEnd = '';
|
||
|
||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||
yesterday.setDate(yesterday.getDate() - 1);
|
||
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
||
// 到Setting表获取时间区间
|
||
try {
|
||
let params = {};
|
||
const res = await getSetting(params);
|
||
if (res != null && res.success == true) {
|
||
for (let i of res.data) {
|
||
if (i.keys == "VIEW_YESTERDAY_TODOLIST_START") {
|
||
dbStart = i.keyValues;
|
||
}else if(i.keys == "VIEW_YESTERDAY_TODOLIST_END"){
|
||
dbEnd = i.keyValues
|
||
}
|
||
}
|
||
let today = new Date();
|
||
let currentHour = today.getHours();
|
||
let currentMinute = today.getMinutes();
|
||
|
||
// 解析 start 和 end 时间
|
||
let startHour = parseInt(dbStart.split(":")[0]);
|
||
let startMinute = parseInt(dbStart.split(":")[1] || 0);
|
||
let endHour = parseInt(dbEnd.split(":")[0]);
|
||
let endMinute = parseInt(dbEnd.split(":")[1] || 0);
|
||
|
||
// 将当前时间转换为分钟总数以便比较
|
||
let totalCurrent = currentHour * 60 + currentMinute;
|
||
let totalStart = startHour * 60 + startMinute;
|
||
let totalEnd = endHour * 60 + endMinute;
|
||
// 判断当前时间是否在 [start, end) 区间内
|
||
if (totalCurrent >= totalStart && totalCurrent < totalEnd) {
|
||
this.minDate = this.formatDate(yesterday);
|
||
this.isYesterday = true;
|
||
} else {
|
||
this.isYesterday = false;
|
||
this.minDate = this.formatDate(today);
|
||
}
|
||
} else {
|
||
// write log
|
||
}
|
||
} catch (e) {
|
||
// write log
|
||
console.error(e);
|
||
uni.$u.toast(e.errMsg, 5000);
|
||
var request = e.config!=undefined?JSON.stringify(e.config):"";
|
||
var response = e.data!=undefined?JSON.stringify(e.data):"";
|
||
await this.writeLog(this.userData.userId, "Set Calendar", "",
|
||
"[APP][newBooking.vue][getSetting][Catch Exception]" + e.errMsg, request,response, 1, false);
|
||
} finally {
|
||
}
|
||
if(this.isYesterday){
|
||
this.startDate = yesterday; // 存储为 Date 对象
|
||
this.endDate = today; // 存储为 Date 对象
|
||
}else{
|
||
this.startDate = today; // 存储为 Date 对象
|
||
this.endDate = tomorrow; // 存储为 Date 对象
|
||
}
|
||
this.todayDate = today;
|
||
this.yesterdayDate = yesterday;
|
||
this.tomorrowDate = tomorrow;
|
||
this.maxDate=this.formatDate(nextMonth);
|
||
this.monthNum=2;
|
||
this.maxRange=6;
|
||
this.showRangePrompt=true;
|
||
this.getTodoListByData();
|
||
|
||
},
|
||
switchFilterType() {
|
||
this.isOpen = !this.isOpen;
|
||
if (this.isOpen == true) {
|
||
this.filterType = 'MASS';
|
||
} else {
|
||
this.filterType = 'IM';
|
||
}
|
||
this.listData = [];
|
||
this.getTodoListByData();
|
||
},
|
||
// 显示元素的统一方法
|
||
showElements() {
|
||
if (this.isShowing) return;
|
||
|
||
this.isShowing = true;
|
||
this.isHiding = false;
|
||
|
||
// 使用CSS过渡效果显示元素
|
||
this.navbarOpacity = 1;
|
||
this.showNavbar = true;
|
||
|
||
// 修改这里的判断逻辑,确保tabbar能被显示
|
||
this.tabbarVisible = true;
|
||
uni.showTabBar();
|
||
|
||
// 重置状态,时间与CSS过渡时间匹配
|
||
setTimeout(() => {
|
||
this.isShowing = false;
|
||
}, 400);
|
||
},
|
||
cancelDate() {
|
||
this.showCalendar = false;
|
||
},
|
||
confirmDate(e) {
|
||
this.startDate = e[0];
|
||
this.endDate = e[e.length-1];
|
||
this.getTodoListByData();
|
||
this.showCalendar = false;
|
||
|
||
},
|
||
async rangeSelected(e) {
|
||
if (e && e.length >= 2) {
|
||
const startDate = e[0];
|
||
const endDate = e[e.length - 1];
|
||
}
|
||
},
|
||
|
||
hideElements() {
|
||
if (this.isHiding) return;
|
||
this.isHiding = true;
|
||
this.isShowing = false;
|
||
|
||
// 使用CSS过渡效果隐藏元素
|
||
this.navbarOpacity = 0;
|
||
this.showNavbar = false;
|
||
|
||
// 修改这里的判断逻辑,确保tabbar能被隐藏
|
||
this.tabbarVisible = false;
|
||
uni.hideTabBar();
|
||
|
||
// 重置状态,时间与CSS过渡时间匹配
|
||
setTimeout(() => {
|
||
this.isHiding = false;
|
||
}, 400);
|
||
},
|
||
// checkPassTimeArea(today,dbStart,dbEnd){
|
||
// let tMStart = dbStart.split(":");
|
||
// let tMEnd = dbEnd.split(":");
|
||
// let pass = false;
|
||
// // 判断是否超过时间区间
|
||
// if(today.getHours>tMStart[0] && today.getHourt<tMEnd[0]){
|
||
// // 没超过,返回true
|
||
// pass = ture;
|
||
// }else if(today.getHours===tMStart[0] && today.getMinutes>tMStart[1]){
|
||
|
||
// }
|
||
// else if(today.getHours<tMStart[0] && today.getHourt>tMEnd[0]){
|
||
// // 超过返回false
|
||
// pass = false
|
||
// }
|
||
|
||
// },
|
||
switchTab(index) {
|
||
this.currentIndex = index;
|
||
this.$nextTick(() => {
|
||
this.updateSliderPosition();
|
||
});
|
||
},
|
||
formatDate(date) {
|
||
if(typeof(date)!=='string'){
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
return `${year}-${month}-${day}`;
|
||
}else{
|
||
// 兼容后端/前端返回的 ISO 字符串:2026-03-25T00:00:00
|
||
// 只保留 YYYY-MM-DD
|
||
if (date.includes('T')) {
|
||
return date.split('T')[0];
|
||
}
|
||
return date;
|
||
}
|
||
},
|
||
async getTodoListByData() {
|
||
|
||
if (this.currentTask) {
|
||
try {
|
||
this.currentTask.abort();
|
||
uni.hideLoading();
|
||
} catch (err) {
|
||
}
|
||
}
|
||
|
||
uni.showLoading({
|
||
title: this.$t("common.loading")
|
||
});
|
||
let requestBody = "";
|
||
try {
|
||
let params = {};
|
||
params.TodoSegment = this.filterType;
|
||
if(this.currentIndex ===0){//根据currentIndex获取TodoCategory
|
||
params.TodoCategory = "Arrival";
|
||
}else if(this.currentIndex ===1){
|
||
params.TodoCategory = "Departure";
|
||
}else if(this.currentIndex ===2){
|
||
params.TodoCategory = "Inhouse";
|
||
}else if(this.currentIndex ===3){
|
||
params.TodoCategory = "Others";
|
||
}
|
||
if(this.currentIndex===2||this.currentIndex===3){
|
||
if(this.isYesterday){
|
||
params.StartDate = this.formatDate(this.yesterdayDate);
|
||
params.EndDate = this.formatDate(this.yesterdayDate);
|
||
}else{
|
||
params.StartDate = this.formatDate(this.todayDate);
|
||
params.EndDate = this.formatDate(this.todayDate);
|
||
}
|
||
}else{
|
||
params.StartDate = this.formatDate(this.startDate);
|
||
params.EndDate = this.formatDate(this.endDate);
|
||
}
|
||
this.calendarSave[0] = this.formatDate(params.StartDate);
|
||
this.calendarSave[1] = this.formatDate(params.EndDate);
|
||
|
||
this.checkCalendarSave();
|
||
|
||
requestBody = JSON.stringify(params);
|
||
|
||
const res = await getTodoList(params, {
|
||
getTask: (task, options) => {
|
||
this.currentTask = task;
|
||
}
|
||
});
|
||
|
||
this.currentTask = null;
|
||
|
||
if (Array.isArray(res.data.records) && res.data.records.length > 0) {
|
||
this.showTodoListView=true;
|
||
this.listData = res.data.records.map(record => ({
|
||
...record,
|
||
dateRecords: record.dateRecords.map(dateRecord => ({
|
||
...dateRecord,
|
||
showDetailLoading: false, // 为每条 dateRecord 添加 loading
|
||
showDetail: false, // 添加展开状态
|
||
arrowName: 'arrow-down', // 添加箭头方向
|
||
isProcessing: false,
|
||
detailData: null,
|
||
splitDescription:null,
|
||
showOffer:false,
|
||
itemOpen:"none"
|
||
}))
|
||
}));
|
||
}else{
|
||
if(res.data.records.length === 0){
|
||
this.dataNull = this.$t("common.noRecord");
|
||
}else if(res.errorCode.toUpperCase().indexOf('NO RECORD') != -1){
|
||
this.dataNull = this.$t("todo.returnError");
|
||
}
|
||
|
||
this.showTodoListView=false;
|
||
}
|
||
} catch (e) {
|
||
|
||
if (e.errMsg.includes("abort")) {
|
||
|
||
} else if (e.data!==null&&e.data!==undefined&&e.data.message!==undefined){
|
||
this.dataNull = e.data.message;
|
||
this.showTodoListView=false;
|
||
console.error(e.data.message);
|
||
}else{
|
||
this.dataNull = this.$t("todo.returnError");
|
||
this.showTodoListView=false;
|
||
console.error(e);
|
||
}
|
||
} finally {
|
||
if(!this.currentTask){
|
||
uni.hideLoading();
|
||
}
|
||
}
|
||
},
|
||
async fetchTodoDetail(record) {
|
||
// 防止重复点击
|
||
if (record.isProcessing) {
|
||
return;
|
||
}
|
||
if (record.arrowName === 'arrow-down') {
|
||
try {
|
||
this.todoDetailData = [];
|
||
let params = {
|
||
PlayerId: record.playerId,
|
||
TodoSegment: this.filterType
|
||
};
|
||
if(this.currentIndex ===0){//根据currentIndex获取TodoCategory
|
||
params.TodoCategory = "Arrival";
|
||
}else if(this.currentIndex ===1){
|
||
params.TodoCategory = "Departure";
|
||
}else if(this.currentIndex ===2){
|
||
params.TodoCategory = "Inhouse";
|
||
}else if(this.currentIndex ===3){
|
||
params.TodoCategory = "Others";
|
||
}
|
||
record.isProcessing = true;
|
||
record.showDetailLoading = true;
|
||
//如果是Inhouse或者Others 参数日期为当天
|
||
if(this.currentIndex === 2 || this.currentIndex ===3)params.Date = this.formatDate(this.todayDate);
|
||
else params.Date = this.formatDate(record.actionDate);
|
||
const res = await getTodoDetail(params);
|
||
if (res != null && res.success == true) {
|
||
record.detailData = res.data;
|
||
if(record.detailData.descriptions!==null){
|
||
for(let i=0;i<record.detailData.descriptions.length;i++){
|
||
if(record.detailData.descriptions[i].itemRecordType == 'Offer'){
|
||
record.showOffer = true;
|
||
}
|
||
}
|
||
}
|
||
setTimeout(() => {
|
||
record.arrowName = 'arrow-up';
|
||
record.showDetail = true;
|
||
record.showDetailLoading = false;
|
||
record.isProcessing = false;
|
||
}, 1000);
|
||
}else{
|
||
uni.showToast({
|
||
title:res.message,
|
||
icon: "none"
|
||
});
|
||
record.showDetail = false;
|
||
record.arrowName = 'arrow-down';
|
||
record.showDetailLoading = false;
|
||
record.isProcessing = false;
|
||
}
|
||
} catch (e) {
|
||
uni.showToast({
|
||
title:this.$t("todo.detailFail"),
|
||
icon: "none"
|
||
});
|
||
record.showDetail = false;
|
||
record.arrowName = 'arrow-down';
|
||
record.showDetailLoading = false;
|
||
record.isProcessing = false;
|
||
} finally {
|
||
}
|
||
} else {
|
||
// 收起时添加一个短暂的延迟,让动画更自然
|
||
record.isProcessing = true;
|
||
setTimeout(() => {
|
||
record.showDetail = false;
|
||
record.arrowName = 'arrow-down';
|
||
record.showDetailLoading = false;
|
||
record.isProcessing = false;
|
||
}, 100); // 100ms延迟让收起更自然
|
||
}
|
||
},
|
||
|
||
|
||
updateSliderPosition() {
|
||
const query = uni.createSelectorQuery().in(this);
|
||
|
||
// 获取当前选中tab的位置信息
|
||
query.select(`#tab${this.currentIndex}`).boundingClientRect();
|
||
|
||
// 获取slider-container的位置信息
|
||
query.select('#slider-container').boundingClientRect();
|
||
|
||
query.exec(rects => {
|
||
if (rects && rects.length === 2) {
|
||
const tabRect = rects[0];
|
||
const containerRect = rects[1];
|
||
|
||
if (tabRect && containerRect) {
|
||
// 计算tab的中心位置
|
||
const tabCenter = tabRect.left + (tabRect.width / 2);
|
||
|
||
// 计算slider应该移动的距离(相对于slider-container)
|
||
this.sliderPosition = tabCenter - containerRect.left - 10; // 10是slider宽度的一半
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
// 监听日期区间的变化,以修改日历 icon 的颜色
|
||
checkCalendarSave() {
|
||
if (!this.calendarSave[0] || !this.calendarSave[1]) {
|
||
this.calendarIconColor = "#000000";
|
||
return;
|
||
}
|
||
|
||
const startDt = new Date(this.calendarSave[0]);
|
||
const endDt = new Date(this.calendarSave[1]);
|
||
|
||
// 获取今天和明天的日期,并且设置时间部分为00:00:00
|
||
const today = new Date();
|
||
if(this.isYesterday){
|
||
today.setDate(today.getDate() - 1); // 设置为昨天
|
||
}
|
||
today.setHours(0, 0, 0, 0);
|
||
|
||
const tomorrow = new Date(today);
|
||
tomorrow.setDate(today.getDate() + 1);
|
||
|
||
const isStartToday = this.isSameDate(startDt, today);
|
||
const isEndTomorrow = this.isSameDate(endDt, tomorrow);
|
||
|
||
this.calendarIconColor = isStartToday && isEndTomorrow ? "#000000" : "#C39A4B";
|
||
},
|
||
|
||
showTrashIcon(){
|
||
const startDt = new Date(this.calendarSave[0]);
|
||
const endDt = new Date(this.calendarSave[1]);
|
||
|
||
// 获取今天和明天的日期,并且设置时间部分为00:00:00
|
||
const today = new Date();
|
||
if(this.isYesterday){
|
||
today.setDate(today.getDate() - 1); // 设置为昨天
|
||
}
|
||
today.setHours(0, 0, 0, 0);
|
||
|
||
const tomorrow = new Date(today);
|
||
tomorrow.setDate(today.getDate() + 1);
|
||
|
||
const isStartToday = this.isSameDate(startDt, today);
|
||
const isEndTomorrow = this.isSameDate(endDt, tomorrow);
|
||
|
||
const canShow = (isStartToday && isEndTomorrow) || this.currentIndex ===2 || this.currentIndex ===3 ? false : true;
|
||
return canShow;
|
||
},
|
||
isSameDate(date1, date2) {
|
||
return date1.getFullYear() === date2.getFullYear() &&
|
||
date1.getMonth() === date2.getMonth() &&
|
||
date1.getDate() === date2.getDate()
|
||
}
|
||
},
|
||
computed: {
|
||
getFlightDescription() {
|
||
return function(record) {
|
||
if (record.itemRecordType == 'Flight')
|
||
return record.itemRecordDescription;
|
||
};
|
||
},
|
||
hasFlightRecord() {
|
||
return function(record) {
|
||
let result = false;
|
||
for (let i = 0; i < record.length; i++) {
|
||
if (record[i].itemRecordType == 'Flight') {
|
||
result = true;
|
||
break;
|
||
} else {
|
||
result = false;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
},
|
||
getOfferDescription() {
|
||
return function(record) {
|
||
if (record.itemRecordType == 'Offer')
|
||
return record.itemRecordDescription;
|
||
};
|
||
},
|
||
getLimoDescription() {
|
||
return function(record) {
|
||
if (record.itemRecordType == 'Limo')
|
||
return record.itemRecordDescription;
|
||
};
|
||
},
|
||
hasLimoRecord() {
|
||
return function(record) {
|
||
let result = false;
|
||
for (let i = 0; i < record.length; i++) {
|
||
if (record[i].itemRecordType == 'Limo') {
|
||
result = true;
|
||
break;
|
||
} else {
|
||
result = false;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
},
|
||
getRoomDescription() {
|
||
return function(record) {
|
||
if (record.itemRecordType == 'Room'){
|
||
return record.itemRecordDescription.split('|').slice(0, 2).join("|");
|
||
}
|
||
};
|
||
},
|
||
hasRoomRecord() {
|
||
return function(record) {
|
||
let result = false;
|
||
for (let i = 0; i < record.length; i++) {
|
||
if (record[i].itemRecordType == 'Room') {
|
||
result = true;
|
||
break;
|
||
} else {
|
||
result = false;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
},
|
||
getItemDescription() {
|
||
return function(record) {
|
||
if (this.currentIndex !== 3 && record.indexOf("Sharer") !== -1) {
|
||
return record.split('|').slice(0, 2).join("|");
|
||
} else {
|
||
return record;
|
||
}
|
||
}
|
||
},
|
||
showETA(){
|
||
return function(record){
|
||
let isShow = false;
|
||
if (this.currentIndex ===0) {
|
||
if(record.eta !=='' && record.eta !== null){
|
||
isShow = true;
|
||
}
|
||
}
|
||
if(this.currentIndex === 2){
|
||
if(record.bigLossFlag === 1 || record.bigWinFlag === 1 || record.noPlayFlag === 1 || record.noPlayFlag === 2){
|
||
isShow = true;
|
||
}
|
||
}
|
||
return isShow;
|
||
}
|
||
},
|
||
getTextColor() {
|
||
return function(record) {
|
||
if (record.noPlayFlag == 1) {
|
||
return "#000000"; // black
|
||
}
|
||
return "#FFFFFF"; // white
|
||
}
|
||
},
|
||
getItemShowSharerIcon() {
|
||
return function(record) {
|
||
let sharerRecord = record.split("Sharer:");
|
||
let hasSharer = "N";
|
||
if (sharerRecord.length > 1) {
|
||
hasSharer = sharerRecord[1].trim();
|
||
}
|
||
return hasSharer == "N" ? false : true;
|
||
}
|
||
},
|
||
getETALable() {
|
||
return function(record) {
|
||
if (this.currentIndex !== 1 && this.currentIndex !== 2) {
|
||
return record.eta;
|
||
} else if (record.bigLossFlag === 1) {
|
||
return "BIGLOSS";
|
||
} else if (record.bigWinFlag === 1) {
|
||
return "BIGWIN";
|
||
} else if (record.noPlayFlag === 1 || record.noPlayFlag === 2){
|
||
return "No Play";
|
||
}
|
||
}
|
||
},
|
||
getETAColor() {
|
||
return function(record) {
|
||
if (this.currentIndex !== 1 && this.currentIndex !== 2 && record.eta !== null && record.eta !== undefined) {
|
||
if(this.checkPassEtaTime(record)){
|
||
return '#ff5a5f';
|
||
}else{
|
||
return '#9f9f9f';
|
||
}
|
||
} else if (record.bigLossFlag === 1) {
|
||
return '#ff5a5f';
|
||
} else if (record.bigWinFlag === 1) {
|
||
return '#4a6da7';
|
||
} else if(record.noPlayFlag === 1){
|
||
return '#ffff00'; // yellow
|
||
} else if (record.noPlayFlag === 2) {
|
||
return '#aa0000' // red
|
||
}
|
||
}
|
||
},
|
||
getparamData() {
|
||
return function(record) {
|
||
let paramData = {
|
||
items:[]
|
||
};
|
||
if(record.operaConfirmationNo!==undefined && record.operaConfirmationNo!==null && record.operaConfirmationNo!==""){
|
||
//遍历opeaConfirmationNo拿到MGM的hotelName和confNo
|
||
let items = record.operaConfirmationNo.split(",");
|
||
for(let i =0;i<items.length;i++){
|
||
let item={};
|
||
let rowData = items[i];
|
||
if(rowData != ""){
|
||
let property = rowData.split(';')[0];
|
||
let confNo = rowData.split(';')[1];
|
||
if(property!=="" && confNo !=="")
|
||
{
|
||
item.hotelName = property;
|
||
item.confNo = confNo;
|
||
paramData.items.push(item);
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
return paramData;
|
||
}
|
||
},
|
||
getPercentFormat() {
|
||
return function(val) {
|
||
return Math.trunc((val * 100)) + "%";
|
||
}
|
||
},
|
||
getOtherDescription(){
|
||
return function(descriptions){
|
||
let resList = [];
|
||
if(descriptions!==undefined && descriptions!==null){
|
||
for(let i=0;i<descriptions.length;i++){
|
||
let arrDesc = descriptions[i].split("#CRMLINE#");
|
||
if(arrDesc.length>0){
|
||
for(let j=0;j<arrDesc.length;j++){
|
||
if(arrDesc[j]!=""){
|
||
resList.push(arrDesc[j]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return resList;
|
||
}
|
||
},
|
||
getEmojiDescription() {
|
||
return function(descriptions) {
|
||
return descriptions.replace(/&#([0-9A-Fa-f]+)/g, function(match, code) {
|
||
if (/[A-Fa-f]/.test(code)) {
|
||
return String.fromCodePoint(parseInt(code, 16));
|
||
} else {
|
||
return String.fromCodePoint(parseInt(code, 10));
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
@import '../../static/css/todo.scss';
|
||
@import '../../static/css/custom.scss';
|
||
|
||
</style> |