ソースを参照

1.添加短期和nwp实时数据查看
2.添加短期历史数据查询

wangtao 3 年 前
コミット
e519b2b4dd
18 ファイル変更3085 行追加349 行削除
  1. 43 33
      ipfcst-common/ipfcst-common-data/src/main/java/com/jiayue/ipfcst/common/data/repository/ForecastPowerShortTermHisRepository.java
  2. 18 8
      ipfcst-common/ipfcst-common-data/src/main/java/com/jiayue/ipfcst/common/data/repository/NwpRepository.java
  3. 84 0
      ipfcst-console/src/main/frontend/components/Charts/mixins/resize.js
  4. 70 0
      ipfcst-console/src/main/frontend/components/curvecolors.js
  5. 143 141
      ipfcst-console/src/main/frontend/main.js
  6. 21 0
      ipfcst-console/src/main/frontend/router/modules/dataquery.js
  7. 184 0
      ipfcst-console/src/main/frontend/views/dataquery/forecastPowerShortHisTerm/charts/index.vue
  8. 295 0
      ipfcst-console/src/main/frontend/views/dataquery/forecastPowerShortHisTerm/index.vue
  9. 184 0
      ipfcst-console/src/main/frontend/views/dataquery/forecastPowerShortTerm/charts/index.vue
  10. 323 0
      ipfcst-console/src/main/frontend/views/dataquery/forecastPowerShortTerm/index.vue
  11. 426 0
      ipfcst-console/src/main/frontend/views/dataquery/nwp/charts/index.vue
  12. 312 0
      ipfcst-console/src/main/frontend/views/dataquery/nwp/index.vue
  13. 73 0
      ipfcst-console/src/main/java/com/jiayue/ipfcst/console/controller/ForecastPowerShortTermController.java
  14. 52 0
      ipfcst-console/src/main/java/com/jiayue/ipfcst/console/controller/ForecastPowerShortTermHisController.java
  15. 81 0
      ipfcst-console/src/main/java/com/jiayue/ipfcst/console/controller/NwpController.java
  16. 170 0
      ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/ForecastPowerShortTermHisService.java
  17. 118 15
      ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/ForecastPowerShortTermService.java
  18. 488 152
      ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/NwpService.java

+ 43 - 33
ipfcst-common/ipfcst-common-data/src/main/java/com/jiayue/ipfcst/common/data/repository/ForecastPowerShortTermHisRepository.java

@@ -14,40 +14,50 @@ import java.util.List;
  * @since 2019/8/2 10:57
  */
 public interface ForecastPowerShortTermHisRepository extends BaseRepository<ForecastPowerShortTermHis, Integer> {
-	/**
-	 * 根据时间段删除当日凌晨零点以后生成的短期历史期数据
-	 *
-	 * @param startTime 开始时间
-	 * @param endTime   结束时间
-	 */
-	@Modifying
-	@Query(value = "delete from ForecastPowerShortTermHis t where t.genDate >= CURRENT_DATE and t.forecastTime >=?1 and t.forecastTime<=?2 and t.stationCode=?3")
-	void deleteToday(Long startTime, Long endTime,String stationCode);
+    /**
+     * 根据时间段删除当日凌晨零点以后生成的短期历史期数据
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     */
+    @Modifying
+    @Query(value = "delete from ForecastPowerShortTermHis t where t.genDate >= CURRENT_DATE and t.forecastTime >=?1 and t.forecastTime<=?2 and t.stationCode=?3")
+    void deleteToday(Long startTime, Long endTime, String stationCode);
 
-	/**
-	 * 根据提前多久,开始结束时间查询历史短期 yh
-	 *
-	 * @param startTime 开始时间
-	 * @param endTime   结束时间
-	 * @param ago       提前多久预测
-	 * @return 结果集
-	 */
-	List<ForecastPowerShortTermHis> findByForecastTimeBetweenAndForecastHowLongAgo(Long startTime, Long endTime, Integer ago);
+    /**
+     * 根据提前多久,开始结束时间查询历史短期 yh
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @param ago       提前多久预测
+     * @return 结果集
+     */
+    List<ForecastPowerShortTermHis> findByForecastTimeBetweenAndForecastHowLongAgo(Long startTime, Long endTime, Integer ago);
 
-	/**
-	 * 根据提前多久,时间查询历史短期 yh
-	 *
-	 * @param queryTime 时间
-	 * @param ago       提前多久预测
-	 * @return 结果集
-	 */
-	ForecastPowerShortTermHis findByForecastTimeAndForecastHowLongAgo(Long queryTime, Integer ago);
+    /**
+     * 根据提前多久,时间查询历史短期 yh
+     *
+     * @param queryTime 时间
+     * @param ago       提前多久预测
+     * @return 结果集
+     */
+    ForecastPowerShortTermHis findByForecastTimeAndForecastHowLongAgo(Long queryTime, Integer ago);
 
-	/**
-	 * 根据时间段删除和提前多久预测删除短期数据
-	 *
-	 * @param startTime 开始时间
-	 * @param endTime   结束时间
-	 */
-	void deleteByForecastTimeBetweenAndForecastHowLongAgo(Long startTime, Long endTime,int HowLongAgo);
+    /**
+     * 根据时间段删除和提前多久预测删除短期数据
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     */
+    void deleteByForecastTimeBetweenAndForecastHowLongAgo(Long startTime, Long endTime, int HowLongAgo);
+
+    /**
+     * 根据时间 场站编码
+     *
+     * @param startTime   开始时间
+     * @param endTime     结束时间
+     * @param stationCode
+     * @return 结果集
+     */
+    List<ForecastPowerShortTermHis> findByForecastTimeBetweenAndStationCode(Long startTime, Long endTime, String stationCode);
 }

+ 18 - 8
ipfcst-common/ipfcst-common-data/src/main/java/com/jiayue/ipfcst/common/data/repository/NwpRepository.java

@@ -13,13 +13,23 @@ import java.util.List;
  */
 public interface NwpRepository extends BaseRepository<Nwp, Integer> {
 
-	void deleteByPreTimeBetweenAndStationCode(Long startTime, Long endTime,String stationCode);
+    void deleteByPreTimeBetweenAndStationCode(Long startTime, Long endTime, String stationCode);
 
-	/**
-	 * 按时间段查询数据
-	 *
-	 * @param startTime
-	 * @param endTime
-	 */
-	List<Nwp> findByPreTimeBetween(Long startTime, Long endTime);
+    /**
+     * 按时间段查询数据
+     *
+     * @param startTime
+     * @param endTime
+     */
+    List<Nwp> findByPreTimeBetween(Long startTime, Long endTime);
+
+    /**
+     * 根据时间段和场站编码查询nwp数据
+     *
+     * @param startTime
+     * @param endTime
+     * @param stationCode
+     * @return
+     */
+    List<Nwp> findByPreTimeBetweenAndStationCode(Long startTime, Long endTime, String stationCode);
 }

+ 84 - 0
ipfcst-console/src/main/frontend/components/Charts/mixins/resize.js

@@ -0,0 +1,84 @@
+import { debounce } from '@/utils'
+
+export default {
+  data() {
+    return {
+      $_sidebarElm: null,
+      $_itemElm1:null,
+      $_itemElm2:null,
+      $_itemElm3:null,
+      $_itemElm4:null,
+      $_windTowerItemElm1:null,
+      $_windTowerItemElm2:null,
+      $_windTowerItemElm3:null,
+      $_tabsClass:null,
+      $_resizeHandler: null,
+
+    }
+  },
+  mounted() {
+    this.initListener()
+  },
+  activated() {
+    if (!this.$_resizeHandler) {
+      // avoid duplication init
+      this.initListener()
+    }
+    // when keep-alive chart activated, auto resize
+    this.resize()
+  },
+  beforeDestroy() {
+    this.destroyListener()
+  },
+  deactivated() {
+    this.destroyListener()
+  },
+  methods: {
+    // use $_ for mixins properties
+    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
+    $_sidebarResizeHandler(e) {
+      if (e.propertyName === 'width') {
+        this.$_resizeHandler()
+      }
+    },
+
+    initListener() {
+      this.$_resizeHandler = debounce(() => {
+        this.resize()
+      }, 100)
+      window.addEventListener('resize', this.$_resizeHandler)
+
+      this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
+      this.$_itemElm1 = document.getElementsByClassName('item')[0]
+      this.$_itemElm2 = document.getElementsByClassName('item')[1]
+      this.$_itemElm3 = document.getElementsByClassName('item')[2]
+
+      this.$_windTowerItemElm1 = document.getElementsByClassName('windTowerItem')[0]
+      this.$_windTowerItemElm2 = document.getElementsByClassName('windTowerItem')[1]
+      this.$_windTowerItemElm3 = document.getElementsByClassName('windTowerItem')[2]
+
+
+      this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
+      this.$_itemElm1 && this.$_itemElm1.addEventListener('transitionend', this.$_sidebarResizeHandler)
+      this.$_itemElm2 && this.$_itemElm2.addEventListener('transitionend', this.$_sidebarResizeHandler)
+      this.$_itemElm3 && this.$_itemElm3.addEventListener('transitionend', this.$_sidebarResizeHandler)
+
+      this.$_windTowerItemElm1 && this.$_windTowerItemElm1.addEventListener('transitionend', this.$_sidebarResizeHandler)
+      this.$_windTowerItemElm2 && this.$_windTowerItemElm2.addEventListener('transitionend', this.$_sidebarResizeHandler)
+      this.$_windTowerItemElm3 && this.$_windTowerItemElm3.addEventListener('transitionend', this.$_sidebarResizeHandler)
+
+
+
+    },
+    destroyListener() {
+      window.removeEventListener('resize', this.$_resizeHandler)
+      this.$_resizeHandler = null
+
+      this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
+    },
+    resize() {
+      const { chart } = this
+      chart && chart.resize()
+    }
+  }
+}

+ 70 - 0
ipfcst-console/src/main/frontend/components/curvecolors.js

@@ -0,0 +1,70 @@
+export default {
+    //实际功率
+    sj:'#FF4136',
+    //短期
+    dq: '#0066CC',
+    //超短期
+    cdq: '#FFD700',
+    //可用功率
+    kygl: '#2ECC40',
+    //理论功率
+    llgl: '#F012BE',
+    //测风测光法理论
+    cfgf: '#85144b',
+    //样板机法理论
+    ybjf: '#39CCCC',
+    //测风测光法可用
+    kycfgf: '#921AFF',
+    //样板机法可用
+    kyybjf: '#cf20e2',
+    //总辐射
+    zfs: '#8A2BE2',
+    //散辐射
+    sfs: '#FF8C00',
+    //直辐射
+    zhfs: '#0000E3',
+    //斜辐射
+    xfs: '#73BF00',
+    // nwp辐射
+    nwpfs: '#FF6666',
+    // nwp直辐射
+    nwpzhfs: '#6699FF',
+    // nwp散辐射
+    nwpsfs: '#FF95CA',
+    ws10: '#8A2BE2',
+    ws30: '#FF8C00',
+    ws50: '#0000E3',
+    ws60: '#85144b',
+    ws70: '#A8FF24',
+    ws80: '#FF6666',
+    ws90: '#6699FF',
+    ws100: '#FF95CA',
+    ws110: '#FFBB77',
+    ws120: '#98FB98',
+    wsHubHeight: '#0066CC',
+    nwp10: '#00FFFF',
+    nwp30: '#2894FF',
+    nwp50: '#9393FF',
+    nwp70: '#FF44FF',
+    nwp80: '#FF5809',
+    nwp90: '#C07AB8',
+    nwp100: '#4F9D9D',
+    nwp170: '#B87070',
+
+    line1:"#FFD700",
+    line2:"#2ECC40",
+    line3:"#F012BE",
+    line4:"#85144b",
+    line5:"#39CCCC",
+    line6:"#8A2BE2",
+    line7:"#FF8C00",
+    line8:"#0000E3",
+    line9:"#73BF00",
+    line10:"#FF6666",
+    line11:"#6699FF",
+    line12:"#FF95CA",
+    line13:"#98FB98",
+    line14:"#0066CC",
+    line15:"#FFBB77",
+    line16:"#921AFF",
+}

+ 143 - 141
ipfcst-console/src/main/frontend/main.js

@@ -19,11 +19,13 @@ import axios from 'axios'
 import 'xe-utils'
 import VXETable from 'vxe-table'
 import 'vxe-table/lib/index.css'
+import XEUtils from 'xe-utils'
 
 import {removeToken} from './utils/auth'
 import {getBrowserToken} from './utils/commonFuc' // get token from cookie
 Vue.prototype.$moment = moment
 Vue.prototype.$echarts = echarts
