jQuery绘制甘特图

jQuery绘制甘特图

一、任务需求

任务需求:需要在maximo中以甘特图方式显示工程进度,如图:

工程进度表公告转到报表启动中心个人设置退出帮助

所有书签查找:选择操作

工程进度看板列表工程进度表

工程进度看板过滤器

录入人录入时间

进度日期

上一页

下一页

二、分析

在Maximo应用程序设计器中无法实现所需要求,甘特图实现需要在maximo中嵌套jsp。

分析用web技术实现甘特图

1、整理绘制甘特图所需的数据。“工程进度、名称、进度、受控、备注”这些数据可以直

接从数据库查询;我们需要处理的是表头的年份和甘特图的开始位置、长度。

a)需要得到表头的年份,这个可以根据工程进度记录的开始时间和结束时间获取到

b)甘特图的开始位置及长度,开始位置可以根据该条记录开始时间和开始年份时间相

减得到,长度则是该条记录的开始时间和结束时间。

2、根据数据绘制甘特图步履

jQuery有强大的选择器和操作DOM的方便性,我们可以选择jQuery来绘制甘特图。至于数据传输,毫无疑问选择JSON。

a)首先需要在页面上用table实现基本效果

b)再根据查询出来的开始和结束年份,用jQuery动态添加到表头中

c)然后将记录添加到table中

d)最后就是用jQuery绘制甘特图。甘特图以季度为刻度,一刻度占用一个单元格。甘

特图效果以td的背景色显示,如果从第三个刻度开始,甘特图前方就新增一个td 并占用三个单元格。甘特图长度有几个季度就占用多少个单元格。

三、实现

根据分析逐步实现甘特图

甘特图实现

1、后台数据处理

需要查询工程进度最新主表记录及其从表记录,还需要得到开始年份和结束年份,最重要的甘特图所需数据的处理。

a)新建主表类Prorate和从表类ProrateLine

Prorate表:

其中prorateLineList为从表集合

private String proratenum;

private String prorateStartDate;

private String prorateEndDate;

private String prodate;

private String enterby;

private String enterdate;

private List prorateLineList;

ProrateLine表:

其中“//用于甘特图显示的数据字段”注释下的都是甘特图所需数据字段private Prorate prorate;

private Integer prorateLineId;

private String prorateNum;

private String seq;

private String proName;

private String planstartdate;

private String planenddate;

private String actstartdate;

private String actenddate;

private String iplanstartdate;

private String iplanenddate;

private String iactstartdate;

private String iactenddate;

private double finishrate;

private String iscontrol;

private double ifinishrate;

private String iiscontrol;

private String isstartcenter;

private String memo;

private String imemo;

//用于甘特图显示的数据字段

private int plan;

private int planNext;

private int planPrev;

private int act;

private int actNext;

private int actPrev;

private int iplan;

private int iplanNext;

private int iplanPrev;

private int iact;

private int iactNext;

private int iactPrev;

b)新建数据处理类ProrateDAO

ProrateDAO负责查询数据并处理数据

1.首先需要查出主记录中最新一条记录,新建方法findProrate()。主要代码如

String sql = "select * from (select * from prorate order by prodate desc) where rownum = 1 ";

rs = stmt.executeQuery(sql);

while (rs != null && rs.next()) {

prorate = new Prorate();

prorate.setEnterby(rs.getString("enterby"));

prorate.setEnterdate(rs.getString("enterdate"));

prorate.setProdate(rs.getString("prodate"));

prorate.setProratenum(rs.getString("proratenum"));

}

2.还需要查出开始年份和结束年份,新建方法findStartEndYear(),主要代码

如下:

i.sql语句待优化

String sql = "select startdate,enddate from "+

" (select (LEAST((case when PLANSTARTDATE is null then '9999' else PLANSTARTDATE end),(case when ACTSTARTDATE is null then '9999' else ACTSTARTDATE end)"+

" ,(case when IPLANSTARTDATE is null then '9999' else IPLANSTARTDATE end),(case when IACTSTARTDATE is null then '9999' else IACTSTARTDATE end))) startdate from"+

" (select * from (select to_char(PLANSTARTDATE,'yyyy') PLANSTARTDATE from prorateline where PLANSTARTDATE is not null and PRORATENUM =

'"+proratenum+"' order by PLANSTARTDATE asc) where rownum = 1)"+

" FULL OUTER JOIN(select * from (select to_char(ACTSTARTDATE,'yyyy') ACTSTARTDATE from prorateline where ACTSTARTDATE is not null and PRORATENUM = '"+proratenum+"' order by ACTSTARTDATE asc) where rownum = 1)"+

