Browse Source

[Feat 0000] 开发瓦斯监测曲线页面

houzekong 11 months ago
parent
commit
495e6d7e2c

+ 12 - 0
src/assets/icons/gas-monitor-co.svg

@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="21.103" height="15.454" viewBox="0 0 21.103 15.454">
+  <defs>
+    <linearGradient id="linear-gradient" x1="0.798" x2="0.205" y2="1" gradientUnits="objectBoundingBox">
+      <stop offset="0" stop-color="#fff"/>
+      <stop offset="1" stop-color="#2cb6ff"/>
+    </linearGradient>
+  </defs>
+  <g id="组_14943" data-name="组 14943" transform="translate(-81.914 -204.795)">
+    <path id="路径_56090" data-name="路径 56090" d="M541.488,206.474v.015l.008-.008-.008-.008Zm2.771,3.338c2.041-.123,2.3-.291,3.53.852a1.874,1.874,0,0,0-1.4-3.446c.108-1.535-2.786-4.16-4.9-.768.069.054,2.732.967,2.763,3.361Zm-4.136,4.006c-.767,0-1.251.652-1.251,1.734s.491,1.765,1.251,1.765,1.259-.691,1.259-1.765S540.882,213.818,540.122,213.818Z" transform="translate(-445.746)" fill="url(#linear-gradient)"/>
+    <path id="路径_56091" data-name="路径 56091" d="M99.564,262.173l-2.3-.084c-.859-6.224-9.6-7.291-11.457,1.044l-.906.046c-4.766,2.3-2.893,7.4-.767,8.142h15.54c3.683-.944,4.489-7.191-.108-9.148ZM90.6,269.027a2.087,2.087,0,0,1-2.041-2.364,2.135,2.135,0,0,1,2.072-2.394,1.771,1.771,0,0,1,1.3.583l-.391.461a1.22,1.22,0,0,0-.9-.414c-.767,0-1.343.66-1.343,1.742s.515,1.758,1.32,1.758a1.336,1.336,0,0,0,1.021-.491l.391.453a1.819,1.819,0,0,1-1.435.668Zm3.768,0c-1.182,0-2-.922-2-2.395s.821-2.364,1.995-2.364,2.011.874,2.011,2.356-.844,2.4-2,2.4h-.008Z" transform="translate(0 -51.072)" fill="url(#linear-gradient)"/>
+  </g>
+</svg>

+ 9 - 0
src/assets/icons/gas-monitor-extract.svg

@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="17.922" height="20.742" viewBox="0 0 17.922 20.742">
+  <defs>
+    <linearGradient id="linear-gradient" x1="0.798" x2="0.205" y2="1" gradientUnits="objectBoundingBox">
+      <stop offset="0" stop-color="#fff"/>
+      <stop offset="1" stop-color="#2cb6ff"/>
+    </linearGradient>
+  </defs>
+  <path id="路径_56089" data-name="路径 56089" d="M90.293,2.823V4.588c0,1.555-3.789,2.824-8.461,2.824s-8.461-1.268-8.461-2.824V2.823C73.371,1.268,77.161,0,81.832,0S90.293,1.268,90.293,2.823Zm0,3.915v3.977c0,1.557-3.789,2.828-8.461,2.828s-8.461-1.271-8.461-2.828V6.738c1.818,1.281,5.145,1.878,8.461,1.878s6.643-.6,8.461-1.878Zm0,6.2v3.977c0,1.557-3.789,2.828-8.461,2.828s-8.461-1.271-8.461-2.828V12.937c1.818,1.281,5.145,1.878,8.461,1.878s6.643-.6,8.461-1.878Z" transform="translate(-72.871 0.5)" stroke="rgba(0,0,0,0)" stroke-miterlimit="10" stroke-width="1" fill="url(#linear-gradient)"/>
+</svg>

+ 9 - 0
src/assets/icons/gas-monitor-flow.svg