+Vue.prototype.$XEUtils = XEUtils
 Vue.use(VXETable)
 /**
  * If you don't want to use mock-server
@@ -45,171 +47,171 @@ Vue.use(ElementUI, {locale})
 Vue.prototype.$fpath = require('path')
 Vue.config.productionTip = false
 Vue.prototype.$axios = axios.create({
-    baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
-    // withCredentials: true, // send cookies when cross-domain requests
-    timeout: 1000 * 60 * 10 // request timeout
+  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
+  // withCredentials: true, // send cookies when cross-domain requests
+  timeout: 1000 * 60 * 10 // request timeout
 })
 VXETable.setup({
   validArgs: 'obsolete' // 将自定义校验参数还原为 Function(rule, cellValue, callback)
 })
 
 Vue.prototype.$axios.interceptors.request.use(
-    config => {
-        // do something before request is sent
-        /*    if (store.getters.token) {
-          // let each request carry token
-          // ['X-Token'] is a custom headers key
-          // please modify it according to the actual situation
-          config.headers['Authorization'] = getToken()
-        }*/
+  config => {
+    // do something before request is sent
+    /*    if (store.getters.token) {
+      // let each request carry token
+      // ['X-Token'] is a custom headers key
+      // please modify it according to the actual situation
+      config.headers['Authorization'] = getToken()
+    }*/
 
-        if (getBrowserToken()) { // 判断是否存在token,如果存在的话,则每个http header都加上token
-            config.headers['Authorization'] = getBrowserToken()
-            sessionStorage.setItem('user', getBrowserUser())
-        }
-        return config
-    },
-    error => {
-        // do something with request error
-        console.log(error) // for debug
-        return Promise.reject(error)
+    if (getBrowserToken()) { // 判断是否存在token,如果存在的话,则每个http header都加上token
+      config.headers['Authorization'] = getBrowserToken()
+      sessionStorage.setItem('user', getBrowserUser())
     }
+    return config
+  },
+  error => {
+    // do something with request error
+    console.log(error) // for debug
+    return Promise.reject(error)
+  }
 )
 
 
 function getBrowserUser() {
-    var user = "";
-    var ca = document.cookie.split(';');
-    for (var i = 0; i < ca.length; i++) {
-        var c = ca[i].trim();
-        if (c.indexOf("user=") == 0){
-            user = c.substring("user=".length, c.length);
-        }
+  var user = "";
+  var ca = document.cookie.split(';');
+  for (var i = 0; i < ca.length; i++) {
+    var c = ca[i].trim();
+    if (c.indexOf("user=") == 0) {
+      user = c.substring("user=".length, c.length);
     }
-    return user
+  }
+  return user
 }
 
 // response interceptor
 Vue.prototype.$axios.interceptors.response.use(
-    /**
-     * If you want to get http information such as headers or status
-     * Please return  response => response
-     */
+  /**
+   * If you want to get http information such as headers or status
+   * Please return  response => response
+   */
 
-    /**
-     * Determine the request status by custom code
-     * Here is just an example
-     * You can also judge the status by HTTP Status Code
-     */
-    response => {
-        // 处理下载文件
-        if (response.headers && response.headers['content-type'] && (response.headers['content-type'].indexOf('application/x-msdownload') != -1)) {
-            // 创建一个blob对象,file的一种
-            const blob = new Blob([response.data], {type: response.headers['content-type']})
-            const fileName = decodeURI(response.headers['content-disposition'].split('=')[1])
-            if (window.navigator.msSaveOrOpenBlob) {
-                // 兼容IE10
-                navigator.msSaveBlob(blob, fileName)
-            } else {
-                // 非IE下载
-                const elink = document.createElement('a')
-                elink.download = fileName
-                elink.style.display = 'none'
-                elink.href = URL.createObjectURL(blob)
-                document.body.appendChild(elink)
-                elink.click()
-                URL.revokeObjectURL(elink.href) // 释放URL 对象
-                document.body.removeChild(elink)
-            }
+  /**
+   * Determine the request status by custom code
+   * Here is just an example
+   * You can also judge the status by HTTP Status Code
+   */
+  response => {
+    // 处理下载文件
+    if (response.headers && response.headers['content-type'] && (response.headers['content-type'].indexOf('application/x-msdownload') != -1)) {
+      // 创建一个blob对象,file的一种
+      const blob = new Blob([response.data], {type: response.headers['content-type']})
+      const fileName = decodeURI(response.headers['content-disposition'].split('=')[1])
+      if (window.navigator.msSaveOrOpenBlob) {
+        // 兼容IE10
+        navigator.msSaveBlob(blob, fileName)
+      } else {
+        // 非IE下载
+        const elink = document.createElement('a')
+        elink.download = fileName
+        elink.style.display = 'none'
+        elink.href = URL.createObjectURL(blob)
+        document.body.appendChild(elink)
+        elink.click()
+        URL.revokeObjectURL(elink.href) // 释放URL 对象
+        document.body.removeChild(elink)
+      }
 
-            response.data = ''
-            response.headers['content-type'] = 'text/json'
-            return response
-        } else {
-            const res = response.data
-            // if the custom code is not 20000, it is judged as an error.
-            //console.log(res.code)
-            if (res.code !== 0) {
-                Message({
-                    message: res.message || 'Error',
-                    type: 'error',
-                    duration: 5 * 1000
-                })
-
-                // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
-                if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
-                    // to re-login
-                    MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
-                        confirmButtonText: 'Re-Login',
-                        cancelButtonText: 'Cancel',
-                        type: 'warning'
-                    }).then(() => {
-                        store.dispatch('user/resetToken').then(() => {
-                            location.reload()
-                        })
-                    })
-                }
-                return Promise.reject(new Error(res.message || 'Error'))
-            } else {
-                return res
-            }
-        }
-    },
-    error => {
-        if (error.response) {
-            switch (error.response.status) {
-                case 401:
-                    console.log('用户验证失败!')
-                    // 返回 401 清除token信息并跳转到登录页面
-                    removeToken()
-                    resetRouter()
-                    Message({
-                        message: error.response.data.data,
-                        type: 'error',
-                        duration: 5 * 1000
-                    })
-                    break
-                case 403:
-                    console.log('登录超时!')
-                    // 返回 401 清除token信息并跳转到登录页面
-                    removeToken()
-                    resetRouter()
-                    router.push('/login')
-                    Message({
-                        message: '登录超时',
-                        type: 'error',
-                        duration: 5 * 1000
-                    })
-                    break
-                case 500:
-                    Message({
-                        message: '服务器关闭了!请联系相关工作人员',
-                        type: 'error',
-                        duration: 5 * 1000
-                    })
-                    removeToken()
-                    resetRouter()
-                    router.push('/login')
-                    break
-                case 504:
-                    console.log('服务器关闭了!')
-                    resetRouter()
-                    break
-            }
-        }
-        /*    console.log('err' + error) // for debug
+      response.data = ''
+      response.headers['content-type'] = 'text/json'
+      return response
+    } else {
+      const res = response.data
+      // if the custom code is not 20000, it is judged as an error.
+      //console.log(res.code)
+      if (res.code !== 0) {
         Message({
-          message: error.message,
+          message: res.message || 'Error',
           type: 'error',
           duration: 5 * 1000
-        })*/
-        return Promise.reject(error)
+        })
+
+        // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
+        if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
+          // to re-login
+          MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
+            confirmButtonText: 'Re-Login',
+            cancelButtonText: 'Cancel',
+            type: 'warning'
+          }).then(() => {
+            store.dispatch('user/resetToken').then(() => {
+              location.reload()
+            })
+          })
+        }
+        return Promise.reject(new Error(res.message || 'Error'))
+      } else {
+        return res
+      }
+    }
+  },
+  error => {
+    if (error.response) {
+      switch (error.response.status) {
+        case 401:
+          console.log('用户验证失败!')
+          // 返回 401 清除token信息并跳转到登录页面
+          removeToken()
+          resetRouter()
+          Message({
+            message: error.response.data.data,
+            type: 'error',
+            duration: 5 * 1000
+          })
+          break
+        case 403:
+          console.log('登录超时!')
+          // 返回 401 清除token信息并跳转到登录页面
+          removeToken()
+          resetRouter()
+          router.push('/login')
+          Message({
+            message: '登录超时',
+            type: 'error',
+            duration: 5 * 1000
+          })
+          break
+        case 500:
+          Message({
+            message: '服务器关闭了!请联系相关工作人员',
+            type: 'error',
+            duration: 5 * 1000
+          })
+          removeToken()
+          resetRouter()
+          router.push('/login')
+          break
+        case 504:
+          console.log('服务器关闭了!')
+          resetRouter()
+          break
+      }
     }
+    /*    console.log('err' + error) // for debug
+    Message({
+      message: error.message,
+      type: 'error',
+      duration: 5 * 1000
+    })*/
+    return Promise.reject(error)
+  }
 )
 
 new Vue({
-    el: '#app',
-    router,
-    store,
-    render: h => h(App)
+  el: '#app',
+  router,
+  store,
+  render: h => h(App)
 })

+ 21 - 0
ipfcst-console/src/main/frontend/router/modules/dataquery.js

@@ -35,6 +35,27 @@ const dataqueryRouter = {
       component: () => import('@/views/dataquery/windTowerStatusData'),
       name: 'windTowerStatusData',
       meta: { title: '测风塔数据', noCache: true }
+    },
+    {
+      path: 'realTimeDQ',
+      component: () => import('@/views/dataquery/forecastPowerShortTerm/index'),
+      name: 'realTimeDQ',
+      meta: {title: '实时短期数据', noCache: true},
+      sign: 'currency'
+    },
+    {
+      path: 'realTimeNWP',
+      component: () => import('@/views/dataquery/nwp/index'),
+      name: 'realTimeNWP',
+      meta: {title: '实时nwp数据', noCache: true},
+      sign: 'currency'
+    },
+    {
+      path: 'historyDq',
+      component: () => import('@/views/dataquery/forecastPowerShortHisTerm/index'),
+      name: 'historyDq',
+      meta: {title: '历史短期查询', noCache: true},
+      sign: 'currency'
     }
   ]
 }

+ 184 - 0
ipfcst-console/src/main/frontend/views/dataquery/forecastPowerShortHisTerm/charts/index.vue

@@ -0,0 +1,184 @@
+<template>
+  <div style="width: 100%;height: 100%" >
+    <div id="fpcharts"></div>
+  </div>
+</template>
+
+<script>
+  import resize from '../../../../components/Charts/mixins/resize'
+  import echarts from 'echarts'
+  export default {
+    mixins: [resize],
+    watch: {
+      drawData:{
+        handler(newValue, oldValue) {
+          this.draw(newValue.times, newValue.datas,newValue.cap)
+        },
+        deep: true
+      },
+      resizeKey:function(newQuestion, oldQuestion){
+        if(this.chart !=null){
+          this.chart.resize();
+        }
+      }
+    },
+    props: {
+      drawData:{
+        type:Object,
+      },
+      resizeKey:{
+        type:Number
+      }
+    },
+    data() {
+      return {
+        chart: null,
+      }
+    },
+    mounted() {
+    },
+    beforeDestroy() {
+      if (!this.chart) {
+        return
+      }
+      this.chart.dispose()
+      this.chart = null
+    },
+    methods: {
+      draw(timeaxis,realpower,cap) {
+        this.chart = echarts.init(document.getElementById('fpcharts'))
+        var option ={
+          backgroundColor: 'transparent',
+          title: {
+            top: 20,
+            text: '短期预测实时查询',
+            textStyle: {
+              fontWeight: 'normal',
+              fontSize: 16,
+              color: '#F1F1F3'
+            },
+            left: '1%'
+          },
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              lineStyle: {
+                color: '#57617B'
+              }
+            }
+          },
+          legend: {
+            top: 20,
+            icon: 'rect',
+            itemWidth: 14,
+            itemHeight: 5,
+            itemGap: 13,
+            data: ['实时短期预测'],
+            right: '4%',
+            textStyle: {
+              fontSize: 12,
+              color: '#F1F1F3'
+            }
+          },
+          dataZoom: [{
+            show: true,
+            realtime: true,
+            start: 0,
+            end: 100,
+            left:"15%",
+            right:"15%",
+            textStyle:{
+              color:"#ffffff"
+            }
+          }, {
+            type: 'inside'
+          }],
+          grid: {
+            top: 100,
+            left: '2%',
+            right: '2%',
+            bottom: '10%',
+            containLabel: true
+          },
+          xAxis: [{
+            type: 'category',
+            boundaryGap: false,
+            axisLine: {
+              lineStyle: {
+                color: '#ffffff'
+              }
+            },
+            data: timeaxis
+          }],
+          yAxis: [{
+            type: 'value',
+            name: '(MW)',
+            axisTick: {
+              show: false
+            },
+            axisLine: {
+              lineStyle: {
+                color: '#ffffff'
+              }
+            },
+            axisLabel: {
+              margin: 10,
+              textStyle: {
+                fontSize: 14
+              }
+            },
+            splitLine: {
+              lineStyle: {
+                color: '#57617B'
+              }
+            }
+          }],
+          series: [{
+            name: '实时短期预测',
+            type: 'line',
+            smooth: true,
+            symbol: 'circle',
+            symbolSize: 5,
+            showSymbol: false,
+            lineStyle: {
+              normal: {
+                width: 1
+              }
+            },
+            areaStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: 'rgba(50,194,219, 0.3)'
+                }, {
+                  offset: 0.8,
+                  color: 'rgba(219, 50, 51, 0)'
+                }], false),
+                shadowColor: 'rgba(0, 0, 0, 0.1)',
+                shadowBlur: 10
+              }
+            },
+            itemStyle: {
+              normal: {
+
+                color: 'rgb(50,194,219)',
+                borderColor: 'rgba(50,194,219,0.2)',
+                borderWidth: 12
+              }
+            },
+            data: realpower
+          }]
+        }
+        option.yAxis[0].max = cap
+        this.chart.setOption(option,true)
+      },
+
+    }
+  }
+</script>
+<style scoped>
+  #fpcharts{
+    width: 100%;
+    height:calc(80vh - 50px);
+  }
+</style>

+ 295 - 0
ipfcst-console/src/main/frontend/views/dataquery/forecastPowerShortHisTerm/index.vue