" on 1=1"+

" FULL OUTER JOIN(select * from (select to_char(IPLANSTARTDATE,'yyyy') IPLANSTARTDATE from prorateline where IPLANSTARTDATE is not null and PRORATENUM = '"+proratenum+"' order by IPLANSTARTDATE asc) where rownum = 1)"+

" on 1=1"+

" FULL OUTER JOIN(select * from (select to_char(IACTSTARTDATE,'yyyy') IACTSTARTDATE from prorateline where IACTSTARTDATE is not null and PRORATENUM = '"+proratenum+"' order by IACTSTARTDATE asc) where rownum = 1)"+

" on 1=1),"+

" (select (greatest((case when PALNENDDATE is null then '0' else PALNENDDATE end),(case when ACTENDDATE is null then '0' else ACTENDDATE end)"+

" ,(case when IPALNENDDATE is null then '0' else IPALNENDDATE end),(case when IACTENDDATE is null then '0' else IACTENDDATE end))) enddate from"+ " (select * from (select to_char(PALNENDDATE,'yyyy') PALNENDDATE from prorateline where PALNENDDATE is not null and PRORATENUM =

'"+proratenum+"' order by PALNENDDATE desc) where rownum = 1)"+

" FULL OUTER JOIN(select * from (select to_char(ACTENDDATE,'yyyy') ACTENDDATE from prorateline where ACTENDDATE is not null and PRORATENUM = '"+proratenum+"' order by ACTENDDATE desc) where rownum = 1)"+

" on 1=1"+

" FULL OUTER JOIN(select * from (select to_char(IPALNENDDATE,'yyyy') IPALNENDDATE from prorateline where IPALNENDDATE is not null and PRORATENUM = '"+proratenum+"' order by IPALNENDDATE desc) where rownum = 1)"+

" on 1=1"+

" FULL OUTER JOIN(select * from (select to_char(IACTENDDATE,'yyyy') IACTENDDATE from prorateline where IACTENDDATE is not null and PRORATENUM = '"+proratenum+"' order by IACTENDDATE desc) where rownum = 1)"+

" on 1=1)";

rs = stmt.executeQuery(sql);

while (rs != null && rs.next()) {

prorate = new Prorate();

prorate.setProrateStartDate(rs.getString("startdate")); prorate.setProrateEndDate(rs.getString("enddate"));

}

3.根据主记录编号查出从表记录,并根据开始年份和结束年份处理甘特图所需数据,

新建方法findProrateLineList(),主要代码如下:

其中“//添加用于显示甘特图的数据”注释下的代码为添加显示甘特图所需数据

String sql = "select * from prorateline where proratenum = '"+proratenum+"' order by seq ";

rs = stmt.executeQuery(sql);

list = new ArrayList();

ProrateLine prorateLine = null;

