入职已有两个月了,从以前的前后台均开发到目前的专向做前端,最大的感触便是更加有耐心了,不管什么样的效果及布局,都能静下心来从解决方案到观摩别人解决方案,进而实现。这样看来人的精力是有限的是对的。然而写着写着会越加意识到自己该提高下代码质量,特别是对于日渐庞大的工程及需要不断维护和拓展的实现来说,代码规范、高质量是至关重要的一个环节,这是自己接下来需要提高和注意的地方。
在此以自己近期遇到的一个开发任务:时间线的开发过程,来记录下自己此刻的思路与状态。最终实现效果如下图:
整体布局思路:纯css布局,大小采用百分比,以便适应各种分辨率环境;
时间轴算法:依据已有时间点,找出最大时间及最小时间,以最小时间为起点,包含最大时间且为6的倍数时间点为结束时间;
时间段定位:根据开始时间点及时间段跨度,进行百分比绝对定位;
时间线绘制:利用模板,动态添加dom元素;
js实现过程:插件化,便于移植、复用和维护。无奈当前水平首先,封装的不好,以后要多看看别人源码,学习模块化,面向对象js编程了。个人封装js逻辑如下:
//时间线刷新定时器
var timeLineTimer=null;
//当前时间线渲染数据集,用来控制定时器中时间线是否需要刷新
var currentData="";
// 时间线类
function OwnTimeLine (arg) {
var $that=this;
//告警时间线主体参数
var timeLineArg={"entityName":"告警描述信息","alarmCount":"0条告警","okNum":0,"infoCount":0,
"warningCount":0,"errorCount":0,"minTime":new Date(),"maxTime":new Date(),"alarms":[]};
//告警时间线参数(示例)
var timeParam={"timelines":[{"beginPriorityColor":OwnTimeLine.alarmlevel[1],"endPriorityColor":OwnTimeLine.alarmlevel[0],
"beginTime":"2016/4/7 10:00:","endTime":"2016/4/7 10:10"}],"alarmName":"Test"};
if(arg==null||arg==undefined){
arg=timeLineArg;
}
//主告警名称
this.entityName=arg.entityName;
//告警总数
this.alarmCount=arg.alarmCount;
//正常告警数量
this.okNum=arg.okNum==null?0:arg.okNum;
//提示告警数量
this.infoCount=arg.infoCount==null?0:arg.infoCount;
//警告告警数量
this.warningCount=arg.warningCount==null?0:arg.warningCount;
//验证告警数量
this.errorCount=arg.errorCount==null?0:arg.errorCount;
// 时间轴开始时间
this.minTime=arg.minTime==null?new Date():arg.minTime;
// 最大结束时间
this.maxTime=arg.maxTime==null?new Date():arg.maxTime;
// 时间线跨度(分钟为单位)
this.timeLineWidthMins=60;
//初始化时间线对象
this.initAll();
//初始化时间线
if(arg.alarms!=null&&arg.alarms.length>0){
$.each(arg.alarms,function(index,item){
$that.appendTimeArr(item);
});
}
}
// 渲染子告警及其时间线数据
OwnTimeLine.prototype.appendTimeArr = function (param) {
$that=this;
if(param.timelines!=null && param.timelines.length>0){
//console.log(JSON.stringify(param.timelines));
if(OwnTimeLine.currentTimeNo>OwnTimeLine.timeTotal){
this.appAlarmDom();
OwnTimeLine.timeTotal++;
$(".div-flex-verticalline").css("height",(parseInt($(".div-flex-verticalline").css("height"))+30)+"px");
}
$.each(param.timelines,function (index,item){
//console.log(this);//this指item function产生闭包
var $domTime=$($("#tmp-time").html());
$domTime.css("left",$that.getLeft(item.beginTime)).css("width",$that.getWidth(item.beginTime,item.endTime));
$domTime.find(".span-timestart").css("background-color",item.beginPriorityColor).attr("title",item.beginTime).tooltip();
$domTime.find(".div-hrline").css("border-bottom-color",item.beginPriorityColor);
if(item.endTime!=null && item.endTime!="" && item.endTime!=undefined){
$domTime.find(".span-timeend").css("background-color",item.endPriorityColor).attr("title",item.endTime).tooltip();
}
$("#div-timeline-"+OwnTimeLine.currentTimeNo).find(".div-time-left").append($domTime);
});
// 设置告警信息
var $domName=$("#div-timeline-"+OwnTimeLine.currentTimeNo);
var lastItem=param.timelines[param.timelines.length-1];
if(lastItem.endTime!=null && lastItem.endTime!="" && lastItem.endTime!=undefined){
$domName.find(".div-alarm-right").find(".span-level-circle").css("background-color",lastItem.endPriorityColor);
}
else{
$domName.find(".div-alarm-right").find(".span-level-circle").css("background-color",lastItem.beginPriorityColor);
}
$domName.find(".font12").html(param.alarmName);
// $("#div-timeline-"+OwnTimeLine.currentTimeNo).find(".div-flex-sys").find(".font12").html(param.sys);
OwnTimeLine.currentTimeNo++;
}
};
// 添加子告警dom
OwnTimeLine.prototype.appAlarmDom=function(){
var $dom=$($("#tmp-timeline").html());
$dom.attr("id","div-timeline-"+OwnTimeLine.currentTimeNo);
$(".div-timeline").append($dom);
};
// 渲染时间线基本信息
OwnTimeLine.prototype.initBaseInfo=function(){
$("#span-alarm-description").html(this.entityName);
$("#span-alarm-total").html(this.alarmCount);
$("#span-ok-num").html(this.okNum);
$("#span-level1-num").html(this.infoCount);
$("#span-level2-num").html(this.warningCount);
$("#span-level3-num").html(this.errorCount);
};
// 初始化时间线计算刻度
OwnTimeLine.prototype.initTimeInfo=function(min,max){
var timeInterval=0;
if(min!=null&&min!=undefined&&min!=""&&max!=""&&max!=null&&max!=undefined){
this.minTime=new Date(min);
this.maxTime=new Date(max);
}
var temp=this.maxTime-this.minTime;
if(temp>0){
temp=temp/(1000*60);
if(temp>60){
var mod = temp%6;
if(mod!=0){
this.timeLineWidthMins=temp+6-mod;
}
else{
this.timeLineWidthMins=temp;
}
}
else{
this.timeLineWidthMins=60;
}
}
timeInterval=this.timeLineWidthMins/6*60*1000;
// 时间跨度
var minSuffix="";
if(this.timeLineWidthMins%60!=0){
minSuffix=this.timeLineWidthMins%60+"分钟";
}
$("#span-time-scope").html(parseInt(this.timeLineWidthMins/60)+"小时"+minSuffix);
var dateTmpMs=this.minTime-0;
var dateTmp=this.minTime;
var suffix="am";
for(var i=1;i<=6;i++){
var hourVal=dateTmp.getHours();
var minVal=dateTmp.getMinutes()<10?"0"+dateTmp.getMinutes():dateTmp.getMinutes();
if(hourVal>12){
suffix="pm";
hourVal-=12;
}
$("#div-flex-time"+i).find(".span-date").html(dateTmp.getMonth()+1+"月"+dateTmp.getDate()+"日");
$("#div-flex-time"+i).find(".span-time").html(hourVal+":"+minVal+suffix);
dateTmpMs+=timeInterval;
dateTmp=new Date(dateTmpMs);
}
};
// 根据起始时间计算左偏移距离
OwnTimeLine.prototype.getLeft=function(time1){
var dateTmpVal=((new Date(time1)-this.minTime)/60000)/this.timeLineWidthMins*100+"%";
return dateTmpVal;
};
// 根据起止时间计算宽度
OwnTimeLine.prototype.getWidth=function(time1,time2){
if(time2==null || time2==""){
time2=this.maxTime;
}
if(new Date(time2)-new Date(time1)<=0){
return 0;
}
else{
var dateTmpVal=((new Date(time2)-new Date(time1))/60000)/this.timeLineWidthMins*100+"%";
return dateTmpVal;
}
};
// 初始化
OwnTimeLine.prototype.initAll=function(){
OwnTimeLine.clearTimeLine();
this.initBaseInfo();
this.initTimeInfo();
};
// 展示子告警时间线总数
OwnTimeLine.timeTotal=10;
// 原始时间线总数
OwnTimeLine.standardTotal=10;
// 下一可渲染时间线序号
OwnTimeLine.currentTimeNo=1;
// 媒体查询控制时间线渲染数量
OwnTimeLine.setSize=function(){
if($(".div-timeline-wrap").css("width")=="1200px"){
OwnTimeLine.timeTotal=15;
OwnTimeLine.standardTotal=15;
for(var i=11;i<16;i++){
var $dom=$($("#tmp-timeline").html());
$dom.attr("id","div-timeline-"+i);
$(".div-timeline").append($dom);
}
}
};
// 清空已渲染时间线信息
OwnTimeLine.clearTimeLine=function(){
if(OwnTimeLine.timeTotal>OwnTimeLine.standardTotal){
for(var i=OwnTimeLine.standardTotal+1;i<=OwnTimeLine.timeTotal;i++){
$("#div-timeline-"+i).remove();
}
OwnTimeLine.timeTotal=OwnTimeLine.standardTotal;
OwnTimeLine.setSize();
$(".div-flex-verticalline").css("height","100%");
}
for(var i=1;i<OwnTimeLine.currentTimeNo;i++){
$("#div-timeline-"+i).find(".div-time-left").empty();
$("#div-timeline-"+i).find(".div-alarm-right").find(".span-level-circle").css("background-color","");
$("#div-timeline-"+i).find(".div-alarm-right").find(".font-lh-29").html("");
}
OwnTimeLine.currentTimeNo=1;
};
//告警状态颜色
OwnTimeLine.alarmlevel=["#7EC92E","#42a8ef","#EF7742","#FF3A3A"];
OwnTimeLine.setSize();
//弹窗打开时停止主页定时器
$('#alarm-timeline').on('show.bs.modal', function () {
endTimer();
});
//弹窗关闭时开始主页定时器,停止弹窗定时器
$('#alarm-timeline').off('hidden.bs.modal').on('hidden.bs.modal',function() {
startTimer();
//停止时间线定时器
clearInterval(timeLineTimer);
currentData="";
});
/**
* @des 渲染时间线
* @author QIAN
* @since 2016年4月11日
* @return
*/
function loadTimeLine(data) {
var timeLineNode={};
timeLineNode.entityName=data.entityName;
timeLineNode.alarmCount=data.alarmCount==null?0:data.alarmCount+" 条告警";
timeLineNode.errorCount=data.errorCount==null?0:data.errorCount;
timeLineNode.warningCount=data.warningCount==null?0:data.warningCount;
timeLineNode.infoCount=data.infoCount==null?0:data.infoCount;
timeLineNode.okNum=data.okNum==null?0:data.okNum;
timeLineNode.minTime=new Date();
timeLineNode.maxTime=null;
timeLineNode.alarms=[];
if(data.alarms!=null&&data.alarms.length>0){
$.each(data.alarms,function(index,item){
var lineNode={};
lineNode.alarmName=item.alarmName;
lineNode.timelines=[];
if(item.timelines!=null&&item.timelines.length>0){
var t1=item.timelines[0].beginTime;
var t2=item.timelines[item.timelines.length-1].endTime;
var time1=(t1==null||t1=="")?new Date():new Date(t1);
var time2=(t2==null||t2=="")?new Date():new Date(t2);
if(timeLineNode.minTime-time1>0){
timeLineNode.minTime=time1;
}
if(timeLineNode.maxTime==null){
timeLineNode.maxTime=time2;
}
else if(time2-timeLineNode.maxTime>0){
timeLineNode.maxTime=time2;
}
$.each(item.timelines,function(index,line){
var node={};
if(line.beginTime==null||line.beginTime==""){
return;
}
else{
node.beginTime=line.beginTime;
node.beginPriorityColor=OwnTimeLine.alarmlevel[line.beginPriority];
}
node.endTime=line.endTime;
if(line.endTime!=null && line.endTime!=""){
(line.endPriority==null||line.endPriority==="")?line.endPriority=0:line.endPriority;
node.endPriorityColor=OwnTimeLine.alarmlevel[line.endPriority];
}
lineNode.timelines.push(node);
});
}
timeLineNode.alarms.push(lineNode);
});
}
new OwnTimeLine(timeLineNode);
}
//测试数据
var data1={"entityName": "主告警1","alarmCount": 10,"errorCount": 1,"warningCount": 5,
"infoCount": 10,"alarms": [
{"timelines": [{"beginPriority": 1,"endPriority": 0,"beginTime": "2016/4/11 10:00","endTime": "2016/4/11 10:10"},
{"beginPriority": 1,"endPriority": 0,"beginTime": "2016/4/11 10:25","endTime": "2016/4/11 10:50"}],
"alarmName": "Alarm Test1"},
{"timelines": [{"beginPriority": 3,"endPriority": 0,"beginTime": "2016/4/11 10:23","endTime": "2016/4/11 10:40"},{"beginPriority": 3,
"endPriority": 0,"beginTime": "2016/4/11 10:45","endTime": "2016/4/11 11:05"}],"alarmName": "Alarm Test2"},
{"timelines": [{"beginPriority": 2,"endPriority": 0,"beginTime": "2016/4/11 10:04","endTime": "2016/4/11 10:33"},{"beginPriority": 2,
"endPriority": "","beginTime": "2016/4/11 10:40","endTime": "2016/4/11 11:10"}],"alarmName": "Alarm Test3"},
{"timelines": [{"beginPriority": 1,"endPriority": 0,"beginTime": "2016/4/11 10:11","endTime": "2016/4/11 10:22"},{"beginPriority": 1,
"endPriority": 0,"beginTime": "2016/4/11 10:30","endTime": "2016/4/11 10:45"},{"beginPriority": 1,
"endPriority": "","beginTime": "2016/4/11 10:50","endTime": "2016/4/11 11:20"}],"alarmName": "Alarm Test4"}]};
var data2={"entityName": "主告警1","alarmCount": 10,"errorCount": 1,"warningCount": 5,
"infoCount": 10,"alarms": [
{"timelines": [{"beginPriority": 3,"endPriority": 0,"beginTime": "2016/4/11 10:35","endTime": "2016/4/11 10:55"},
{"beginPriority": 3,"endPriority": 0,"beginTime": "2016/4/11 11:05","endTime": "2016/4/11 11:20"}],
"alarmName": "Alarm Test1"},
{"timelines": [{"beginPriority": 2,"endPriority": 0,"beginTime": "2016/4/11 10:43","endTime": "2016/4/11 10:58"},{"beginPriority": 2,
"endPriority": 0,"beginTime": "2016/4/11 11:22","endTime": "2016/4/11 11:50"}],"alarmName": "Alarm Test2"}
]};
//显示时间线
function showTimeLine(){
var data=data1;
loadTimeLine(data);
currentData=JSON.stringify(data1);
//获取时间线数据,并启动技术器定时刷新
timeLineTimer = setInterval(function(){
if(currentData==JSON.stringify(data2)){
data=data1;
}
else{
data=data2;
}
//如果数据发生变化则更新时间线渲染
if(currentData!=JSON.stringify(data)){
currentData=JSON.stringify(data);
loadTimeLine(data);
}
},5000);
}