@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="22.434" height="20.742" viewBox="0 0 22.434 20.742">
+  <defs>
+    <linearGradient id="linear-gradient" x1="0.798" x2="0.205" y2="1" gradientUnits="objectBoundingBox">
+      <stop offset="0" stop-color="#fff"/>
+      <stop offset="1" stop-color="#2cb6ff"/>
+    </linearGradient>
+  </defs>
+  <path id="路径_56094" data-name="路径 56094" d="M73.48,96.993a.6.6,0,0,0-.453-.2h-3.35l-1.24-4.375a.632.632,0,0,0-.608-.513.447.447,0,0,0-.131.012l-.7.012c-.036,0-.072-.012-.107-.012a.652.652,0,0,0-.572.56L64.646,101.4,62.309,88.589v-.012a.629.629,0,0,0-.6-.513.447.447,0,0,0-.131.012c-.119,0-.656.012-.906.012a.658.658,0,0,0-.584.489v.012L58.351,98.722l-.441-1.5a.589.589,0,0,0-.644-.441h-.1l-4.315.012a.662.662,0,0,0-.632.7v.978a.669.669,0,0,0,.632.7h3.338l1.24,4.3a.644.644,0,0,0,.62.513.581.581,0,0,0,.143-.012l.632-.012c.036,0,.072.012.107.012a.743.743,0,0,0,.656-.56l1.729-9.072,2.36,12.946a.642.642,0,0,0,.6.513.447.447,0,0,0,.131-.012h.715c.334,0,.477-.405.513-.751l1.9-9.883.429,1.526a.642.642,0,0,0,.608.513.447.447,0,0,0,.131-.012h4.327a.662.662,0,0,0,.632-.7v-.978A.746.746,0,0,0,73.48,96.993Z" transform="translate(-51.724 -87.564)" stroke="rgba(0,0,0,0)" stroke-miterlimit="10" stroke-width="1" fill="url(#linear-gradient)"/>
+</svg>

+ 12 - 0
src/assets/icons/gas-monitor-np.svg

@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="19.747" height="19.742" viewBox="0 0 19.747 19.742">
+  <defs>
+    <linearGradient id="linear-gradient" x1="0.798" x2="0.205" y2="1" gradientUnits="objectBoundingBox">
+      <stop offset="0" stop-color="#fff"/>
+      <stop offset="1" stop-color="#2cb6ff"/>
+    </linearGradient>
+  </defs>
+  <g id="组_14944" data-name="组 14944" transform="translate(0 -0.341)">
+    <path id="路径_56092" data-name="路径 56092" d="M19.745,767.768v2.826H0v-2.826a2.058,2.058,0,0,1,1.941-2.157h5.39a2.632,2.632,0,0,0,3.437,1.825,2.861,2.861,0,0,0,1.645-1.825H17.8a2.058,2.058,0,0,1,1.94,2.157Z" transform="translate(0 -750.511)" fill="url(#linear-gradient)"/>
+    <path id="路径_56093" data-name="路径 56093" d="M99.765,9.242a2.436,2.436,0,1,1-4.834,0,.709.709,0,0,1,.658-.752.693.693,0,0,1,.658.658v.1a1.178,1.178,0,0,0,1.1,1.244,1.162,1.162,0,0,0,1.091-1.115V1.088A.707.707,0,0,1,99.1.341a.694.694,0,0,1,.658.647V9.243Zm6.591,0a2.432,2.432,0,1,0,4.824,0,.706.706,0,0,0-.666-.739.694.694,0,0,0-.645.64v.1a1.18,1.18,0,0,1-1.091,1.252,1.152,1.152,0,0,1-1.1-1.124V1.088a.707.707,0,0,0-.658-.747.7.7,0,0,0-.658.647V9.243ZM102.98,1.922a.691.691,0,0,1,.658.647v8.073a.707.707,0,0,1-.658.747.691.691,0,0,1-.658-.647V2.674a.707.707,0,0,1,.658-.752Z" transform="translate(-93.096)" fill="url(#linear-gradient)"/>
+  </g>
+</svg>

