自定义时间线插件

时间:2021-06-01 17:16:08

入职已有两个月了,从以前的前后台均开发到目前的专向做前端,最大的感触便是更加有耐心了,不管什么样的效果及布局,都能静下心来从解决方案到观摩别人解决方案,进而实现。这样看来人的精力是有限的是对的。然而写着写着会越加意识到自己该提高下代码质量,特别是对于日渐庞大的工程及需要不断维护和拓展的实现来说,代码规范、高质量是至关重要的一个环节,这是自己接下来需要提高和注意的地方。

在此以自己近期遇到的一个开发任务:时间线的开发过程,来记录下自己此刻的思路与状态。最终实现效果如下图:

自定义时间线插件

整体布局思路:纯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);
}