fix bugs
This commit is contained in:
+151
-84
@@ -7,79 +7,84 @@
|
||||
style="margin-top:36rpx;margin-right:36rpx;">
|
||||
{{$t('dashboard.dataAsOf')}} {{dataAsOf}}
|
||||
</view>
|
||||
<view class="hz-font-bolder hz-font-xl hz-font-color-black hz-text-left"
|
||||
style="margin-top:36rpx;margin-left:36rpx;">
|
||||
{{$t('dashboard.achievement')}}
|
||||
|
||||
<view v-if="showAchievement">
|
||||
<view class="hz-font-bolder hz-font-xl hz-font-color-black hz-text-left"
|
||||
style="margin-top:36rpx;margin-left:36rpx;">
|
||||
{{$t('dashboard.achievement')}}
|
||||
|
||||
</view>
|
||||
<uni-card>
|
||||
<view v-for="(record,index) in dashboardData" :key="index" v-show="getShowAchievement(record)"
|
||||
style="margin-top:12px;">
|
||||
<view class="hz-flex-row">
|
||||
<view style="width:37%">
|
||||
<view class="hz-font-color-dark hz-font-base">{{record.itemName}}</view>
|
||||
</view>
|
||||
<view v-if="record.targetValue!==0&&record.targetValue!==null&&record.targetValue!==undefined" class="hz-flex-row"
|
||||
style="width:63%;justify-content: flex-end;align-items: center;align-items: center;">
|
||||
<view class="hz-font-color-dark hz-font-12px" style="white-space: nowrap;">{{getTargetValue(record)}}</view>
|
||||
<view class="hz-card-level" style="margin-left:4px;">LV{{record.level}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view style="margin-top:3px;" v-if="record.targetValue!==0&&record.targetValue!==null&&record.targetValue!==undefined">
|
||||
<u-line-progress :percentage="getPercentValue(record)" activeColor="#C39A4B"
|
||||
height="16"></u-line-progress>
|
||||
</view>
|
||||
<view style="margin-top:3px;" v-else>
|
||||
<u-line-progress :percentage="0" activeColor="#C39A4B" height="16"><span
|
||||
style="font-size:10px;padding-left: 10px;">{{getCurrentValue(record)}}</span></u-line-progress>
|
||||
</view>
|
||||
</view>
|
||||
<view v-show="userSegment =='IM'">
|
||||
<view class="im-view-outside">
|
||||
<view class="im-view-inside" style="margin-right:5px;">
|
||||
<view class="im-text-gold">{{formatNumber(MFValue)}}</view>
|
||||
<view class="hz-font-color-dark hz-font-base">MF Turnover</view>
|
||||
</view>
|
||||
<view class="im-view-inside" style="margin-left:5px;">
|
||||
<view class="im-text-gold">{{formatNumber(IMValue)}}</view>
|
||||
<view class="hz-font-color-dark hz-font-base">IM Turnover</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="im-view-outside">
|
||||
<view class="im-view-inside" style="margin-right:5px;">
|
||||
<view class="im-text-gold">{{formatNumber(NFROValue)}}</view>
|
||||
<view class="hz-font-color-dark hz-font-base">NFRO Turnover</view>
|
||||
</view>
|
||||
<view class="im-view-inside" style="margin-left:5px;">
|
||||
<view class="im-text-gold">{{formatNumber(MRIValue)}}</view>
|
||||
<view class="hz-font-color-dark hz-font -base">MRI Turnover</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-card>
|
||||
</view>
|
||||
<uni-card>
|
||||
<view v-for="(record,index) in dashboardData" :key="index" v-show="getShowAchievement(record)"
|
||||
style="margin-top:12px;">
|
||||
<view class="hz-flex-row">
|
||||
<view style="width:37%">
|
||||
<view class="hz-font-color-dark hz-font-base">{{record.itemName}}</view>
|
||||
</view>
|
||||
<view v-if="record.targetValue!==0&&record.targetValue!==null&&record.targetValue!==undefined" class="hz-flex-row"
|
||||
style="width:63%;justify-content: flex-end;align-items: center;align-items: center;">
|
||||
<view class="hz-font-color-dark hz-font-12px" style="white-space: nowrap;">{{getTargetValue(record)}}</view>
|
||||
<view class="hz-card-level" style="margin-left:4px;">LV{{record.level}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view style="margin-top:3px;" v-if="record.targetValue!==0&&record.targetValue!==null&&record.targetValue!==undefined">
|
||||
<u-line-progress :percentage="getPercentValue(record)" activeColor="#C39A4B"
|
||||
height="16"></u-line-progress>
|
||||
</view>
|
||||
<view style="margin-top:3px;" v-else>
|
||||
<u-line-progress :percentage="0" activeColor="#C39A4B" height="16"><span
|
||||
style="font-size:10px;padding-left: 10px;">{{getCurrentValue(record)}}</span></u-line-progress>
|
||||
</view>
|
||||
<view v-if="showKPI">
|
||||
<view class="hz-font-bolder hz-font-xl hz-font-color-black hz-text-left"
|
||||
style="margin-top:36rpx;margin-left:36rpx;">
|
||||
{{$t('dashboard.kpi')}}
|
||||
</view>
|
||||
<view v-show="userSegment =='IM'">
|
||||
<view class="im-view-outside">
|
||||
<view class="im-view-inside" style="margin-right:5px;">
|
||||
<view class="im-text-gold">{{formatNumber(MFValue)}}</view>
|
||||
<view class="hz-font-color-dark hz-font-base">MF Turnover</view>
|
||||
<uni-card>
|
||||
<view v-for="(record,index) in dashboardData" :key="index" v-show="getShowKPI(record)"
|
||||
style="margin-top:12px;">
|
||||
<view class="hz-flex-row">
|
||||
<view style="width:85%">
|
||||
<view class="hz-font-color-dark hz-font-base">{{record.itemName}}</view>
|
||||
</view>
|
||||
<view class="hz-flex-row"
|
||||
style="width:15%;justify-content: flex-end;align-items: center;align-items: center;">
|
||||
<view class="hz-font-color-dark hz-font-12px">{{getTargetValue(record)}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="im-view-inside" style="margin-left:5px;">
|
||||
<view class="im-text-gold">{{formatNumber(IMValue)}}</view>
|
||||
<view class="hz-font-color-dark hz-font-base">IM Turnover</view>
|
||||
<view style="margin-top:3px;">
|
||||
<u-line-progress :percentage="getPercentValue(record)" activeColor="#C39A4B"
|
||||
height="16"><span
|
||||
style="font-size:10px;margin-right:6px;padding-left: 10px;">{{percentFormat(record.currentValue)}}</span></u-line-progress>
|
||||
</view>
|
||||
</view>
|
||||
<view class="im-view-outside">
|
||||
<view class="im-view-inside" style="margin-right:5px;">
|
||||
<view class="im-text-gold">{{formatNumber(NFROValue)}}</view>
|
||||
<view class="hz-font-color-dark hz-font-base">NFRO Turnover</view>
|
||||
</view>
|
||||
<view class="im-view-inside" style="margin-left:5px;">
|
||||
<view class="im-text-gold">{{formatNumber(MRIValue)}}</view>
|
||||
<view class="hz-font-color-dark hz-font -base">MRI Turnover</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-card>
|
||||
<view class="hz-font-bolder hz-font-xl hz-font-color-black hz-text-left"
|
||||
style="margin-top:36rpx;margin-left:36rpx;">
|
||||
{{$t('dashboard.kpi')}}
|
||||
</uni-card>
|
||||
</view>
|
||||
<uni-card>
|
||||
<view v-for="(record,index) in dashboardData" :key="index" v-show="getShowKPI(record)"
|
||||
style="margin-top:12px;">
|
||||
<view class="hz-flex-row">
|
||||
<view style="width:85%">
|
||||
<view class="hz-font-color-dark hz-font-base">{{record.itemName}}</view>
|
||||
</view>
|
||||
<view class="hz-flex-row"
|
||||
style="width:15%;justify-content: flex-end;align-items: center;align-items: center;">
|
||||
<view class="hz-font-color-dark hz-font-12px">{{getTargetValue(record)}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view style="margin-top:3px;">
|
||||
<u-line-progress :percentage="getPercentValue(record)" activeColor="#C39A4B"
|
||||
height="16"><span
|
||||
style="font-size:10px;margin-right:6px;padding-left: 10px;">{{percentFormat(record.currentValue)}}</span></u-line-progress>
|
||||
</view>
|
||||
</view>
|
||||
</uni-card>
|
||||
|
||||
<u-modal :content="msgStr" :show="showMsg" :confirmText="okText" :showCancelButton="false"
|
||||
closeOnClickOverlay @confirm="showMsg=false" confirmColor="#C39A4B"
|
||||
@close="showMsg=false"></u-modal>
|
||||
@@ -127,6 +132,8 @@
|
||||
NFROValue: '0',
|
||||
IMValue: '0',
|
||||
MRIValue: '0',
|
||||
showAchievement: false,
|
||||
showKPI: false,
|
||||
showDashboardView: false,
|
||||
userSegment: null
|
||||
}
|
||||
@@ -149,6 +156,19 @@
|
||||
},
|
||||
|
||||
methods: {
|
||||
normalizeDashboardRecord(record) {
|
||||
record = record || {};
|
||||
return {
|
||||
currentValue: record.currentValue ?? record.CurrentValue,
|
||||
identifier: record.identifier ?? record.Identifier,
|
||||
itemName: record.itemName ?? record.ItemName,
|
||||
level: record.level ?? record.Level,
|
||||
targetValue: record.targetValue ?? record.TargetValue,
|
||||
type: record.type ?? record.Type,
|
||||
userId: record.userId ?? record.UserId,
|
||||
userSegment: record.userSegment ?? record.UserSegment,
|
||||
};
|
||||
},
|
||||
formatNumber(num) {
|
||||
return num?.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") || "0";
|
||||
},
|
||||
@@ -161,39 +181,84 @@
|
||||
let params = {};
|
||||
requestBody = JSON.stringify(params);
|
||||
const res = await getTodoDashboard(params);
|
||||
this.dashboardData = [];
|
||||
this.dataAsOf = "";
|
||||
this.userSegment = null;
|
||||
this.MFValue = this.IMValue = this.NFROValue = this.MRIValue = "0";
|
||||
if (res.data != null && res.success == true) {
|
||||
if(Array.isArray(res.data.records) && res.data.records.length > 0){
|
||||
this.dashboardData = res.data.records;
|
||||
const records = Array.isArray(res.data.records)
|
||||
? res.data.records
|
||||
: Array.isArray(res.data.Records)
|
||||
? res.data.Records
|
||||
: [];
|
||||
if (records.length > 0) {
|
||||
this.dashboardData = records.map((record) => this.normalizeDashboardRecord(record));
|
||||
this.showDashboardView = true;
|
||||
// 设置用户类型
|
||||
this.userSegment = this.dashboardData[0].userSegment;
|
||||
this.hasTargetValue = this.dashboardData[0].targetValue !== null ||this.dashboardData[0].targetValue !== undefined ? true :false;
|
||||
this.hasTargetValue = this.dashboardData[0].targetValue !== null && this.dashboardData[0].targetValue !== undefined;
|
||||
} else {
|
||||
this.dashboardData = [];
|
||||
this.showDashboardView = false;
|
||||
this.dataNull = this.$t("common.noRecord");
|
||||
}
|
||||
if(this.userSegment == 'IM' && this.userSegment !== null){
|
||||
// 重置显示标志
|
||||
this.showAchievement = false;
|
||||
this.showKPI = false;
|
||||
let hasIMValues = false;
|
||||
|
||||
if(this.dashboardData.length > 0){
|
||||
// 检查是否有IM类型的特殊数据
|
||||
if(this.userSegment == 'IM'){
|
||||
for (let i = 0; i < this.dashboardData.length; i++) {
|
||||
if (this.dashboardData[i].itemName == "MF Turnover") this.MFValue = this.dashboardData[i]
|
||||
.currentValue;
|
||||
if (this.dashboardData[i].itemName == "IM Turnover") this.IMValue = this.dashboardData[i]
|
||||
.currentValue;
|
||||
if (this.dashboardData[i].itemName == "NFRO Turnover") this.NFROValue = this.dashboardData[i]
|
||||
.currentValue;
|
||||
if (this.dashboardData[i].itemName == "MRI Turnover") this.MRIValue = this.dashboardData[i]
|
||||
.currentValue;
|
||||
|
||||
if (this.dashboardData[i].itemName == "MF Turnover") {
|
||||
this.MFValue = this.dashboardData[i].currentValue;
|
||||
hasIMValues = true;
|
||||
}
|
||||
if (this.dashboardData[i].itemName == "IM Turnover") {
|
||||
this.IMValue = this.dashboardData[i].currentValue;
|
||||
hasIMValues = true;
|
||||
}
|
||||
if (this.dashboardData[i].itemName == "NFRO Turnover") {
|
||||
this.NFROValue = this.dashboardData[i].currentValue;
|
||||
hasIMValues = true;
|
||||
}
|
||||
if (this.dashboardData[i].itemName == "MRI Turnover") {
|
||||
this.MRIValue = this.dashboardData[i].currentValue;
|
||||
hasIMValues = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 检查是否有DataAsOf类型的数据
|
||||
for (let i = 0; i < this.dashboardData.length; i++) {
|
||||
if (this.dashboardData[i].type == "DataAsOf"){
|
||||
this.dataAsOf = this.dashboardData[i].itemName;
|
||||
}
|
||||
}
|
||||
// 检查是否有Achievement类型的数据
|
||||
if (this.dashboardData[i].type == "Achievement" && this.dashboardData[i].itemName !=="MF Turnover" && this.dashboardData[i].itemName !=="IM Turnover"
|
||||
&& this.dashboardData[i].itemName !=="NFRO Turnover" && this.dashboardData[i].itemName !=="MRI Turnover") {
|
||||
this.showAchievement = true;
|
||||
}
|
||||
// 检查是否有KPI类型的数据
|
||||
if (this.dashboardData[i].type == "KPI") {
|
||||
this.showKPI = true;
|
||||
}
|
||||
}
|
||||
// 如果没有Achievement数据,但有IM用户的四个Value,也要显示卡片
|
||||
if(!this.showAchievement && hasIMValues){
|
||||
this.showAchievement = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.showDashboardView = false;
|
||||
this.showAchievement = false;
|
||||
this.showKPI = false;
|
||||
if(res.errorCode == 'NO_PERMISSION'){
|
||||
this.dataNull = this.$t("todo.noPermission");
|
||||
}else if(res.errorCode == 'INVOKE_TODODASHBOARD_API_ERROR'){
|
||||
this.dataNull = this.$t("todo.invokeError");
|
||||
}else {
|
||||
if(res.errorCode.toUpperCase().indexOf('NO RECORD') != -1){
|
||||
if(String(res.errorCode || res.code || '').toUpperCase().indexOf('NO RECORD') != -1){
|
||||
this.dataNull = this.$t("common.noRecord");
|
||||
}else{
|
||||
this.dataNull = this.$t("todo.returnError");
|
||||
@@ -201,7 +266,9 @@
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
this.showDashboardView = false;
|
||||
this.showAchievement = false;
|
||||
this.showKPI = false;
|
||||
} finally {
|
||||
uni.hideLoading();
|
||||
}
|
||||
@@ -308,4 +375,4 @@
|
||||
.im-text-gold {
|
||||
color: #cfa34f;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
+43
-4
@@ -44,13 +44,13 @@
|
||||
|
||||
<view style="width: 100%;">
|
||||
<u-popup :show="showCommitment" :round="10" mode="center" customStyle="margin:0rpx 40rpx;">
|
||||
<view style="padding: 20px 22px 32px 22px;">
|
||||
<h4 style="font-size: 18px; display: flex; justify-content: center; padding: 7px;">{{commitTitle}}</h4>
|
||||
<view style="height:490px;font-size:13px;color:#333;">
|
||||
<view class="commitment-dialog" style="padding: 20px 22px 32px 22px;">
|
||||
<h4 class="commitment-title" style="font-size: 18px; display: flex; justify-content: center; padding: 7px;">{{commitTitle}}</h4>
|
||||
<view class="commitment-body" style="height:490px;font-size:13px;color:#333;">
|
||||
<view style="margin-bottom: 24rpx;line-height: 1.7;">{{commitmentText1}}</view>
|
||||
<view >{{commitmentText2}}</view>
|
||||
</view>
|
||||
<view >
|
||||
<view class="commitment-footer">
|
||||
<view @click="handleConfirm()" class="hz-btn hz-font-color-white hz-font-lg hz-font-bold hz-text-center" >{{confirmText}}</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -391,6 +391,45 @@
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* #ifdef H5 */
|
||||
.commitment-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
max-height: calc(100vh - 48px);
|
||||
max-height: calc(100dvh - 48px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.commitment-title,
|
||||
.commitment-footer {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.commitment-body {
|
||||
min-height: 0;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
overflow-wrap: anywhere;
|
||||
padding-right: 10px;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
.commitment-body::-webkit-scrollbar {
|
||||
/* uView globally sets scrollbar width to 0 !important. */
|
||||
width: 2px !important;
|
||||
height: 2px !important;
|
||||
display: block;
|
||||
}
|
||||
.commitment-body::-webkit-scrollbar-track {
|
||||
background: #eee;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.commitment-body::-webkit-scrollbar-thumb {
|
||||
background: #a67c30;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.commitment-footer {
|
||||
padding-top: 16px;
|
||||
}
|
||||
/* #endif */
|
||||
.commit-content{
|
||||
line-height: 1.5; /* 增加行间距提升可读性 */
|
||||
color: #333; /* 深灰提升阅读舒适度 */
|
||||
|
||||
@@ -0,0 +1,781 @@
|
||||
<template>
|
||||
<view class="room-calendar-page">
|
||||
<u-navbar
|
||||
:safeAreaInsetTop="true"
|
||||
:placeholder="true"
|
||||
:title="title"
|
||||
:fixed="true"
|
||||
:autoBack="false"
|
||||
leftIcon=""
|
||||
leftIconColor="#C39A4B"
|
||||
bgColor="#C39A4B"
|
||||
titleStyle="font-weight:bold;color:#ffffff;"
|
||||
>
|
||||
<view slot="right" class="calendar-refresh-btn" @click.stop="refreshCalendar">
|
||||
<u-icon name="reload" size="24" color="#ffffff"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<view class="calendar-shell">
|
||||
<view class="property-tabs">
|
||||
<u-tabs
|
||||
:current="selectedPropertyIndex"
|
||||
:scrollable="true"
|
||||
: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="availability"
|
||||
:months="calendarMonths"
|
||||
:weekday-labels="weekdayLabels"
|
||||
:room-types="selectedRoomTypes"
|
||||
:data-map="availabilityMap"
|
||||
:initial-week-id="todayWeekId"
|
||||
></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 { getPropertiesRoomTypes, requestRoomCalendar } from '../../api/roomCalendarApi.js';
|
||||
import { getCalendarSetting as requestCalendarSetting } from '../../api/configApi.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
title: this.$t("roomCalendar.title"),
|
||||
userData: null,
|
||||
selectedPropertyCode: '',
|
||||
selectedRoomTypeCodes: [],
|
||||
selectedOtherPropertyCodes: [],
|
||||
availabilityMap: {},
|
||||
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: {
|
||||
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: '78rpx',
|
||||
padding: '0 24rpx',
|
||||
flexShrink: 0,
|
||||
};
|
||||
},
|
||||
propertyTabActiveStyle() {
|
||||
return {
|
||||
whiteSpace: 'nowrap',
|
||||
color: '#C39A4B',
|
||||
fontFamily: 'Inter-Bold',
|
||||
fontSize: '30rpx',
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
},
|
||||
propertyTabInactiveStyle() {
|
||||
return {
|
||||
whiteSpace: 'nowrap',
|
||||
color: '#111111',
|
||||
fontFamily: 'Inter-Bold',
|
||||
fontSize: '30rpx',
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
},
|
||||
todayWeekId() {
|
||||
return getTodayWeekId(this.calendarMonths);
|
||||
},
|
||||
},
|
||||
onLoad() {},
|
||||
onShow() {
|
||||
this.$i18n.locale = uni.getLocale();
|
||||
this.title = this.$t("roomCalendar.title");
|
||||
this.userData = uni.getStorageSync("userData");
|
||||
this.showTabbarByPermission(this.userData);
|
||||
if (!this.userData || this.userData.canViewCalendar !== true) {
|
||||
this.calendarNoPermission = true;
|
||||
this.calendarReady = false;
|
||||
return;
|
||||
}
|
||||
this.calendarNoPermission = false;
|
||||
this.loadPropertiesRoomTypes();
|
||||
},
|
||||
onUnload() {
|
||||
this.calendarRequestId += 1;
|
||||
this.abortCalendarRequest();
|
||||
},
|
||||
methods: {
|
||||
async loadPropertiesRoomTypes() {
|
||||
if (!this.userData || this.userData.canViewCalendar !== true) {
|
||||
this.showCalendarNoPermission();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.calendarReady = false;
|
||||
uni.showLoading({
|
||||
title: this.$t("common.loading"),
|
||||
});
|
||||
await this.loadCalendarSetting();
|
||||
const res = await getPropertiesRoomTypes({});
|
||||
if (this.isNoPermissionResponse(res)) {
|
||||
this.showCalendarNoPermission();
|
||||
return;
|
||||
}
|
||||
this.propertyList = Array.isArray(res && res.propertyList) ? res.propertyList : [];
|
||||
if (!this.propertyList.length) throw new Error('No calendar properties configured');
|
||||
this.selectedPropertyCode = this.propertyList[0].code;
|
||||
this.selectDefaultOptions();
|
||||
this.buildCalendar();
|
||||
await this.loadAvailabilityData();
|
||||
this.calendarRenderKey += 1;
|
||||
this.$nextTick(() => {
|
||||
this.calendarReady = !this.calendarNoPermission;
|
||||
});
|
||||
} 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.loadAvailabilityData();
|
||||
},
|
||||
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.loadAvailabilityData();
|
||||
return;
|
||||
}
|
||||
if (this.selectedRoomTypeCodes.length === 1) {
|
||||
uni.$u.toast('At least one room type is required');
|
||||
return;
|
||||
}
|
||||
this.selectedRoomTypeCodes.splice(index, 1);
|
||||
this.loadAvailabilityData();
|
||||
},
|
||||
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.loadAvailabilityData();
|
||||
return;
|
||||
}
|
||||
if (this.selectedOtherPropertyCodes.length === 1) {
|
||||
uni.$u.toast('At least one property is required');
|
||||
return;
|
||||
}
|
||||
this.selectedOtherPropertyCodes.splice(index, 1);
|
||||
this.loadAvailabilityData();
|
||||
},
|
||||
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() {
|
||||
if (!this.userData || this.userData.canViewCalendar !== true || this.calendarNoPermission) return;
|
||||
this.ensureSelectedOptionsForRefresh(true);
|
||||
this.loadAvailabilityData();
|
||||
},
|
||||
async loadAvailabilityData() {
|
||||
const records = [];
|
||||
const dateRange = this.getCalendarDateRange();
|
||||
const requestId = this.startCalendarRequest();
|
||||
this.hideCalendarForLoading();
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: this.$t("common.loading"),
|
||||
});
|
||||
if (this.isOtherProperty) {
|
||||
const params = this.buildAvailabilityParams(dateRange);
|
||||
if (!params.Property || !params.RoomType) {
|
||||
this.availabilityMap = {};
|
||||
return;
|
||||
}
|
||||
console.log('[RoomCalendar] request Property:', params.Property, 'RoomType:', params.RoomType);
|
||||
const res = await requestRoomCalendar(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');
|
||||
}
|
||||
|
||||
records.push(...this.buildOtherPropertyRecords(res.data || []));
|
||||
this.availabilityMap = mapRoomCalendarQualificationRecords(records);
|
||||
return;
|
||||
}
|
||||
const allRoomType = this.selectedRoomTypes
|
||||
.map(roomType => roomType.code)
|
||||
.join(',');
|
||||
console.log('[RoomCalendar] request RoomType:', allRoomType);
|
||||
const params = {
|
||||
Property: this.selectedPropertyCode,
|
||||
RoomType: allRoomType,
|
||||
StartDate: dateRange.startDate,
|
||||
EndDate: dateRange.endDate,
|
||||
};
|
||||
const res = await requestRoomCalendar(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');
|
||||
}
|
||||
|
||||
records.push(...(res.data || []));
|
||||
this.availabilityMap = mapRoomCalendarQualificationRecords(records);
|
||||
|
||||
} catch (e) {
|
||||
if (!this.isLatestCalendarRequest(requestId) || this.isRequestAbortError(e)) return;
|
||||
this.availabilityMap = {};
|
||||
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 || res.code) === 'NO_PERMISSION';
|
||||
},
|
||||
showCalendarNoPermission() {
|
||||
this.availabilityMap = {};
|
||||
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;
|
||||
},
|
||||
buildAvailabilityParams(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 {
|
||||
Property: allProperty,
|
||||
RoomType: allRoomType,
|
||||
StartDate: dateRange.startDate,
|
||||
EndDate: dateRange.endDate,
|
||||
};
|
||||
},
|
||||
getUniqueCodes(codes) {
|
||||
return [...new Set(codes.filter(code => code))];
|
||||
},
|
||||
getOtherPropertyRoomTypeCode(propertyCode, roomTypeCode) {
|
||||
return `${propertyCode}_${roomTypeCode}`;
|
||||
},
|
||||
getDefaultOtherPropertyCodes() {
|
||||
const defaultPropertySource =
|
||||
this.currentProperty.defaultProperty ||
|
||||
this.currentProperty.defaultProperties ||
|
||||
this.currentProperty.defaultOtherProperty ||
|
||||
this.currentProperty.defaultOtherProperties ||
|
||||
this.currentProperty.defaultPropertyList ||
|
||||
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 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],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.room-calendar-page {
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - var(--window-bottom));
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.calendar-shell {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
padding: 2rpx 8rpx 0;
|
||||
}
|
||||
|
||||
.property-tabs {
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
padding: 8rpx 0 2rpx;
|
||||
}
|
||||
|
||||
.room-type-grid {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
padding: 8rpx 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>
|
||||
@@ -368,11 +368,12 @@
|
||||
this.$nextTick(() => {
|
||||
try {
|
||||
// pages.json tabBar.list 顺序:
|
||||
// 0 dashboard, 1 todo, 2 hotel(findPlayer), 3 setting
|
||||
// 0 dashboard, 1 todo, 2 hotel(findPlayer), 3 calendar, 4 setting
|
||||
uni.setTabBarItem({ index: 0, text: this.$t("dashboard.title") });
|
||||
uni.setTabBarItem({ index: 1, text: this.$t("todo.title") });
|
||||
uni.setTabBarItem({ index: 2, text: this.$t("hotel.title") });
|
||||
uni.setTabBarItem({ index: 3, text: this.$t("setting.title") });
|
||||
uni.setTabBarItem({ index: 3, text: this.$t("roomCalendar.title") });
|
||||
uni.setTabBarItem({ index: 4, text: this.$t("setting.title") });
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user