Browse Source

[Feat 0000] 瓦斯抽采泵二维模型对接

houzekong 2 days ago
parent
commit
863327b705

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

@@ -242,6 +242,8 @@
   import { useCamera } from '/@/hooks/system/useCamera';
 
   const globalConfig = inject('globalConfig');
+  /** 二维模型的动画入口(页面 provide;三维模式下 modelRef 为空,调用即 no-op) */
+  const animate2D = inject<((data?: any) => void) | null>('animateGasPump2D', null);
 
   const props = defineProps({
     deviceId: {
@@ -299,6 +301,7 @@
               const data = await getDataSource(props.deviceId);
               selectData.value = data;
               playAnimate(data);
+              animate2D?.(data); // 二维模型:同一份监测数据
               // Object.assign(selectData, data);
             }
             if (timer) {

+ 3 - 0
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeBD.vue

@@ -69,6 +69,8 @@
   const { configs: rawConfigs, fetchConfigs } = useInitConfigs();
 
   const globalConfig = inject<any>('globalConfig');
+  /** 二维模型的动画入口(页面 provide;三维模式下 modelRef 为空,调用即 no-op) */
+  const animate2D = inject<((data?: any) => void) | null>('animateGasPump2D', null);
 
   const props = defineProps<{ deviceId: string; deviceType: string }>();
   // const [register, { openModal }] = useModal();
@@ -93,6 +95,7 @@
             const data = await getDataSource();
             selectData.value = data;
             playAnimate(data);
+            animate2D?.(data); // 二维模型:同一份监测数据
             // Object.assign(selectData, data);
             if (timer) {
               timer = null;

+ 3 - 0
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeBet.vue

@@ -180,6 +180,8 @@
   import { get } from 'lodash-es';
 
   const globalConfig = inject('globalConfig');
+  /** 二维模型的动画入口(页面 provide;三维模式下 modelRef 为空,调用即 no-op) */
+  const animate2D = inject<((data?: any) => void) | null>('animateGasPump2D', null);
 
   const props = defineProps({
     deviceId: {
@@ -243,6 +245,7 @@
               const data = await getDataSource(props.deviceId);
               selectData.value = data;
               playAnimate(data);
+              animate2D?.(data); // 二维模型:同一份监测数据
               // Object.assign(selectData, data);
             }
             if (timer) {

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

@@ -213,6 +213,8 @@
   import ListItem from '@/views/vent/gas/components/list/listItem.vue';
 
   const globalConfig = inject('globalConfig');
+  /** 二维模型的动画入口(页面 provide;三维模式下 modelRef 为空,调用即 no-op) */
+  const animate2D = inject<((data?: any) => void) | null>('animateGasPump2D', null);
 
   const props = defineProps({
     deviceId: {
@@ -254,6 +256,7 @@
               const data = await getDataSource(props.deviceId);
               selectData.value = data;
               playAnimate(data);
+              animate2D?.(data); // 二维模型:同一份监测数据
             }
             if (timer) {
               timer = null;

+ 3 - 0
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeCopy.vue

@@ -73,6 +73,8 @@
   import { set } from 'lodash-es';
 
   const globalConfig = inject<any>('globalConfig');
+  /** 二维模型的动画入口(页面 provide;三维模式下 modelRef 为空,调用即 no-op) */
+  const animate2D = inject<((data?: any) => void) | null>('animateGasPump2D', null);
 
   const props = defineProps({
     deviceId: {
@@ -113,6 +115,7 @@
               const data = await getDataSource();
               selectData.value = data;
               playAnimate(data);
+              animate2D?.(data); // 二维模型:同一份监测数据
               // Object.assign(selectData, data);
             }
             if (timer) {

File diff suppressed because it is too large
+ 4334 - 0
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpSVG.vue


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

@@ -590,3 +590,72 @@ export interface devicePropertyType {
   children: deviceChildType[];
   list: propertyListType[];
 }
+
+/** 二维 SVG 模型组件缓存(用于切换模型时不闪烁) */
+const componentsCaches = new Map<string, any>();
+
+/**
+ * 获取瓦斯抽采泵模型组件
+ *
+ * @param is2DModel 是否为二维模型;三维模型由 index.vue 的 mountedThree 负责,此处仅返回二维组件
+ * @param type 站型(页面 dataSource 里的 deviceType,如 pump_over / pump_under / pump_22m2pq)
+ */
+export function getModelComponent(is2DModel: boolean = false, type: string = '') {
+  if (!is2DModel) return null;
+
+  const getComponent = (name) => {
+    if (!componentsCaches.has(name)) {
+      componentsCaches.set(name, import(`./components/${name}.vue`));
+    }
+    return componentsCaches.get(name);
+  };
+
+  // @ts-ignore
+  return defineAsyncComponent(() => {
+    switch (type) {
+      // case 'pump_over':
+      // case 'pump_under':
+      // 目前地上/井下共用同一套二维场景,将来要分开时按站型指到不同组件即可
+      default:
+        return getComponent('gasPumpSVG');
+    }
+  });
+}
+
+/**
+ * 判断某台泵是否运行(与三维 gasPump.threejs.under.ts 的 isPumpRunning 同一套口径)
+ *
+ * 已注入 runSignals 时(布尔台两站)按泵运行状态点位判定:Number(data[code]) === 1;
+ * 未注入时(寸草塔1/2、保德等未接入该机制的站型)回落到进气/出气阀门开度,
+ * 避免这些站的流动动画因缺少运行点位而全部不动。
+ *
+ * @param data 子组件轮询得到的监测数据(与传给三维 playAnimate 的同一份)
+ * @param pumpNo 泵号(1 / 2)
+ * @param runSignals 该站的"泵号 → 运行点位"表,null 表示未接入
+ * @param tags 回落口径用的标签表(getModelMonitorTags() 的返回值)
+ */
+export function isPumpRunning(
+  data: any,
+  pumpNo: number,
+  runSignals: Record<number, { code: string }> | null,
+  tags: { domId: string; code: string }[]
+): boolean {
+  if (!data) return false;
+
+  const code = 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 valvePrefixes = pumpNo === 1 ? ['jqf1', 'cqf1'] : ['jqf2', 'cqf2'];
+  return valvePrefixes.some((domId) => {
+    const tag = tags?.find((e: any) => e.domId === domId);
+    if (!tag) return false;
+    const value = Number(data[tag.code]);
+    return Number.isFinite(value) && value > 0;
+  });
+}

+ 3 - 24
src/views/vent/monitorManager/gasPumpMonitor/gasPump.threejs.under.ts

@@ -1,6 +1,6 @@
 import * as THREE from 'three';
 import { CSS3DSprite } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
-import { getModelMonitorTags } from './gasPump.data';
+import { getModelMonitorTags, isPumpRunning } from './gasPump.data';
 import ArrowFlow from '../../comment/threejs/ArrowFlow';
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
@@ -117,31 +117,10 @@ class gasPumpUnder {
   }
 
   /**
-   * 判断某台泵是否运行。
-   *
-   * 已注入 runSignals 时(布尔台两站)按泵运行状态判定;
-   * 未注入时(寸草塔1/2、保德等未接入该机制的站型)保持历史上的阀门口径回落,
-   * 避免这些站的箭头因本次改动而全部不再流动。
+   * 判断某台泵是否运行:口径抽到 gasPump.data.ts 的 isPumpRunning,二维模型共用同一份判定。
    */
   private isPumpRunning(data: any, pumpNo: number): boolean {
-    if (!data) return false;
-
-    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 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;
-    });
+    return isPumpRunning(data, pumpNo, this.runSignals, this.modelMonitorTags);
   }
 
   /** 根据各泵运行状态控制动画:泵运行时该泵所接的水、气四路管道全部流动 */

+ 48 - 11
src/views/vent/monitorManager/gasPumpMonitor/index.vue

@@ -1,10 +1,18 @@
 <template>
   <div class="bg" style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden">
     <a-spin :spinning="loading" />
-    <div id="gasPump3D" v-show="activeKey == 'monitor'" style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
+    <!-- 二维 SVG 模型(瓦斯抽采泵站,按泵运行状态点亮管路) -->
+    <component v-if="globalConfig?.is2DModel" ref="modelRef" :is="modelComponent" :device-type="currentDeviceType" style="z-index: 2" />
+    <!-- 三维模型容器(由 index.vue 的 mountedThree 初始化) -->
+    <div v-else id="gasPump3D" v-show="activeKey == 'monitor'" style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
     <div
       id="gas3DCSS"
-      v-show="activeKey == 'monitor' && !loading && (currentDeviceType.startsWith('pump_under') || currentDeviceType == 'pump_n12m2pq')"
+      v-show="
+        !globalConfig?.is2DModel &&
+        activeKey == 'monitor' &&
+        !loading &&
+        (currentDeviceType.startsWith('pump_under') || currentDeviceType == 'pump_n12m2pq')
+      "
       style="width: 100%; height: 100%; top: 0; left: 0; position: absolute; overflow: hidden; pointer-events: none"
     >
     </div>
@@ -59,10 +67,10 @@
 
 <script setup lang="ts">
   import customHeader from '/@/components/vent/customHeader.vue';
-  import { ref, onMounted, onUnmounted, reactive, toRaw } from 'vue';
+  import { ref, onMounted, onUnmounted, reactive, toRaw, inject, shallowRef, provide } from 'vue';
   import { list } from './gasPump.api';
   import BottomMenu from '/@/views/vent/comment/components/bottomMenu.vue';
-  import { getComponent } from './gasPump.data';
+  import { getComponent, getModelComponent } from './gasPump.data';
   import gasPumpHistory from './components/gasPumpHistory.vue';
   import gasPumpHandleHistoryVue from './components/gasPumpHandleHistory.vue';
   import gasPumpAlarmHistory from './components/gasPumpAlarmHistory.vue';
@@ -75,6 +83,20 @@
   const activeKey = ref('monitor');
   const loading = ref(false);
 
+  /** 全局配置(is2DModel 决定二维 / 三维模型) */
+  const globalConfig: any = inject('globalConfig');
+  /** 二维模型容器(三维由 mountedThree 负责,此处仅二维有值) */
+  const modelRef = ref();
+  // 注意:站型 currentDeviceType 在下面才声明,这里先用默认场景,选中站型后由 getSelectRow 刷新
+  const modelComponent = shallowRef(getModelComponent(globalConfig?.is2DModel));
+
+  /**
+   * 二维模型的动画入口,供子组件(gasPumpHome*)在轮询里调用:
+   * 子组件那边就是 animate2D(data) —— 与三维 playAnimate(data) 用同一份监测数据。
+   * 三维模式下 modelRef 为空,这里自然 no-op。
+   */
+  provide('animateGasPump2D', (data: any) => modelRef.value?.animate?.(data));
+
   const historyTable = ref();
   const alarmHistoryTable = ref();
   const handlerHistoryTable = ref();
@@ -98,7 +120,7 @@
   });
 
   function changeActive(activeValue) {
-    if (activeKey.value == 'monitor') {
+    if (activeKey.value == 'monitor' && !globalConfig?.is2DModel) {
       if (currentDeviceType.value == 'pump_over') {
         setModelType('gasPump');
       } else if (currentDeviceType.value.startsWith('pump_under')) {
@@ -171,18 +193,31 @@
       optionValue.value = currentData['deviceID'];
       currentDeviceType.value = currentData['deviceType'];
       Object.assign(selectData, currentData);
-      if (currentDeviceType.value == 'pump_over') {
-        setModelType('gasPump');
-      } else if (currentDeviceType.value.startsWith('pump_under')) {
-        setModelType('gasPumpUnder');
+      if (globalConfig?.is2DModel) {
+        // 二维:换站型时切到对应场景(当前地上/井下共用一套),并立刻刷新一次流动状态
+        // 换站型时切到对应场景(当前地上/井下共用一套),动画由子组件轮询驱动
+        modelComponent.value = getModelComponent(true, currentDeviceType.value);
       } else {
-        setModelType('gasPumpUnder');
+        if (currentDeviceType.value == 'pump_over') {
+          setModelType('gasPump');
+        } else if (currentDeviceType.value.startsWith('pump_under')) {
+          setModelType('gasPumpUnder');
+        } else {
+          setModelType('gasPumpUnder');
+        }
       }
     }
   }
 
   onMounted(async () => {
     if (currentRoute.value && currentRoute.value['query'] && currentRoute.value['query']['id']) optionValue.value = currentRoute.value['query']['id'];
+    // 二维模式:不初始化三维,只加载数据;动画由子组件(gasPumpHome*)轮询时调 animate2D(data) 驱动
+    if (globalConfig?.is2DModel) {
+      await getSysDataSource();
+      await getDeviceList();
+      getSelectRow(optionValue.value);
+      return;
+    }
     mountedThree().then(async () => {
       await getSysDataSource();
       await getDeviceList();
@@ -191,7 +226,9 @@
   });
 
   onUnmounted(() => {
-    destroy();
+    if (!globalConfig?.is2DModel) {
+      destroy();
+    }
   });
 </script>
 <style lang="less" scoped>

Some files were not shown because too many files changed in this diff