@@ -0,0 +1,295 @@
+<template>
+  <div class="chart-container">
+    <div class="filter">
+      <div class="startTime">
+        <span class="timeText">起始时间</span>
+        <el-date-picker
+          v-model="startTime"
+          :clearable="false"
+          type="datetime"
+          value-format="timestamp"
+          placeholder="选择日期">
+        </el-date-picker>
+      </div>
+      <div class="endTime">
+        <span class="timeText">截止时间</span>
+        <el-date-picker
+          v-model="endTime"
+          :clearable="false"
+          type="datetime"
+          value-format="timestamp"
+          placeholder="选择日期">
+        </el-date-picker>
+      </div>
+      <div>
+        <span style="font-weight: bold;font-size: 14px">场站名称:</span>
+        <el-select style="width:250px" clearable v-model="stationCode" size="small">
+          <el-option
+            v-for="item in stationList"
+            :key="item.stationCode"
+            :label="item.name"
+            :value="item.stationCode">
+            <span style="float: left">{{ item.name }}</span>
+            <span style="float: right; color: #8492a6;font-size: 13px">{{ item.stationCode }}</span>
+          </el-option>
+        </el-select>
+      </div>
+      <div class="timeQuery">
+        <el-button size="small" :loading="loading" @click="dateQuery">查询</el-button>
+      </div>
+    </div>
+
+    <div class="content">
+      <el-tabs type="card" v-model="activeName" @tab-click="Byresize">
+
+        <el-tab-pane label="表格" name="first">
+          <div class="tableContent">
+            <vxe-table
+              id="fstTable"
+              ref="fstRef"
+              border
+              export-config
+              beforeExportMethod=""
+              :loading="loading"
+              @sort-change="sortChangeEvent"
+              :custom-config="{storage: true, checkMethod: checkColumnMethod}"
+              :auto-resize="true"
+              highlight-hover-row
+              :header-cell-style="{background:'black',color:'white',border:'white'}"
+              max-height="90%"
+              :cell-style="{background:'black',color:'white'}"
+              align="center"
+              :data="tableData">
+              <vxe-table-column field="forecastTime" title="预测时间" :formatter="dateFormat" width="180" sortable
+                                min-width="150"></vxe-table-column>
+              <vxe-table-column field="genDate" title="生成时间" min-width="60" :formatter="dateMoment"></vxe-table-column>
+              <vxe-table-column field="ableValue" title="预测功率" min-width="60"></vxe-table-column>
+              <vxe-table-column field="predictionModelEnum" title="预测模型" min-width="60"
+                                :formatter="enumToWord"></vxe-table-column>
+            </vxe-table>
+            <div class="rtPageturning">
+              <vxe-pager
+                background
+                :loading="loading"
+                :current-page="currentPage"
+                :page-size="pageSize"
+                :total="total"
+                @page-change="handlePageChange"
+                :layouts="['PrevJump', 'PrevPage', 'JumpNumber', 'NextPage', 'NextJump', 'Sizes', 'FullJump', 'Total']">
+              </vxe-pager>
+            </div>
+          </div>
+          <!-- <Table height="100%" width="100%" :queryTime=this.queryTime @sendLoading="getLoadingFormTable"></Table>-->
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
+<script>
+import Chart from './charts'
+import resize from '../../../components/Charts/mixins/resize'
+import moment from "moment";
+
+export default {
+  name: 'dq',
+  components: {Chart},
+  mixins: [resize],
+  data() {
+    return {
+      stationCode: '',
+      chart: null,
+      queryStartTime: '',
+      queryEndTime: '',
+      startTime: new Date(new Date().toLocaleDateString()).getTime() + 60 * 60 * 24 * 1000,
+      endTime: new Date(new Date().toLocaleDateString()).getTime() + 60 * 60 * 24 * 1000 * 4 - 1,
+      loading: true,
+      drawLoading: true,
+      tableLoading: true,
+      resizeKey: 1,
+      activeName: 'first',
+      drawData: {datas: [], times: []},
+      tableData: [],
+      stationList: [],
+      total: 0,
+      sortOrder: 'asc',
+      pageSize: 10,
+      currentPage: 1,
+      showToolBar: false,
+
+    }
+  },
+  created() {
+    this.$nextTick(() => {
+      // 手动将表格和工具栏进行关联
+      this.$refs.fstRef.connect(this.$refs.fstToolBar)
+    })
+  },
+  mounted() {
+    this.getStationList()
+    this.init()
+  },
+  methods: {
+    getStationList() {
+      this.$axios.get('/electricField/getElectricField').then((res) => {
+        this.stationList = res.data
+      }).catch((error) => {
+        this.$message.error('获取场站下拉框出错' + error)
+      })
+      this.loading = false
+    },
+    init() {
+      this.pageSize = 10
+      this.queryStartTime = this.startTime
+      this.queryEndTime = this.endTime
+      this.loading = false
+    },
+    getTable() {
+      this.tableLoading = true
+      this.$axios.get('/forecastPowerShortTermHis/' + this.queryStartTime + '/' + this.queryEndTime + '/' + this.stationCode + '/' + this.currentPage + '/' + this.pageSize + '?sortOrder=' + this.sortOrder).then((res) => {
+        this.tableData = res.data.content
+        // 表分页格数据总条数
+        this.total = res.data.count
+        this.tableLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+      }).catch((error) => {
+        this.tableLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+        this.$message.error('查询table出错' + error)
+      })
+      this.loading = false
+    },
+    handlePageChange({currentPage, pageSize}) {
+      this.currentPage = currentPage
+      if (this.pageSize != pageSize) {
+        this.changePageSize(pageSize)
+      }
+      this.pageSize = pageSize
+      this.startTime = this.queryStartTime
+      this.endTime = this.queryEndTime
+      this.loading = true
+      this.getTable();
+    },
+    changePageSize(pageSize) {
+      this.displayConfigPageSize.showCode = pageSize
+      this.$axios.post('displayConfig/', this.displayConfigPageSize).then((res) => {
+        this.displayConfigPageSize = res.data
+        // this.$message.success('PageSize设置成功' )
+        this.dialogVisible = false
+      }).catch((error) => {
+        this.$message.error('PageSize设置出错' + error)
+      })
+    },
+    dateFormat({cellValue, row, column}) {
+      return this.$XEUtils.toDateString(cellValue, 'yyyy-MM-dd HH:mm:ss')
+    },
+    enumToWord({cellValue, row, column}) {
+      if (cellValue == "E1") {
+        return "云端模型"
+      }
+      if (cellValue == 'E2') {
+        return "物理模型"
+      }
+      if (cellValue == 'E3') {
+        return "统计模型"
+      }
+      if (cellValue == 'E4') {
+        return "补录数据"
+      }
+      if (cellValue == 'E5') {
+        return "差值模型"
+      }
+    },
+    dateMoment({cellValue, row, column}) {
+      return moment(cellValue).format('YYYY-MM-DD HH:mm:ss')
+    },
+    sortChangeEvent({column, property, order}) {
+      if (order == null) {
+        order = 'asc'
+      }
+      this.currentPage = 1
+      this.sortOrder = order
+      this.loading = true
+      this.getTable()
+    },
+
+    checkColumnMethod({column}) {
+      if (column.property === 'preTime') {
+        return false
+      }
+      return true
+    },
+    dateQuery() {
+      this.loading = true
+      if (this.endTime <= this.startTime) {
+        this.$message.error("开始时间不能小于结束时间")
+        this.startTime = this.queryStartTime
+        this.endTime = this.queryEndTime
+        this.loading = false
+        return
+      }
+      if (this.endTime - this.startTime > 60 * 60 * 24 * 1000 * 31) {
+        this.startTime = this.queryStartTime
+        this.endTime = this.queryEndTime
+        this.$message.error("只能最多查询31天的数据哦")
+        this.loading = false
+        return
+      }
+      this.queryStartTime = this.startTime
+      this.queryEndTime = this.endTime
+      this.getTable()
+    },
+
+  }
+}
+</script>
+
+<style scoped>
+.chart-container {
+  position: relative;
+  width: 100%;
+  height: calc(100vh - 50px);
+}
+
+.filter {
+  position: relative;
+  display: flex;
+  padding: 20px 0 10px 15px;
+  font-size: 12px;
+  line-height: 11px;
+  color: white;
+}
+
+input {
+  background: transparent;
+  border: none;
+  color: white;
+}
+
+.timeText {
+  opacity: 0.69;
+  padding-right: 7px;
+  font-size: 14px;
+}
+
+.startTime {
+  display: inline-block;
+}
+
+.endTime {
+  display: inline-block;
+  padding-left: 42px;
+}
+
+
+.timeQuery {
+  background: transparent;
+}
+
+
+</style>
+

+ 184 - 0
ipfcst-console/src/main/frontend/views/dataquery/forecastPowerShortTerm/charts/index.vue

@@ -0,0 +1,184 @@
+<template>
+  <div style="width: 100%;height: 100%" >
+    <div id="fpcharts"></div>
+  </div>
+</template>
+
+<script>
+  import resize from '../../../../components/Charts/mixins/resize'
+  import echarts from 'echarts'
+  export default {
+    mixins: [resize],
+    watch: {
+      drawData:{
+        handler(newValue, oldValue) {
+          this.draw(newValue.times, newValue.datas,newValue.cap)
+        },
+        deep: true
+      },
+      resizeKey:function(newQuestion, oldQuestion){
+        if(this.chart !=null){
+          this.chart.resize();
+        }
+      }
+    },
+    props: {
+      drawData:{
+        type:Object,
+      },
+      resizeKey:{
+        type:Number
+      }
+    },
+    data() {
+      return {
+        chart: null,
+      }
+    },
+    mounted() {
+    },
+    beforeDestroy() {
+      if (!this.chart) {
+        return
+      }
+      this.chart.dispose()
+      this.chart = null
+    },
+    methods: {
+      draw(timeaxis,realpower,cap) {
+        this.chart = echarts.init(document.getElementById('fpcharts'))
+        var option ={
+          backgroundColor: 'transparent',
+          title: {
+            top: 20,
+            text: '短期预测实时查询',
+            textStyle: {
+              fontWeight: 'normal',
+              fontSize: 16,
+              color: '#F1F1F3'
+            },
+            left: '1%'
+          },
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              lineStyle: {
+                color: '#57617B'
+              }
+            }
+          },
+          legend: {
+            top: 20,
+            icon: 'rect',
+            itemWidth: 14,
+            itemHeight: 5,
+            itemGap: 13,
+            data: ['实时短期预测'],
+            right: '4%',
+            textStyle: {
+              fontSize: 12,
+              color: '#F1F1F3'
+            }
+          },
+          dataZoom: [{
+            show: true,
+            realtime: true,
+            start: 0,
+            end: 100,
+            left:"15%",
+            right:"15%",
+            textStyle:{
+              color:"#ffffff"
+            }
+          }, {
+            type: 'inside'
+          }],
+          grid: {
+            top: 100,
+            left: '2%',
+            right: '2%',
+            bottom: '10%',
+            containLabel: true
+          },
+          xAxis: [{
+            type: 'category',
+            boundaryGap: false,
+            axisLine: {
+              lineStyle: {
+                color: '#ffffff'
+              }
+            },
+            data: timeaxis
+          }],
+          yAxis: [{
+            type: 'value',
+            name: '(MW)',
+            axisTick: {
+              show: false
+            },
+            axisLine: {
+              lineStyle: {
+                color: '#ffffff'
+              }
+            },
+            axisLabel: {
+              margin: 10,
+              textStyle: {
+                fontSize: 14
+              }
+            },
+            splitLine: {
+              lineStyle: {
+                color: '#57617B'
+              }
+            }
+          }],
+          series: [{
+            name: '实时短期预测',
+            type: 'line',
+            smooth: true,
+            symbol: 'circle',
+            symbolSize: 5,
+            showSymbol: false,
+            lineStyle: {
+              normal: {
+                width: 1
+              }
+            },
+            areaStyle: {
+              normal: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                  offset: 0,
+                  color: 'rgba(50,194,219, 0.3)'
+                }, {
+                  offset: 0.8,
+                  color: 'rgba(219, 50, 51, 0)'
+                }], false),
+                shadowColor: 'rgba(0, 0, 0, 0.1)',
+                shadowBlur: 10
+              }
+            },
+            itemStyle: {
+              normal: {
+
+                color: 'rgb(50,194,219)',
+                borderColor: 'rgba(50,194,219,0.2)',
+                borderWidth: 12
+              }
+            },
+            data: realpower
+          }]
+        }
+        option.yAxis[0].max = cap
+        this.chart.setOption(option,true)
+      },
+
+    }
+  }
+</script>
+<style scoped>
+  #fpcharts{
+    width: 100%;
+    height:calc(80vh - 50px);
+  }
+</style>

+ 323 - 0
ipfcst-console/src/main/frontend/views/dataquery/forecastPowerShortTerm/index.vue

@@ -0,0 +1,323 @@
+<template>
+  <div class="chart-container">
+    <div class="filter">
+      <div class="startTime">
+        <span class="timeText">起始时间</span>
+        <el-date-picker
+          v-model="startTime"
+          :clearable="false"
+          type="datetime"
+          value-format="timestamp"
+          placeholder="选择日期">
+        </el-date-picker>
+      </div>
+      <div class="endTime">
+        <span class="timeText">截止时间</span>
+        <el-date-picker
+          v-model="endTime"
+          :clearable="false"
+          type="datetime"
+          value-format="timestamp"
+          placeholder="选择日期">
+        </el-date-picker>
+      </div>
+      <div>
+        <span style="font-weight: bold;font-size: 14px">场站名称:</span>
+        <el-select style="width:250px" clearable v-model="stationCode" size="small">
+          <el-option
+            v-for="item in stationList"
+            :key="item.stationCode"
+            :label="item.name"
+            :value="item.stationCode">
+            <span style="float: left">{{ item.name }}</span>
+            <span style="float: right; color: #8492a6;font-size: 13px">{{ item.stationCode }}</span>
+          </el-option>
+        </el-select>
+      </div>
+      <div class="timeQuery">
+        <el-button size="small" :loading="loading" @click="dateQuery">查询</el-button>
+      </div>
+    </div>
+
+    <div class="content">
+      <el-tabs type="card" v-model="activeName" @tab-click="Byresize">
+        <el-tab-pane label="图表" name="first">
+          <chart :drawData=this.drawData :resizeKey=this.resizeKey
+          />
+        </el-tab-pane>
+        <el-tab-pane label="表格" name="second">
+          <div class="tableContent">
+            <vxe-table
+              id="fstTable"
+              ref="fstRef"
+              border
+              export-config
+              beforeExportMethod=""
+              :loading="loading"
+              @sort-change="sortChangeEvent"
+              :custom-config="{storage: true, checkMethod: checkColumnMethod}"
+              :auto-resize="true"
+              highlight-hover-row
+              :header-cell-style="{background:'black',color:'white',border:'white'}"
+              max-height="90%"
+              :cell-style="{background:'black',color:'white'}"
+              align="center"
+              :data="tableData">
+              <vxe-table-column field="forecastTime" title="预测时间" :formatter="dateFormat" width="180" sortable
+                                min-width="150"></vxe-table-column>
+              <vxe-table-column field="genDate" title="生成时间" min-width="60" :formatter="dateMoment"></vxe-table-column>
+              <vxe-table-column field="fpValue" title="预测功率" min-width="60"></vxe-table-column>
+              <vxe-table-column field="predictionModelEnum" title="预测模型" min-width="60"
+                                :formatter="enumToWord"></vxe-table-column>
+            </vxe-table>
+            <div class="rtPageturning">
+              <vxe-pager
+                background
+                :loading="loading"
+                :current-page="currentPage"
+                :page-size="pageSize"
+                :total="total"
+                @page-change="handlePageChange"
+                :layouts="['PrevJump', 'PrevPage', 'JumpNumber', 'NextPage', 'NextJump', 'Sizes', 'FullJump', 'Total']">
+              </vxe-pager>
+            </div>
+          </div>
+          <!-- <Table height="100%" width="100%" :queryTime=this.queryTime @sendLoading="getLoadingFormTable"></Table>-->
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
+<script>
+import Chart from './charts'
+import resize from '../../../components/Charts/mixins/resize'
+import moment from "moment";
+
+export default {
+  name: 'dq',
+  components: {Chart},
+  mixins: [resize],
+  data() {
+    return {
+      stationCode: '',
+      chart: null,
+      queryStartTime: '',
+      queryEndTime: '',
+      startTime: new Date(new Date().toLocaleDateString()).getTime() + 60 * 60 * 24 * 1000,
+      endTime: new Date(new Date().toLocaleDateString()).getTime() + 60 * 60 * 24 * 1000 * 4 - 1,
+      loading: true,
+      drawLoading: true,
+      tableLoading: true,
+      resizeKey: 1,
+      activeName: 'first',
+      drawData: {datas: [], times: []},
+      tableData: [],
+      stationList: [],
+      total: 0,
+      sortOrder: 'asc',
+      pageSize: 10,
+      currentPage: 1,
+      showToolBar: false,
+
+    }
+  },
+  created() {
+    this.$nextTick(() => {
+      // 手动将表格和工具栏进行关联
+      this.$refs.fstRef.connect(this.$refs.fstToolBar)
+    })
+  },
+  mounted() {
+    this.getStationList()
+    this.init()
+  },
+  methods: {
+    getStationList() {
+      this.$axios.get('/electricField/getElectricField').then((res) => {
+        this.stationList = res.data
+      }).catch((error) => {
+        this.$message.error('获取场站下拉框出错' + error)
+      })
+      this.loading = false
+    },
+    init() {
+      this.pageSize = 10
+      this.queryStartTime = this.startTime
+      this.queryEndTime = this.endTime
+      this.loading = false
+    },
+    getDraw(startTime, endTime, stationCode) {
+      this.drawLoading = true
+      this.$axios.get('/forecastPowerShortTerm/' + startTime + '/' + endTime + '/' + stationCode).then((res) => {
+        this.drawData = res.data
+        this.drawLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+      }).catch((error) => {
+        this.drawLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+        this.$message.error('查询实时预测短期echarts出错' + error)
+      })
+    },
+    getTable() {
+      this.tableLoading = true
+      this.$axios.get('/forecastPowerShortTerm/' + this.queryStartTime + '/' + this.queryEndTime + '/' + this.stationCode + '/' + this.currentPage + '/' + this.pageSize + '?sortOrder=' + this.sortOrder).then((res) => {
+        this.tableData = res.data.content
+        // 表分页格数据总条数
+        this.total = res.data.count
+        this.tableLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+      }).catch((error) => {
+        this.tableLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+        this.$message.error('查询table出错' + error)
+      })
+
+    },
+    handlePageChange({currentPage, pageSize}) {
+      this.currentPage = currentPage
+      if (this.pageSize != pageSize) {
+        this.changePageSize(pageSize)
+      }
+      this.pageSize = pageSize
+      this.startTime = this.queryStartTime
+      this.endTime = this.queryEndTime
+      this.loading = true
+      this.getTable();
+    },
+    changePageSize(pageSize) {
+      this.displayConfigPageSize.showCode = pageSize
+      this.$axios.post('displayConfig/', this.displayConfigPageSize).then((res) => {
+        this.displayConfigPageSize = res.data
+        // this.$message.success('PageSize设置成功' )
+        this.dialogVisible = false
+      }).catch((error) => {
+        this.$message.error('PageSize设置出错' + error)
+      })
+    },
+    dateFormat({cellValue, row, column}) {
+      return this.$XEUtils.toDateString(cellValue, 'yyyy-MM-dd HH:mm:ss')
+    },
+    enumToWord({cellValue, row, column}) {
+      if (cellValue == "E1") {
+        return "云端模型"
+      }
+      if (cellValue == 'E2') {
+        return "物理模型"
+      }
+      if (cellValue == 'E3') {
+        return "统计模型"
+      }
+      if (cellValue == 'E4') {
+        return "补录数据"
+      }
+      if (cellValue == 'E5') {
+        return "差值模型"
+      }
+    },
+    dateMoment({cellValue, row, column}) {
+      return moment(cellValue).format('YYYY-MM-DD HH:mm:ss')
+    },
+    sortChangeEvent({column, property, order}) {
+      if (order == null) {
+        order = 'asc'
+      }
+      this.currentPage = 1
+      this.sortOrder = order
+      this.loading = true
+      this.getTable()
+    },
+
+    checkColumnMethod({column}) {
+      if (column.property === 'preTime') {
+        return false
+      }
+      return true
+    },
+    dateQuery() {
+      this.loading = true
+      if (this.endTime <= this.startTime) {
+        this.$message.error("开始时间不能小于结束时间")
+        this.startTime = this.queryStartTime
+        this.endTime = this.queryEndTime
+        this.loading = false
+        return
+      }
+      if (this.endTime - this.startTime > 60 * 60 * 24 * 1000 * 31) {
+        this.startTime = this.queryStartTime
+        this.endTime = this.queryEndTime
+        this.$message.error("只能最多查询31天的数据哦")
+        this.loading = false
+        return
+      }
+      this.queryStartTime = this.startTime
+      this.queryEndTime = this.endTime
+      this.getDraw(this.queryStartTime, this.queryEndTime, this.stationCode)
+      this.getTable()
+    },
+    Byresize(tab) {
+      if (tab.name == 'first') {
+        this.resizeKey++
+        this.showToolBar = false
+      } else {
+        this.showToolBar = true
+      }
+
+    },
+  }
+}
+</script>
+
+<style scoped>
+.chart-container {
+  position: relative;
+  width: 100%;
+  height: calc(100vh - 50px);
+}
+
+.filter {
+  position: relative;
+  display: flex;
+  padding: 20px 0 10px 15px;
+  font-size: 12px;
+  line-height: 11px;
+  color: white;
+}
+
+input {
+  background: transparent;
+  border: none;
+  color: white;
+}
+
+.timeText {
+  opacity: 0.69;
+  padding-right: 7px;
+  font-size: 14px;
+}
+
+.startTime {
+  display: inline-block;
+}
+
+.endTime {
+  display: inline-block;
+  padding-left: 42px;
+}
+
+
+.timeQuery {
+  background: transparent;
+}
+
+
+</style>
+

