先給大家看一看效果,最近一段時間都在研究這個東西。
如果我把日期間隔選寬呢?比如5月日到5月5日?下面給大家看看效果,不用擔心哦
看到了吧,哈哈,這個日期都是動態生成的,下面就來跟大家分享一下這個的實現方法。
本人是用JAVA EE的后台實現的,
先來貼HTML代碼:

1 <div>站點:<input class="easyui-combobox" width="200px" id="stnmCombo"> 2 起始時間:<input id="StartTime" class="easyui-datebox" editable="false" /> 3 結束時間:<input id="EndTime" class="easyui-datebox" editable="false" /> 4 <a id="btnSearch" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-search'">查詢</a> 5 <a id="export" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-search'">導出</a> 6 </div> 7 8 <div class="easyui-layout" fit="true"> 9 <table id="dg"></table> 10 </div>
HTML代碼非常的簡單,其中關鍵的datagrid只有一個TABLE,其實關鍵在於JS代碼哦
下面就把代碼發出來:
我來給大家解釋下幾個關鍵的地方以及思路吧,代碼不是特別的復雜。
- formLoader.load(param1,param2,function(s){})這個方法第一個參數就是controller的RequestMapping的名字,因為是用的MVC三層構架弄的,第二個參數可以是字符串的,也可以是一個JSON對象,此方法返回的是一個JSON對象,如果alert(s)就會看到結果,這個公司框架的一個方法,所以大家不用再找,我只是分享思路。
- 本例子主要是后台構造動態列,使用得比較多的是PUSH方法,用PUSH方法把JSON對象存到數組里面去。
其中有幾點需要解釋一下:表頭名稱title,field(JSON對象返回到的對應的Key),field給大家放張圖片就知道了
下面是具體的代碼:
var gv=$("#dg"); var today=new Date(); //動態生成列 var dynamicCols=[]; var dynamicItems=[]; var dynamicItemsAfter=[]; var dynamicItemsEnd=[]; $(function(){ $("#StartTime").datebox('setValue',today.getFullYear()+"-"+(today.getMonth()+1)+"-"+(today.getDate()-1)); $("#EndTime").datebox('setValue',today.getFullYear()+"-"+(today.getMonth()+1)+"-"+(today.getDate())); //綁定空數據 gv.datagrid( "dataBind" , { autoHeight : 46 , datas : [], striped:true, pagination : true, autoRowHeight:false }); //綁定空列 gv.datagrid({ columns:[[ {title:'時間',width:150,sortable:true}, {title:'站點1',width:150,sortable:true}, {title:'站點2',width:150,sortable:true}, {title:'站點3',width:500,sortable:true}, ]] }); }); //列元素(動態) //序號 var stcd={ field: 'Stcd', title: '序號', // width: 150, rowspan:3, sortable:true } //站名 var stnm={ field: 'Stnm', title: '站名', // width: 150, rowspan:3, sortable:true } //平均值 var avg={ title:'平均值', //width:500, colspan:2 } //庫水位 var rz={ title:'庫水位', //width:150 /*PS:動態列中不適宜固定寬度,其他同樣的*/ } //庫容 var rv={ title:'庫容', width:150 } //庫容(平均) var rvAvg={ title:'庫容', field:"rvAvg2", //width:500 formatter:function(value,row,index) { return "-"; } } //查詢按鈕 $("#btnSearch").click(function(){ //得到開始日期和結束日期之間的天數之差 var ipt1=$("#StartTime").datebox('getValue'); var ipt2=$("#EndTime").datebox('getValue'); var arr1 = ipt1.split("-"); var arr2 = ipt2.split("-"); var dt1 = new Date(); dt1.setFullYear(arr1[0]); dt1.setMonth(arr1[1] - 1); dt1.setDate(arr1[2]); var dt2 = new Date(); dt2.setFullYear(arr2[0]); dt2.setMonth(arr2[1] - 1); dt2.setDate(arr2[2]); var dif = dt2.getTime() - dt1.getTime(); var days = dif / (24 * 60 * 60 * 1000); //再次初始化,避免數組的堆積 dynamicCols=[]; dynamicItems=[]; dynamicItemsAfter=[]; dynamicItemsEnd=[]; //前部 dynamicItems.push(stcd); dynamicItems.push(stnm); //查詢條件數據 var datas={ "Stcd":$("#stnmCombo").combobox('getValue'), "StartTime":$("#StartTime").datebox('getValue'), "EndTime":$("#EndTime").datebox('getValue') } //查詢具體的數據 formLoader.load("querydata",datas,function(s){ //空白SPAN var blank={ title:' ', colspan:days*2+4 //動態得到COLSPAN的跨度,根據天數 } dynamicItems.push(blank); //var sss = s; //遍歷動態數組 // for(j=0;j<s.length;j++) // { //alert(s.DaynamicList[1].z0); //alert(s[7].DynamicList.z0); //動態載入庫水位數據 //庫水位 rz={ title:'庫水位', field:"DynamicList", formatter:function(value,row,index){ //alert(row); //return value.z1; //因為這是一個對象DynamicList,所以返回對象的值 //alert(value); var temp; $.each(value,function(i,option){ //alert(option); temp=option; }); return temp; } } //alert(s); //拼湊表頭 $.each(s[0].DynamicList, function(i,option){ //alert(i); //alert(i); rv={ title:'庫容', field:"DynamicList2", formatter:function(value,row,index) { return "-"; } } //詳細數據 var k=0; //設定一個值,匹配Z0,Z1,Z2。。。。。 var d = new Date($("#StartTime").datebox('getValue')); do{ //alert(i.substring(1)); d.setDate(d.getDate()+parseInt(i.substring(1))); //轉換成INT類型的 var RealDate=d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate(); //動態得到日期值 var details2={ title:RealDate, // width:150, colspan:2 } dynamicItemsAfter.push(details2); k+=2; break; //這里因為會執行i此結果 ,所以 BREAK掉 }while(days>k) //dynamicItemsAfter.push(details2); // dynamicItemsEnd.push(rz); // dynamicItemsEnd.push(rv); dynamicItemsEnd.push(rz); dynamicItemsEnd.push(rv); //dynamicItemsAfter.push(details2); }); // } //庫水位(平均) var rzAvg={ title:'庫水位', field:"DynamicList5", //這里隨便設一個Field formatter:function(value,row,index) { var k=row.DynamicList; //alert(k); //算出平均值 var temp=0; $.each(k,function(i,option){ //alert(option); //alert(i); temp+=Number(option); //alert(temp); }); //alert(temp); //return 0; //alert(temp); return temp/(days+1); } //width:150 } //alert(s[0].Stcd); dynamicItemsAfter.push(avg); dynamicItemsEnd.push(rzAvg); dynamicItemsEnd.push(rvAvg); dynamicCols.push(dynamicItems); dynamicCols.push(dynamicItemsAfter); dynamicCols.push(dynamicItemsEnd); //綁定動態列 gv.datagrid({ columns:dynamicCols, }); gv.datagrid( "dataBind" , { datas : s, striped:true, pagination : true, pageSize:15 }); //total(); }); }); //得到測站編碼 var dataCount=0; formLoader.load("getstnm","",function(data){ data.unshift({Stnm : "全部" , Stcd : "" }); $("#stnmCombo").combobox({ data:data, valueField:"Stcd", textField:"Stnm", editable:false, //panelHeight:"auto", onLoadSuccess:function() { //alert('1'); //alert(data[0].Stcd); $("#stnmCombo").combobox('setValue',data[0].Stcd); dataCount=data.length; }, onShowPanel:function() { if(dataCount.length>10) { $(this).combobox('panel').height(251); } } }); });
本例的難點在於,要構建一個動態的DTO實體類,因為我返回的是一個LIST<DTO的名稱>,因為列是不固定的,所以這個是一個難點,這個怎么實現呢?
其實大家細心的注意到了有一個Field叫做DynamicList我們把這個DYNAMICLIST打開看看里面的內部結構。
這里其實是因為我選擇了8個日期間隔的時間,所以就有8個元素在里面,如果我選擇了4天時間間隔呢?
這個是怎么實現的呢?
下面進入后台時間,其實后台是拼接的SQL,先給大家看看查詢SQL是怎么拼湊出來的。
public String querySql(ReservoirDayReportParam param) { StringBuffer sb=new StringBuffer(); sb.append("select b.STNM,r.STCD,"); //開始時間和結束時間 String startTime=param.getStartTime(); String endTime=param.getEndTime(); SimpleDateFormat format =new SimpleDateFormat("yyyy-mm-dd"); Calendar start=Calendar.getInstance(); Calendar end=Calendar.getInstance(); try { start.setTime(format.parse(startTime)); end.setTime(format.parse(endTime)); } catch(Exception e) { e.printStackTrace(); } //遍歷出時間 int count=0; while(start.compareTo((end))<=0) { String time=format.format(start.getTime()); String finalStart=time.concat(" 00:00:00"); //最終獲得的每天的開始時間 String finalEnd=time.concat(" 23:59:59"); //最終獲得的每天的結束時間 sb.append("max(case when r.TM between '"+finalStart+"' and '"+finalEnd+"' then r.RZ else 0 end) as z"+count+","); count++; start.add(Calendar.DAY_OF_MONTH, 1); //列的別名 } String tempBuffer=sb.substring(0,sb.length()-1); //把獲得的值的最后一個逗號去掉 StringBuffer lastBuff=new StringBuffer(); //新建一個字符串 lastBuff.append(tempBuffer); lastBuff.append(" from ST_RSVR_R r,ST_STBPRP_B b where r.stcd=b.stcd"); if(!param.getStcd().equals("")) { lastBuff.append(" and r.STCD='"+param.getStcd()+"'"); } lastBuff.append(" group by b.STNM,r.STCD"); return lastBuff.toString(); }
其中的ReservoirDayReportParam 是一個實體類,代碼都有注釋的,我就說說關鍵的,其實的動態列(水位)這一列,其實是根據傳入的開始時間和結束時間,來循環去把SQL拼湊出來,代碼不是太難,中間使用到了一個count的變量,用來給列起別名,比如z0,z1,z2,z3...等等。
那么這樣就實現了動態的拼接SQL,就是我有選擇了多少個日期間隔,就會在后台AS出多少個動態列,下面先給大家看看實體模型吧。
//開始時間和結束時間 private String startTime; private String endTime; public Map getDynamicList() { return dynamicList; } public void setDynamicList(Map dynamicList) { this.dynamicList = dynamicList; } //動態實體類 private Map dynamicList;
其中的dynamicList就是動態的,為什么是Map類型的?那是因為可以添加鍵值對。把形如z0,z1這樣的添加到里面去,這就實現了動態化。
開始已經說過了formLoader方法,那么我們要執行的這個方法,在后台優勢什么樣呢?
public List<ReservoirDayReportParam> queryData(ReservoirDayReportParam param) { // TODO Auto-generated method stub String sql=querySql(param); List<Object[]> dataFromSTCD=this.daoHelper.findBySql(sql); List<ReservoirDayReportParam> arrList=new ArrayList<ReservoirDayReportParam>(); List list = new ArrayList(); try { for(Object[] obj:dataFromSTCD) { ReservoirDayReportParam params=new ReservoirDayReportParam(); Map map=new LinkedHashMap(); //新建一個ARRLIST,用於存放動態列 params.setStnm(String.valueOf(obj[0])); params.setStcd(String.valueOf(obj[1])); //把動態列存到Map中去,然后分別設定鍵值對 for(int i=2;i<dataFromSTCD.get(0).length;i++) { map.put("z"+(i-2), obj[i]); } params.setDynamicList(map); arrList.add(params); } } catch(Exception e) { e.printStackTrace(); } return arrList; }
其中的querySql就是剛才的拼接SQL的方法。
首先得到拼接的SQL,那個findbysql方法是返回一個List集合的方法,公司框架,知道意思就行,大家可以無視。
具體思路就是從List中循環出結果,然后添加到實體類中去,然后再把每個實體類添加到arraylist中去,然后再返回。
具體的注釋已經寫了,JS代碼是主體,大家如果有不懂的地方,可以留言。