每个会议室可以设置开始时间和结束时间,最小预约时间(15分钟,30分钟,60分钟)也就是每个小方块代表的时间,选择两个非连续的时间块时,如果中间没有已经被预约的时间段则中间所有的时间段都会被选中
<div class="container_body" v-for="(obj,index) in tableData" :key="index+'tables'">
<div style="flex: 0 0 100px;">{{(page.currentPage-1)*page.pageSize + (index+1)}}</div>
<img :src="obj.conferenceImg" width="200px" style="border-radius: 10px;flex: 0 0 200px;" />
<div class="container_body_desc">
<p>{{obj.conferenceName}}</p>
<p>可容纳人数:{{obj.limitMaxCount}}</p>
<p>会议室地点:{{obj.conferenceLocation}}</p>
<p>
<span v-for="(v,i) in obj.conferenceDesc" :key="i">{{v}}</span>
</p>
</div>
<div class="container_body_time">
<div v-for="(item,index) in obj.arr" :key="index+'arrc'">
<p>{{item.startNodeTime}}</p>
<p class="times" v-for="(v,i) in item.stepArr" :key="i" :class="getDisabled(v) && !v.isReserved ? 'disabledClass' : ''">
<el-tooltip
effect="dark"
:disabled="!v.isReserved"
placement="bottom-end">
<template slot="content">
<div>
<div>会议主题:{{showContent(obj,v).subject}}</div>
<div>会议时间:{{showContent(obj,v).meetingTime}}</div>
<div>申请人:{{showContent(obj,v).applicatEmpName}}</div>
</div>
</template>
<span
:class="{'disabledEventClass': getDisabled(v) && !v.isReserved,'reservedClass' : v.isReserved,'activeClass' : getSelected(v)}"
@click.stop="timeClick(v,obj)"
@dblclick="itemDblclick(obj)">
</span>
<i v-if="getDisabled(v) && !v.isReserved" class="iconfont icon-jinyong1"></i>
</el-tooltip>
</p>
<p>{{item.endNodeTime}}</p>
</div>
</div>
</div>
onLoad(){
let timeNodeArr = []
d.pageData.records.forEach(v => {
v.conferenceDesc = v.conferenceDesc ? v.conferenceDesc.split(',') : []
let startTime = new Date(v.startTime).getTime() ,
endTime = new Date(v.endTime).getTime(),
reserveMinTime = d.system.reserveMinTime;// 配置的最小预约时间
let diff = endTime - startTime;
let step = reserveMinTime*60*1000;
let arr = []
for(let i= 0,index = 0;i < diff;i+=60*60*1000,index++){
arr[index] = {
startNodeTime:moment(startTime+i).format('HH:mm'),
endNodeTime:moment(startTime+i+60*60*1000).format('HH:mm')
}
for(let j=i+step; j<=i+60*60*1000; j+=step){
if(!arr[index].stepArr){
arr[index].stepArr = []
}
let time = moment(startTime+j).format('HH:mm')
arr[index].stepArr.push({
id:j,
isReserved:v.meetingTimeStep.includes((startTime+j)/1000 +'') ? true : false,
time,
parentId:v.id
})
timeNodeArr.push(new Date(moment().format('YYYY-MM-DD') + ' ' +time+':00').getTime())
}
}
v.arr = arr;
})
this.tableData = d.pageData.records;
this.timeNodeArr = timeNodeArr;
}
// 当前时间之前的时间块禁用
getDisabled(val){
let time = this.meetingDay +' '+val.time+':00';
return new Date().getTime() >= new Date(time).getTime()-this.systemCfg.reserveMinTime*60*1000
},
// 判断当前选择的时间
getSelected(val){
let time = moment().format('YYYY/MM/DD')+' '+val.time+':00';
return this.selectedArr.findIndex(item => item.time === new Date(time).getTime() && item.parentId === val.parentId) < 0 ? false : true
}
// 单击事件
timeClick(val,obj){
clearTimeout(this.timer);
this.timer = setTimeout(() => {
if(val.parentId != this.activeId){
this.selectedArr = []
this.activeId = val.parentId
}
if(!val.isReserved && val.parentId){
// 当前选中的时间不在已选择列表中
if(!this.getSelected(val)){
let arr = [...this.selectedArr]
arr.push({
parentId:val.parentId,
time:new Date(moment().format('YYYY-MM-DD') + ' ' +val.time+':00').getTime()
})
arr = arr.sort((a,b) => a.time - b.time)
let arr1 = [...arr]
this.timeNodeArr.forEach(v => {
if(v > arr[0].time && v < arr[arr.length-1].time){
arr1.push({
parentId:val.parentId,
time:v
})
}
})
// 已预定时间数组,到秒
let meetingTimeStep = obj.meetingTimeStep;
if(meetingTimeStep.length){
// 判断已选择列表中是否含有已预定时间
let index = arr1.findIndex(v => v.time/1000 == meetingTimeStep[0])
// 大于0表示存在已预定时间,则已选时间列表等于当前选择时间
if(index > 0){
this.selectedArr = [{parentId:val.parentId,time:new Date(moment().format('YYYY-MM-DD') + ' ' +val.time+':00').getTime()}]
return;
}
}
this.selectedArr = arr1.sort((a,b) => a.time - b.time).filter( (element, index, array) => {
return array.findIndex(ele => element.time === ele.time) === index
})
}else{
// 当前选择时间已在选择列表中时,将当前时间之后的时间清空
let arr = [...this.selectedArr]
if(arr.length === 1){
this.selectedArr = []
return;
}
let time = new Date(moment().format('YYYY-MM-DD') + ' ' +val.time+':00').getTime()
arr.splice(arr.findIndex(ele => ele.time === time)+1)
this.selectedArr = arr
}
}
},300)
},
// 鼠标双击事件
itemDblclick(val){
clearTimeout(this.timer);
let startTime = this.selectedArr[0].time,endTime = this.selectedArr[this.selectedArr.length-1].time;
let start = moment(startTime-this.systemCfg.reserveMinTime*60*1000).format('HH:mm');
let end = moment(endTime).format('HH:mm')
let diff = (endTime - startTime + this.systemCfg.reserveMinTime*60*1000)/1000/60
this.$confirm(`${start}-${end} ${diff}分钟`, {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
let form = {...this.systemCfg,start,end,roomId:this.activeId,isRequireTask:val.isRequireTask,date:this.meetingDay}
this.$refs.InitiateMeetingRef.openDialog(form)
}).catch(() => {
this.selectedArr = [];
})
},
computed:{
nextDisabled(){
return new Date(moment(this.meetingDay).endOf('day')).getTime() < new Date(moment().add(this.reserveTimeLimit,'days').endOf('day')).getTime() ? false : true
}
}
.container_body{
display: flex;align-items: center;text-align: center;padding: 10px;font-size: 14px;border-bottom: 1px solid #e8eaec;
&_desc{
flex: 0 0 240px;text-align: left;margin: 0 15px;
p:nth-child(1){
font-weight: 600;
font-size: 16px;
}
p:nth-child(4){
margin: 0;
span{
padding: 6px 10px;margin: 0 10px 6px 0;border: 1px solid #e8eaec;border-radius: 6px;display: inline-block;
}
}
}
&_time{
flex: 1;display: flex;align-items: center;margin-right: 10px;
&>div{margin: 0 10px;}
p{
margin: 5px auto;
}
.times{
width: 30px;height: 30px;cursor: pointer;position: relative;
span{
background-color: #7ce37a;width: 30px;height: 30px;cursor: pointer;display: inline-block;border-radius: 6px;
}
i{
position: absolute;top: -2px;left: -1px;color: #ccc;font-size: 33px;
}
}
.disabledClass{
cursor: not-allowed;
}
.disabledEventClass{
pointer-events: none;
}
.activeClass{
background-color: #0073EB !important;
}
.reservedClass{
background-color: #FF0000 !important;
}
}
}