فهرست منبع

feat: 实时模拟

hum 1 سال پیش
والد
کامیت
b5e7479548

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

@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+export function listAchievements(query) {
+  return request({
+    url: '/achievement/queryAchievement',
+    method: 'post',
+    data: query
+  })
+}

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

@@ -0,0 +1,186 @@
+<template>
+  <div class="hum-page-container">
+    <div class="hum-page-title">测流任务</div>
+    <div class="hum-page-main">
+      <div class="hum-page-search">
+        <el-form :model="queryParams" size="large" ref="queryForm" label-position="top">
+          <el-row :gutter="30">
+            <el-col :span="6">
+              <el-form-item label="选择站点">
+                <el-select v-model="siteId" placeholder="请选择站点" @change="handleSiteChange">
+                  <el-option
+                    v-for="item in siteList"
+                    :key="item.siteId"
+                    :label="item.siteName"
+                    :value="item.siteId">
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item class="hum-page-search-action">
+                <el-button type="primary" @click="handleQuery">查询</el-button>
+                <el-button @click="resetQuery">重置</el-button>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+      </div>
+      <div class="hum-page-action">
+        <el-button type="primary" @click="$router.push('/site/site/add')">新增站点</el-button>
+      </div>
+      <el-table v-loading="loading" :data="list" border>
+        <el-table-column label="任务编号" prop="taskid" />
+        <el-table-column label="任务模式" prop="workmode" />
+        <el-table-column label="策略名称" prop="workmode" />
+        <el-table-column label="起测时间">
+          <template slot-scope="scope">
+            <span>{{ formatDateTime(scope.row.createTime) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="水位" prop="workmode" />
+        <el-table-column label="过水面积" prop="workmode" />
+        <el-table-column label="瞬时流量(总)" prop="workmode" />
+        <el-table-column label="当前状态">
+          <template slot-scope="scope">
+            <span class="status status-running" v-if="scope.row.status === 0">
+              <span class="status-circle"></span>
+              <span class="status-text">测流中</span>
+            </span>
+            <span class="status status-stopped" v-else-if="scope.row.status === 1">
+              <span class="status-circle"></span>
+              <span class="status-text">已终止</span>
+            </span>
+            <span class="status status-finished" v-else-if="scope.row.status === 2">
+              <span class="status-circle"></span>
+              <span class="status-text">已完成</span>
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <template v-if="scope.row.status === 0">
+              <el-button size="mini" type="text" icon="el-icon-edit" @click="goRealTime(scope.row)">实时动态</el-button>
+              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">中止</el-button>
+            </template>
+            <template v-else-if="scope.row.status === 2">
+              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">测流成果</el-button>
+              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">导出</el-button>
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination
+        v-show="total>0"
+        :total="total"
+        :page.sync="queryParams.page"
+        :limit.sync="queryParams.size"
+        @pagination="getList"
+      />
+    </div>
+  </div>
+</template>
+
+<script>
+import { listSite } from "@/api/site/site";
+import { listAchievements } from "@/api/analysis/achievement";
+
+export default {
+  data() {
+    return {
+      siteId: '',
+      siteList: [],
+      queryParams: {
+        page: 1,
+        size: 10,
+      },
+      dateRange: [],
+      siteTypeOptions: [
+        { value: 1, label: '流量站' }
+      ],
+      loading: true,
+      total: 0,
+      list: []
+    }
+  },
+  created() {
+    this.init();
+  },
+  methods: {
+    init() {
+      this.loading = true;
+      listSite({ page: 1, size: 1000 }).then(response => {
+          this.siteList = response.data.records || [];
+          if (this.siteList.length > 0) {
+            this.siteId = this.siteList[0].siteId;
+            this.getList();
+          }
+        }
+      ).catch(() => {
+        this.loading = false;
+      });
+    },
+    handleQuery() {
+      this.getList();
+    },
+    handleSiteChange(siteId) {
+      this.siteId = siteId;
+      this.getList();
+    },
+    resetQuery() {
+      this.queryParams = {
+        page: 1,
+        size: 10,
+      };
+      this.getList();
+    },
+    getList() {
+      this.loading = true;
+      const data = this.addDateRange(this.queryParams, this.dateRange);
+      data.siteId = this.siteId;
+      listAchievements(data).then(response => {
+          this.list = response.data.records;
+          this.total = response.data.total;
+          this.loading = false;
+        }
+      );
+    },
+    goRealTime(task) {
+      this.$router.push(`/analysis/task/realtime/${task.taskid}`);
+    },
+    handleUpdate(site) {
+      this.$router.push(`/site/site/edit/${site.siteId}`);
+    },
+    handleConfig(site) {
+      this.$router.push(`/site/site/config/${site.siteId}`);
+    },
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.status {
+  display: flex;
+  align-items: center;
+  &-circle {
+    width: 8px;
+    height: 8px;
+    border-radius: 50%;
+  }
+  &-text {
+    margin-left: 6px;
+    color: #54606C;
+  }
+}
+
+.status-running .status-circle {
+  background: #22C777;
+}
+.status-stopped .status-circle {
+  background: #FA3C58;
+}
+.status-finished .status-circle {
+  background: #8D99A4;
+}
+</style>

+ 54 - 0
ruoyi-ui/src/views/analysis/task/realtime.vue

@@ -0,0 +1,54 @@
+<template>
+  <div>
+    <el-row :gutter="10">
+      <el-col :span="18">
+        <Simulation />
+        <el-row :gutter="20" style="margin-top: 10px">
+          <el-col :span="8">
+            <Site />
+          </el-col>
+          <el-col :span="8">
+            <Car />
+          </el-col>
+          <el-col :span="8">
+            <Message />
+          </el-col>
+        </el-row>
+      </el-col>
+      <el-col :span="6">
+        <Movie />
+        <Flow style="margin-top: 10px" />
+        <Water style="margin-top: 10px" />
+      </el-col>
+    </el-row>
+    <Report style="margin-top: 10px" />
+  </div>
+</template>
+
+<script>
+import Simulation from './realtime/simulation'
+import Site from './realtime/site'
+import Car from './realtime/car'
+import Message from './realtime/message'
+import Movie from './realtime/movie'
+import Flow from './realtime/flow'
+import Water from './realtime/water'
+import Report from './realtime/report'
+
+export default {
+  components: {
+    Simulation,
+    Site,
+    Car,
+    Message,
+    Movie,
+    Flow,
+    Water,
+    Report,
+  },
+}
+</script>
+
+<style scoped>
+
+</style>

+ 72 - 0
ruoyi-ui/src/views/analysis/task/realtime/car.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="realtime-container">
+    <div class="title">小车状态</div>
+    <div class="info">
+      <div class="item">
+        <div class="item-icon"></div>
+        <div class="item-label">电压:</div>
+        <div class="item-value">12V</div>
+      </div>
+      <div class="item">
+        <div class="item-icon"></div>
+        <div class="item-label">电流:</div>
+        <div class="item-value">3A</div>
+      </div>
+      <div class="item">
+        <div class="item-icon"></div>
+        <div class="item-label">电量:</div>
+        <div class="item-value">95%</div>
+      </div>
+      <div class="item">
+        <div class="item-icon"></div>
+        <div class="item-label">新号强度:</div>
+        <div class="item-value">21</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+}
+</script>
+
+<style scoped>
+.realtime-container {
+  background: #fff;
+  height: 190px;
+  border-radius: 4px;
+  padding: 10px 20px;
+}
+.title {
+  font-size: 18px;
+  line-height: 26px;
+  font-weight: 600;
+  color: #1D2738;
+}
+.info {
+  padding-top: 5px;
+  font-size: 14px;
+  line-height: 18px;
+  color: #54606C;
+}
+.item {
+  display: flex;
+  align-items: center;
+  padding: 5px 0;
+}
+.item-icon {
+  width: 6px;
+  height: 6px;
+  border-radius: 50%;
+  background: #55DA74;
+  margin-right: 8px;
+}
+.item-label {
+  width: 70px;
+  color: #54606C;
+}
+.item-value {
+  color: #1D2738;
+}
+</style>

+ 114 - 0
ruoyi-ui/src/views/analysis/task/realtime/flow.vue

@@ -0,0 +1,114 @@
+<template>
+  <div class="realtime-container">
+    <div class="title">垂线点对应的流量图</div>
+    <div ref="chart" class="chart" :style="{height: '140px', width: '100%'}" />
+  </div>
+</template>
+
+<script>
+import * as echarts from "echarts";
+require('echarts/theme/macarons') // echarts theme
+import resize from '@/utils/resize'
+
+export default {
+  mixins: [resize],
+  mounted() {
+    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
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    setOptions(chartData) {
+      if (!this.chart) {
+        return;
+      }
+      const xAxisData = chartData.map(({ pn }) => pn);
+      const seriesData = chartData.map(({ flow }) => flow);
+      const options = {
+        xAxis: {
+          name: '停泊点',
+          data: xAxisData,
+          type: 'category',
+          axisLabel: {
+            color: '#54606C'
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#E4E4E4'
+            }
+          }
+        },
+        yAxis: [
+          {
+            name: '流量(m³/h)',
+            axisLine: {
+              show: false
+            },
+            axisLabel: {
+              color: '#54606C'
+            },
+            nameTextStyle: {
+              color: '#8D99A4'
+            }
+          },
+        ],
+        grid: {
+          left: 10,
+          right: 0,
+          bottom: 0,
+          top: 30,
+          containLabel: true
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'line'
+          },
+          formatter: function(prams) {
+            return `停泊点:${prams[0].name}<br/>流量:${prams[0].data}m³/h`;
+          },
+          padding: [5, 10]
+        },
+        series: [{
+          name: '流量',
+          type: 'bar',
+          data: seriesData,
+          itemStyle: {
+            color: '#7FC8E5'
+          }
+        }]
+      };
+      this.chart.setOption(options);
+    }
+  }
+}
+</script>
+
+<style scoped>
+.realtime-container {
+  background: #fff;
+  height: 190px;
+  border-radius: 4px;
+  padding: 10px 20px;
+}
+.title {
+  font-size: 18px;
+  line-height: 26px;
+  font-weight: 600;
+  color: #1D2738;
+}
+</style>

+ 59 - 0
ruoyi-ui/src/views/analysis/task/realtime/message.vue

@@ -0,0 +1,59 @@
+<template>
+  <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>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+}
+</script>
+
+<style scoped>
+.realtime-container {
+  background: #fff;
+  height: 190px;
+  border-radius: 4px;
+  padding: 10px 20px;
+}
+.title {
+  font-size: 18px;
+  line-height: 26px;
+  font-weight: 600;
+  color: #1D2738;
+}
+.info {
+  padding-top: 5px;
+  font-size: 14px;
+  line-height: 18px;
+  height: 140px;
+  overflow: auto;
+}
+.item {
+  padding: 5px 0;
+  color: #54606C;
+}
+</style>

