928 lines
32 KiB
Vue
928 lines
32 KiB
Vue
<template>
|
||
<view>
|
||
<view class="hz-page">
|
||
<u-navbar
|
||
:safeAreaInsetTop="true"
|
||
:placeholder="true"
|
||
:title="title"
|
||
:fixed="true"
|
||
:autoBack="false"
|
||
leftIconColor="#000000"
|
||
titleStyle="font-weight:bold;"
|
||
@leftClick="back()"
|
||
>
|
||
<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="navToPlayerRoomCalendar" src="../../static/images/calendar-line.png" class="hz-nav-btn"></image>
|
||
</view>
|
||
</view>
|
||
</u-navbar>
|
||
|
||
<!-- booking record page -->
|
||
<view class="hz-spacing hz-bg-white mt-[20]">
|
||
<view class="hz-card-profile mb-[40]">
|
||
<view class="hz-flex-row">
|
||
<view class="hz-w-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 class="hz-w-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 class="hz-w-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>
|
||
<view v-for="(record,index) in displayRecordList" :key="`${record.recordType}-${record.id || record.confirmationNo || index}`">
|
||
<view @click="openRecordDetail(record)" :class="getRecordCardClass(record)" class="hz-card-booking hz-record-card hz-pd-30 hz-font-bold hz-font-sm">
|
||
<view class="hz-flex-row hz-booking-type-row">
|
||
<view class="hz-booking-type-wrap">
|
||
<image :src="getBookingTypeIcon(record)" class="hz-booking-type-icon"></image>
|
||
<view class="hz-font-md">{{ getBookingTypeLabel(record) }}</view>
|
||
</view>
|
||
<view class="hz-font-md hz-text-right" :class="getRecordStatusClass(record)">{{getRecordStatusText(record)}}</view>
|
||
</view>
|
||
<view v-if="isHotelRecord(record)">
|
||
<view class="hz-flex-row hz-row-gap">
|
||
<view class="hz-w-50">
|
||
<view class="hz-font-md">{{$t("common.confirmationNo")}}: {{ getConfirmationNo(record)}}</view>
|
||
</view>
|
||
<view class="hz-w-50">
|
||
<view class="hz-font-md hz-text-right">{{ record.propertyName }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="hz-flex-row hz-row-gap">
|
||
<view class="hz-w-55">
|
||
<view class="hz-font-md">{{$t("common.checkInDate")}}: {{ record.checkinDate }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="hz-flex-row hz-row-gap">
|
||
<view class="hz-w-55">
|
||
<view class="hz-font-md">{{$t("common.checkOutDate")}}: {{ record.checkoutDate }}</view>
|
||
</view>
|
||
<view class="hz-flex-row hz-sharer-wrap" v-if="canShowSharer(record)">
|
||
<view v-if="hasSharer(record)" class="hz-btn-sharer hz-font-min hz-sharer-tag">{{$t("bookingRecord.sharer").toUpperCase()}}</view>
|
||
</view>
|
||
</view>
|
||
<!-- <view class="hz-flex-row hz-row-gap">
|
||
<view class="hz-w-55 hz-font-md" v-show="record.eta!==null && record.eta!=='00:00:00'">{{$t("common.etaTime")}}: {{formatEtaToHHmm(record.eta)}}</view>
|
||
<view v-if="record.miscCharge != null" class="hz-flex-row hz-sharer-wrap">
|
||
<view>
|
||
<view class="hz-font-md">{{$t("common.misCharge")}}: {{ formatWithThousands(record.miscCharge) }}</view>
|
||
</view>
|
||
</view>
|
||
</view> -->
|
||
<view class="hz-flex-row" style="margin-top:6px;">
|
||
<view v-show="record.eta!==null && record.eta!=='00:00:00'" class="hz-font-md">{{$t("common.etaTime")}}: {{formatEtaToHHmm(record.eta)}}</view>
|
||
<span v-show="record.eta!==null && record.eta!=='00:00:00' && record.miscCharge!==null" class="hz-font-md" style="padding:0 6px;">|</span>
|
||
<view v-show="record.miscCharge!==null" class="hz-font-md">{{$t("common.misCharge")}}: {{formatWithThousands(record.miscCharge)}}</view>
|
||
</view>
|
||
</view>
|
||
<!-- 不然就是 limo 的 booking -->
|
||
<view v-else>
|
||
<view class="hz-flex-row hz-row-gap">
|
||
<view class="hz-w-100">
|
||
<view class="hz-font-md">Conf # : {{ getConfirmationNo(record) }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="hz-flex-row hz-row-gap">
|
||
<view class="hz-w-100">
|
||
<view class="hz-font-md">{{$t("limoBookingRecord.pickupDatetime")}}: {{ record.pickupDatetime }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="hz-flex-row hz-row-gap">
|
||
<view class="hz-w-100">
|
||
<view class="hz-font-md">{{$t("limoBookingRecord.pickup")}}: {{ record.pickup }}</view>
|
||
</view>
|
||
</view>
|
||
<view v-if="record.extraDropoff && record.extraDropoff.length" class="hz-flex-row hz-row-gap">
|
||
<view class="hz-w-100">
|
||
<view class="hz-font-md">{{$t("limoBookingRecord.extraDropoff")}}:</view>
|
||
<view class="hz-font-md" v-for="(dropoffPoint,index) in record.extraDropoff" :key="index">
|
||
#{{index + 1}}:{{dropoffPoint}}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="hz-flex-row hz-row-gap hz-flex-vertical-mid">
|
||
<view class="hz-w-100 hz-limo-dropoff-wrap">
|
||
<view class="hz-font-md">
|
||
{{$t("limoBookingRecord.dropoff")}}: {{record.dropoff}}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- <u-empty
|
||
v-if="isDisplayEmpty"
|
||
mode="search"
|
||
:text="dataNotFoundStr"
|
||
>
|
||
</u-empty> -->
|
||
</view>
|
||
<u-tabbar
|
||
:fixed="true"
|
||
:placeholder="true"
|
||
:safeAreaInsetBottom="true"
|
||
customStyle="z-index:100;height:58px;"
|
||
>
|
||
<view v-if="userData.canNewBooking" class="book hz-flex-row hz-spacing hz-book-btn-wrap" :class="{'hz-book-btn-wrap--single': hasSingleBookingPermission}">
|
||
<view class="hz-btn hz-font-color-white hz-font-sm hz-font-bold hz-text-center" @click="navToNewBooking()">
|
||
{{$t("bookingRecord.newsBooking")}}
|
||
</view>
|
||
</view>
|
||
<view v-if="userData.canViewLimo" class="book hz-flex-row hz-spacing hz-book-btn-wrap" :class="{'hz-book-btn-wrap--single': hasSingleBookingPermission}">
|
||
<view class="hz-btn hz-font-color-white hz-font-sm hz-font-bold hz-text-center" @click="navToNewLimo()">
|
||
{{$t("bookingRecord.newLimo")}}
|
||
</view>
|
||
</view>
|
||
</u-tabbar>
|
||
<u-modal :content="msgStr" :show="showMsg" :confirmText="yesText" :showCancelButton="false" closeOnClickOverlay @confirm="showMsg=false" confirmColor="#C39A4B" @close="showMsg=false"></u-modal>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {playerLookup} from '../../api/mgmApi.js'
|
||
import {mapOperaStatus,mapApproveStatus} from '../../common/mapping.js'
|
||
import {getBookings, getLimoBookings} from '../../api/bookingApi.js';
|
||
import dayjs from '../../uni_modules/uview-ui/libs/util/dayjs.js';
|
||
export default {
|
||
data() {
|
||
return {
|
||
//数据变量
|
||
playerData:null,
|
||
userData:null,
|
||
bookingList:[],
|
||
dataNotFoundStr:this.$t("common.dataNotFound"),
|
||
// 界面变量
|
||
from:'',
|
||
title:'',
|
||
showMsg:false,
|
||
msgStr:this.$t("bookingRecord.operaProfile"),
|
||
yesText:this.$t("common.ok"),
|
||
currentTask:null,
|
||
getDataByPageRequestId:0,
|
||
limoBookingList:[
|
||
]
|
||
}
|
||
},
|
||
onLoad(opt) {
|
||
// 初始化界面
|
||
this.initUI();
|
||
this.playerData = uni.getStorageSync("playerData");
|
||
this.userData = uni.getStorageSync("userData");
|
||
if(opt.from!==undefined && opt.from!='') this.from = opt.from;
|
||
// this.getDataByPage();
|
||
},
|
||
onShow() {
|
||
this.$i18n.locale = uni.getLocale();
|
||
// 检查是否登录
|
||
this.isLogin();
|
||
// 拿localstorage中的playerData
|
||
//修改MiscCharge后 返回页面自动刷新
|
||
// this.refreshHotelBooking();
|
||
|
||
this.getDataByPage();
|
||
},
|
||
// 下拉刷新(页面生命周期,需与 onLoad/onShow 同级)
|
||
onPullDownRefresh() {
|
||
this.pullDownRefresh();
|
||
},
|
||
methods: {
|
||
updateHotelBookingList(res){
|
||
if(Array.isArray(res) && res.length > 0){
|
||
this.bookingList = res;
|
||
}else{
|
||
this.bookingList = [];
|
||
}
|
||
},
|
||
updateLimoBookingList(res) {
|
||
if(this.userData.canViewLimo==false) return;
|
||
if (Array.isArray(res) && res.length > 0) {
|
||
let temp = res.map(item => {
|
||
const pickUpDatetime = item.pickUpDatetime || item.pickUpDateTime || item.pickupDatetime || '';
|
||
return {
|
||
id: item.id,
|
||
recordType: 'limo',
|
||
confirmationNo: item.confirmationNo,
|
||
status: item.bookingStatus,
|
||
pickUpDatetime,
|
||
pickupDatetime: this.formatDate(pickUpDatetime, 'YYYY-MM-DD HH:mm'),
|
||
pickup: item.pickUpPoint,
|
||
dropoff: item.dropOffPoint,
|
||
extraDropoff:this.getExtraDropOff(item.extraDropOffPoint)
|
||
// extraDropoff:item.extraDropOffPoint.split(";")
|
||
}
|
||
});
|
||
|
||
this.limoBookingList = temp;
|
||
} else {
|
||
this.limoBookingList = [];
|
||
}
|
||
},
|
||
openBookingPage(path){
|
||
uni.showLoading({
|
||
title: this.$t("common.loading")
|
||
});
|
||
this.navTo(path,0,false);
|
||
uni.hideLoading();
|
||
},
|
||
|
||
// 數據方法
|
||
async getDataByPage(){
|
||
if(this.userData.canViewBooking==false) return;
|
||
const previousTask = this.currentTask;
|
||
const requestId = ++this.getDataByPageRequestId;
|
||
if(previousTask){
|
||
try{
|
||
previousTask.abort();
|
||
}catch(err){
|
||
}
|
||
}
|
||
|
||
// 一次页面加载会同时发起 Hotel 和 Limo 请求,统一保存并取消它们。
|
||
const requestTasks = [];
|
||
const requestController = {
|
||
abort: () => {
|
||
requestTasks.forEach(task => {
|
||
if(task && typeof task.abort === 'function'){
|
||
try{
|
||
task.abort();
|
||
}catch(err){
|
||
}
|
||
}
|
||
});
|
||
}
|
||
};
|
||
const requestConfig = {
|
||
getTask: task => {
|
||
if(requestId === this.getDataByPageRequestId){
|
||
requestTasks.push(task);
|
||
}else if(task && typeof task.abort === 'function'){
|
||
task.abort();
|
||
}
|
||
}
|
||
};
|
||
this.currentTask = requestController;
|
||
let params = {};
|
||
uni.showLoading({
|
||
title: this.$t("common.loading")
|
||
});
|
||
try{
|
||
if(this.playerData.nameIds.length==0){
|
||
await this.getProfileByPlayerId(requestId, requestConfig)
|
||
}else{
|
||
params.member = this.playerData;
|
||
params.userId = this.userData.userId;
|
||
params.profileId = this.playerData.profileId;
|
||
const limoPromise = getLimoBookings(params, requestConfig).catch((e) => {
|
||
return null;
|
||
});
|
||
const hotelPromise = getBookings(params, requestConfig).catch((e) => {
|
||
return null;
|
||
});
|
||
const [resLimo, resHotel] = await Promise.all([limoPromise, hotelPromise]);
|
||
if(requestId !== this.getDataByPageRequestId) return;
|
||
if (resLimo) {
|
||
this.updateLimoBookingList(resLimo);
|
||
}
|
||
if (resHotel) {
|
||
this.updateHotelBookingList(resHotel);
|
||
}
|
||
}
|
||
}catch(e){
|
||
if(requestId !== this.getDataByPageRequestId || (e && e.errMsg!==undefined && e.errMsg.includes("abort"))){
|
||
return;
|
||
}
|
||
// console.log(e);
|
||
// write log
|
||
uni.$u.toast(e.errMsg,5000);
|
||
await this.writeLog(this.userData.userId,"save_booking","","[APP][bookingDetail.vue][getDataByPage][Catch Exception]"+e.errMsg,"[RequestData]" +JSON.stringify(params),"",1,false);
|
||
}finally{
|
||
if(requestId === this.getDataByPageRequestId){
|
||
if(this.currentTask === requestController){
|
||
this.currentTask = null;
|
||
}
|
||
uni.hideLoading();
|
||
}
|
||
}
|
||
},
|
||
async refreshHotelBooking(){
|
||
if(this.userData.canViewBooking==false) return;
|
||
let params = {};
|
||
uni.showLoading({
|
||
title: this.$t("common.loading")
|
||
});
|
||
try{
|
||
if(this.playerData.nameIds.length==0){
|
||
await this.getProfileByPlayerId()
|
||
}else{
|
||
params.member = this.playerData;
|
||
params.userId = this.userData.userId;
|
||
params.profileId = this.playerData.profileId;
|
||
const resHotel = await getBookings(params);
|
||
this.updateHotelBookingList(resHotel);
|
||
}
|
||
}catch(e){
|
||
console.log(e);
|
||
// write log
|
||
uni.$u.toast(e.errMsg,5000);
|
||
await this.writeLog(this.userData.userId,"save_booking","","[APP][bookingDetail.vue][getDataByPage][Catch Exception]"+e.errMsg,"[RequestData]" +JSON.stringify(params),"",1,false);
|
||
}finally{
|
||
uni.hideLoading();
|
||
}
|
||
},
|
||
pullDownRefresh(){
|
||
try{
|
||
this.getDataByPage('refresh');
|
||
}finally{
|
||
uni.stopPullDownRefresh();
|
||
}
|
||
},
|
||
// 界面方法
|
||
isHotelRecord(record){
|
||
return record.recordType === 'hotel';
|
||
},
|
||
getRecordCardClass(record){
|
||
return this.getRecordColor(record);
|
||
},
|
||
openRecordDetail(record){
|
||
if(this.isHotelRecord(record)){
|
||
this.navToDetail(record);
|
||
}else{
|
||
this.navToLimoDetail(record);
|
||
}
|
||
},
|
||
getBookingTypeIcon(record){
|
||
if(this.isHotelRecord(record)){
|
||
return '../../static/images/ico_hotel_active.png';
|
||
}
|
||
return '../../static/icon/tabbar/taxi-fill.png';
|
||
},
|
||
getBookingTypeLabel(record){
|
||
let bookingType = this.$t("limoBookingRecord.bookingType");
|
||
if(this.isHotelRecord(record)){
|
||
return bookingType+': Hotel';
|
||
}
|
||
return bookingType+': Limo';
|
||
},
|
||
getRecordStatusText(record){
|
||
if(this.isHotelRecord(record)){
|
||
return this.getStatusText(record);
|
||
}else{
|
||
return record.status.replace("_"," ");
|
||
}
|
||
},
|
||
getRecordStatusClass(record){
|
||
return this.getStatusTextColor(record);
|
||
},
|
||
canShowSharer(record){
|
||
return this.userData && this.userData.canNewBooking && record.propertyCategory!='OTHER';
|
||
},
|
||
hasSharer(record){
|
||
return (record.sharer!==null && record.sharer!=='[]')||record.isShare;
|
||
},
|
||
hasEta(record){
|
||
return record.eta!==undefined && record.eta!==null && record.eta!=='';
|
||
},
|
||
getDropOffPointLines(dropOffPoint){
|
||
if(dropOffPoint === null || dropOffPoint === undefined || dropOffPoint === '') return [''];
|
||
return String(dropOffPoint).split(/[;;]/).map(item => item.trim()).filter(item => item !== '');
|
||
},
|
||
getExtraDropOffPoint(dropOffPoint){
|
||
if(dropOffPoint === null || dropOffPoint === undefined || dropOffPoint === '') return [''];
|
||
|
||
return String(dropOffPoint).split(/[;;]/).map(item => item.trim()).filter(item => item !== '');
|
||
},
|
||
back(){
|
||
if(this.from==='booking'){
|
||
this.navTo("/pages/findPlayer/findPlayer",1,false);
|
||
}else{
|
||
this.navBack();
|
||
}
|
||
},
|
||
navToDetail(booking){
|
||
this.navTo('/booking/bookingDetail/bookingDetail?id='+booking.id+"&conf="+booking.confirmationNo+"&from=list",0,false)
|
||
},
|
||
navToLimoDetail(limoBooking){
|
||
this.navTo('/limo/bookingDetail/bookingDetail?id=' + limoBooking.id +'&conf='+limoBooking.confirmationNo+"&from=list",0,false)
|
||
},
|
||
navToPlayerRoomCalendar(){
|
||
this.navTo('/booking/playerRoomCalendar/playerRoomCalendar',0,false)
|
||
},
|
||
// ETA 统一显示 HH:mm(兼容 HH:mm:ss / HH:mm)
|
||
formatEtaToHHmm(eta) {
|
||
if (eta === null || eta === undefined || eta === '') return '';
|
||
const str = String(eta).trim();
|
||
const m = str.match(/^(\d{1,2}):(\d{2})(?::\d{2})?$/);
|
||
if (m) {
|
||
const hh = m[1].padStart(2, '0');
|
||
return `${hh}:${m[2]}`;
|
||
}
|
||
// 兜底:如果有冒号,取前两段
|
||
const parts = str.split(':');
|
||
if (parts.length >= 2) {
|
||
return `${parts[0].padStart(2, '0')}:${parts[1]}`;
|
||
}
|
||
return str;
|
||
},
|
||
formatWithThousands(value) {
|
||
if (value === null || value === undefined || value === '') return '-';
|
||
const str = String(value).trim();
|
||
if (/^-?\d{1,3}(,\d{3})*(\.\d+)?$/.test(str)) return str;
|
||
const normalized = str.replace(/,/g, '');
|
||
if (/^-?\d+(\.\d+)?$/.test(normalized)) {
|
||
const n = Number(normalized);
|
||
return n.toLocaleString('en-US');
|
||
}
|
||
return value;
|
||
},
|
||
initUI() {
|
||
this.deviceData = uni.getStorageSync("deviceData");
|
||
this.title = this.$t("bookingRecord.title");
|
||
},
|
||
navToNewBooking(){
|
||
this.openBookingPage('/booking/newBooking/newBooking');
|
||
},
|
||
navToNewLimo(){
|
||
this.openBookingPage('/limo/newLimo/newLimo?from=bookingRecord');
|
||
},
|
||
async getProfileByPlayerId(requestId = this.getDataByPageRequestId, requestConfig = {}){
|
||
try{
|
||
const params = {playerId:this.playerData.playerId,userId:this.userData.userId};
|
||
const res = await playerLookup(params, requestConfig);
|
||
if(requestId !== this.getDataByPageRequestId) return;
|
||
if(res.success == true){
|
||
const player = res.data;
|
||
if(player !== null){
|
||
if(player.codedFlag==1){
|
||
uni.setStorageSync("playerData",player);
|
||
this.playerData = uni.getStorageSync("playerData");
|
||
const bookingParams = {
|
||
member: player,
|
||
userId: this.userData.userId
|
||
};
|
||
const [resHotel, resLimo] = await Promise.all([
|
||
getBookings(bookingParams, requestConfig),
|
||
getLimoBookings(bookingParams, requestConfig)
|
||
]);
|
||
if(requestId !== this.getDataByPageRequestId) return;
|
||
this.updateHotelBookingList(resHotel);
|
||
this.updateLimoBookingList(resLimo);
|
||
}
|
||
}
|
||
}
|
||
}catch(e){
|
||
if(requestId !== this.getDataByPageRequestId || (e && e.errMsg!==undefined && e.errMsg.includes("abort"))){
|
||
return;
|
||
}
|
||
console.error(e);
|
||
var request = e.config!=undefined?JSON.stringify(e.config):"";
|
||
var response = e.data!=undefined?JSON.stringify(e.data):"";
|
||
await this.writeLog(this.userData.userId,"find_player","","[APP][findPlayer.vue][getProfileByPlayerId][Catch Exception]"+e.errMsg,request,response,1,false);
|
||
}
|
||
},
|
||
formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
|
||
const d = new Date(date);
|
||
if (Number.isNaN(d.getTime())) {
|
||
return '';
|
||
}
|
||
|
||
const map = {
|
||
YYYY: d.getFullYear(),
|
||
MM: String(d.getMonth() + 1).padStart(2, '0'),
|
||
DD: String(d.getDate()).padStart(2, '0'),
|
||
HH: String(d.getHours()).padStart(2, '0'),
|
||
mm: String(d.getMinutes()).padStart(2, '0'),
|
||
ss: String(d.getSeconds()).padStart(2, '0')
|
||
};
|
||
return format.replace(/YYYY|MM|DD|HH|mm|ss/g, matched => map[matched]);
|
||
},
|
||
getExtraDropOff(extraDropOffPoint) {
|
||
let returnExtraDropOffPoint = null;
|
||
if(extraDropOffPoint!=undefined && extraDropOffPoint!=null && extraDropOffPoint!=''){
|
||
returnExtraDropOffPoint = extraDropOffPoint.split(";");
|
||
}
|
||
console.log(returnExtraDropOffPoint);
|
||
return returnExtraDropOffPoint;
|
||
},
|
||
/** 用于酒店 / limo 混合列表排序:越大表示时间越晚 */
|
||
getRecordSortTimeMs(record) {
|
||
if (!record) {
|
||
return Number.POSITIVE_INFINITY;
|
||
}
|
||
if (record.recordType === 'limo') {
|
||
const raw = record.pickUpDatetime || record.pickUpDateTime || record.pickupDatetime;
|
||
if (raw != null && raw !== '') {
|
||
const n = Number(raw);
|
||
if (!Number.isNaN(n)) {
|
||
return n;
|
||
}
|
||
const parsedRaw = dayjs(String(raw).trim());
|
||
if (parsedRaw.isValid()) {
|
||
return parsedRaw.valueOf();
|
||
}
|
||
}
|
||
if (record.pickupDatetime) {
|
||
const s = String(record.pickupDatetime).trim();
|
||
const m = s.match(/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})\s+(\d{1,2}):(\d{2})$/);
|
||
if (m) {
|
||
const year = m[3].length === 2 ? 2000 + parseInt(m[3], 10) : parseInt(m[3], 10);
|
||
const d = new Date(
|
||
year,
|
||
parseInt(m[2], 10) - 1,
|
||
parseInt(m[1], 10),
|
||
parseInt(m[4], 10),
|
||
parseInt(m[5], 10)
|
||
);
|
||
if (!Number.isNaN(d.getTime())) {
|
||
return d.getTime();
|
||
}
|
||
}
|
||
}
|
||
return Number.POSITIVE_INFINITY;
|
||
}
|
||
const checkInDate = record.checkinDate || record.checkInDate || record.CheckInDate;
|
||
if (checkInDate != null && String(checkInDate).trim() !== '') {
|
||
const parsed = dayjs(String(checkInDate).trim());
|
||
if (parsed.isValid()) {
|
||
return parsed.valueOf();
|
||
}
|
||
}
|
||
return Number.POSITIVE_INFINITY;
|
||
},
|
||
getRecordSortDateMs(record) {
|
||
const timeMs = this.getRecordSortTimeMs(record);
|
||
if (!Number.isFinite(timeMs) || Number.isNaN(timeMs)) {
|
||
return Number.POSITIVE_INFINITY;
|
||
}
|
||
const d = new Date(timeMs);
|
||
d.setHours(0, 0, 0, 0);
|
||
return d.getTime();
|
||
},
|
||
getRecordTypeSortIndex(record) {
|
||
return record && record.recordType === 'limo' ? 1 : 0;
|
||
},
|
||
compareRecordForDisplay(a, b) {
|
||
const dateA = this.getRecordSortDateMs(a);
|
||
const dateB = this.getRecordSortDateMs(b);
|
||
if (dateA !== dateB) {
|
||
return dateA - dateB;
|
||
}
|
||
const typeDiff = this.getRecordTypeSortIndex(a) - this.getRecordTypeSortIndex(b);
|
||
if (typeDiff !== 0) {
|
||
return typeDiff;
|
||
}
|
||
if (a && b && a.recordType === 'limo' && b.recordType === 'limo') {
|
||
const timeA = this.getRecordSortTimeMs(a);
|
||
const timeB = this.getRecordSortTimeMs(b);
|
||
if (timeA !== timeB) {
|
||
return timeA - timeB;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
},
|
||
computed:{
|
||
hasSingleBookingPermission(){
|
||
if (!this.userData) return false;
|
||
return Boolean(this.userData.canNewBooking) !== Boolean(this.userData.canViewLimo);
|
||
},
|
||
displayRecordList(){
|
||
const hotelRecords = this.bookingList.map(item => ({...item, recordType: 'hotel'}));
|
||
const limoRecords = this.limoBookingList.map(item => ({...item, recordType: 'limo'}));
|
||
console.log(limoRecords);
|
||
return hotelRecords.concat(limoRecords).sort((a, b) => this.compareRecordForDisplay(a, b));
|
||
},
|
||
isDisplayEmpty(){
|
||
return this.displayRecordList.length === 0;
|
||
},
|
||
getConfirmationNo(){
|
||
return function (booking) {
|
||
if(booking!==undefined && booking!==null){
|
||
if(booking.confirmationNo!==undefined && booking.confirmationNo!==null &&
|
||
booking.confirmationNo!=='null' && booking.confirmationNo!=='' && booking.approveStatus!='W' && booking.approveStatus!='AP'){
|
||
return booking.confirmationNo;
|
||
}
|
||
}
|
||
return 'N/A';
|
||
}
|
||
},
|
||
dateFormat() {
|
||
return function (date) {
|
||
if (date != undefined) {
|
||
return dayjs(date).format("DD/MM/YY");
|
||
}
|
||
}
|
||
},
|
||
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' ||approveStatus.toUpperCase()==='WA'){
|
||
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' || approveStatus.toUpperCase()==='WA'){
|
||
return 'hz-status-font-waitlist';
|
||
}else if(approveStatus.toUpperCase()==='AP'){
|
||
console.log(111);
|
||
return 'hz-status-font-approval'
|
||
}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;
|
||
}
|
||
if(booking.recordType === 'limo'){
|
||
const noOpera = operaStatus==null || operaStatus==undefined || operaStatus==='' || operaStatus==='null';
|
||
const noApprove = approveStatus==null || approveStatus==undefined || approveStatus==='' || approveStatus==='null';
|
||
if(noOpera && noApprove && booking.status!=null && booking.status!==undefined && String(booking.status).trim()!==''){
|
||
const s = String(booking.status).toUpperCase().replace(/\s+/g,' ');
|
||
if(s.includes('CANCEL')){
|
||
return 'hz-status-font-cancel';
|
||
}
|
||
if(s.includes('WAITLIST') || s.includes('WAIT LIST')){
|
||
return 'hz-status-font-waitlist';
|
||
}
|
||
if(s.includes('NOT YET')){
|
||
return 'hz-status-font-waitlist';
|
||
}
|
||
if(s.includes('PENDING')){
|
||
return 'hz-status-font-pending';
|
||
}
|
||
if(s.includes('CONFIRM')){
|
||
return 'hz-status-font-duein';
|
||
}
|
||
if(s.includes('DRIVER_DEPARTED')){
|
||
return 'hz-status-font-duein';
|
||
}
|
||
if(s.includes('DRIVER_ASSIGNED')){
|
||
return 'hz-status-font-duein';
|
||
}
|
||
if(s.includes('DRIVER_ARRIVED')){
|
||
return 'hz-status-font-duein';
|
||
}
|
||
if(s.includes('GUEST_PICKED')){
|
||
return 'hz-status-font-duein';
|
||
}
|
||
return '';
|
||
}
|
||
}
|
||
if((operaStatus!=null && operaStatus!=undefined) || (approveStatus!=null && approveStatus!=undefined))
|
||
{
|
||
if(approveStatus.toUpperCase()==='PN'||approveStatus.toUpperCase()==='F'){
|
||
return 'hz-status-font-pending';
|
||
}else if(approveStatus.toUpperCase()==='N' || approveStatus.toUpperCase()==="FC"){
|
||
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 if(operaStatus.toUpperCase()==='PENDING CANCEL'){
|
||
return 'hz-status-font-cancel';
|
||
}
|
||
else
|
||
{
|
||
return '';
|
||
}
|
||
}
|
||
}else if(approveStatus.toUpperCase()==='W'|| approveStatus.toUpperCase()==='WA'){
|
||
return 'hz-status-font-waitlist';
|
||
}else if(approveStatus.toUpperCase()==='AP'){
|
||
return 'hz-status-font-approval';
|
||
}
|
||
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'||approveStatus.toUpperCase()==='F'){
|
||
return 'hz-status-font-pending';
|
||
}else if(approveStatus.toUpperCase()==='W' || approveStatus.toUpperCase()==='WA'){
|
||
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' || approveStatus.toUpperCase()==='WA'
|
||
|| approveStatus.toUpperCase()==='F' || approveStatus.toUpperCase()==='AP'){
|
||
if(approveStatus!==null && approveStatus!==undefined && approveStatus!=='' && approveStatus!=='null'){
|
||
if(approveStatus.toUpperCase()==='F'&&booking.tryTime<5){
|
||
return "PENDING";
|
||
}else{
|
||
return mapApproveStatus(approveStatus.toUpperCase());
|
||
}
|
||
}
|
||
}else if( approveStatus.toUpperCase()==='N' || approveStatus.toUpperCase()==='FC'){
|
||
if(operaStatus!==null && operaStatus!==undefined && operaStatus!=='' && operaStatus!=='null')
|
||
return mapOperaStatus(operaStatus.toUpperCase());
|
||
}
|
||
}
|
||
else if((operaStatus==null || operaStatus==undefined) && (approveStatus!=null && approveStatus!=undefined))
|
||
{
|
||
if(approveStatus.toUpperCase()==='F'&&booking.tryTime<5){
|
||
return "PENDING";
|
||
}else{
|
||
return mapApproveStatus(approveStatus.toUpperCase());
|
||
}
|
||
}
|
||
}
|
||
},
|
||
getRecordColor(){
|
||
return function (booking) {
|
||
if(booking==null){
|
||
return 'hz-card-booking';
|
||
}
|
||
if(booking.recordType === 'limo'){
|
||
const noApprove = booking.approveStatus==null || booking.approveStatus===undefined || booking.approveStatus==='' || booking.approveStatus==='null';
|
||
const noOpera = booking.lastOperaStatus==null || booking.lastOperaStatus===undefined || booking.lastOperaStatus==='' || booking.lastOperaStatus==='null';
|
||
if(noApprove && noOpera && booking.status!=null && booking.status!==undefined && String(booking.status).trim()!==''){
|
||
const s = String(booking.status).toUpperCase().replace(/\s+/g,' ');
|
||
if(s.includes('NOT YET') || s.includes('CONFIRM')){
|
||
return 'hz-card-booking';
|
||
}
|
||
if(s.includes('WAITLIST') || s.includes('WAIT LIST') || s.includes('PENDING')){
|
||
return 'hz-card-waitlist';
|
||
}
|
||
return 'hz-card-booking';
|
||
}
|
||
}
|
||
if(booking.approveStatus==='W'|| booking.approveStatus==='WA'){
|
||
return 'hz-card-waitlist'
|
||
}else if(booking.approveStatus==='AP'){
|
||
return 'hz-card-approval'
|
||
}else if((booking.lastOperaStatus==='DUE_OUT' || booking.lastOperaStatus==='CHECKED_IN') && booking.confirmationNo!=null && (booking.sharer==null || booking.sharer==='[]' || booking.sharer==='')){
|
||
return 'hz-card-booking'
|
||
}else if(booking.approveStatus==='AP'){
|
||
return 'hz-card-approval'
|
||
}else{
|
||
return 'hz-card-booking'
|
||
}
|
||
}
|
||
},
|
||
getETA(){
|
||
return function(ETA){
|
||
let returnStr = [];
|
||
if(ETA !== null && ETA !== undefined){
|
||
returnStr = ETA.split(":");
|
||
return returnStr[0] + ":" +returnStr[1];
|
||
}
|
||
return null;
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.hz-book-btn-wrap--single {
|
||
width: 95%;
|
||
}
|
||
</style>
|