+ 14 - 0
src/assets/icons/warning-icon-gas.svg

@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="69.485" height="66.318" viewBox="0 0 69.485 66.318">
+  <defs>
+    <filter id="路径_44665" x="0" y="0" width="69.485" height="66.318" filterUnits="userSpaceOnUse">
+      <feOffset input="SourceAlpha"/>
+      <feGaussianBlur stdDeviation="5" result="blur"/>
+      <feFlood flood-color="#2cb6ff"/>
+      <feComposite operator="in" in2="blur"/>
+      <feComposite in="SourceGraphic"/>
+    </filter>
+  </defs>
+  <g transform="matrix(1, 0, 0, 1, 0, 0)" filter="url(#路径_44665)">
+    <path id="路径_44665-2" data-name="路径 44665" d="M39.264,74.357,21.618,42.085a2.142,2.142,0,0,0-3.77,0L.221,74.357a2.027,2.027,0,0,0,1.895,2.921H37.389a2.025,2.025,0,0,0,1.875-2.921Zm-21.1-19.166a1.579,1.579,0,1,1,3.158,0v9.474a1.579,1.579,0,1,1-3.158,0Zm1.579,16.58A1.974,1.974,0,1,1,21.716,69.8,1.98,1.98,0,0,1,19.743,71.771Z" transform="translate(15 -25.96)" fill="#fff"/>
+  </g>
+</svg>

BIN
src/assets/images/vent/gas/confirm-modal.png


+ 25 - 0
src/components/chart/LineMulti.vue

