为满足复杂的业务需求,如在线订房,选择入住离店日期。
不考虑业务的情况下,可以先构造符合日历,满足n个月,且月份上下滚动切换
后端数据传入,先与日期数据进行匹配,进行覆盖和赋值,再依据业务要求设置日期状态。最后完成复杂的业务交互。
构造n个月日历数据
// 组装n个月的日期
getDateOfNextMonth() {
let data = [];
let day = new Date();
let y = day.getFullYear();
let m = day.getMonth() + 1;
if (m < 10) { m = '0' + m; }
let d = day.getDate();
let dayTime = new Date(y +'-'+ m +'-'+ d).getTime(); // 当前时间戳
let date = y +'-'+ m;
let lastDay = (new Date(new Date(y,m,1).getTime()-1000*60*60*24)).getDate();//获取当月最后一天日期
data.push({
day: date,
getLastDay: lastDay,
})
// monthNum-1为月数,这里是多一个月展示(业务需要)
for (let i=0; i<this.monthNum; i++) {
day = i == 0 ? day: new Date(data[i].day)
m = parseInt(m) + 1; //获取下个月的月份
if (m == 13) {
y = parseInt(y) + 1; //获取下个月的年份
m = 1;
}
if (m < 10) {
m = '0' + m;
}
date = y + '-' + m;
let lastDay = new Date(y,m,1); //取当年当月中的第一天
lastDay = (new Date(lastDay.getTime()-1000*60*60*24)).getDate();//获取当月最后一天日期
data.push({
day: date,
getLastDay: lastDay,
})
}
this.DateOfNextMonth = data;
for (let i=0; i<data.length; i++) {
this.getNearlyMonths(data[i].day, data[i].getLastDay, dayTime)
}
},
// 获取近月份数据
getNearlyMonths(date, getLastDay, dayTime) {
let data = [];
for (let i=1; i<getLastDay+1; i++) {
let index = i.toString().length == 1 ? '0'+ i : i;
// 组装数据处理
data.push({
date: date +'-'+ index,
state: 8,//默认置灰,无任何状态
quantity: 0,//默认库存10
displayType: 0,//默认正常可选
addPrice: 0,//默认加收0
checkState:1//默认未选中
});
}
this.$set(this.resultData, date, data)
},
//拿到日历房数据
getCalenderData() {
this.getDateOfNextMonth();
/**
* 页面加载完成后,处理3件事情,
* 1,请求拿到n个月的数据;
* 2,处理这些数据,变成我们需要的结构;
* 3,处理初始化默认入住和结束
* 得到resultData后,处理priceItems得到日历数据
* 每个日期对象,除保留原有的属性外,追加一个state状态
* 0空块 -1不可点(灰色日期) 1可点(普通样式) 6满房 7 displayType决定置灰 8 后端未返回的日期
* 追加checkState状态,表示选中情况
* 1 可选的 2入住(入住样式) 3中间选中 4离店样式 5非酒店类型单选选中 6非酒店类型多选起 7非酒店类型多选止
*/
const priceItems = this.resultData;
const monthArr = Object.keys(priceItems);
monthArr.forEach((month, monthIndex) => {
priceItems[month].forEach(item => {
// 判断节假日
let day = new Date(item.date).getDate()
item.day = day; // 用于显示在日历中间的日期/节日
item.week = new Date(item.date).getDay(); // 用于补充头部空块
})
// 这里要找出这个日历哪一天是今天
if (new Date(priceItems[month][0].date).getMonth() === new Date().getMonth()) { // 首先要判断该月是不是本月
// 设置默认可选的开始日期
const todayIndex = priceItems[month].findIndex(v => new Date(v.date).getDate() === new Date().getDate());
priceItems[month][todayIndex].day = '今天';
}
// 判读月份的第一天是周几,前面对应补充空白块(只要第一天不是周日,就需要补空白块)(处理state 0)
const firstDayWeek = priceItems[month][0].week;
if (firstDayWeek > 0) {
for (let i = 0; i < firstDayWeek; i++) {
priceItems[month].unshift({
state: 0
}) // 从数组头部插入空块
}
}
});
this.calendarData = priceItems;
},
根据后端接口设置日期状态
//遍历calendarData,赋值接口数据,设置入住和离店信息样式
addPriceToCa(cl) {
let keyList=[]
let key=[]
Object.keys(cl).forEach(res => {
cl[res].forEach((data, index) => {
this.priceItems.forEach(item => {
if (data.date == item.date) {
this.$set(data, 'addPrice', item.addPrice);
this.$set(data, 'displayType', item.displayType);
this.$set(data, 'quantity', item.quantity);
this.$set(data, 'checkState', 1);
this.$set(data, 'state', 1);//匹配上的先变为1
//满房
if (data.quantity===0) {
data.state=6
}
//不可约,免预约,不显示
if(data.displayType!==0){
data.state=7
}
}
//区间类有区间
if(this.startDate<=data.date&&data.date<=this.endDate){
if(!keyList.includes(data.date)){
keyList.push(data.date)
this.checkDayList.push(data)
}
}
//非区间类有开始日期
if(this.startDate===data.date&&!this.isPeriod&&!this.endDate){
if(!key.includes(data.date)){
key.push(data.date)
this.checkDayList.push(data)
}
}
});
//将今天日期所在之前的时间设置为灰色
const date = new Date();
const nowDay=date.getFullYear()+'-'+(date.getMonth() + 1)+'-'+date.getDate();
if(new Date(data.date).getTime()<new Date(nowDay).getTime()) {
data.state = -1;
}
});
})
//显示状态 设置入住离店以及区间样式
this.setDateCheckState()
},