Przeglądaj źródła

feat: 实时模拟

hum 1 rok temu
rodzic
commit
2d8b9e0d29

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TaskNoticeMapper.java

@@ -29,7 +29,7 @@ public interface TaskNoticeMapper {
      * @param pageable         分页对象
      * @return 对象列表
      */
-    Page<TaskNotice> queryAllByLimit(Long siteId, Page page);
+    Page<TaskNotice> queryAllByLimit(@Param("siteId") Long siteId, Page page);
 
     /**
      * 统计总行数

+ 40 - 0
ruoyi-ui/src/api/analysis/achievement.js

@@ -15,3 +15,43 @@ export function listWaterLevel(query) {
     data: query
   })
 }
+
+export function listMeasureLine(siteId) {
+  return request({
+    url: '/reportData/getMeasureLine',
+    method: 'get',
+    params: { siteId },
+  })
+}
+
+export function getCarInfo(siteId) {
+  return request({
+    url: '/reportData/carInfo',
+    method: 'get',
+    params: { siteId },
+  })
+}
+
+export function getCarLocation(siteId) {
+  return request({
+    url: '/reportData/carLocation',
+    method: 'get',
+    params: { siteId },
+  })
+}
+
+export function getSiteRealTime(siteId) {
+  return request({
+    url: '/reportData/siteRealTime',
+    method: 'get',
+    params: { siteId },
+  })
+}
+
+export function getTaskNotice(siteId, taskId) {
+  return request({
+    url: '/reportData/taskNotice',
+    method: 'get',
+    params: { siteId, taskId, page: 1, size: 10000 },
+  })
+}

+ 1 - 0
ruoyi-ui/src/assets/images/bar.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="18" height="271" viewBox="0 0 18 271"><g><g><rect x="0" y="8" width="18" height="263" rx="0" fill="#A6B7C7" fill-opacity="1"/></g><g><ellipse cx="9" cy="6" rx="9" ry="6" fill="#A6B7C7" fill-opacity="1"/><ellipse cx="9" cy="6" rx="8" ry="5" fill-opacity="0" stroke-opacity="1" stroke="#D6EBFF" fill="none" stroke-width="2"/></g></g></svg>

+ 1 - 1
ruoyi-ui/src/views/analysis/task/index.vue

@@ -147,7 +147,7 @@ export default {
       );
     },
     goRealTime(task) {
-      this.$router.push(`/analysis/task/realtime/${task.taskid}`);
+      this.$router.push(`/analysis/task/realtime/${task.siteId}/${task.taskid}`);
     },
     handleUpdate(site) {
       this.$router.push(`/site/site/edit/${site.siteId}`);

+ 37 - 5
ruoyi-ui/src/views/analysis/task/realtime/car.vue

@@ -5,29 +5,61 @@
       <div class="item">
         <div class="item-icon"></div>
         <div class="item-label">电压:</div>
-        <div class="item-value">12V</div>
+        <div class="item-value">{{carInfo.voltage || '-'}}V</div>
       </div>
       <div class="item">
         <div class="item-icon"></div>
         <div class="item-label">电流:</div>
-        <div class="item-value">3A</div>
+        <div class="item-value">{{carInfo.current || '-'}}A</div>
       </div>
       <div class="item">
         <div class="item-icon"></div>
         <div class="item-label">电量:</div>
-        <div class="item-value">95%</div>
+        <div class="item-value">{{carInfo.eq || '-'}}%</div>
       </div>
       <div class="item">
         <div class="item-icon"></div>
-        <div class="item-label">新号强度:</div>
-        <div class="item-value">21</div>
+        <div class="item-label">信号强度:</div>
+        <div class="item-value">{{carInfo.signalstrength || '-'}}</div>
+      </div>
+      <div class="item">
+        <div class="item-icon"></div>
+        <div class="item-label">温度:</div>
+        <div class="item-value">{{carInfo.temperature || '-'}}</div>
       </div>
     </div>
   </div>
 </template>
 
 <script>
+import { getCarInfo } from '@/api/analysis/achievement';
+
 export default {
+  data() {
+    return {
+      siteId: 0,
+      carInfo: {}
+    }
+  },
+  methods: {
+    loadCarInfo() {
+      getCarInfo(this.siteId).then((res) => {
+        this.carInfo = res.data || {};
+      }).finally(() => {
+        this.timer = setTimeout(() => this.loadCarInfo(), 5e3)
+      })
+    }
+  },
+  mounted() {
+    const { siteId } = this.$route.params;
+    this.siteId = siteId;
+    this.loadCarInfo()
+  },
+  beforeDestroy() {
+    if (this.timer) {
+      clearTimeout(this.timer);
+    }
+  }
 }
 </script>
 

+ 23 - 12
ruoyi-ui/src/views/analysis/task/realtime/flow.vue

@@ -6,38 +6,49 @@
 </template>
 
 <script>
+import { listMeasureLine } from '@/api/analysis/achievement'
 import * as echarts from "echarts";
 require('echarts/theme/macarons') // echarts theme
 import resize from '@/utils/resize'
 
 export default {
   mixins: [resize],
+  data() {
+    return {
+      siteId: 0,
+    }
+  },
   mounted() {
+    const { siteId } = this.$route.params;
+    this.siteId = siteId;
+    this.loadMeasureLine()
     this.$nextTick(() => {
       this.chart = echarts.init(this.$refs.chart, 'macarons');
-      this.setOptions([
-        { pn: 1, flow: 300 },
-        { pn: 2, flow: 200 },
-        { pn: 3, flow: 100 },
-        { pn: 4, flow: 400 },
-        { pn: 5, flow: 200 },
-      ])
     })
   },
   beforeDestroy() {
-    if (!this.chart) {
-      return
+    if (this.timer) {
+      clearTimeout(this.timer);
+    }
+    if (this.chart) {
+      this.chart.dispose()
+      this.chart = null
     }
-    this.chart.dispose()
-    this.chart = null
   },
   methods: {
+    loadMeasureLine() {
+      listMeasureLine(this.siteId).then((res) => {
+        this.setOptions(res.data || [])
+      }).finally(() => {
+        this.timer = setTimeout(() => this.loadMeasureLine(), 5e3)
+      })
+    },
     setOptions(chartData) {
       if (!this.chart) {
         return;
       }
       const xAxisData = chartData.map(({ pn }) => pn);
-      const seriesData = chartData.map(({ flow }) => flow);
+      const seriesData = chartData.map(({ wspeed }) => wspeed);
       const options = {
         xAxis: {
           name: '停泊点',

+ 30 - 20
ruoyi-ui/src/views/analysis/task/realtime/message.vue

@@ -2,33 +2,43 @@
   <div class="realtime-container">
     <div class="title">即时信息</div>
     <div class="info">
-      <div class="item">
-        <div class="item-value">开始测流</div>
-      </div>
-      <div class="item">
-        <div class="item-value">到达第1垂线测流点</div>
-      </div>
-      <div class="item">
-        <div class="item-value">垂线点1测流开始</div>
-      </div>
-      <div class="item">
-        <div class="item-value">垂线点1测流结束</div>
-      </div>
-      <div class="item">
-        <div class="item-value">到达第2垂线测流点</div>
-      </div>
-      <div class="item">
-        <div class="item-value">垂线点2测流开始</div>
-      </div>
-      <div class="item">
-        <div class="item-value">垂线点2测流结束</div>
+      <div class="item" v-for="item in messages">
+        <div class="item-value">{{ item.remark }}</div>
       </div>
     </div>
   </div>
 </template>
 
 <script>
+import { getTaskNotice } from '@/api/analysis/achievement';
+
 export default {
+  data() {
+    return {
+      siteId: 0,
+      messages: []
+    }
+  },
+  methods: {
+    loadTaskNotice() {
+      getTaskNotice(this.siteId, this.id).then((res) => {
+        this.messages = res.data.records || [];
+      }).finally(() => {
+        this.timer = setTimeout(() => this.loadTaskNotice(), 5e3)
+      })
+    }
+  },
+  mounted() {
+    const { siteId, id } = this.$route.params;
+    this.id = id;
+    this.siteId = siteId;
+    this.loadTaskNotice()
+  },
+  beforeDestroy() {
+    if (this.timer) {
+      clearTimeout(this.timer);
+    }
+  }
 }
 </script>
 

+ 121 - 44
ruoyi-ui/src/views/analysis/task/realtime/simulation.vue

@@ -9,6 +9,9 @@ import * as echarts from "echarts";
 require('echarts/theme/macarons') // echarts theme
 import resize from '@/utils/resize'
 import { getSiteSection } from '@/api/site/berthing'
+import { getCarLocation } from '@/api/analysis/achievement'
+import CarSvg from '@/assets/images/car.svg'
+import BarSvg from '@/assets/images/bar.svg'
 
 export default {
   mixins: [resize],
@@ -17,16 +20,22 @@ export default {
   },
   data() {
     return {
-      sections: []
+      sections: [],
+      location: 0,
     }
   },
   mounted() {
     this.loadSection();
+    this.loadCarLocation();
     this.$nextTick(() => {
       this.chart = echarts.init(this.$refs.chart, 'macarons');
     })
   },
   beforeDestroy() {
+    if (this.timer1) {
+      clearTimeout(this.timer1);
+    }
+
     if (!this.chart) {
       return
     }
@@ -34,6 +43,14 @@ export default {
     this.chart = null
   },
   methods: {
+    loadCarLocation() {
+      getCarLocation(this.siteId).then((res) => {
+        this.location = res.data?.position || 0;
+        this.setOptions();
+      }).finally(() => {
+        this.timer1 = setTimeout(() => this.loadCarLocation(), 5e3)
+      })
+    },
     loadSection() {
       getSiteSection(this.siteId).then((res) => {
         this.sections = JSON.parse(res.data.positions) || [];
@@ -47,13 +64,25 @@ export default {
       const xAxisData = this.sections.map(({ x }) => x);
       const seriesData = this.sections.map(({ y }) => y);
       const waterData = this.sections.map(() => 405);
+      const locationData = this.sections.map(() => 420);
+      const topData = this.sections.map(() => 430);
+
+      console.log(Math.min(...xAxisData), Math.max(...xAxisData))
+
       const options = {
-        xAxis: {
-          name: '起点距',
-          data: xAxisData,
-          boundaryGap: false,
-          show: false,
-        },
+        xAxis: [
+          {
+            data: xAxisData,
+            boundaryGap: false,
+            show: false,
+          },
+          {
+            type: 'value',
+            min: Math.min(...xAxisData),
+            max: Math.max(...xAxisData),
+            show: false,
+          }
+        ],
         yAxis: [
           {
             name: '高程',
@@ -70,48 +99,96 @@ export default {
           containLabel: true
         },
         tooltip: {
-          trigger: 'axis',
-          axisPointer: {
-            type: 'line'
-          },
-          formatter: function(prams) {
-            return `时间:${prams[0].name}<br/>水位:${prams[0].data}m`;
-          },
-          padding: [5, 10]
+          show: false,
         },
-        series: [{
-          name: '水位',
-          type: 'line',
-          silent: true,
-          data: waterData,
-          symbolSize: 0,
-          lineStyle: {
-            normal: {
-              width: 0
-            }
+        series: [
+          {
+            name: '水位',
+            type: 'line',
+            silent: true,
+            data: waterData,
+            symbol: 'none',
+            lineStyle: {
+              normal: {
+                width: 0
+              }
+            },
+            areaStyle: {
+              normal: {
+                color: '#adcef8',
+              }
+            },
+            z: 1,
           },
-          areaStyle: {
-            normal: {
-              color: '#adcef8',
-            }
+          {
+            name: '小车',
+            type: 'scatter',
+            data: [[this.location, 420]],
+            symbol: `image://${CarSvg}`,
+            symbolSize: [50, 30],
+            xAxisIndex: 1,
+            itemStyle: {
+              normal: {
+                color: '#ff5722',
+                shadowColor: '#ff5722',
+                shadowBlur: 100
+              }
+            },
+            silent: true,
+            z: 3
+          },
+          {
+            name: '柱子',
+            type: 'scatter',
+            data: [[40, 420]],
+            symbol: `image://${BarSvg}`,
+            symbolSize: [20, 500],
+            symbolOffset: [0, '50%'],
+            xAxisIndex: 1,
+            itemStyle: {
+              normal: {
+                color: '#ff5722',
+                shadowColor: '#ff5722',
+                shadowBlur: 100
+              }
+            },
+            silent: true,
+            z: 3
           },
-          z: 1,
-        }, {
-          name: '高程',
-          type: 'line',
-          symbol: false,
-          smooth: false,
-          data: seriesData,
-          lineStyle: {
-            color: '#FF8500',
+          {
+            name: '小车',
+            type: 'line',
+            data: topData,
+            symbol: 'none',
+            lineStyle: {
+              normal: {
+                width: 0
+              }
+            },
+            areaStyle: {
+              normal: {
+                color: 'transparent',
+              }
+            },
+            z: 0,
           },
-          areaStyle: {
-            normal: {
-              color: '#f6c27d',
-            }
+          {
+            name: '高程',
+            type: 'line',
+            symbol: false,
+            smooth: false,
+            data: seriesData,
+            lineStyle: {
+              color: '#FF8500',
+            },
+            areaStyle: {
+              normal: {
+                color: '#f6c27d',
+              }
+            },
+            z: 10,
           },
-          z: 2,
-        }]
+        ]
       };
       this.chart.setOption(options);
     },

+ 30 - 3
ruoyi-ui/src/views/analysis/task/realtime/site.vue

@@ -5,24 +5,51 @@
       <div class="item">
         <div class="item-icon"></div>
         <div class="item-label">站点名称:</div>
-        <div class="item-value">赤水(80307010)</div>
+        <div class="item-value">{{siteRealTime.siteName}}</div>
       </div>
       <div class="item">
         <div class="item-icon"></div>
         <div class="item-label">下次测流时间:</div>
-        <div class="item-value">2024-04-01</div>
+        <div class="item-value">{{ siteRealTime.nextTime || '-' }}</div>
       </div>
       <div class="item">
         <div class="item-icon"></div>
         <div class="item-label">站点状态:</div>
-        <div class="item-value">测流</div>
+        <div class="item-value">{{['空闲', '测流中'][siteRealTime.siteStatus]}}</div>
       </div>
     </div>
   </div>
 </template>
 
 <script>
+import { getSiteRealTime } from '@/api/analysis/achievement';
+
 export default {
+  data() {
+    return {
+      siteId: 0,
+      siteRealTime: {}
+    }
+  },
+  methods: {
+    loadSiteRealTime() {
+      getSiteRealTime(this.siteId).then((res) => {
+        this.siteRealTime = res.data || {};
+      }).finally(() => {
+        this.timer = setTimeout(() => this.loadSiteRealTime(), 5e3)
+      })
+    }
+  },
+  mounted() {
+    const { siteId } = this.$route.params;
+    this.siteId = siteId;
+    this.loadSiteRealTime()
+  },
+  beforeDestroy() {
+    if (this.timer) {
+      clearTimeout(this.timer);
+    }
+  }
 }
 </script>
 

+ 37 - 19
ruoyi-ui/src/views/analysis/task/realtime/water.vue

@@ -6,45 +6,63 @@
 </template>
 
 <script>
-
+import { listWaterLevel } from '@/api/analysis/achievement'
 import * as echarts from "echarts";
 require('echarts/theme/macarons') // echarts theme
 import resize from '@/utils/resize'
 
 export default {
   mixins: [resize],
+  data() {
+    return {
+      siteId: 0,
+    }
+  },
   mounted() {
+    const { siteId } = this.$route.params;
+    this.siteId = siteId;
+    this.loadWaterLevel()
     this.$nextTick(() => {
       this.chart = echarts.init(this.$refs.chart, 'macarons');
-      this.setOptions([
-        { time: '00:00', level: 207.01 },
-        { time: '00:30', level: 207.03 },
-        { time: '01:00', level: 207.11 },
-        { time: '01:30', level: 207.09 },
-        { time: '02:00', level: 207.06 },
-        { time: '02:30', level: 207.03 },
-        { time: '03:00', level: 207.01 },
-        { time: '03:30', level: 207.03 },
-        { time: '04:00', level: 207.11 },
-        { time: '04:30', level: 207.09 },
-        { time: '05:00', level: 207.06 },
-      ])
     })
   },
   beforeDestroy() {
-    if (!this.chart) {
-      return
+    if (this.timer) {
+      clearTimeout(this.timer);
+    }
+    if (this.chart) {
+      this.chart.dispose()
+      this.chart = null
     }
-    this.chart.dispose()
-    this.chart = null
   },
   methods: {
+    loadWaterLevel() {
+      const endTime = new Date()
+      const startTime = new Date()
+      startTime.setHours(0)
+      startTime.setMinutes(0)
+      startTime.setSeconds(0)
+      startTime.setMilliseconds(0)
+      const params = {
+        startTime: this.parseTime(startTime),
+        endTime: this.parseTime(endTime),
+        siteId: this.siteId,
+        type: 1,
+        page: 1,
+        size: 10000
+      }
+      listWaterLevel(params).then((res) => {
+        this.setOptions(res.data?.records || [])
+      }).finally(() => {
+        this.timer = setTimeout(() => this.loadWaterLevel(), 5e3)
+      })
+    },
     setOptions(chartData) {
       if (!this.chart) {
         return;
       }
       const xAxisData = chartData.map(({ time }) => time);
-      const seriesData = chartData.map(({ level }) => level);
+      const seriesData = chartData.map(({ avgWaterlevel }) => avgWaterlevel);
       const options = {
         xAxis: {
           name: '时间',

+ 7 - 7
waterAffairs-admin/src/main/java/com/ruoyi/web/controller/tool/ReportDataController.java

@@ -10,7 +10,7 @@ import com.ruoyi.system.service.ReportDataService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -33,40 +33,40 @@ public class ReportDataController {
     ReportDataService reportDataService;
 
     //小车位置
-    @PostMapping(value = "/carLocation")
+    @GetMapping(value = "/carLocation")
     @ApiOperation("获取小车实时位置")
     public R<CarPosition> carLocation(Long siteId)  {
         return R.ok(reportDataService.carLocation(siteId));
     }
 
     //小车信息
-    @PostMapping(value = "/carInfo")
+    @GetMapping(value = "/carInfo")
     @ApiOperation("获取小车实时信息")
     public R<HeartBeat> carInfo(Long siteId)  {
         return R.ok(reportDataService.carInfo(siteId));
     }
 
     //站点实时信息
-    @PostMapping(value = "/siteRealTime")
+    @GetMapping(value = "/siteRealTime")
     @ApiOperation("获取站点实时信息")
     public R<SiteRealTimeDTO> siteRealTime(Long siteId)  {
         return R.ok(reportDataService.siteRealTime(siteId));
     }
     //即时信息
-    @PostMapping(value = "/taskNotice")
+    @GetMapping(value = "/taskNotice")
     @ApiOperation("获取任务通知(及时消息)")
     public R<Page<TaskNotice>> taskNotice(Long siteId, Long page, Long size)  {
         return R.ok(reportDataService.taskNotice(siteId,page,size));
     }
     //当前水位
-    @PostMapping(value = "/getWaterLevel")
+    @GetMapping(value = "/getWaterLevel")
     @ApiOperation("获取实时水位")
     public R<WaterLevel> getWaterLevel(Long siteId)  {
         return R.ok(reportDataService.getWaterLevel(siteId));
     }
 
     //垂线点对应流量图
-    @PostMapping(value = "/getMeasureLine")
+    @GetMapping(value = "/getMeasureLine")
     @ApiOperation("获取垂线点对应流量图")
     public R<List<MeasureUpload>> getMeasureLine(Long siteId)  {
         return R.ok(reportDataService.getMeasureLine(siteId));