5 次代碼提交 c1574145bb ... 903e6f2107

作者 SHA1 備註 提交日期
  houzekong 903e6f2107 [Mod 0000] 修改了均压信息提示框的内容 3 周之前
  houzekong 6edbeda58c [Feat 0000] 为可配置首页常用模块添加隐藏功能与动画 3 周之前
  houzekong 5c6397b706 [Mod 0000] 三道沟通风首页对接均压模型添加全屏功能 4 周之前
  houzekong 75819cac5e [Feat 0000] 可配置首页原版模块支持Transition动画 4 周之前
  houzekong 8455d0fe9e [Mod 0000] 修改三道沟均压页面的报警提示以及对接细则 4 周之前

+ 20 - 11
src/views/vent/home/configurable/components/ModuleCommon.vue

@@ -1,16 +1,21 @@
 <template>
   <!-- 常用模块 -->
-  <ventBox1 :class="getModuleClass(showStyle)" :style="style">
-    <template v-if="moduleName" #title>
-      <div :class="{ 'cursor-pointer': !!moduleData.to }" @click="redirectTo">{{ moduleName }}</div>
-    </template>
-    <template #container>
-      <slot>
-        <Header :deviceType="deviceType" :moduleData="moduleData" :data="data" @select="selectedData = $event" />
-        <Content :style="{ height: header.show ? 'calc(100% - 30px)' : '100%' }" :moduleData="moduleData" :data="selectedData" />
-      </slot>
-    </template>
-  </ventBox1>
+  <Transition
+    :enter-active-class="`animate__animated  animate__fadeIn${capitalizedPosition}`"
+    :leave-active-class="`animate__animated  animate__fadeOut${capitalizedPosition}`"
+  >
+    <ventBox1 v-if="visible" :class="getModuleClass(showStyle)" :style="style">
+      <template v-if="moduleName" #title>
+        <div :class="{ 'cursor-pointer': !!moduleData.to }" @click="redirectTo">{{ moduleName }}</div>
+      </template>
+      <template #container>
+        <slot>
+          <Header :deviceType="deviceType" :moduleData="moduleData" :data="data" @select="selectedData = $event" />
+          <Content :style="{ height: header.show ? 'calc(100% - 30px)' : '100%' }" :moduleData="moduleData" :data="selectedData" />
+        </slot>
+      </template>
+    </ventBox1>
+  </Transition>
 </template>
 <script lang="ts" setup>
   import Header from './header.vue';
@@ -46,6 +51,10 @@
     return size + position + 'position: absolute; pointer-events: auto;';
   });
 
