Kaynağa Gözat

[Feat 0000] 瓦斯泵站动画调整及对接

houzekong 5 gün önce
ebeveyn
işleme
96a0742fd0

+ 0 - 2
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHistory.vue

@@ -4,9 +4,7 @@
   </div>
 </template>
 <script setup lang="ts">
-  import { ref } from 'vue';
   import HistoryTable from '../../comment/HistoryTable.vue';
-  import { getTableList } from '../gasPump.api';
 
   const props = defineProps({
     deviceType: {

+ 1 - 1
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHome.vue

@@ -216,7 +216,7 @@
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted, onUnmounted, reactive, watch, inject, nextTick, onBeforeUnmount } from 'vue';
+  import { ref, onMounted, onUnmounted, watch, inject, nextTick, onBeforeUnmount } from 'vue';
   import ventBox1 from '/@/components/vent/ventBox1.vue';
   import { setModelType, playAnimate } from '../gasPump.threejs';
   import ListItem from '@/views/vent/gas/components/list/listItem.vue';

+ 16 - 13
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeBet.vue

@@ -12,7 +12,10 @@
         </fourBorderBg>
       </div> -->
     </div>
-    <!-- 布尔台新瓦斯泵模型上的数据 -->
+    <!--
+      布尔台瓦斯泵模型上的数据提示框(出气阀1#、进气阀2#、出水阀1#、进水阀2# 等 8 个小方框)已按要求隐藏。
+      当前流动效果改为直接跟随瓦斯泵磁力启动器/变频器运行状态,不再依赖阀门点位,
+      因此这些标签既无数据来源也无展示必要;保留代码以便后续需要时恢复。
     <div class="elementContent" style="position: absolute; display: none">
       <div v-for="(tag, index) in modelMonitorTags" :key="index" :id="tag.domId" class="modal-monitor-box">
         <div class="title">{{ tag.title }}</div>
@@ -24,6 +27,7 @@
         <div v-else class="value">{{ selectData[tag.code] }}</div>
       </div>
     </div>
+    -->
     <div v-if="selectData['netStatus'] == 0" class="device-state">网络断开</div>
     <div class="lr left-box">
       <div class="left-container">
@@ -159,11 +163,11 @@
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted, onUnmounted, watch, inject, nextTick, onBeforeUnmount } from 'vue';
+  import { ref, onMounted, onUnmounted, watch, inject, onBeforeUnmount } from 'vue';
   import ventBox1 from '/@/components/vent/ventBox1.vue';
-  import { setModelType, playAnimate } from '../gasPump.threejs';
+  import { playAnimate, setRunSignals } from '../gasPump.threejs';
   import ListItem from '@/views/vent/gas/components/list/listItem.vue';
-  import { getModelMonitorTags, devicePropertyType, getMonitorData } from '../gasPump.data';
+  import { getModelMonitorTags, devicePropertyType, getMonitorData, getPumpRunSignals } from '../gasPump.data';
   import { list } from '../gasPump.api';
   import { SvgIcon } from '/@/components/Icon';
   import { formatNum } from '/@/utils/ventutil';
@@ -340,17 +344,16 @@
 
   watch(
     () => props.deviceType,
-    () => {
+    async (val) => {
       removeCamera(playerRef);
-      getMonitorData(props.deviceType).then((data) => {
-        deviceProperty.value = data;
+      const data = await getMonitorData(val);
+      deviceProperty.value = data as any;
 
-        // if (props.deviceType == 'pump_over') {
-        //   setModelType('gasPump');
-        // } else if (props.deviceType?.startsWith('pump_under') || props.deviceType == 'pump_n12m2pq') {
-        //   setModelType('gasPumpUnder');
-        // }
-      });
+      if (!val) return;
+      const signals = await getPumpRunSignals(val);
+      // 两个泵站的瓦斯泵运行信号点位不同(新站变频器状态 / 老站磁力启动器断路器状态),
+      // 必须按 deviceType 注入,否则管道流动会跟错泵。
+      setRunSignals(signals);
     }
   );
   watch(

+ 1 - 1
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeCC.vue

@@ -195,7 +195,7 @@
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted, onUnmounted, reactive, watch, inject, nextTick, onBeforeUnmount } from 'vue';
+  import { ref, onMounted, onUnmounted, watch, inject, nextTick, onBeforeUnmount } from 'vue';
   import ventBox1 from '/@/components/vent/ventBox1.vue';
   import { setModelType, playAnimate } from '../gasPump.threejs';
   import { getMonitorData, devicePropertyType, getModelMonitorTags } from '../gasPump.data';

+ 15 - 7
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeCopy.vue

@@ -12,7 +12,10 @@
 </fourBorderBg>
 </div> -->
     </div>
-    <!-- 布尔台新瓦斯泵模型上的数据 -->
+    <!--
+      布尔台瓦斯泵模型上的数据提示框(出气阀1#、进气阀2#、出水阀1#、进水阀2# 等 8 个小方框)已按要求隐藏。
+      当前流动效果改为直接跟随瓦斯泵磁力启动器/变频器运行状态,不再依赖阀门点位,
+      因此这些标签既无数据来源也无展示必要;保留代码以便后续需要时恢复。
     <div class="elementContent" style="position: absolute; display: none">
       <div v-for="(tag, index) in modelMonitorTags" :key="index" :id="tag.domId" class="modal-monitor-box">
         <div class="title">{{ tag.title }}</div>
@@ -25,6 +28,7 @@
         <div v-else class="value">{{ selectData[tag.code] }}</div>
       </div>
     </div>
+    -->
     <div v-if="selectData['netStatus'] == 0" class="device-state">网络断开</div>
 
     <!-- 可配置模块 -->
@@ -53,11 +57,11 @@
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted, onUnmounted, reactive, watch, inject, nextTick, onBeforeUnmount, computed } from 'vue';
+  import { ref, onMounted, onUnmounted, watch, inject, nextTick, computed } from 'vue';
   // import ventBox1 from '/@/components/vent/ventBox1.vue';
-  import { setModelType, playAnimate } from '../gasPump.threejs';
+  import { setModelType, playAnimate, setRunSignals } from '../gasPump.threejs';
   // import ListItem from '@/views/vent/gas/components/list/listItem.vue';
-  import { getModelMonitorTags } from '../gasPump.data';
+  import { getModelMonitorTags, getPumpRunSignals } from '../gasPump.data';
   import { list } from '../gasPump.api';
   import { deviceControlApi } from '/@/api/vent/index';
   import PasswordModal from '../../comment/components/PasswordModal.vue';
@@ -208,14 +212,18 @@
 
   watch(
     () => props.deviceType,
-    () => {
+    (val) => {
       // removeCamera();
       nextTick(async () => {
-        if (props.deviceType == 'pump_over') {
+        if (val == 'pump_over') {
           setModelType('gasPump');
-        } else if (props.deviceType?.startsWith('pump_under') || props.deviceType == 'pump_n12m2pq') {
+        } else if (val?.startsWith('pump_under') || val == 'pump_n12m2pq') {
           setModelType('gasPumpUnder');
         }
+        if (!val) return;
+        const signals = await getPumpRunSignals(val);
+        // 按站型注入瓦斯泵运行信号,驱动管道流动动画
+        setRunSignals(signals);
       });
     }
   );

+ 0 - 1
src/views/vent/monitorManager/gasPumpMonitor/gasPump.api.ts

@@ -1,5 +1,4 @@
 import { defHttp } from '/@/utils/http/axios';
-import { Modal } from 'ant-design-vue';
 
 enum Api {
   list = '/monitor/device',

+ 13 - 0
src/views/vent/monitorManager/gasPumpMonitor/gasPump.data.bet.ts

@@ -1,3 +1,16 @@
+/**
+ * 【模型管流动画触发信号】布尔台老站 pump_under。
+ *
+ * 该站以「瓦斯泵磁力启动器」的断路器状态判定瓦斯泵是否运行,泵运行时其进气/出气/进水/排水
+ * 四路管道全部流动。1# 泵 = 场景左侧管,2# 泵 = 场景右侧管。
+ *
+ * 实测报文:Starter5_CBStatus=1、Starter5_Ia=119A(1# 运行);Starter6_CBStatus=0、Ia=0(2# 停止)。
+ */
+export const pumpRunSignals = {
+  1: { code: 'Starter5_CBStatus' },
+  2: { code: 'Starter6_CBStatus' },
+};
+
 export const leftMonitor = [
   {
     type: 'list',

+ 14 - 0
src/views/vent/monitorManager/gasPumpMonitor/gasPump.data.bet2.ts

@@ -1,3 +1,17 @@
+/**
+ * 【模型管流动画触发信号】布尔台新站 pump_22m2pq。
+ *
+ * 该站瓦斯泵由变频器驱动,没有磁力启动器的 CBStatus 点,因此用变频器运行状态判定;
+ * 泵运行时其进气/出气/进水/排水四路管道全部流动。1# 泵 = 场景左侧管,2# 泵 = 场景右侧管。
+ *
+ * 实测报文:CentrifugalPump1_VFD_Status=1、Ia=180A(1# 运行);CentrifugalPump2_VFD_Status=0、Ia=0(2# 停止)。
+ * 备用等价信号:CentrifugalPump<n>_VFD_RunningReturn(同为 1 表示运行)。
+ */
+export const pumpRunSignals = {
+  1: { code: 'CentrifugalPump1_VFD_Status' },
+  2: { code: 'CentrifugalPump2_VFD_Status' },
+};
+
 export const leftMonitor = [
   {
     type: 'list',

+ 21 - 1
src/views/vent/monitorManager/gasPumpMonitor/gasPump.data.ts

@@ -1,6 +1,5 @@
 import { reactive, defineAsyncComponent } from 'vue';
 import { useGlobSetting } from '/@/hooks/setting';
-import { Interface } from 'readline';
 
 export const warningConfig = reactive({
   header: ['设备名称', '预警信息', '时间'],
@@ -526,6 +525,27 @@ export function getComponent() {
   }
 }
 
+/**
+ * 按站型取「瓦斯泵运行信号」表(泵号 → 运行状态点位),用于驱动管道流动动画。
+ *
+ * 两个布尔台泵站的运行信号点位完全不同,绝不能互相借用:
+ *   - pump_22m2pq(新站):瓦斯泵由变频器驱动,用 CentrifugalPump<n>_VFD_Status
+ *   - pump_under (老站):用瓦斯泵磁力启动器 Starter5_/Starter6_ 的断路器状态
+ *
+ * 返回 null 表示该站型暂不支持泵状态驱动动画(调用方据此不点亮任何箭头)。
+ */
+export async function getPumpRunSignals(deviceType: string) {
+  const { sysOrgCode } = useGlobSetting();
+  if (sysOrgCode !== 'sdmtjtbetmk') return null;
+  if (deviceType == 'pump_22m2pq') {
+    return (await import('./gasPump.data.bet2')).pumpRunSignals;
+  }
+  if (deviceType?.startsWith('pump_under')) {
+    return (await import('./gasPump.data.bet')).pumpRunSignals;
+  }
+  return null;
+}
+
 export async function getMonitorData(deviceType) {
   const { sysOrgCode } = useGlobSetting();
   // const sysOrgCode = 'sdmtjtcctmk';

+ 18 - 6
src/views/vent/monitorManager/gasPumpMonitor/gasPump.threejs.ts

@@ -2,7 +2,7 @@ import * as THREE from 'three';
 import UseThree from '../../../../utils/threejs/useThree';
 import gasPumpBase from './gasPump.threejs.over';
 import gasPumpUnder from './gasPump.threejs.under';
-import { animateCamera, setModalCenter } from '/@/utils/threejs/util';
+import { animateCamera } from '/@/utils/threejs/util';
 import useEvent from '../../../../utils/threejs/useEvent';
 
 // 模型对象、 文字对象
@@ -17,7 +17,7 @@ const { mouseDownFn } = useEvent();
 // 鼠标点击事件
 const mouseEvent = (event) => {
   if (event.button == 0) {
-    mouseDownFn(<UseThree>model, <THREE.Object3D>group, event, (intersects) => {
+    mouseDownFn(<UseThree>model, <THREE.Object3D>group, event, () => {
       if (gasPumpType === 'gasPump') {
         // gasPumpBaseObj.mousedownModel.call(gasPumpBaseObj, intersects);
       }
@@ -36,7 +36,15 @@ export const playAnimate = (monitorData: any) => {
   }
 };
 
-export const addgasPumpText = (selectData) => {
+/**
+ * 注入泵运行信号表(泵号 → 运行状态点位),用于驱动管道流动动画。
+ * 不同泵站的运行信号点位不同,必须由页面按 deviceType 传入。
+ */
+export const setRunSignals = (signals: Record<number, { code: string }> | null) => {
+  gasPumpUnderObj?.setRunSignals(signals);
+};
+
+export const addgasPumpText = () => {
   if (gasPumpType === 'gasPump') {
     // return gasPumpBaseObj.addgasPumpText.call(gasPumpBaseObj, selectData);
   }
@@ -51,10 +59,12 @@ export const setModelType = (type) => {
         model.scene.remove(gasPumpUnderObj.group);
       }
       group = gasPumpBaseObj.group;
+      // 用局部常量承接,保证 setTimeout 回调里类型已收窄(group 是可变模块变量,回调内无法保持收窄)
+      const baseGroup = gasPumpBaseObj.group;
       // model.isRender = false;
       const oldCameraPosition = { x: 15.9074, y: 5.40264, z: 27.12551 };
       setTimeout(async () => {
-        model?.scene?.add(group);
+        model?.scene?.add(baseGroup);
         await animateCamera(
           oldCameraPosition,
           { x: 0.544, y: 0.3335, z: 0.29222 },
@@ -73,10 +83,12 @@ export const setModelType = (type) => {
       }
       gasPumpUnderObj.addCssText();
       group = gasPumpUnderObj.group;
+      // 用局部常量承接,保证 setTimeout 回调里类型已收窄
+      const underGroup = gasPumpUnderObj.group;
       // model.isRender = true;
       const oldCameraPosition = { x: 15.9074, y: 5.40264, z: 27.12551 };
       setTimeout(async () => {
-        model?.scene?.add(group);
+        model?.scene?.add(underGroup);
         await animateCamera(
           oldCameraPosition,
           { x: 0.544, y: 0.3335, z: 0.29222 },
@@ -96,7 +108,7 @@ export const mountedThree = () => {
   return new Promise(async (resolve) => {
     model = new UseThree('#gasPump3D', '#gas3DCSS');
     model.setEnvMap('test2.hdr');
-    model.renderer.toneMappingExposure = 1.0;
+    if (model.renderer) model.renderer.toneMappingExposure = 1.0;
     // model.renderer.outputEncoding = THREE.sRGBEncoding;
     gasPumpBaseObj = new gasPumpBase(model);
     await gasPumpBaseObj.mountedThree();

+ 57 - 75
src/views/vent/monitorManager/gasPumpMonitor/gasPump.threejs.under.ts

@@ -1,5 +1,5 @@
 import * as THREE from 'three';
-import { CSS3DObject, CSS3DSprite } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
+import { CSS3DSprite } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
 import { getModelMonitorTags } from './gasPump.data';
 import ArrowFlow from '../../comment/threejs/ArrowFlow';
 // import * as dat from 'dat.gui';
@@ -91,89 +91,71 @@ class gasPumpUnder {
     }
   };
 
-  /** 根据各个泵的状态控制动画 */
-  handleAnimation(monitorData?: any) {
-    if (!monitorData) return;
+  /**
+   * 【核心不变式】泵号 → 该泵所接的管道箭头。左右分配只在这里写一次。
+   *
+   * 1# 瓦斯泵 = 场景左侧管(A 组,x≈-9.3,管号与泵号一致)
+   * 2# 瓦斯泵 = 场景右侧管(B+R 组,x≈-5.5)
+   *
+   * 现场若与上述左右相反,只需调换本表两行,几何与动画代码一律不动。
+   */
+  private readonly pumpArrows = {
+    1: ['airInA', 'airOutA', 'waterInA', 'waterOutA'],
+    2: ['airInB', 'airInR', 'airOutB', 'airOutR', 'waterInB', 'waterInR', 'waterOutB', 'waterOutR'],
+  } as const;
 
-    this.airInA?.hideElement();
-    this.airInB?.hideElement();
-    this.airInR?.hideElement();
-    this.airInL?.hideElement();
-    this.airOutA?.hideElement();
-    this.airOutB?.hideElement();
-    this.airOutR?.hideElement();
-    this.airOutL?.hideElement();
-    this.waterInA?.hideElement();
-    this.waterInB?.hideElement();
-    this.waterInR?.hideElement();
-    this.waterInL?.hideElement();
-    this.waterOutA?.hideElement();
-    this.waterOutB?.hideElement();
-    this.waterOutR?.hideElement();
-    this.waterOutL?.hideElement();
-    // 进气动画控制
-    const jqf1Open = this.modelMonitorTags.find((e) => e.domId === 'jqf1' && parseInt(monitorData[e.code]) > 0);
-    const jqf2Open = this.modelMonitorTags.find((e) => e.domId === 'jqf2' && parseInt(monitorData[e.code]) > 0);
+  /**
+   * 泵运行信号表:泵号 → 该泵的运行状态点位。
+   * 由页面按站型注入(布尔台新站用变频器状态、老站用磁力启动器断路器状态)。
+   * 未注入时不点亮任何箭头,避免误判。
+   */
+  runSignals: Record<number, { code: string }> | null = null;
 
-    if (jqf1Open && jqf2Open) {
-      this.airInB?.showElement();
-      this.airInR?.showElement();
-      this.airInL?.showElement();
-    } else if (jqf1Open) {
-      this.airInB?.showElement();
-      this.airInR?.showElement();
-    } else if (jqf2Open) {
-      this.airInA?.showElement();
-      this.airInL?.showElement();
-    }
+  setRunSignals(signals: Record<number, { code: string }> | null) {
+    this.runSignals = signals;
+  }
 
-    // 出气动画控制
-    const cqf1Open = this.modelMonitorTags.find((e) => e.domId === 'cqf1' && parseInt(monitorData[e.code]) > 0);
-    const cqf2Open = this.modelMonitorTags.find((e) => e.domId === 'cqf2' && parseInt(monitorData[e.code]) > 0);
+  /**
+   * 判断某台泵是否运行。
+   *
+   * 已注入 runSignals 时(布尔台两站)按泵运行状态判定;
+   * 未注入时(寸草塔1/2、保德等未接入该机制的站型)保持历史上的阀门口径回落,
+   * 避免这些站的箭头因本次改动而全部不再流动。
+   */
+  private isPumpRunning(data: any, pumpNo: number): boolean {
+    if (!data) return false;
 
-    if (cqf1Open && cqf2Open) {
-      this.airOutB?.showElement();
-      this.airOutR?.showElement();
-      this.airOutL?.showElement();
-    } else if (cqf1Open) {
-      this.airOutB?.showElement();
-      this.airOutR?.showElement();
-    } else if (cqf2Open) {
-      this.airOutA?.showElement();
-      this.airOutL?.showElement();
+    const code = this.runSignals?.[pumpNo]?.code;
+    if (code) {
+      const raw = data[code];
+      if (raw === undefined || raw === null || raw === '') return false;
+      const value = Number(raw);
+      return Number.isFinite(value) && value === 1;
     }
 
-    // 进水动画控制
-    const jsf1Open = this.modelMonitorTags.find((e) => e.domId === 'jsf1' && parseInt(monitorData[e.code]) == 1);
-    const jsf2Open = this.modelMonitorTags.find((e) => e.domId === 'jsf2' && parseInt(monitorData[e.code]) == 1);
+    // 回落到旧的阀门开度口径:该泵的任一进气/出气阀门开启即认为有流动
+    const valvePrefixes = pumpNo === 1 ? ['jqf1', 'cqf1'] : ['jqf2', 'cqf2'];
+    return valvePrefixes.some((domId) => {
+      const tag = this.modelMonitorTags.find((e) => e.domId === domId);
+      if (!tag) return false;
+      const value = Number(data[tag.code]);
+      return Number.isFinite(value) && value > 0;
+    });
+  }
 
-    if (jsf1Open && jsf2Open) {
-      this.waterInB?.showElement();
-      this.waterInR?.showElement();
-      this.waterInL?.showElement();
-    } else if (jsf1Open) {
-      this.waterInB?.showElement();
-      this.waterInR?.showElement();
-    } else if (jsf2Open) {
-      this.waterInA?.showElement();
-      this.waterInL?.showElement();
-    }
+  /** 根据各泵运行状态控制动画:泵运行时该泵所接的水、气四路管道全部流动 */
+  handleAnimation(monitorData?: any) {
+    if (!monitorData) return;
 
-    // 出水动画控制
-    const csf1Open = this.modelMonitorTags.find((e) => e.domId === 'csf1' && parseInt(monitorData[e.code]) == 1);
-    const csf2Open = this.modelMonitorTags.find((e) => e.domId === 'csf2' && parseInt(monitorData[e.code]) == 1);
+    // 先全部隐藏,后续只点亮运行中泵所接的管路
+    Object.values(this.pumpArrows).forEach((names) => {
+      names.forEach((name) => this[name]?.hideElement());
+    });
 
-    if (csf1Open && csf2Open) {
-      this.waterOutB?.showElement();
-      this.waterOutR?.showElement();
-      this.waterOutL?.showElement();
-    } else if (csf1Open) {
-      this.waterOutB?.showElement();
-      this.waterOutR?.showElement();
-    } else if (csf2Open) {
-      this.waterOutA?.showElement();
-      this.waterOutL?.showElement();
-    }
+    ([1, 2] as const).forEach((pumpNo) => {
+      if (!this.isPumpRunning(monitorData, pumpNo)) return;
+      this.pumpArrows[pumpNo].forEach((name) => this[name]?.showElement());
+    });
   }
 
   clearCssText = () => {

+ 1 - 1
src/views/vent/monitorManager/gasPumpMonitor/index-copy.vue

@@ -59,7 +59,7 @@
 
 <script setup lang="ts">
   import customHeader from '/@/components/vent/customHeader.vue';
-  import { onBeforeMount, ref, onMounted, onUnmounted, reactive, toRaw } from 'vue';
+  import { ref, onMounted, onUnmounted, reactive, toRaw } from 'vue';
   import { list } from './gasPump.api';
   import BottomMenu from '/@/views/vent/comment/components/bottomMenu.vue';
   import { getComponent } from './gasPump.data';

+ 1 - 1
src/views/vent/monitorManager/gasPumpMonitor/index.vue

@@ -59,7 +59,7 @@
 
 <script setup lang="ts">
   import customHeader from '/@/components/vent/customHeader.vue';
-  import { onBeforeMount, ref, onMounted, onUnmounted, reactive, toRaw } from 'vue';
+  import { ref, onMounted, onUnmounted, reactive, toRaw } from 'vue';
   import { list } from './gasPump.api';
   import BottomMenu from '/@/views/vent/comment/components/bottomMenu.vue';
   import { getComponent } from './gasPump.data';