while (rs != null && rs.next()) {

prorateLine = new ProrateLine();

prorateLine.setProrateLineId(rs.getInt("proratelineid"));

prorateLine.setProrateNum(rs.getString("PRORATENUM"));

prorateLine.setSeq(rs.getString("SEQ"));

prorateLine.setProName(rs.getString("PRONAME")); prorateLine.setPlanstartdate(rs.getString("PLANSTARTDATE")); prorateLine.setPlanenddate(rs.getString("PALNENDDATE"));

prorateLine.setActstartdate(rs.getString("ACTSTARTDATE"));

prorateLine.setActenddate(rs.getString("ACTENDDATE")); prorateLine.setIplanstartdate(rs.getString("IPLANSTARTDATE")); prorateLine.setIplanenddate(rs.getString("IPALNENDDATE"));

prorateLine.setIactstartdate(rs.getString("IACTSTARTDATE"));

prorateLine.setIactenddate(rs.getString("IACTENDDATE"));

prorateLine.setFinishrate(rs.getDouble("FINISHRATE"));

prorateLine.setIscontrol(rs.getString("ISCONTROL"));

prorateLine.setIfinishrate(rs.getDouble("IFINISHRATE"));

prorateLine.setIiscontrol(rs.getString("IISCONTROL"));

prorateLine.setIsstartcenter(rs.getString("ISSTARTCENTER"));

prorateLine.setMemo(rs.getString("MEMO"));

prorateLine.setImemo(rs.getString("IMEMO"));

//添加用于显示甘特图的数据

prorateLine.setPlan(DateUtil.getQuarterCount(prorateLine.getPlanstart date(), prorateLine.getPlanenddate()));

prorateLine.setAct(DateUtil.getQuarterCount(prorateLine.getActstartda te(), prorateLine.getActenddate()));

prorateLine.setIplan(DateUtil.getQuarterCount(prorateLine.getIplansta rtdate(), prorateLine.getIplanenddate()));

prorateLine.setIact(DateUtil.getQuarterCount(prorateLine.getIactstart date(), prorateLine.getIactenddate()));

prorateLine.setPlanPrev(DateUtil.getQuarterCount(prorateYear.getProra teStartDate()+"-01-00 00:00:00", prorateLine.getPlanstartdate()));

prorateLine.setActPrev(DateUtil.getQuarterCount(prorateYear.getProrat eStartDate()+"-01-00 00:00:00", prorateLine.getActstartdate()));

prorateLine.setIplanPrev(DateUtil.getQuarterCount(prorateYear.getPror ateStartDate()+"-01-00 00:00:00", prorateLine.getIplanstartdate()));

prorateLine.setIactPrev(DateUtil.getQuarterCount(prorateYear.getProra teStartDate()+"-01-00 00:00:00", prorateLine.getIactstartdate()));

Integer year =

Integer.parseInt(prorateYear.getProrateEndDate())-Integer.parseInt(pr orateYear.getProrateStartDate());

prorateLine.setPlanNext((year+1)*4-prorateLine.getPlan()-prorateLine. getPlanPrev());

prorateLine.setActNext((year+1)*4-prorateLine.getAct()-prorateLine.ge tActPrev());

prorateLine.setIplanNext((year+1)*4-prorateLine.getIplan()-prorateLin e.getIplanPrev());

prorateLine.setIactNext((year+1)*4-prorateLine.getIact()-prorateLine. getIactPrev());

list.add(prorateLine);

}

4.得到最新工程进度和从表记录,新建方法findProrate()

c)新建工具类DateUtil和MathUtil

1.DateUtil工具类中有方法getQuarterCount(),可计算出两个时间相差的季度

2.MathUtil工具类中有方法divide(),可计算两个参数的商并四舍五入,以字符

串格式返回

d)新建Servlet类ProrateGanttChartServlet,接受数据并转为JSON格式以供页面调用,

主要代码如下:

response.setContentType("text/html;charset=utf-8");

ProrateDAO proratedao = new ProrateDAO();

Prorate prorate = proratedao.getProrate();

JSONArray jsonArray = JSONArray.fromObject(prorate);

2、页面效果实现

1.建立模型table

a)在页面上建立模型table,代码如下:

工程名称阶段2012进度受控备注
Q1Q2Q3Q4
#1机组制造

id="planGanttChartTd">?¤

70%
安装70%

src="../img/iscontrol0.gif"/>

i.

b)

2.Ajax取得json格式数据

a)用Ajax取到数据,代码如下

