最近在做项目的时候有个需求是通过循环出来多行时间段选择的选择器进行时间段选择的时候需要保证每个时间段之间的时间不能有交叉的情况,这里边的每个时间段是包括开始、结束时间的,图例如下所示:
我这里使用的是element-ui中的 el-time-select 选择器去实现的,下边是具体的结构代码:
<el-form
ref="yawForm"
:label-position="right"
:model="yawForm"
:inline="true"
style="height: 450px; overflow:auto;"
size="small"
@submit.native.prevent
>
<div
v-for="(item, index) in yawForm.venicleYawList"
:key="index"
>
<el-form-item
:prop="'yawList.' + index + '.time'"
class="secondCl"
label="时间段"
>
<el-time-select
v-model="item.timeStartSlot"
:picker-options="{
start: '00:00',
step: '00:30',
end: '24:00',
maxTime: item.timeEndSlot
}"
:clearable="false"
style="margin-left: 14px; width: 95px; height: 32px;"
class="time-select"
placeholder="起始时间"
@change="checkTimeOverlap(item,index)"
/>
<el-time-select
v-model="item.timeEndSlot"
:picker-options="{
start: '00:00',
step: '00:30',
end: '24:00',
minTime: item.timeStartSlot
}"
:clearable="false"
style="margin-left: 5px; width: 95px; height: 32px;"
class="time-select"
placeholder="结束时间"
@change="checkTimeOverlap(item,index)"
/>
</el-form-item>
<el-divider
class="alarmDivider"
style="height:1px; width: 580px; color: #e6e6e6;"
/>
</div>
<div
class="addbtn"
@click="addVehicleYawAlarm">
<div style="margin: auto; display: flex;">
<span style="font-size: 20px; display: inline-block; line-height: 31px;">+</span>
<div class="div-text">添加</div>
</div>
</div>
</el-form>
具体的样式我就不往这里贴了,可根据自己的需求自己去设置相应的样式,我这里设置了默认可选择的开始时间和结束时间,(开始时间必须是比结束时间小,结束时间必须比开始时间大),
这里的时间大小可能不同的人有不同的歧义,这个不重要,这里给个例子吧,如下:
比如开始时间选择了 01:00 那么结束时间就必须是 02:00、 03:00、 04:00、 05:00 ...
如果先选择了结束时间 21:00,那么开始时间就必须为 20:00、19:00、18:00、17:00...
这样应该就很明了了,我这里的时间选项间隔是30分钟,这个可根据需求自行更改。
然后就是给开始时间结束时间都绑定了 change 事件 @change="checkTimeOverlap(item,index)"
把当前对象和当前的下标传递到方法中去,接下来我们看方法:
// 校验时间段是否有交叉
checkTimeOverlap (currentItem, currentIndex) {
if (!currentItem.timeStartSlot || !currentItem.timeEndSlot) return
for (let i = 0; i < this.yawForm.wayYawList.length; i++) {
if (i !== currentIndex) {
const otherItem = this.yawForm.wayYawList[i];
if (
(currentItem.timeStartSlot >= otherItem.timeStartSlot &&
currentItem.timeStartSlot < otherItem.timeEndSlot) ||
(currentItem.timeEndSlot > otherItem.timeStartSlot &&
currentItem.timeEndSlot <= otherItem.timeEndSlot) ||
(currentItem.timeStartSlot < otherItem.timeStartSlot &&
currentItem.timeEndSlot > otherItem.timeEndSlot)
) {
this.$message.error('时间段有交叉,请重新选择!');
this.yawForm.wayYawList[currentIndex].timeStartSlot = '';
this.yawForm.wayYawList[currentIndex].timeEndSlot = '';
return;
}
}
}
},
以下是判断逻辑的详细解释:
-
第一个条件:
currentItem.timeStartSlot >= otherItem.timeStartSlot && currentItem.timeStartSlot < otherItem.timeEndSlot
这个条件表示,如果当前时间段(currentItem)的起始时间大于等于其他时间段(otherItem)的起始时间,并且当前时间段起始时间小于其他时间段结束时间,那么这两个时间段就有可能重叠。 -
第二个条件:
currentItem.timeEndSlot > otherItem.timeStartSlot && currentItem.timeEndSlot <= otherItem.timeEndSlot
这个条件表示,如果当前时间段(currentItem)的结束时间大于其他时间段(otherItem)的起始时间,并且当前时间段结束时间小于等于其他时间段结束时间,那么这两个时间段也有可能重叠。 -
第三个条件:currentItem.timeStartSlot < otherItem.timeStartSlot && currentItem.timeEndSlot > otherItem.timeEndSlot 这个条件表示,如果当前时间段currentItem)的开始时间小于其它时间段(otherItem)的起始时间,并且当前时间段结束时间大于其它时间的结束时间,那么这两个时间段也有可能重叠。
-
这里for循环外边的if条件是必须的,不加这个条件如果用户先是选择了结束时间,时间如果符合以上三个条件中的一种就选择不了,因为先选择结束时间那么开始时间就是空,空字符串跟时间比肯定是空字符串小,所有这个条件是必要的。
综合以上两个条件,如果(1,2,3)任何一个条件成立,就说明两个时间段有重叠。
我这里的需求就是如果有交叉直接给当前选择的时间置为空并且给出相应的提示,这里可以根据自己的需要进行调整。