Quellcode durchsuchen

[Feat 0000] 二位抽采泵模型动画对接

houzekong vor 2 Tagen
Ursprung
Commit
0b0fffd90e
1 geänderte Dateien mit 185 neuen und 37 gelöschten Zeilen
  1. 185 37
      src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpSVG.vue

+ 185 - 37
src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpSVG.vue

@@ -7313,6 +7313,31 @@
         fill="none"
         d="
M 17567.8 5512.9
L 17647.25 5603"
       />
+
+      <g id="Mask_Main_9_a_FILL">
+        <path fill="#FFFFFF" stroke="none" d="M 746.15 471.26 L 67.03 569.48 L 70.43 592.93 L 749.54 494.71 Z" />
+      </g>
+      <g id="Mask_Main_9_b_FILL">
+        <path fill="#FFFFFF" stroke="none" d="M 1027.07 454.57 L 1023.68 431.12 L 746.15 471.26 L 749.54 494.71 L 1027.07 454.57 Z" />
+      </g>
+      <g id="Mask_Main_19_a_FILL">
+        <path fill="#FFFFFF" stroke="none" d="M 469.16 421.16 L 67.25 470.4 L 69.35 487.65 L 471.27 438.41 Z" />
+      </g>
+      <g id="Mask_Main_19_b_FILL">
+        <path fill="#FFFFFF" stroke="none" d="M 862.8 390.45 L 860.7 373.2 L 469.16 421.16 L 471.27 438.41 L 862.8 390.45 Z" />
+      </g>
+      <g id="Mask_Main_7_a_FILL">
+        <path fill="#FFFFFF" stroke="none" d="M 574.33 635.55 L 517 648.25 L 521 661.95 L 577.43 649.57 Z" />
+      </g>
+      <g id="Mask_Main_7_b_FILL">
+        <path fill="#FFFFFF" stroke="none" d="M 940.55 569.95 L 937.3 555.15 L 574.33 635.55 L 577.43 649.57 L 940.55 569.95 Z" />
+      </g>
+      <g id="Mask_Main_8_a_FILL">
+        <path fill="#FFFFFF" stroke="none" d="M 627.1 642.68 L 429.85 687.2 L 430.85 702.15 L 630.34 656.98 Z" />
+      </g>
+      <g id="Mask_Main_8_b_FILL">
+        <path fill="#FFFFFF" stroke="none" d="M 994.2 574.6 L 991.05 560.55 L 627.1 642.68 L 630.34 656.98 L 994.2 574.6 Z" />
+      </g>
     </defs>
     <g transform="matrix( 0.053741455078125, 0, 0, 0.053741455078125, 11.4,265.3) ">
       <g transform="matrix( 1, 0, 0, 1, 0,0) ">
@@ -8280,6 +8305,48 @@
         </g>
       </g>
     </g>
+
+    <mask id="Mask_Main_9_a">
+      <g transform="matrix( 1, 0, 0, 1, 0,0) ">
+        <use xlink:href="#Mask_Main_9_a_FILL" />
+      </g>
+    </mask>
+    <mask id="Mask_Main_9_b">
+      <g transform="matrix( 1, 0, 0, 1, 0,0) ">
+        <use xlink:href="#Mask_Main_9_b_FILL" />
+      </g>
+    </mask>
+    <mask id="Mask_Main_19_a">
+      <g transform="matrix( 1, 0, 0, 1, 0,0) ">
+        <use xlink:href="#Mask_Main_19_a_FILL" />
+      </g>
+    </mask>
+    <mask id="Mask_Main_19_b">
+      <g transform="matrix( 1, 0, 0, 1, 0,0) ">
+        <use xlink:href="#Mask_Main_19_b_FILL" />
+      </g>
+    </mask>
+    <mask id="Mask_Main_7_a">
+      <g transform="matrix( 1, 0, 0, 1, 0,0) ">
+        <use xlink:href="#Mask_Main_7_a_FILL" />
+      </g>
+    </mask>
+    <mask id="Mask_Main_7_b">
+      <g transform="matrix( 1, 0, 0, 1, 0,0) ">
+        <use xlink:href="#Mask_Main_7_b_FILL" />
+      </g>
+    </mask>
+    <mask id="Mask_Main_8_a">
+      <g transform="matrix( 1, 0, 0, 1, 0,0) ">
+        <use xlink:href="#Mask_Main_8_a_FILL" />
+      </g>
+    </mask>
+    <mask id="Mask_Main_8_b">
+      <g transform="matrix( 1, 0, 0, 1, 0,0) ">
+        <use xlink:href="#Mask_Main_8_b_FILL" />
+      </g>
+    </mask>
+
     <mask id="Mask_Mask_1">
       <g transform="matrix( 1, 0, 0, 1, 0,0) ">
         <use xlink:href="#Mask_39_MASK_0_FILL" />
