前段时间完成的一个项目的笔记

过程还算顺利,但是为了方便后面有需要的同事进行学习,就简单做了一下过程的笔记.方便后面有需要的同事进行查看.

##具体的需求

原文如下

各新能源场站必须添加超短期预测曲线监视界面,要求 3 月 31日前完成。
16 条预测曲线(15 分钟、30 分钟、45 分钟,……,240 分钟)
与实际出力在同一界面显示,场站值班人员必须会看预测曲线出力,省调
值班人员会不定时询问场站值班人员,不清楚者将按照调度违纪考核,严
重者吊销持证上岗证。

任务分配

差不多设计的任务都在我这儿了,现场学习的就不是我的任务了,至于具体的场站因为公司的缘故不便透漏,直说设计了.

通过经理的会议与分析,除了这个16条曲线外,另外还要添加96条曲线,针对96次预测的数据进行选择性展示. 没有具体的开发文档,说是可以直接新建一个页面进行存储也行.于是在原来的位置直接新建的一个页面,找到这个位置不轻松啊.

这里找到之后,添加一条还算轻松,有了连接之后,需要把对应的页面也同样添加出来,同样直接复制的页面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);

}

到这里,大致功能就已经实现了.

风电任务分配

前面的是光伏的设计更改了,本来页面区别不是很大的,但是看了代码之后发现代码的风格区别太大了!

首先存在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数组.然后现在基本正常了.

这里注意到这个代码里面有个部分是读取配置的,所以还是要找到对应的配置文件DisplayPageCfg.xml,并添加相关的条目.

			<LoadInfo On="true" />
				<UltraForecast On="true" />
				<ShortPlanForecast On="true" />
				<MiddleForeCast On="true"/>
				<MangForecastCampare On="true" />	
				<MangPowerForecastCampare On="true" /><!--wkupdate 20180408-->	

这里的话,需要修改页面,先要添加对应的配置.修改之后的配置如下,风速部分的代码不变,但是全部不展示.

	<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着手风电的功能实现以及笔记