+ 426 - 0
ipfcst-console/src/main/frontend/views/dataquery/nwp/charts/index.vue

@@ -0,0 +1,426 @@
+<template>
+  <div style="width: 100%;height: 100%">
+    <div id="nwpcharts"></div>
+  </div>
+</template>
+
+<script>
+import resize from '../../../../components/Charts/mixins/resize'
+import echarts from 'echarts'
+import cc from '../../../../components/curvecolors'
+
+export default {
+  mixins: [resize],
+  watch: {
+    drawData: {
+      handler(newValue, oldValue) {
+        this.cName = newValue.cName
+        if (newValue.stationType == '1') {
+          this.company = 'W/㎡'
+          this.thFormat = [
+            {key: "directRadiation", value: '直辐射'},
+            {key: "diffuseRadiation", value: '散辐射'},
+            {key: "swr", value: '总辐射'}
+          ]
+        } else {
+          this.thFormat = [
+            {key: "ws10", value: this.cName.ws10},
+            {key: "ws30", value: this.cName.ws30},
+            {key: "ws50", value: this.cName.ws50},
+            {key: "ws70", value: this.cName.ws70},
+            {key: "ws80", value: this.cName.ws80},
+            {key: "ws90", value: this.cName.ws90},
+            {key: "ws100", value: this.cName.ws100},
+            {key: "ws170", value: this.cName.ws170}]
+        }
+
+        this.draw(newValue.times, newValue.datas)
+
+      },
+      deep: true
+    },
+    resizeKey: function (newQuestion, oldQuestion) {
+      if (this.chart != null) {
+        this.chart.resize();
+      }
+    }
+  },
+  props: {
+    drawData: {
+      type: Object,
+    },
+    resizeKey: {
+      type: Number
+    }
+  },
+  data() {
+    return {
+      cName: {},
+      chart: null,
+      thFormat: [],
+      company: 'm/s',
+      lineStyle: [
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(219,50,51,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws10,
+              borderColor: 'rgba(219,50,51,0.2)',
+              borderWidth: 12
+            }
+          },
+        },
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(219,196,50,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws30,
+              borderColor: 'rgba(219,196,50,0.2)',
+              borderWidth: 12
+            }
+          },
+        },
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(101,219,50,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws50,
+              borderColor: 'rgba(101,219,50,0.2)',
+              borderWidth: 12
+            }
+          },
+        },
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(50,219,171,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws70,
+              borderColor: 'rgba(50,219,171,0.2)',
+              borderWidth: 12
+            }
+          },
+        },
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(50,118,219,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws80,
+              borderColor: 'rgba(50,118,219,0.2)',
+              borderWidth: 12
+            }
+          },
+        },
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(140,50,219,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws90,
+              borderColor: 'rgba(140,50,219,0.2)',
+              borderWidth: 12
+            }
+          },
+        },
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(202,50,219,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws100,
+              borderColor: 'rgba(202,50,219,0.2)',
+              borderWidth: 12
+            }
+          },
+        },
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(50,199,219,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws110,
+              borderColor: 'rgba(50,199,219,0.2)',
+              borderWidth: 12
+            }
+          },
+        },
+        {
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                offset: 0,
+                color: 'rgba(219,143,50,0.3)'
+              }, {
+                offset: 0.8,
+                color: 'rgba(219, 50, 51, 0)'
+              }], false),
+              shadowColor: 'rgba(0, 0, 0, 0.1)',
+              shadowBlur: 10
+            }
+          },
+          itemStyle: {
+            normal: {
+              color: cc.ws120,
+              borderColor: 'rgba(219,143,50,0.2)',
+              borderWidth: 12
+            }
+          },
+        }
+      ]
+    }
+  },
+  mounted() {
+  },
+  beforeDestroy() {
+    if (!this.chart) {
+      return
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    draw(timeaxis, datas) {
+      this.chart = echarts.init(document.getElementById('nwpcharts'))
+      var option = {
+        backgroundColor: 'transparent',
+        title: {
+          top: 20,
+          text: 'nwp信息',
+          textStyle: {
+            fontWeight: 'normal',
+            fontSize: 16,
+            color: '#79acff'
+          },
+          left: '1%'
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            lineStyle: {
+              color: '#57617B'
+            }
+          }
+        },
+        toolbox: {
+          feature: {
+            // dataView: {show: true, readOnly: false},
+            // magicType: {show: true, type: ['line', 'bar']},
+            // restore: {show: true},
+            saveAsImage: {show: true}
+          }
+        },
+        legend: {
+          top: 20,
+          width: '70%',
+          icon: 'rect',
+          itemWidth: 14,
+          itemHeight: 5,
+          itemGap: 13,
+          data: [],
+          right: '4%',
+          textStyle: {
+            fontSize: 12,
+            color: '#79acff'
+          },
+          selected: {}
+        },
+        dataZoom: [{
+          show: true,
+          realtime: true,
+          start: 0,
+          end: 100,
+          left: "15%",
+          right: "15%",
+          textStyle: {
+            color: "#79acff"
+          }
+        }, {
+          type: 'inside'
+        }],
+        grid: {
+          top: 100,
+          left: '2%',
+          right: '2%',
+          bottom: '10%',
+          containLabel: true
+        },
+        xAxis: [{
+          type: 'category',
+          boundaryGap: false,
+          axisLine: {
+            lineStyle: {
+              color: '#79acff'
+            }
+          },
+          data: []
+        }],
+        yAxis: [{
+          type: 'value',
+          name: this.company,
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#79acff'
+            }
+          },
+
+          axisLabel: {
+            margin: 10,
+            textStyle: {
+              fontSize: 14,
+              color: '#79acff'
+            },
+            formatter: '{value}',
+          },
+          splitLine: {
+            lineStyle: {
+              color: '#57617B'
+            }
+          }
+        }],
+        series: []
+      }
+      option.xAxis[0].data = timeaxis
+      var index = 0;
+      for (var key in datas) {
+        var keyName = '';
+        for (var i = 0; i < this.thFormat.length; i++) {
+          if (key == this.thFormat[i].key) {
+            keyName = this.thFormat[i].value;
+          }
+        }
+        option.legend.data.push(keyName)
+        if (index > 5) {
+          option.legend.selected[keyName] = false
+        } else {
+          option.legend.selected[keyName] = true
+        }
+        var sValue = {
+          name: '',
+          type: 'line',
+          smooth: false,
+          symbol: 'circle',
+          symbolSize: 5,
+          showSymbol: false,
+          lineStyle: {
+            normal: {
+              width: 2
+            }
+          },
+          // areaStyle: {},
+          itemStyle: {},
+          data: []
+        }
+        sValue.name = keyName
+        sValue.data = datas[key]
+        // sValue.areaStyle = this.lineStyle[index].areaStyle
+        sValue.itemStyle = this.lineStyle[index].itemStyle
+        option.series.push(sValue)
+        index++;
+      }
+      this.chart.setOption(option, true)
+    },
+
+  }
+}
+</script>
+<style scoped>
+#nwpcharts {
+  width: 100%;
+  height: calc(80vh - 50px);
+}
+</style>

+ 312 - 0
ipfcst-console/src/main/frontend/views/dataquery/nwp/index.vue

