一、需求:实现类似钉钉会议室预约功能的列表功能
二、功能介绍:钉钉会议室列表会展示早上7点到晚上11点的会议室预约情况。实际需求是24小时的预约情况,会议室预约时间以半小时为间隔
三、分析:预约的时间是多个时间段组成的数组,后端会返回一天内预约的每个时间段的开始时间和接结束时间,首先将24小时 以半小时拆分成48个div,对每个div赋予不同的颜色。赋予颜色分为三种情况,未预约,已预约,已过期。当某个时间段内状态重合,以已预约为最高优先级展示。之后再以状态可以分为三个模块。昨天之前 、今天、明天之后,昨天之前:存在两种状态--已过期和已预约,今天存在三种状态--已过期,已预约,未预约,明天之后存在两种状态--未预约已预约。
四、实际实现:前端追寻一个宗旨,数据驱动页面。需要梳理数据格式,对于后端返回的时间段是某一天预约的时间段,需要将后端返回的时间段数据转化为48个包含每半小时的状态数据。
五、步骤分析:
1.需要获取当前年月日,判断所选择的是否是昨天还是今天还是明天。
2.获取当天小时,处于24小时的那个位置,对应着48个div的哪个index。
3.初始化48个div,给定基础type对象状态为0,代表着未预约。
4.遍历返回的数据源,分为两种情况。
4.1当返回的预约时间段为空数组时,意味着该会议室没有预约。当选择的年月日为昨天之前时,需要将48个div的type赋值为2,代表已过期。当选择的年月日是今天时,需要小于目前小时的type变为2为已过期。因为初始化就代表着未预约,因为返回的时间段数据为空,所以不需要考虑未来时间为空数组的情况。
4.2当返回的预约时间段有数据时,再进行遍历预约时间段,将时间依据是整点还是半点。对开始时间和结束时间赋值(比如返回的13点转换后为26,14点半转换为29),这样就对返回的每个预约时间段,都转化为数据类型。先判断年月日是大前提,之后再比较当前24小时,对应着给type赋值。
六、根据处理好的数据,根据type对48个div赋值,这样就完成了会议室预约信息展示。对于这个需求,把前端的数据驱动页面体现出来了,如果不这样处理数据单独的根据后端返回的预约时间段很难去区分展示。这样做前端实现太麻烦,后端可能会把数据梳理的更好一些,但有时候就会面对这些。
七、代码实现
saveMeetingRoom: (state, data) => {
// 获取时间---年月日
let getNowTime = moment(new Date()).format('YYYY-MM-DD')
let getPreTime = moment(state.selectPreDate).format('YYYY-MM-DD')
let isBefore= moment(getPreTime).isBefore(getNowTime) // 判断选择的时间在当前时间之后
// 获取当前时间--获取24小时
let nowDate = moment(new Date()).format('HH:mm')
let transDate = 0
if(nowDate.split(':')[1] == '00') {
transDate = (Number(nowDate.split(':')[0])*2)
}else if(nowDate.split(':')[1] <= 30) {
transDate = (Number(nowDate.split(':')[0])*2 +1)
}else {
transDate = (Number(nowDate.split(':')[0])*2 +2)
}
// 修改数据源
let transData = JSON.parse(JSON.stringify(data.payload.data))
// 初始化列表状态,根据状态不同渲染不同颜色--默认是未预约状态
let initData = [
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
{ type: 0 },
]
transData.forEach(item => {
// 如果为空数组,代表没有预约,只存在两种状态,获取当前时间,小于之前的时间代表失效,改变状态
let tranInitData = JSON.parse(JSON.stringify(initData))
if(item.appointmentList.length == 0) {
if(getNowTime != getPreTime && isBefore) { // 当选择的日期是当前之前--都是已过期
tranInitData.forEach((t, i) => {
t.type = 2
})
}else if(getNowTime == getPreTime){ // 当选择的是今天--比较小时数,已过期的时间更改状态
tranInitData.forEach((t, i) => {
if (i < transDate) {
t.type = 2
}
})
}
item.appointmentList = [...tranInitData]
}else{
/*
startTime: 预约开始时间
endTime: 预约结束时间
*/
let tranInitData = JSON.parse(JSON.stringify(initData))
item.appointmentList.forEach(item => {
let startTime = moment(item.meetingStartTime).format('HH:mm')
let endTime = moment(item.meetingEndTime).format('HH:mm')
let transStartTime = 0
let transEndTime = 0
if(startTime.split(':')[1] != '00') {
transStartTime = (Number(startTime.split(':')[0])*2 + 1)
}else{
transStartTime = (Number(startTime.split(':')[0]) *2)
}
if(endTime.split(':')[1] != '00') {
transEndTime = (Number(endTime.split(':')[0])*2 + 1)
}else {
transEndTime = (Number(endTime.split(':')[0]) *2)
}
if(getNowTime == getPreTime) { // 选择的时间是今天,存在3种状态,存在三种状态--已过期--已预约--未预约
tranInitData.forEach((t, i) => {
if (i < transDate ) { // 过期时间
t.type = 2
}
if (transStartTime <= i + 1 && transEndTime > i + 1) { // 预约时间
t.type = 1
}
})
}
if(getNowTime != getPreTime && isBefore){ // 选择时间是已过期的日期,存在两种状态--已过期--已预约
tranInitData.forEach((t, i) => {
t.type = 2
if (transStartTime <= i + 1 && transEndTime > i + 1) {
t.type = 1
}
})
}
if(!isBefore) { // 选择的时间是未来时间,存在两种状态--未预约--已预约
tranInitData.forEach((t, i) => {
if (transStartTime <= i + 1 && transEndTime > i + 1) {
t.type = 1
}
})
}
})
item.appointmentList = [...tranInitData]
}
})
return (state = {
...state,
meetRoomList: transData,
})
},