+ 17 - 0
ruoyi-ui/src/views/analysis/task/realtime/movie.vue

@@ -0,0 +1,17 @@
+<template>
+  <div class="realtime-container">实时视频</div>
+</template>
+
+<script>
+export default {
+}
+</script>
+
+<style scoped>
+.realtime-container {
+  background: #fff;
+  height: 300px;
+  border-radius: 4px;
+  padding: 10px 20px;
+}
+</style>

+ 18 - 0
ruoyi-ui/src/views/analysis/task/realtime/report.vue

@@ -0,0 +1,18 @@
+<template>
+  <div class="realtime-container">报表</div>
+
+</template>
+
+<script>
+export default {
+}
+</script>
+
+<style scoped>
+.realtime-container {
+  background: #fff;
+  height: 300px;
+  border-radius: 4px;
+  padding: 10px 20px;
+}
+</style>

+ 16 - 0
ruoyi-ui/src/views/analysis/task/realtime/simulation.vue

@@ -0,0 +1,16 @@
+<template>
+  <div class="realtime-container">实时动态模拟</div>
+</template>
+
+<script>
+export default {
+}
+</script>
+
+<style scoped>
+.realtime-container {
+  height: 500px;
+  background: linear-gradient(0, #FFFFFF 57%, #D1E8FF 100%);
+  border-radius: 4px;
+}
+</style>

+ 66 - 0
ruoyi-ui/src/views/analysis/task/realtime/site.vue

@@ -0,0 +1,66 @@
+<template>
+  <div class="realtime-container">
+    <div class="title">站点信息</div>
+    <div class="info">
+      <div class="item">
+        <div class="item-icon"></div>
+        <div class="item-label">站点名称:</div>
+        <div class="item-value">赤水(80307010)</div>
+      </div>
+      <div class="item">
+        <div class="item-icon"></div>
+        <div class="item-label">下次测流时间:</div>
+        <div class="item-value">2024-04-01</div>
+      </div>
+      <div class="item">
+        <div class="item-icon"></div>
+        <div class="item-label">站点状态:</div>
+        <div class="item-value">测流</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+}
+</script>
+
+<style scoped>
+.realtime-container {
+  background: #fff;
+  height: 190px;
+  border-radius: 4px;
+  padding: 10px 20px;
+}
+.title {
+  font-size: 18px;
+  line-height: 26px;
+  font-weight: 600;
+  color: #1D2738;
+}
+.info {
+  padding-top: 5px;
+  font-size: 14px;
+  line-height: 18px;
+}
+.item {
+  display: flex;
+  align-items: center;
+  padding: 5px 0;
+}
+.item-icon {
+  width: 6px;
+  height: 6px;
+  border-radius: 50%;
+  background: #55DA74;
+  margin-right: 8px;
+}
+.item-label {
+  width: 100px;
+  color: #54606C;
+}
+.item-value {
+  color: #1D2738;
+}
+</style>

