Files
mgm-daylight-mcrm-mobile-ios/booking/bookingConfirm/bookingConfirm.vue
T
2026-09-08 17:20:27 +08:00

1886 lines
72 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<view class="hz-page">
<u-navbar :safeAreaInsetTop="true" :placeholder="true" :title="title" :fixed="true" :autoBack="true"
leftIconColor="#000000" titleStyle="font-weight:bold;">
<view style="margin-top:2px;margin-right:3px;" slot="right">
<view style="border:1rpx solid #ccc;border-radius: 14px;padding:4px 12px;"
class="hz-flex-row hz-flex-vertical-mid">
<image @click="navTo('/pages/findPlayer/findPlayer',1,false)"
src="../../static/images/ico_find_player.png" class="hz-nav-btn"></image>
<view style="height:20px;border-left:1px solid #ccc;margin-left:8px;margin-right:8px;"></view>
<image @click="navTo('/booking/bookingRecord/bookingRecord?from=booking',0,false)"
src="../../static/images/ico_list.png" class="hz-nav-btn"></image>
</view>
</view>
</u-navbar>
<view class="hz-spacing hz-bg-white" style="margin-top:8px;">
<view class="hz-card-profile hz-mr-b-30">
<view class="hz-flex-row">
<view style="width:60%">
<view class="hz-font-color-light hz-font-sm">{{$t("common.playerId")}}</view>
<view class="hz-font-bolder hz-font-lg">{{ playerData.playerId }}</view>
</view>
<view style="width:40%">
<view class="hz-font-color-light hz-font-sm">{{$t("common.tier")}}</view>
<view class="hz-font-bolder hz-font-lg">{{ playerData.tierName }}</view>
</view>
</view>
<view class="hz-flex-row hz-mr-t-30">
<view style="width:100%">
<view class="hz-font-color-light hz-font-sm">{{$t("common.name")}}</view>
<view class="hz-font-bolder hz-font-lg">{{playerData.salutation + " " + playerData.name }}
</view>
</view>
</view>
</view>
<view class="hz-pd-30 hz-font-bolder hz-font-md hz-card-booking"
:class="bookingData.bookType==1? 'hz-card-booking':'hz-card-extend'"
style="margin-top:10px;align-items: center;">
<view v-if="bookingData.bookType==1" class="hz-font-bolder hz-font-md hz-font-color-primary"
style="margin-bottom:10px;">
{{$t("bookingConfirm.currentStay")}}
</view>
<view v-if="bookingData.bookType==1" v-for="(item,index) in bookingData.dateList"
:key="'extend'+index" class="hz-font-color-primary" style="align-items: center;">
<view class="hz-flex-row" style="align-items: center;">
<image src="../../static/images/ico_calendar.png" style="width:16px;height:16px;"></image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{dateFormat(item.date[0])}}&nbsp; {{$t("common.to")}}&nbsp;
{{dateFormat(item.date[item.date.length-1])}}</span>
</view>
<view class="hz-flex-row" style="margin-top:8px;">
<view class="hz-flex-row" style="width:33%;align-items: center;">
<image src="../../static/images/ico_night.png" style="width:16px;height:16px;"></image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{getNight(item.numOfNight)}}</span>
</view>
<view class="hz-flex-row" style="width:33%;align-items: center;">
<image src="../../static/images/ico_room.png" style="width:16px;height:16px;"></image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{getRoom(item.numOfRoom)}}</span>
</view>
<view class="hz-flex-row" style="width:34%;justify-content: right;">
<view :class="getStatusColor(bookingData.lastOperaStatus,bookingData.approveStatus)"
class="hz-btn-status hz-font-min hz-text-center"
style="width:70%;height:14px;line-height:14px;">
{{getStatusText(bookingData.lastOperaStatus,bookingData.approveStatus)}}
</view>
</view>
</view>
</view>
<view v-if="bookingData.bookType==1" class="hz-font-bolder hz-font-md "
style="margin-top:20px;margin-bottom:10px;">
{{$t("bookingConfirm.extending")}}
</view>
<view v-if="bookingData.bookType==1" v-for="(item,index) in bookingData.extendDate"
:key="'date'+index" style="align-items: center;">
<view class="hz-flex-row" style="align-items: center;">
<image src="../../static/images/ico_calendar_grey.png" style="width:16px;height:16px;">
</image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{dateFormat(item.date[0])}}&nbsp; {{$t("common.to")}}&nbsp;
{{dateFormat(item.date[item.date.length-1])}}</span>
</view>
<view class="hz-flex-row" style="margin-top:8px;">
<view class="hz-flex-row" style="width:33%;align-items: center;">
<image src="../../static/images/ico_night_grey.png" style="width:16px;height:16px;">
</image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{getNight(item.numOfNight)}}</span>
</view>
<view class="hz-flex-row" style="width:33%;align-items: center;">
<image src="../../static/images/ico_room_grey.png" style="width:16px;height:16px;">
</image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{getRoom(item.numOfRoom)}}</span>
</view>
<view class="hz-flex-row" style="width:34%;align-items: center;"></view>
</view>
</view>
<view v-if="bookingData.bookType==0" v-for="(item,index) in bookingData.dateList"
:key="'date'+index" style="align-items: center;">
<view class="hz-flex-row" style="align-items: center;">
<image src="../../static/images/ico_calendar.png" style="width:16px;height:16px;"></image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{dateFormat(item.date[0])}}&nbsp; {{$t("common.to")}}&nbsp;
{{dateFormat(item.date[item.date.length-1])}}</span>
</view>
<view class="hz-flex-row" style="margin-top:8px;">
<view class="hz-flex-row" style="width:33%;align-items: center;">
<image src="../../static/images/ico_night.png" style="width:16px;height:16px;"></image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{getNight(item.numOfNight)}}</span>
</view>
<view class="hz-flex-row" style="width:33%;align-items: center;">
<image src="../../static/images/ico_room.png" style="width:16px;height:16px;"></image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{getRoom(item.numOfRoom)}}</span>
</view>
<view class="hz-flex-row" style="width:34%;align-items: center;"></view>
</view>
</view>
</view>
<view class="hz-spacing hz-mr-t-30" style="margin-bottom:30px;">
<view class="hz-flex-row">
<view style="width:65%">
<view class="hz-font-color-black hz-font-sm">{{$t("common.property")}}</view>
<view class="hz-font-bolder hz-font-lg">{{bookingData.propertyName}}</view>
</view>
<view style="width:35%">
<view class="hz-font-color-black hz-font-sm">{{$t("newBooking.roomType")}}</view>
<view class="hz-font-bolder hz-font-lg">{{bookingData.room}}</view>
</view>
</view>
<view
v-if="(bookingData.specialName!=null && bookingData.specialName!='') || (bookingData.bedTypeName!=null && bookingData.bedTypeName!='')"
class="hz-flex-row hz-mr-t-30">
<view style="width:100%">
<view class="hz-font-color-black hz-font-sm">{{$t("newBooking.specialPreference")}}</view>
<view class="hz-font-bolder hz-font-lg">
{{getSpecial(bookingData.specialName,bookingData.bedTypeName)}}
</view>
</view>
</view>
<view v-if="bookingData.sharerList!=null && bookingData.sharerList.length>0"
class="hz-flex-row hz-mr-t-30">
<view style="width:100%">
<view class="hz-font-color-black hz-font-sm">{{$t("bookingRecord.sharer")}}</view>
<view v-for="(item,index) in bookingData.sharerList" :key="'sharer'+index"
class="hz-font-bolder hz-font-lg">{{getSharer(item.playerId,item.name)}}</view>
</view>
</view>
<view class="hz-flex-row hz-mr-t-30">
<view style="width:65%">
<view class="hz-font-color-black hz-font-sm">{{$t("bookingConfirm.createdOn")}}</view>
<view class="hz-font-bolder hz-font-lg">{{bookingData.createdOn}}</view>
</view>
<view style="width:35%">
<view class="hz-font-color-black hz-font-sm">{{$t("bookingConfirm.createdBy")}}</view>
<view class="hz-font-bolder hz-font-lg">
{{bookingData.createdByName!=null?bookingData.createdByName:userData.userName}}
</view>
</view>
</view>
<view class="hz-flex-row">
<view v-if="bookingData.etaTime!=null" class="hz-flex-row hz-mr-t-30" style="width: 65%;">
<view style="width:100%">
<view class="hz-font-color-black hz-font-sm">{{ $t("common.etaTime") }}</view>
<view class="hz-font-bolder hz-font-lg" >{{ bookingData.etaTime || "-" }}</view>
<!-- <view class="hz-font-bolder hz-font-lg" >{{ handleShowWhenScreenshot(bookingData.eta) }}</view> -->
</view>
</view>
<view v-if="bookingData.miscCharge!=null" class="hz-flex-row hz-mr-t-30">
<view style="width:100%">
<view class="hz-font-color-black hz-font-sm">{{ $t("common.misCharge") }}</view>
<view class="hz-font-bolder hz-font-lg">{{ bookingData.miscCharge || "-" }}</view>
</view>
</view>
</view>
<view v-if="bookingData.depositType!=null" class="hz-flex-row hz-mr-t-30">
<view style="width:100%">
<view class="hz-font-color-black hz-font-sm">{{$t("newBooking.deposit")}}</view>
<view class="hz-font-bolder hz-font-lg">
{{bookingData.depositType==0? $t("newBooking.waiveDeposit"):$t("newBooking.collectDeposit")}}
</view>
</view>
</view>
<view v-if="bookingData.isPost!=null" class="hz-flex-row hz-mr-t-30">
<view style="width:100%">
<view class="hz-font-color-black hz-font-sm">{{$t("newBooking.postCharge")}}</view>
<view class="hz-font-bolder hz-font-lg">
{{bookingData.isPost==1? $t("newBooking.yesPost"):$t("newBooking.noPost")}}
</view>
</view>
</view>
</view>
<view :style="'height:'+footFuncHei+'rpx;'"></view>
</view>
<u-tabbar :fixed="true" :placeholder="true" :safeAreaInsetBottom="true"
customStyle="z-index:100;height:58px;">
<view @click="recheckBooking()" class="book hz-flex-row hz-spacing"
:class="submitLoading==true? 'hz-disabled':''">
<view class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center">
{{$t("bookingConfirm.confirmBooking")}}
</view>
</view>
</u-tabbar>
</view>
<u-popup :safeAreaInsetBottom="true" :safeAreaInsetTop="true" :mode="'center'" :round="12" :show="showMsgBox">
<view :style="'width:'+ windowWidth + 'px;'" style="padding:0px 25px 25px 25px;">
<view class="hz-flex-row" style="justify-content: center;">
<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;">
<rich-text v-html="msgStr" style="line-height:26px;"></rich-text>
</view>
<view v-if="bookingData && bookingData.bookType==0 && showDateList && item" v-for="(item,index) in bookingData.dateList"
:key="'date'+index" class="hz-pd-30 hz-font-bold hz-font-sm hz-card-extend"
style="margin-top:6px;align-items: center;">
<view class="hz-flex-row" style="align-items: center;">
<span class="hz-font-sm hz-font-bolder"
style="margin-left:4px;">{{dateFormat(item.date[0])}}&nbsp; {{$t("common.to")}}&nbsp;
{{dateFormat(item.date[item.date.length-1])}}</span>
</view>
<view class="hz-flex-row" style="margin-top:8px;">
<view class="hz-flex-row" style="width:33%;align-items: center;">
<image src="../../static/images/ico_night.png" style="width:16px;height:16px;"></image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{getNight(item.numOfNight)}}</span>
</view>
<view class="hz-flex-row" style="width:33%;align-items: center;">
<image src="../../static/images/ico_room.png" style="width:16px;height:16px;"></image>
<span class="hz-font-md hz-font-bolder"
style="margin-left:4px;">{{getRoom(item.numOfRoom)}}</span>
</view>
<view class="hz-flex-row" style="width:34%;align-items: center;">
<view v-if="item.status==0" class="hz-status-duein hz-btn-status hz-font-min hz-text-center"
style="margin-top:4px;width:100%;height:14px;line-height:14px;">Qualified</view>
<view v-if="item.status==1 && (item.isWaitlist==undefined || item.isWaitlist==0)"
class="hz-status-waitlist hz-btn-status hz-font-min hz-text-center"
style="margin-top:4px;width:100%;height:14px;line-height:14px;">Unqualified</view>
<view v-if="item.status==1 && item.isWaitlist!==undefined && item.isWaitlist==1"
class="hz-status-waitlist hz-btn-status hz-font-min hz-text-center"
style="margin-top:4px;width:100%;height:14px;line-height:14px;">WaitList</view>
</view>
</view>
</view>
<view v-if="showDirBtn" @click="navToDetail(url)"
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center" style="margin-top:20px;">
{{buttonStr}}
</view>
<view v-if="!showDirBtn" style="margin-top:10px;">
<view class="hz-flex-col" style="justify-content: center;align-items: center;margin-top:18px;">
<view @click="submitApproval()"
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center confirmButton">
{{$t("bookingConfirm.urgentApproval").toUpperCase()}}
</view>
<view @click="showWaitlistPop()"
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center confirmButton">
{{$t("bookingConfirm.putInWaitlist").toUpperCase()}}
</view>
<view @click="navTo('/booking/bookingRecord/bookingRecord?from=booking',0,false)"
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center confirmButton">
{{$t("bookingConfirm.backToRecords").toUpperCase()}}
</view>
</view>
</view>
</view>
</u-popup>
<u-modal :content="msgStr" :show="showMsg" :confirmText="yesText" :showCancelButton="false" closeOnClickOverlay
@confirm="showMsg=false" confirmColor="#C39A4B" @close="showMsg=false"></u-modal>
<!-- 审批模态框 -->
<u-popup :safeAreaInsetBottom="true" :safeAreaInsetTop="true" :mode="'center'" :round="12"
:show="showApprovalModal" @close="closeApprovalPop()">
<view :style="'width:'+ windowWidth + 'px;'" style="padding:0px 25px 25px 25px">
<view class="hz-flex-row" style="align-items: center; justify-content: space-between; margin-bottom: 10px;">
<view class="hz-flex-row" style="flex: 1; justify-content: center;margin-left: 25px;">
<text class="approvalHeader">Approval Request</text>
</view>
<view @click="closeApprovalPop()" style="width: 25px;">
<image src="/static/images/close.png" style="width: 25px;height: 25px; pointer-events: none;" />
</view>
</view>
<!-- Remark -->
<view style="margin-bottom: 16px;margin-top: 16px;">
<view style="text-align: left;"> {{$t("bookingConfirm.approvalRemark")}}</view>
<u-checkbox-group placement="row" @change="changeOtherRemark"
style="flex-direction: unset;display: block;">
<view style="width:50%;display: inline-flex;">
<u-checkbox activeColor="#C39A4B" labelColor="#333333" shape="circle"
customStyle="height:30px;width:100%;" label="Extend" name="Extend"></u-checkbox>
</view>
<view style="width:50%;display: inline-flex;position: relative;left:10%;">
<u-checkbox activeColor="#C39A4B" labelColor="#333333" shape="circle"
customStyle="height:30px;width:100%;" label="Remark" name="Remark"></u-checkbox>
</view>
</u-checkbox-group>
<view style="width:100%;margin-top:16px;" v-show="showRemark">
<view class="hz-font-bolder hz-font-md" style="margin-top:4px;">
<u--textarea v-model="freeRemark" :maxlength="128" :placeholder="inputRemark"></u--textarea>
</view>
</view>
</view>
<!-- Request Reason -->
<view style="margin-bottom:16px;">
<view class="hz-font-md hz-font-bolder" style="margin-bottom:8px;">
{{$t("bookingConfirm.requestReason")}} <text style="color: #ff0000;">*</text>
</view>
<view>
<lu-data-select placeholder="Select Reason" :options="selectReasonData" v-model="selectedReason"
:multiple="false" :filterable="true" @change="onReasonChange" style="width: 100%;" :clearable="false"></lu-data-select>
</view>
</view>
<!-- ROUTER TO APPROVAL -->
<view style="margin-bottom:16px;">
<view class="hz-font-md hz-font-bolder" style="margin-bottom:8px;">
{{$t("bookingConfirm.routeToApprover")}} <text style="color: #ff0000;">*</text>
</view>
<view>
<lu-data-select placeholder="Select Approver" :options="selectApproverData" v-model="selectedApprover"
:multiple="true" :filterable="true" @change="onApprovalChange" style="width: 100%;" :clearable="false"></lu-data-select>
</view>
</view>
<view class="hz-flex-col" style="justify-content: center;align-items: center;margin-top:10px;">
<view @click="submitApprovalRequest()"
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center"
style="background-color:#C39A4B;margin-bottom:10px;">
{{$t("bookingConfirm.submitApproval").toUpperCase()}}
</view>
<view @click="navTo('/booking/bookingRecord/bookingRecord?from=booking',0,false)"
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center"
style="background-color:#C39A4B;margin-bottom:10px;">
{{$t("bookingConfirm.backToRecords").toUpperCase()}}
</view>
</view>
</view>
</u-popup>
<!-- Waitlist 模态框 -->
<u-popup :safeAreaInsetBottom="true" :safeAreaInsetTop="true" :mode="'center'" :round="12"
:show="showWaitlistModal" @close="showWaitlistModal=false">
<view :style="'width:'+ windowWidth + 'px;'" style="padding:0px 25px 25px 25px">
<view class="hz-spacing" style="margin-top:10px;margin-left:15px;">
<view @click="showWaitlistModal=false" style="width: 25px;margin-left: auto;">
<image src="/static/images/close.png" style="width: 25px;height: 25px; pointer-events: none;" />
</view>
<view class="hz-flex-row" style="justify-content: center;">
<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;">
<rich-text v-html="msgStr" style="line-height:26px;"></rich-text>
</view>
<view style="margin-bottom: 10px;text-align: left;"> {{$t("bookingConfirm.remark")}}</view>
<!-- 受控单选:不用 u-checkbox-group(iOS 下可能出现内部多选状态不跟随 :value 的情况) -->
<view style="flex-direction: unset;display: block;">
<view style="width:50%;display: inline-flex;">
<u-checkbox activeColor="#C39A4B" labelColor="#333333" shape="circle"
customStyle="height:30px;width:100%;" label="2nd Room" name="2nd Room"
:checked="bookingData && bookingData.roomRemark === '2nd Room'"
@change="onRoomCheckboxChange('2nd Room')"></u-checkbox>
</view>
<view style="width:50%;display: inline-flex;position: relative;left:10%;">
<u-checkbox activeColor="#C39A4B" labelColor="#333333" shape="circle"
customStyle="height:30px;width:100%;" label="3rd Room" name="3rd Room"
:checked="bookingData && bookingData.roomRemark === '3rd Room'"
@change="onRoomCheckboxChange('3rd Room')"></u-checkbox>
</view>
</view>
<u-checkbox-group placement="row" @change="changeOtherRemark"
style="flex-direction: unset;display: block;">
<view style="width:50%;display: inline-flex;">
<u-checkbox activeColor="#C39A4B" labelColor="#333333" shape="circle"
customStyle="height:30px;width:100%;" label="Extend" name="Extend"></u-checkbox>
</view>
<view style="width:50%;display: inline-flex;position: relative;left:10%;">
<u-checkbox activeColor="#C39A4B" labelColor="#333333" shape="circle"
customStyle="height:30px;width:100%;" label="Remark" name="Remark"></u-checkbox>
</view>
</u-checkbox-group>
<view style="width:100%;margin-top:16px;" v-show="showRemark">
<view class="hz-font-bolder hz-font-md" style="margin-top:4px;">
<u--textarea v-model="freeRemark" :maxlength="128" :placeholder="inputRemark"></u--textarea>
</view>
</view>
</view>
<view class="hz-flex-col" style="justify-content: center;align-items: center;margin-top:18px;">
<view @click="submitWaitlist()"
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center confirmButton">
{{$t("bookingConfirm.putInWaitlist").toUpperCase()}}
</view>
<view @click="navTo('/booking/bookingRecord/bookingRecord?from=booking',0,false)"
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center confirmButton">
{{$t("bookingConfirm.backToRecords").toUpperCase()}}
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import dayjs from '../../uni_modules/uview-ui/libs/util/dayjs.js';
import {
checkTPD,
checkSecondTPD
} from '../../api/mgmApi.js';
import {
saveBooking,
editBooking,
getBookings
} from '../../api/bookingApi.js';
import {
getWaitlistBooking,
getCriterias,
} from '../../api/configApi.js';
import {
debounce
} from 'lodash';
import {
getApprovalReason,
getApprover
} from '../../api/approvalApi.js';
export default {
data() {
return {
//数据变量
playerData: null,
userData: null,
bookingData: null,
// 界面变量
title: '',
iconPath: '',
showWaitlistModal: false,
msgStr: '',
buttonStr: '',
url: '',
inputRemark: this.$t("common.inputRemark"),
showDirBtn: true,
showMsgBox: false,
showDateList: false,
windowWidth: 0,
footFuncHei: 100,
showMsg: false,
yesText: this.$t("common.ok"),
freeRemark: '',
showRemark: false,
submitLoading: false,
// 审批模态框变量
showApprovalModal: false,
// 多选 Approver:必须为数组,否则 lu-data-select 会报 Expected 'array' for multiple mode
selectedApprover: [],
selectedReason:"",
selectedApproverName:"",
selectApproverData:[],
selectReasonData:[],
routingResaon:"",
canSubmit:true,
approvalForm: {
numberOfRoomRequest: '1',
requestReason: '',
approvalRoutingRemark: '',
remarkText: '',
routeToApprover: ''
},
approvers: ['Clara', 'Mooney', 'Ella'],
// 下拉框变量
openDropdown: null,
reasonOptions: [{
name: 'Guest from Wynn',
value: 'Guest from Wynn'
},
{
name: 'VIP Request',
value: 'VIP Request'
},
{
name: 'Other',
value: 'Other'
}
],
}
},
onLoad(opt) {
// 初始化界面
this.initUI();
this.playerData = uni.getStorageSync("playerData");
this.userData = uni.getStorageSync("userData");
this.getBooking();
},
onShow() {
// 检查是否登录
// this.isLogin();
},
methods: {
// 數據方法
getBooking() {
this.bookingData = uni.getStorageSync("bookingData");
// 确保 roomRemark 是响应式字段,否则 iOS 上可能出现 u-checkbox 状态未被正确回刷导致“可多选”
if (this.bookingData !== null && this.bookingData !== undefined && typeof this.bookingData === 'object') {
const hasRoomRemark = Object.prototype.hasOwnProperty.call(this.bookingData, 'roomRemark');
if (!hasRoomRemark || this.bookingData.roomRemark === null || this.bookingData.roomRemark === undefined || this.bookingData.roomRemark === 'null') {
(this.$set ? this.$set(this.bookingData, 'roomRemark', '') : this.bookingData.roomRemark = '');
}
const hasOtherRemark = Object.prototype.hasOwnProperty.call(this.bookingData, 'otherRemark');
if (!hasOtherRemark || this.bookingData.otherRemark === null || this.bookingData.otherRemark === undefined || this.bookingData.otherRemark === 'null') {
(this.$set ? this.$set(this.bookingData, 'otherRemark', '') : this.bookingData.otherRemark = '');
}
}
if (this.bookingData !== null && this.bookingData !== undefined && this.bookingData !== '') {
this.getCurrentDate();
} else {
// 报错
}
},
async checkBooking(type) {
uni.showLoading({
title: this.$t("common.loading")
});
try {
let params = {};
//let dates = ''; 看到时候MGM最后确定是传字符串还是数组给他们,后端接口也要相应调整一下
let dates = [];
if (type == 1) {
for (let i = 0; i < this.bookingData.extendDate.length; i++) {
let date = this.bookingData.extendDate[i].date;
for (let j = 0; j < date.length - 1; j++) {
dates.push(date[j]);
}
}
} else {
for (let i = 0; i < this.bookingData.dateList.length; i++) {
let date = this.bookingData.dateList[i].date;
for (let j = 0; j < date.length - 1; j++) {
/*if(dates==''){
dates = date[j];
}else{
dates = dates+','+date[j];
}*/
dates.push(date[j]);
}
}
}
var criteriaCount = this.bookingData.criteriaList.length;
var dateRange = [];
var rangeStartDate = this.bookingData.checkInDate;
var bookingType = this.bookingData.bookingTypeName;
var roomCat = this.bookingData.roomCategory;
var isSecondRoom = false;
var currentRoomNum = 0;
var lastRangeDate = null;
let lastEndDate = null;
for (let i = 0; i < criteriaCount; i++) {
let criteria = this.bookingData.criteriaList[i];
let numOfRoom = 0;
let firstDate = criteria.bookDate == this.bookingData.checkInDate;
let lastDate = (i == criteriaCount - 1);
if (bookingType == "Mass") {
if (criteria.massStandard != undefined) {
if (roomCat == "Standard Room") {
numOfRoom = criteria.massStandard
} else if (roomCat == "Suite") {
numOfRoom = criteria.massStandard
}
} else if (criteria.massSuite != undefined) {
numOfRoom = criteria.massSuite
}
} else if (bookingType == "IM") {
if (criteria.im != undefined) {
numOfRoom = criteria.im
}
}
numOfRoom = (numOfRoom + 1);
if (firstDate) {
currentRoomNum = numOfRoom;
}
if (rangeStartDate == null) rangeStartDate = lastEndDate;
if (currentRoomNum == null) currentRoomNum = numOfRoom;
if (numOfRoom != currentRoomNum || lastDate) {
if (rangeStartDate == this.bookingData.checkOutDate) continue;
let nowRoomNum = numOfRoom;
numOfRoom = currentRoomNum;
let endDate = lastEndDate;
let rangeObj = {
"StartDate": rangeStartDate,
"EndDate": lastEndDate,
"RoomBookingOrdinalNumber": numOfRoom,
}
dateRange.push(rangeObj)
rangeStartDate = null;
currentRoomNum = nowRoomNum;
if (numOfRoom > 1) isSecondRoom = true;
}
lastEndDate = criteria.bookDate;
}
// console.log(dateRange)
params.playerId = this.playerData.playerId;
params.property = this.bookingData.propertyName
params.roomCat = this.bookingData.room;
params.bookingType = this.bookingData.bookingTypeName;
params.dates = dates;
await this.writeLog(this.userData.userId, "check_booking", "",
"[APP][bookingConfirm.vue][checkBooking][Begin]", "", "", 0, false);
let res = {};
if (this.bookingData.roomForBooking == 0 && this.bookingData.roomForWaitlist == 1) {
res.success = true;
res.data = {}
res.data.status = 1;
} else {
if (isSecondRoom) {
params.dateRange = dateRange;
res = await checkSecondTPD(params);
} else {
res = await checkTPD(params);
}
}
if (res.success === true) {
var waitlistRes = this.checkWaitlist();
var changeWaitlist = false;
//把waitlist日期与够不够分日期合并,changeWaitlist为true时则原来够分改为waitlist
if (waitlistRes.status == 1 || waitlistRes.status == 2) {
if (res.data.status == 0) {
if (waitlistRes.status == 2)
res.data.status = 1; // 改TPD返回的状态为不够分
else
res.data.status = 2; // 改TPD返回的状态为部分够分
res.data.dates = waitlistRes.dates;
changeWaitlist = true;
} else if (res.data.status == 2) {
if (waitlistRes.status == 2)
res.data.status = 1; // 改TPD返回的状态为不够分
var resdates = res.data.dates;
var waitDates = Array.isArray(waitlistRes.dates) ? waitlistRes.dates : [];
var count = 0;
// 把TPD返回的datelist结果跟Room allotment的waitlist结果匹配一次
for (var i in resdates) {
const waitDate = waitDates[i];
if (waitDate && waitDate.status == 1) {
resdates[i].status = 1;
resdates[i].isWaitlist = 1;
}
if (resdates[i].status == 1) count++;
}
// 这种情况是如果TPD返回部分够分,经过检查Room allotment的waitlist后,全部都变成不够分的场景
if (count == resdates.length) res.data.status = 1;
}
}
// 够分
if (res.data.status == 0) {
if (type == 1) {
// 把extendDate中的状态都设置成够分
for (let i = 0; i < this.bookingData.extendDate.length; i++) {
this.bookingData.extendDate[i].status = 0;
this.bookingData.extendDate[i].submit = true;
}
} else {
// 把dateList中的状态都设置成够分
for (let i = 0; i < this.bookingData.dateList.length; i++) {
this.bookingData.dateList[i].status = 0;
this.bookingData.dateList[i].submit = true;
}
}
uni.setStorageSync("bookingData", this.bookingData);
return 1; // 全够分
} else if (res.data.status == 1 || this.bookingData.bookType == "1") { // 不够分
if (type == 1) {
// 把extendDate中的状态都设置成不够分
for (let i = 0; i < this.bookingData.extendDate.length; i++) {
this.bookingData.extendDate[i].status = 1;
this.bookingData.dateList[i].checked = true;
}
} else {
// 把dateList中的状态都设置成不够分
for (let i = 0; i < this.bookingData.dateList.length; i++) {
this.bookingData.dateList[i].status = 1;
this.bookingData.dateList[i].checked = true;
}
// 删除sharer 之后waitlist要去掉
// this.bookingData.sharerList = [];
}
uni.setStorageSync("bookingData", this.bookingData);
return 3; // 全部不够分
} else if (res.data.status == 2) { // 部分够分
/* //測試用
const originalArray = [
{ "date": "2024-01-01", "status": 1 },
{ "date": "2024-01-02", "status": 0 },
{ "date": "2024-01-05", "status": 0},
{ "date": "2024-01-06", "status": 1 },
{ "date": "2024-01-08", "status": 1 }
];*/
const originalArray = res.data.dates;
if (originalArray != null) {
// 初始化结果数组和临时日期数组
let resultArray = [];
let tpdArray = [];
let tempDates = [];
let prevStatus = null;
let prevDate = null;
// 遍历原始数组
for (let i = 0; i < originalArray.length; i++) {
const currentObject = originalArray[i];
tpdArray.push(currentObject);
const currentDate = currentObject.date;
const nextDate = new Date(currentDate);
nextDate.setDate(nextDate.getDate() + 1);
const currentStatus = currentObject.status;
const currentWaitlist = currentObject.isWaitlist;
// 如果当前status与前一个不同,或者tempDates为空,则添加新的status对象到结果数组
if (prevStatus === null || currentStatus !== prevStatus) {
if (tempDates.length > 0) { // 如果tempDates有数据,则添加到结果数组
// 在添加之前,尝试将tempDates中最大的日期加一天
const lastDate = new Date(tempDates[tempDates.length - 1]);
lastDate.setDate(lastDate.getDate() + 1); // 增加一天
tempDates.push(dayjs(lastDate).format("YYYY-MM-DD"));
resultArray.push({
date: tempDates,
status: prevStatus,
isWaitlist: currentWaitlist
});
tempDates = []; // 重置tempDates
}
prevStatus = currentStatus; // 更新prevStatus
prevDate = dayjs(nextDate).format("YYYY-MM-DD");
}
// 将当前日期添加到tempDates
tempDates.push(currentDate);
// 如果这是最后一个元素,或者下一个元素的status或date+1天不同,则添加当前status对象到结果数组
if (i === originalArray.length - 1 || (i < originalArray.length - 1 && (
currentStatus !== originalArray[i + 1].status || dayjs(nextDate)
.format("YYYY-MM-DD") !== originalArray[i + 1].date))) {
// 在添加之前,尝试将tempDates中最大的日期加一天
const lastDate = new Date(tempDates[tempDates.length - 1]);
lastDate.setDate(lastDate.getDate() + 1); // 增加一天
tempDates.push(dayjs(lastDate).format("YYYY-MM-DD"));
resultArray.push({
date: tempDates,
status: currentStatus,
isWaitlist: currentWaitlist
});
tempDates = []; // 重置tempDates,为下一个可能的status做准备
}
}
//console.log(resultArray);
this.bookingData.tpdList = tpdArray;
if (type == 1) {
// 重新构建extendDate
this.bookingData.extendDate = [];
} else {
// 重新构建dateList
this.bookingData.dateList = [];
}
for (let i = 0; i < resultArray.length; i++) {
let tpdResult = resultArray[i];
let submitTag = false;
let objDate = {
date: tpdResult.date,
status: tpdResult.status,
checked: false,
remark: '',
numOfNight: tpdResult.date.length - 1,
numOfRoom: 1,
submit: submitTag,
bookingStatus: '',
isWaitlist: tpdResult.isWaitlist
};
if (type == 1) {
this.bookingData.extendDate.push(objDate);
} else {
this.bookingData.dateList.push(objDate);
}
}
}
uni.setStorageSync("bookingData", this.bookingData);
return 2; // 部分够分
}
} else {
this.showMsg = true;
this.msgStr = res.message;
await this.writeLog(this.userData.userId, "check_booking", "",
"[APP][bookingConfirm.vue][checkBooking][Fail]" + res.message, "", "", 1, false);
}
} catch (e) {
console.error(e);
this.showMsg = true;
this.msgStr = e.errMsg;
await this.writeLog(this.userData.userId, "check_booking", "",
"[APP][bookingConfirm.vue][checkBooking][Catch Exception]" + e.errMsg, "", "", 1, false);
} finally {
uni.hideLoading();
}
},
async confirmBooking() {
try {
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][confirmBooking][Begin]", "", "", 0, true);
let needCheckBooking = this.checkIMCheckBooking();
if (needCheckBooking) {
var resCheck = await this.checkBooking(this.bookingData.bookType);
} else {
var resCheck = 3;
}
uni.showLoading({
title: this.$t("common.loading")
});
if (resCheck === 1) // 够分,直接submit
{
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][confirmBooking][CheckBooking Result]1", "", "", 0, false);
let resBook = null
if (this.bookingData.bookType == 1) {
resBook = await editBooking(this.bookingData); // 保存到數據庫
} else {
resBook = await saveBooking(this.bookingData); // 保存到數據庫
}
// 保存數據成功,彈出對話框,點View Booking去到bookingRecords
if (resBook.success == true) {
this.buttonStr = this.$t("bookingConfirm.backToRecords");
this.iconPath = '../../static/images/ico_suc.png';
if (this.bookingData.bookType == 0) {
// this.msgStr = this.$t("bookingConfirm.alert1") + "<br /><span class='hz-font-xl'>" + this.playerData.playerId +"</span><br />"+ this.$t("bookingConfirm.alert2");
this.msgStr = this.$t("bookingConfirm.alert1")
this.bookingData.lastOperaStatus = null;
this.bookingData.approveStatus = 'PN';
} else {
if (resBook.errorCode == "EMAIL") {
this.msgStr = this.$t("bookingConfirm.extensionEmail");
} else if (resBook.errorCode == "OWS_ERROR") {
this.msgStr = resBook.message;
} else {
this.msgStr = this.$t("bookingConfirm.extensionProccessing");
this.bookingData.approveStatus = 'PN';
}
}
const resultBookings = resBook.data;
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][confirmBooking][Success][Result Count]" + resultBookings
.length, "", "", 0, false);
//if(resultBookings.length==1){
// 保存完把新建的id或extend的id带过去给detail页
//this.url = "/booking/bookingDetail/bookingDetail?id="+resultBookings[0].id+"&conf="+resultBookings[0].confirmationNo + "&from=booking";
this.url = "/booking/bookingRecord/bookingRecord?from=booking";
//}/*else if(resultBookings.length>1){
//this.url = "/booking/bookingGroup/bookingGroup?groupId="+resultBookings[0].groupId;
//}
this.showMsgBox = true;
}
// 保存失敗彈出錯誤提示框
else {
var message = resBook.errorCode != null && resBook.errorCode != "" ? resBook.errorCode :
resBook.message;
this.buttonStr = this.$t("common.ok");
this.iconPath = '../../static/images/ico_err.png';
this.msgStr = this.$t("common.saveFail") + ". " + this.$t("common.errorMsg") + ": " +
message; // 具體的錯誤信息,errorCode要做一个mapping,对应一些什么错误
this.url = '';
this.showMsgBox = true;
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][confirmBooking][ErrorMessage]" + resBook.message,
"[RequestData]" + JSON.stringify(this.bookingData), "", 1, false);
}
} else if (resCheck === 2) // 部分够分和不够分的情況,彈出提示,跳到下一頁選擇性submit
{
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][confirmBooking][CheckBooking Result]2", "", "", 0, false);
uni.setStorageSync("bookingData", this.bookingData);
this.iconPath = '../../static/images/ico_err.png';
this.showDateList = true;
// 如果需要弹出提示是不是有Date的状态是room allotment的waitlist改变的,在这里循环一次dateList找是否有isWaitlist的记录,然后改变提示
var isWaitlist = false;
for (var i of this.bookingData.criteriaList) {
if (i.bookDate == this.bookingData.checkOutDate) continue;
if (i.isWaitlist == 1) isWaitlist = true;
}
this.msgStr = isWaitlist ? this.$t("bookingConfirm.alert4") : this.$t("bookingConfirm.alert5");
this.url = "/booking/submitBooking/submitBooking"
this.buttonStr = this.$t("bookingConfirm.viewProceedBooking");
this.showMsgBox = true;
} else if (resCheck === 3) // 全部不够分的情况,直接跳转到newWaitlist
{
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][confirmBooking][CheckBooking Result]3", "", "", 0, false);
uni.setStorageSync("bookingData", this.bookingData);
this.bookingData.remark = null;
this.iconPath = '../../static/images/ico_err.png';
//IM 不能waitlist
if (this.bookingData.bookingTypeName == "IM") {
this.showDateList = false;
// 如果需要弹出提示是不是有Date的状态是room allotment的waitlist改变的,在这里循环一次dateList找是否有isWaitlist的记录,然后改变提示
var isWaitlist = false;
var secondRoom = 0;
for (var i of this.bookingData.criteriaList) {
if (i.bookDate == this.bookingData.checkOutDate) continue;
if (i.isWaitlist == 1) isWaitlist = true;
if (i.secondRoom != undefined) secondRoom = i.secondRoom
}
// if(needCheckBooking){
// this.msgStr = isWaitlist?this.$t("bookingConfirm.IMAlert2"):this.$t("bookingConfirm.alert3");
// }else{
// this.msgStr = this.$t("bookingConfirm.IMAlert1");
// }
if (secondRoom > 0) {
this.msgStr = this.$t("bookingConfirm.IMAlert1");
} else {
this.msgStr = isWaitlist ? this.$t("bookingConfirm.IMAlert2") : this.$t(
"bookingConfirm.alert3");
}
this.buttonStr = this.$t("bookingConfirm.backToRecords");
this.url = "/booking/bookingRecord/bookingRecord?from=booking"
this.showDirBtn = true;
this.showMsgBox = true;
} else {
var isWaitlist = false;
var secondRoom = 0;
for (var i of this.bookingData.criteriaList) {
if (i.bookDate == this.bookingData.checkOutDate) continue;
if (i.isWaitlist == 1 || i.reserved == 1) isWaitlist = true;
if (i.secondRoom != undefined) secondRoom = i.secondRoom;
}
this.msgStr = isWaitlist ? this.$t("bookingConfirm.alert4") : this.$t(
"bookingConfirm.alert3");
if (secondRoom == 1) this.msgStr = this.$t("bookingConfirm.secondRoom1")
if (secondRoom == 2) this.msgStr = this.$t("bookingConfirm.secondRoom2")
if (secondRoom == 3) this.msgStr = this.$t("bookingConfirm.secondRoom3")
if (secondRoom == 4) this.msgStr = this.$t("bookingConfirm.secondRoom4")
this.iconPath = '../../static/images/warn.png';
this.showDirBtn = false;
this.buttonStr = this.$t("bookingConfirm.viewBooking");
// this.buttonStr = this.$t("bookingConfirm.backToRecords");
// this.msgStr = this.$t("bookingConfirm.alert3");
// this.url = "/booking/bookingRecord/bookingRecord?from=booking"
this.checkWaitlistBooking();
// if(isWaitlist){
// this.checkWaitlistBooking();
// }else{
// this.showMsgBox = true;
// }
}
}
} catch (e) {
uni.hideLoading();
// 把錯誤信息寫入log
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, "save_booking", "",
"[APP][bookingConfirm.vue][confirmBooking][Catch Exception]" + e.errMsg, request, response,
1, false);
} finally {
uni.hideLoading();
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][confirmBooking][End]", "", "", 0, false);
}
},
checkIMCheckBooking() {
let bookingType = this.bookingData.bookingTypeName;
let propertyName = this.bookingData.propertyName;
let roomName = this.bookingData.room;
// if(bookingType=="IM"){
// if(propertyName.includes("MGM")){
// if(roomName=="Grand Room"||roomName.includes("Suite")||roomName.includes("Resort")){
// return true;
// }else{
// return false;
// }
// }else{
// return false
// }
// }
return true;
},
checkWaitlist() {
var dates = [];
let isWaitlist = false;
var waitlistCount = 0;
var criteriaCount = this.bookingData.criteriaList.length;
var lastDate = 0;
// var isReserved = false;
var bookingType = this.bookingData.bookingTypeName;
var roomCat = this.bookingData.roomCategory;
var secondRoom = 0; //1=max room 2=partal night max room 3=has suite 4=2nd room suite
var secondRoomNum = 0;
for (let i = 0; i < criteriaCount; i++) {
let criteria = this.bookingData.criteriaList[i];
if (criteria.bookDate == this.bookingData.checkOutDate) continue;
// if(criteria.reserved==1) isReserved=true;
if (bookingType == "Mass") {
if (criteria.massStandard != undefined) {
if (roomCat == "Standard Room") {
if (criteria.massStandard >= 2) {
secondRoom = 2;
secondRoomNum++;
}
} else if (roomCat == "Suite") {
if (criteria.massStandard >= 1) secondRoom = 4;
}
} else if (criteria.massSuite != undefined) {
secondRoom = 3;
}
} else if (bookingType == "IM") {
if (criteria.im != undefined) {
if (criteria.im >= 2) {
secondRoom = 2;
secondRoomNum++;
}
}
}
}
if (secondRoomNum == this.bookingData.criteriaList.length - 1 && secondRoom == 2) secondRoom = 1;
for (let i = 0; i < criteriaCount; i++) {
let criteria = this.bookingData.criteriaList[i];
if (criteria.bookDate == this.bookingData.checkOutDate) {
lastDate = 1; //不计算checkoutDate
continue;
}
var obj = {
"date": criteria.bookDate,
"status": 0
};
if (criteria.isWaitlist == 1 || (secondRoom > 0)) {
obj.status = 1;
obj.isWaitlist = 1;
this.bookingData.criteriaList[i].secondRoom = secondRoom;
isWaitlist = true;
waitlistCount++;
}
dates.push(obj);
}
criteriaCount = criteriaCount - lastDate;
if (isWaitlist && waitlistCount < criteriaCount) { //部分日期waitlist
return {
'status': 1,
'dates': dates
}
} else if (isWaitlist && waitlistCount == criteriaCount) { //全部日期waitlist
return {
'status': 2,
'dates': dates
}
} else { //没waitlist
return {
'status': 0
}
}
},
onApprovalChange(value) {
this.selectedApprover = value;
// 多选:value 为 id 数组,如 ['80002','80001']
if (Array.isArray(value)) {
if (value.length === 0) {
this.selectedApproverName = '';
console.log(this.selectedApproverName);
console.log(this.selectedApprover);
return;
}
const names = value.map((id) => {
const item = this.selectApproverData.find(
(opt) => String(opt.value) === String(id)
);
return item ? (item.approverName || item.label || '') : '';
}).filter(Boolean);
this.selectedApproverName = names.join(', ');
console.log(this.selectedApproverName);
console.log(this.selectedApprover);
return;
}
// 单选:兼容旧逻辑
const selectedApproverItem = this.selectApproverData.find(
(item) => String(item.value) === String(value)
);
this.selectedApproverName = selectedApproverItem
? (selectedApproverItem.approverName || selectedApproverItem.label || '')
: '';
},
onReasonChange(value){
this.selectedReason = value;
},
async submitWaitlist() {
if(this.canSubmit){
this.canSubmit = false;
}else{
return;
uni.$u.toast("Please do not submit repeatedly");
}
uni.showLoading({
title: this.$t("common.loading")
});
try {
if (this.bookingData.bookType == 1) {
for (let i = 0; i < this.bookingData.extendDate.length; i++) {
if (this.bookingData.extendDate[i].status === 1) {
this.bookingData.extendDate[i].remark = this.bookingData.remark;
this.bookingData.extendDate[i].submit = true;
}
}
} else {
for (let i = 0; i < this.bookingData.dateList.length; i++) {
if (this.bookingData.dateList[i].status === 1) {
this.bookingData.dateList[i].remark = this.bookingData.remark;
this.bookingData.dateList[i].submit = true;
}
}
}
this.getWaitlistRemark();
uni.setStorageSync("bookingData", this.bookingData);
// 保存waitlist
var res = null;
if (this.bookingData.bookType == '1') {
res = await editBooking(this.bookingData);
} else {
res = await saveBooking(this.bookingData);
}
// 如果成功
if (res.success === true) {
const resultBookings = res.data;
//this.url = '/booking/bookingDetail/bookingDetail?id='+resultBookings[0].id+'&conf='+resultBookings[0].confirmationNo+'&from=booking';
this.url = "/booking/bookingRecord/bookingRecord?from=booking";
this.buttonStr = this.$t(
"bookingConfirm.backToRecords"); //this.$t("newWailist.viewSubmitedWaitlist");
this.msgStr = this.$t("bookingConfirm.alert1_1") + "<br /><span class='hz-font-xl'>" + this
.playerData.playerId + "</span><br />" + this.$t(
"bookingConfirm.alert2"); //this.$t("newWaitlist.savesuccessful");
this.iconPath = '../../static/images/ico_suc.png';
this.showDirBtn = true;
this.showMsgBox = true;
} else {
var message = res.errorCode != "" ? res.errorCode : res.message;
this.buttonStr = this.$t("common.ok");
this.iconPath = '../../static/images/ico_err.png';
this.msgStr = this.$t("common.saveFail") + ". " + this.$t("common.errorMsg") + ": " +
message; // 具體的錯誤信息,errorCode要做一个mapping,对应一些什么错误
this.url = '';
this.showMsgBox = true;
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][submitWaitlist][ErrorMessage]" + res.message,
"[RequestData]" + JSON.stringify(this.bookingData), "", 1, false);
}
} catch (e) {
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, "save_booking", "",
"[APP][bookingConfirm.vue][submitWaitlist][Catch Exception]" + e.errMsg, request, response,
1, false);
} finally {
this.canSubmit = true;
this.showWaitlistModal = false;
uni.hideLoading();
}
},
submitApproval() {
// 显示审批模态框
this.getApprovalReason();
this.getApprover();
this.showApprovalModal = true;
},
async checkWaitlistBooking() {
uni.showLoading({
title: this.$t("common.loading")
});
try {
let params = {
playerId: this.bookingData.playerId,
userId: this.bookingData.createdBy,
propertyId: this.bookingData.propertyId,
roomId: this.bookingData.roomId,
checkinDate: this.bookingData.checkInDate,
checkoutDate: this.bookingData.checkOutDate,
};
const res = await getWaitlistBooking(params);
if (res.success === true) {
if (res.data.length > 0) {
let criteriaList = this.bookingData.criteriaList;
let duplicateDate = {};
let dateStr = "";
for (let d of res.data) {
let idate = d.checkinDate;
let odate = d.checkoutDate;
let sbdate = criteriaList[0].bookDate;
let ebdate = criteriaList[criteriaList.length - 1].bookDate;
// for(let i=0;i<criteriaList.length;i++){
// let bdate = criteriaList[i].bookDate;
// let isBefore = (dayjs(bdate).isBefore(dayjs(odate), 'day') ||
// dayjs(bdate).isSame(dayjs(odate), 'day') );
// let isAfter = dayjs(bdate).isAfter(dayjs(idate), 'day') ||
// dayjs(bdate).isSame(dayjs(idate), 'day') ;
// let isBetween = isBefore && isAfter;
// if(isBetween) duplicateDate[dayjs(bdate).format("DD-MM-YYYY")] = 1;
// }
let isBefore = dayjs(idate).isBefore(dayjs(sbdate), 'day');
let isAfter = dayjs(odate).isAfter(dayjs(ebdate), 'day');
let startDate = isBefore ? sbdate : idate;
let endDate = isAfter ? ebdate : odate;
var spaceStr = (dateStr == "") ? "" : "</br>";
dateStr += spaceStr + dayjs(startDate).format("DD-MM-YYYY") + " to " + dayjs(endDate)
.format("DD-MM-YYYY");
}
// let keys = Object.keys(duplicateDate);
// let dateStr = keys.join(",")
// dateStr = dayjs(idate).format("DD-MM-YYYY")+" to "+dayjs(odate).format("DD-MM-YYYY")
this.msgStr = this.msgStr += ("</br>" + this.$t("bookingConfirm.duplicateWaitlist") +
"</br>" + dateStr)
}
}
this.showMsgBox = true;
} catch (e) {
this.showMsgBox = true;
} finally {
uni.hideLoading();
}
},
getWaitlistRemark() {
let remarkArr = [];
let roomRemark = this.bookingData.roomRemark;
let otherRemark = this.bookingData.otherRemark;
if (roomRemark != '' && roomRemark != undefined) remarkArr.push(roomRemark);
if (otherRemark != '' && otherRemark != undefined) remarkArr.push(otherRemark);
if (this.showRemark && this.freeRemark != '') remarkArr.push(this.freeRemark);
if (remarkArr.length > 0) {
this.bookingData.remark = remarkArr.join('; ');
} else {
this.bookingData.remark = "";
}
},
async recheckBooking() {
uni.$u.throttle(this.toNext, 200)
if (this.submitLoading) return;
this.submitLoading = true;
uni.showLoading({
title: this.$t("common.loading")
});
try {
let params = {};
params.member = this.playerData
params.userId = this.userData.userId;
const resB = await getBookings(params);
if (this.bookingData.bookType == "1") {
params = {
roomId: this.bookingData.roomId,
propertyId: this.bookingData.propertyId,
userId: this.userData.userId,
playerId: this.playerData.playerId,
coded: this.playerData.codedFlag,
teamId: this.userData.teamStructureId,
blockId: this.bookingData.blockId,
segmentId: this.bookingData.segmentId,
};
} else {
params = {
roomId: this.bookingData.roomId,
propertyId: this.bookingData.propertyId,
coded: this.playerData.codedFlag,
userId: this.userData.userId,
userName: this.userData.userName,
playerId: this.playerData.playerId,
teamId: this.userData.teamStructureId,
bedTypeId: this.bookingData.bedTypeId,
bookingTypeId: this.bookingData.bookingTypeId,
segmentId: this.bookingData.segmentId,
};
}
let criteriaData = await getCriterias(params);
let criteria = criteriaData.data;
let bookCriteria = this.bookingData.criteriaList;
this.bookingData.criteriaList = [];
for (let i = 0; i < bookCriteria.length; i++) {
let date = bookCriteria[i].bookDate;
if (criteria[date] !== undefined && criteria[date] != null) {
this.bookingData.criteriaList.push(criteria[date]);
}
if (criteria[date] == undefined && i == (bookCriteria.length - 1)) {
this.bookingData.criteriaList.push({
'bookDate': date,
'available': 0,
});
}
}
this.confirmBooking();
} catch (e) {
console.log(e);
// write log
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, "save_booking", "",
"[APP][bookingConfirm.vue][getDataByPage][Catch Exception]" + e.errMsg, request, response,
1, false);
} finally {
this.submitLoading = false;
uni.hideLoading();
}
},
// 界面方法
getCurrentDate() {
this.bookingData.createdOn = this.bookingData.createdAt != null ? this.bookingData.createdAt :
dayjs().format("YYYY-MM-DD");
},
navToDetail(url) {
if (url != null && url !== undefined && url !== '') {
this.navTo(url, 0, false);
} else {
this.showMsgBox = false;
}
},
onRoomCheckboxChange(name) {
if (this.bookingData && (this.$set ? !Object.prototype.hasOwnProperty.call(this.bookingData, 'roomRemark') : this.bookingData.roomRemark === undefined)) {
this.$set ? this.$set(this.bookingData, 'roomRemark', '') : this.bookingData.roomRemark = '';
}
const current = this.bookingData ? this.bookingData.roomRemark : '';
this.bookingData.roomRemark = current === name ? "" : name;
},
changeOtherRemark(e) {
if (e) {
let str = '';
let show = false;
for (let i = 0; i < e.length; i++) {
if (e[i] == 'Remark') {
show = true;
} else {
str = e[i];
}
}
this.showRemark = show;
this.bookingData.otherRemark = str;
}
},
handleRemarkChange(e) {
this.approvalForm.approvalRoutingRemark = e;
if (e !== 'Remark') {
this.approvalForm.remarkText = '';
}
},
toggleDropdown(type) {
if (this.openDropdown === type) {
this.openDropdown = null;
} else {
this.openDropdown = type;
}
},
async submitApprovalRequest() {
if(this.canSubmit){
this.canSubmit = false;
}else{
return;
uni.$u.toast("Please do not submit repeatedly");
}
// 验证是否选择了请求原因和审批人
if (!this.selectedReason) {
uni.$u.toast("Please select Request Reason");
return;
}
const noApprover = Array.isArray(this.selectedApprover)
? this.selectedApprover.length === 0
: !this.selectedApprover;
if (noApprover) {
uni.$u.toast("Please select Approver");
return;
}
uni.showLoading({
title: this.$t("common.loading")
});
this.showApprovalModal = false;
try {
if (this.bookingData.bookType == 1) {
for (let i = 0; i < this.bookingData.extendDate.length; i++) {
if (this.bookingData.extendDate[i].status === 1) {
this.bookingData.extendDate[i].remark = this.bookingData.remark;
this.bookingData.extendDate[i].submit = true;
}
}
} else {
for (let i = 0; i < this.bookingData.dateList.length; i++) {
if (this.bookingData.dateList[i].status === 1) {
this.bookingData.dateList[i].remark = this.bookingData.remark;
this.bookingData.dateList[i].submit = true;
}
}
}
this.bookingData.requestReasonId = this.selectedReason;
// 多选 Approver 为数组,入库时用逗号拼接,避免出现 JSON/[] 被写入 DB
this.bookingData.routerToApproverId = Array.isArray(this.selectedApprover)
? this.selectedApprover.map(String).join(',')
: this.selectedApprover;
this.bookingData.routerToApproverName = this.selectedApproverName;
this.bookingData.isApproval = 1;
this.bookingData.routingReason = this.routingResaon;
this.getWaitlistRemark();
uni.setStorageSync("bookingData", this.bookingData);
// 保存waitlist
let res = '';
if(this.bookingData.bookType == '1'){
res = await editBooking(this.bookingData);
}else{
res = await saveBooking(this.bookingData);
}
// 如果成功
if (res.success === true) {
console.log(1111);
const resultBookings = res.data;
//this.url = '/booking/bookingDetail/bookingDetail?id='+resultBookings[0].id+'&conf='+resultBookings[0].confirmationNo+'&from=booking';
this.url = "/booking/bookingRecord/bookingRecord?from=booking";
this.buttonStr = this.$t(
"bookingConfirm.backToRecords"); //this.$t("newWailist.viewSubmitedWaitlist");
this.msgStr = this.$t("bookingConfirm.alert1_2") + "<br /><span class='hz-font-xl'>" + this
.playerData.playerId + "</span><br />" + this.$t(
"bookingConfirm.alert2"); //this.$t("newWaitlist.savesuccessful");
this.iconPath = '../../static/images/ico_suc.png';
this.showDirBtn = true;
this.showMsgBox = true;
} else {
var message = res.errorCode != "" ? res.errorCode : res.message;
this.buttonStr = this.$t("common.ok");
this.iconPath = '../../static/images/ico_err.png';
this.msgStr = this.$t("common.saveFail") + ". " + this.$t("common.errorMsg") + ": " +
message; // 具體的錯誤信息,errorCode要做一个mapping,对应一些什么错误
this.url = '';
this.showMsgBox = true;
await this.writeLog(this.userData.userId, "save_booking", "",
"[APP][bookingConfirm.vue][submitApprovalRequest][ErrorMessage]" + res.message,
"[RequestData]" + JSON.stringify(this.bookingData), "", 1, false);
}
} catch (e) {
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, "save_booking", "",
"[APP][bookingConfirm.vue][submitWaitlist][Catch Exception]" + e.errMsg, request, response,
1, false);
} finally {
this.canSubmit = true;
uni.hideLoading();
}
},
initUI() {
this.deviceData = uni.getStorageSync("deviceData");
this.title = this.$t("bookingConfirm.title");
this.windowWidth = this.deviceData.windowWidth - 70;
// 判斷iphone下方安全區域
const area = this.deviceData.saveArea;
if (area) {
this.footFuncHei = 160;
}
},
showWaitlistPop() {
this.showWaitlistModal = true;
},
async getApprovalReason(){
try {
let params = {};
const res = await getApprovalReason(params);
if (res.success === true) {
// 转换数据格式为 lu-data-select 需要的格式
this.selectReasonData = res.data.map(item => ({
label: item.code,
value: item.id,
...item
}));
}
} catch (e) {
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, "bookingConfirm", "",
"[APP][bookingConfirm.vue][getApprovalReason][Catch Exception]" + e.errMsg, request, response, 1,
false);
}
},
async getApprover(){
try {
if(this.bookingData!==null && this.bookingData !=undefined){
let params = {playerId:this.bookingData.playerId,bookingType:this.bookingData.bookingTypeName,
propertyName:this.bookingData.propertyName,roomCategory:this.bookingData.room,checkInDate:this.bookingData.checkInDate,checkOutDate:this.bookingData.checkOutDate};
const res = await getApprover(params);
if (res.success === true) {
const record = res.data && Array.isArray(res.data.records)
? res.data.records[0]
: null;
const approverList = record && Array.isArray(record.approverList)
? record.approverList
: [];
this.selectApproverData = approverList.map(item => ({
label: item.employeeName,
value: item.employeeId,
...item
}));
this.routingResaon = record ? (record.approvalRoutingMessage || '') : '';
console.log(this.routingResaon);
}
}
} catch (e) {
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, "bookingConfirm", "",
"[APP][bookingConfirm.vue][getApprovalReason][Catch Exception]" + e.errMsg, request, response, 1,
false);
}
},
closeApprovalPop(){
this.showApprovalModal = false;
console.log(111);
}
},
computed: {
getStatusColor() {
return function(booking) {
let operaStatus = null;
if (booking == null) {
return '';
}
if (booking.lastOperaStatus != null) {
operaStatus = booking.lastOperaStatus;
}
let approveStatus = null;
if (booking.approveStatus != null) {
approveStatus = booking.approveStatus;
}
// Opera和Approve Status都不为空的情况
if ((operaStatus != null && operaStatus != undefined) || (approveStatus != null && approveStatus !=
undefined)) {
if (approveStatus.toUpperCase() === 'PN') {
return 'hz-status-pending';
} else if (approveStatus.toUpperCase() === 'N') {
if (operaStatus !== null && operaStatus !== undefined && operaStatus !== '' &&
operaStatus !== 'null') {
if (operaStatus.toUpperCase() === 'DUE_IN') {
return 'hz-status-duein';
} else if (operaStatus.toUpperCase() === 'CHECKED_IN') {
return 'hz-status-checkedin';
} else if (operaStatus.toUpperCase() === 'CHECKED_OUT') {
return 'hz-status-waitlist';
} else if (operaStatus.toUpperCase() === 'DUE_OUT') {
return 'hz-status-dueout';
} else if (operaStatus.toUpperCase() === 'RESERVED') {
return 'hz-status-reserved';
} else {
return '';
}
}
} else if (approveStatus.toUpperCase() === 'W') {
return 'hz-status-waitlist';
} else {
if (operaStatus == null) return '';
if (operaStatus.toUpperCase() === 'DUE_IN') {
return 'hz-status-duein';
} else if (operaStatus.toUpperCase() === 'CHECKED_IN') {
return 'hz-status-checkedin';
} else if (operaStatus.toUpperCase() === 'CHECKED_OUT') {
return 'hz-status-waitlist';
} else if (operaStatus.toUpperCase() === 'DUE_OUT') {
return 'hz-status-dueout';
} else if (operaStatus.toUpperCase() === 'RESERVED') {
return 'hz-status-reserved';
} else {
return '';
}
}
}
// Opera status为空,Approve Status不为空的情况
else if ((operaStatus == null || operaStatus == undefined) && (approveStatus != null &&
approveStatus != undefined)) {
if (approveStatus.toUpperCase() === 'PN') {
return 'hz-status-font-pending';
} else if (approveStatus.toUpperCase() === 'W') {
return 'hz-status-font-waitlist';
} else {
return '';
}
}
}
},
getStatusTextColor() {
return function(booking) {
let operaStatus = null;
if (booking == null) {
return '';
}
if (booking.lastOperaStatus != null) {
operaStatus = booking.lastOperaStatus;
}
let approveStatus = null;
if (booking.approveStatus != null) {
approveStatus = booking.approveStatus;
}
// Opera和Approve Status都不为空的情况
if ((operaStatus != null && operaStatus != undefined) || (approveStatus != null && approveStatus !=
undefined)) {
if (approveStatus.toUpperCase() === 'PN') {
return 'hz-status-font-pending';
} else if (approveStatus.toUpperCase() === 'N') {
if (operaStatus !== null && operaStatus !== undefined && operaStatus !== '' &&
operaStatus !== 'null') {
if (operaStatus.toUpperCase() === 'DUE_IN') {
return 'hz-status-font-duein';
} else if (operaStatus.toUpperCase() === 'CHECKED_IN') {
return 'hz-status-font-checkedin';
} else if (operaStatus.toUpperCase() === 'CHECKED_OUT') {
return 'hz-status-font-waitlist';
} else if (operaStatus.toUpperCase() === 'DUE_OUT') {
return 'hz-status-font-dueout';
} else if (operaStatus.toUpperCase() === 'RESERVED') {
return 'hz-status-font-reserved';
} else {
return '';
}
}
} else if (approveStatus.toUpperCase() === 'W') {
return 'hz-status-font-waitlist';
} else {
if (operaStatus == null) return '';
if (operaStatus.toUpperCase() === 'DUE_IN') {
return 'hz-status-font-duein';
} else if (operaStatus.toUpperCase() === 'CHECKED_IN') {
return 'hz-status-font-checkedin';
} else if (operaStatus.toUpperCase() === 'CHECKED_OUT') {
return 'hz-status-font-waitlist';
} else if (operaStatus.toUpperCase() === 'DUE_OUT') {
return 'hz-status-font-dueout';
} else if (operaStatus.toUpperCase() === 'RESERVED') {
return 'hz-status-font-reserved';
} else {
return '';
}
}
}
// Opera status为空,Approve Status不为空的情况
else if ((operaStatus == null || operaStatus == undefined) && (approveStatus != null &&
approveStatus != undefined)) {
if (approveStatus.toUpperCase() === 'PN') {
return 'hz-status-font-pending';
} else if (approveStatus.toUpperCase() === 'W') {
return 'hz-status-font-waitlist';
} else {
return '';
}
}
}
},
getStatusText() {
return function(booking) {
let operaStatus = null;
if (booking == null) {
return;
}
if (booking.lastOperaStatus != null) {
operaStatus = booking.lastOperaStatus;
}
let approveStatus = null;
if (booking.approveStatus != null) {
approveStatus = booking.approveStatus;
}
if ((operaStatus != null && operaStatus != undefined) || (approveStatus != null && approveStatus !=
undefined)) {
if (approveStatus.toUpperCase() === 'PN' || approveStatus.toUpperCase() === 'W') {
if (approveStatus !== null && approveStatus !== undefined && approveStatus !== '' &&
approveStatus !== 'null')
return mapApproveStatus(approveStatus.toUpperCase());
} else if (approveStatus.toUpperCase() === 'N') {
if (operaStatus !== null && operaStatus !== undefined && operaStatus !== '' &&
operaStatus !== 'null')
return mapOperaStatus(operaStatus.toUpperCase());
}
} else if ((operaStatus == null || operaStatus == undefined) && (approveStatus != null &&
approveStatus != undefined)) {
return mapApproveStatus(approveStatus.toUpperCase());
}
}
},
getSpecial() {
return function(specialName, bedTypeName) {
let str = ''
if (bedTypeName != null && bedTypeName != '') {
str = bedTypeName;
}
if (specialName != null && specialName != '') {
if (str == '') {
str = specialName;
} else {
str = str + ", " + specialName;
}
}
return str;
}
},
dateFormat() {
return function(date) {
if (date != undefined) {
let weekNum = dayjs(date).day();
let week = '';
switch (weekNum) {
case 1:
week = 'Mon'
break;
case 2:
week = 'Tue';
break;
case 3:
week = 'Wed';
break;
case 4:
week = 'Thu';
break;
case 5:
week = 'Fri';
break;
case 6:
week = 'Sat';
break;
case 0:
week = 'Sun';
break;
}
return '(' + week + ') ' + dayjs(date).format("YYYY-MM-DD");
}
}
},
getSharer() {
return function(playerId, name) {
let id = null;
if (playerId !== null && playerId !== undefined && playerId !== '' && playerId !== 'null') {
id = playerId;
}
let na = null;
if (name !== null && name !== undefined && name !== '' && name !== 'null') {
na = name;
}
let res = '';
if (id != null) {
res = id;
}
if (na != null) {
if (res !== '') {
res = res + ' (' + na + ')';
} else {
res = na;
}
}
return res;
}
},
getNight() {
return function(num) {
if (num !== null && num !== undefined && num !== 'null') {
if (num > 1) {
return num + " " + this.$t("common.nights");
} else {
return num + " " + this.$t("common.night");
}
} else
return '';
}
},
getRoom() {
return function(num) {
if (num !== null && num !== undefined && num !== 'null') {
if (num > 1) {
return num + " " + this.$t("common.rooms");
} else {
return num + " " + this.$t("common.room");
}
} else
return '';
}
}
}
}
</script>
<style lang="scss" scoped>
.u-border {
border-width: 0.5px !important;
border-color: #ccc !important;
border-style: solid;
}
.u-border-bottom {
border-bottom-width: 1px !important;
border-color: #333333 !important;
border-bottom-style: solid;
}
/* 下拉框样式 */
.dropdown-container {
position: relative;
}
.dropdown-options {
max-height: 0;
overflow: hidden;
transition: all 0.3s ease-in-out;
opacity: 0;
transform: translateY(-10px);
}
.dropdown-options.show {
max-height: 200px;
opacity: 1;
transform: translateY(0);
}
.rotate {
transform: translateY(-50%) rotate(180deg) !important;
transition: transform 0.3s ease-in-out;
}
.dropdown-option:hover {
background-color: #f5f7fa;
}
.dropdown-option:last-child {
border-bottom: none;
}
.approvalHeader {
font-size: 25px;
font-weight: bold;
text-align: center;
display: block;
color: #C39A4B;
margin-bottom: 15px;
}
.confirmButton {
margin-bottom: 9px;
}
.backBtn {
background-color: white;
border-color: #C39A4B;
border-width: 2px;
border-style: solid;
width: 100%;
margin-top: 6px;
height: 44px;
line-height: 44px;
border-radius: 22px;
}
</style>