前一个版本不符合领导要求,和实验室资源没有紧密关联,前一个版本是以时间为事件单位,选择时候后,才去选择实验室以及设备。但实际要求是时间与资源强关联,以资源为限制入口,然后才是时间。 在原有的3张数据表:calendar,lab,dev的基础上进行设计,重点是关于预约区域的设计,由于上个版本使用的fullcalendar是以时间为基础,不适用于此版本,于是我需要另一个能够和设备相关联的日程表,刚好公司OA的会议室预约的是和会议室相关联的,所以决定仿照公司OA的会议室预约来设计,但是由于OA系统是第三方公司开发的,拿不到源码,也就不知道用的插件是什么,所以只能自己琢磨着写了。
日历表设计
本来开始是设计的设备与资源相关联,展示设备每天的每小时的使用情况,但是被否决了,之前写的代码也作废了,那就不浪费时间介绍了,直接介绍最终版吧。 日历表是以设备为基础单位,横坐标表示24小时,竖坐标表示天数。获取该月天数的代码如下:
function getDaysInMonth(year,month){
month = parseInt(month,10);
var temp = new Date(year,month,0); return temp.getDate();
}
//year表示年份,month是月份,可以在进入系统或者选择年月的时候分解,依次传参
根据月份循环天数,输出一个天/时的日历表,每个日历表增加预约点击事件。
设备预约情况展示设计
表格好设计,重点是如何展示清楚的设备的预约情况,开始的时候,我想设计成OA会议室预约那样,该天该时间段内有预约的话,该块颜色就变成绿色,如果有多个,那么该td里面会显示数字表示有几个在改天该时间段内被预约(设备有承载量,可以被预约多次)。但是这样,无法直观展示预约的实际情况,而且对于查看预约的信息,比较麻烦,需要根据时间范围去查,效率比较低,所以比较而言,我又改版设计成类似fullcalendar那样的以div块的形式展示预约情况,详细设计如下:
div绝对定位的相对定位
显示的div块需要横跨td并浮于td上方,需要对div进行定位,div有相对定位和绝对定位两种,相比较而言,相对因为适应性表好点,所以用div相对定位,div的css代码如下:
.calen{
position: absolute;
height:15px;
font-size:0.8em;
border-radius:4px;
}
.clear{clear:both;}//清除浮动带来的布局混乱
预约情况展示
然后是根据获取的时间展示,多说无益,直接上代码:
function resulte(id){
//id值是设备的id值
document.getElementById('chuid').value=id;
var time=document.getElementById('testt').innerText;
var str=time.split("-");
var year=parseInt(str[0]);
var month=parseInt(str[1]);
var endm=year+"-"+parseInt(month+1);
var a=time.replace(/\-/gi,"/");
var starts=new Date(a).getTime();//月初的时间戳
var b=endm.replace(/\-/gi,"/");
var ends=new Date(b).getTime();//月末的时间戳
var table=document.getElementById('table');
$('#table td').css('background-color','white');
$('.time').html('');
var width=$('#table').width();//获取table calendar的宽度
var vtd=parseFloat(width/25);
var row=table.rows.length;
var cell=table.rows[0].cells.length;
//获取当前时间 去数据库查询当前实验室的当前日期的数据,
//处理,并返回,将数据放在相应地方,改变颜色
$.ajax({
url:"calendar.php?id="+id+'&start='+time+'&end='+endm,
type:"POST",
dataType:'text',
success:function(result){
//获取了开始时间为当天的当前实验室的数据
var str=JSON.parse(result);
//当前数据是由数组组成的json数据,先转换
//首先要匹配到table表中的设备,然后再匹配到对应小时时间
//先循环table,再循环结果
for(i=0;i<str.length;i++)
{
var eventid=str[i].id;
var title=str[i].title;
var color=str[i].color;
var dev_sty=str[i].dev_sty;
//获取开始时间戳
var time=str[i].starttime;
var times=getLocalTime(time);
//获取开始时间的小时
var shour=parseInt(gethour(times))+parseInt(1);
//获取开始时间天数
var sday=parseInt(getday(times));
var etime=str[i].endtime;
var etimes=getLocalTime(etime);
//获取结束时间的小时
var ehour=parseInt(gethour(etimes))+parseInt(1);
//获取开始时间天数
var eday=parseInt(getday(etimes));
//将设备与table表中的设备对应上
if(sday==eday){//如果是在同一天的话
var dv=parseInt(ehour-shour);
var wid=parseFloat(dv*4);
var dis=document.getElementsByName('dis').length;
var heig=parseInt(15+3*1);
//根据时长决定div的长度,开始时是获取table的宽度,然后决定div的宽度
//但是浏览器缩小后div不变化,所以改成百分比
var spans='<div name="dis" onclick="showd('+eventid+')" oncontextmenu="details('+eventid+',event)" style="background-color:'+color+';width:'+wid+'%;height:'+heig+'px;color:white;" class="calen">'+eventid+' '+title+'</div><br class="clear"/>';
$("#table tr:eq('"+(sday-1)+"') td:eq('"+shour+"')").append(spans);
$("#table tr:eq('"+(sday-1)+"') td:eq('"+shour+"')").removeAttr('onclick');
}
else{//如果跨天的话
var ddv=parseInt(eday-sday);//获取天数差
//第一天是从开始小时数到结束
var std=parseInt(25-shour);
var wid1=parseFloat(4*std);
var dis1=document.getElementsByName('dis').length;
var heig1=parseInt(15+3*1);
var spans1='<div name="dis" onclick="showd('+eventid+')" oncontextmenu="details('+eventid+',event)"style="background-color:'+color+';width:'+wid1+'%;height:'+heig1+'px;color:white;" class="calen">'+eventid+' '+title+'</div><br class="clear"/>';
$("#table tr:eq('"+(sday-1)+"') td:eq('"+shour+"')").append(spans1);
$("#table tr:eq('"+(sday-1)+"') td:eq('"+shour+"')").removeAttr('onclick');
//}
//接下来的n-1是整行都充满颜色
for(m=0;m<ddv-1;m++){
var wid2=parseFloat(vtd*24);
var dis2=document.getElementsByName('dis').length;
var heig2=parseInt(15+3*1);
var spans2='<div name="dis"onclick="showd('+eventid+')" oncontextmenu="details('+eventid+',event)" style="background-color:'+color+';width:96%;height:'+heig2+'px;color:white;" class="calen">'+eventid+' '+title+'</div><br class="clear"/>';
$("#table tr:eq('"+(sday+m)+"') td:eq(1)").append(spans2);
$("#table tr:eq('"+(sday-1)+"') td:eq('"+shour+"')").removeAttr('onclick');
}
//最后一天是从0到结束小时
var etd=parseInt(ehour);
var wid3=parseFloat(4*(ehour-1));
var dis3=document.getElementsByName('dis').length;
var heig3=parseInt(15+3*1);
var spans3='<div name="dis" onclick="showd('+eventid+')" oncontextmenu="details('+eventid+',event)" style="background-color:'+color+';width:'+wid3+'%;height:'+heig3+'px;color:white;" class="calen">'+eventid+' '+title+'</div><br class="clear"/>';
$("#table tr:eq('"+(eday-1)+"') td:eq(1)").append(spans3);
$("#table tr:eq('"+(sday-1)+"') td:eq('"+shour+"')").removeAttr('onclick');
}
}
},
error:function(errMsg){
alert(errMsg);
}
});
}
预约信息展示
实际展示中,只会显示预约事件的title,需要展示详细信息,鼠标左键有别的用处,所以设计的是点击鼠标右键弹出详细信息,代码如下:
function details(id,e){
window.event.returnValue = false;//一定要加上这句,不然就会弹出浏览器本身的事件
var e = e || window.event;
//鼠标点的坐标
var oX = e.clientX;
var oY = e.clientY;
//菜单出现后的位置
$.ajax({
url:"search.php?id="+id+'&action=1',
type:"POST",
dataType: 'text',
error: function(errMsg){
alert('Error loading XML document');
console.log(errMsg);
},
success:function(data){
var str=JSON.parse(data);
var title=str.title;
var starttime=str.starttime;
var endtime=str.endtime;
var lab=str.l_id;
var user=str.user;
var project=str.project;
var remark=str.remark;
var start=getLocalTime(starttime);
var st=new Date(start).Format("yyyy-MM-dd HH:mm:ss");
var end=getLocalTime(endtime);
var ed=new Date(end).Format("yyyy-MM-dd HH:mm:ss");
document.getElementById('t1').innerHTML=title;
document.getElementById('t2').innerHTML=user;
document.getElementById('t3').innerHTML=project;
document.getElementById('t4').innerHTML=remark;
document.getElementById('t5').innerHTML=st;
document.getElementById('t6').innerHTML=ed;
layer.open({
type: 1,
title:false,
offset: [oY,oX],
shadeClose:true,
closeBtn: 0,
skin: 'layui-layer-rim', //加上边框
area: ['300px', 'auto'], //宽高
content:$("#bes")
});
}
});
}
大致的介绍就是这个了,思路设计差不多就是这样,代码太多,不可能全部展示。因为公司网络原因,上传不了网盘,所以源码后面再补。