基于Layui的多级联动时间控件(laydate开始时间和结束时间联动,含日期控制)
0 引言
近期,跟随团队做项目,项目前端基于Layui框架开发,(插一句使用框架真的比自己写原生HTML+CSS舒服多了),项目中有一个时间控件的需求,一般项目常用的就是选取一个时间日期就完了,但是这个项目的时间控件需要考虑开始时间和结束时间的相互联动,即多个(本文是三个时间控件-日期控件、开始时间控件及结束时间控件相互限制,层级联动)。
1 示例
比如,当我选择了当前日期为当天后,开始时间控件的可选时间节点必须是当前时间之后(即当前时间之前不可选了),选取开始时间后需要限制结束时间必须在开始时间之后,本项目需求是结束时间必须必开始时间晚十分钟。
2 需求细化
(1)开始时间和结束时间每天可选的最大最小时间为凌晨1点-23点;
(2)当选取的时间和当天时,开始时间自动调整之后当前时间之后的时间节点可选;
(3)结束时间必须在开始时间后10分钟;
(4)开始和结束时间无需选择秒,分钟单位间隔为10;
(5)当出现开始时间比当天系统时间更小时或结束时间比开始时间更小时需要错误提示;
Tips:以上需求大部分LayUI的时间控件均无法直接满足,需要通过逻辑设计或修改CSS达到
3 实现
3.1 引入基本控件(laydate)
Html代码:
<div class="layui-form-item layui-row layui-col-space10">
<div class="layui-col-xs4">
<label for="mDate" class="layui-form-label">会议日期</label>
<div class="layui-input-block">
<input type="text" class="layui-input" name="mDate" id="mDate"
autocomplete="off" placeholder="请选择会议日期" lay-verify="required|date">
</div>
</div>
<div class="layui-col-xs4">
<label class="layui-form-label" for="mDateStartTime" >开始时间</label>
<div class="layui-input-block">
<input class="layui-input" placeholder="选择开始时间" name="mDateStartTime" id="mDateStartTime"
autocomplete="off" lay-verify="required|time" >
</div>
</div>
<div class="layui-col-xs4">
<label class="layui-form-label" for="mDateEndTime">预计结束时间</label>
<div class="layui-input-block">
<input class="layui-input" placeholder="请选择预计结束时间" name="mDateEndTime" id="mDateEndTime"
autocomplete="off" lay-verify="required|time">
</div>
</div>
</div>
Js处理
(Tips:这部分可以参考LayUI文档即可实现,这里只做演示,详细还是见下面完整代码,https://www.layui.com/doc/modules/laydate.html)
<script src="laydate.js"></script> //导入laydate.js脚本响应处理
laydate.render({
elem: '# mDate ' //指定要响应的时间控件id – mDate、mDateStartTime、mDateEndTime
});
3.2 实现LayUI分钟间隔10分钟且不可点击秒数
这部分,笔者尝试去查阅了文档,原本以为,layui文档这个需求会提供配置,找了一圈最后还是没有找到,最后只好自己通过“粗暴”的做法实现了这个需求。做法,通过CSS样式的nth-child强制隐藏秒数部分,间隔10分钟也是一样的。
代码如下:(时分宽度各占50%,即把整个控件吃满,同时秒的li设置为隐藏)
<style type="text/css">
.laydate-time-list > li:nth-child(1){
width: 50%;
}
.laydate-time-list > li:nth-child(2){
width: 50%;
}
.laydate-time-list > li:nth-child(2) > ol > li{
display: none;// 处理间隔10分钟
}
.laydate-time-list > li:nth-child(2) > ol > li:nth-child(10n+1){
display: block; // 处理间隔10分钟,每10的整分数就显示
}
.laydate-time-list > li:nth-child(3){
display: none !important;
}
.error-tips{
border: solid 1px red;
}
</style>
3.3 日期和开始结束时间范围限制
日期可选范围:半个月之内可选
开始结束时间:1-23点
<script src="${pageContext.request.contextPath}/UIAdmin/layui/layui.js"></script>
<script>
layui.config({
base: '${pageContext.request.contextPath}/UIAdmin/' //静态资源所在路径
}).extend({
index: 'lib/index', //主入口模块
comm: 'lib/CommonFunction',
pullDwonPartTree:'lib/extend/pullDwonPartTree'
}).use(['index', 'comm', 'jquery', 'layer', 'form','laydate'], function () {
var $ = layui.jquery
, form = layui.form
, laydate = layui.laydate
,layer=layui.layer
, comm = layui.comm;
// 限制开始结束时间最大最小值
var min = "01:00:00",
max = "24:00:00";
var selectday = laydate.render({
elem: '#mDate' //指定元素
,min: 0//7天前
,max: 15 //15天后
,trigger: 'click'
,done: function(value, date){}
});
// 开始时间配置
var start =laydate.render({
elem: '#mDateStartTime' //指定元素
,type: 'time'
,trigger: 'click'
,format: 'HH:mm:ss'
,min: min
,max: max
,btns: ['clear', 'confirm']
,done: function(value, date){}
});
// 结束时间
var end = laydate.render({
elem: '#mDateEndTime' //指定元素
,type: 'time'
,trigger: 'click'
,format: 'HH:mm:ss'
,min: min
,max: max
,btns: ['clear', 'confirm']
,done: function(value, date){}
});
(1)日期如为当天,则开始时间必须为大于系统当前时刻;
(2)结束时间必须大于开始10分钟以后;
(3)如果上述不满足,则需要错误提示,即在控件上添加红色标识;
处理逻辑上,选择了日期就要判断当前日期是否当天,如果是当天则需要限定开始时间的可选范围;选取开始时间后,就同样需要限制结束时间的可选范围;同理,如果先选择了结束时间,那么他要反向限制开始时间。这些操作均在layui提供的时间中间中的done:function(){}中,即控件选取后要执行的动作,而我们限制范围本来就是通过min、max值控制的,这里要注意的是,因为要知道我们要控制的是哪个控件,所以每一个控件都定义成了变量,如开始时间 var start =laydate.render({ …})
<script src="${pageContext.request.contextPath}/UIAdmin/layui/layui.js"></script>
<script>
layui.config({
base: '${pageContext.request.contextPath}/UIAdmin/' //静态资源所在路径
}).extend({
index: 'lib/index', //主入口模块
comm: 'lib/CommonFunction',
pullDwonPartTree:'lib/extend/pullDwonPartTree'
}).use(['index', 'comm', 'jquery', 'layer', 'form','laydate'], function () {
var $ = layui.jquery
, form = layui.form
, laydate = layui.laydate
,layer=layui.layer
, comm = layui.comm;
// 限制开始结束时间最大最小值
var min = "01:00:00",
max = "24:00:00";
var selectday = laydate.render({
elem: '#mDate' //指定元素
,min: 0//7天前
,max: 15 //15天后
,trigger: 'click'
,done: function(value, date){
var isRealTime = true;
var curDate = new Date();
var month = curDate.getMonth()+1;
month = month > 9 ? month : '0' + month;
var day = curDate.getDate();
day = day > 9 ? day : '0' + day;
var h = curDate.getHours();
var sh = h > 9 ? h : '0' + h;
var mi = curDate.getMinutes();
var smi = mi > 9 ? mi : '0' + mi;
var today = curDate.getFullYear()+ '-' + month + '-' + day;
// 判断当前选时间是否为当天
if (today==value){
//处理小时
if (h >= 1){
// 当天可选最小时间为当前时间
start.config.min.hours = h;
// start.config.min.minutes = mi;
}
// 结合开始时间 判断选择的时间是否比当前时间
if ($("#mDateStartTime").val()!=""|| $("#mDateEndTime").val()!=""){
var startTime = $("#mDateStartTime").val();
var endTime = $("#mDateEndTime").val();
var systemTime = sh+":"+smi+":"+"00";
if (endTime!="" && endTime<=systemTime){
isRealTime=false;
layer.msg("会议选择时间异常!会议预约时间必须大于当前时刻", function () {
return false;
});
$("#mDateStartTime").addClass("error-tips");
$("#mDateEndTime").addClass("error-tips");
$("#mDate").addClass("error-tips");
}else if(startTime!="" && startTime<=systemTime){
isRealTime=false;
layer.msg("会议选择时间异常!会议预约开始时间必须大于当前时刻", function () {
return false;
});
$("#mDateStartTime").addClass("error-tips");
$("#mDate").addClass("error-tips");
}
}
}else{
start.config.min.hours = 1;
}
if (isRealTime){
$("#mDateStartTime").removeClass("error-tips");
$("#mDateEndTime").removeClass("error-tips");
$("#mDate").removeClass("error-tips");
}
}
});
// 开始时间
var start =laydate.render({
elem: '#mDateStartTime' //指定元素
,type: 'time'
,trigger: 'click'
,format: 'HH:mm:ss'
,min: min
,max: max
,btns: ['clear', 'confirm']
,done: function(value, date){
var selStartH = date.hours;
var selStartM = date.minutes;
// 判断当前选择时间是否超过系统时间
var isRealTime = true;
var selectDay = $("#mDate").val();
var startTime = value;
var endTime = $("#mDateEndTime").val();
if (selectDay !=""){
var curDate = new Date();
var month = curDate.getMonth()+1;
month = month > 9 ? month : '0' + month;
var day = curDate.getDate();
day = day > 9 ? day : '0' + day;
var h = curDate.getHours();
var sh = h > 9 ? h : '0' + h;
// 处理4小时内
var ah = curDate.getHours()+4;
var sah = ah > 9 ? ah : '0' + ah;
var mi = curDate.getMinutes();
var smi = mi > 9 ? mi : '0' + mi;
var today = curDate.getFullYear()+ '-' + month + '-' + day;
if (today==selectDay){
var systemTime = sh+":"+smi+":"+"00";
var foursystemTime = sah+":"+smi+":"+"00";
if (endTime!="" && endTime<=systemTime){
isRealTime=false;
layer.msg("会议选择时间异常!会议预约时间必须大于当前时刻", function () {
return false;
});
$("#mDateStartTime").addClass("error-tips");
$("#mDateEndTime").addClass("error-tips");
$("#mDate").addClass("error-tips");
// }else if(startTime<=systemTime){
}else if(startTime<=systemTime){
isRealTime=false;
layer.msg("会议选择时间异常!会议预约开始时间必须大于系统当前时刻!", function () {
return false;
});
$("#mDateStartTime").addClass("error-tips");
$("#mDate").addClass("error-tips");
}
}
}
if(endTime!="" && endTime<=startTime){
isRealTime=false;
layer.msg("会议选择时间异常!会议预约结束时间必须大于开始时间", function () {
return false;
});
$("#mDateStartTime").addClass("error-tips");
$("#mDateEndTime").addClass("error-tips");
}
// 开始时间处理完之后 处理结束时间,一个会议时间间隔至少10分钟,
var endPreM = selStartM+10;
var endPreH = selStartH;
if (50<endPreM && endPreM<=60){
endPreH = selStartH+1;
endPreM = 0;
}
if(60<endPreM){
endPreH = selStartH+1;
endPreM = 10;
}
// 设置结束时间的min max限制值
end.config.min.hours = endPreH;
end.config.min.minutes = endPreM;
// 会场时间冲突提醒
if (isRealTime){
$("#mDateStartTime").removeClass("error-tips");
$("#mDateEndTime").removeClass("error-tips");
$("#mDate").removeClass("error-tips");
}
}
,change: function(value, date, endDate){
var curDate = new Date();
var month = curDate.getMonth()+1;
month = month > 9 ? month : '0' + month;
var day = curDate.getDate();
day = day > 9 ? day : '0' + day;
var h = curDate.getHours();
var sh = h > 9 ? h : '0' + h;
var mi = curDate.getMinutes();
var smi = mi > 9 ? mi : '0' + mi;
var today = curDate.getFullYear()+ '-' + month + '-' + day;
// 根据今天点击小时数,决定分钟数,如果是当期小时 则需要根据当前系统分钟限制
var selectday = $("#mDate").val();
if (selectday==today && date.hours==h){
// 双击时间才会生效
start.config.min.minutes = mi;
}else{
start.config.min.minutes = 0;
}
}
});
// 结束时间
var end = laydate.render({
elem: '#mDateEndTime' //指定元素
,type: 'time'
,trigger: 'click'
,format: 'HH:mm:ss'
,min: min
,max: max
,btns: ['clear', 'confirm']
,done: function(value, date){
// 判断当前选择时间是否超过系统时间
var isRealTime = true;
var selectDay = $("#mDate").val();
var startTime = $("#mDateStartTime").val();
var endTime = value;
if (selectDay !=""){
var curDate = new Date();
var month = curDate.getMonth()+1;
month = month > 9 ? month : '0' + month;
var day = curDate.getDate();
day = day > 9 ? day : '0' + day;
var h = curDate.getHours();
var sh = h > 9 ? h : '0' + h;
// 处理4小时内
var ah = curDate.getHours()+4;
var sah = ah > 9 ? ah : '0' + ah;
var mi = curDate.getMinutes();
var smi = mi > 9 ? mi : '0' + mi;
var today = curDate.getFullYear()+ '-' + month + '-' + day;
if (today==selectDay){
var systemTime = sh+":"+smi+":"+"00";
var foursystemTime = sah+":"+smi+":"+"00";
if (endTime!="" && endTime<=systemTime){
isRealTime=false;
layer.msg("会议选择时间异常!会议预约时间必须大于当前时刻", function () {
return false;
});
$("#mDateStartTime").addClass("error-tips");
$("#mDateEndTime").addClass("error-tips");
$("#mDate").addClass("error-tips");
}else if(startTime!="" && startTime<=systemTime){
isRealTime=false;
layer.msg("会议选择时间异常!会议预约开始时间必须大于系统当前时刻!", function () {
return false;
});
$("#mDateStartTime").addClass("error-tips");
$("#mDate").addClass("error-tips");
}
}
}
if(startTime!="" && endTime<=startTime){
isRealTime=false;
layer.msg("会议选择时间异常!会议预约结束时间必须大于开始时间", function () {
return false;
});
$("#mDateStartTime").addClass("error-tips");
$("#mDateEndTime").addClass("error-tips");
}
// 处理时间限制-先选择了结束时间,那么开始时间的最大值应为结束时间-10
if($("#mDateStartTime").val()==""){
var selStartH = date.hours;
var selStartM = date.minutes;
var endPreM = selStartM-10;
console.log(endPreM);
console.log(selStartH);
var endPreH = selStartH;
if (endPreM<0){
endPreH = selStartH-1;
endPreM = 50;
}
// 设置开始时间的min max限制值
start.config.max.hours = endPreH;
start.config.max.minutes = endPreM;
}
// 会场时间冲突提醒
if (isRealTime){
$("#mDateStartTime").removeClass("error-tips");
$("#mDateEndTime").removeClass("error-tips");
$("#mDate").removeClass("error-tips");
}
}
});
});