$.ajax({

url:basePath+'/prorate/prorateGanttChartServlet',

data:{emsnum:"testData"},

dataType:'json',

type:"POST",

error:function(data){

$("body").hide(function(){

alert("error occured!!!");

});

},

success:function(data){

if(data!=null&&data!=""&&data.length>0){

i.prorate = data;

3.根据得到的年份,调整table表头和内容

a)循环json数组,得到开始年份和结束年份并调整模型table,代码如下:

//得到统计年份的数组,并调整table

var numberArray =

getNumberArray(prorate[i].prorateEndDate,prorate[i].prorateStartDate) ;

for(var j=0;j

if(j==0){

$("th.yearTh:first").text(numberArray[j]);

}else{

var $yearTh =

$("th.yearTh:first").clone().text(numberArray[j]);

$("th.yearTh:last").after($yearTh);

$("tr.quarterTr:first >

th:last").after($("tr.quarterTr:first > th:lt(4)").clone());

}

}

$("td.ganttChartTd").attr("colspan",(numberArray.length)*4);

4.根据模型table,显示数据到页面上

a)根据分页显示数据内容到页面上,代码如下:

//把得到的集合显示到页面上

function showList(prorateLineList,pagefirst,pagelast){

$("tbody.tbody:visible").remove();

for(var k=pagefirst-1;k

var tbodyClone = $("tbody.tbody:first").clone();

//判断百分比显示方式

var finishrate = prorateLineList[k].finishrate;

var ifinishrate = prorateLineList[k].ifinishrate;

if(finishrate<1||finishrate==1){

finishrate = finishrate*100;

}

if(ifinishrate<1||ifinishrate==1){

ifinishrate = ifinishrate*100;

}

//添加除甘特图之外的数据

tbodyClone.find("#proName").text(prorateLineList[k].proName).end( )

.find("#finishrate").text(finishrate+"%").end()

.find("#iscontrol >

img").attr("src","../img/iscontrol"+prorateLineList[k].iscontrol+".gi f").end()

.find("#memo").text(prorateLineList[k].memo).end()

.find("#ifinishrate").text(ifinishrate+"%").end()

.find("#iiscontrol >

img").attr("src","../img/iscontrol"+prorateLineList[k].iiscontrol+".g if").end()

.find("#imemo").text(prorateLineList[k].imemo).end();

//添加甘特图数据

//计划制造

var plan = prorateLineList[k].plan;

var planPrev = prorateLineList[k].planPrev;

var planNext = prorateLineList[k].planNext;

if(plan==0){

tbodyClone.find("#planGanttChartTd").css({ background:"#ffffff",c olor:"#ffffff" });

}else if(planPrev==0&&planNext==0){

tbodyClone.find("#planGanttChartTd").attr("colspan",plan);

}else if(planPrev==0&&planNext>0){

tbodyClone.find("#planGanttChartTd").attr("colspan",plan).css("bo rder","0px")

.after("

style='border:0px;'>");

}else if(planPrev>0&&planNext==0){

tbodyClone.find("#planGanttChartTd").attr("colspan",plan).css("bo rder","0px")

.before("");

}else if(planPrev>0&&planNext>0){

tbodyClone.find("#planGanttChartTd").attr("colspan",plan).css("bo rder","0px")

.before("

style='border-right:0px;'>")

.after("

style='border-left:0px;'>");

}

else{

alert("数据错误!");

}

//实际制造

var act = prorateLineList[k].act;

var actPrev = prorateLineList[k].actPrev;

var actNext = prorateLineList[k].actNext;

if(act==0){

tbodyClone.find("#actGanttChartTd").css({ background:"#ffffff",co lor:"#ffffff" });

}else if(actPrev==0&&actNext==0){

tbodyClone.find("#actGanttChartTd").attr("colspan",act);

}else if(actPrev==0&&actNext>0){

tbodyClone.find("#actGanttChartTd").attr("colspan",act).css("bord er","0px")

.after("

style='border:0px;'>");

}else if(actPrev>0&&actNext==0){

tbodyClone.find("#actGanttChartTd").attr("colspan",act).css("bord er","0px")

.before("");

}else if(actPrev>0&&actNext>0){

tbodyClone.find("#actGanttChartTd").attr("colspan",act).css("bord er","0px")

.before("

style='border-right:0px;'>")

.after("

style='border-left:0px;'>");

}

else{

alert("数据错误!");

}

//计划制造

var iplan = prorateLineList[k].iplan;

var iplanPrev = prorateLineList[k].iplanPrev;

var iplanNext = prorateLineList[k].iplanNext;

if(iplan==0){

tbodyClone.find("#iplanGanttChartTd").css({ background:"#ffffff", color:"#ffffff" });

}else if(iplanPrev==0&&iplanNext==0){

tbodyClone.find("#iplanGanttChartTd").attr("colspan",iplan);

}else if(iplanPrev==0&&iplanNext>0){

tbodyClone.find("#iplanGanttChartTd").attr("colspan",iplan).css(" border","0px")

.after("

style='border:0px;'>");

}else if(iplanPrev>0&&iplanNext==0){

tbodyClone.find("#iplanGanttChartTd").attr("colspan",iplan).css(" border","0px")

.before("");

}else if(iplanPrev>0&&iplanNext>0){

tbodyClone.find("#iplanGanttChartTd").attr("colspan",iplan).css(" border","0px")

.before("

style='border-right:0px;'>")

.after("

style='border-left:0px;'>");

}

else{

alert("数据错误!");

}

//实际制造

var iact = prorateLineList[k].iact;

var iactPrev = prorateLineList[k].iactPrev;

var iactNext = prorateLineList[k].iactNext;

if(iact==0){

tbodyClone.find("#iactGanttChartTd").css({ background:"#ffffff",c olor:"#ffffff" });

}else if(iactPrev==0&&iactNext==0){

tbodyClone.find("#iactGanttChartTd").attr("colspan",iact);

}else if(iactPrev==0&&iactNext>0){

tbodyClone.find("#iactGanttChartTd").attr("colspan",iact).css("bo rder","0px")

.after("

style='border:0px;'>");

}else if(iactPrev>0&&iactNext==0){

tbodyClone.find("#iactGanttChartTd").attr("colspan",iact).css("bo

rder","0px")

.before("");

}else if(iactPrev>0&&iactNext>0){

tbodyClone.find("#iactGanttChartTd").attr("colspan",iact).css("bo rder","0px")

.before("

style='border-right:0px;'>")

.after("

style='border-left:0px;'>");

}

else{

alert("数据错误!");

}

tbodyClone.show().appendTo("#ganttChartTable");

}

i.}

5.分页及快捷键功能

a)分页函数,代码如下:

//上一页

function pageprev(){

if($(".pageprev").hasClass("pagelink")){

var pagefirst = Number($(".page03").text())-pageSize;

var pagelast = pagefirst+pageSize-1;

var pageIndex = Number($(".page01").text())-1;

showList(list,pagefirst,pagelast);

showPageInfo(pagefirst,pagelast);

showPageIndex(pageIndex);

pageStyle();

}

}

//下一页

function pagenext(){

if($(".pagenext").hasClass("pagelink")){

var pagefirst = Number($(".page03").text())+pageSize;

var pagelast = pagefirst+pageSize-1;

if(pagelast>list.length){

pagelast = list.length;

}

var pageIndex = Number($(".page01").text())+1;

showList(list,pagefirst,pagelast);

showPageInfo(pagefirst,pagelast);

showPageIndex(pageIndex);

pageStyle();

}

}

//首页

function pagefirst(){

if($(".pagefirst").hasClass("pagelink")){

showList(list,1,pageSize);

showPageInfo(1,pageSize);

showPageIndex(1);

pageStyle();

}

}

//尾页

function pagelast(){

if($(".pagelast").hasClass("pagelink")){

var pagefirst = pageSize*(pageCount-1)+1;

var pagelast = list.length;

showList(list,pagefirst,pagelast);

showPageInfo(pagefirst,pagelast);

showPageIndex(pageCount);

pageStyle();

}

}

//默认显示指定条数的记录

function showPageList(list){

if(list.length>=pageSize){

showList(list,1,pageSize);

showPageInfo(1,pageSize);

}else{

showList(list,1,list.length);

showPageInfo(1,list.length);

}

}

//显示当前显示的开始和结束条数

function showPageInfo(pagefirst,pagelast){

$(".page03").text(pagefirst);

$(".page04").text(pagelast);

}

//显示分页总数

function showPageCount(list){

$(".page02").text(pageCount);

}

//显示当前页数

function showPageIndex(pageIndex){

$(".page01").text(pageIndex);

}

//取得分页总数

function getPageCount(list){

var length = list.length;

if(pageSize>length){

return 1;

}

var count = Number(length/pageSize);

if(length%pageSize!=0){

if((length%pageSize)/pageSize<0.5){

count += 1;

}

count = count.toFixed(0);

}

return count;

}

//控制page样式

function pageStyle(){

if($(".page01").text()=="1"){

$(".pagefirst,.pageprev").removeClass("pagelink").addClass("pageu nlink");

}else{

$(".pagefirst,.pageprev").removeClass("pageunlink").addClass("pag elink");

}

if($(".page01").text()==$(".page02").text()){

$(".pagenext,.pagelast").removeClass("pagelink").addClass("pageun link");

}else{

$(".pagenext,.pagelast").removeClass("pageunlink").addClass("page link");

}

}

分页快捷键(支持IE),代码如下:

//增加快捷键预览

function hotkey()

{

var a=window.event.keyCode;

if((a==65)&&(event.ctrlKey))

{

}

if(a == 37){

pageprev();

}

if(a == 39){

pagenext();

}

if(a == 36){

pagefirst();

}

if(a == 35){

pagelast();

}

}// end hotkey

document.onkeydown = hotkey; //当onkeydown 事件发生时调用hotkey函数

最后将实现的页面嵌套到maximo中

四、预览

说明:由于开发时间仓促,以上代码还有很多不足之处,很多地方都有待优化。如果时间允许,甘特图效果可以做成一个插件,可方便以后重复使用。

页面代码SVN地址:调峰调频发电公司基建期机电设备数据采集系统\04 开发库\02 源代码\maximo.ear\maximouiweb.war\webclient\jxnet\prorate\prorateline.jsp

Java代码SVN地址:调峰调频发电公司基建期机电设备数据采集系统\04 开发库\02 源代码\maxqx\src\com\jxkj\webclient\beans\prorate

相关文档
最新文档