843 lines
26 KiB
Vue
843 lines
26 KiB
Vue
<template>
|
|
<view class="player-room-calendar-page">
|
|
<u-navbar
|
|
:safeAreaInsetTop="true"
|
|
:placeholder="true"
|
|
:title="title"
|
|
:fixed="true"
|
|
:autoBack="false"
|
|
leftIconColor="#000000"
|
|
titleStyle="font-weight:bold;"
|
|
@leftClick="back"
|
|
>
|
|
<view slot="right" class="calendar-refresh-btn" @click.stop="refreshCalendar">
|
|
<u-icon name="reload" size="24" color="#000000"></u-icon>
|
|
</view>
|
|
</u-navbar>
|
|
|
|
<!-- <view class="player-summary"> -->
|
|
<view class="hz-card-profile mb-[40]" style="margin:9px 9px 6px;">
|
|
<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 class="calendar-panel">
|
|
<view class="property-tabs">
|
|
<u-tabs
|
|
:current="selectedPropertyIndex"
|
|
:scrollable="false"
|
|
:list="propertyTabList"
|
|
lineColor="#C39A4B"
|
|
:itemStyle="propertyTabItemStyle"
|
|
:activeStyle="propertyTabActiveStyle"
|
|
:inactiveStyle="propertyTabInactiveStyle"
|
|
@change="changePropertyTab"
|
|
></u-tabs>
|
|
</view>
|
|
|
|
<view class="room-type-grid">
|
|
<view
|
|
v-for="option in currentSelectorList"
|
|
:key="option.code"
|
|
class="room-type-btn"
|
|
:class="{ active: selectedSelectorCodes.indexOf(option.code) !== -1 }"
|
|
@click="toggleSelectorOption(option.code)"
|
|
>
|
|
{{ option.label }}
|
|
</view>
|
|
</view>
|
|
|
|
<view v-if="calendarNoPermission" class="calendar-empty-state">
|
|
<view class="hz-flex-row calendar-empty-image-row">
|
|
<image src="/static/images/datanull.png" class="calendar-empty-image"></image>
|
|
</view>
|
|
<view class="hz-flex-row hz-font-bolder hz-font-md calendar-empty-text">
|
|
{{$t("todo.noPermission")}}
|
|
</view>
|
|
</view>
|
|
|
|
<room-calendar-grid
|
|
v-else-if="calendarReady"
|
|
:key="calendarRenderKey"
|
|
mode="qualification"
|
|
:months="calendarMonths"
|
|
:weekday-labels="weekdayLabels"
|
|
:room-types="selectedRoomTypes"
|
|
:data-map="qualificationMap"
|
|
:initial-week-id="todayWeekId"
|
|
:center-content="true"
|
|
:show-leader="false"
|
|
></room-calendar-grid>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import dayjs from '../../uni_modules/uview-ui/libs/util/dayjs.js';
|
|
import {
|
|
buildCalendarDateRange,
|
|
getTodayWeekId,
|
|
mapRoomCalendarQualificationRecords,
|
|
} from '../../common/roomCalendarUi.js';
|
|
import { getPlayerRoomQualification, getPropertiesRoomTypes } from '../../api/roomCalendarApi.js';
|
|
import { getCalendarSetting as requestCalendarSetting } from '../../api/configApi.js';
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
title: this.$t("roomCalendar.playerTitle"),
|
|
userData: null,
|
|
playerData: null,
|
|
selectedPropertyCode: '',
|
|
selectedRoomTypeCodes: [],
|
|
selectedOtherPropertyCodes: [],
|
|
qualificationMap: {},
|
|
calendarPreviousDays: 0,
|
|
calendarVisibleDays: 90,
|
|
calendarYesterdayStart: '',
|
|
calendarYesterdayEnd: '',
|
|
maxSelectedRoomTypes: 0,
|
|
calendarToday: dayjs().format('YYYY-MM-DD'),
|
|
calendarStartDate: '',
|
|
calendarEndDate: '',
|
|
calendarMonths: [],
|
|
calendarReady: false,
|
|
calendarNoPermission: false,
|
|
calendarRenderKey: 0,
|
|
calendarRequestTask: null,
|
|
calendarRequestId: 0,
|
|
weekdayLabels: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
|
propertyList: [],
|
|
};
|
|
},
|
|
computed: {
|
|
safePlayerData() {
|
|
return this.playerData || {};
|
|
},
|
|
playerName() {
|
|
const salutation = this.safePlayerData.salutation || '';
|
|
const name = this.safePlayerData.name || '';
|
|
const text = `${salutation} ${name}`.trim();
|
|
return text || '-';
|
|
},
|
|
currentProperty() {
|
|
return this.propertyList.find(item => item.code === this.selectedPropertyCode) || this.propertyList[0] || {
|
|
defaultRoomTypes: [],
|
|
roomTypes: [],
|
|
};
|
|
},
|
|
isOtherProperty() {
|
|
return this.selectedPropertyCode === 'OTHER';
|
|
},
|
|
currentRoomTypes() {
|
|
return this.currentProperty.roomTypes || [];
|
|
},
|
|
currentOtherProperties() {
|
|
return this.currentProperty.otherProperties || [];
|
|
},
|
|
currentSelectorList() {
|
|
if (this.isOtherProperty) {
|
|
return this.currentOtherProperties.map(item => ({
|
|
code: item.code,
|
|
label: item.code,
|
|
}));
|
|
}
|
|
return this.currentRoomTypes;
|
|
},
|
|
selectedSelectorCodes() {
|
|
return this.isOtherProperty ? this.selectedOtherPropertyCodes : this.selectedRoomTypeCodes;
|
|
},
|
|
selectedOtherProperties() {
|
|
return this.currentOtherProperties.filter(item => this.selectedOtherPropertyCodes.indexOf(item.code) !== -1);
|
|
},
|
|
selectedRoomTypes() {
|
|
if (this.isOtherProperty) {
|
|
return this.selectedOtherProperties.reduce((list, property) => {
|
|
(property.roomTypes || []).forEach(roomType => {
|
|
list.push({
|
|
...roomType,
|
|
code: this.getOtherPropertyRoomTypeCode(property.code, roomType.code),
|
|
displayName: roomType.label,
|
|
parentCode: property.code,
|
|
propertyCode: property.code,
|
|
requestRoomTypeCode: roomType.code,
|
|
});
|
|
});
|
|
return list;
|
|
}, []);
|
|
}
|
|
const selected = this.currentRoomTypes.filter(item => this.selectedRoomTypeCodes.indexOf(item.code) !== -1);
|
|
return selected;
|
|
},
|
|
selectedPropertyIndex() {
|
|
const index = this.propertyList.findIndex(item => item.code === this.selectedPropertyCode);
|
|
return index === -1 ? 0 : index;
|
|
},
|
|
propertyTabList() {
|
|
return this.propertyList.map(item => ({
|
|
code: item.code,
|
|
name: item.name,
|
|
}));
|
|
},
|
|
propertyTabItemStyle() {
|
|
return {
|
|
height: '70rpx',
|
|
padding: '0',
|
|
};
|
|
},
|
|
propertyTabActiveStyle() {
|
|
return {
|
|
color: '#C39A4B',
|
|
fontFamily: 'Inter-Bold',
|
|
fontSize: '30rpx',
|
|
fontWeight: 'bold',
|
|
};
|
|
},
|
|
propertyTabInactiveStyle() {
|
|
return {
|
|
color: '#111111',
|
|
fontFamily: 'Inter-Bold',
|
|
fontSize: '30rpx',
|
|
fontWeight: 'bold',
|
|
};
|
|
},
|
|
todayWeekId() {
|
|
return getTodayWeekId(this.calendarMonths);
|
|
},
|
|
},
|
|
onLoad() {
|
|
this.playerData = uni.getStorageSync("playerData");
|
|
this.userData = uni.getStorageSync("userData");
|
|
this.loadPropertiesRoomTypes();
|
|
},
|
|
onShow() {
|
|
this.$i18n.locale = uni.getLocale();
|
|
this.title = this.$t("roomCalendar.playerTitle");
|
|
},
|
|
onUnload() {
|
|
this.calendarRequestId += 1;
|
|
this.abortCalendarRequest();
|
|
},
|
|
methods: {
|
|
back() {
|
|
this.navBack();
|
|
},
|
|
async loadPropertiesRoomTypes() {
|
|
try {
|
|
this.calendarReady = false;
|
|
uni.showLoading({
|
|
title: this.$t("common.loading"),
|
|
});
|
|
await this.loadCalendarSetting();
|
|
const res = await getPropertiesRoomTypes({});
|
|
this.propertyList = res.propertyList;
|
|
this.selectedPropertyCode = this.getDefaultPropertyCode();
|
|
this.selectDefaultOptions();
|
|
this.buildCalendar();
|
|
await this.loadQualificationData();
|
|
this.calendarRenderKey += 1;
|
|
this.$nextTick(() => {
|
|
this.calendarReady = true;
|
|
});
|
|
} catch (e) {
|
|
uni.$u.toast(e.message || e.errMsg || 'Load property room types failed');
|
|
} finally {
|
|
uni.hideLoading();
|
|
}
|
|
},
|
|
async loadCalendarSetting() {
|
|
try {
|
|
const res = await requestCalendarSetting({});
|
|
if (res && res.data) {
|
|
this.applyCalendarSettings(res.data);
|
|
}
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
},
|
|
applyCalendarSettings(settings) {
|
|
const settingMap = settings.reduce((map, item) => {
|
|
map[item.keys] = item.keyValues;
|
|
return map;
|
|
}, {});
|
|
this.calendarPreviousDays = this.getNumberSetting(settingMap.CALENDAR_VIEW_PREVIOUS_DAYS, this.calendarPreviousDays);
|
|
this.calendarVisibleDays = this.getNumberSetting(settingMap.CALENDAR_VIEW_VISIBLE_DAYS, this.calendarVisibleDays);
|
|
this.calendarYesterdayStart = settingMap.CALENDAR_VIEW_YESTERDAY_START || this.calendarYesterdayStart;
|
|
this.calendarYesterdayEnd = settingMap.CALENDAR_VIEW_YESTERDAY_END || this.calendarYesterdayEnd;
|
|
this.maxSelectedRoomTypes = this.getPositiveIntegerSetting(settingMap.MAX_SELECTED_ROOM_TYPES, this.maxSelectedRoomTypes);
|
|
},
|
|
getNumberSetting(value, defaultValue) {
|
|
if (value === undefined || value === null || value === '') return defaultValue;
|
|
const numberValue = Number(value);
|
|
return Number.isNaN(numberValue) ? defaultValue : numberValue;
|
|
},
|
|
getPositiveIntegerSetting(value, defaultValue) {
|
|
const numberValue = this.getNumberSetting(value, defaultValue);
|
|
return numberValue > 0 ? Math.floor(numberValue) : 0;
|
|
},
|
|
buildCalendar() {
|
|
const effectiveToday = this.getEffectiveCalendarToday();
|
|
const startDate = dayjs(effectiveToday).subtract(this.calendarPreviousDays, 'day').format('YYYY-MM-DD');
|
|
const endDate = dayjs(effectiveToday).add(this.calendarVisibleDays + this.calendarPreviousDays, 'day').format('YYYY-MM-DD');
|
|
this.calendarToday = effectiveToday;
|
|
this.calendarStartDate = startDate;
|
|
this.calendarEndDate = endDate;
|
|
this.calendarMonths = buildCalendarDateRange({
|
|
today: effectiveToday,
|
|
startDate,
|
|
endDate,
|
|
weekdayLabels: this.weekdayLabels,
|
|
});
|
|
},
|
|
getEffectiveCalendarToday() {
|
|
const now = dayjs();
|
|
if (this.isInYesterdayWindow(now)) {
|
|
return now.subtract(1, 'day').format('YYYY-MM-DD');
|
|
}
|
|
return now.format('YYYY-MM-DD');
|
|
},
|
|
isInYesterdayWindow(now) {
|
|
const startMinutes = this.getTimeMinutes(this.calendarYesterdayStart);
|
|
const endMinutes = this.getTimeMinutes(this.calendarYesterdayEnd);
|
|
if (startMinutes === null || endMinutes === null) return false;
|
|
const currentMinutes = now.hour() * 60 + now.minute();
|
|
if (startMinutes <= endMinutes) {
|
|
return currentMinutes >= startMinutes && currentMinutes <= endMinutes;
|
|
}
|
|
return currentMinutes >= startMinutes || currentMinutes <= endMinutes;
|
|
},
|
|
getTimeMinutes(value) {
|
|
if (!value) return null;
|
|
const parts = String(value).split(':').map(Number);
|
|
if (parts.length < 2 || Number.isNaN(parts[0]) || Number.isNaN(parts[1])) return null;
|
|
return parts[0] * 60 + parts[1];
|
|
},
|
|
changePropertyTab(tab) {
|
|
const property = this.propertyList[tab.index];
|
|
if (!property) return;
|
|
this.selectProperty(property.code);
|
|
},
|
|
selectProperty(code) {
|
|
const isSameProperty = code === this.selectedPropertyCode;
|
|
this.selectedPropertyCode = code;
|
|
this.ensureSelectedOptionsForRefresh(isSameProperty);
|
|
this.loadQualificationData();
|
|
},
|
|
selectDefaultOptions() {
|
|
if (this.isOtherProperty) {
|
|
this.selectedOtherPropertyCodes = this.getDefaultOtherPropertyCodes();
|
|
} else {
|
|
this.selectedRoomTypeCodes = this.getDefaultRoomTypeCodes();
|
|
}
|
|
},
|
|
ensureSelectedOptionsForRefresh(isSameProperty = false) {
|
|
if (this.isOtherProperty) {
|
|
if (!isSameProperty) {
|
|
this.selectedOtherPropertyCodes = this.getValidOtherPropertyCodes(this.selectedOtherPropertyCodes);
|
|
}
|
|
if (!this.selectedOtherPropertyCodes.length) {
|
|
this.selectedOtherPropertyCodes = this.getDefaultOtherPropertyCodes();
|
|
}
|
|
return;
|
|
}
|
|
if (!isSameProperty) {
|
|
this.selectedRoomTypeCodes = this.getValidRoomTypeCodes(this.selectedRoomTypeCodes);
|
|
}
|
|
if (!this.selectedRoomTypeCodes.length) {
|
|
this.selectedRoomTypeCodes = this.getDefaultRoomTypeCodes();
|
|
}
|
|
},
|
|
getValidRoomTypeCodes(codes) {
|
|
const validCodes = this.currentRoomTypes.map(item => this.getRoomTypeCode(item));
|
|
return (codes || []).filter(code => validCodes.indexOf(code) !== -1);
|
|
},
|
|
getValidOtherPropertyCodes(codes) {
|
|
const validCodes = this.currentOtherProperties.map(item => this.getPropertyCode(item));
|
|
return (codes || []).filter(code => validCodes.indexOf(code) !== -1);
|
|
},
|
|
toggleSelectorOption(code) {
|
|
if (this.isOtherProperty) {
|
|
this.toggleOtherProperty(code);
|
|
return;
|
|
}
|
|
this.toggleRoomType(code);
|
|
},
|
|
toggleRoomType(code) {
|
|
const index = this.selectedRoomTypeCodes.indexOf(code);
|
|
if (index === -1) {
|
|
if (this.isMaxSelectedRoomTypesReached(this.selectedRoomTypeCodes.length)) {
|
|
this.showMaxSelectedRoomTypesToast();
|
|
return;
|
|
}
|
|
this.selectedRoomTypeCodes.push(code);
|
|
this.loadQualificationData();
|
|
return;
|
|
}
|
|
if (this.selectedRoomTypeCodes.length === 1) {
|
|
uni.$u.toast('At least one room type is required');
|
|
return;
|
|
}
|
|
this.selectedRoomTypeCodes.splice(index, 1);
|
|
this.loadQualificationData();
|
|
},
|
|
toggleOtherProperty(code) {
|
|
const index = this.selectedOtherPropertyCodes.indexOf(code);
|
|
if (index === -1) {
|
|
if (this.isMaxSelectedRoomTypesReached(this.selectedOtherPropertyCodes.length)) {
|
|
this.showMaxSelectedRoomTypesToast();
|
|
return;
|
|
}
|
|
this.selectedOtherPropertyCodes.push(code);
|
|
this.loadQualificationData();
|
|
return;
|
|
}
|
|
if (this.selectedOtherPropertyCodes.length === 1) {
|
|
uni.$u.toast('At least one property is required');
|
|
return;
|
|
}
|
|
this.selectedOtherPropertyCodes.splice(index, 1);
|
|
this.loadQualificationData();
|
|
},
|
|
limitRoomTypeCodes(codes) {
|
|
if (!this.maxSelectedRoomTypes) return codes;
|
|
return codes.slice(0, this.maxSelectedRoomTypes);
|
|
},
|
|
getDefaultRoomTypeCodes() {
|
|
const defaultRoomTypes = this.normalizeRoomTypeCodes(
|
|
this.currentProperty.defaultRoomTypes || this.currentProperty.DefaultRoomTypes
|
|
);
|
|
const firstRoomTypeCode = this.getRoomTypeCode(this.currentRoomTypes[0]);
|
|
const roomTypeCodes = defaultRoomTypes.length
|
|
? defaultRoomTypes
|
|
: (firstRoomTypeCode ? [firstRoomTypeCode] : []);
|
|
return this.limitRoomTypeCodes(roomTypeCodes);
|
|
},
|
|
normalizeRoomTypeCodes(roomTypes) {
|
|
if (!roomTypes) return [];
|
|
if (Array.isArray(roomTypes)) {
|
|
return roomTypes.reduce((list, item) => list.concat(this.normalizeRoomTypeCodes(item)), []);
|
|
}
|
|
if (typeof roomTypes === 'string') {
|
|
return roomTypes
|
|
.split(',')
|
|
.map(code => code.trim())
|
|
.filter(code => code);
|
|
}
|
|
const code = this.getRoomTypeCode(roomTypes);
|
|
return code ? [code] : [];
|
|
},
|
|
getRoomTypeCode(roomType) {
|
|
if (!roomType) return '';
|
|
if (typeof roomType === 'string') return roomType;
|
|
return roomType.code || roomType.Code || roomType.roomType || roomType.RoomType || roomType.roomTypeCode || roomType.RoomTypeCode || '';
|
|
},
|
|
isMaxSelectedRoomTypesReached(selectedCount) {
|
|
return this.maxSelectedRoomTypes > 0 && selectedCount >= this.maxSelectedRoomTypes;
|
|
},
|
|
showMaxSelectedRoomTypesToast() {
|
|
uni.$u.toast(this.$t("roomCalendar.maxSelectedRoomTypes", {
|
|
count: this.maxSelectedRoomTypes,
|
|
}));
|
|
},
|
|
refreshCalendar() {
|
|
this.ensureSelectedOptionsForRefresh(true);
|
|
this.loadQualificationData();
|
|
},
|
|
async loadQualificationData() {
|
|
const records = [];
|
|
const dateRange = this.getCalendarDateRange();
|
|
const requestId = this.startCalendarRequest();
|
|
this.hideCalendarForLoading();
|
|
try {
|
|
uni.showLoading({
|
|
title: this.$t("common.loading"),
|
|
});
|
|
const params = this.buildQualificationParams(dateRange);
|
|
if (!params.RoomType) {
|
|
this.qualificationMap = {};
|
|
return;
|
|
}
|
|
console.log('[PlayerRoomCalendar] request Property:', params.Property, 'RoomType:', params.RoomType);
|
|
const res = await getPlayerRoomQualification(params, this.getCalendarRequestConfig(requestId));
|
|
if (!this.isLatestCalendarRequest(requestId)) return;
|
|
if (this.isNoPermissionResponse(res)) {
|
|
this.showCalendarNoPermission();
|
|
return;
|
|
}
|
|
if (res.success !== true) {
|
|
throw new Error(res.message || 'Load room calendar failed');
|
|
}
|
|
if (this.isOtherProperty) {
|
|
records.push(...this.buildOtherPropertyRecords(res.data || []));
|
|
} else {
|
|
records.push(...(res.data || []));
|
|
}
|
|
this.qualificationMap = mapRoomCalendarQualificationRecords(records);
|
|
} catch (e) {
|
|
if (!this.isLatestCalendarRequest(requestId) || this.isRequestAbortError(e)) return;
|
|
this.qualificationMap = {};
|
|
uni.$u.toast(e.message || e.errMsg || 'Load room calendar failed');
|
|
} finally {
|
|
if (this.isLatestCalendarRequest(requestId)) {
|
|
this.calendarRequestTask = null;
|
|
uni.hideLoading();
|
|
this.showCalendarAfterLoading(requestId);
|
|
}
|
|
}
|
|
},
|
|
hideCalendarForLoading() {
|
|
this.calendarReady = false;
|
|
this.calendarNoPermission = false;
|
|
},
|
|
showCalendarAfterLoading(requestId) {
|
|
this.$nextTick(() => {
|
|
if (this.isLatestCalendarRequest(requestId) && !this.calendarNoPermission) {
|
|
this.calendarReady = true;
|
|
}
|
|
});
|
|
},
|
|
isNoPermissionResponse(res) {
|
|
return res && res.success === false && res.errorCode === 'NO_PERMISSION';
|
|
},
|
|
showCalendarNoPermission() {
|
|
this.qualificationMap = {};
|
|
this.calendarReady = false;
|
|
this.calendarNoPermission = true;
|
|
},
|
|
startCalendarRequest() {
|
|
this.calendarRequestId += 1;
|
|
this.abortCalendarRequest();
|
|
this.calendarRequestTask = null;
|
|
return this.calendarRequestId;
|
|
},
|
|
abortCalendarRequest() {
|
|
if (this.calendarRequestTask && typeof this.calendarRequestTask.abort === 'function') {
|
|
this.calendarRequestTask.abort();
|
|
}
|
|
this.calendarRequestTask = null;
|
|
},
|
|
getCalendarRequestConfig(requestId) {
|
|
return {
|
|
getTask: task => {
|
|
if (this.isLatestCalendarRequest(requestId)) {
|
|
this.calendarRequestTask = task;
|
|
}
|
|
},
|
|
};
|
|
},
|
|
isLatestCalendarRequest(requestId) {
|
|
return requestId === this.calendarRequestId;
|
|
},
|
|
isRequestAbortError(error) {
|
|
const errMsg = error && error.errMsg ? String(error.errMsg) : '';
|
|
return errMsg.indexOf('abort') !== -1;
|
|
},
|
|
buildQualificationParams(dateRange) {
|
|
const allProperty = this.isOtherProperty
|
|
? this.selectedOtherPropertyCodes.join(',')
|
|
: this.selectedPropertyCode;
|
|
const allRoomType = this.getUniqueCodes(this.selectedRoomTypes.map(roomType => {
|
|
return roomType.requestRoomTypeCode || roomType.parentCode || roomType.code;
|
|
})).join(',');
|
|
return {
|
|
PlayerId: this.safePlayerData.playerId,
|
|
Property: allProperty,
|
|
RoomType: allRoomType,
|
|
StartDate: dateRange.startDate,
|
|
EndDate: dateRange.endDate,
|
|
category: this.currentProperty.category,
|
|
};
|
|
},
|
|
getUniqueCodes(codes) {
|
|
return [...new Set(codes.filter(code => code))];
|
|
},
|
|
getOtherPropertyRoomTypeCode(propertyCode, roomTypeCode) {
|
|
return `${propertyCode}_${roomTypeCode}`;
|
|
},
|
|
getDefaultOtherPropertyCodes() {
|
|
const defaultPropertySource =
|
|
this.currentProperty.defaultProperty ||
|
|
this.currentProperty.DefaultProperty ||
|
|
this.currentProperty.defaultProperties ||
|
|
this.currentProperty.DefaultProperties ||
|
|
this.currentProperty.defaultOtherProperty ||
|
|
this.currentProperty.DefaultOtherProperty ||
|
|
this.currentProperty.defaultOtherProperties ||
|
|
this.currentProperty.DefaultOtherProperties ||
|
|
this.currentProperty.defaultPropertyList ||
|
|
this.currentProperty.DefaultPropertyList ||
|
|
this.currentProperty.defaultPropertyCodes ||
|
|
this.currentProperty.DefaultPropertyCodes ||
|
|
this.currentProperty.defaultRoomTypes;
|
|
const defaultProperties = this.normalizeDefaultProperties(defaultPropertySource);
|
|
const defaultCodes = defaultProperties
|
|
.map(item => this.getPropertyCode(item))
|
|
.filter(code => this.currentOtherProperties.some(property => property.code === code));
|
|
const uniqueDefaultCodes = [...new Set(defaultCodes)];
|
|
if (uniqueDefaultCodes.length) {
|
|
return this.limitRoomTypeCodes(uniqueDefaultCodes);
|
|
}
|
|
const propertiesWithDefaultRoomTypes = [...new Set(this.currentOtherProperties
|
|
.filter(property => (property.defaultRoomTypes || property.DefaultRoomTypes || []).length)
|
|
.map(property => property.code))];
|
|
if (propertiesWithDefaultRoomTypes.length) {
|
|
return this.limitRoomTypeCodes(propertiesWithDefaultRoomTypes);
|
|
}
|
|
const firstOtherPropertyCode = this.getPropertyCode(this.currentOtherProperties[0]);
|
|
return firstOtherPropertyCode ? [firstOtherPropertyCode] : [];
|
|
},
|
|
normalizeDefaultProperties(defaultProperties) {
|
|
if (!defaultProperties) return [];
|
|
if (Array.isArray(defaultProperties)) {
|
|
return defaultProperties.reduce((list, item) => list.concat(this.normalizeDefaultProperties(item)), []);
|
|
}
|
|
if (typeof defaultProperties === 'string') {
|
|
return defaultProperties
|
|
.split(',')
|
|
.map(code => code.trim())
|
|
.filter(code => code);
|
|
}
|
|
return [defaultProperties];
|
|
},
|
|
getPropertyCode(property) {
|
|
if (typeof property === 'string') return property;
|
|
return property.code || property.Code || property.propertyCode || property.PropertyCode || property.Property || property.property || '';
|
|
},
|
|
getRecordRoomType(record) {
|
|
return record.roomType !== undefined ? record.roomType : record.RoomType;
|
|
},
|
|
getRecordProperty(record) {
|
|
return record.property !== undefined
|
|
? record.property
|
|
: record.Property || record.propertyCode || record.PropertyCode || '';
|
|
},
|
|
buildOtherPropertyRecords(records) {
|
|
return records.reduce((list, record) => {
|
|
this.getOtherPropertyRecordRoomTypeCodes(record).forEach(roomTypeCode => {
|
|
list.push({
|
|
...record,
|
|
roomType: roomTypeCode,
|
|
RoomType: roomTypeCode,
|
|
});
|
|
});
|
|
return list;
|
|
}, []);
|
|
},
|
|
getOtherPropertyRecordRoomTypeCodes(record) {
|
|
const recordRoomType = this.getRecordRoomType(record);
|
|
if (!recordRoomType) return [];
|
|
if (this.selectedRoomTypes.some(roomType => roomType.code === recordRoomType)) {
|
|
return [recordRoomType];
|
|
}
|
|
const recordPropertyCode = this.getSelectedOtherPropertyCode(this.getRecordProperty(record));
|
|
if (recordPropertyCode) {
|
|
return [this.getOtherPropertyRoomTypeCode(recordPropertyCode, recordRoomType)];
|
|
}
|
|
const matchedRoomTypes = this.selectedRoomTypes.filter(roomType => roomType.requestRoomTypeCode === recordRoomType);
|
|
return matchedRoomTypes.length ? matchedRoomTypes.map(roomType => roomType.code) : [recordRoomType];
|
|
},
|
|
getSelectedOtherPropertyCode(propertyValue) {
|
|
const normalizedValue = this.normalizeText(propertyValue);
|
|
if (!normalizedValue) return '';
|
|
const property = this.selectedOtherProperties.find(item => {
|
|
return this.getOtherPropertyAliases(item).some(value => this.normalizeText(value) === normalizedValue);
|
|
});
|
|
return property ? property.code : '';
|
|
},
|
|
getOtherPropertyAliases(property) {
|
|
const aliases = [
|
|
property.code,
|
|
property.name,
|
|
property.displayName,
|
|
property.propertyName,
|
|
property.hotelName,
|
|
];
|
|
if (property.code === 'MO') {
|
|
aliases.push('MGM Macau', 'Macau', 'MOGR');
|
|
}
|
|
return aliases;
|
|
},
|
|
normalizeText(value) {
|
|
return String(value || '').trim().toUpperCase();
|
|
},
|
|
getCalendarDateRange() {
|
|
const dates = [];
|
|
this.calendarMonths.forEach(month => {
|
|
month.weeks.forEach(week => {
|
|
week.days.forEach(day => {
|
|
if (!day.isOutsideMonth) {
|
|
dates.push(day.date);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
return {
|
|
startDate: dates[0],
|
|
endDate: dates[dates.length - 1],
|
|
};
|
|
},
|
|
getDefaultPropertyCode() {
|
|
const userText = JSON.stringify(this.userData || {}).toUpperCase();
|
|
const property = this.propertyList.find(item => {
|
|
const name = String(item.name || '').toUpperCase();
|
|
return userText.indexOf(name) !== -1 || (item.code === 'OTHER' && userText.indexOf('OTHER') !== -1);
|
|
});
|
|
return (property || this.propertyList[0]).code;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
page {
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.player-room-calendar-page {
|
|
background-color: #ffffff;
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.player-summary {
|
|
background-color: #c39a4b;
|
|
border-radius: 24rpx;
|
|
box-sizing: border-box;
|
|
flex-shrink: 0;
|
|
margin: 16rpx 16rpx 12rpx;
|
|
padding: 26rpx 28rpx;
|
|
}
|
|
|
|
.summary-row {
|
|
display: flex;
|
|
flex-direction: row;
|
|
}
|
|
|
|
.summary-name-row {
|
|
margin-top: 22rpx;
|
|
}
|
|
|
|
.summary-item {
|
|
min-width: 0;
|
|
}
|
|
|
|
.summary-player {
|
|
width: 60%;
|
|
}
|
|
|
|
.summary-tier {
|
|
width: 40%;
|
|
}
|
|
|
|
.summary-label {
|
|
color: #fff8e8;
|
|
font-family: "Inter-Bold";
|
|
font-size: 26rpx;
|
|
line-height: 32rpx;
|
|
}
|
|
|
|
.summary-value {
|
|
color: #ffffff;
|
|
font-family: "Inter-Bold";
|
|
font-size: 34rpx;
|
|
font-weight: bold;
|
|
line-height: 42rpx;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.calendar-panel {
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
padding: 2rpx 8rpx 0;
|
|
}
|
|
|
|
.property-tabs {
|
|
flex-shrink: 0;
|
|
padding: 4rpx 0 2rpx;
|
|
}
|
|
|
|
.room-type-grid {
|
|
display: flex;
|
|
flex-direction: row;
|
|
flex-shrink: 0;
|
|
flex-wrap: wrap;
|
|
padding: 6rpx 0 2rpx;
|
|
}
|
|
|
|
.room-type-btn {
|
|
background-color: #ffffff;
|
|
border: 1rpx solid #d8d8d8;
|
|
border-radius: 8rpx;
|
|
box-sizing: border-box;
|
|
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.12);
|
|
color: #111111;
|
|
font-family: "Inter-Bold";
|
|
font-size: 28rpx;
|
|
height: 58rpx;
|
|
line-height: 58rpx;
|
|
margin: 5rpx 6rpx;
|
|
text-align: center;
|
|
width: calc(16.6666% - 12rpx);
|
|
}
|
|
|
|
.room-type-btn.active {
|
|
background-color: #c39a4b;
|
|
border-color: #c39a4b;
|
|
box-shadow: none;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.calendar-refresh-btn {
|
|
align-items: center;
|
|
display: flex;
|
|
height: 88rpx;
|
|
justify-content: center;
|
|
margin-right: 5rpx;
|
|
width: 64rpx;
|
|
}
|
|
|
|
.calendar-empty-state {
|
|
flex: 1;
|
|
}
|
|
|
|
.calendar-empty-image-row {
|
|
justify-content: center;
|
|
margin-top: 80px;
|
|
}
|
|
|
|
.calendar-empty-image {
|
|
height: 160px;
|
|
width: 160px;
|
|
}
|
|
|
|
.calendar-empty-text {
|
|
justify-content: center;
|
|
margin: 20px;
|
|
}
|
|
|
|
</style>
|