Jelajahi Sumber

增加超短期16点列表,预测报表展示及导出

xusl 2 hari lalu
induk
melakukan
d682eb6ded

+ 10 - 0
ipp-ap/src/router/page/index.js

@@ -53,6 +53,16 @@ export default [
     }],
   },
   {
+    path: '/idp/data/ultraforecast16',
+    component: Layout,
+    children: [{
+      path: 'index',
+      name: '超短期16点位',
+      component: () =>
+        import ( /* webpackChunkName: "views" */ '@/views/idp/data/ultraforecast16')
+    }],
+  },
+  {
     path: '/idp/data/forecastReport',
     component: Layout,
     children: [{

+ 14 - 0
ipp-ap/src/router/views/index.js

@@ -121,6 +121,20 @@ export default [
       children: [],
       hasChildren: false,
       icon: "",
+      id: "4077",
+      keepAlive: "0",
+      label: "超短期16点位",
+      menuType: "0",
+      name: "超短期16点位",
+      parentId: "4058",
+      path: "/idp/data/ultraforecast16/index",
+      permission: "",
+      sort: 1,
+      spread: false
+    },{
+      children: [],
+      hasChildren: false,
+      icon: "",
       id: "4078",
       keepAlive: "0",
       label: "预测报表导出",

+ 1 - 9
ipp-ap/src/views/idp/data/forecastReport/index.vue

@@ -224,15 +224,7 @@ export default {
       console.log(tab.name);
     },
     exportDataEvent() {
-      if (this.startTime==null){
-        this.$message.warning('请选择开始时间')
-        return
-      }
-      if (this.endTime==null){
-        this.$message.warning('请选择结束时间')
-        return
-      }
-      this.$axios.get("/windtotalpowercontrast/exportDataEvent/" +this.startTime + "/" + this.endTime, {
+      this.$axios.get("/forecastReportController/exportDataEvent/" +this.ycDate + "/" + this.cdqDate+ "/" + this.sjDate+ "/" + this.agcDate, {
         responseType: 'blob'// 用于解决中文乱码
       }).then((response) => {
         this.loading = false

+ 226 - 0
ipp-ap/src/views/idp/data/ultraforecast16/index.vue

@@ -0,0 +1,226 @@
+<!--
+  -    Copyright (c) 2018-2025, lengleng All rights reserved.
+  -
+  - Redistribution and use in source and binary forms, with or without
+  - modification, are permitted provided that the following conditions are met:
+  -
+  - Redistributions of source code must retain the above copyright notice,
+  - this list of conditions and the following disclaimer.
+  - Redistributions in binary form must reproduce the above copyright
+  - notice, this list of conditions and the following disclaimer in the
+  - documentation and/or other materials provided with the distribution.
+  - Neither the name of the pig4cloud.com developer nor the names of its
+  - contributors may be used to endorse or promote products derived from
+  - this software without specific prior written permission.
+  - Author: lengleng (wangiegie@gmail.com)
+  -->
+<template>
+  <div class="execution">
+    <div class="filter">
+      <div class="endTime" style="display: inline-block">
+        <span class="timeText" style="font-weight: bold;font-size: 14px">&#12288;超短期日期:</span>
+        <el-date-picker
+          value-format="timestamp"
+          v-model="cdqDate"
+          :clearable="false"
+          type="date"
+          placeholder="选择日期">
+        </el-date-picker>
+      </div>
+      <div class="timeQuery" style="display: inline-block">
+        &#12288;<el-button size="small" :loading="loading" @click="fetchStationData">查询</el-button>
+        <el-button size="small" :loading="loading" @click="exportDataEvent">导出</el-button>
+      </div>
+    </div>
+
+    <div class="station-container">
+      <el-tabs v-model="activeStation" type="card" @tab-click="handleClick">
+        <el-tab-pane
+          v-for="(stationData, stationName) in stationMap"
+          :key="stationName"
+          :label="stationName"
+          :name="stationName"
+        >
+        </el-tab-pane>
+      </el-tabs>
+      <el-table
+        :data="tableData"
+        border
+        style="width: 100%"
+        :cell-style="{ textAlign: 'center' }"
+        v-loading="loading"
+        height="720"
+      >
+        <el-table-column header-align="center" prop="time" label="时间" ></el-table-column>
+        <el-table-column header-align="center" prop="value1" label="第1点" ></el-table-column>
+        <el-table-column header-align="center" prop="value2" label="第2点" ></el-table-column>
+        <el-table-column header-align="center" prop="value3" label="第3点" ></el-table-column>
+        <el-table-column header-align="center" prop="value4" label="第4点" ></el-table-column>
+        <el-table-column header-align="center" prop="value5" label="第5点" ></el-table-column>
+        <el-table-column header-align="center" prop="value6" label="第6点" ></el-table-column>
+        <el-table-column header-align="center" prop="value7" label="第7点" ></el-table-column>
+        <el-table-column header-align="center" prop="value8" label="第8点" ></el-table-column>
+        <el-table-column header-align="center" prop="value9" label="第9点" ></el-table-column>
+        <el-table-column header-align="center" prop="value10" label="第10点" ></el-table-column>
+        <el-table-column header-align="center" prop="value11" label="第11点" ></el-table-column>
+        <el-table-column header-align="center" prop="value12" label="第12点" ></el-table-column>
+        <el-table-column header-align="center" prop="value13" label="第13点" ></el-table-column>
+        <el-table-column header-align="center" prop="value14" label="第14点" ></el-table-column>
+        <el-table-column header-align="center" prop="value15" label="第15点" ></el-table-column>
+        <el-table-column header-align="center" prop="value16" label="第16点" ></el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import {mapGetters} from 'vuex'
+import * as echarts from 'echarts';
+import {
+  queryCharts
+
+} from '@/api/windtotalpowercontrast'
+export default {
+  name: 'forecastReport',
+  data() {
+    return {
+      activeStation: '', // 当前激活的场站名称
+      stationMap: {},   // 存储所有场站数据
+      cdqDate: new Date(new Date().toLocaleDateString()).getTime() - 60 * 60 * 24 * 1000,
+      dynamicColumns: [], // 动态风电场信息,例如: [{ name: '哈斯风电场' }, { name: '千伏苏加风电场' }]
+      columns: [],
+      searchForm: {},
+      tableData: [],
+      times: [],
+      page: {
+        total: 0, // 总页数
+        currentPage: 1, // 当前页数
+        pageSize: 20 // 每页显示多少条
+      },
+      total: 0, // 总页数
+      currentPage: 1, // 当前页数
+      pageSize: 10, // 每页显示多少条
+      wsChart:null,
+      tableLoading: false,
+      stationCode: '',
+      stationType:'',
+      stationList: [],
+      forecastManufactor: '',
+      forecastManufactorList: [],
+      resizeKey: 1,
+      activeName: 'first',
+      loading: false,
+      ultraShortData: [],
+      shortData: [],
+      powerStationStatusData: [],
+      timeStamp: [],
+      arrays: [],
+      fromHead: []
+    }
+  },
+  computed: {
+    ...mapGetters(['permissions']),
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.$refs.table.doLayout();
+    });
+  },
+  methods: {
+    // 获取场站数据
+    async fetchStationData() {
+      this.loading = true;
+      var queryParams = {
+        ycDate:this.ycDate,
+        cdqDate:this.cdqDate,
+        sjDate:this.sjDate,
+        agcDate:this.agcDate
+      }
+      this.$axios.get('/ultraForecast16Controller/queryReport',{params: queryParams}).then((res) => {
+        this.times = res.data.data.times;
+        this.stationMap = res.data.data.dataMap;
+        // 设置默认激活第一个场站
+        const stationNames = Object.keys(this.stationMap);
+        if (stationNames.length > 0) {
+          this.activeStation = stationNames[0];
+          this.tableData = []
+          const value = this.stationMap[this.activeStation];
+          for(let i = 0;i< 96;i++){
+            const temp = {}
+            temp.time = this.times[i]
+            temp.value1 = value.value1[i]
+            temp.value2 = value.value2[i]
+            temp.value3 = value.value3[i]
+            temp.value4 = value.value4[i]
+            temp.value5 = value.value5[i]
+            temp.value6 = value.value6[i]
+            temp.value7 = value.value7[i]
+            temp.value8 = value.value8[i]
+            temp.value9 = value.value9[i]
+            temp.value10 = value.value10[i]
+            temp.value11 = value.value11[i]
+            temp.value12 = value.value12[i]
+            temp.value13 = value.value13[i]
+            temp.value14 = value.value14[i]
+            temp.value15 = value.value15[i]
+            temp.value16 = value.value16[i]
+            this.tableData.push(temp)
+          }
+        }
+      })
+      this.loading = false;
+    },
+    handleClick(tab, event) {
+      this.tableData = []
+      const value = this.stationMap[tab.name];
+      for(let i = 0;i< 96;i++){
+        const temp = {}
+        temp.time = this.times[i]
+        temp.value1 = value.value1[i]
+        temp.value2 = value.value2[i]
+        temp.value3 = value.value3[i]
+        temp.value4 = value.value4[i]
+        temp.value5 = value.value5[i]
+        temp.value6 = value.value6[i]
+        temp.value7 = value.value7[i]
+        temp.value8 = value.value8[i]
+        temp.value9 = value.value9[i]
+        temp.value10 = value.value10[i]
+        temp.value11 = value.value11[i]
+        temp.value12 = value.value12[i]
+        temp.value13 = value.value13[i]
+        temp.value14 = value.value14[i]
+        temp.value15 = value.value15[i]
+        temp.value16 = value.value16[i]
+        this.tableData.push(temp)
+      }
+    },
+    exportDataEvent() {
+      this.$axios.get("/forecastReportController/exportDataEvent/" +this.ycDate + "/" + this.cdqDate+ "/" + this.sjDate+ "/" + this.agcDate, {
+        responseType: 'blob'// 用于解决中文乱码
+      }).then((response) => {
+        this.loading = false
+      }).catch((error) => {
+        this.loading = false
+        this.$message.error('导出失败' + error)
+      })
+    },
+
+    getCapacity(param) {
+      return new Promise(function (resolve, reject) {
+        getCapacity(param).then(response => {
+          resolve(response.data.data)
+        })
+      })
+    },
+    handlePageChange({currentPage, pageSize}) {
+      this.currentPage = currentPage;//当前页
+      this.pageSize = pageSize//每页显示的条数
+    },
+    refreshChange() {
+      // this.getCompositeData()
+      this.getStationCode()
+    }
+  }
+}
+</script>

+ 259 - 0
ipp-idp/src/main/java/com/jiayue/ipp/idp/controller/ForecastReportController.java

@@ -245,4 +245,263 @@ public class ForecastReportController {
         }
         return R.ok(resultMap);
     }
+
+    @GetMapping(value = {"/exportDataEvent/{ycDate}/{cdqDate}/{sjDate}/{agcDate}","/exportDataEvent/{ycDate}/{cdqDate}/{sjDate}/{agcDate}" })
+    public void exportDataEvent(
+            @PathVariable("ycDate") Long ycDate,
+            @PathVariable("cdqDate") Long cdqDate,
+            @PathVariable("sjDate") Long sjDate,
+            @PathVariable("agcDate") Long agcDate,
+            HttpServletResponse response) {
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        String fileName = "预测报表"+simpleDateFormat.format(new Date())+".xlsx";
+        response.setContentType("application/x-msdownload;charset=utf-8");
+
+        try (Workbook workbook = new XSSFWorkbook();ServletOutputStream out = response.getOutputStream()){
+            response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
+            Date ycStartTime = new Date(ycDate+1000*60*15);
+            Date ycEndTime = new Date(ycDate+1000*60*1440);
+            // 获取场站短期实时
+            QueryWrapper<ForecastPowerShortTerm> queryWrapper = new QueryWrapper<>();
+            queryWrapper.between("forecast_time", ycStartTime, ycEndTime);
+            List<ForecastPowerShortTerm> forecastPowerShortTermList = forecastPowerShortTermService.list(queryWrapper);
+            // 按照场站编号进行分组
+            Map<String, List<ForecastPowerShortTerm>> stListByStationCodeMap = forecastPowerShortTermList.stream().collect(Collectors.groupingBy(r -> r.getStationCode()));
+
+            // 获取nwp实时
+            QueryWrapper<Nwp> nwpWrapper = new QueryWrapper<>();
+            nwpWrapper.between("pre_time", ycStartTime, ycEndTime);
+            List<Nwp> nwpList = nwpService.list(nwpWrapper);
+            // 按照场站编号进行分组
+            Map<String, List<Nwp>> nwpListByStationCodeMap = nwpList.stream().collect(Collectors.groupingBy(r -> r.getStationCode()));
+
+            // 获取场站超短期实时
+            Date cdqStartTime = new Date(cdqDate+1000*60*15);
+            Date cdqEndTime = new Date(cdqDate+1000*60*1440);
+            QueryWrapper<ForecastPowerUltraShortTerm> cdqWrapper = new QueryWrapper<>();
+            cdqWrapper.between("forecast_time", cdqStartTime, cdqEndTime);
+            List<ForecastPowerUltraShortTerm> cdqList = forecastPowerUltraShortTermService.list(cdqWrapper);
+            // 按照场站编号进行分组
+            Map<String, List<ForecastPowerUltraShortTerm>> cdqListByStationCodeMap = cdqList.stream().collect(Collectors.groupingBy(r -> r.getStationCode()));
+
+            // 获取场站实际功率
+            Date sjStartTime = new Date(sjDate+1000*60*15);
+            Date sjEndTime = new Date(sjDate+1000*60*1440);
+            QueryWrapper<PowerStationStatusData> sjWrapper = new QueryWrapper<>();
+            sjWrapper.between("time", sjStartTime, sjEndTime);
+            List<PowerStationStatusData> sjList = powerStationStatusDataService.list(sjWrapper);
+            // 按照场站编号进行分组
+            Map<String, List<PowerStationStatusData>> sjListByStationCodeMap = sjList.stream().collect(Collectors.groupingBy(r -> r.getStationCode()));
+
+            // 获取agc
+            Date agcStartTime = new Date(agcDate+1000*60*15);
+            Date agcEndTime = new Date(agcDate+1000*60*1440);
+            QueryWrapper<GridApCommandValue> agcWrapper = new QueryWrapper<>();
+            agcWrapper.between("time", agcStartTime, agcEndTime);
+            List<GridApCommandValue> agcList = gridApCommandValueService.list(agcWrapper);
+            // 按照场站编号进行分组
+            Map<String, List<GridApCommandValue>> agcListByStationCodeMap = agcList.stream().collect(Collectors.groupingBy(r -> r.getStationId()));
+
+            List<ElectricField> list = electricFieldService.list();
+            list.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
+            Long momentTime = 15 * 60 * 1000L;
+            for (int i=0;i<list.size();i++) {
+                ElectricField electricField = list.get(i);
+                Sheet sheet = workbook.createSheet(electricField.getName());
+                // 创建样式 - 水平垂直居中,带边框
+                CellStyle centerStyle = workbook.createCellStyle();
+                centerStyle.setAlignment(HorizontalAlignment.CENTER);
+                centerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+                centerStyle.setBorderTop(BorderStyle.THIN);
+                centerStyle.setBorderBottom(BorderStyle.THIN);
+                centerStyle.setBorderLeft(BorderStyle.THIN);
+                centerStyle.setBorderRight(BorderStyle.THIN);
+                // 创建表头
+                List<String> headList = new ArrayList<>();
+                headList.add("时间");
+                headList.add("风速");
+                headList.add("短期功率预测");
+                headList.add("超短期功率预测");
+                headList.add("实际发电");
+                headList.add("AGC指令");
+
+                // 提取短期map
+                Map<String, ForecastPowerShortTerm> stListByTimeMap = new HashMap<>();
+                if (stListByStationCodeMap.get(electricField.getStationCode())!=null){
+                    List<ForecastPowerShortTerm> forecastPowerShortTerms = stListByStationCodeMap.get(electricField.getStationCode());
+                    stListByTimeMap = forecastPowerShortTerms.stream()
+                            .filter(forecast -> electricField.getBelongForecastManufactor().equals(forecast.getForecastManufactor()))
+                            .collect(Collectors.toMap(
+                                    myObject -> DateUtil.format(myObject.getForecastTime(),"HH:mm"), // keyMapper,将Date转换为long
+                                    myObject -> myObject, // valueMapper,保持原对象
+                                    (existing, replacement) -> existing // mergeFunction,处理重复key的情况,这里简单地保留现有的value
+                            ));
+                }
+                // 提取nwp风速
+                Map<String, Nwp> nwpListByTimeMap = new HashMap<>();
+                if (nwpListByStationCodeMap.get(electricField.getStationCode())!=null){
+                    List<Nwp> forecastPowerShortTerms = nwpListByStationCodeMap.get(electricField.getStationCode());
+                    nwpListByTimeMap = forecastPowerShortTerms.stream()
+                            .filter(forecast -> "SYJY".equals(forecast.getForecastManufactor()))
+                            .collect(Collectors.toMap(
+                                    myObject -> DateUtil.format(myObject.getPreTime(),"HH:mm"), // keyMapper,将Date转换为long
+                                    myObject -> myObject, // valueMapper,保持原对象
+                                    (existing, replacement) -> existing // mergeFunction,处理重复key的情况,这里简单地保留现有的value
+                            ));
+                }
+                // 获取nwp轮毂高度
+                int nwpHubHeight = Integer.parseInt(sysParameterService.getSysParameterAndStationCode("NWP_HubHeight", "100", electricField.getStationCode()));
+                // 提取超短期map
+                Map<String, ForecastPowerUltraShortTerm> cdqListByTimeMap = new HashMap<>();
+                if (cdqListByStationCodeMap.get(electricField.getStationCode())!=null){
+                    List<ForecastPowerUltraShortTerm> cdqTerms = cdqListByStationCodeMap.get(electricField.getStationCode());
+                    cdqListByTimeMap = cdqTerms.stream()
+                            .filter(forecast -> electricField.getBelongForecastManufactor().equals(forecast.getForecastManufactor()))
+                            .collect(Collectors.toMap(
+                                    myObject -> DateUtil.format(myObject.getForecastTime(),"HH:mm"), // keyMapper,将Date转换为long
+                                    myObject -> myObject, // valueMapper,保持原对象
+                                    (existing, replacement) -> existing // mergeFunction,处理重复key的情况,这里简单地保留现有的value
+                            ));
+                }
+                // 提取实际功率
+                Map<String, PowerStationStatusData> sjListByTimeMap = new HashMap<>();
+                if (sjListByStationCodeMap.get(electricField.getStationCode())!=null){
+                    List<PowerStationStatusData> sjTerms = sjListByStationCodeMap.get(electricField.getStationCode());
+                    sjListByTimeMap = sjTerms.stream()
+                            .filter(forecast -> electricField.getStationCode().equals(forecast.getStationCode()))
+                            .collect(Collectors.toMap(
+                                    myObject -> DateUtil.format(new Date(myObject.getTime().toInstant(ZoneOffset.of("+8")).toEpochMilli()),"HH:mm"), // keyMapper,将Date转换为long
+                                    myObject -> myObject, // valueMapper,保持原对象
+                                    (existing, replacement) -> existing // mergeFunction,处理重复key的情况,这里简单地保留现有的value
+                            ));
+                }
+                // 提取agc
+                Map<String, GridApCommandValue> agcListByTimeMap = new HashMap<>();
+                if (agcListByStationCodeMap.get(electricField.getStationCode())!=null){
+                    List<GridApCommandValue> agcTerms = agcListByStationCodeMap.get(electricField.getStationCode());
+                    agcListByTimeMap = agcTerms.stream()
+                            .filter(forecast -> electricField.getStationCode().equals(forecast.getStationId()))
+                            .collect(Collectors.toMap(
+                                    myObject -> DateUtil.format(myObject.getTime(),"HH:mm"), // keyMapper,将Date转换为long
+                                    myObject -> myObject, // valueMapper,保持原对象
+                                    (existing, replacement) -> existing // mergeFunction,处理重复key的情况,这里简单地保留现有的value
+                            ));
+                }
+                List<ForecastReportDto> forecastReportDtoList = new ArrayList<>();
+                for (Long tempTime = ycStartTime.getTime(); tempTime <= ycEndTime.getTime(); tempTime = tempTime + momentTime) {
+                    ForecastReportDto forecastReportDto = new ForecastReportDto();
+                    String timeStr = DateUtil.format(new Date(tempTime),"HH:mm");
+                    if (timeStr.equals("00:00")){
+                        forecastReportDto.setTime("24:00");
+                    }
+                    else{
+                        forecastReportDto.setTime(timeStr);
+                    }
+                    // 短期
+                    if (stListByTimeMap.get(timeStr)!=null){
+                        ForecastPowerShortTerm forecastPowerShortTerm = stListByTimeMap.get(timeStr);
+                        forecastReportDto.setShortTerm(forecastPowerShortTerm.getFpValue());
+                    }
+                    // 超短期
+                    if (cdqListByTimeMap.get(timeStr)!=null){
+                        ForecastPowerUltraShortTerm forecastPowerUltraShortTerm = cdqListByTimeMap.get(timeStr);
+                        forecastReportDto.setUltraShortTerm(forecastPowerUltraShortTerm.getFpValue());
+                    }
+                    // 实际功率
+                    if (sjListByTimeMap.get(timeStr)!=null){
+                        PowerStationStatusData powerStationStatusData = sjListByTimeMap.get(timeStr);
+                        forecastReportDto.setActualPower(powerStationStatusData.getRealValue());
+                    }
+                    // agc
+                    if (agcListByTimeMap.get(timeStr)!=null){
+                        GridApCommandValue gridApCommandValue = agcListByTimeMap.get(timeStr);
+                        forecastReportDto.setAgc(gridApCommandValue.getCommandValue());
+                    }
+                    // nwp轮毂风速
+                    if (nwpListByTimeMap.get(timeStr)!=null){
+                        Nwp nwp = nwpListByTimeMap.get(timeStr);
+                        // 获取nwp轮毂风速
+                        if (nwpHubHeight==170){
+                            forecastReportDto.setWindSpeed(nwp.getWs170());
+                        }
+                        else if (nwpHubHeight==150){
+                            forecastReportDto.setWindSpeed(nwp.getWs150());
+                        }
+                        else if (nwpHubHeight==140){
+                            forecastReportDto.setWindSpeed(nwp.getWs140());
+                        }
+                        else if (nwpHubHeight==130){
+                            forecastReportDto.setWindSpeed(nwp.getWs130());
+                        }
+                        else if (nwpHubHeight==120){
+                            forecastReportDto.setWindSpeed(nwp.getWs120());
+                        }
+                        else if (nwpHubHeight==110){
+                            forecastReportDto.setWindSpeed(nwp.getWs110());
+                        }
+                        else if (nwpHubHeight==100){
+                            forecastReportDto.setWindSpeed(nwp.getWs100());
+                        }
+                        else if (nwpHubHeight==90){
+                            forecastReportDto.setWindSpeed(nwp.getWs90());
+                        }
+                        else if (nwpHubHeight==80){
+                            forecastReportDto.setWindSpeed(nwp.getWs80());
+                        }
+                        else if (nwpHubHeight==70){
+                            forecastReportDto.setWindSpeed(nwp.getWs70());
+                        }
+                        else if (nwpHubHeight==50){
+                            forecastReportDto.setWindSpeed(nwp.getWs50());
+                        }
+                        else if (nwpHubHeight==30){
+                            forecastReportDto.setWindSpeed(nwp.getWs30());
+                        }
+                        else if (nwpHubHeight==10){
+                            forecastReportDto.setWindSpeed(nwp.getWs10());
+                        }
+
+                    }
+                    forecastReportDtoList.add(forecastReportDto);
+                }
+
+                // 第一行 - 主表头
+                Row headerRow = sheet.createRow(0);
+                for (int p = 0; p < headList.size(); p++) {
+                    Cell cell = headerRow.createCell(p);
+                    cell.setCellValue(headList.get(p));
+                    cell.setCellStyle(centerStyle);
+                }
+                for (int k=0;k<forecastReportDtoList.size();k++){
+                    ForecastReportDto forecastReportDto = forecastReportDtoList.get(k);
+
+                    Row row = sheet.createRow(k + 1);
+                    Cell cell0 = row.createCell(0);
+                    cell0.setCellValue(forecastReportDto.getTime());
+                    cell0.setCellStyle(centerStyle);
+                    Cell cell1 = row.createCell(1);
+                    cell1.setCellValue(forecastReportDto.getWindSpeed()==null?"":forecastReportDto.getWindSpeed().toString());
+                    cell1.setCellStyle(centerStyle);
+                    Cell cell2 = row.createCell(2);
+                    cell2.setCellValue(forecastReportDto.getShortTerm()==null?"":forecastReportDto.getShortTerm().toString());
+                    cell2.setCellStyle(centerStyle);
+                    Cell cell3 = row.createCell(3);
+                    cell3.setCellValue(forecastReportDto.getUltraShortTerm()==null?"":forecastReportDto.getUltraShortTerm().toString());
+                    cell3.setCellStyle(centerStyle);
+                    Cell cell4 = row.createCell(4);
+                    cell4.setCellValue(forecastReportDto.getActualPower()==null?"":forecastReportDto.getActualPower().toString());
+                    cell4.setCellStyle(centerStyle);
+                    Cell cell5 = row.createCell(5);
+                    cell5.setCellValue(forecastReportDto.getAgc()==null?"":forecastReportDto.getAgc().toString());
+                    cell5.setCellStyle(centerStyle);
+                }
+            }
+            // 写入输出流
+            workbook.write(out);
+            out.flush();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 }

+ 109 - 0
ipp-idp/src/main/java/com/jiayue/ipp/idp/controller/UltraForecast16Controller.java

@@ -0,0 +1,109 @@
+package com.jiayue.ipp.idp.controller;
+
+
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.jiayue.ipp.common.data.entity.*;
+import com.jiayue.ipp.idp.dto.ForecastReportDto;
+import com.jiayue.ipp.idp.service.*;
+import com.jiayue.ipp.idp.util.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.time.ZoneOffset;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * idp_wind_tower_status_data
+ *
+ * @author whc
+ * @date 2022-03-18 15:50:05
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/ultraForecast16Controller")
+@Api(value = "ultraForecast16Controller", tags = "ultraForecast16Controller管理")
+public class UltraForecast16Controller {
+    private final ElectricFieldService electricFieldService;
+    private final ForecastPowerUltraShortTermHisService forecastPowerUltraShortTermHisService;
+
+    @ApiOperation(value = "通过条件查询", notes = "通过条件查询")
+    @GetMapping("/queryReport")
+    public R queryReport(Long cdqDate) throws Exception {
+        // 获取场站超短期实时
+        Date cdqStartTime = new Date(cdqDate+1000*60*15);
+        Date cdqEndTime = new Date(cdqDate+1000*60*1440);
+        QueryWrapper<ForecastPowerUltraShortTermHis> cdqWrapper = new QueryWrapper<>();
+        cdqWrapper.between("forecast_time", cdqStartTime, cdqEndTime);
+        List<ForecastPowerUltraShortTermHis> cdqList = forecastPowerUltraShortTermHisService.list(cdqWrapper);
+        // 按照场站编号进行分组
+        Map<String, List<ForecastPowerUltraShortTermHis>> cdqListByStationCodeMap = cdqList.stream().collect(Collectors.groupingBy(r -> r.getStationCode()));
+
+        List<ElectricField> list = electricFieldService.list();
+        list.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
+        Map<String,Object> dataMap = new HashMap<>();
+        Map<String,Object> resultMap = new HashMap<>();
+        Long momentTime = 15 * 60 * 1000L;
+        long startTime = cdqStartTime.getTime();
+        for (int k=0;k<list.size();k++){
+            ElectricField electricField = list.get(k);
+            List<ForecastPowerUltraShortTermHis> forecastPowerUltraShortTermHisList = new ArrayList<>();
+            if (cdqListByStationCodeMap.get(electricField.getStationCode())!=null){
+                forecastPowerUltraShortTermHisList = cdqListByStationCodeMap.get(electricField.getStationCode());
+            }
+            Map<String,Object> realPowerMap = new HashMap<>();
+            for(int p = 1;p<=16;p++){
+                int finalP = p;
+                List<ForecastPowerUltraShortTermHis> filterList  = forecastPowerUltraShortTermHisList.stream().filter(t->t.getForecastHowLongAgo() == finalP && t.getForecastManufactor().equals(electricField.getBelongForecastManufactor())).collect(Collectors.toList());
+                long timeStep = 900000L;
+                if (startTime % timeStep != 0) {
+                    startTime = startTime - (startTime % timeStep);
+                }
+                List<Float> ableDatas = new ArrayList<>();
+                for (long i = startTime; i <= cdqEndTime.getTime(); i = i + 900000L) {
+                    long finalI = i;
+                    List<ForecastPowerUltraShortTermHis> p1 = filterList.stream().filter(t -> t.getForecastTime().getTime() == finalI).collect(Collectors.toList());
+                    if (p1 != null && p1.size() > 0) {
+                        if (p1.get(0).getAbleValue().compareTo(new BigDecimal(-99)) == 0) {
+                            ableDatas.add(0f);
+                        } else {
+                            ableDatas.add(p1.get(0).getAbleValue().floatValue());
+                        }
+                    } else {
+                        ableDatas.add(null);
+                    }
+                }
+                realPowerMap.put("value"+p,ableDatas);
+            }
+            dataMap.put(electricField.getName(),realPowerMap);
+        }
+        List<String> times = new ArrayList<>();
+        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
+        for (long i = startTime; i <= cdqEndTime.getTime(); i = i + 900000L) {
+            String timeStr = sdf.format(new Date(i));
+            if (timeStr.equals("00:00")){
+                times.add("24:00");
+            }
+            else{
+                times.add(timeStr);
+            }
+        }
+        resultMap.put("times",times);
+        resultMap.put("dataMap",dataMap);
+        return R.ok(resultMap);
+    }
+}

+ 1 - 2
ipp-idp/src/main/java/com/jiayue/ipp/idp/controller/WindtotalpowercontrastController.java

@@ -177,7 +177,7 @@ public class WindtotalpowercontrastController {
     }
 
     @GetMapping(value = {"/exportDataEvent/{startTime}/{endTime}","/exportDataEvent/{startTime}/{endTime}" })
-    public R exportDataEvent(
+    public void exportDataEvent(
             @PathVariable("startTime") Long startTime,
             @PathVariable("endTime") Long endTime,
             HttpServletResponse response) {
@@ -358,6 +358,5 @@ public class WindtotalpowercontrastController {
         } catch (Exception e) {
             e.printStackTrace();
         }
-        return R.ok();
     }
 }