工程名称 | 阶段 | 2012 | 进度 | 受控 | 备注 | |||
---|---|---|---|---|---|---|---|---|
Q1 | Q2 | Q3 | Q4 | |||||
#1机组 | 制造 | id="planGanttChartTd">?¤ | 70% | 无 | ||||
?¤ | ||||||||
安装 | ?¤ | 70% | src="../img/iscontrol0.gif"/> | 无 | ||||
?¤ |
i.
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
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 | 进度 | 受控 | 备注 | |||
---|---|---|---|---|---|---|---|---|
Q1 | Q2 | Q3 | Q4 | |||||
#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