@@ -8,6 +8,9 @@
   export default defineComponent({
     name: 'LineMulti',
     props: {
+      /**
+       * 图表数据,配合xAxisPropType、propTypeArr使用
+       */
       chartData: {
         type: Array,
         default: () => [],
@@ -17,10 +20,32 @@
         type: Object,
         default: () => ({}),
       },
+      /**
+       * x轴数据对应的prop,将从chartData中映射prop到一个Set中。
+       *
+       * @example
+       * ```js
+       * const props = { xAxisPropType: 'name', chartData: [{ name: 'a' }, { name: 'b' }] }
+       *
+       * // truns out
+       * option.xAxis.data = ['a', 'b'];
+       * ```
+       */
       xAxisPropType: {
         type: String,
         required: true,
       },
+      /**
+       * 提供一个Map,该Map将用于生成基于chartData的echart.series数据。
+       *
+       * @example
+       * ```js
+       * const props = { propTypeArr: new Map([['valueA', '值A']]), chartData: [{ valueA: 'a' }, { valueA: 'b' }] }
+       *
+       * // truns out
+       * option.series = [{ name: '值A', data: ['a', 'b'] }]
+       * ```
+       */
       propTypeArr: {
         type: Map,
         default: () => new Map(),

+ 24 - 0
src/utils/limitedArray.ts

@@ -0,0 +1,24 @@
+/**
+ * 限制长度的数据,可以理解为限制了最大长度的队列
+ */
+export class LimitedArray {
+  readonly limit: number = 5;
+  public items: any[] = [];
+
+  constructor(limit: number = 5, initial: any[] = []) {
+    this.limit = limit;
+    initial.forEach((item) => {
+      this.push(item);
+    });
+  }
+
+  push(...items: any[]) {
+    items.forEach((item) => {
+      this.items.push(item);
+      if (this.items.length > this.limit) {
+        this.items.shift();
+      }
+    });
+    return this.items.length;
+  }
+}

+ 1 - 0
src/views/vent/gas/components/form/formTitle.vue

@@ -40,6 +40,7 @@
     height: 40px;
     line-height: 40px;
     margin-bottom: 20px;
+    color: @white;
   }
 
   .form-title__text {

+ 1 - 1
src/views/vent/gas/components/list/listItem.vue

@@ -121,7 +121,7 @@
     background-size: 20px 20px;
   }
 
-  :v-deep(.zxm-input) {
+  ::v-deep .zxm-input {
     color: @white;
   }
 </style>

+ 56 - 0
src/views/vent/gas/components/modal/confirmModal.vue

@@ -0,0 +1,56 @@
+<template>
+  <Modal v-bind="props" @change="$emit('change', $event)">
+    <slot></slot>
+    <template #footer>
+      <slot name="footer">
+        <Button class="mr-20px" ghost @click="cancelHandler">{{ cancelText }}</Button>
+        <Button type="primary" @click="okHandler">{{ okText }}</Button>
+      </slot>
+    </template>
+  </Modal>
+</template>
+<script setup lang="ts">
+  import { Modal, Button, ModalProps } from 'ant-design-vue';
+
+  const props = withDefaults(defineProps<ModalProps>(), {
+    context: '确认操作?',
+    cancelText: '取消',
+    okText: '确认',
+    centered: true,
+    wrapClassName: 'gas-confirm-modal',
+  });
+
+  const emit = defineEmits(['ok', 'cancel', 'update:visible', 'change']);
+  function cancelHandler() {
+    emit('update:visible', false);
+    emit('cancel');
+  }
+  function okHandler() {
+    emit('update:visible', false);
+    emit('ok');
+  }
+</script>
+<style lang="less">
+  .gas-confirm-modal {
+    .zxm-modal-content {
+      width: 410px;
+      height: 300px;
+      border: none !important;
+      box-shadow: none !important;
+      background-color: transparent !important;
+      background-image: url('@/assets/images/vent/gas/confirm-modal.png');
+      background-size: 100% auto;
+      background-repeat: no-repeat;
+
+      .zxm-modal-body {
+        font-size: 32px;
+        padding-top: 70px;
+        height: 210px;
+        text-align: center;
+      }
+      .zxm-modal-footer {
+        text-align: center;
+      }
+    }
+  }
+</style>

+ 16 - 2
src/views/vent/gas/gasPumpMonitor/components/monitor.vue

@@ -31,8 +31,8 @@
           </template>
           <template #container>
             <div class="flex justify-between mt-10px mb-10px">
-              <Button>一键倒机</Button>
-              <Button>一键启停</Button>
+              <Button @click="reverseModalVisible = true">一键倒机</Button>
+              <Button @click="switchModalVisible = true">一键启停</Button>
             </div>
             <List icon="pump" title="抽放泵" layout="double-columns" type="status-light" :label-width="80" v-bind="pumpStatusProp" />
             <List icon="water-pump" title="水泵" layout="double-columns" type="status-light" :label-width="80" v-bind="waterPumpStatusProp" />
@@ -42,6 +42,14 @@
         </ventBox1>
       </div>
     </div>
+    <ConfirmModal v-model:visible="reverseModalVisible">
+      <SvgIcon class="icon" size="34" name="warning-icon-gas" />
+      <span> 是否进行一键倒机 </span>
+    </ConfirmModal>
+    <ConfirmModal v-model:visible="switchModalVisible">
+      <SvgIcon class="icon" size="34" name="warning-icon-gas" />
+      <span> 是否进行一键启停 </span>
+    </ConfirmModal>
   </div>
 </template>
 
@@ -52,6 +60,8 @@
   import BaseTab from '@/views/vent/gas/components/tab/baseTab.vue';
   import Button from '@/views/vent/gas/components/form/button.vue';
   import CategoryBoard from '@/views/vent/gas/components/board/categoryBoard.vue';
+  import ConfirmModal from '@/views/vent/gas/components/modal/confirmModal.vue';
+  import { SvgIcon } from '/@/components/Icon';
   import {
     pumpListConfig,
     pumpStationListConfig,
@@ -136,6 +146,10 @@
     };
   });
 
+  // 模态框相关
+  const reverseModalVisible = ref(false);
+  const switchModalVisible = ref(false);
+
   onMounted(async () => {});
 </script>
 

+ 80 - 0
src/views/vent/gas/gasPumpMonitor/components/monitorChart.vue

@@ -0,0 +1,80 @@
+<template>
+  <div class="monitor-chart">
+    <Row :gutter="[40, 40]">
+      <Col :span="12">
+        <div class="h-400px monitor-chart__wrapper p-20px">
+          <FormTitle class="monitor-chart__title" icon="gas-monitor-extract" title="累积抽采量" />
+          <BarMulti :propTypeArr="chartSeriesMap" xAxisPropType="date" :chartData="testChartData.items" />
+        </div>
+      </Col>
+      <Col :span="12">
+        <div class="h-400px monitor-chart__wrapper p-20px">
+          <FormTitle class="monitor-chart__title" icon="gas-monitor-co" title="CO浓度" />
+          <BarMulti :propTypeArr="chartSeriesMap" xAxisPropType="date" :chartData="testChartData.items" />
+        </div>
+      </Col>
+      <Col :span="12">
+        <div class="h-400px monitor-chart__wrapper p-20px">
+          <FormTitle class="monitor-chart__title" icon="gas-monitor-np" title="负压浓度" />
+          <BarMulti :propTypeArr="chartSeriesMap" xAxisPropType="date" :chartData="testChartData.items" />
+        </div>
+      </Col>
+      <Col :span="12">
+        <div class="h-400px monitor-chart__wrapper p-20px">
+          <FormTitle class="monitor-chart__title" icon="gas-monitor-flow" title="瞬时流量" />
+          <LineMulti :propTypeArr="chartSeriesMap" xAxisPropType="date" :chartData="testChartData.items" />
+        </div>
+      </Col>
+    </Row>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import FormTitle from '/@/views/vent/gas/components/form/formTitle.vue';
+  import BarMulti from '/@/components/chart/BarMulti.vue';
+  import LineMulti from '/@/components/chart/LineMulti.vue';
+  import { Row, Col } from 'ant-design-vue';
+  import { LimitedArray } from '/@/utils/limitedArray';
+  import { onMounted, onUnmounted } from 'vue';
+  defineProps({
+    deviceId: {
+      type: String,
+      require: true,
+    },
+  });
+
+  const testChartData = new LimitedArray(10);
+  const chartSeriesMap = new Map([
+    ['valueA', '值A'],
+    ['valueB', '值A'],
+  ]);
+  let timer: any = null;
+
+  onMounted(() => {
+    timer = setTimeout(() => {
+      testChartData.push({
+        valueA: Math.floor(Math.random() * 10),
+        valueB: Math.floor(Math.random() * 10),
+        date: new Date().getMilliseconds().toString(),
+      });
+    }, 2000);
+  });
+  onUnmounted(() => {
+    clearTimeout(timer);
+  });
+</script>
+
+<style lang="less" scoped>
+  @import '@/design/vent/color.less';
+
+  .monitor-chart {
+    margin-top: 100px;
+    margin-left: 20px;
+    margin-right: 20px;
+  }
+  .monitor-chart__wrapper {
+    color: @white;
+    border-top: 3px solid @vent-gas-primary-text;
+    background-color: @vent-gas-primary-trasparent-bg;
+  }
+</style>

+ 50 - 0
src/views/vent/gas/gasPumpMonitor/gasPumpMonitor.data.ts

@@ -7,6 +7,11 @@ export const navList = ref([
     isHover: false,
   },
   {
+    title: '监测曲线',
+    pathName: 'monitorChart',
+    isHover: false,
+  },
+  {
     title: '历史查询',
     pathName: 'history',
     isHover: false,
@@ -93,3 +98,48 @@ export const LPumpCategoryConfig = [
   { prop: 'activedPump', label: '瞬时流量' },
   { prop: 'activedPump', label: '累计抽采时间' },
 ];
+
+/** 累积抽采量图表配置项 */
+export const cumulativeExtractionChart = [
+  {
+    name: '高负压',
+    prop: 'HPressure',
+  },
+  {
+    name: '低负压',
+    prop: 'LPressure',
+  },
+];
+/** CO浓度图表配置项 */
+export const coChart = [
+  {
+    name: '高负压',
+    prop: 'HPressure',
+  },
+  {
+    name: '低负压',
+    prop: 'LPressure',
+  },
+];
+/** 负压浓度图表配置项 */
+export const negativePressureChart = [
+  {
+    name: '高负压',
+    prop: 'HPressure',
+  },
+  {
+    name: '低负压',
+    prop: 'LPressure',
+  },
+];
+/** 瞬时流量图表配置项 */
+export const instantaneousFlowChart = [
+  {
+    name: '高负压',
+    prop: 'HPressure',
+  },
+  {
+    name: '低负压',
+    prop: 'LPressure',
+  },
+];

+ 15 - 8
src/views/vent/gas/gasPumpMonitor/index.vue

@@ -1,17 +1,14 @@
 <!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <div class="scene-box">
-    <customHeader
-      :fieldNames="{ label: 'systemname', value: 'id', options: 'children' }"
-      :options="options"
-      @change="getSelectRow"
-      :optionValue="optionValue"
-      >瓦斯抽采泵监测系统</customHeader
-    >
+    <customHeader :fieldNames="calcFieldNames" :options="options" @change="getSelectRow" :optionValue="optionValue">瓦斯抽采泵监测系统</customHeader>
     <div class="center-container">
       <template v-if="activeKey == 'deviceMonitor'">
         <GasPumpMonitor :deviceId="optionValue" />
       </template>
+      <template v-if="activeKey == 'monitorChart'">
+        <GasMonitorChart :deviceId="optionValue" />
+      </template>
       <div v-else class="history-group">
         <div class="device-button-group" v-if="deviceList.length > 0 && activeKey !== 'faultRecord'">
           <div
@@ -38,13 +35,14 @@
   </div>
 </template>
 <script lang="ts" setup>
-  import { ref, onMounted } from 'vue';
+  import { ref, onMounted, computed } from 'vue';
   import customHeader from '/@/components/vent/customHeader.vue';
   import { useSystemSelect } from '/@/hooks/vent/useSystemSelect';
   import BottomMenu from '/@/views/vent/comment/components/bottomMenu.vue';
   import HistoryTable from '../../monitorManager/comment/HistoryTable.vue';
   import { navList } from './gasPumpMonitor.data';
   import GasPumpMonitor from './components/monitor.vue';
+  import GasMonitorChart from './components/monitorChart.vue';
 
   const activeKey = ref('deviceMonitor');
 
@@ -54,6 +52,15 @@
   function changeActive(activeValue) {
     activeKey.value = activeValue;
   }
+
+  // 在监测图表模块展示时,返回空以隐藏 CustomHeader 中的选择框
+  const calcFieldNames = computed(() => {
+    if (activeKey.value === 'monitorChart') {
+      return undefined;
+    }
+    return { label: 'systemname', value: 'id', options: 'children' };
+  });
+
   onMounted(async () => {
     await getSysDataSource();
   });

+ 1 - 1
src/views/vent/gas/gasPumpSetting/components/settingForm.vue

@@ -94,7 +94,7 @@
   .setting-form__wrapper {
     color: #fff;
     border-top: 3px solid @vent-gas-primary-text;
-    background-color: #0091ff12;
+    background-color: @vent-gas-primary-trasparent-bg;
     padding: 10px 10px 0 10px;
     margin-bottom: 10px;
   }