@@ -8407,11 +8474,11 @@
    *    36 个动画元素里有 31 个真有位移,另 5 个(9/11/12/13/15/16 中的 9/11/12/13/16)只是生成器
    *    把 0.1~0.2px 的浮点舍入当成了变化,因此不参与动画、保持静止。
    *
-   * 2) 与三维 handleAnimation 同源:子组件在轮询里调 animate2D(data),传的就是给三维 playAnimate
-   *    的同一份监测数据。判定口径与三维逐字一致 —— 优先用该站注入的"泵号 → 运行点位"
-   *    (getPumpRunSignals(deviceType),布尔台新站变频器状态 / 老站磁力启动器断路器状态),
-   *    未注入时回落到进气/出气阀门开度(jqf1/cqf1、jqf2/cqf2);先全部不点亮,
-   *    再只点亮运行中泵所接的管路(与三维"先隐藏、再点亮"完全对应)。
+   * 2) 动画分组按"泵号 + 管路 → mask"渲染(PUMP_PIPE_MASKS,见下方):
+   *    1 号泵用整段总管(9/19/8/7),2 号泵用按接入节点切出的分段总管(9a/19a/8a/7a),
+   *    各泵自己的支管段各自成组;运行时把对应分组点亮并播放,其余分组停住并隐藏。
+   *    泵运行与否的判定与三维 handleAnimation 同源:优先用该站注入的"泵号 → 运行点位"
+   *    (getPumpRunSignals(deviceType)),未注入时回落到进气/出气阀门开度(jqf/cqf)。
    */
   const elementInfo = new Map([
     [
@@ -9107,27 +9174,12 @@
    */
   const UNLIT_OPACITY = '0';
 
-  /** 有位移、需要参与动画的元素序号(其余保持静止) */
-  const MOVING = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35];
-
-  /**
-   * 泵号 → 参与该泵流动的元素序号
-   *
-   * 与三维 pumpArrows 表同一个思路(每台泵一组管路),现场若与左右相反,只改这两行即可。
-   */
-  const PUMP_FLOW_ELEMENTS: Record<number, number[]> = {
-    1: [2, 3, 4, 5, 6, 25, 26, 30, 31, 32, 33],
-    2: [0, 1, 19, 20, 21, 22, 23, 24, 27, 28, 29, 35],
-  };
-
-  /** 跨区总管/共用管路(二维版面特有):任一台泵运行就应该流动 */
-  const SHARED_FLOW_ELEMENTS = [7, 8, 10, 14, 15, 17, 18, 34];
-
-  /** 回落口径用的标签表(与三维同一张表) */
+  /** 回落口径用的标签表(与三维同一张表:按 domId 取该站的点位) */
   const modelMonitorTags = getModelMonitorTags();
 
-  /** 当前站型的"泵号 → 运行点位",随 deviceType 解析并缓存 */
+  /** 当前站型的“泵号 → 运行点位”,随 deviceType 解析并缓存 */
   const runSignals = ref<Record<number, { code: string }> | null>(null);
+
   /** 上一次收到的监测数据:站型变化或运行点位解析完成后,用它立刻重刷一次 */
   let lastData: any = null;
 
@@ -9143,22 +9195,115 @@
     return el ? [el] : [];
   }
 
-  /** 按"每台泵是否运行"批量应用到分组:运行=继续流动,未运行=停住并隐藏 */
-  function applyPumps(pumps: Record<number, boolean>) {
-    MOVING.forEach((n) => {
-      const els = elementsOf(n);
-      if (!els.length) return;
+  /**
+   * mask 编号 → 该 mask 覆盖的动画分组(auto_anim_N 的 N)
+   *
+   * 与源素材一一对应:Mask_Mask_1 → 0、Mask_Mask_2 → 1 …… 一个 mask 里的多个分组是同一条管道
+   * 的不同段(横管/立管/弯头),所以一条 mask 会带多个分组编号。带 a 的分段 mask 与整段共用同一批分组。
+   */
+  const MASK_GROUPS: Record<string, number[]> = {
+    '1': [0],
+    '2': [1],
+    '3': [2],
+    '4': [3],
+    '5': [4, 5],
+    '6': [6],
+    '7': [7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+    '8': [17],
+    '9': [18],
+    '10': [19, 20, 21, 22, 23],
+    '11': [24],
+    '12': [25],
+    '13': [26],
+    '14': [27],
+    '15': [28, 29],
+    '16': [30],
+    '17': [31],
+    '18': [32, 33],
+    '19': [34],
+    '20': [35],
+  };
 
-      const shared = SHARED_FLOW_ELEMENTS.includes(n);
-      const lit = shared
-        ? Object.values(pumps).some(Boolean) // 共用管路:任一台泵运行就流动
-        : Object.entries(PUMP_FLOW_ELEMENTS).some(([pumpNo, list]) => pumps[Number(pumpNo)] && list.includes(n));
+  /**
+   * 泵号 + 管路 → 使用哪些 mask(现场给定的分组规则)
+   *
+   * 带 a 的是按节点切出来的分段 mask(9a/19a/8a/7a):2 号泵接在总管中段,
+   * 所以总管只画到它接入的节点为止;1 号泵接在总管靠外侧,用整段。
+   */
+  const PUMP_PIPE_MASKS: Record<number, Record<string, string[]>> = {
+    1: {
+      airIn: ['9', '10', '11'],
+      airOut: ['14', '15', '19', '20'],
+      waterIn: ['1', '8'],
+      waterOut: ['2', '5', '6', '7'],
+    },
+    2: {
+      airIn: ['9a', '12', '13'],
+      airOut: ['16', '17', '18', '19a'],
+      waterIn: ['3', '8a'],
+      waterOut: ['4', '5', '6', '7a'],
+    },
+  };
+
+  /** 分段 mask 编号 → 组件里实际定义的 mask id(其余按 Mask_Mask_<编号> 取) */
+  const SPLIT_MASK_ID: Record<string, string> = {
+    '9a': 'Mask_Main_9_a',
+    '19a': 'Mask_Main_19_a',
+    '8a': 'Mask_Main_8_a',
+    '7a': 'Mask_Main_7_a',
+  };
+
+  /** 四条管路(与 PUMP_PIPE_MASKS 的键一致) */
+  const PIPE_KEYS = ['airIn', 'airOut', 'waterIn', 'waterOut'];
+
+  /** 分组编号 → 它原本挂的整段 mask;同时给出需要参与控制的全部分组 */
+  const MASK_BY_GROUP: Record<number, string> = {};
+  Object.entries(MASK_GROUPS).forEach(([key, list]) => list.forEach((n) => (MASK_BY_GROUP[n] = `Mask_Mask_${key}`)));
+  const ALL_GROUPS = Object.keys(MASK_BY_GROUP).map(Number);
+
+  /**
+   * 点亮 / 熄灭一个分组
+   *
+   * @param maskKey 该分组这次用的 mask 编号;传 null 表示这次不点亮(停住并隐藏)
+   *                带 a 的分段 mask 会把包裹层的 mask 属性换成对应的分段 mask,
+   *                不点亮或整段时恢复成它原本的 mask。
+   */
+  function setGroup(n: number, maskKey: string | null) {
+    const els = elementsOf(n);
+    if (!els.length) return;
+    const base = MASK_BY_GROUP[n];
+    const want = !maskKey ? base : SPLIT_MASK_ID[maskKey] || base;
+    els.forEach((el) => {
+      el.style.animationPlayState = maskKey ? 'running' : 'paused';
+      el.style.opacity = maskKey ? '' : UNLIT_OPACITY;
+      const wrapper = el.parentElement; // 带 mask 属性的那层(管道裁剪窗口)
+      if (!wrapper || !wrapper.getAttribute('mask')) return;
+      const value = `url(#${want})`;
+      if (wrapper.getAttribute('mask') !== value) wrapper.setAttribute('mask', value);
+    });
+  }
 
-      els.forEach((el) => {
-        el.style.animationPlayState = lit ? 'running' : 'paused';
-        el.style.opacity = lit ? '' : UNLIT_OPACITY;
+  /**
+   * 按"每台泵是否运行"渲染:先算出每个分组这次用哪条 mask,再统一点亮/熄灭
+   *
+   * 同一分组可能被多台泵/多条管路同时引用(比如 5、6、7 段两条出水都用),
+   * 这里整段优先于分段;两台泵都运行时取并集(现场不会同时运行,仅作兜底)。
+   */
+  function applyPumps(pumps: Record<number, boolean>) {
+    const plan = new Map<number, string>();
+    ([1, 2] as const).forEach((pumpNo) => {
+      if (!pumps[pumpNo]) return;
+      PIPE_KEYS.forEach((pipe) => {
+        (PUMP_PIPE_MASKS[pumpNo][pipe] || []).forEach((maskKey) => {
+          const groups = MASK_GROUPS[maskKey.replace(/a$/, '')] || [];
+          groups.forEach((n) => {
+            const cur = plan.get(n);
+            if (cur === undefined || (cur.endsWith('a') && !maskKey.endsWith('a'))) plan.set(n, maskKey);
+          });
+        });
       });
     });
+    ALL_GROUPS.forEach((n) => setGroup(n, plan.get(n) ?? null));
   }
 
   /** 从监测数据算每台泵是否运行(判定口径与三维 isPumpRunning 完全一致) */
@@ -9175,9 +9320,12 @@
    * @param payload 子组件轮询得到的监测数据;内部按"泵号 → 运行点位"(未注入时回落到阀门开度)
    *                判定每台泵是否运行,先全部不点亮再只点亮运行中泵所接的管路。
    *                也兼容直接给 { pumps: { 1: true, 2: false } }(便于测试/兜底)。
-   *                不传或数据为空 → 全部不点亮,与三维"未注入运行状态就不点亮箭头"一致。
+   *                与三维 handleAnimation 对齐:不传数据(undefined/null)→ 保持上一次状态;
+   *                传空对象/空数据 → 全部熄灭(先隐藏、再只点亮运行中泵的管路)。
    */
-  function animate(payload: any = {}) {
+  function animate(payload?: any) {
+    // 与三维 handleAnimation 一致:没传数据(undefined/null)就保持上一次状态,不把画面清空
+    if (!payload) return;
     lastData = payload;
     // 兼容直接给 { pumps } 的调用(监测数据里不会出现 pumps 字段,所以这样判不会误判)
     if (payload && typeof payload === 'object' && Object.prototype.hasOwnProperty.call(payload, 'pumps')) {