+ 137 - 0
ruoyi-ui/src/views/analysis/task/realtime/water.vue

@@ -0,0 +1,137 @@
+<template>
+  <div class="realtime-container">
+    <div class="title">当日时间水位趋势图</div>
+    <div ref="chart" class="chart" :style="{height: '140px', width: '100%'}" />
+  </div>
+</template>
+
+<script>
+
+import * as echarts from "echarts";
+require('echarts/theme/macarons') // echarts theme
+import resize from '@/utils/resize'
+
+export default {
+  mixins: [resize],
+  mounted() {
+    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
+    }
+    this.chart.dispose()
+    this.chart = null
+  },
+  methods: {
+    setOptions(chartData) {
+      if (!this.chart) {
+        return;
+      }
+      const xAxisData = chartData.map(({ time }) => time);
+      const seriesData = chartData.map(({ level }) => level);
+      const options = {
+        xAxis: {
+          name: '时间',
+          data: xAxisData,
+          type: 'category',
+          axisLabel: {
+            color: '#54606C'
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#E4E4E4'
+            }
+          }
+        },
+        yAxis: [
+          {
+            name: '水位(m)',
+            axisLine: {
+              show: false
+            },
+            axisLabel: {
+              color: '#54606C'
+            },
+            nameTextStyle: {
+              color: '#8D99A4'
+            },
+            min: 'dataMin',
+            max: 'dataMax',
+          },
+        ],
+        grid: {
+          left: 10,
+          right: 0,
+          bottom: 0,
+          top: 30,
+          containLabel: true
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'line'
+          },
+          formatter: function(prams) {
+            return `时间:${prams[0].name}<br/>水位:${prams[0].data}m`;
+          },
+          padding: [5, 10]
+        },
+        series: [{
+          name: '水位',
+          type: 'line',
+          smooth: false,
+          data: seriesData,
+          areaStyle: {
+            normal: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                {
+                  offset: 0,
+                  color: "rgba(127, 200, 229, 0.4)"
+                },
+                {
+                  offset: 1,
+                  color: "rgba(119, 211, 247, 0.1)"
+                }
+              ], false),
+              shadowColor: "rgba(119, 211, 247, 0.1)",
+              shadowBlur: 20
+            }
+          },
+        }]
+      };
+      this.chart.setOption(options);
+    }
+  }
+}
+</script>
+
+<style scoped>
+.realtime-container {
+  background: #fff;
+  height: 190px;
+  border-radius: 4px;
+  padding: 10px 20px;
+}
+.title {
+  font-size: 18px;
+  line-height: 26px;
+  font-weight: 600;
+  color: #1D2738;
+}
+</style>