前段时间完成的一个项目的笔记
过程还算顺利,但是为了方便后面有需要的同事进行学习,就简单做了一下过程的笔记.方便后面有需要的同事进行查看.
##具体的需求
原文如下
各新能源场站必须添加超短期预测曲线监视界面,要求 3 月 31日前完成。
16 条预测曲线(15 分钟、30 分钟、45 分钟,……,240 分钟)
与实际出力在同一界面显示,场站值班人员必须会看预测曲线出力,省调
值班人员会不定时询问场站值班人员,不清楚者将按照调度违纪考核,严
重者吊销持证上岗证。
任务分配
差不多设计的任务都在我这儿了,现场学习的就不是我的任务了,至于具体的场站因为公司的缘故不便透漏,直说设计了.
通过经理的会议与分析,除了这个16条曲线外,另外还要添加96条曲线,针对96次预测的数据进行选择性展示. 没有具体的开发文档,说是可以直接新建一个页面进行存储也行.于是在原来的位置直接新建的一个页面,找到这个位置不轻松啊.
- 导航添加链接
//位置在\Web\PVForecast(s)\WebRoot\PVForecast\jsCommon\data\MenuData.js //别问为什么在js写的菜单,之前来到这儿我就奇怪很多天了.全部都是js写的页面. id : "menuInternalDataConnection", name : "光伏电站功率信息", itemdata : [{ text : "日有功过程线", url : serverMapPath() + "/Power/PowerFigureF.html", icon : '../jsCommon/images/menu-show.gif', hrefTarget:'_self' },{ text : "预测\\实际功率\\理论功率对比曲线", url : serverMapPath() + "/Power/ContrastPowerFigureF.html", icon : '../jsCommon/images/menu-show.gif', hrefTarget:'_self' },{//新加20180314 text : "超短期\\实际功率\\理论功率对比曲线", url : serverMapPath() + "/Power/ContrastUShortRealtimeTheory.html", icon : '../jsCommon/images/menu-show.gif', hrefTarget:'_self' },{ text : "实际\\预测辐照度、实际\\预测功率对比曲线", url : serverMapPath() + "/Power/ContrastLists.html", icon : '../jsCommon/images/menu-show.gif', hrefTarget:'_self' }]
- 添加对应页面
这里找到之后,添加一条还算轻松,有了连接之后,需要把对应的页面也同样添加出来,同样直接复制的页面ContrastPowerFigureF.html.和对应的ContrastUShortRealtimeTheory.js. 复制之后,页面需要修改的位置有对应的js需要修改,如下:
<script type="text/javascript" src="ContrastUShortRealtimeTheory.js">
- 实现页面对应的菜单
针对js部分,需要修改的就不少了.这里就简单做一个分析了.
//之前的数据显示菜单
var LineType = ['日前预测', '今日实测', '超短期预测(15分钟)', '超短期预测(1小时)', '超短期预测(4小时)','测光法应发理论功率','测光法可发理论功率','样板机法应发理论功率','样板机法可发理论功率'];
//现在的数据显示菜单
var LineType = ['日前预测', '今日实测', '超短期预测功率', '超短期预测单次发布','测光法应发理论功率','测光法可发理论功率','样板机法应发理论功率','样板机法可发理论功率'];
菜单现在是有了,为了方便的显示数据,就只是将其中的一条默认显示出来了,代码对比如下:
//之前的代码
if(LineType[i].contains('日前预测') || LineType[i].contains('今日实测') || LineType[i].contains('超短期预测(15分钟)') || LineType[i].contains('样板机法可发理论功率')){
obj.checked = true;
} else{
obj.checked = false;
}
//现在的代码
if(LineType[i].contains('日前预测') || LineType[i].contains('今日实测') || LineType[i].contains('超短期预测功率') || LineType[i].contains('样板机法可发理论功率')){
obj.checked = true;
} else{
obj.checked = false;
}
菜单现在是有了,但是具体的是选择的哪一条呢?还是没有选择的位置,于是需要两个选择框,为了和风格对应,只能选择本身的js带有的组件进行设计了,最后添加如下的代码总算是完成了.
var comboData = [//这里要是数据不多,我肯定直接复制几遍了
// ['超短期预测第15分钟', '0'],
// ['超短期预测第30分钟', '1'],
];
for(var i=0;i<16;i++){
var singleCombo=['超短期预测第'+(i+1)+'个点('+(i+1)*15+'分钟)', i];
comboData[i]=singleCombo;
}
MyEWISUtilObj.CreateCombox(comboData, comboSelectFunction);
//设置默认值
combo.setValue('超短期预测第一个点(15分钟)');
var comboDataInDay = [];
for(var i=0;i<96;i++){
var hour=parseInt(i/4);
var minute=i%4*15;
var newHour=hour<10?'0'+hour:hour;
var newMinute=minute==0?'00':minute;
var singleCombo=['超短期第'+(i+1)+'次预测('+newHour+':'+newMinute+')', i];
comboDataInDay[i]=singleCombo;
}
MyEWISUtilObj.CreateComboxInDay(comboDataInDay, comboInDaySelectFunction);
//设置默认值
var now=new Date();
var hour=now.getHours();
var minuteInFour=parseInt(now.getMinutes()/15);
selectTypeInDay=hour*4+minuteInFour+1;
var newHour=hour<10?'0'+hour:hour;
var newMinute=minuteInFour==0?'00':minuteInFour*15;
comboInDay.setValue('超短期第'+selectTypeInDay+'次预测('+newHour+':'+newMinute+')');//为了方便格式化日期输出我也是拼了
这里需要留意一下的是CreateComboxInDay方法是重载的,有几个js有同样的方法,但是都不能完成设计,因为他们用的是一个全局变量传递的参数.
//原来的方法
//创建选择Combox
CreateCombox:function(comboData,comboSelectFunction){
var store=new Ext.data.SimpleStore({
fields:['text','id'],
data:comboData
});
combo=new Ext.form.ComboBox({
id:'comboxType',
editable:false,
store:store,
displayField:'text',
valueField:'id',
typeAhead:true,
mode:'local',
triggerAction:'all',
//emptyText:'选择要显示的类型',
emptyText:'',
selsectOnFocus:true,
renderTo:'west',
width:200,
frame:true,
resizable:false,
listeners:{
'select':comboSelectFunction
}
});
},
//重载之后的新的方法,基本没有变化,就是一个全局变量的变化()
//创建选择Combox
CreateComboxInDay:function(comboData,comboSelectFunction){
var store=new Ext.data.SimpleStore({
fields:['text','id'],
data:comboData
});
comboInDay=new Ext.form.ComboBox({
id:'comboxTypeInDay',
editable:false,
store:store,
displayField:'text',
valueField:'id',
typeAhead:true,
mode:'local',
triggerAction:'all',
//emptyText:'选择要显示的类型',
emptyText:'',
selsectOnFocus:true,
renderTo:'west',
width:200,
frame:true,
resizable:false,
listeners:{
'select':comboSelectFunction
}
});
},
- 添加对应的相应事件
控件现在是有了,需要添加选择他们之后的一个方法,默认的显示的是第一个点和当前的时间点了,点击的响应函数如下:
//两个全局变量进行所选定的条目的存储了.
function comboSelectFunction() {
//grid 中根据后续点号使用filter过滤grid中的数据
selectType = this.selectedIndex;
}
function comboInDaySelectFunction() {
//grid 中根据后续点号使用filter过滤grid中的数据
selectTypeInDay = this.selectedIndex;
}
条目变化存储完毕之后,需要处理的就是点击查询之后的响应方法了,本来有一套自主查询的组建的,不过被前面部分开发人员改成了手动的查询,我也只能顺着下来继续了.
//原本的请求方法
url: '../action/ManyDatalist',
params: {
'beginDate':bY,
'endDate':eY,
'planpowerID':WindFarmCfg.WindFarms[selectedFarmIndex].ID,
'uplanpowerID': WindFarmCfg.WindFarms[selectedFarmIndex].UPlanPower.ID,
'rtpowerID':WindFarmCfg.WindFarms[selectedFarmIndex].RTPower.ID,
'planPowerType' : WindFarmCfg.WindFarms[selectedFarmIndex].PlanPower.Type,
'uPlanPowerType':WindFarmCfg.WindFarms[selectedFarmIndex].UPlanPower.Type,
Random: Math.round(Math.random() * 200)
},
//这个只是发送请求的部分,不过主要的区别也是在这里了.
url: '../action/ManyUSDatalist',
params: {
'beginDate':bY,
'endDate':eY,
'planpowerID':WindFarmCfg.WindFarms[selectedFarmIndex].ID,
'uplanpowerID': WindFarmCfg.WindFarms[selectedFarmIndex].UPlanPower.ID,
'rtpowerID':WindFarmCfg.WindFarms[selectedFarmIndex].RTPower.ID,
'planPowerType' : WindFarmCfg.WindFarms[selectedFarmIndex].PlanPower.Type,
'uPlanPowerType':WindFarmCfg.WindFarms[selectedFarmIndex].UPlanPower.Type,
'indexIn16':selectType,
'indexIn96':selectTypeInDay,
Random: Math.round(Math.random() * 200)
},
- 添加对应的接口
到了这里,不错了,就是再把接口重新写一遍,不能更改原来的,毕竟原来的业务还是需要正常运行.添加接口直接在配置文件处理了
<action path="/ManyDatalist" type="com.narisq.ewis.struts.ManyDatalistAction" />
<action path="/ManyUSDatalist" type="com.narisq.ewis.struts.ManyUSDatalistAction" />
新的方法和旧的差不多,就是根据自己的参数进行解析数据和存储数据了,新的方法的主要改动如下:
int indexIn16 = Integer.valueOf(request.getParameter("indexIn16").trim());
int indexIn96 = Integer.valueOf(request.getParameter("indexIn96").trim());
Map<String, Double> ss16pDataMap = new HashMap<String, Double>();// 共计96个点,有16条组合
Map<String, Double> ss96pDataMap = new HashMap<String, Double>();// 共计16个点,有96组不同组合
ss16pDataMap.put(simpleDateFormat.format(beginDate), -99d);
ss96pDataMap.put(simpleDateFormat.format(beginDate), -99d);
List<Double> ss16pData = manyDatalistDAO.getSuperShort16PowerList( linesVO, ss16pDataMap, markDate,indexIn16);
JSONArray superShort16Power = JSONArray.fromObject(ss16pData,config);
ParamDataSetObjList.put("superShort16Power", superShort16Power);
List<Double> ss96pData = manyDatalistDAO.getSuperShort96PowerList(linesVO, ss96pDataMap, markDate,indexIn96);
JSONArray superShort96Power = JSONArray.fromObject(ss96pData,config);
ParamDataSetObjList.put("superShort96Power", superShort96Power);
//一条查询语句大致如下了,不过我想你应该不会看的,太乱了.
int point = indexIn96;
StringBuffer sb = new StringBuffer();
sb.append(" select round(load,3) as sp, to_char(ybtime, 'yyyy-mm-dd hh24:mi:ss') as timekey");
sb.append(" from fd_plan_load");
sb.append(" where (((((ybtime > to_date('" + linesVO.getbY()+ "', 'yyyy-mm-dd hh24-mi-ss') and");
sb.append(" ybtime <= to_date('" + linesVO.geteY()+ "', 'yyyy-mm-dd hh24-mi-ss')) and");
sb.append(" fbtime = to_date('" + linesVO.getbY()+ "', 'yyyy-mm-dd hh24-mi-ss') + " + 15 * point + " / 24 / 60)) and");
sb.append(" engineid in (" + linesVO.getUplanpowerID()+ ")) and type = " + linesVO.getuPlanPowerType() + ")");
sb.append(" order by ybtime");
System.out.println();
System.out.println("_______________超短期预测功率第"+indexIn96+"个(总96)数据SQL如下:");
System.out.println(sb.toString());
return sb.toString();
- 针对返回数据的解析
到这里的话,目前数据都返回过来了,但是还没有进行数据的显示,不过好在组件方便扩展,还算顺利.添加到扩展的代码如下:
switch (checkedType[i]) {
case 0:
arr = beforePlanArray;
break;
case 1:
arr = rtArray;
break;
case 2:
arr = ushortPlanArray16;
break;
case 3:
arr = ushortPlanArray96;
break;
case 4:
arr = theoryLoadCgfAllArray;
break;
case 5:
arr = theoryLoadCgfArray;
break;
case 6:
arr = theoryLoadYbjAllArray;
break;
case 7:
arr = theoryLoadYbjArray;
break;
}
//片段节选
if (LineType[checkedType[i]] == '超短期预测功率') {
var DataSetStyle = [
{
"name": "color",
"value": "07F856"
},
{
"name": "anchorBorderColor",
"value": "07F856"
},
{
"name": "anchorBgColor",
"value": "07F856"
}
];
myFusionChart.addAttributes(ds, DataSetStyle);
}
if (LineType[checkedType[i]] == '超短期预测单次发布') {
var DataSetStyle = [
{
"name": "color",
"value": "000000"
},
{
"name": "anchorBorderColor",
"value": "000000"
},
{
"name": "anchorBgColor",
"value": "000000"
}
];
myFusionChart.addAttributes(ds, DataSetStyle);
}
到这里,大致功能就已经实现了.
风电任务分配
前面的是光伏的设计更改了,本来页面区别不是很大的,但是看了代码之后发现代码的风格区别太大了!
- 解决界面显示bug
首先存在js的括号不对应的关系,直接轻松解决,别问为什么直接通过了.
接着存在数据加载时候出现无限等待的状况,分析之后发现是因为有些数据没有,并且赋值为null,然后获取长度导致的,于是直接跳过相关部分的代码,将没有数据的部分直接跳过.
//之前代码:
// 实际功率
if ("true" == ManyPlanDisplayParam.RTPower.On) {
powerdataArray.push(responseObject.actualPower);
powerdataArrayChart.push(responseObject.actualPower);
}
//之后代码:
// 实际功率
if ("true" == ManyPlanDisplayParam.RTPower.On) {
if (responseObject.actualPower != null) {
powerdataArray.push(responseObject.actualPower);
powerdataArrayChart.push(responseObject.actualPower);
}
}
但是问题没有解决完,因为在数据展示的时候,是把所有已经勾选的数据都加载出来,前面的做法是直接跳过没有查询到的数据了,所以要重新整改一下,现在最后的样子:
// 实际功率
if ("true" == ManyPlanDisplayParam.RTPower.On) {
if (responseObject.actualPower != null) {
powerdataArray.push(responseObject.actualPower);
powerdataArrayChart.push(responseObject.actualPower);
} else {
powerdataArray.push([]);
powerdataArrayChart.push([]);
}
}
展示所有数据的代码在这儿:
var ds2 = xml.createElementNS(null, "dataset");
myFusionChart.addAttributes(ds2, powerUsageAttributes);
var dataArrayLen = powerdataArrayChart[PowercheckedType[i]].length;
这里并没有判断就直接展示所有的数据了,所以为了防止出现空指针状况,直接给不存在数据的数组赋值为长度0数组.然后现在基本正常了.
- 添加对应的连接
这里和前面一样,找到对应的位置然后直接添加相关的条目就行.//sample if ("true" == displayPageConfig.MangForecastCampare.On) { var MangForecastCamparePage = { text : "多曲线对比", url : serverMapPath() + "/Power/ManyForecastContrast.html", icon : '../jsCommon/images/menu-show.gif', hrefTarget : '_self' }; LoadMenu.itemdata.push(MangForecastCamparePage); } //add if ("true" == displayPageConfig.MangPowerForecastCampare.On) { var MangForecastCamparePage = { text : "多曲线对比", url : serverMapPath() + "/Power/ManyPowerForecastContrast.html", icon : '../jsCommon/images/menu-show.gif', hrefTarget : '_self' }; LoadMenu.itemdata.push(MangPowerForecastCamparePage); }
这里注意到这个代码里面有个部分是读取配置的,所以还是要找到对应的配置文件DisplayPageCfg.xml,并添加相关的条目.
<LoadInfo On="true" />
<UltraForecast On="true" />
<ShortPlanForecast On="true" />
<MiddleForeCast On="true"/>
<MangForecastCampare On="true" />
<MangPowerForecastCampare On="true" /><!--wkupdate 20180408-->
- 实现界面
现在连接有了,直接把对应的界面,以及界面对应的js的连接修改好了之后就完成了界面了,
界面有了,但是还有许多不需要的曲线,通过下面的代码,我们可以知道程序是直接读取的配置文件.
function getCfgInfo() { // 更加配置文件中的配置构造数据类型选择面板 var ManyPlanDisplayParam = WebCfg.WebCfg.ManyPlanDisplayParam; // 实时功率是否显示 if ("true" == ManyPlanDisplayParam.RTPower.On) { PowerLineTag.push(ManyPlanDisplayParam.RTPower.DisplayTag); if ("true" == ManyPlanDisplayParam.RTPower.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[0]); } // 前日20时功率是否显示 if ("true" == ManyPlanDisplayParam.PlanPower20.On) { PowerLineTag.push(ManyPlanDisplayParam.PlanPower20.DisplayTag); if ("true" == ManyPlanDisplayParam.PlanPower20.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[1]); } // 前日20时修正是否显示 if ("true" == ManyPlanDisplayParam.PlanPowerCorByCapacity20.On) { PowerLineTag .push(ManyPlanDisplayParam.PlanPowerCorByCapacity20.DisplayTag); if ("true" == ManyPlanDisplayParam.PlanPowerCorByCapacity20.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[2]); } // 人工修正短期功率显示 if ("true" == ManyPlanDisplayParam.PlanPowerCorByMaual.On) { PowerLineTag.push(ManyPlanDisplayParam.PlanPowerCorByMaual.DisplayTag); if ("true" == ManyPlanDisplayParam.PlanPowerCorByMaual.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[12]); } // 昨日08时是否进行显示 if ("true" == ManyPlanDisplayParam.PlanPower08.On) { PowerLineTag.push(ManyPlanDisplayParam.PlanPower08.DisplayTag); if ("true" == ManyPlanDisplayParam.PlanPower08.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[3]); } // 昨日08时修正是否进行显示 if ("true" == ManyPlanDisplayParam.PlanPowerCorByCapacity08.On) { PowerLineTag .push(ManyPlanDisplayParam.PlanPowerCorByCapacity08.DisplayTag); if ("true" == ManyPlanDisplayParam.PlanPowerCorByCapacity08.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[4]); } // 超短期功率1 if ("true" == ManyPlanDisplayParam.UPlanPower1.On) { PowerLineTag.push(ManyPlanDisplayParam.UPlanPower1.DisplayTag); if ("true" == ManyPlanDisplayParam.UPlanPower1.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[5]); } // 超短期功率2 if ("true" == ManyPlanDisplayParam.UPlanPower2.On) { PowerLineTag.push(ManyPlanDisplayParam.UPlanPower2.DisplayTag); if ("true" == ManyPlanDisplayParam.UPlanPower2.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[6]); } // 超短期功率3 if ("true" == ManyPlanDisplayParam.UPlanPower3.On) { PowerLineTag.push(ManyPlanDisplayParam.UPlanPower3.DisplayTag); if ("true" == ManyPlanDisplayParam.UPlanPower3.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[7]); } // 超短期功率4 if ("true" == ManyPlanDisplayParam.UPlanPower4.On) { PowerLineTag.push(ManyPlanDisplayParam.UPlanPower4.DisplayTag); if ("true" == ManyPlanDisplayParam.UPlanPower4.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[8]); } // 次日发电计划 if ("true" == ManyPlanDisplayParam.PowerShedule.On) { PowerLineTag.push(ManyPlanDisplayParam.PowerShedule.DisplayTag); if ("true" == ManyPlanDisplayParam.PowerShedule.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[9]); } // 实时发电计划 if ("true" == ManyPlanDisplayParam.RTPowerShedule.On) { PowerLineTag.push(ManyPlanDisplayParam.RTPowerShedule.DisplayTag); if ("true" == ManyPlanDisplayParam.RTPowerShedule.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[10]); } // 发电计划执行 if ("true" == ManyPlanDisplayParam.PowerSheduleExe.On) { PowerLineTag.push(ManyPlanDisplayParam.PowerSheduleExe.DisplayTag); if ("true" == ManyPlanDisplayParam.PowerSheduleExe.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[11]); } // 中期预测功率显示 if ("true" == ManyPlanDisplayParam.MidForecast.On) { PowerLineTag.push(ManyPlanDisplayParam.MidForecast.DisplayTag); if ("true" == ManyPlanDisplayParam.MidForecast.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[13]); } // 样板法理论功率显示 if ("true" == ManyPlanDisplayParam.SampleTheoryPower.On) { PowerLineTag.push(ManyPlanDisplayParam.SampleTheoryPower.DisplayTag); if ("true" == ManyPlanDisplayParam.SampleTheoryPower.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[14]); } // 测风法理论功率显示 if ("true" == ManyPlanDisplayParam.TowerTheoryPower.On) { PowerLineTag.push(ManyPlanDisplayParam.TowerTheoryPower.DisplayTag); if ("true" == ManyPlanDisplayParam.TowerTheoryPower.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[15]); } // 所有风机机头风速法理论功率显示 if ("true" == ManyPlanDisplayParam.AllengineTheoryPower.On) { PowerLineTag.push(ManyPlanDisplayParam.AllengineTheoryPower.DisplayTag); if ("true" == ManyPlanDisplayParam.AllengineTheoryPower.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[16]); } // 部分风机机头风速法理论功率显示 if ("true" == ManyPlanDisplayParam.PartengineTheoryPower.On) { PowerLineTag .push(ManyPlanDisplayParam.PartengineTheoryPower.DisplayTag); if ("true" == ManyPlanDisplayParam.PartengineTheoryPower.Checked) PowerLineChec.push(true); else PowerLineChec.push(false); PowerLineID.push(LineIDAllPower[17]); } var WindDisplayParam = WebCfg.WebCfg.ManyPlanDisplayParam; // 实时风速是否显示 if ("true" == WindDisplayParam.RTWind.On) { WindLineTag.push(WindDisplayParam.RTWind.DisplayTag); if ("true" == WindDisplayParam.RTWind.Checked) WindLineChec.push(true); else WindLineChec.push(false); WindLineID.push(LineIDAllWind[0]); } // 前日20时风速是否显示 if ("true" == WindDisplayParam.PLanWind20.On) { WindLineTag.push(WindDisplayParam.PLanWind20.DisplayTag); if ("true" == WindDisplayParam.PLanWind20.Checked) WindLineChec.push(true); else WindLineChec.push(false); WindLineID.push(LineIDAllWind[1]); } // 昨日08时是否显示 if ("true" == WindDisplayParam.PLanWind08.On) { WindLineTag.push(WindDisplayParam.PLanWind08.DisplayTag); if ("true" == WindDisplayParam.PLanWind08.Checked) WindLineChec.push(true); else WindLineChec.push(false); WindLineID.push(LineIDAllWind[2]); } // 超短期风速是否进行显示 if ("true" == WindDisplayParam.UPLanWind1.On) { WindLineTag.push(WindDisplayParam.UPLanWind1.DisplayTag); if ("true" == WindDisplayParam.UPLanWind1.Checked) WindLineChec.push(true); else WindLineChec.push(false); WindLineID.push(LineIDAllWind[3]); } // 超短期风速是否进行显示 if ("true" == WindDisplayParam.UPLanWind2.On) { WindLineTag.push(WindDisplayParam.UPLanWind2.DisplayTag); if ("true" == WindDisplayParam.UPLanWind2.Checked) WindLineChec.push(true); else WindLineChec.push(false); WindLineID.push(LineIDAllWind[4]); } // 超短期风速是否进行显示 if ("true" == WindDisplayParam.UPLanWind3.On) { WindLineTag.push(WindDisplayParam.UPLanWind3.DisplayTag); if ("true" == WindDisplayParam.UPLanWind3.Checked) WindLineChec.push(true); else WindLineChec.push(false); WindLineID.push(LineIDAllWind[6]); } // 超短期风速是否进行显示 if ("true" == WindDisplayParam.UPLanWind4.On) { WindLineTag.push(WindDisplayParam.UPLanWind4.DisplayTag); if ("true" == WindDisplayParam.UPLanWind4.Checked) WindLineChec.push(true); else WindLineChec.push(false); WindLineID.push(LineIDAllWind[7]); } // 中期风速是否进行显示 if ("true" == WindDisplayParam.MidPlanWind.On) { WindLineTag.push(WindDisplayParam.MidPlanWind.DisplayTag); if ("true" == WindDisplayParam.MidPlanWind.Checked) WindLineChec.push(true); else WindLineChec.push(false); WindLineID.push(LineIDAllWind[5]); } createArray(); }
这里的话,需要修改页面,先要添加对应的配置.修改之后的配置如下,风速部分的代码不变,但是全部不展示.
<ManyPowerPlanDisplayParam>
<RTPower On="true" DisplayTag="实际功率" Checked="true" />
<PlanPower20 On="false" DisplayTag="短期预测功率" Checked="false" />
<PlanPowerCorByCapacity20 On="true" DisplayTag="短期预测功率" Checked="true" />
<PlanPowerCorByMaual On="true" DisplayTag="人工修正预测功率" Checked="true" />
<PlanPower08 On="false" DisplayTag="短期预测功率" Checked="false" />
<PlanPowerCorByCapacity08 On="false" DisplayTag="短期预测功率" Checked="false" />
<UPlanPower1 On="true" Type="401" Point="1" DisplayTag="超短期预测功率单次发布" Checked="true" />
<UPlanPower2 On="true" Type="401" Point="2" DisplayTag="超短期预测功率" Checked="false" /><!--updaate-->
<UPlanPower3 On="false" Type="401" Point="1" DisplayTag="超短期预测功率(15分钟)" Checked="true" />
<UPlanPower4 On="false" Type="401" Point="2" DisplayTag="超短期预测功率(30分钟)" Checked="false" />
<PowerShedule On="false" DisplayTag="次日发电计划" Checked="false" />
<RTPowerShedule On="false" DisplayTag="实时发电计划" Checked="false" />
<PowerSheduleExe On="false" DisplayTag="发电计划执行" Checked="false" />
<MidForecast On="true" DisplayTag="中期功率预测" Checked="false" />
<SampleTheoryPower On="true" Point="1" DisplayTag="理论功率(样板机)" Checked="true" />
<TowerTheoryPower On="false" Point="2" DisplayTag="理论功率(测风)" Checked="false" />
<AllengineTheoryPower On="false" Point="3" DisplayTag="理论功率(所有风机机头风速)" Checked="false" />
<PartengineTheoryPower On="tfalse" Point="4" DisplayTag="理论功率(除检修外机头风速)" Checked="false" />
<RTWind On="false" DisplayTag="实测风速" Checked="false" />
<PLanWind20 On="false" DisplayTag="短期预测风速" Checked="false" />
<PLanWind08 On="false" DisplayTag="短期预测风速" Checked="false" />
<UPLanWind1 On="false" Type="201" Point="1" DisplayTag="超短期预测风速(15分钟)" Checked="false" />
<UPLanWind2 On="false" Type="201" Point="2" DisplayTag="超短期预测风速(30分钟)" Checked="false" />
<UPLanWind3 On="false" Type="201" Point="3" DisplayTag="超短期预测风速(45分钟)" Checked="false" />
<UPLanWind4 On="false" Type="201" Point="4" DisplayTag="超短期预测风速(60分钟)" Checked="false" />
<MidPlanWind On="false" DisplayTag="中期预测风速" Checked="false" />
</ManyPowerPlanDisplayParam>
然后把,对应的js部分的关于风速的不变,在将重复的几个功率不变,添加需要的部分就行最好是后面添加,不用更改前面的数据,上面的部分有js的完全展现,删除大块的显示部分应该是没有难度的.
// 功率 ID
var LineIDAllPower = [ 'rtload', 'before20planload', 'before20planloadmodify',
'before08planload', 'before08planloadmodify',// 实测功率,短期预测功率
'shortplanload1', 'shortplanload2', 'shortplanload3', 'shortplanload4',// 超短期预测功率
'planschedule', 'rtplanschedule', 'planscheduleExe',// 发电计划执行
'before20Maualplanload', 'midplanload',// 人工修正,中期预测
'sampletheoryload','towertheoryload','allenginetheoryload','partenginetheoryload,'//理论功率(样板法、测风法、所有风机机头风速法、部分风机法)
'shortplanload5', 'shortplanload6'//"wkadd 20180417 for single power "
];
// 风速 ID
var LineIDAllWind = [ 'rtwindsp', 'before20planwind', 'before08planwind',
'shortplanwind1', 'shortplanwind2', 'midplanwind', 'shortplanwind3',
'shortplanwind4' ];
然后就是同样的把两个时间节点选择的控件写一下.
//在function createArray()结尾部分添加
var comboData = [
//['超短期预测第15分钟', '0'],
//['超短期预测第30分钟', '1'],
];
for(var i=0;i<16;i++){
var singleCombo=['超短期预测第'+(i+1)+'个点('+(i+1)*15+'分钟)', i];
comboData[i]=singleCombo;
}
MyEWISUtilObj.CreateComboxInOnce(comboData, comboInOnceSelectFunction);
//设置默认值
comboInOnce.setValue('超短期预测第一个点(15分钟)');
var comboDataInDay = [];
for(var i=0;i<96;i++){
var hour=parseInt(i/4);
var minute=i%4*15;
var newHour=hour<10?'0'+hour:hour;
var newMinute=minute==0?'00':minute;
var singleCombo=['超短期第'+(i+1)+'次预测('+newHour+':'+newMinute+')', i];
comboDataInDay[i]=singleCombo;
}
MyEWISUtilObj.CreateComboxInDay(comboDataInDay, comboInDaySelectFunction);
//设置默认值
var now=new Date();
var hour=now.getHours();
var minuteInFour=parseInt(now.getMinutes()/15);
selectTypeInDay=hour*4+minuteInFour+1;
var newHour=hour<10?'0'+hour:hour;
var newMinute=minuteInFour==0?'00':minuteInFour*15;
comboInDay.setValue('超短期第'+selectTypeInDay+'次预测('+newHour+':'+newMinute+')');
///WindForecast/jsCommon/Mcommand/MyEWISUtil.js的添加代码
//创建选择Combox
CreateComboxInDay:function(comboData,comboSelectFunction){
var store=new Ext.data.SimpleStore({
fields:['text','id'],
data:comboData
});
comboInDay=new Ext.form.ComboBox({
id:'comboxTypeInDay',
editable:false,
store:store,
displayField:'text',
valueField:'id',
typeAhead:true,
mode:'local',
triggerAction:'all',
//emptyText:'选择要显示的类型',
emptyText:'',
selsectOnFocus:true,
renderTo:'west',
width:200,
frame:true,
resizable:false,
listeners:{
'select':comboSelectFunction
}
});
},
//创建选择Combox
CreateComboxInOnce:function(comboData,comboSelectFunction){
var store=new Ext.data.SimpleStore({
fields:['text','id'],
data:comboData
});
comboInOnce=new Ext.form.ComboBox({
id:'comboxTypeInOnce',
editable:false,
store:store,
displayField:'text',
valueField:'id',
typeAhead:true,
mode:'local',
triggerAction:'all',
//emptyText:'选择要显示的类型',
emptyText:'',
selsectOnFocus:true,
renderTo:'west',
width:200,
frame:true,
resizable:false,
listeners:{
'select':comboSelectFunction
}
});
},
//对应的还有几个全局变量和响应函数
var selectTypeInDay = null;
var selectTypeInOnce = null;
var comboInOnce = null;
var comboInDay = null;
function comboInOnceSelectFunction() {
//grid 中根据后续点号使用filter过滤grid中的数据
selectType = this.selectedIndex;
}
function comboInDaySelectFunction() {
//grid 中根据后续点号使用filter过滤grid中的数据
selectTypeInDay = this.selectedIndex;
}
现在相应函数和对应的数据保存的变量都有了,剩下的就是响应函数的处理了,用来获取数据.
//原来代码
var requestConfig = {
url : '../action/manyForecastContrastAction',
timeout : 60000,
params : {
'now' : fbtime.format('Y-m-d H-i-s'),
'beginDate' : bY.format('Y-m-d H-i-s'),
'endDate' : eY.format('Y-m-d H-i-s'),
'windFarmid' : WindFarmCfg.WindFarms[currentSelectedIndex].ID,
'towerid' : WindFarmCfg.WindFarms[currentSelectedIndex].RTWindTowerSet.WindTower[currentTowerSelectedIndex].ID,
'layerField' : WindFarmCfg.WindFarms[currentSelectedIndex].RTWindTowerSet.WindTower[currentTowerSelectedIndex].LayerMapCfg[currentLayerHeightSelectedIndex].TableField
.toLowerCase()
+ "avgsp",
'tpid' : WindFarmCfg.WindFarms[currentSelectedIndex].WeatherTPSet.WeatherTP[currentWeatherSelectedIndex].ID,
'layer' : WindFarmCfg.WindFarms[currentSelectedIndex].WeatherTPSet.WeatherTP[currentWeatherSelectedIndex].LayerMapCfg[currentWeatherHeightSelectedIndex].RealLayer,
'ultraShortId' : WindFarmCfg.WindFarms[currentSelectedIndex].UltraForecastSet.UltraTP[currentUltraShortSelectedIndex].ID,
'ultraShortLayer' : WindFarmCfg.WindFarms[currentSelectedIndex].UltraForecastSet.UltraTP[currentUltraShortSelectedIndex].LayerMapCfg[currentUltraShortHeightSelectedIndex].RealLayer,
'shortPowerPoint' : WebCfg.WebCfg.ManyPlanDisplayParam.UPlanPower1.Point,
'shortPowerPoint2' : WebCfg.WebCfg.ManyPlanDisplayParam.UPlanPower2.Point,
'shortPowerPoint3' : WebCfg.WebCfg.ManyPlanDisplayParam.UPlanPower3.Point,
'shortPowerPoint4' : WebCfg.WebCfg.ManyPlanDisplayParam.UPlanPower4.Point,
'shortPowerType' : WebCfg.WebCfg.ManyPlanDisplayParam.UPlanPower1.Type,
'shortPowerType2' : WebCfg.WebCfg.ManyPlanDisplayParam.UPlanPower2.Type,
'shortPowerType3' : WebCfg.WebCfg.ManyPlanDisplayParam.UPlanPower3.Type,
'shortPowerType4' : WebCfg.WebCfg.ManyPlanDisplayParam.UPlanPower4.Type,
'shortWindPoint' : WebCfg.WebCfg.ManyPlanDisplayParam.UPLanWind1.Point,
'shortWindPoint2' : WebCfg.WebCfg.ManyPlanDisplayParam.UPLanWind2.Point,
'shortWindPoint3' : WebCfg.WebCfg.ManyPlanDisplayParam.UPLanWind3.Point,
'shortWindPoint4' : WebCfg.WebCfg.ManyPlanDisplayParam.UPLanWind4.Point,
'shortWindType' : WebCfg.WebCfg.ManyPlanDisplayParam.UPLanWind1.Type,
'shortWindType2' : WebCfg.WebCfg.ManyPlanDisplayParam.UPLanWind2.Type,
'shortWindType3' : WebCfg.WebCfg.ManyPlanDisplayParam.UPLanWind3.Type,
'shortWindType4' : WebCfg.WebCfg.ManyPlanDisplayParam.UPLanWind4.Type,
'stPowerType' : stPowerType,
'midPowerType' : WindFarmCfg.WindFarms[currentSelectedIndex].MidForecast.showtype,
'stWindType' : '1',
'midWindType' : '1',
'corPowerType' : WindFarmCfg.WindFarms[currentSelectedIndex].PlanPower.ManualType,
'inputdataStr' : inputdataStr,
Random : Math.round(Math.random() * 200)
},
//现在代码
var requestConfig = {
url : '../action/manyPowerForecastContrastAction',
timeout : 60000,
params : {
'now' : fbtime.format('Y-m-d H-i-s'),
'beginDate' : bY.format('Y-m-d H-i-s'),
'endDate' : eY.format('Y-m-d H-i-s'),
'windFarmid' : WindFarmCfg.WindFarms[currentSelectedIndex].ID,
'towerid' : WindFarmCfg.WindFarms[currentSelectedIndex].RTWindTowerSet.WindTower[currentTowerSelectedIndex].ID,
'layerField' : WindFarmCfg.WindFarms[currentSelectedIndex].RTWindTowerSet.WindTower[currentTowerSelectedIndex].LayerMapCfg[currentLayerHeightSelectedIndex].TableField
.toLowerCase()
+ "avgsp",
'tpid' : WindFarmCfg.WindFarms[currentSelectedIndex].WeatherTPSet.WeatherTP[currentWeatherSelectedIndex].ID,
'layer' : WindFarmCfg.WindFarms[currentSelectedIndex].WeatherTPSet.WeatherTP[currentWeatherSelectedIndex].LayerMapCfg[currentWeatherHeightSelectedIndex].RealLayer,
'ultraShortId' : WindFarmCfg.WindFarms[currentSelectedIndex].UltraForecastSet.UltraTP[currentUltraShortSelectedIndex].ID,
'ultraShortLayer' : WindFarmCfg.WindFarms[currentSelectedIndex].UltraForecastSet.UltraTP[currentUltraShortSelectedIndex].LayerMapCfg[currentUltraShortHeightSelectedIndex].RealLayer,
'shortPowerPoint' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPlanPower1.Point,
'shortPowerPoint2' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPlanPower2.Point,
'shortPowerPoint3' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPlanPower3.Point,
'shortPowerPoint4' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPlanPower4.Point,
'shortPowerType' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPlanPower1.Type,
'shortPowerType2' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPlanPower2.Type,
'shortPowerType3' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPlanPower3.Type,
'shortPowerType4' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPlanPower4.Type,
'shortWindPoint' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPLanWind1.Point,
'shortWindPoint2' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPLanWind2.Point,
'shortWindPoint3' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPLanWind3.Point,
'shortWindPoint4' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPLanWind4.Point,
'shortWindType' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPLanWind1.Type,
'shortWindType2' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPLanWind2.Type,
'shortWindType3' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPLanWind3.Type,
'shortWindType4' : WebCfg.WebCfg.ManyPowerPlanDisplayParam.UPLanWind4.Type,
'stPowerType' : stPowerType,
'midPowerType' : WindFarmCfg.WindFarms[currentSelectedIndex].MidForecast.showtype,
'stWindType' : '1',
'midWindType' : '1',
'corPowerType' : WindFarmCfg.WindFarms[currentSelectedIndex].PlanPower.ManualType,
'inputdataStr' : inputdataStr,
'indexIn16' : selectTypeInOnce,
'indexIn96' : selectTypeInDay,
Random : Math.round(Math.random() * 200)
},
接口的代码写好了,现在需要数据处理的接口,直接还是之前的复制一下之后作为处理就行.
private String indexIn16="1";
private String indexIn96="1";
public String getIndexIn16() {
return indexIn16;
}
public void setIndexIn16(String indexIn16) {
this.indexIn16 = indexIn16;
}
public String getIndexIn96() {
return indexIn96;
}
public void setIndexIn96(String indexIn96) {
this.indexIn96 = indexIn96;
}
if (StringUtils.isNotBlank(request.getParameter("indexIn16"))) {
linesVO.setCorPowerType(request.getParameter("indexIn16"));
}
if (StringUtils.isNotBlank(request.getParameter("indexIn96"))) {
linesVO.setCorPowerType(request.getParameter("indexIn96"));
}
Map<String, Double> ss16pDataMap = new HashMap<String, Double>();// 超短期预测功率(15分钟)
Map<String, Double> ss96pDataMap = new HashMap<String, Double>();// 超短期预测功率(15分钟)
if (strInputStr.indexOf("shortplanload1") != -1) {
List<Double> ss16pData = manyForecastContrastDAO
.getSuperShort16PowerList(linesVO, ss16pDataMap,
markDate);
JSONArray superShort16Power = JSONArray.fromObject(ss16pData,
config);
ParamDataSetObjList.put("superShort16Power", superShort16Power);
}
if (strInputStr.indexOf("shortplanload2") != -1) {
List<Double> ss96pData = manyForecastContrastDAO
.getSuperShort96PowerList(linesVO, ss96pDataMap,
markDate);
JSONArray superShort96Power = JSONArray.fromObject(ss96pData,
config);
ParamDataSetObjList.put("superShort96Power", superShort96Power);
}
//超短期预测功率(15分钟)
public List<Double> getSuperShort16PowerList(ManyPowerForecastContrastVO linesVO,Map<String, Double> initMap,List<String> dateKeyList){
return map2list( dateKeyList, getResutSet(this.getSQLss16p(linesVO), initMap));
}
//超短期预测功率(30分钟)
public List<Double> getSuperShort96PowerList(ManyPowerForecastContrastVO linesVO,Map<String, Double> initMap,List<String> dateKeyList){
return map2list( dateKeyList, getResutSet(this.getSQLss96p(linesVO), initMap));
}
//超短期预测功率(15分钟)各个共48个点SQL
public String getSQLss16p(ManyPowerForecastContrastVO linesVO){
int point=Integer.parseInt(linesVO.getIndexIn16())+1;
StringBuffer sb = new StringBuffer();
sb.append(" select round(load,3) as sp, to_char(ybtime, 'yyyy-mm-dd hh24-mi-ss') as timekey");
sb.append(" from fd_plan_load");
sb.append(" where (((((ybtime > to_date('"+linesVO.getBegindate()+"', 'yyyy-mm-dd hh24-mi-ss') and");
sb.append(" ybtime <= to_date('"+linesVO.getEnddate()+"', 'yyyy-mm-dd hh24-mi-ss')) and");
//sb.append(" fbtime = (ybtime - "+15*point+" / 24 / 60)) or");
sb.append(" fbtime = to_date('"+linesVO.getNow()+"', 'yyyy-mm-dd hh24-mi-ss')+"+15*point+"/24/60)) and");
sb.append(" engineid in ("+linesVO.getWindFarmid()+")) and type = "+linesVO.getShortPowerType()+")");
sb.append(" order by ybtime");
System.out.println();
System.out.println("_______________超短期预测功率("+15*point+"分钟)SQL如下:");
System.out.println(sb.toString());
return sb.toString();
}
//超短期预测功率(15分钟)96个SQL
public String getSQLss96p(ManyPowerForecastContrastVO linesVO){
int point=Integer.parseInt(linesVO.getIndexIn96());
StringBuffer sb = new StringBuffer();
sb.append(" select load as sp, to_char(ybtime, 'yyyy-mm-dd hh24-mi-ss') as timekey");
sb.append(" from fd_plan_load");
sb.append(" where ((((((ybtime > to_date('"+linesVO.getBegindate()+"', 'yyyy-mm-dd hh24-mi-ss') and");
sb.append(" ybtime <= to_date('"+linesVO.getEnddate()+"', 'yyyy-mm-dd hh24-mi-ss')) and");
sb.append(" fbtime = (ybtime - "+15*point+" / 24 / 60)) or");
sb.append(" fbtime = to_date('"+linesVO.getNow()+"', 'yyyy-mm-dd hh24-mi-ss')) and");
sb.append(" fbtime != (ybtime)) and");
sb.append(" engineid in ("+linesVO.getWindFarmid()+")) and type = "+linesVO.getShortPowerType2()+")");
sb.append(" order by ybtime");
System.out.println();
System.out.println("_______________超短期预测功率第"+point +"个(总96)数据SQL如下:");
System.out.println(sb.toString());
return sb.toString();
}
- 针对返回数据的解析 数据现在有了,需要把数据展示出来.如果一切按照之前的数据处理格式的话,现在基本没有多大的需要更改的地方,需要修改的地方就只是根据数据库的配置,直接进行相对应的数据展示就行了.
遇到的问题需要注意的是,不要把两个超短期的数据弄反了.
数据如果不是完全一致的话,会导致数据表格信息不一致,之前为了干净,直接删除风电的代码,后来数据没有显示全,只能恢复风电部分,不过直接让他不显示罢了,后面这个部分可以优化.
另外需要注意的是风电和光伏的超短期类型不同,风电是401,光伏是201,按需修改配置即可.
说明
过程看起来还算顺利,不过其中还是遇到不少需要解决的问题,尤其是时间处理需要小心,不小心就错位了,或者不是按照自己需要的格式输出了.
由于代码属于公司,很多代码都是节选的,所以不能单独运行了.
20180314完成光伏记录的笔记
20180404着手风电的功能实现以及笔记