@@ -0,0 +1,312 @@
+<template>
+  <div class="chart-container">
+    <div class="filter">
+      <div class="startTime">
+        <span class="timeText">起始时间</span>
+        <el-date-picker
+          v-model="startTime"
+          :clearable="false"
+          type="datetime"
+          value-format="timestamp"
+          placeholder="选择日期">
+        </el-date-picker>
+      </div>
+      <div class="endTime">
+        <span class="timeText">截止时间</span>
+        <el-date-picker
+          v-model="endTime"
+          :clearable="false"
+          type="datetime"
+          value-format="timestamp"
+          placeholder="选择日期">
+        </el-date-picker>
+      </div>
+      <div>
+        <span style="font-weight: bold;font-size: 14px">场站名称:</span>
+        <el-select style="width:250px" clearable v-model="stationCode" size="small">
+          <el-option
+            v-for="item in stationList"
+            :key="item.stationCode"
+            :label="item.name"
+            :value="item.stationCode">
+            <span style="float: left">{{ item.name }}</span>
+            <span style="float: right; color: #8492a6;font-size: 13px">{{ item.stationCode }}</span>
+          </el-option>
+        </el-select>
+      </div>
+      <div class="timeQuery">
+        <el-button size="small" :loading="loading" @click="dateQuery">查询</el-button>
+      </div>
+
+      <div class="toolbar" v-show="this.showToolBar">
+        <vxe-toolbar ref="nwpToolBar" custom></vxe-toolbar>
+      </div>
+    </div>
+
+    <div class="content">
+      <el-tabs type="card" v-model="activeName" @tab-click="Byresize">
+        <el-tab-pane label="图表" name="first">
+          <chart :drawData=this.drawData :resizeKey=this.resizeKey
+          />
+        </el-tab-pane>
+        <el-tab-pane label="表格" name="second">
+          <div class="tableContent">
+            <vxe-grid
+              id="nwpTable"
+              ref="nwpRef"
+              border
+              export-config
+              :loading="loading"
+              @sort-change="sortChangeEvent"
+              :custom-config="{storage: true, checkMethod: checkColumnMethod}"
+              :auto-resize="true"
+              highlight-hover-row
+              :header-cell-style="{background:'black',color:'white',border:'white'}"
+              max-height="90%"
+              :cell-style="{background:'black',color:'white'}"
+              align="center"
+              :columns="tableColumn"
+              :data="tableData">
+            </vxe-grid>
+            <div class="rtPageturning">
+              <vxe-pager
+                background
+                :loading="loading"
+                :current-page.sync="currentPage"
+                :page-size.sync="pageSize"
+                :total="total"
+                @page-change="handlePageChange"
+                :layouts="['PrevJump', 'PrevPage', 'JumpNumber', 'NextPage', 'NextJump', 'Sizes', 'FullJump', 'Total']">
+              </vxe-pager>
+            </div>
+          </div>
+          <!-- <Table height="100%" width="100%" :queryTime=this.queryTime @sendLoading="getLoadingFormTable"></Table>-->
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
+<script>
+import Chart from './charts'
+import resize from '../../../components/Charts/mixins/resize'
+
+export default {
+  name: 'nwp',
+  components: {Chart},
+  mixins: [resize],
+  data() {
+    return {
+      stationCode: '',
+      stationList: [],
+      tableColumn: [],
+      chart: null,
+      queryStartTime: new Date(new Date().toLocaleDateString()).getTime() - 60 * 60 * 24 * 1000 * 10,
+      queryEndTime: new Date(new Date().toLocaleDateString()).getTime() + 60 * 60 * 24 * 1000 * 10,
+      startTime: new Date(new Date().toLocaleDateString()).getTime() - 60 * 60 * 24 * 1000 * 10,
+      endTime: new Date(new Date().toLocaleDateString()).getTime() + 60 * 60 * 24 * 1000 * 10,
+      loading: true,
+      drawLoading: true,
+      tableLoading: true,
+      resizeKey: 1,
+      activeName: 'first',
+      drawData: {datas: [], times: []},
+      tableData: [],
+      statisticsData: [],
+      total: 0,
+      sortOrder: 'asc',
+      pageSize: 10,
+      currentPage: 1,
+      showToolBar: false
+
+    }
+  },
+  created() {
+    this.$nextTick(() => {
+      // 手动将表格和工具栏进行关联
+      this.$refs.nwpRef.connect(this.$refs.nwpToolBar)
+    })
+  },
+  mounted() {
+    this.getStationList()
+  },
+  methods: {
+    getStationList() {
+      this.$axios.get('/electricField/getElectricField').then((res) => {
+        this.stationList = res.data
+      }).catch((error) => {
+        this.$message.error('获取场站下拉框出错' + error)
+      })
+      this.loading = false
+    },
+    getDraw(startTime, endTime, stationCode) {
+      this.drawLoading = true
+      this.$axios.get('/nwp/' + startTime + '/' + endTime + '/' + stationCode).then((res) => {
+        this.drawData = res.data
+        this.drawLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+      }).catch((error) => {
+        this.drawLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+        this.$message.error('查询实时预测短期echarts出错' + error)
+      })
+
+    },
+    getTable() {
+      this.tableLoading = true
+      this.$axios.get('/nwp/' + this.queryStartTime + '/' + this.queryEndTime + '/' + this.stationCode + '/' + this.currentPage + '/' + this.pageSize + '?sortOrder=' + this.sortOrder).then((res) => {
+        this.tableData = res.data.content
+        // 表分页格数据总条数
+        this.total = res.data.count
+        this.statisticsData = res.data.statistics
+        const cName = res.data.cName
+
+        this.tableColumn = [
+          {field: 'preTime', title: cName.preTime, formatter: this.dateFormat, minWidth: "150", width: "180"},
+          {field: 'scTime', title: cName.scTime, minWidth: "150"},
+          {field: 't', title: cName.t, minWidth: "90"},
+          {field: 'rh', title: cName.rh, minWidth: "90"},
+          {field: 'pressure', title: cName.pressure, minWidth: "90"},
+          {field: 'swr', title: cName.swr, minWidth: "90"},
+          {field: 'directRadiation', title: cName.directRadiation, minWidth: "90"},
+          {field: 'diffuseRadiation', title: cName.diffuseRadiation, minWidth: "90"},
+          {field: 'ws10', title: cName.ws10, minWidth: "90"},
+          {field: 'ws30', title: cName.ws30, minWidth: "90"},
+          {field: 'ws50', title: cName.ws50, minWidth: "90"},
+          {field: 'ws70', title: cName.ws70, minWidth: "90"},
+          {field: 'ws80', title: cName.ws80, minWidth: "90"},
+          {field: 'ws90', title: cName.ws90, minWidth: "90"},
+          {field: 'ws100', title: cName.ws100, minWidth: "90"},
+          {field: 'ws170', title: cName.ws170, minWidth: "90"},
+          {field: 'wd10', title: cName.wd10, minWidth: "90"},
+          {field: 'wd30', title: cName.wd30, minWidth: "90"},
+          {field: 'wd50', title: cName.wd50, minWidth: "90"},
+          {field: 'wd70', title: cName.wd70, minWidth: "90"},
+          {field: 'wd80', title: cName.wd80, minWidth: "90"},
+          {field: 'wd90', title: cName.wd90, minWidth: "90"},
+          {field: 'wd100', title: cName.wd100, minWidth: "90"},
+          {field: 'wd170', title: cName.wd170, minWidth: "90"},
+        ]
+        this.tableLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+      }).catch((error) => {
+        this.tableLoading = false
+        if (!this.drawLoading && !this.tableLoading) {
+          this.loading = false
+        }
+        this.$message.error('查询table出错' + error)
+      })
+      this.tableLoading = false
+      this.loading = false
+    },
+    handlePageChange({currentPage, pageSize}) {
+      this.currentPage = currentPage
+      this.pageSize = pageSize
+      this.startTime = this.queryStartTime
+      this.endTime = this.queryEndTime
+      this.loading = true
+      this.getTable();
+    },
+    dateFormat({cellValue, row, column}) {
+      return this.$XEUtils.toDateString(cellValue, 'yyyy-MM-dd HH:mm:ss')
+    },
+    sortChangeEvent({column, property, order}) {
+      if (order == null) {
+        order = 'asc'
+      }
+      this.currentPage = 1
+      this.sortOrder = order
+      this.loading = true
+      this.getTable()
+    },
+
+    checkColumnMethod({column}) {
+      if (column.property === 'preTime') {
+        return false
+      }
+      return true
+    },
+    dateQuery() {
+      this.loading = true
+      if (this.endTime <= this.startTime) {
+        this.$message.error("开始时间不能小于结束时间")
+        this.startTime = this.queryStartTime
+        this.endTime = this.queryEndTime
+        this.loading = false
+        return
+      }
+      if (this.endTime - this.startTime > 60 * 60 * 24 * 1000 * 31) {
+        this.startTime = this.queryStartTime
+        this.endTime = this.queryEndTime
+        this.$message.error("只能最多查询31天的数据哦")
+        this.loading = false
+        return
+      }
+      this.queryStartTime = this.startTime
+      this.queryEndTime = this.endTime
+      this.getDraw(this.queryStartTime, this.queryEndTime, this.stationCode)
+      this.getTable()
+    },
+    Byresize(tab) {
+      if (tab.name == 'first') {
+        this.resizeKey++
+        this.showToolBar = false
+      } else {
+        this.showToolBar = true
+      }
+
+    },
+  }
+}
+</script>
+
+<style scoped>
+.chart-container {
+  position: relative;
+  width: 100%;
+  height: calc(100vh - 50px);
+}
+
+.filter {
+  position: relative;
+  display: flex;
+  padding: 20px 0 10px 15px;
+  font-size: 12px;
+  line-height: 11px;
+  color: white;
+}
+
+input {
+  background: transparent;
+  border: none;
+  color: white;
+}
+
+.timeText {
+  opacity: 0.69;
+  padding-right: 7px;
+  font-size: 14px;
+}
+
+.startTime {
+  display: inline-block;
+}
+
+.endTime {
+  display: inline-block;
+  padding-left: 42px;
+}
+
+
+.timeQuery {
+  background: transparent;
+}
+
+</style>
+

+ 73 - 0
ipfcst-console/src/main/java/com/jiayue/ipfcst/console/controller/ForecastPowerShortTermController.java

@@ -0,0 +1,73 @@
+package com.jiayue.ipfcst.console.controller;
+
+import com.jiayue.ipfcst.common.core.web.vo.ResponseVO;
+import com.jiayue.ipfcst.console.service.ForecastPowerShortTermService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 短期预测信息restful接口
+ */
+@RestController
+@Slf4j
+public class ForecastPowerShortTermController {
+  private final ForecastPowerShortTermService forecastPowerShortTermService;
+
+  @Autowired
+  public ForecastPowerShortTermController(ForecastPowerShortTermService forecastPowerShortTermService) {
+    this.forecastPowerShortTermService = forecastPowerShortTermService;
+  }
+
+  /**
+   * 按时间查询实时预测短期 yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 结果集
+   */
+  @GetMapping(value = "/forecastPowerShortTerm/{startTime}/{endTime}/{stationCode}")
+  public ResponseVO findByForecastTimeBetween(@PathVariable("startTime") Long startTime,
+                                              @PathVariable("endTime") Long endTime, @PathVariable("stationCode") String stationCode) {
+    Map<String, Object> map = new HashMap<>();
+    try {
+      map = forecastPowerShortTermService.findByForecastTimeBetweenAndStationCode(startTime, endTime, stationCode);
+      return ResponseVO.success(map);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return ResponseVO.fail(e.getMessage());
+    }
+  }
+
+  /**
+   * 分页查询  实时短期预测
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @param page      页码
+   * @param size      条数
+   * @param sortOrder 排序
+   * @return
+   */
+  @GetMapping(value = "/forecastPowerShortTerm/{startTime}/{endTime}/{stationCode}/{page}/{size}")
+  public ResponseVO findByTimeBetweenForPaging(@PathVariable("startTime") Long startTime,
+                                               @PathVariable("endTime") Long endTime,
+                                               @PathVariable("stationCode") String stationCode,
+                                               @PathVariable("page") Integer page,
+                                               @PathVariable("size") Integer size,
+                                               String sortOrder) {
+    Map<String, Object> map = new HashMap<>();
+    try {
+      map = forecastPowerShortTermService.findByTimeBetweenAndNoForPaging(startTime, endTime, stationCode, page, size, sortOrder);
+      return ResponseVO.success(map);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return ResponseVO.fail(e.toString());
+    }
+  }
+}

+ 52 - 0
ipfcst-console/src/main/java/com/jiayue/ipfcst/console/controller/ForecastPowerShortTermHisController.java

@@ -0,0 +1,52 @@
+package com.jiayue.ipfcst.console.controller;
+
+import com.jiayue.ipfcst.common.core.web.vo.ResponseVO;
+import com.jiayue.ipfcst.console.service.ForecastPowerShortTermHisService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 短期预测历史信息restful接口
+ */
+@RestController
+@Slf4j
+public class ForecastPowerShortTermHisController {
+  private final ForecastPowerShortTermHisService forecastPowerShortTermHisService;
+
+  @Autowired
+  public ForecastPowerShortTermHisController(ForecastPowerShortTermHisService forecastPowerShortTermHisService) {
+    this.forecastPowerShortTermHisService = forecastPowerShortTermHisService;
+  }
+
+  /**
+   * 按时间查询历史预测短期 yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 结果集
+   */
+  @GetMapping(value = "/forecastPowerShortTermHis/{startTime}/{endTime}/{stationCode}/{page}/{size}")
+  public ResponseVO findByForecastTimeBetween(@PathVariable("startTime") Long startTime,
+                                              @PathVariable("endTime") Long endTime,
+                                              @PathVariable("stationCode") String stationCode,
+                                              @PathVariable("page") Integer page,
+                                              @PathVariable("size") Integer size,
+                                              String sortOrder) {
+    Map<String, Object> map = new HashMap<>();
+    try {
+      map = forecastPowerShortTermHisService.findByForecastTimeBetweenAndStationCode(startTime, endTime, stationCode, page, size, sortOrder);
+      return ResponseVO.success(map);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return ResponseVO.fail(e.toString());
+    }
+  }
+
+
+}

+ 81 - 0
ipfcst-console/src/main/java/com/jiayue/ipfcst/console/controller/NwpController.java

@@ -0,0 +1,81 @@
+package com.jiayue.ipfcst.console.controller;
+
+import com.jiayue.ipfcst.common.core.web.vo.ResponseVO;
+import com.jiayue.ipfcst.console.service.NwpService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * NWP信息restful接口
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2019/8/7 10:12
+ */
+@RestController
+@Slf4j
+public class NwpController {
+  private final NwpService nwpService;
+
+  @Autowired
+  public NwpController(NwpService nwpService) {
+    this.nwpService = nwpService;
+  }
+
+  /**
+   * 按时间查询实时nwp yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 结果集
+   */
+  @GetMapping(value = "/nwp/{startTime}/{endTime}/{stationCode}")
+  public ResponseVO findByForecastTimeBetween(@PathVariable("startTime") Long startTime,
+                                              @PathVariable("endTime") Long endTime,
+                                              @PathVariable("stationCode") String stationCode) {
+    Map<String, Object> map = new HashMap<>();
+    try {
+      map = nwpService.findByForecastTimeBetween(startTime, endTime, stationCode);
+      return ResponseVO.success(map);
+    } catch (Exception e) {
+      e.printStackTrace();
+      log.error("nwp实时查询错误");
+      return ResponseVO.fail(e.toString());
+    }
+  }
+
+  /**
+   * 分页查询  实时nwp
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @param page      页码
+   * @param size      条数
+   * @param sortOrder 排序
+   * @return
+   */
+  @GetMapping(value = "/nwp/{startTime}/{endTime}/{stationCode}/{page}/{size}")
+  public ResponseVO findByTimeBetweenForPaging(@PathVariable("startTime") Long startTime,
+                                               @PathVariable("endTime") Long endTime,
+                                               @PathVariable("stationCode") String stationCode,
+                                               @PathVariable("page") Integer page,
+                                               @PathVariable("size") Integer size,
+                                               String sortOrder) {
+    Map<String, Object> map = new HashMap<>();
+    try {
+      map = nwpService.findByTimeBetweenAndNoForPaging(startTime, endTime, stationCode, page, size, sortOrder);
+      return ResponseVO.success(map);
+    } catch (Exception e) {
+      e.printStackTrace();
+      log.error("nwp实时分页查询错误");
+      return ResponseVO.fail(e.toString());
+    }
+  }
+
+}

+ 170 - 0
ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/ForecastPowerShortTermHisService.java