+  const capitalizedPosition = computed(() => {
+    return props.showStyle.position.includes('left') ? 'Left' : 'Right';
+  });
+
   // 根据配置里的定位判断应该使用哪个class
   function getModuleClass({ size, position }) {
     const [_, width] = size.match(/width:([0-9]+)px/) || [];

+ 46 - 45
src/views/vent/home/configurable/components/ModuleOriginal.vue

@@ -16,56 +16,57 @@
   </component>
 </template>
 <script lang="ts" setup>
-import Header from './header.vue';
-import Content from './content.vue';
-import ModuleLeft from './original/moduleLeft.vue';
-import ModuleBottom from './original/moduleBottom.vue';
-import { computed, ref } from 'vue';
-import { openWindow } from '/@/utils';
-import { getFormattedText } from '../hooks/helper';
-// import { ModuleProps } from '../types';
+  import Header from './header.vue';
+  import Content from './content.vue';
+  import ModuleLeft from './original/moduleLeft.vue';
+  import ModuleRight from './original/moduleRight.vue';
+  import ModuleBottom from './original/moduleBottom.vue';
+  import { computed, ref } from 'vue';
+  import { openWindow } from '/@/utils';
+  import { getFormattedText } from '../hooks/helper';
+  // import { ModuleProps } from '../types';
 
-const props = defineProps<{
-  /** 配置的详细模块信息 */
-  moduleData: any;
-  /** 配置的详细样式信息 */
-  showStyle: any;
-  /** 该模块配置中的设备标识符 */
-  deviceType: string;
-  /** api返回的数据 */
-  data: any;
-  moduleName: string;
-  visible: boolean;
-}>();
-defineEmits(['close', 'click']);
+  const props = defineProps<{
+    /** 配置的详细模块信息 */
+    moduleData: any;
+    /** 配置的详细样式信息 */
+    showStyle: any;
+    /** 该模块配置中的设备标识符 */
+    deviceType: string;
+    /** api返回的数据 */
+    data: any;
+    moduleName: string;
+    visible: boolean;
+  }>();
+  defineEmits(['close', 'click']);
 
-const { header } = props.moduleData;
-const selectedData = ref();
+  const { header } = props.moduleData;
+  const selectedData = ref();
 
-const style = computed(() => {
-  const size = props.showStyle.size;
-  const position = props.showStyle.position;
-  return size + position;
-});
+  const style = computed(() => {
+    const size = props.showStyle.size;
+    const position = props.showStyle.position;
+    return size + position;
+  });
 
-// 根据配置里的定位判断应该使用哪个module组件
-function getModuleComponent({ size, position }) {
-  const [_, width] = size.match(/width:([0-9]+)px/) || [];
-  if (position.includes('bottom') || parseInt(width) > 800) {
+  // 根据配置里的定位判断应该使用哪个module组件
+  function getModuleComponent({ size, position }) {
+    const [_, width] = size.match(/width:([0-9]+)px/) || [];
+    if (position.includes('bottom') || parseInt(width) > 800) {
+      return ModuleBottom;
+    }
+    if (position.includes('left')) {
+      return ModuleLeft;
+    }
+    if (position.includes('right')) {
+      return ModuleRight;
+    }
     return ModuleBottom;
   }
-  if (position.includes('left')) {
-    return ModuleLeft;
-  }
-  if (position.includes('right')) {
-    return ModuleLeft;
-  }
-  return ModuleBottom;
-}
 
-function redirectTo() {
-  const { to } = props.moduleData;
-  if (!to) return;
-  openWindow(getFormattedText(selectedData.value, to));
-}
+  function redirectTo() {
+    const { to } = props.moduleData;
+    if (!to) return;
+    openWindow(getFormattedText(selectedData.value, to));
+  }
 </script>

+ 10 - 8
src/views/vent/home/configurable/components/original/moduleBottom.vue

@@ -1,13 +1,15 @@
 <template>
-  <div v-if="visible" class="module-content">
-    <div v-if="title" class="module-content__title__expand">
-      <span class="action-btn close-btn" @click="closeModel"></span>
-      <span @click="clickHandler">{{ title }}</span>
+  <Transition>
+    <div v-if="visible" class="module-content">
+      <div v-if="title" class="module-content__title__expand">
+        <span class="action-btn close-btn" @click="closeModel"></span>
+        <span @click="clickHandler">{{ title }}</span>
+      </div>
+      <div class="module-slot">
+        <slot></slot>
+      </div>
     </div>
-    <div class="module-slot">
-      <slot></slot>
-    </div>
-  </div>
+  </Transition>
 </template>
 <script lang="ts" setup>
   defineProps<{ title: string; visible: boolean }>();

+ 10 - 8
src/views/vent/home/configurable/components/original/moduleLeft.vue

@@ -1,13 +1,15 @@
 <template>
-  <div v-if="visible" class="module-content">
-    <div v-if="title" class="module-content__title__expand">
-      <span class="action-btn close-btn" @click="closeModel"></span>
-      <span @click="clickHandler">{{ title }}</span>
+  <Transition>
+    <div v-if="visible" class="module-content">
+      <div v-if="title" class="module-content__title__expand">
+        <span class="action-btn close-btn" @click="closeModel"></span>
+        <span @click="clickHandler">{{ title }}</span>
+      </div>
+      <div class="module-slot">
+        <slot></slot>
+      </div>
     </div>
-    <div class="module-slot">
-      <slot></slot>
-    </div>
-  </div>
+  </Transition>
 </template>
 <script lang="ts" setup>
   defineProps<{ title: string; visible: boolean }>();

+ 100 - 0
src/views/vent/home/configurable/components/original/moduleRight.vue

@@ -0,0 +1,100 @@
+<template>
+  <Transition>
+    <div v-if="visible" class="module-content">
+      <div v-if="title" class="module-content__title__expand">
+        <span class="action-btn close-btn" @click="closeModel"></span>
+        <span @click="clickHandler">{{ title }}</span>
+      </div>
+      <div class="module-slot">
+        <slot></slot>
+      </div>
+    </div>
+  </Transition>
+</template>
+<script lang="ts" setup>
+  // 和 ./moduleLeft 一样,针对动画做了一些修改
+  defineProps<{ title: string; visible: boolean }>();
+  const emit = defineEmits(['close', 'click']);
+
+  function closeModel() {
+    emit('close');
+  }
+  function clickHandler() {
+    emit('click');
+  }
+</script>
+<style lang="less" scoped>
+  @import '/@/design/theme.less';
+
+  @{theme-deepblue} {
+    .module-content {
+      --image-model_original_title_bg: url('@/assets/images/themify/deepblue/home-container/configurable/model_original_title_bg.png');
+    }
+  }
+
+  .module-content {
+    --image-model_original_title_bg: url('@/assets/images/home-container/configurable/model_original_title_bg.png');
+    --bg-height: 33px;
+    color: #fff;
+    box-sizing: border-box;
+    position: absolute;
+    width: 100%;
+    height: 100%;
+  }
+
+  .module-content__title__expand {
+    width: 100%;
+    height: var(--bg-height);
+    background: var(--image-model_original_title_bg) no-repeat;
+    background-size: 100% 100%;
+    position: relative;
+    text-align: center;
+    line-height: var(--bg-height);
+  }
+
+  // .module-content__title {
+  //   width: 50%;
+  //   height: var(--bg-height);
+  //   background: url('@/assets/images/home-container/configurable/model_left_title_bg.png') no-repeat;
+  //   background-size: 100% 100%;
+  //   position: relative;
+  //   text-align: right;
+  //   padding: 4px 10% 0 0;
+  // }
+
+  // 固定在父容器右上角的按钮图标
+  // .action-btn {
+  //   width: 18px;
+  //   height: 18px;
+  //   background: url('@/assets/images/home-container/configurable/expand.svg') no-repeat center;
+  //   position: absolute;
+  //   right: 0;
+  //   top: 0;
+  // }
+  // .close-btn {
+  //   transform: rotate(-90deg);
+  // }
+
+  .module-slot {
+    height: calc(100% - 33px);
+    width: calc(100% - 20px);
+    backdrop-filter: blur(5px);
+    // #182d47
+    background-color: var(--vent-configurable-original-module-bg);
+    margin-left: 10px;
+  }
+
+  // Transition动画相关
+  .v-enter-active,
+  .v-leave-active {
+    transition: all 0.3s ease;
+  }
+
+  .v-enter-from,
+  .v-leave-to {
+    // opacity: 1;
+    transform: translateX(100%);
+    // transform: scaleY(0);
+    // transform-origin: center top;
+  }
+</style>

+ 34 - 4
src/views/vent/home/configurable/ventSDG.vue

@@ -1,8 +1,25 @@
 <!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <div class="company-home">
-    <div style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 0">
+    <CustomHeader> 三道沟煤矿均压综采面智能监测与动态调控 </CustomHeader>
+    <!-- <div style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 0">
       <VentModal />
+    </div> -->
+    <div class="bg" style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden; z-index: 0">
+      <a-spin :spinning="loading" />
+      <div id="balancePress3D" v-show="!loading" style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
+      <!-- <div id="damper3DCSS" v-show="!loading" style="width: 100%; height: 100%; top:0; left: 0; position: absolute; overflow: hidden;">
+      <div>
+        <div ref="elementContent" class="elementContent">
+          <p><span class="data-title">压力(Pa):</span>{{selectData.frontRearDP}}</p>
+          <p><span class="data-title">动力源压力(MPa):</span>{{selectData.sourcePressure}}</p>
+          <p><span class="data-title">故障诊断:</span>
+            <i
+              :class="{'state-icon': true, 'open': selectData.messageBoxStatus, 'close': !selectData.messageBoxStatus}"
+            ></i>{{selectData.fault}}</p>
+        </div>
+      </div>
+    </div> -->
     </div>
     <!-- 如果是有 deviceType、type 等 query,认为是详情页,不需要展示普通模块,只需要模型 -->
     <template v-if="!route.query.deviceType">
@@ -29,8 +46,11 @@
           :module-name="cfg.moduleName"
           :device-type="cfg.deviceType"
           :data="data"
-          :visible="true"
+          :visible="showModules"
         />
+
+        <div v-if="showModules" class="switch-button icon-goto right-475px bottom-300px" @click="showModules = false"></div>
+        <div v-else class="switch-button icon-goto right-20px bottom-20px" @click="showModules = true"></div>
       </template>
       <template v-else-if="isCommon">
         <ModuleCommon
@@ -71,11 +91,11 @@
         class="switch-button report-mode right-525px"
         @click="switchDataMode"
       ></div> -->
-      <div class="switch-button icon-goto right-475px" @click="goMicroApp()"></div>
     </template>
   </div>
 </template>
 <script lang="ts" setup>
+  import CustomHeader from '/@/components/vent/customHeader.vue';
   import { onMounted, onUnmounted, ref, watch } from 'vue';
   // import { CaretDownOutlined } from '@ant-design/icons-vue';
   // import MonitorBar from './components/MonitorBar.vue';
@@ -85,6 +105,7 @@
   import ModuleCommon from './components/ModuleCommon.vue';
   // import { useRoute } from 'vue-router';
   import VentModal from '/@/components/vent/micro/ventModal.vue';
+  import { mountedThree, destroy, setModelType, updateText, play } from '/@/views/vent/monitorManager/balancePressMonitor/balancePress.threejs';
   import { list } from './configurable.api';
   import { useRoute, useRouter } from 'vue-router';
   import { useGlobSetting } from '/@/hooks/setting';
@@ -97,6 +118,8 @@
   const router = useRouter();
   const isDataRealTime = ref(sysDataType === 'monitor');
   // const showBar = ref(true);
+  const loading = ref(false);
+  const showModules = ref(true);
   let interval: number | undefined;
 
   // function switchDataMode() {
@@ -184,9 +207,16 @@
   onMounted(() => {
     refresh();
     initInterval();
+
+    mountedThree().then(async () => {
+      await setModelType('balancePressTun'); //balancePressBase
+      loading.value = false;
+      play('startSmoke', 'top', 30, 'open', 0);
+    });
   });
 
   onUnmounted(() => {
+    destroy();
     clearInterval(interval);
   });
 </script>
@@ -280,7 +310,7 @@
       height: 34px;
       position: absolute;
       // right: 5px;
-      bottom: 300px;
+      // bottom: 300px;
       z-index: 5;
       background-repeat: no-repeat;
       background-size: 100% 100%;

+ 2 - 0
src/views/vent/monitorManager/balancePressMonitor/balancePress.api.ts

@@ -11,6 +11,7 @@ enum Api {
   updatePassword = '/monitor/demo/avePress/update/password',
   validPassword = '/monitor/demo/avePress/valid/password',
   controlWindow = '/monitor/demo/avePress/controlWindow',
+  cancelcontrolWindow = '/monitor/demo/avePress/cancel-controlWindow',
 }
 /**
  * 列表接口
@@ -50,6 +51,7 @@ export const subList2 = (params) => defHttp.get({ url: Api.subList2, params });
 export const submitEdit = (params) => defHttp.post({ url: Api.submitEdit, params });
 
 export const controlWindow = (params) => defHttp.get({ url: Api.controlWindow, params }, { joinParamsToUrl: true });
+export const cancelcontrolWindow = (params) => defHttp.get({ url: Api.cancelcontrolWindow, params }, { joinParamsToUrl: true });
 
 export const updatePassword = (params) =>
   defHttp.get({ url: Api.updatePassword, params }).then((e) => {

+ 2 - 2
src/views/vent/monitorManager/balancePressMonitor/balancePress.data.ts

@@ -206,12 +206,12 @@ export const settingParam4 = [
     title: '氧气上限',
     code: 'o2MaxVal',
     value: '',
-    unit: 'm³/min',
+    unit: '%',
   },
   {
     title: '氧气下限',
     code: 'o2MinVal',
     value: '',
-    unit: 'm³/min',
+    unit: '%',
   },
 ];

+ 210 - 155
src/views/vent/monitorManager/balancePressMonitor/components/balancePressHomeBD.vue

@@ -2,102 +2,96 @@
   <a-spin tip="Loading..." :spinning="loading">
     <div class="monitor-container">
       <div class="lr left-box">
-        <ventBox1>
-          <template #title>
-            <div>均压与低氧参数监测与设置</div>
-          </template>
-          <template #container>
-            <div class="vent-flex-row-between auto-control mt-10px mb-10px">
-              <div class="title">自动调节:</div>
-              <a-radio-group :value="avePressSetting.isAutoControl" name="radioGroup" @change="changeIsAutoControl">
-                <a-radio value="1">关闭</a-radio>
-                <a-radio value="2">开启</a-radio>
-              </a-radio-group>
-            </div>
-            <div class="vent-flex-row-between auto-control mt-10px mb-10px">
-              <div class="title">调节类型:</div>
-              <a-radio-group :value="avePressSetting.controlType" name="radioGroup" @change="changeIsAutoControl">
-                <a-radio value="o2">氧气</a-radio>
-                <a-radio value="pressure">压差</a-radio>
-              </a-radio-group>
-            </div>
-            <div class="input-box">
-              <!-- <div class="divider-line">开始条件</div>
+        <Transition enter-active-class="animate__animated  animate__fadeInLeft" leave-active-class="animate__animated  animate__fadeOutLeft">
+          <ventBox1 v-if="showModules">
+            <template #title>
+              <div>均压与低氧参数监测与设置</div>
+            </template>
+            <template #container>
+              <div class="vent-flex-row-between auto-control mt-10px mb-10px">
+                <div class="title">自动调节:</div>
+                <a-radio-group :value="avePressSetting.isAuto" name="radioGroup" @change="changeAvePressState($event, 'isAuto')">
+                  <a-radio :value="false">关闭</a-radio>
+                  <a-radio :value="true">开启</a-radio>
+                </a-radio-group>
+              </div>
+              <div class="vent-flex-row-between auto-control mt-10px mb-10px">
+                <div class="title">调节类型:</div>
+                <a-radio-group :value="avePressSetting.controlType" name="radioGroup" @change="changeAvePressState($event, 'controlType')">
+                  <a-radio value="o2">氧气</a-radio>
+                  <a-radio value="pressure">压差</a-radio>
+                </a-radio-group>
+              </div>
+              <div>
+                <!-- <div class="divider-line">开始条件</div>
               <div v-for="(item, index) in settingParam1" class="input-item" :key="index">
                 <div class="title">{{ item.title }}:</div>
                 <a-input-number class="input-value" v-model:value="formData[item.code]" placeholder="" />
                 <div class="unit">{{ item.unit }}</div>
               </div> -->
-              <div class="divider-line">调节参数</div>
-              <div v-for="(item, index) in settingParam4" class="input-item" :key="index">
-                <div class="title">{{ item.title }}:</div>
-                <a-input-number class="input-value" v-model:value="avePressSetting[item.code]" placeholder="" :disabled="settingFormDisabled" />
-                <div class="unit">{{ item.unit }}</div>
-              </div>
-              <!-- <div class="divider-line">结束时间</div>
+                <div class="divider-line"></div>
+                <div v-for="(item, index) in settingParam4" class="input-item" :key="index">
+                  <div class="title">{{ item.title }}:</div>
+                  <a-input-number class="input-value" v-model:value="avePressSetting[item.code]" placeholder="" :disabled="settingFormDisabled" />
+                  <div class="unit">&nbsp;{{ item.unit }}</div>
+                </div>
+                <!-- <div class="divider-line">结束时间</div>
               <div v-for="(item, index) in settingParam3" class="input-item" :key="index">
                 <div class="title">{{ item.title }}:</div>
                 <a-input-number class="input-value" v-model:value="formData[item.code]" placeholder="" />
                 <div class="unit">{{ item.unit }}</div>
               </div> -->
-            </div>
-            <div class="btn-box flex" style="text-align: center">
-              <div class="btn btn1 flex-1" @click="editSettingForm">{{ settingFormDisabled ? '编辑' : '取消' }}</div>
-              <div class="btn btn1 flex-1" @click="submitSettingForm">提交</div>
-            </div>
-          </template>
-        </ventBox1>
-      </div>
-      <div style="pointer-events: auto" class="flex mt-10px h-100% w-770px">
-        <ventBox1 class="mr-10px">
-          <template #title>
-            <div>均压工作面风门与风门联动</div>
-          </template>
-          <template #container>
-            <div class="vent-flex-row-between auto-control mt-10px mb-10px">
-              <div class="title">自动调节:</div>
-              <a-radio-group :value="gateLinkage.isAuto" name="radioGroup" @change="changeIsAuto($event, gateLinkage.id)">
-                <a-radio :value="false">关闭</a-radio>
-                <a-radio :value="true">开启</a-radio>
-              </a-radio-group>
-            </div>
-            <div class="btn-box" style="text-align: center">
-              <div class="btn btn1" @click="() => openModal(false, { id: gateLinkage.id })">控制密码修改</div>
-            </div>
-          </template>
-        </ventBox1>
-        <ventBox1>
-          <template #title>
-            <div>均压工作面风机与风门联动</div>
-          </template>
-          <template #container>
-            <div class="vent-flex-row-between auto-control mt-10px mb-10px">
-              <div class="title">自动调节:</div>
-              <a-radio-group :value="avePressLinkage.isAuto" name="radioGroup" @change="changeIsAuto($event, avePressLinkage.id)">
-                <a-radio :value="false">关闭</a-radio>
-                <a-radio :value="true">开启</a-radio>
-              </a-radio-group>
-            </div>
-            <div class="btn-box" style="text-align: center">
-              <div class="btn btn1" @click="() => openModal(false, { id: avePressLinkage.id })">控制密码修改</div>
-            </div>
-          </template>
-        </ventBox1>
+              </div>
+              <div class="btn-box flex" style="text-align: center">
+                <div class="btn btn1 flex-1" @click="editSettingForm">{{ settingFormDisabled ? '编辑' : '取消' }}</div>
+                <div class="btn btn1 flex-1" @click="submitSettingForm">提交</div>
+              </div>
+            </template>
+          </ventBox1>
+        </Transition>
+        <Transition enter-active-class="animate__animated  animate__fadeInLeft" leave-active-class="animate__animated  animate__fadeOutLeft">
+          <ventBox1 v-if="showModules" class="mt-10px">
+            <template #title>
+              <div>均压工作面联动控制</div>
+            </template>
+            <template #container>
+              <div class="vent-flex-row-between auto-control mt-10px mb-10px">
+                <div class="title">风门与风门自动调节:</div>
+                <a-radio-group :value="gateLinkage.isAuto" name="radioGroup" @change="changeIsAuto($event, gateLinkage.id)">
+                  <a-radio :value="false">关闭</a-radio>
+                  <a-radio :value="true">开启</a-radio>
+                </a-radio-group>
+                <div class="btn btn1" @click="() => openModal(false, { id: gateLinkage.id })">密码修改</div>
+              </div>
+              <div class="vent-flex-row-between auto-control mt-10px mb-10px">
+                <div class="title">风机与风门自动调节:</div>
+                <a-radio-group :value="avePressLinkage.isAuto" name="radioGroup" @change="changeIsAuto($event, avePressLinkage.id)">
+                  <a-radio :value="false">关闭</a-radio>
+                  <a-radio :value="true">开启</a-radio>
+                </a-radio-group>
+                <div class="btn btn1" @click="() => openModal(false, { id: avePressLinkage.id })">密码修改</div>
+              </div>
+              <!-- <div class="btn-box" style="text-align: center">
+            </div> -->
+            </template>
+          </ventBox1>
+        </Transition>
       </div>
+
       <ModuleCommon
-        v-for="cfg in configs"
-        :key="cfg.deviceType"
+        v-for="(cfg, index) in configs"
+        :key="`svvmbcb${index}`"
         :show-style="cfg.showStyle"
         :module-data="cfg.moduleData"
         :module-name="cfg.moduleName"
         :device-type="cfg.deviceType"
         :data="selectData"
-        :visible="true"
+        :visible="showModules"
       />
     </div>
     <PasswordModal :modal-is-show="modalVisible" modal-title="提交" @handle-ok="handleResolve" @handle-cancel="handleReject" />
     <UpdatePassword @register="updatePwdRegister" @submit="handleChangePassword" />
-    <BasicModal title="风门状态监测" :mask="false" :bodyStyle="{ height: '50px' }" style="top: 20px" :show-ok-btn="false" @register="warnRegister2">
+    <!-- <BasicModal title="风门状态监测" :mask="false" :bodyStyle="{ height: '50px' }" style="top: 20px" :show-ok-btn="false" @register="warnRegister2">
       {{ warnModalText2 }}
     </BasicModal>
     <BasicModal
@@ -113,22 +107,25 @@
     </BasicModal>
     <BasicModal title="局扇状态监测" :mask="false" :bodyStyle="{ height: '50px' }" style="top: 420px" :show-ok-btn="false" @register="warnRegister3">
       {{ warnModalText3 }}
-    </BasicModal>
+    </BasicModal> -->
+
+    <div class="switch-button icon-goto right-10px top-70px" :class="{ 'right-390px': showModules }" @click="showModules = !showModules"></div>
+    <!-- <div v-else class="switch-button icon-goto right-10px top-70px" @click="showModules = true"></div> -->
   </a-spin>
 </template>
 <script setup lang="ts">
-  import { ref, onMounted, onUnmounted, defineProps } from 'vue';
+  import { ref, onMounted, onUnmounted, defineProps, h } from 'vue';
   import { mountedThree, destroy, setModelType, updateText, play } from '../balancePress.threejs';
   import { list } from '../balancePress.api';
   import ModuleCommon from '../../../home/configurable/components/ModuleCommon.vue';
   import { useInitConfigs } from '../../../home/configurable/hooks/useInit';
   import { useGlobSetting } from '/@/hooks/setting';
   import { settingParam4 } from '../balancePress.data';
-  import { notification } from 'ant-design-vue';
+  import { Modal } from 'ant-design-vue';
   import ventBox1 from '/@/components/vent/ventBox1.vue';
   import PasswordModal from '../../comment/components/PasswordModal.vue';
   import UpdatePassword from '../../comment/components/UpdatePassword.vue';
-  import { BasicModal, useModal } from '/@/components/Modal';
+  import { useModal } from '/@/components/Modal';
   import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
   import { getToken } from '/@/utils/auth';
   import { useUserStore } from '/@/store/modules/user';
@@ -145,6 +142,7 @@
   const { sysOrgCode } = useGlobSetting();
 
   const loading = ref(false);
+  const showModules = ref(true);
 
   // 监测数据
   const selectData = ref();
@@ -216,17 +214,24 @@
     return result;
   }
 
-  const { avePressSetting, avePressLinkage, gateLinkage, formData, getAvePress, changePassword, linkageControl, settingControl, autoControl } =
-    usePressControl();
+  const {
+    avePressSetting,
+    avePressLinkage,
+    gateLinkage,
+    formData,
+    getAvePress,
+    changePassword,
+    linkageControl,
+    settingControl,
+    autoControl,
+    cancelControl,
+  } = usePressControl();
 
   const modalVisible = ref(false);
 
   const { configs, fetchConfigs } = useInitConfigs();
 
   const [updatePwdRegister, { openModal, closeModal, setModalProps }] = useModal();
-  const [warnRegister1, warnModal1] = useModal();
-  const [warnRegister2, warnModal2] = useModal();
-  const [warnRegister3, warnModal3] = useModal();
 
   function handleChangePassword(values) {
     setModalProps({ confirmLoading: true });
@@ -250,14 +255,14 @@
       });
     };
   }
-  function changeIsAutoControl({ target }) {
-    formData.value.isAutoControl = target.value;
+  function changeAvePressState({ target }, key) {
+    formData.value.temp = target.value;
     modalVisible.value = true;
     resolver = (password) => {
       settingControl(
         { password, id: avePressSetting.value.id },
         {
-          isAutoControl: formData.value.isAutoControl,
+          [key]: formData.value.temp,
         }
       ).finally(() => {
         modalVisible.value = false;
@@ -286,9 +291,15 @@
     resolver = null;
   }
 
-  const warnModalText1 = ref('');
-  const warnModalText2 = ref('');
-  const warnModalText3 = ref('');
+  // const [warnRegister1, warnModal1] = useModal();
+  // const [warnRegister2, warnModal2] = useModal();
+  // const [warnRegister3, warnModal3] = useModal();
+  const warnModal1 = ref();
+  const warnModal2 = ref();
+  const warnModal3 = ref();
+  // const warnModalText1 = ref('');
+  // const warnModalText2 = ref('');
+  // const warnModalText3 = ref('');
 
   // 初始化 WebSocket
   function initWebSocket() {
@@ -299,73 +310,88 @@
     const url = `${glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://')}/websocket/${userStore.getUserInfo.id}?token=${token}`;
     connectWebSocket(url);
     onWebSocket((data: any) => {
-      if (data.cmd === 'topic') {
-        if (data.msgTxt) {
-          const { info = '' } = JSON.parse(data.msgTxt);
-          if (info.includes('局扇')) {
-            warnModalText3.value = info;
-            warnModal3.openModal();
-          }
-          if (info.includes('风门')) {
-            warnModalText2.value = info;
-            warnModal2.openModal();
-          }
-          if (info.includes('压差')) {
-            warnModalText1.value = info;
-            warnModal1.openModal();
-          }
-        }
+      if (data.cmd !== 'topic' || data.topic !== 'warn') return;
+      if (!data.msgTxt) return;
+
+      const { info = '', type = '', avgPressLogId, date } = JSON.parse(data.msgTxt);
+      switch (type) {
+        case 'o2':
+          if (warnModal1.value) break;
+          warnModal1.value = Modal.confirm({
+            title: data.msgTitle,
+            content: h('div', { style: { color: '#fff' } }, [h('p', date), h('p', info)]),
+            centered: true,
+            okText: '下发调节指令',
+            mask: true,
+            class: 'balancePress',
+            async onOk() {
+              await autoControl(avgPressLogId);
+              warnModal1.value = null;
+            },
+            async onCancel() {
+              await cancelControl(avgPressLogId);
+              warnModal1.value = null;
+            },
+          });
+          // warnModalText1.value = info;
+          // warnModal1.openModal();
+
+          break;
+        case 'pressure':
+          // warnModalText1.value = info;
+          // warnModal1.openModal();
+          if (warnModal1.value) break;
+          warnModal1.value = Modal.confirm({
+            title: data.msgTitle,
+            content: h('div', { style: { color: '#fff' } }, [h('p', date), h('p', info)]),
+            centered: true,
+            okText: '下发调节指令',
+            mask: true,
+            class: 'balancePress',
+            async onOk() {
+              await autoControl(avgPressLogId);
+              warnModal1.value = null;
+            },
+            async onCancel() {
+              await cancelControl(avgPressLogId);
+              warnModal1.value = null;
+            },
+          });
+
+          break;
+        case 'gate':
+          if (warnModal2.value) break;
+          warnModal2.value = Modal.warn({
+            title: data.msgTitle,
+            content: info,
+            showOkBtn: false,
+            mask: true,
+            class: 'balancePress',
+            onOk: () => {
+              warnModal2.value = null;
+            },
+          });
+          break;
+        case 'fansys':
+          if (warnModal3.value) break;
+          warnModal3.value = Modal.warn({
+            title: data.msgTitle,
+            content: info,
+            showOkBtn: false,
+            mask: true,
+            class: 'balancePress',
+            style: 'top: 700px',
+            onOk: () => {
+              warnModal3.value = null;
+            },
+          });
+
+          break;
+
+        default:
+          break;
       }
     });
-
-    // setInterval(() => {
-    //   const data = [
-    //     {
-    //       cmd: 'topic',
-    //       msgTxt: `{"info":"局扇-我是局扇啊!"}`,
-    //     },
-    //     {
-    //       cmd: 'topic',
-    //       msgTxt: `{"info":"压差-我是压差啊!"}`,
-    //     },
-    //     {
-    //       cmd: 'topic',
-    //       msgTxt: `{"info":"风门-我是风门啊!"}`,
-    //     },
-    //   ][(Math.random() * 3) | 0];
-    //   if (data.cmd === 'topic') {
-    //     if (data.msgTxt) {
-    //       const { info = '' } = JSON.parse(data.msgTxt);
-    //       if (info.includes('局扇')) {
-    //         warnModalText3.value = info;
-    //         warnModal3.openModal();
-    //         // notification.warn({
-    //         //   description: info,
-    //         //   message: '警报!',
-    //         //   duration: 0,
-    //         // });
-    //       }
-    //       if (info.includes('风门')) {
-    //         warnModalText2.value = info;
-    //         warnModal2.openModal();
-    //         // notification.warn({
-    //         //   description: info,
-    //         //   message: '警报!',
-    //         //   duration: 0,
-    //         // });
-    //       }
-    //       if (info.includes('压差')) {
-    //         warnModalText1.value = info;
-    //         warnModal1.openModal();
-    //         // notification.warn({
-    //         //   description: info,
-    //         //   message: '警报!',
-    //         //   duration: 0,
-    //         // });
-    //       }
-    //     }
-    //   }
-    // }, 5000);
   }
 
   const settingFormDisabled = ref(true);
@@ -409,4 +435,33 @@
   .monitor-container {
     margin-top: 60px;
   }
+
+  .switch-button {
+    width: 34px;
+    height: 34px;
+    position: fixed;
+    // right: 5px;
+    // bottom: 300px;
+    z-index: 1000;
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    pointer-events: auto;
+    transition: right 1s;
+  }
+  .icon-goto {
+    --image-monitor-goto: url('/@/assets/images/company/monitor-goto.png');
+    background-image: var(--image-monitor-goto);
+  }
+
+  .divider-line {
+    border-bottom: 1px solid white;
+  }
+</style>
+<style>
+  /* .balancePress .zxm-modal-confirm-title {
+    font-size: 20px;
+  } */
+  .balancePress .zxm-modal-confirm-content {
+    font-size: 22px;
+  }
 </style>

+ 17 - 6
src/views/vent/monitorManager/balancePressMonitor/hooks/useControl.ts

@@ -1,19 +1,19 @@
 import { message } from 'ant-design-vue';
 import { get } from 'lodash-es';
 import { ref } from 'vue';
-import { submitEdit, updatePassword, validPassword, subList2, controlWindow } from '../balancePress.api';
+import { submitEdit, updatePassword, validPassword, subList2, controlWindow, cancelcontrolWindow } from '../balancePress.api';
 
 export function usePressControl() {
   /** 参数与设置、风机风门联动表单数据 */
   const formData = ref({
     /** 风机风门联动的自动调控 */
     isAuto: false,
-    /** 参数与设置的自动调控 */
-    isAutoControl: false,
+    /** 参数与设置的状态暂存字段 */
+    temp: false,
   });
   /** 参数与设置、风机风门联动的数据 */
   const avePressLinkage = ref<any>({ isAuto: false });
-  const avePressSetting = ref<any>({ isAutoControl: false });
+  const avePressSetting = ref<any>({ isAuto: false });
   /** 风门与风门联动控制 */
   const gateLinkage = ref<any>({ isAuto: false });
 
@@ -106,8 +106,18 @@ export function usePressControl() {
       });
   }
 
-  function autoControl() {
-    return controlWindow({ id: avePressSetting.value.id })
+  function autoControl(avgPressLogId) {
+    return controlWindow({ avgPressId: avePressSetting.value.id, avgPressLogId })
+      .then(() => {
+        message.success('下发成功');
+      })
+      .catch(() => {
+        message.error('下发失败');
+      });
+  }
+
+  function cancelControl(avgPressLogId) {
+    return cancelcontrolWindow({ avgPressId: avePressSetting.value.id, avgPressLogId })
       .then(() => {
         message.success('下发成功');
       })
@@ -122,6 +132,7 @@ export function usePressControl() {
     changePassword,
     getAvePress,
     autoControl,
+    cancelControl,
     avePressLinkage,
     avePressSetting,
     gateLinkage,