1009 lines
36 KiB
Vue
1009 lines
36 KiB
Vue
<template>
|
|
<view class="hz-page">
|
|
<!-- #ifdef APP-PLUS -->
|
|
<simple-watermark ref="watermark"></simple-watermark>
|
|
<!-- #endif -->
|
|
<u-navbar @leftClick="back()" :safeAreaInsetTop="true" :placeholder="true" :title="title" :fixed="true"
|
|
:autoBack="false" leftIconColor="#000000" bgColor="#fff" titleStyle="font-weight:bold;">
|
|
</u-navbar>
|
|
<view class="hz-spacing hz-bg-white" style="margin-top:8px;">
|
|
<!-- Player Info 卡片 -->
|
|
<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">
|
|
{{bookingListData.length > 0 ? bookingListData[0].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">
|
|
{{bookingListData.length > 0 ? bookingListData[0].tier : '-'}}</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">
|
|
{{bookingListData.length > 0 ? (bookingListData[0].memberTitle || '') + ' ' + (bookingListData[0].memberFirstName || '') + ' ' + (bookingListData[0].memberLastName || '') : '-'}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- Booking Info 卡片 -->
|
|
<view class="hz-pd-16 hz-font-bolder hz-font-md hz-card-extend"
|
|
style="margin-top:10px;align-items: center;">
|
|
<view class="hz-flex-row" style="align-items: center; width: 100%;">
|
|
<!-- 房间信息轮播 -->
|
|
<view style="flex: 1; margin-right: 10px; min-height: 80px;">
|
|
<!-- 房间信息轮播 -->
|
|
<view style="position: relative; height: 100px;" @touchstart="touchStart" @touchend="touchEnd">
|
|
<!-- 轮播内容 -->
|
|
<view v-for="(room, index) in roomList" :key="index"
|
|
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; transition: opacity 0.5s;"
|
|
:style="{ opacity: currentRoomIndex === index ? 1 : 0, zIndex: currentRoomIndex === index ? 1 : 0 }">
|
|
<view class="hz-flex-row" style="align-items: center;">
|
|
<!-- 多选框 -->
|
|
<view
|
|
style="width: 17px; height: 17px; display: flex; align-items: center; justify-content: center;;"
|
|
@click="toggleSelection(index)">
|
|
<view
|
|
style="width: 15px; height: 15px; border: 0.5px solid #C39A4B; transition: all 0.3s; display: flex; align-items: center; justify-content: center;border-radius: 25px;"
|
|
:style="{ backgroundColor: room.selected ? '#C39A4B' : '#ffffff' }">
|
|
<view v-if="room.selected"
|
|
style="color: white; font-size: 10px; font-weight: bold;">✔</view>
|
|
</view>
|
|
</view>
|
|
<!-- 房间信息 -->
|
|
<view style="flex: 1;margin-left: 10px;">
|
|
<!-- Edit 按钮 -->
|
|
<view @click="toEdit()" style="display:flex;justify-content:flex-end;width:100%;">
|
|
<image src="/static/images/edit_active.png"
|
|
style="width: 17px; height: 17px;" />
|
|
</view>
|
|
|
|
<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-bolder"
|
|
style="margin-left:4px;font-size: 14px;">{{room.date}} {{$t("common.to")}}
|
|
{{room.endDate}}</span>
|
|
</view>
|
|
<view class="hz-flex-row" style="margin-top:8px;">
|
|
<view class="hz-flex-row" style="align-items: center;">
|
|
<image src="/static/images/ico_room.png"
|
|
style="width:16px;height:16px;"></image>
|
|
<span class="hz-font-bolder"
|
|
style="margin-left:4px;font-size: 14px;">{{room.roomInfo}}</span>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 轮播指示器 -->
|
|
<view
|
|
style="position: absolute; bottom: 0; left: 0; width: 100%; display: flex; justify-content: center; gap: 8px;">
|
|
<view v-for="(room, index) in roomList" :key="index"
|
|
style="width: 6px; height: 6px; border-radius: 50%; transition: background-color 0.3s;"
|
|
:style="{ backgroundColor: currentRoomIndex === index ? '#C39A4B' : '#CCCCCC' }"
|
|
@click="currentRoomIndex = index"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 玩家信息 -->
|
|
<view style="padding-left: 8px;padding-right: 8px;">
|
|
<view class="infoButton">
|
|
<view class="hz-flex-row dataMargin">
|
|
<view class="" style="width: 50%;font-weight: bolder">
|
|
Current Trip Theo
|
|
</view>
|
|
<view class="">
|
|
{{formatWithThousands(currentApprovalData.currentTripTheoWinAmount)}}
|
|
</view>
|
|
</view>
|
|
<view class="hz-flex-row dataMargin">
|
|
<view class="" style="width: 50%;font-weight: bolder">
|
|
Last 2 Days Theo
|
|
</view>
|
|
<view class="">
|
|
{{formatWithThousands(currentApprovalData.last2DayTheoWinAmount)}}
|
|
</view>
|
|
</view>
|
|
<view class="dataMargin">
|
|
<view class="hz-flex-row">
|
|
<view class="" style="width: 50%;font-weight: bolder">
|
|
R3 Theo/TPD/Actual win
|
|
</view>
|
|
</view>
|
|
<view class="hz-flex-row">
|
|
<view>
|
|
{{formatWithThousands(currentApprovalData.r3TheoWin)}} / {{formatWithThousands(currentApprovalData.r3TPD)}} / {{formatWithThousands(currentApprovalData.r3ActualWin)}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="hz-flex-row">
|
|
<view class="" style="width: 50%;font-weight: bolder">
|
|
R6 Theo/TPD/Actual win
|
|
</view>
|
|
</view>
|
|
<view class="hz-flex-row">
|
|
<view>
|
|
{{formatWithThousands(currentApprovalData.r6TheoWin)}} / {{formatWithThousands(currentApprovalData.r6TPD)}} / {{formatWithThousands(currentApprovalData.r6ActualWin)}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="infoButton">
|
|
<view style="font-weight: bolder">
|
|
Continuous / Overlap Booking (C/I to C/O)
|
|
</view>
|
|
<view>
|
|
{{currentApprovalData.overlapBooking}}
|
|
</view>
|
|
</view>
|
|
<!-- RoomCount -->
|
|
<view class="infoButton">
|
|
<view style="font-weight: bolder">
|
|
Room Count
|
|
</view>
|
|
<view>
|
|
{{ sortRoomCountByDate(currentApprovalData.roomCount) }}
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Remark -->
|
|
<view class="infoButton">
|
|
<view style="font-weight: bolder">
|
|
Remark
|
|
</view>
|
|
<view class="">
|
|
{{roomList[currentRoomIndex] && roomList[currentRoomIndex].remark ? roomList[currentRoomIndex].remark : '-'}}
|
|
</view>
|
|
</view>
|
|
<view class="infoButton">
|
|
<view style="font-weight: bolder">
|
|
Sharer
|
|
</view>
|
|
<view class="">
|
|
{{roomList[currentRoomIndex] ? roomList[currentRoomIndex].sharer : '-'}}
|
|
</view>
|
|
</view>
|
|
<view class="infoButton">
|
|
<view style="font-weight: bolder">
|
|
Request Reason
|
|
</view>
|
|
<view class="">
|
|
{{ currentApprovalRouting.approvalReason}}
|
|
</view>
|
|
</view>
|
|
<view class="infoButton">
|
|
<view style="font-weight: bolder">
|
|
Routing Reason
|
|
</view>
|
|
<view class="">
|
|
{{currentApprovalRouting.routingReason}}
|
|
</view>
|
|
</view>
|
|
<view class="hz-mr-t-30">
|
|
<view class="hz-flex-row">
|
|
<view class="" style="width: 50%;font-weight: bolder">
|
|
Requested on
|
|
</view>
|
|
<view class="" style="font-weight: bolder">
|
|
Requested by
|
|
</view>
|
|
</view>
|
|
<view class="hz-flex-row">
|
|
<view class="" style="width: 50%;">
|
|
{{currentApprovalRouting.createdAt ? formatDate(currentApprovalRouting.createdAt) : '-'}}
|
|
</view>
|
|
<view class="" style="width: 50%;">
|
|
{{currentApprovalRouting.createdBy}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<u-tabbar :fixed="true" :placeholder="true" :safeAreaInsetBottom="true" customStyle="z-index:100;height:58px;">
|
|
<view @click="toPreviousRecord()" class="book hz-flex-row hz-spacing"
|
|
:class="canPrevious==false? 'hz-disabled':''" style="width: 60%;">
|
|
<view class="hz-btn hz-font-color-primary hz-font-lg hz-font-bold hz-text-center"
|
|
style="background-color: #fff;border: #C39A4B solid 2px;display: flex;justify-content: center;align-items: center;">
|
|
<image src="/static/images/arrow_previous_active.png"
|
|
style="width: 25px; height: 25px;" />
|
|
</view>
|
|
</view>
|
|
<view @click="onTabApproveTap" class="book hz-flex-row hz-spacing"
|
|
:class="approvalLoading==true || roomList.filter(r => r.selected).length > 0? 'hz-disabled':''">
|
|
<view class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center">
|
|
{{$t("approval.approve")}}
|
|
</view>
|
|
</view>
|
|
<view @click="onTabRejectTap" class="book hz-flex-row hz-spacing"
|
|
:class="approvalLoading==true || roomList.filter(r => r.selected).length > 0? 'hz-disabled':''">
|
|
<view class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center">
|
|
{{$t("bookingDetail.reject")}}
|
|
</view>
|
|
</view>
|
|
<view @click="toNextRecord()" class="book hz-flex-row hz-spacing" :class="canNext==false? 'hz-disabled':''"
|
|
style="width: 60%">
|
|
<view class="hz-btn hz-font-color-primary hz-font-lg hz-font-bold hz-text-center"
|
|
style="background-color: #fff;border: #C39A4B solid 2px;display: flex;justify-content: center;align-items: center;">
|
|
<image src="/static/images/arrow_next_active.png"
|
|
style="width: 25px; height: 25px;" />
|
|
</view>
|
|
</view>
|
|
</u-tabbar>
|
|
<u-popup :safeAreaInsetBottom="true" :closeOnClickOverlay="false" :safeAreaInsetTop="true" :mode="'center'" :round="12" :show="showMsgBox"
|
|
customStyle="width:94%; padding-top: 30px" @close="closePopup()">
|
|
<view>
|
|
<view class="hz-flex-row" style="justify-content:center;align-items:center;width:100%;">
|
|
<image :src="iconPath" style="width:64px;height:64px;"></image>
|
|
</view>
|
|
<view class="hz-font-xl hz-font-bold hz-text-center"
|
|
style="margin-top:20px;margin-bottom: 20px;margin-left: 15px;margin-right: 15px;white-space:pre-wrap;">
|
|
<rich-text v-html="popMsgStr" style="line-height:26px;"></rich-text>
|
|
</view>
|
|
<view v-if="showSubmit">
|
|
<view @click="currentAction === 'approve' ? confirmApproval() : confirmReject()"
|
|
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center"
|
|
style="width: 90%;margin: 0 auto;margin-bottom: 15px;">
|
|
{{$t("common.confirm").toUpperCase()}}
|
|
</view>
|
|
<view @click="closePopup()"
|
|
class="hz-btn hz-font-color-primary hz-font-lg hz-font-bold hz-text-center"
|
|
style="width: 90%;margin: 0 auto;margin-bottom: 30px;background-color: white;border: 0.5px solid;">
|
|
{{$t("common.cancel").toUpperCase()}}
|
|
</view>
|
|
</view>
|
|
<view v-else>
|
|
<view @click="backToNotification()"
|
|
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center"
|
|
style="width: 90%;margin: 0 auto;margin-bottom: 15px;">
|
|
{{$t("approval.backToRecord").toUpperCase()}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</u-popup>
|
|
<u-popup :safeAreaInsetBottom="true" :safeAreaInsetTop="true" :mode="'center'" :round="12"
|
|
:show="showReturnMsgBox">
|
|
<view :style="'width:'+ windowWidth + 'px;'" style="padding:20px;">
|
|
<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 @click="showReturnMsgBox = false"
|
|
class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center" style="margin-top:20px;">
|
|
{{buttonStr}}
|
|
</view>
|
|
</view>
|
|
</u-popup>
|
|
<u-calendar closeOnClickOverlay :confirmText="confirmText" :confirmDisabledText="confirmText" color="#C39A4B"
|
|
title="" :startText="startText" :endText="endText" :show="showCalendar" :allowSameDay="true" mode="range"
|
|
:minDate="selectAbleStart" :maxDate="selectAbleEnd" :defaultDate="[calendarStartDate, calendarEndDate]"
|
|
@close="cancelDate" @confirm="confirmDate" :showMark="false">
|
|
</u-calendar>
|
|
|
|
<!-- 悬浮栏 - 显示选中的记录数量 -->
|
|
<view v-if="roomList.filter(r => r.selected).length > 0" class="floating-bar">
|
|
<view class="floating-content">
|
|
<text class="selected-count">{{ roomList.filter(r => r.selected).length }} {{ $t("common.selected") }}</text>
|
|
<view class="floating-actions">
|
|
<view @click="handleBatchApprove" class="action-btn approve-btn">{{ $t("approval.batchApprove") }}</view>
|
|
<view @click="handleBatchReject" class="action-btn reject-btn">{{ $t("approval.batchReject") }}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
batchSubmitApproval,
|
|
batchSubmitReject,
|
|
getApprovalData,
|
|
rejectApproval,
|
|
submitApproval
|
|
} from '../../api/approvalApi';
|
|
import {
|
|
times
|
|
} from '../../uni_modules/uview-ui/libs/function/digit';
|
|
|
|
// #ifdef APP-PLUS
|
|
import SimpleWatermark from '@/components/simple-watermark/simple-watermark.vue'
|
|
// #endif
|
|
|
|
export default {
|
|
components: {
|
|
// #ifdef APP-PLUS
|
|
SimpleWatermark
|
|
// #endif
|
|
},
|
|
data() {
|
|
return {
|
|
title: "Detail",
|
|
approvalLoading: false,
|
|
iconPath: '',
|
|
popMsgStr: '',
|
|
showMsgBox: false,
|
|
confirmText: this.$t('playerDetail.confirm'),
|
|
startText: this.$t('common.in'),
|
|
endText: this.$t('common.out'),
|
|
// 日历日期范围
|
|
calendarStartDate: '',
|
|
calendarEndDate: '',
|
|
selectAbleStart: '',
|
|
selectAbleEnd: '',
|
|
searchPlayerId: '',
|
|
showCalendar: false,
|
|
showSubmit: true,
|
|
deviceData: '',
|
|
canNext: false,
|
|
canPrevious: true,
|
|
// 玩家导航
|
|
currentPlayerIndex: 0,
|
|
approvalPlayerList: [],
|
|
showReturnMsgBox: false,
|
|
// 触摸事件
|
|
touchStartX: 0,
|
|
touchEndX: 0,
|
|
buttonStr: '',
|
|
msgStr: '',
|
|
windowWidth: 0,
|
|
// 房间信息轮播
|
|
currentRoomIndex: 0,
|
|
// 当前操作类型:approve 或 reject
|
|
currentAction: '',
|
|
bookingListData: [],
|
|
approvalGamingDataList: [],
|
|
approvalRoutingList: [],
|
|
roomList: []
|
|
}
|
|
},
|
|
computed: {
|
|
// 获取当前房间对应的 approvalGamingData
|
|
currentApprovalData() {
|
|
const currentRoom = this.roomList[this.currentRoomIndex];
|
|
if (currentRoom && currentRoom.id) {
|
|
const approvalData = this.approvalGamingDataList.find(
|
|
item => (item.bookingId != null ? item.bookingId : item.BookingId) == currentRoom.id
|
|
);
|
|
return approvalData || {};
|
|
}
|
|
return {};
|
|
},
|
|
// 当前轮播房间对应的 cfgApprovalRouting(按 bookingId 匹配)
|
|
currentApprovalRouting() {
|
|
const currentRoom = this.roomList[this.currentRoomIndex];
|
|
if (!currentRoom || currentRoom.id == null) return {};
|
|
const row = this.approvalRoutingList.find(
|
|
item => item.bookingId == currentRoom.id
|
|
);
|
|
return row || {};
|
|
}
|
|
},
|
|
methods: {
|
|
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;
|
|
},
|
|
// 将形如:2025-03-18 +12 (W +2) | 2025-03-16 + 16 ... 按日期升序排序
|
|
normalizeApprovalGamingData(item) {
|
|
if (!item) return {};
|
|
return {
|
|
bookingId: item.bookingId != null ? item.bookingId : item.BookingId,
|
|
playerId: item.playerId != null ? item.playerId : item.PlayerId,
|
|
currentTripTheoWinAmount: item.currentTripTheoWinAmount != null ? item.currentTripTheoWinAmount : item.CurrentTripTheoWinAmount,
|
|
last2DayTheoWinAmount: item.last2DayTheoWinAmount != null ? item.last2DayTheoWinAmount : item.Last2DayTheoWinAmount,
|
|
r3TheoWin: item.r3TheoWin != null ? item.r3TheoWin : item.R3TheoWin,
|
|
r3TPD: item.r3TPD != null ? item.r3TPD : item.R3TPD,
|
|
r3ActualWin: item.r3ActualWin != null ? item.r3ActualWin : item.R3ActualWin,
|
|
r6TheoWin: item.r6TheoWin != null ? item.r6TheoWin : item.R6TheoWin,
|
|
r6TPD: item.r6TPD != null ? item.r6TPD : item.R6TPD,
|
|
r6ActualWin: item.r6ActualWin != null ? item.r6ActualWin : item.R6ActualWin,
|
|
r12TheoWin: item.r12TheoWin != null ? item.r12TheoWin : item.R12TheoWin,
|
|
r12TPD: item.r12TPD != null ? item.r12TPD : item.R12TPD,
|
|
r12ActualWin: item.r12ActualWin != null ? item.r12ActualWin : item.R12ActualWin,
|
|
overlapBooking: item.overlapBooking != null ? item.overlapBooking : item.OverlapBooking,
|
|
roomCount: item.roomCount != null ? item.roomCount : item.RoomCount
|
|
};
|
|
},
|
|
sortRoomCountByDate(roomCountValue) {
|
|
if (roomCountValue === null || roomCountValue === undefined || roomCountValue === '') return '-';
|
|
const input = String(roomCountValue).trim();
|
|
if (!input) return '-';
|
|
const dateRegex = /^(\d{4}-\d{2}-\d{2})/;
|
|
|
|
// 新格式:类似 2026-04-01(100,W+0),2026-04-03(100,W+0),...(逗号分隔,括号内部也包含逗号)
|
|
// 不能简单 split(','),提取每个完整的 “YYYY-MM-DD(... )” 片段再排序
|
|
const parts = input.match(/\d{4}-\d{2}-\d{2}\s*[^)]*\([^)]*\)/g);
|
|
if (!parts || parts.length <= 1) return input;
|
|
|
|
const enriched = parts.map((part) => {
|
|
const m = part.match(dateRegex);
|
|
const dateStr = m ? m[1] : '';
|
|
const time = dateStr ? Date.parse(dateStr) : Number.POSITIVE_INFINITY;
|
|
return { part, time };
|
|
});
|
|
enriched.sort((a, b) => {
|
|
if (a.time === b.time) return a.part.localeCompare(b.part);
|
|
return a.time - b.time;
|
|
});
|
|
|
|
// 新格式分段之间通常是逗号
|
|
return enriched.map(x => x.part).join(',');
|
|
},
|
|
back() {
|
|
this.navBack();
|
|
},
|
|
toEdit() {
|
|
// 获取当前轮播图显示的房间信息
|
|
const currentRoom = this.roomList[this.currentRoomIndex];
|
|
if (currentRoom) {
|
|
// 从 bookingListData 中获取原始日期范围作为可选范围
|
|
// 因为 roomList 中的日期可能已经被修改过
|
|
const originalBooking = this.bookingListData.find(item => item.id === currentRoom.id);
|
|
if (originalBooking) {
|
|
// 可选日期范围保持为原始日期
|
|
// 注意:selectAbleStart 和 selectAbleEnd 只在数据加载时设置,这里不再修改
|
|
|
|
// 但默认显示的日期应该是当前房间的当前日期(可能已经被修改过的)
|
|
this.calendarStartDate = currentRoom.checkinDate;
|
|
this.calendarEndDate = currentRoom.checkoutDate;
|
|
}
|
|
}
|
|
this.showCalendar = true;
|
|
},
|
|
showApproval() {
|
|
// 设置当前操作类型为 approve
|
|
this.currentAction = 'approve';
|
|
this.iconPath = '../../static/images/warn.png';
|
|
this.popMsgStr = this.$t("approval.submitApproval");
|
|
this.showMsgBox = true; // 显示整个弹窗
|
|
this.showSubmit = true;
|
|
},
|
|
// 底部 Approve:有选中记录或 loading 时不进入 confirmApproval(避免仅样式置灰仍触发)
|
|
onTabApproveTap() {
|
|
if (this.approvalLoading || this.roomList.some(r => r.selected)) return;
|
|
this.confirmApproval();
|
|
},
|
|
// 底部 Reject:同上
|
|
onTabRejectTap() {
|
|
if (this.approvalLoading || this.roomList.some(r => r.selected)) return;
|
|
this.confirmReject();
|
|
},
|
|
async confirmApproval() {
|
|
if (this.approvalLoading || this.roomList.some(r => r.selected)) return;
|
|
uni.showLoading({
|
|
title: this.$t("common.loading")
|
|
});
|
|
|
|
// 获取当前轮播图显示的房间信息
|
|
const currentRoom = this.roomList[this.currentRoomIndex];
|
|
if (currentRoom) {
|
|
}
|
|
|
|
|
|
try {
|
|
let params = {
|
|
bookingId: currentRoom.id,
|
|
checkinDate: currentRoom.checkinDate,
|
|
checkoutDate: currentRoom.checkoutDate
|
|
};
|
|
const res = await submitApproval(params);
|
|
this.showMsgBox = false;
|
|
if (res.success == true) {
|
|
this.iconPath = '../../static/images/ico_suc.png';
|
|
this.popMsgStr = this.$t("bookingConfirm.approvalSuccess");
|
|
this.showMsgBox = true; // 显示整个弹窗
|
|
this.showSubmit = false;
|
|
} else {
|
|
this.buttonStr = this.$t("common.ok");
|
|
this.iconPath = '../../static/images/ico_err.png';
|
|
this.msgStr = res.message!=null?res.message:this.$t("common.approvalFail");
|
|
this.url = '';
|
|
this.showReturnMsgBox = true;
|
|
}
|
|
} 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, "find_player", "",
|
|
"[APP][findPlayer.vue][getProfileByPlayerId][Catch Exception]" + e.errMsg, request,
|
|
response, 1, false);
|
|
} finally {
|
|
uni.hideLoading();
|
|
}
|
|
|
|
},
|
|
async getApprovalDetailData(playerId) {
|
|
uni.showLoading({
|
|
title: this.$t("common.loading")
|
|
});
|
|
try {
|
|
// 如果传入了 playerId,则使用传入的,否则使用 searchPlayerId
|
|
const targetPlayerId = playerId || this.searchPlayerId;
|
|
let params = {
|
|
playerId: targetPlayerId
|
|
};
|
|
const res = await getApprovalData(params);
|
|
if (res.success == true) {
|
|
if (res.data !== null) {
|
|
this.bookingListData = res.data.bookingsViewList;
|
|
this.approvalGamingDataList = Array.isArray(res.data.approvalGamingData)
|
|
? res.data.approvalGamingData.map(item => this.normalizeApprovalGamingData(item))
|
|
: [];
|
|
const routingList = res.data.cfgApprovalRoutingList;
|
|
if (Array.isArray(routingList) && routingList.length > 0) {
|
|
this.approvalRoutingList = routingList;
|
|
} else if (res.data.cfgApprovalRouting) {
|
|
this.approvalRoutingList = [res.data.cfgApprovalRouting];
|
|
} else {
|
|
this.approvalRoutingList = [];
|
|
}
|
|
|
|
// 将 bookingListData 转换为 roomList 格式
|
|
if (this.bookingListData && this.bookingListData.length > 0) {
|
|
this.roomList = this.bookingListData.map(item => {
|
|
// 格式化日期,添加星期和月份
|
|
const formatDate = (dateStr) => {
|
|
if (!dateStr) return '';
|
|
const date = new Date(dateStr);
|
|
const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
const weekday = weekdays[date.getDay()];
|
|
const year = date.getFullYear();
|
|
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
const day = date.getDate().toString().padStart(2, '0');
|
|
return `(${weekday})${year}-${month}-${day}`;
|
|
};
|
|
|
|
return {
|
|
id: item.id,
|
|
bookingId: item.id, // 保存 bookingId 用于匹配 approvalGamingData
|
|
date: formatDate(item.checkinDate),
|
|
checkinDate: item.checkinDate, // 保存原始入住日期
|
|
endDate: formatDate(item.checkoutDate),
|
|
checkoutDate: item.checkoutDate, // 保存原始退房日期
|
|
roomInfo: `${item.propertyName || ''}, ${item.room || ''}`.trim(),
|
|
selected: false,
|
|
sharer: item.sharer || '-',
|
|
remark: item.remark
|
|
};
|
|
});
|
|
|
|
// 切换 player 后重置轮播索引,避免 new roomList 更短导致取不到数据
|
|
this.currentRoomIndex = 0;
|
|
|
|
// 数据加载完成后,获取当前房间的日期作为可选范围
|
|
if (this.roomList.length > 0) {
|
|
const currentRoom = this.roomList[this.currentRoomIndex];
|
|
if (currentRoom) {
|
|
this.selectAbleStart = currentRoom.checkinDate;
|
|
this.selectAbleEnd = currentRoom.checkoutDate;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 更新当前玩家在列表中的位置
|
|
this.updateCurrentPlayerIndex(targetPlayerId);
|
|
|
|
uni.hideLoading();
|
|
}
|
|
} else {
|
|
this.msgStr = res.message;
|
|
this.showMsg = true;
|
|
}
|
|
} 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, "find_player", "",
|
|
"[APP][findPlayer.vue][getProfileByPlayerId][Catch Exception]" + e.errMsg, request,
|
|
response, 1, false);
|
|
} finally {
|
|
uni.hideLoading();
|
|
}
|
|
},
|
|
closePopup() {
|
|
this.showMsgBox = false;
|
|
},
|
|
cancelDate() {
|
|
this.showCalendar = false;
|
|
},
|
|
confirmDate(e) {
|
|
// e 是选择的日期数组,格式为 [开始日期, 结束日期]
|
|
if (e) {
|
|
const startDate = e[0];
|
|
const endDate = e[e.length - 1];
|
|
|
|
// 获取当前轮播图显示的房间信息
|
|
const currentRoom = this.roomList[this.currentRoomIndex];
|
|
if (currentRoom) {
|
|
// 更新原始日期字段
|
|
currentRoom.checkinDate = startDate;
|
|
currentRoom.checkoutDate = endDate;
|
|
|
|
// 更新显示用的格式化日期
|
|
// 这里需要重新格式化日期,保持与之前相同的格式
|
|
const formatDateForDisplay = (dateStr) => {
|
|
if (!dateStr) return '';
|
|
const date = new Date(dateStr);
|
|
const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
const weekday = weekdays[date.getDay()];
|
|
const year = date.getFullYear();
|
|
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
const day = date.getDate().toString().padStart(2, '0');
|
|
return `(${weekday})${year}-${month}-${day}`;
|
|
};
|
|
|
|
const formatEndDateForDisplay = (dateStr) => {
|
|
if (!dateStr) return '';
|
|
const date = new Date(dateStr);
|
|
const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
const weekday = weekdays[date.getDay()];
|
|
const year = date.getFullYear();
|
|
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
const day = date.getDate().toString().padStart(2, '0');
|
|
return `(${weekday})${year}-${month}-${day}`;
|
|
};
|
|
|
|
currentRoom.date = formatDateForDisplay(startDate);
|
|
currentRoom.endDate = formatEndDateForDisplay(endDate);
|
|
|
|
}
|
|
}
|
|
this.showCalendar = false;
|
|
},
|
|
// 日期格式化方法
|
|
formatDate(timestamp) {
|
|
if (!timestamp) return '-';
|
|
const date = new Date(timestamp);
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
return `${year}-${month}-${day}`;
|
|
},
|
|
// 更新当前玩家在列表中的位置
|
|
updateCurrentPlayerIndex(playerId) {
|
|
if (this.approvalPlayerList && this.approvalPlayerList.length > 0) {
|
|
const currentIndex = this.approvalPlayerList.findIndex(item => item.playerId === playerId);
|
|
if (currentIndex !== -1) {
|
|
this.currentPlayerIndex = currentIndex;
|
|
// 更新 canPrevious 和 canNext
|
|
this.canPrevious = currentIndex > 0;
|
|
this.canNext = currentIndex < this.approvalPlayerList.length - 1;
|
|
}
|
|
}
|
|
},
|
|
backToNotification() {
|
|
this.navBack();
|
|
},
|
|
toPreviousRecord() {
|
|
if (this.canPrevious === true) {
|
|
// 导航到上一个玩家
|
|
const previousIndex = this.currentPlayerIndex - 1;
|
|
if (previousIndex >= 0 && this.approvalPlayerList[previousIndex]) {
|
|
const previousPlayerId = this.approvalPlayerList[previousIndex].playerId;
|
|
// 先重置轮播索引,避免切换过程中出现空白
|
|
this.currentRoomIndex = 0;
|
|
this.getApprovalDetailData(previousPlayerId);
|
|
}
|
|
} else {
|
|
}
|
|
},
|
|
toNextRecord() {
|
|
if (this.canNext === true) {
|
|
// 导航到下一个玩家
|
|
const nextIndex = this.currentPlayerIndex + 1;
|
|
if (nextIndex < this.approvalPlayerList.length && this.approvalPlayerList[nextIndex]) {
|
|
const nextPlayerId = this.approvalPlayerList[nextIndex].playerId;
|
|
// 先重置轮播索引,避免切换过程中出现空白
|
|
this.currentRoomIndex = 0;
|
|
this.getApprovalDetailData(nextPlayerId);
|
|
}
|
|
}
|
|
},
|
|
// 处理轮播图切换事件
|
|
handleSwiperChange(e) {
|
|
this.currentRoomIndex = e.detail.current;
|
|
this.updateSelectableDates();
|
|
},
|
|
// 触摸开始事件
|
|
touchStart(e) {
|
|
this.touchStartX = e.touches[0].clientX;
|
|
},
|
|
// 触摸结束事件
|
|
touchEnd(e) {
|
|
this.touchEndX = e.changedTouches[0].clientX;
|
|
this.handleSwipe();
|
|
},
|
|
// 处理滑动事件
|
|
handleSwipe() {
|
|
const swipeThreshold = 30; // 滑动阈值
|
|
// 向左滑动
|
|
if (this.touchStartX - this.touchEndX > swipeThreshold) {
|
|
this.currentRoomIndex = (this.currentRoomIndex + 1) % this.roomList.length;
|
|
this.updateSelectableDates();
|
|
}
|
|
// 向右滑动
|
|
else if (this.touchEndX - this.touchStartX > swipeThreshold) {
|
|
this.currentRoomIndex = (this.currentRoomIndex - 1 + this.roomList.length) % this.roomList.length;
|
|
this.updateSelectableDates();
|
|
}
|
|
},
|
|
// 更新可选日期范围
|
|
updateSelectableDates() {
|
|
const currentRoom = this.roomList[this.currentRoomIndex];
|
|
if (currentRoom) {
|
|
// 从 bookingListData 中获取原始日期范围作为可选范围
|
|
const originalBooking = this.bookingListData.find(item => item.id === currentRoom.id);
|
|
if (originalBooking) {
|
|
// 可选日期范围保持为原始日期
|
|
this.selectAbleStart = originalBooking.checkinDate;
|
|
this.selectAbleEnd = originalBooking.checkoutDate;
|
|
|
|
// 但默认显示的日期应该是当前房间的当前日期(可能已经被修改过的)
|
|
this.calendarStartDate = currentRoom.checkinDate;
|
|
this.calendarEndDate = currentRoom.checkoutDate;
|
|
}
|
|
}
|
|
},
|
|
// 切换房间选择状态
|
|
toggleSelection(index) {
|
|
this.roomList[index].selected = !this.roomList[index].selected;
|
|
},
|
|
showReject() {
|
|
// 设置当前操作类型为 reject
|
|
this.currentAction = 'reject';
|
|
this.iconPath = '../../static/images/ico_err.png';
|
|
this.popMsgStr = this.$t("approval.submitReject");
|
|
this.showMsgBox = true; // 显示整个弹窗
|
|
this.showSubmit = true;
|
|
},
|
|
|
|
async confirmReject() {
|
|
if (this.approvalLoading || this.roomList.some(r => r.selected)) return;
|
|
|
|
uni.showLoading({
|
|
title: this.$t("common.loading")
|
|
});
|
|
|
|
// 获取当前轮播图显示的房间信息
|
|
const currentRoom = this.roomList[this.currentRoomIndex];
|
|
|
|
try {
|
|
let params = {
|
|
bookingId: currentRoom.id
|
|
};
|
|
const res = await rejectApproval(params);
|
|
if (res.success == true) {
|
|
if (res.data !== null) {
|
|
this.iconPath = '../../static/images/ico_suc.png';
|
|
this.popMsgStr = this.$t("bookingConfirm.rejectSuccess");
|
|
this.showMsgBox = true; // 显示整个弹窗
|
|
this.showSubmit = false;
|
|
}
|
|
} else {
|
|
this.buttonStr = this.$t("common.ok");
|
|
this.iconPath = '../../static/images/ico_err.png';
|
|
this.msgStr = res.message!=null?res.message:this.$t("common.rejectFail");
|
|
this.url = '';
|
|
this.showReturnMsgBox = true;
|
|
}
|
|
} 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, "find_player", "",
|
|
"[APP][findPlayer.vue][getProfileByPlayerId][Catch Exception]" + e.errMsg, request,
|
|
response, 1, false);
|
|
} finally {
|
|
uni.hideLoading();
|
|
}
|
|
|
|
// 延时显示Success
|
|
setTimeout(() => {}, 1000);
|
|
},
|
|
// 批量批准
|
|
async handleBatchApprove() {
|
|
uni.showLoading({
|
|
title: this.$t("common.loading")
|
|
});
|
|
|
|
try {
|
|
const selectedRooms = this.roomList.filter(room => room.selected);
|
|
|
|
// 新建参数,包含每个房间的 RoomId、checkindate 和 checkoutdate
|
|
const roomInfoList = selectedRooms.map(room => ({
|
|
bookingId: room.id,
|
|
checkinDate: room.checkinDate,
|
|
checkoutDate: room.checkoutDate
|
|
}));
|
|
|
|
const params = {submitInfoList:roomInfoList};
|
|
const res = await batchSubmitApproval(params);
|
|
|
|
this.showMsgBox = false;
|
|
if (res.success == true) {
|
|
this.iconPath = '../../static/images/suc.png';
|
|
this.popMsgStr = this.$t("bookingConfirm.approvalSuccess");
|
|
this.showMsgBox = true; // 显示整个弹窗
|
|
this.showSubmit = false;
|
|
} else {
|
|
this.buttonStr = this.$t("common.ok");
|
|
this.iconPath = '../../static/images/ico_err.png';
|
|
this.msgStr = res.message!=null?res.message:this.$t("common.appro")
|
|
this.url = '';
|
|
this.showReturnMsgBox = true;
|
|
}
|
|
} 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, "batch_approval", "",
|
|
"[APP][playerDetail.vue][handleBatchApprove][Catch Exception]" + e.errMsg, request,
|
|
response, 1, false);
|
|
} finally {
|
|
uni.hideLoading();
|
|
}
|
|
|
|
this.roomList.forEach(room => room.selected = false);
|
|
},
|
|
// 批量拒绝
|
|
async handleBatchReject() {
|
|
uni.showLoading({
|
|
title: this.$t("common.loading")
|
|
});
|
|
|
|
try {
|
|
const selectedRooms = this.roomList.filter(room => room.selected);
|
|
|
|
// 新建参数,包含每个房间的 RoomId、checkindate 和 checkoutdate
|
|
const roomInfoList = selectedRooms.map(room => ({
|
|
bookingId: room.id
|
|
}));
|
|
|
|
const params = {submitInfoList:roomInfoList};
|
|
const res = await batchSubmitReject(params);
|
|
|
|
this.showMsgBox = false;
|
|
if (res.success == true) {
|
|
this.iconPath = '../../static/images/suc.png';
|
|
this.popMsgStr = this.$t("bookingConfirm.rejectSuccess");
|
|
this.showMsgBox = true; // 显示整个弹窗
|
|
this.showSubmit = false;
|
|
} else {
|
|
this.buttonStr = this.$t("common.ok");
|
|
this.iconPath = '../../static/images/ico_err.png';
|
|
this.msgStr = this.$t("common.rejectFail") +":"+ res.message;
|
|
this.url = '';
|
|
this.showReturnMsgBox = true;
|
|
}
|
|
} 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, "batch_approval", "",
|
|
"[APP][playerDetail.vue][handleBatchApprove][Catch Exception]" + e.errMsg, request,
|
|
response, 1, false);
|
|
} finally {
|
|
uni.hideLoading();
|
|
}
|
|
this.roomList.forEach(room => room.selected = false);
|
|
}
|
|
},
|
|
onShow() {
|
|
// 手动触发水印更新,确保水印在页面显示时正确显示
|
|
this.$nextTick(() => {
|
|
setTimeout(() => {
|
|
console.log('[TodoList] Manually triggering watermark update on show');
|
|
const watermarkStore = require('@/store/watermark.js');
|
|
if (watermarkStore && watermarkStore.updateWatermark) {
|
|
watermarkStore.updateWatermark(true);
|
|
}
|
|
}, 500);
|
|
});
|
|
},
|
|
onLoad(opt) {
|
|
|
|
this.deviceData = uni.getStorageSync("deviceData");
|
|
this.windowWidth = this.deviceData.windowWidth - 70;
|
|
this.searchPlayerId = opt.playerId;
|
|
this.approvalPlayerList = uni.getStorageSync("approvalPlayerList");
|
|
|
|
if (this.searchPlayerId != null) this.getApprovalDetailData()
|
|
},
|
|
onReady() {
|
|
// 页面首次渲染完成后,延迟触发水印更新
|
|
setTimeout(() => {
|
|
console.log('[TodoList] Triggering watermark update on ready');
|
|
const watermarkStore = require('@/store/watermark.js');
|
|
if (watermarkStore && watermarkStore.updateWatermark) {
|
|
watermarkStore.updateWatermark(true);
|
|
}
|
|
}, 1200);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 悬浮栏样式 - 显示在tabbar上方 */
|
|
.floating-bar {
|
|
position: fixed;
|
|
bottom: 65px;
|
|
/* tabbar高度 */
|
|
left: 0;
|
|
right: 0;
|
|
background-color: #ffffff;
|
|
border-top: 1px solid #e4e7ed;
|
|
border-radius: 25px;
|
|
padding: 10px 15px;
|
|
margin: 0px 10px;
|
|
z-index: 99;
|
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.floating-content {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.selected-count {
|
|
font-size: 14px;
|
|
color: #606266;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.floating-actions {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
|
|
.action-btn {
|
|
padding: 8px 16px;
|
|
border-radius: 20px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.approve-btn {
|
|
background-color: #C39A4B;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.reject-btn {
|
|
background-color:#C39A4B;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.infoButton {
|
|
border-bottom: 0.5px #999 solid;
|
|
padding-bottom: 6px;
|
|
margin-top: 6px;
|
|
}
|
|
|
|
.dataMargin {
|
|
margin-bottom: 3px;
|
|
}
|
|
</style>
|