@@ -0,0 +1,170 @@
+package com.jiayue.ipfcst.console.service;
+
+import com.jiayue.ipfcst.common.data.entity.ForecastPowerShortTermHis;
+import com.jiayue.ipfcst.common.data.repository.ForecastPowerShortTermHisRepository;
+import com.jiayue.ipfcst.common.data.service.BaseService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.criteria.Predicate;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 历史预测短期业务层
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2019/8/5 16:02
+ */
+@Service
+public class ForecastPowerShortTermHisService extends BaseService {
+  private final ForecastPowerShortTermHisRepository forecastPowerShortTermHisRepository;
+
+  @Autowired
+  public ForecastPowerShortTermHisService(ForecastPowerShortTermHisRepository forecastPowerShortTermHisRepository) {
+    this.forecastPowerShortTermHisRepository = forecastPowerShortTermHisRepository;
+  }
+
+  /**
+   * 根据提前多久,开始结束时间查询历史超短期 yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @param ago       提前多久预测
+   * @return 结果集
+   */
+  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
+  public Map<String, Object> findByForecastTimeBetweenAndForecastHowLongAgoOrderByForecastTime(Long startTime, Long endTime, Integer ago) {
+    Map<String, Object> map = new HashMap<>();
+    List<ForecastPowerShortTermHis> list = forecastPowerShortTermHisRepository.findByForecastTimeBetweenAndForecastHowLongAgo(startTime, endTime, ago);
+    list.sort(Comparator.comparing(ForecastPowerShortTermHis::getForecastTime));
+    long timeStep = 900000L;
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    List<String> times = new ArrayList<>();
+    List<Float> datas = new ArrayList<>();
+    if (startTime % timeStep != 0) {
+      startTime = startTime - (startTime % timeStep) + timeStep;
+    }
+    if (list != null && list.size() > 0) {
+      for (Long i = startTime; i < endTime; i = i + timeStep) {
+        long finalI = i;
+        List<ForecastPowerShortTermHis> filterList = list.stream().filter(t -> t.getForecastTime() == finalI).collect(Collectors.toList());
+        if (filterList != null && filterList.size() > 0) {
+          datas.add(filterList.get(0).getAbleValue().floatValue());
+        } else {
+          datas.add(null);
+        }
+
+        times.add(sdf.format(new Date(finalI)));
+      }
+    }
+    map.put("times", times);
+    map.put("datas", datas);
+
+    return map;
+  }
+
+  /**
+   * 根据时间,场站编码查询历史短期数据
+   *
+   * @param startTime   开始时间
+   * @param endTime     结束时间
+   * @param stationCode
+   * @return 结果集
+   */
+  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
+  public Map<String, Object> findByForecastTimeBetweenAndStationCode(Long startTime, Long endTime, String stationCode, Integer page, Integer size, String sortOrder) {
+
+    Map<String, Object> map = new HashMap<>();
+    Sort sort = Sort.by(Sort.Direction.DESC, "forecastTime");
+    if (sortOrder.contains("asc")) {
+      sort = Sort.by(Sort.Direction.ASC, "forecastTime");
+    }
+    Specification<ForecastPowerShortTermHis> specification = this.specificationFindByTimeAndNo(startTime, endTime, stationCode);
+    Pageable pageable = PageRequest.of(page - 1, size, sort);
+    Page forecastPowerShortTermHiss = forecastPowerShortTermHisRepository.findAll(specification, pageable);
+    List<ForecastPowerShortTermHis> datas = forecastPowerShortTermHiss.getContent();
+    map.put("content", datas);
+    map.put("count", forecastPowerShortTermHiss.getTotalElements());
+
+    return map;
+  }
+
+
+  /**
+   * 根据提前多久,开始结束时间查询历史超短期 yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @param ago       提前多久预测
+   * @return 结果集
+   */
+  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
+  public Map<String, Object> findByForecastTimeBetweenAndForecastHowLongAgoOrderByForecastTimeForDB(Long startTime, Long endTime, Integer ago, Long timeStep) {
+    Map<String, Object> map = new HashMap<>();
+    List<ForecastPowerShortTermHis> list = forecastPowerShortTermHisRepository.findByForecastTimeBetweenAndForecastHowLongAgo(startTime, endTime, ago);
+    list.sort(Comparator.comparing(ForecastPowerShortTermHis::getForecastTime));
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    List<String> times = new ArrayList<>();
+    List<Float> datas = new ArrayList<>();
+    if (startTime % timeStep != 0) {
+      startTime = startTime - (startTime % timeStep) + timeStep;
+    }
+    for (Long i = startTime; i < endTime; i = i + timeStep) {
+      if (list != null && list.size() > 0) {
+        long finalI = i;
+        List<ForecastPowerShortTermHis> filterList = list.stream().filter(t -> t.getForecastTime() == finalI).collect(Collectors.toList());
+        if (filterList != null && filterList.size() > 0) {
+          datas.add(filterList.get(0).getAbleValue().floatValue());
+        } else {
+          datas.add(null);
+        }
+      } else {
+        datas.add(null);
+      }
+      times.add(sdf.format(new Date(i)));
+
+    }
+
+    map.put("times", times);
+    map.put("datas", datas);
+
+    return map;
+  }
+
+
+  /**
+   * 根据时间和编号 分页查询条件 yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 过滤条件
+   */
+  Specification<ForecastPowerShortTermHis> specificationFindByTimeAndNo(final Long startTime, final Long endTime, String stationCode) {
+    return (Specification<ForecastPowerShortTermHis>) (root, criteriaQuery, cb) -> {
+      List<Predicate> predicates = new ArrayList<>();
+      if (startTime != null) {
+        //大于或等于传入时间
+        predicates.add(cb.greaterThanOrEqualTo(root.get("forecastTime").as(Long.class), startTime));
+      }
+      if (endTime != null) {
+        //小于传入时间
+        predicates.add(cb.lessThan(root.get("forecastTime").as(Long.class), endTime));
+      }
+      predicates.add(cb.equal(root.get("stationCode").as(String.class), stationCode));
+      //添加排序的功能
+      return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+
+    };
+  }
+
+}

+ 118 - 15
ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/ForecastPowerShortTermService.java

@@ -18,11 +18,18 @@ import com.sun.istack.internal.NotNull;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.time.DateFormatUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.persistence.criteria.Predicate;
 import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -45,8 +52,8 @@ public class ForecastPowerShortTermService extends BaseService {
    * @param listDq
    */
   @Transactional(propagation = Propagation.REQUIRED)
-  public void deleteBetweenAndGenTime(Long startTime, Long endTime, List<ForecastPowerShortTerm> listDq,String stationCode) {
-    forecastPowerShortTermRepository.deleteByForecastTimeBetweenAndStationCode(startTime, endTime,stationCode);
+  public void deleteBetweenAndGenTime(Long startTime, Long endTime, List<ForecastPowerShortTerm> listDq, String stationCode) {
+    forecastPowerShortTermRepository.deleteByForecastTimeBetweenAndStationCode(startTime, endTime, stationCode);
     //保存短期数据
     forecastPowerShortTermRepository.saveAll(listDq);
   }
@@ -62,25 +69,25 @@ public class ForecastPowerShortTermService extends BaseService {
   @Transactional(propagation = Propagation.REQUIRED)
   public List<ForecastPowerShortTermHis> getForecastPowerShortTerm(@NotNull final Long startTime,
                                                                    @NotNull final Long endTime, @NotNull final String stationCode) {
-    log.info(stationCode+"开始获取短期预测功率" + DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss") + " 至 " + DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));
+    log.info(stationCode + "开始获取短期预测功率" + DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss") + " 至 " + DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));
     // 查询场站信息
     ElectricField electricFieldInfo = electricFieldService.getSingleStation(stationCode);
     // 查询预测时间点对应的开机容量
     Map<Long, BigDecimal> openCapacityMap = null;
     try {
-      openCapacityMap = super.queryOpenCapacity(startTime, endTime, electricFieldInfo.getCapacity(),stationCode);
+      openCapacityMap = super.queryOpenCapacity(startTime, endTime, electricFieldInfo.getCapacity(), stationCode);
     } catch (BusinessException e) {
-      log.error(stationCode+"预测数据生成获取开机容量出错:" + CommonUtil.printStackTraceToString(e));
+      log.error(stationCode + "预测数据生成获取开机容量出错:" + CommonUtil.printStackTraceToString(e));
     }
     // 查询短期预测功率
     List<ForecastPowerShortTerm> forecastPowerShortTerms =
-      this.forecastPowerShortTermRepository.findByForecastTimeBetweenAndStationCode(startTime, endTime,stationCode);
+      this.forecastPowerShortTermRepository.findByForecastTimeBetweenAndStationCode(startTime, endTime, stationCode);
     forecastPowerShortTerms.sort(Comparator.comparing(ForecastPowerShortTerm::getForecastTime));
-    log.info(stationCode+"查询现有短期预测记录数:" + forecastPowerShortTerms.size());
+    log.info(stationCode + "查询现有短期预测记录数:" + forecastPowerShortTerms.size());
     // 判断查询结果是否满足查询所需
     Long momentTime = 15 * 60 * 1000L; // 15分钟一个时刻
     Integer moments = Math.toIntExact((endTime - startTime) / momentTime + 1);
-    log.info(stationCode+"获取所需记录数:" + moments);
+    log.info(stationCode + "获取所需记录数:" + moments);
     if (moments > forecastPowerShortTerms.size()) {
       Map<Long, List<ForecastPowerShortTerm>> forecastPowerShortTermsMap =
         forecastPowerShortTerms.stream().collect(Collectors.groupingBy(ForecastPowerShortTerm::getForecastTime));
@@ -110,7 +117,7 @@ public class ForecastPowerShortTermService extends BaseService {
     Long systemTime = System.currentTimeMillis();
 
     //获取数据下限参数
-    String lowerPredictionLimit = super.getSysParameter("LowerPredictionLimit", "0",stationCode);
+    String lowerPredictionLimit = super.getSysParameter("LowerPredictionLimit", "0", stationCode);
     BigDecimal lpl = new BigDecimal(lowerPredictionLimit);
     for (ForecastPowerShortTerm _forecastPowerShortTerm : forecastPowerShortTerms) {
       forecastPowerShortTermHis = new ForecastPowerShortTermHis();
@@ -122,7 +129,7 @@ public class ForecastPowerShortTermService extends BaseService {
         _forecastPowerShortTerm.getFpValue().multiply(openCapacityMap.get(_forecastPowerShortTerm.getForecastTime()))
           .divide(electricFieldInfo.getCapacity(), 2, BigDecimal.ROUND_HALF_UP);
 
-      forecastPowerShortTermHis.setAbleValue(ableValue.compareTo(lpl) == -1?lpl:ableValue);
+      forecastPowerShortTermHis.setAbleValue(ableValue.compareTo(lpl) == -1 ? lpl : ableValue);
       forecastPowerShortTermHis.setPredictionModelEnum(_forecastPowerShortTerm.getPredictionModelEnum());
       forecastPowerShortTermHis.setGenDate(new Date());
       forecastPowerShortTermHis.setSuCapacity(openCapacityMap.get(_forecastPowerShortTerm.getForecastTime()));
@@ -138,7 +145,7 @@ public class ForecastPowerShortTermService extends BaseService {
     forecastPowerShortTermHiss.sort(Comparator.comparing(ForecastPowerShortTermHis::getForecastTime));
     // 删除当日生成的短期历史记录
     this.forecastPowerShortTermHisRepository.deleteToday(forecastPowerShortTermHiss.get(0).getForecastTime(),
-      forecastPowerShortTermHiss.get(forecastPowerShortTermHiss.size() - 1).getForecastTime(),stationCode);
+      forecastPowerShortTermHiss.get(forecastPowerShortTermHiss.size() - 1).getForecastTime(), stationCode);
     // 保存短期历史记录
     this.forecastPowerShortTermHisRepository.saveAll(forecastPowerShortTermHiss);
     return forecastPowerShortTermHiss;
@@ -158,7 +165,7 @@ public class ForecastPowerShortTermService extends BaseService {
     // 根据场站类型调用不同的短期预测模型
     if (ElectricFieldTypeEnum.E2.equals(electricFieldInfo.getElectricFieldTypeEnum())) {
       // 风预测
-      forecastPowerShortTerms = this.generateWindPowerShortTerm(tempTime, openCapacity,electricFieldInfo.getStationCode());
+      forecastPowerShortTerms = this.generateWindPowerShortTerm(tempTime, openCapacity, electricFieldInfo.getStationCode());
     } else {
       // 光预测
       forecastPowerShortTerms = this.generateSolarPowerShortTerm(tempTime, openCapacity, electricFieldInfo);
@@ -183,7 +190,7 @@ public class ForecastPowerShortTermService extends BaseService {
     if (DateTimeUtil.checkInSunriseAndSunset(tempTime, electricFieldInfo.getLongitude().doubleValue(),
       electricFieldInfo.getLatitude().doubleValue())) {
       // 2021-4-22 xsl修改补数取固定系数
-      String a = Constant.forecastCoe(tempTime,electricFieldInfo.getElectricFieldTypeEnum());
+      String a = Constant.forecastCoe(tempTime, electricFieldInfo.getElectricFieldTypeEnum());
       tempValue = new BigDecimal(a);
     } else {
       // 日升日落
@@ -205,17 +212,113 @@ public class ForecastPowerShortTermService extends BaseService {
    * @return 短期预测功率
    */
   @Transactional(propagation = Propagation.REQUIRED)
-  public ForecastPowerShortTerm generateWindPowerShortTerm(@NotNull final Long tempTime, BigDecimal openCapacity,String stationCode) {
+  public ForecastPowerShortTerm generateWindPowerShortTerm(@NotNull final Long tempTime, BigDecimal openCapacity, String stationCode) {
     System.out.println("风补数");
     ForecastPowerShortTerm forecastPowerShortTerm = new ForecastPowerShortTerm();
     forecastPowerShortTerm.setForecastTime(tempTime);
     BigDecimal randomValue = new BigDecimal(CommonUtil.getRandom(97, 99) / 100.0d);
     // 2021-4-22 xsl修改补数取固定系数
-    BigDecimal tempValue = new BigDecimal(Constant.forecastCoe(tempTime,ElectricFieldTypeEnum.E2));
+    BigDecimal tempValue = new BigDecimal(Constant.forecastCoe(tempTime, ElectricFieldTypeEnum.E2));
     forecastPowerShortTerm.setFpValue(NumberUtils.multiply(tempValue, openCapacity).multiply(randomValue).setScale(2, BigDecimal.ROUND_HALF_UP));
     forecastPowerShortTerm.setGenDate(new Date());
     forecastPowerShortTerm.setPredictionModelEnum(PredictionModelEnum.E4);
     forecastPowerShortTerm.setStationCode(stationCode);
     return forecastPowerShortTerm;
   }
+
+  /**
+   * 实时预测数据查询
+   * 时间和场站编码
+   *
+   * @param startTime
+   * @param endTime
+   * @param stationCode
+   * @return
+   */
+  public Map<String, Object> findByForecastTimeBetweenAndStationCode(Long startTime, Long endTime, String stationCode) {
+    Map<String, Object> map = new HashMap<>();
+    // 查询场站信息
+    ElectricField electricFieldInfo = electricFieldService.getSingleStation(stationCode);
+    map.put("cap", electricFieldInfo.getCapacity());
+    // 查询短期预测功率
+    List<ForecastPowerShortTerm> list = forecastPowerShortTermRepository.findByForecastTimeBetweenAndStationCode(startTime, endTime, stationCode);
+
+    list.sort(Comparator.comparing(ForecastPowerShortTerm::getForecastTime));
+
+    long startTimeLong = startTime;
+    long endTimeLong = endTime;
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    long timeStep = 900000L;
+    if (startTimeLong % timeStep != 0) {
+      startTimeLong = startTimeLong - (startTimeLong % timeStep) + timeStep;
+    }
+    List<Float> datas = new ArrayList<>();
+    List<String> times = new ArrayList<>();
+
+    for (long i = startTimeLong; i < endTimeLong; i = i + timeStep) {
+      long finalI = i;
+      List<ForecastPowerShortTerm> p = list.stream().filter(t -> t.getForecastTime() == finalI).collect(Collectors.toList());
+      if (p != null && p.size() > 0) {
+        datas.add(p.get(0).getFpValue().floatValue());
+      } else {
+        datas.add(null);
+      }
+      String timeFormat = sdf.format(new Date(i));
+      times.add(timeFormat);
+    }
+    map.put("times", times);
+    map.put("datas", datas);
+    return map;
+  }
+
+  /**
+   * 根据场站编码和时间分页查询
+   *
+   * @param startTime
+   * @param endTime
+   * @param stationCode
+   * @param page
+   * @param size
+   * @param sortOrder
+   * @return
+   */
+  public Map<String, Object> findByTimeBetweenAndNoForPaging(Long startTime, Long endTime, String stationCode, Integer page, Integer size, String sortOrder) {
+    Map<String, Object> map = new HashMap<>();
+    Sort sort = Sort.by(Sort.Direction.DESC, "forecastTime");
+    if (sortOrder.contains("asc")) {
+      sort = Sort.by(Sort.Direction.ASC, "forecastTime");
+    }
+    Specification<ForecastPowerShortTerm> specification = this.specificationFindByTimeAndNo(startTime, endTime, stationCode);
+    Pageable pageable = PageRequest.of(page - 1, size, sort);
+    Page forecastPowerShortTerms = forecastPowerShortTermRepository.findAll(specification, pageable);
+    List<ForecastPowerShortTerm> datas = forecastPowerShortTerms.getContent();
+    map.put("content", datas);
+    map.put("count", forecastPowerShortTerms.getTotalElements());
+    return map;
+  }
+
+  /**
+   * 根据时间和编号 分页查询条件 yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 过滤条件
+   */
+  Specification<ForecastPowerShortTerm> specificationFindByTimeAndNo(final Long startTime, final Long endTime, String stationCode) {
+    return (Specification<ForecastPowerShortTerm>) (root, criteriaQuery, cb) -> {
+      List<Predicate> predicates = new ArrayList<>();
+      if (startTime != null) {
+        //大于或等于传入时间
+        predicates.add(cb.greaterThanOrEqualTo(root.get("forecastTime").as(Long.class), startTime));
+      }
+      if (endTime != null) {
+        //小于传入时间
+        predicates.add(cb.lessThan(root.get("forecastTime").as(Long.class), endTime));
+      }
+      predicates.add(cb.equal(root.get("stationCode").as(String.class), stationCode));
+      //添加排序的功能
+      return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+
+    };
+  }
 }

+ 488 - 152
ipfcst-console/src/main/java/com/jiayue/ipfcst/console/service/NwpService.java

@@ -3,7 +3,7 @@ package com.jiayue.ipfcst.console.service;
 
 import com.jiayue.ipfcst.common.core.util.CommonUtil;
 import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
-import com.jiayue.ipfcst.common.data.constant.enums.AlarmTypeEnum;
+import com.jiayue.ipfcst.common.data.entity.ElectricField;
 import com.jiayue.ipfcst.common.data.entity.Nwp;
 import com.jiayue.ipfcst.common.data.entity.NwpHis;
 import com.jiayue.ipfcst.common.data.repository.NwpHisRepository;
@@ -14,11 +14,18 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.time.DateFormatUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.persistence.criteria.Predicate;
 import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -26,169 +33,498 @@ import java.util.stream.Collectors;
 @Slf4j
 public class NwpService extends BaseService {
 
-    @Autowired
-    NwpRepository nwpRepository;
-    @Autowired
-    NwpHisRepository nwpHisRepository;
+  @Autowired
+  NwpRepository nwpRepository;
+  @Autowired
+  NwpHisRepository nwpHisRepository;
+  @Autowired
+  ElectricFieldService electricFieldService;
 
+  /**
+   * 保存全部
+   *
+   * @param listNwp
+   */
+  public void saveAll(List<Nwp> listNwp) {
+    nwpRepository.saveAll(listNwp);
+  }
+
+  /**
+   * 根据时间段删除数据
+   *
+   * @param startTime
+   * @param endTime
+   * @param listNwp
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public void deleteBetweenAndPreTime(Long startTime, Long endTime, List<Nwp> listNwp, String stationCode) {
+    nwpRepository.deleteByPreTimeBetweenAndStationCode(startTime, endTime, stationCode);
+    nwpRepository.saveAll(listNwp);
+  }
+
+  /**
+   * 查询NWP数据,当查询结果不足时,需要本地化生成NWP数据并保存到数据库中,用于NWP数据上报时使用
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return NWP数据结果集
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public List<Nwp> getNwpData(@NotNull final Long startTime, @NotNull final Long endTime) {
+    log.info("开始获取NWP数据" + DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss") + " 至 " + DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));
+    // 查询NWP数据
+    List<Nwp> nwpDataList = this.nwpRepository.findByPreTimeBetween(startTime, endTime);
+    nwpDataList.sort(Comparator.comparing(Nwp::getPreTime));// 按预测时间升序
+    log.info("查询现有NWP数据记录数:" + nwpDataList.size());
+    // 判断查询结果是否满足查询所需
+    Long momentTime = 15 * 60 * 1000L; // 15分钟一个时刻
+    Integer moments = Math.toIntExact((endTime - startTime) / momentTime + 1);
+    log.info("获取所需记录数:" + moments);
+    if (moments > nwpDataList.size()) {
+      // 如果查询结果少于所需预测数,则进行本地化计算,补齐预测记录
+      Map<Long, List<Nwp>> nwpDataMap = nwpDataList.stream().collect(Collectors.groupingBy(Nwp::getPreTime));
+      // 如果查询结果少于所需预测数,则进行本地化计算,补齐预测记录
+      List<Nwp> addNwpDataList = new ArrayList<>();
+      for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + momentTime) {
+        if (nwpDataMap.get(tempTime) == null) {
+          // 缺失时间点
+          List<Nwp> _nwpDataList = this.generateNwpData(tempTime);
+          addNwpDataList.addAll(_nwpDataList);
+        }
+      }
+
+      if (!addNwpDataList.isEmpty()) {
+        this.nwpRepository.saveAll(addNwpDataList);
+        // 将补齐的NWP数据追加到查询结果集中
+        nwpDataList.addAll(addNwpDataList);
+        // 进行告警
+        String errorInfo = "NWP数据不足";
+        log.error(errorInfo);
+        // 进行告警
+        String name = "NWP数据不足";
+        String describe = "";
+        String solution = "请检查NWP数据下载软件";
+        //super.saveSysAlarm(AlarmTypeEnum.E1, name, describe, errorInfo, solution);
+      }
 
-    /**
-     * 保存全部
-     *
-     * @param listNwp
-     */
-    public void saveAll(List<Nwp> listNwp) {
-        nwpRepository.saveAll(listNwp);
     }
+    // 处理NWP历史数据记录
+    List<NwpHis> nwpDataHiss = new ArrayList<>();
+    NwpHis nwpHis;
+    Long systemTime = new Date().getTime();
 
-    /**
-     * 根据时间段删除数据
-     *
-     * @param startTime
-     * @param endTime
-     * @param listNwp
-     */
-    @Transactional(propagation = Propagation.REQUIRED)
-    public void deleteBetweenAndPreTime(Long startTime, Long endTime, List<Nwp> listNwp,String stationCode) {
-        nwpRepository.deleteByPreTimeBetweenAndStationCode(startTime, endTime,stationCode);
-        nwpRepository.saveAll(listNwp);
+    for (Nwp nwp : nwpDataList) {
+      nwpHis = new NwpHis();
+      BeanUtils.copyProperties(nwp, nwpHis);
+      // 设置提前几天预测
+      nwpHis.setForecastHowLongAgo(DateMomentUtil.getDaysBetweenTwoDate(systemTime, nwpHis.getPreTime()));
+      nwpDataHiss.add(nwpHis);
     }
+    // 按预测时间升序
+    nwpDataHiss.sort(Comparator.comparing(NwpHis::getPreTime));
+    // 删除当日生成的短期历史记录
+    this.nwpHisRepository.deleteToday(startTime, endTime);
+    // 保存NWP历史记录
+    this.nwpHisRepository.saveAll(nwpDataHiss);
+    return nwpDataList;
+  }
 
-    /**
-     * 查询NWP数据,当查询结果不足时,需要本地化生成NWP数据并保存到数据库中,用于NWP数据上报时使用
-     *
-     * @param startTime 开始时间
-     * @param endTime   结束时间
-     * @return NWP数据结果集
-     */
-    @Transactional(propagation = Propagation.REQUIRED)
-    public List<Nwp> getNwpData(@NotNull final Long startTime, @NotNull final Long endTime) {
-        log.info("开始获取NWP数据" + DateFormatUtils.format(startTime, "yyyy-MM-dd HH:mm:ss") + " 至 " + DateFormatUtils.format(endTime, "yyyy-MM-dd HH:mm:ss"));
-        // 查询NWP数据
-        List<Nwp> nwpDataList = this.nwpRepository.findByPreTimeBetween(startTime, endTime);
-        nwpDataList.sort(Comparator.comparing(Nwp::getPreTime));// 按预测时间升序
-        log.info("查询现有NWP数据记录数:" + nwpDataList.size());
-        // 判断查询结果是否满足查询所需
-        Long momentTime = 15 * 60 * 1000L; // 15分钟一个时刻
-        Integer moments = Math.toIntExact((endTime - startTime) / momentTime + 1);
-        log.info("获取所需记录数:" + moments);
-        if (moments > nwpDataList.size()) {
-            // 如果查询结果少于所需预测数,则进行本地化计算,补齐预测记录
-            Map<Long, List<Nwp>> nwpDataMap = nwpDataList.stream().collect(Collectors.groupingBy(Nwp::getPreTime));
-            // 如果查询结果少于所需预测数,则进行本地化计算,补齐预测记录
-            List<Nwp> addNwpDataList = new ArrayList<>();
-            for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + momentTime) {
-                if (nwpDataMap.get(tempTime) == null) {
-                    // 缺失时间点
-                    List<Nwp> _nwpDataList = this.generateNwpData(tempTime);
-                    addNwpDataList.addAll(_nwpDataList);
-                }
-            }
-
-            if (!addNwpDataList.isEmpty()) {
-                this.nwpRepository.saveAll(addNwpDataList);
-                // 将补齐的NWP数据追加到查询结果集中
-                nwpDataList.addAll(addNwpDataList);
-                // 进行告警
-                String errorInfo = "NWP数据不足";
-                log.error(errorInfo);
-                // 进行告警
-                String name = "NWP数据不足";
-                String describe = "";
-                String solution = "请检查NWP数据下载软件";
-                //super.saveSysAlarm(AlarmTypeEnum.E1, name, describe, errorInfo, solution);
-            }
+  /**
+   * 生成NWP数据,NWP数据为云下载数据,这里不进行覆盖更新,只针对NWP数据不足时补充
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  public void buildNwpData(@NotNull final Long startTime, @NotNull final Long endTime) {
+    this.getNwpData(startTime, endTime);
+  }
 
-        }
-        // 处理NWP历史数据记录
-        List<NwpHis> nwpDataHiss = new ArrayList<>();
-        NwpHis nwpHis;
-        Long systemTime = new Date().getTime();
-
-        for (Nwp nwp : nwpDataList) {
-            nwpHis = new NwpHis();
-            BeanUtils.copyProperties(nwp, nwpHis);
-            // 设置提前几天预测
-            nwpHis.setForecastHowLongAgo(DateMomentUtil.getDaysBetweenTwoDate(systemTime, nwpHis.getPreTime()));
-            nwpDataHiss.add(nwpHis);
-        }
-        // 按预测时间升序
-        nwpDataHiss.sort(Comparator.comparing(NwpHis::getPreTime));
-        // 删除当日生成的短期历史记录
-        this.nwpHisRepository.deleteToday(startTime, endTime);
-        // 保存NWP历史记录
-        this.nwpHisRepository.saveAll(nwpDataHiss);
-        return nwpDataList;
+  /**
+   * 生成NWP数据
+   *
+   * @return nwp数据集
+   */
+  @Transactional(propagation = Propagation.REQUIRED)
+  private List<Nwp> generateNwpData(@NotNull final Long tempTime) {
+
+    List<Nwp> nwpDataList;
+
+    // 使用历史NWP数据生成NWP数据
+    List<Nwp> result = new ArrayList<>();
+    // 查询前一天同时刻NWP数据
+    nwpDataList = this.nwpRepository.findByPreTimeBetween(tempTime - 24 * 60 * 60 * 1000L, tempTime - 24 * 50 * 60 * 1000L);
+    if (nwpDataList.size() > 0) {
+      Nwp nwp = new Nwp();
+      BeanUtils.copyProperties(nwpDataList.get(0), nwp, "id");
+      nwp.setPreTime(tempTime);
+      nwp.setPreDate(DateFormatUtils.format(tempTime, "yyyy-MM-dd"));
+      result.add(nwp);
+    } else {// 如果未查询到前一天数据,则随机生成NWP数据
+      result.add(this.createNwpData(tempTime));
     }
+    return result;
+  }
+
+  private Nwp createNwpData(Long preTime) {
+    Long systemTime = System.currentTimeMillis();
+    Nwp nwpData = new Nwp();
+    nwpData.setFarmId("1");
+    nwpData.setScDate(DateFormatUtils.format(systemTime, "yyyy-MM-dd"));
+    nwpData.setScTime(DateFormatUtils.format(systemTime, "HH:mm:ss"));
+    nwpData.setPreTime(preTime);
+    nwpData.setPreDate(DateFormatUtils.format(preTime, "yyyy-MM-dd"));
+    nwpData.setPressure(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setT(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setRh(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setSenf(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setSwr(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setLwr(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+
+    nwpData.setWd10(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWd30(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWd50(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWd70(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWd80(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWd90(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWd100(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWd170(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWs10(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWs30(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWs50(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWs70(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWs80(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWs90(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWs100(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    nwpData.setWs170(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2, BigDecimal.ROUND_UP));
+    return nwpData;
+  }
+
 
-    /**
-     * 生成NWP数据,NWP数据为云下载数据,这里不进行覆盖更新,只针对NWP数据不足时补充
-     *
-     * @param startTime 开始时间
-     * @param endTime   结束时间
-     */
-    @Transactional(propagation = Propagation.REQUIRED)
-    public void buildNwpData(@NotNull final Long startTime, @NotNull final Long endTime) {
-        this.getNwpData(startTime, endTime);
+  /**
+   * 按时间查询实时NWP yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 结果集
+   */
+  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
+  public Map<String, Object> findByForecastTimeBetween(Long startTime, Long endTime, String stationCode) {
+
+    Map<String, Object> map = new HashMap<>();
+    List<Nwp> checkList = new ArrayList<>();
+    Map<String, Object> datas = new LinkedHashMap<>();
+    List<Nwp> list = nwpRepository.findByPreTimeBetweenAndStationCode(startTime, endTime, stationCode);
+    list.sort(Comparator.comparing(Nwp::getPreTime));
+
+    long startTimeLong = startTime;
+    long endTimeLong = endTime;
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    long timeStep = 900000L;
+    if (startTimeLong % timeStep != 0) {
+      startTimeLong = startTimeLong - (startTimeLong % timeStep);
     }
+    List<String> times = new ArrayList<>();
 
-    /**
-     * 生成NWP数据
-     *
-     * @return nwp数据集
-     */
-    @Transactional(propagation = Propagation.REQUIRED)
-    private List<Nwp> generateNwpData(@NotNull final Long tempTime) {
-
-        List<Nwp> nwpDataList;
-
-        // 使用历史NWP数据生成NWP数据
-        List<Nwp> result = new ArrayList<>();
-        // 查询前一天同时刻NWP数据
-        nwpDataList = this.nwpRepository.findByPreTimeBetween(tempTime - 24 * 60 * 60 * 1000L, tempTime - 24 * 50 * 60 * 1000L);
-        if (nwpDataList.size() > 0) {
-            Nwp nwp = new Nwp();
-            BeanUtils.copyProperties(nwpDataList.get(0), nwp, "id");
-            nwp.setPreTime(tempTime);
-            nwp.setPreDate(DateFormatUtils.format(tempTime, "yyyy-MM-dd"));
-            result.add(nwp);
-        } else {// 如果未查询到前一天数据,则随机生成NWP数据
-            result.add(this.createNwpData(tempTime));
-        }
-        return result;
+    for (long i = startTimeLong; i < endTimeLong; i = i + timeStep) {
+      long finalI = i;
+      List<Nwp> p = list.stream().filter(t -> t.getPreTime() == finalI).collect(Collectors.toList());
+      if (p != null && p.size() > 0) {
+        checkList.add(p.get(0));
+      } else {
+        checkList.add(new Nwp());
+      }
+      String timeFormat = sdf.format(new Date(i));
+      times.add(timeFormat);
     }
+    defaultReplace(checkList);//对集合进行 -99替换null操作,主要用于图标展示空值
+    ElectricField electricFieldInfo = electricFieldService.getSingleStation(stationCode);
 
-    private Nwp createNwpData(Long preTime) {
-        Long systemTime = System.currentTimeMillis();
-        Nwp nwpData = new Nwp();
-        nwpData.setFarmId("1");
-        nwpData.setScDate(DateFormatUtils.format(systemTime, "yyyy-MM-dd"));
-        nwpData.setScTime(DateFormatUtils.format(systemTime, "HH:mm:ss"));
-        nwpData.setPreTime(preTime);
-        nwpData.setPreDate(DateFormatUtils.format(preTime, "yyyy-MM-dd"));
-        nwpData.setPressure(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setT(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setRh(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setSenf(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setSwr(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setLwr(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-
-        nwpData.setWd10(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWd30(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWd50(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWd70(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWd80(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWd90(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWd100(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWd170(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWs10(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWs30(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWs50(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWs70(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWs80(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWs90(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWs100(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        nwpData.setWs170(new BigDecimal(CommonUtil.getRandom(1, 5000) / 10.0).setScale(2,BigDecimal.ROUND_UP));
-        return nwpData;
+    if (electricFieldInfo.getElectricFieldTypeEnum().getCode() == 1) {
+      List<BigDecimal> swrCollect = checkList.stream().map(Nwp::getSwr).collect(Collectors.toList());
+      List<BigDecimal> diffuseRadiationCollect = checkList.stream().map(Nwp::getDiffuseRadiation).collect(Collectors.toList());
+      List<BigDecimal> directRadiationCollect = checkList.stream().map(Nwp::getDirectRadiation).collect(Collectors.toList());
+      datas.put("swr", swrCollect);
+      datas.put("diffuseRadiation", diffuseRadiationCollect);
+      datas.put("directRadiation", directRadiationCollect);
+      map.put("stationType", "1");
+    } else {
+      List<BigDecimal> ws10Collect = checkList.stream().map(Nwp::getWs10).collect(Collectors.toList());
+      List<BigDecimal> ws30Collect = checkList.stream().map(Nwp::getWs30).collect(Collectors.toList());
+      List<BigDecimal> ws50Collect = checkList.stream().map(Nwp::getWs50).collect(Collectors.toList());
+      List<BigDecimal> ws70Collect = checkList.stream().map(Nwp::getWs70).collect(Collectors.toList());
+      List<BigDecimal> ws80Collect = checkList.stream().map(Nwp::getWs80).collect(Collectors.toList());
+      List<BigDecimal> ws90Collect = checkList.stream().map(Nwp::getWs90).collect(Collectors.toList());
+      List<BigDecimal> ws100Collect = checkList.stream().map(Nwp::getWs100).collect(Collectors.toList());
+      List<BigDecimal> ws170Collect = checkList.stream().map(Nwp::getWs170).collect(Collectors.toList());
+      datas.put("ws10", ws10Collect);
+      datas.put("ws30", ws30Collect);
+      datas.put("ws50", ws50Collect);
+      datas.put("ws70", ws70Collect);
+      datas.put("ws80", ws80Collect);
+      datas.put("ws90", ws90Collect);
+      datas.put("ws100", ws100Collect);
+      datas.put("ws170", ws170Collect);
+      Map<String, String> map1 = new HashMap<>();
+      map1.put("ws10", "10米风速");
+      map1.put("ws30", "30米风速");
+      map1.put("ws50", "50米风速");
+      map1.put("ws70", "70米风速");
+      map1.put("ws80", "80米风速");
+      map1.put("ws90", "90米风速");
+      map1.put("ws100", "100米风速");
+      map1.put("ws170", "170米风速");
+      map.put("cName", map1);
+      map.put("stationType", "0");
     }
+
+    map.put("times", times);
+    map.put("datas", datas);
+    return map;
+  }
+
+  /**
+   * 对集合进行 -99替换null操作,主要用于图标展示空值
+   *
+   * @param datas 需要替换集合
+   */
+  public void defaultReplace(List<Nwp> datas) {
+    BigDecimal nullBig = new BigDecimal(-99);
+    for (Nwp i : datas) {
+
+
+      if (i.getT().compareTo(nullBig) == 0) {
+        i.setT(null);
+      }
+      if (i.getRh().compareTo(nullBig) == 0) {
+        i.setRh(null);
+      }
+      if (i.getPressure().compareTo(nullBig) == 0) {
+        i.setPressure(null);
+      }
+      if (i.getSwr().compareTo(nullBig) == 0) {
+        i.setSwr(null);
+      }
+      if (i.getDirectRadiation().compareTo(nullBig) == 0) {
+        i.setDirectRadiation(null);
+      }
+      if (i.getDiffuseRadiation().compareTo(nullBig) == 0) {
+        i.setDiffuseRadiation(null);
+      }
+      if (i.getSenf().compareTo(nullBig) == 0) {
+        i.setSenf(null);
+      }
+      if (i.getWs10().compareTo(nullBig) == 0) {
+        i.setWs10(null);
+      }
+      if (i.getWs30().compareTo(nullBig) == 0) {
+        i.setWs30(null);
+      }
+      if (i.getWs50().compareTo(nullBig) == 0) {
+        i.setWs50(null);
+      }
+      if (i.getWs70().compareTo(nullBig) == 0) {
+        i.setWs70(null);
+      }
+      if (i.getWs80().compareTo(nullBig) == 0) {
+        i.setWs80(null);
+      }
+      if (i.getWs90().compareTo(nullBig) == 0) {
+        i.setWs90(null);
+      }
+      if (i.getWs100().compareTo(nullBig) == 0) {
+        i.setWs100(null);
+      }
+      if (i.getWs170().compareTo(nullBig) == 0) {
+        i.setWs170(null);
+      }
+      if (i.getWd10().compareTo(nullBig) == 0) {
+        i.setWd10(null);
+      }
+      if (i.getWd30().compareTo(nullBig) == 0) {
+        i.setWd30(null);
+      }
+      if (i.getWd50().compareTo(nullBig) == 0) {
+        i.setWd50(null);
+      }
+      if (i.getWd70().compareTo(nullBig) == 0) {
+        i.setWd70(null);
+      }
+      if (i.getWd80().compareTo(nullBig) == 0) {
+        i.setWd80(null);
+      }
+      if (i.getWd90().compareTo(nullBig) == 0) {
+        i.setWd90(null);
+      }
+      if (i.getWd100().compareTo(nullBig) == 0) {
+        i.setWd100(null);
+      }
+      if (i.getWd170().compareTo(nullBig) == 0) {
+        i.setWd170(null);
+      }
+
+    }
+
+  }
+
+  /**
+   * 根据时间和编号 分页查询条件 yh
+   *
+   * @param startTime 开始时间
+   * @param endTime   结束时间
+   * @return 过滤条件
+   */
+  public Specification<Nwp> specificationFindByTimeAndNo(final Long startTime, final Long endTime, String stationCode) {
+    return (Specification<Nwp>) (root, criteriaQuery, cb) -> {
+      List<Predicate> predicates = new ArrayList<>();
+      if (startTime != null) {
+        //大于或等于传入时间
+        predicates.add(cb.greaterThanOrEqualTo(root.get("preTime").as(Long.class), startTime));
+      }
+      if (endTime != null) {
+        //小于传入时间
+        predicates.add(cb.lessThan(root.get("preTime").as(Long.class), endTime));
+      }
+      predicates.add(cb.equal(root.get("stationCode").as(String.class), stationCode));
+      //添加排序的功能
+      return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+
+    };
+  }
+
+  public Map<String, Object> findByTimeBetweenAndNoForPaging(Long startTime, Long endTime, String stationCode, Integer page, Integer size, String sortOrder) {
+    Map<String, Object> map = new HashMap<>();
+    Sort sort = Sort.by(Sort.Direction.DESC, "preTime");
+    if (sortOrder.contains("asc")) {
+      sort = Sort.by(Sort.Direction.ASC, "preTime");
+    }
+    Specification<Nwp> specification = specificationFindByTimeAndNo(startTime, endTime, stationCode);
+    Pageable pageable = PageRequest.of(page - 1, size, sort);
+    Page nwps = nwpRepository.findAll(specification, pageable);
+    List<Nwp> datas = new ArrayList<>();
+    datas = nwps.getContent();
+    this.defaultReplace(datas);
+    map.put("content", datas);
+    map.put("count", nwps.getTotalElements());
+    Map<String, String> map1 = new HashMap<>();
+    map1.put("preTime", "预测时间");
+    map1.put("scTime", "生成时间");
+    map1.put("pressure", "气压");
+    map1.put("t", "温度");
+    map1.put("rh", "湿度");
+    map1.put("swr", "总辐射");
+    map1.put("directRadiation", "直辐射");
+    map1.put("diffuseRadiation", "散辐射");
+    map1.put("senf", "热感通量");
+    map1.put("ws10", "10米风速");
+    map1.put("ws30", "30米风速");
+    map1.put("ws50", "50米风速");
+    map1.put("ws70", "70米风速");
+    map1.put("ws80", "80米风速");
+    map1.put("ws90", "90米风速");
+    map1.put("ws100", "100米风速");
+    map1.put("ws170", "170米风速");
+    map1.put("wd10", "10米风向");
+    map1.put("wd30", "30米风向");
+    map1.put("wd50", "50米风向");
+    map1.put("wd70", "70米风向");
+    map1.put("wd80", "80米风向");
+    map1.put("wd90", "90米风向");
+    map1.put("wd100", "100米风向");
+    map1.put("wd170", "170米风向");
+
+    map.put("cName", map1);
+    //################  统计  ##################
+    int days = DateMomentUtil.getDaysBetweenTwoDate(startTime, endTime + 1000);
+    List<Nwp> dataList = new ArrayList<>();
+    for (int i = 0; i < days; i++) {
+      Nwp nwp = new Nwp();
+      List<Nwp> nwpList = nwpRepository.findByPreTimeBetween(startTime + ((long) i * 60 * 60 * 24 * 1000), startTime + ((long) (i + 1) * 60 * 60 * 24 * 1000 - 1000));
+      BigDecimal t = new BigDecimal(0);
+      BigDecimal rh = new BigDecimal(0);
+      BigDecimal pressure = new BigDecimal(0);
+      BigDecimal swr = new BigDecimal(0);
+      BigDecimal lwr = new BigDecimal(0);
+      BigDecimal directRadiation = new BigDecimal(0);
+      BigDecimal diffuseRadiation = new BigDecimal(0);
+      BigDecimal senf = new BigDecimal(0);
+      BigDecimal ws10 = new BigDecimal(0);
+      BigDecimal ws30 = new BigDecimal(0);
+      BigDecimal ws50 = new BigDecimal(0);
+      BigDecimal ws70 = new BigDecimal(0);
+      BigDecimal ws80 = new BigDecimal(0);
+      BigDecimal ws90 = new BigDecimal(0);
+      BigDecimal ws100 = new BigDecimal(0);
+      BigDecimal ws170 = new BigDecimal(0);
+      BigDecimal wd10 = new BigDecimal(0);
+      BigDecimal wd30 = new BigDecimal(0);
+      BigDecimal wd50 = new BigDecimal(0);
+      BigDecimal wd70 = new BigDecimal(0);
+      BigDecimal wd80 = new BigDecimal(0);
+      BigDecimal wd90 = new BigDecimal(0);
+      BigDecimal wd100 = new BigDecimal(0);
+      BigDecimal wd170 = new BigDecimal(0);
+      for (int j = 0; j < nwpList.size(); j++) {
+        t = t.add(nwpList.get(j).getT() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getT());
+        rh = rh.add(nwpList.get(j).getRh() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getRh());
+        pressure = pressure.add(nwpList.get(j).getPressure() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getPressure());
+        swr = swr.add(nwpList.get(j).getSwr() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getSwr());
+        lwr = lwr.add(nwpList.get(j).getLwr() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getLwr());
+        directRadiation = directRadiation.add(nwpList.get(j).getDirectRadiation() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getDirectRadiation());
+        diffuseRadiation = diffuseRadiation.add(nwpList.get(j).getDiffuseRadiation() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getDiffuseRadiation());
+        senf = senf.add(nwpList.get(j).getSenf() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getSenf());
+        ws10 = ws10.add(nwpList.get(j).getWs10() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWs10());
+        ws30 = ws30.add(nwpList.get(j).getWs30() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWs30());
+        ws50 = ws50.add(nwpList.get(j).getWs50() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWs50());
+        ws70 = ws70.add(nwpList.get(j).getWs70() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWs70());
+        ws80 = ws80.add(nwpList.get(j).getWs80() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWs80());
+        ws90 = ws90.add(nwpList.get(j).getWs90() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWs90());
+        ws100 = ws100.add(nwpList.get(j).getWs100() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWs100());
+        ws170 = ws170.add(nwpList.get(j).getWs170() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWs170());
+        wd10 = wd10.add(nwpList.get(j).getWd10() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWd10());
+        wd30 = wd30.add(nwpList.get(j).getWd30() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWd30());
+        wd50 = wd50.add(nwpList.get(j).getWd50() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWd50());
+        wd70 = wd70.add(nwpList.get(j).getWd70() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWd70());
+        wd80 = wd80.add(nwpList.get(j).getWd80() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWd80());
+        wd90 = wd90.add(nwpList.get(j).getWd90() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWd90());
+        wd100 = wd100.add(nwpList.get(j).getWd100() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWd100());
+        wd170 = wd170.add(nwpList.get(j).getWd170() == null ? BigDecimal.valueOf(0) : nwpList.get(j).getWd170());
+      }
+      if (nwpList.size() > 0) {
+        nwp.setScTime(nwpList.get(0).getScTime());
+        nwp.setScDate(nwpList.get(0).getScDate());
+        nwp.setPreTime(nwpList.get(0).getPreTime());
+        nwp.setPreDate(nwpList.get(0).getPreDate());
+        nwp.setFarmId(nwpList.get(0).getFarmId());
+        nwp.setT(t.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : t.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setRh(rh.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : rh.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setPressure(pressure.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : pressure.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setSwr(swr.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : swr.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setLwr(lwr.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : lwr.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setDirectRadiation(directRadiation.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : directRadiation.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setDiffuseRadiation(diffuseRadiation.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : diffuseRadiation.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setSenf(senf.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : senf.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWs10(ws10.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : ws10.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWs30(ws30.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : ws30.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWs50(ws50.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : ws50.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWs70(ws70.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : ws70.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWs80(ws80.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : ws80.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWs90(ws90.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : ws90.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWs100(ws100.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : ws100.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWs170(ws170.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : ws170.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWd10(wd10.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : wd10.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWd30(wd30.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : wd30.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWd50(wd50.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : wd50.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWd70(wd70.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : wd70.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWd80(wd80.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : wd80.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWd90(wd90.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : wd90.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWd100(wd100.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : wd100.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        nwp.setWd170(wd170.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0d ? new BigDecimal(0) : wd170.divide(BigDecimal.valueOf(nwpList.size()), 2, BigDecimal.ROUND_HALF_UP));
+        dataList.add(nwp);
+      }
+    }
+
+    map.put("statistics", dataList);
+    return map;
+  }
 }