Browse Source

Merge branch 'master' of http://182.92.126.35:3000/hrx/mky-vent-base

lxh 2 days ago
parent
commit
d5d91be8c3

+ 9 - 8
src/layouts/default/header/components/VoiceBroadcastGsd.vue

@@ -71,7 +71,6 @@
       }
       function handleBroad() {
         isBroad.value = !isBroad.value;
-        onWebSocketMessage('test');
       }
       async function clearInfo() {
         broadcastList.value = [];
@@ -99,18 +98,20 @@
 
       async function onWebSocketMessage(data) {
         console.log('WebSocket 监测消息--------------》', data);
-        if (data.topic === 'warn' || data.cmd === 'user') {
+        if (data.topic === 'warn') {
           const messageText = data['warndata'];
-          if (broadcastList.value.length <= 20) {
-            broadcastList.value.push({ label: messageText });
+          const msgList = [...broadcastList.value];
+          if (msgList.length <= 20) {
+            msgList.push({ label: messageText });
             localStorage.removeItem('messageArr');
-            localStorage.setItem('messageArr', broadcastList.value as any);
+            localStorage.setItem('messageArr', msgList as any);
           } else {
-            broadcastList.value.shift();
-            broadcastList.value.push({ label: messageText });
+            msgList.shift();
+            msgList.push({ label: messageText });
             localStorage.removeItem('messageArr');
-            localStorage.setItem('messageArr', broadcastList.value as any);
+            localStorage.setItem('messageArr', msgList as any);
           }
+          broadcastList.value = msgList;
           if (isBroad.value) {
             await speakVoice.getSpeechCnVoices();
             speakVoice.handleReply(messageText);

+ 11 - 0
src/router/routes/basic.ts

@@ -76,6 +76,17 @@ export const QIANKUN_ROUTE: AppRouteRecordRaw = {
       ver: '1',
     },
     {
+      path: '/micro-vent-3dModal/modelchannel/model3D/home',
+      name: 'micro-vent-3dModal-modelchannel-model3D-home',
+      component: () => import('/@/views/vent/home/colliery/index.vue'),
+      meta: {
+        title: '通防综合管控',
+        hideBreadcrumb: true,
+        hideMenu: true,
+      },
+      ver: '1',
+    },
+    {
       path: '/micro-vent-3dModal/gas-pipe-net/home',
       name: 'gas-pipe-net-home',
       component: () => import('/@/views/vent/gas/gasPipeNet/index.vue'),

+ 1 - 0
src/utils/threejs/useThree.ts

@@ -281,6 +281,7 @@ class UseThree {
 
                 const result = (await getList({ fileName: modalNameStr })) || [];
                 const file = result['records'][0];
+                debugger;
                 if (file && file.path) {
                   console.log('需要开启线程下载模型资源。。。。。');
 

+ 1 - 1
src/views/vent/monitorManager/deviceMC/AlarmHistoryTable.vue

@@ -156,7 +156,7 @@
             field: 'startTime',
             label: '开始时间',
             component: 'DatePicker',
-            defaultValue: dayjs().add(-30, 'day').format('YYYY-MM-DD HH:mm:ss'),
+            defaultValue: dayjs().startOf('date'),
             required: true,
             componentProps: {
               showTime: true,

+ 0 - 713
src/views/vent/monitorManager/fanLocalMonitor/fanLocal.three.bk.ts

@@ -1,713 +0,0 @@
-import * as THREE from 'three';
-import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
-import { animateCamera, getTextCanvas, renderVideo, updateAxisCenter } from '/@/utils/threejs/util';
-import UseThree from '../../../../utils/threejs/useThree';
-import fcFan from './fcfanLocal.three';
-import fmFan from './fmfanLocal.three';
-import Smoke from '/@/views/vent/comment/threejs/Smoke';
-import gsap from 'gsap';
-import useEvent from '../../../../utils/threejs/useEvent';
-
-// import * as dat from 'dat.gui';
-// const gui = new dat.GUI();
-// gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
-
-const modelName = 'jbfj-hd';
-// 模型对象、 文字对象
-let model: UseThree | undefined,
-  group: THREE.Object3D | undefined,
-  fcFanObj: fcFan | undefined,
-  fmFanObj: fmFan | undefined,
-  player1,
-  fanType,
-  topSmoke: Smoke | undefined,
-  downSmoke: Smoke | undefined, //
-  returnSmoke: Smoke | undefined,
-  topLife: number | undefined,
-  downLife: number | undefined,
-  playerStartClickTime1 = new Date().getTime();
-
-const { mouseDownFn, mousemoveFn, mouseUpFn } = useEvent();
-
-// 打灯光
-const addLight = () => {
-  const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
-  directionalLight.position.set(-564, 602, -261);
-  group?.add(directionalLight);
-  // directionalLight.target = group;
-
-  // const spotLight = new THREE.SpotLight();
-  // spotLight.angle = Math.PI / 16;
-  // spotLight.penumbra = 0;
-  // spotLight.castShadow = true;
-  // spotLight.position.set(0, 463, 687);
-  // scene.add(spotLight);
-
-  // spotLight.shadow.camera.near = 0.5; // default
-  // spotLight.shadow.camera.far = 1000; // default
-  // spotLight.shadow.focus = 1;
-  // spotLight.shadow.bias = -0.000002;
-  // spotLight.target = group;
-
-  // const pointLight6 = new THREE.PointLight(0xffffff, 1, 500);
-  // pointLight6.position.set(-131, 64, -1);
-  // pointLight6.shadow.bias = 0.05;
-  // group?.add(pointLight6);
-
-  // gui.add(directionalLight.position, 'x', -1000, 1000);
-  // gui.add(directionalLight.position, 'y', -1000, 1000);
-  // gui.add(directionalLight.position, 'z', -1000, 1000);
-
-  // gui.add(pointLight6.position, 'x', -500, 500);
-  // gui.add(pointLight6.position, 'y', -500, 500);
-  // gui.add(pointLight6.position, 'z', -500, 500);
-  // gui.add(pointLight6, 'distance', 0, 500);
-};
-
-// 重置摄像头
-const resetCamera = () => {
-  model.camera.position.set(0, -1000, 100);
-  model.camera.far = 1000;
-  model.orbitControls?.update();
-  model.camera.updateProjectionMatrix();
-};
-
-// 设置模型位置
-const setModalPosition = () => {
-  if (!group) return;
-  group.position.set(0, 10, -50);
-  group.rotation.y = Math.PI / 2;
-};
-
-const setControls = () => {
-  if (model && model.orbitControls) {
-    model.orbitControls.panSpeed = 0.5;
-    model.orbitControls.rotateSpeed = 0.5;
-    model.orbitControls.maxPolarAngle = Math.PI / 2.4;
-    model.orbitControls.minPolarAngle = Math.PI / 3;
-  }
-};
-
-// 切换局部通风机类型
-export const setModelType = (type) => {
-  fanType = type;
-  return new Promise((resolve) => {
-    // 显示双道风窗
-    let childGroup;
-    if (fanType === 'fm' && fcFanObj && fcFanObj.group) {
-      if (group?.getObjectByName('jbfj-fc')) {
-        group?.remove(fcFanObj.group);
-      }
-      childGroup = fmFanObj?.group;
-      if (group && group?.getObjectByName('text5') && group?.getObjectByName('text4')) {
-        group.getObjectByName('text5')['visible'] = false;
-        group.getObjectByName('text4')['visible'] = true;
-      }
-    } else if (fanType === 'fc' && fmFanObj && fmFanObj.group) {
-      // 显示单道风窗
-      if (group?.getObjectByName('jbfj-fm')) {
-        group?.remove(fmFanObj.group);
-      }
-      childGroup = fcFanObj?.group;
-      if (group && group?.getObjectByName('text5') && group?.getObjectByName('text4')) {
-        group.getObjectByName('text5')['visible'] = true;
-        group.getObjectByName('text4')['visible'] = false;
-      }
-    } else {
-      if (group?.getObjectByName('jbfj-fc')) {
-        group?.remove(fcFanObj.group);
-      }
-      if (group?.getObjectByName('jbfj-fm')) {
-        group?.remove(fmFanObj.group);
-      }
-      if (group && group?.getObjectByName('text5') && group?.getObjectByName('text4')) {
-        group.getObjectByName('text5')['visible'] = false;
-        group.getObjectByName('text4')['visible'] = false;
-      }
-      childGroup = null;
-    }
-    setTimeout(async () => {
-      if (childGroup) group?.add(childGroup);
-      const oldCameraPosition = { x: 615, y: 275, z: 744 };
-      await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: 0.08, y: 21.73, z: 78.45 }, { x: 0.13, y: -0.82, z: 0.236 }, model, 0.8);
-      resolve(null);
-    }, 300);
-  });
-};
-
-/* 添加监控数据 */
-export const addText = (selectData) => {
-  if (!group) {
-    return;
-  }
-  const screenDownText = VENT_PARAM['modalText']
-    ? VENT_PARAM['modalText']
-    : History_Type['type'] == 'remote'
-    ? `国能神东煤炭集团监制`
-    : '煤炭科学技术研究院有限公司研制';
-
-  const screenDownTextX = 80 - (screenDownText.length - 10) * 6;
-  const textArr = [
-    {
-      text: `智能局部通风机监测与控制系统`,
-      font: 'normal 30px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 20,
-      y: 108,
-    },
-    {
-      text: `供风距离(m):`,
-      font: 'normal 30px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 0,
-      y: 152,
-    },
-    {
-      text: `${
-        selectData.airSupplyDistence_merge
-          ? selectData.airSupplyDistence_merge
-          : selectData.fchimenylength
-          ? selectData.fchimenylength
-          : selectData.airSupplyDistence_merge
-          ? selectData.airSupplyDistence_merge
-          : '-'
-      }`,
-      font: 'normal 30px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 228,
-      y: 152,
-    },
-    {
-      text: `风筒直径(mm): `,
-      font: 'normal 30px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 0,
-      y: 200,
-    },
-    {
-      text: ` ${selectData.fchimenydiamlimit ? selectData.fchimenydiamlimit : selectData.ductDiameter_merge ? selectData.ductDiameter_merge : '-'}`,
-      font: 'normal 30px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 220,
-      y: 200,
-    },
-    {
-      text: `故障诊断:`,
-      font: 'normal 30px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 0,
-      y: 245,
-    },
-    {
-      text: `${selectData.warnLevel_str ? selectData.warnLevel_str : '-'}`,
-      font: 'normal 30px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 220,
-      y: 245,
-    },
-    {
-      text: `型号功率:`,
-      font: 'normal 30px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 0,
-      y: 285,
-    },
-    {
-      text: `${selectData.model_Power_merge ? selectData.model_Power_merge : '-'}`,
-      font: 'normal 26px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: 220,
-      y: 285,
-    },
-    {
-      text: screenDownText,
-      font: 'normal 28px Arial',
-      color: '#009900',
-      strokeStyle: '#002200',
-      x: screenDownTextX,
-      y: 325,
-    },
-  ];
-  getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
-    const textMap = new THREE.CanvasTexture(canvas); // 关键一步
-    const textMaterial = new THREE.MeshBasicMaterial({
-      // 关于材质并未讲解 实操即可熟悉                 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
-      map: textMap, // 设置纹理贴图
-      transparent: true,
-      side: THREE.FrontSide, // 这里是双面渲染的意思
-    });
-    textMaterial.blending = THREE.CustomBlending;
-    const monitorPlane = group.getObjectByName('monitorText');
-    if (monitorPlane) {
-      monitorPlane.material = textMaterial;
-    } else {
-      const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
-      const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
-      planeMesh.name = 'monitorText';
-      planeMesh.scale.set(0.0135, 0.0135, 0.0135);
-      planeMesh.rotation.y = -Math.PI / 2;
-      planeMesh.position.set(-84.79, 0.82, 17.0);
-      group.add(planeMesh);
-    }
-  });
-};
-
-// // css3D文字
-export const addCssText = () => {
-  if (!group) return;
-
-  if (!group.getObjectByName('text1')) {
-    const element = document.getElementById('inputBox') as HTMLElement;
-    if (element) {
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text1';
-      fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(-85.68, 5.97, -3.39);
-      group.add(fanLocalCSS3D);
-    }
-  }
-
-  if (!group.getObjectByName('text2')) {
-    const element = document.getElementById('outBox') as HTMLElement;
-    if (element) {
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text2';
-      fanLocalCSS3D.scale.set(0.1, 0.1, 0.1);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      // fanLocalCSS3D.position.set(74.63, 13.54, 3.84);
-      fanLocalCSS3D.position.set(57.84, 10.54, 0.08);
-      group.add(fanLocalCSS3D);
-    }
-  }
-  if (!group.getObjectByName('text3')) {
-    const element = document.getElementById('returnBox') as HTMLElement;
-    if (element) {
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text3';
-      fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(-25.97, 9.3, -15.09);
-      group.add(fanLocalCSS3D);
-    }
-  }
-  if (!group.getObjectByName('text4')) {
-    const element = document.getElementById('gateBox') as HTMLElement;
-    if (element) {
-      // element.innerHTML = '';
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text4';
-      fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(-73.13, 8.44, -23.52);
-      group.add(fanLocalCSS3D);
-    }
-  }
-  if (!group.getObjectByName('text5')) {
-    const element = document.getElementById('windownBox') as HTMLElement;
-    if (element) {
-      // element.innerHTML = '';
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text5';
-      fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(-28.44, 9.78, -40.42);
-      group.add(fanLocalCSS3D);
-    }
-  }
-  if (!group.getObjectByName('text7')) {
-    const element = document.getElementById('inputBox0') as HTMLElement;
-    if (element) {
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text7';
-      fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(-84.23, 4.97, -18.92);
-      group.add(fanLocalCSS3D);
-    }
-  }
-  if (!group.getObjectByName('text6')) {
-    const element = document.getElementById('inputBox1') as HTMLElement;
-    if (element) {
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text6';
-      fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(-84.23, 6.89, -4.2);
-      group.add(fanLocalCSS3D);
-    }
-  }
-  if (!group.getObjectByName('text8')) {
-    const element = document.getElementById('gasBox3') as HTMLElement;
-    if (element) {
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text8';
-      fanLocalCSS3D.scale.set(0.03, 0.03, 0.03);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(-90.04, 6, 5);
-      group.add(fanLocalCSS3D);
-    }
-  }
-  if (!group.getObjectByName('text9')) {
-    const element = document.getElementById('gasBox2') as HTMLElement;
-    if (element) {
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text9';
-      fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(-8, 7.46, -35.28);
-      group.add(fanLocalCSS3D);
-    }
-  }
-  if (!group.getObjectByName('text10')) {
-    const element = document.getElementById('gasBox1') as HTMLElement;
-    if (element) {
-      const fanLocalCSS3D = new CSS3DObject(element);
-      fanLocalCSS3D.name = 'text10';
-      fanLocalCSS3D.scale.set(0.1, 0.1, 0.1);
-      fanLocalCSS3D.rotation.y = -Math.PI / 2;
-      fanLocalCSS3D.position.set(80, 9, -43);
-      group.add(fanLocalCSS3D);
-    }
-  }
-};
-
-// export const playSmoke = (controlType, deviceType, frequency, state) => {
-//   if (frequency) {
-//     setSmokeFrequency(deviceType, frequency);
-//   }
-//   if (controlType === 'startSmoke') {
-//     runFly(deviceType, state);
-//   }
-// };
-export const playSmoke = (selectData) => {
-  // debugger;
-  // console.log('selectData[Fan1fHz]------------》', selectData['Fan1fHz'], Number(selectData['Fan1fHz']));
-  if (selectData['Fan1StartStatus'] == '1') {
-    // 主风机打开
-    // setSmokeFrequency('top', Number(selectData['Fan1fHz']) || 40);
-    setSmokeFrequency('top', 40);
-    runFly('top', 'open');
-  } else {
-    // 备风机关闭
-    runFly('top', 'close');
-  }
-  if (selectData['Fan2StartStatus'] == '1') {
-    // 备风机打开
-    // setSmokeFrequency('down', Number(selectData['Fan2fHz']) || 40);
-    setSmokeFrequency('down', 40);
-    runFly('down', 'open');
-  } else {
-    // 备风机关闭
-    runFly('down', 'close');
-  }
-
-  if (selectData['Fan1StartStatus'] != '1' && selectData['Fan2StartStatus'] != '1') {
-    runFly('all', 'close');
-  }
-
-  // if (frequency) {
-  //   setSmokeFrequency(deviceType, frequency);
-  // }
-  // if (controlType === 'startSmoke') {
-  //   runFly(deviceType, state);
-  // }
-};
-
-const initFly = async () => {
-  const topCurve = [
-    {
-      path0: new THREE.Vector3(-89.84, 2.359, 4.91),
-      path1: new THREE.Vector3(-85.678, 2.359, 3.61),
-      isSpread: true,
-      spreadDirection: -1, //
-    },
-    {
-      path0: new THREE.Vector3(-85.678, 2.352, 3.66),
-      path1: new THREE.Vector3(-85.636, 2.353, -3.829),
-      isSpread: false,
-      spreadDirection: 0,
-    },
-    {
-      path0: new THREE.Vector3(-85.636, 2.353, -3.829),
-      path1: new THREE.Vector3(-85.636, 1.026, -5.881),
-      isSpread: false,
-      spreadDirection: 0,
-    },
-    {
-      path0: new THREE.Vector3(-85.636, 1.026, -5.881),
-      path1: new THREE.Vector3(-85.618, 0.887, -12.862),
-      isSpread: false,
-      spreadDirection: 0,
-    },
-    {
-      path0: new THREE.Vector3(-85.618, 0.827, -12.962),
-      path1: new THREE.Vector3(80.404, 0.827, -12.962),
-      isSpread: false,
-      spreadDirection: 0,
-    },
-    {
-      path0: new THREE.Vector3(80.404, 0.827, -12.962),
-      path1: new THREE.Vector3(93.164, 0.85, -12.962),
-      isSpread: true,
-      spreadDirection: 1, // 1是由小变大,-1是由大变小
-    },
-  ];
-
-  const downCurve = [
-    {
-      path0: new THREE.Vector3(-94.84, -0.388, 3.61),
-      path1: new THREE.Vector3(-85.678, -0.393, 3.61),
-      isSpread: true,
-      spreadDirection: -1, //
-    },
-    {
-      path0: new THREE.Vector3(-85.678, -0.393, 3.275),
-      path1: new THREE.Vector3(-85.636, -0.392, -3.829),
-      isSpread: false,
-      spreadDirection: 0,
-    },
-    {
-      path0: new THREE.Vector3(-85.636, -0.392, -3.829),
-      path1: new THREE.Vector3(-85.636, 0.926, -5.881),
-      isSpread: false,
-      spreadDirection: 0,
-    },
-    {
-      path0: new THREE.Vector3(-85.636, 1.026, -5.881),
-      path1: new THREE.Vector3(-85.618, 0.887, -12.862),
-      isSpread: false,
-      spreadDirection: 0,
-    },
-    {
-      path0: new THREE.Vector3(-85.618, 0.887, -12.962),
-      path1: new THREE.Vector3(80.404, 0.887, -12.962),
-      isSpread: false,
-      spreadDirection: 0,
-    },
-    {
-      path0: new THREE.Vector3(80.404, 0.887, -12.962),
-      path1: new THREE.Vector3(93.164, 0.91, -12.962),
-      isSpread: true,
-      spreadDirection: 1, // 1是由小变大,-1是由大变小
-    },
-  ];
-
-  const returnCurve = [
-    {
-      path0: new THREE.Vector3(93.164, 0.85, -12.962),
-      path1: new THREE.Vector3(86.39, 0.827, -12.962),
-      isSpread: false,
-      spreadDirection: 2,
-    },
-    {
-      path0: new THREE.Vector3(86.39, 0.827, -12.962),
-      path1: new THREE.Vector3(83.341, 0.847, -17.658),
-      isSpread: false,
-      spreadDirection: 2,
-    },
-    {
-      path0: new THREE.Vector3(83.341, 0.847, -17.658),
-      path1: new THREE.Vector3(-29.077, 0.847, -17.658),
-      isSpread: false,
-      spreadDirection: 2,
-    },
-    {
-      path0: new THREE.Vector3(-29.077, 0.847, -17.658),
-      path1: new THREE.Vector3(-29.64, 0.827, -39.047),
-      isSpread: false,
-      spreadDirection: 2,
-    },
-  ];
-
-  if (!topSmoke) {
-    topSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
-    topSmoke.setPath(topCurve);
-    await topSmoke.setPoints();
-    group?.add(topSmoke.points);
-  }
-  if (!downSmoke) {
-    downSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
-    downSmoke.setPath(downCurve);
-    await downSmoke.setPoints();
-    group?.add(downSmoke.points);
-  }
-
-  if (!returnSmoke) {
-    returnSmoke = new Smoke('/model/img/texture-smoke.png', '#777777', 0, 0.35, 1.5, 200);
-    returnSmoke.setPath(returnCurve);
-    await returnSmoke.setPoints();
-    group?.add(returnSmoke.points);
-  }
-};
-
-const runFly = (deviceType, state) => {
-  if (state === 'open') {
-    if (deviceType === 'top') {
-      if (downSmoke && downSmoke.frameId) {
-        downSmoke.stopSmoke();
-      }
-      if (topSmoke && !topSmoke.frameId) {
-        topSmoke.startSmoke();
-      }
-    } else {
-      if (topSmoke && topSmoke.frameId) {
-        topSmoke.stopSmoke();
-      }
-      if (downSmoke && !downSmoke.frameId) {
-        downSmoke.startSmoke();
-      }
-    }
-    if (returnSmoke && !returnSmoke.frameId) {
-      returnSmoke?.startSmoke();
-    }
-  } else {
-    if (deviceType === 'top') {
-      if (topSmoke && topSmoke.frameId) {
-        topSmoke.stopSmoke();
-      }
-    } else {
-      if (downSmoke && downSmoke.frameId) {
-        downSmoke.stopSmoke();
-      }
-    }
-  }
-  if (deviceType === 'all' && state === 'close') {
-    returnSmoke?.stopSmoke();
-  }
-};
-
-// 调频 30-50 (life 300 - 800) , 25 = (800 - 300)/ 20
-const setSmokeFrequency = (deviceType, frequency) => {
-  const life = (frequency - 30) * 25;
-  let duration = 0;
-  let smoke;
-
-  if (deviceType === 'top') {
-    if (topLife == life) {
-      return;
-    }
-    topLife = life;
-    smoke = topSmoke;
-    duration = (Math.abs(life - smoke.life) / 500) * 25;
-  } else {
-    if (downLife == life) {
-      return;
-    }
-    downLife = life;
-    smoke = downSmoke;
-    duration = (Math.abs(life - smoke.life) / 500) * 25;
-  }
-  if (smoke) {
-    gsap.to(smoke, {
-      life: life,
-      duration: duration,
-      ease: 'easeInCubic',
-      overwrite: true,
-    });
-  }
-};
-
-const clearFly = () => {
-  if (topSmoke) topSmoke.clearSmoke();
-  if (downSmoke) downSmoke.clearSmoke();
-  if (returnSmoke) returnSmoke.clearSmoke();
-};
-// 初始化事件
-const startAnimation = () => {
-  // 定义鼠标点击事件
-  model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
-  model.canvasContainer?.addEventListener('pointerup', mouseUp);
-};
-
-// 鼠标点击、松开事件
-const mouseEvent = (event) => {
-  if (event.button == 0) {
-    model?.canvasContainer?.addEventListener('mousemove', mousemove);
-    mouseDownFn(<UseThree>model, <THREE.Object3D>group, event, (intersects) => {
-      intersects.find((intersect) => {
-        const mesh = intersect.object;
-      });
-    });
-    console.log('摄像头控制信息', model?.orbitControls, model?.camera);
-  }
-};
-
-const mouseUp = () => {
-  if (!model) return;
-  mouseUpFn(model);
-  model.canvasContainer?.removeEventListener('mousemove', mousemove);
-};
-
-const mousemove = () => {
-  mousemoveFn();
-};
-
-export const mountedThree = (playerVal1) => {
-  player1 = playerVal1;
-  return new Promise((resolve) => {
-    // model = VENT_PARAM['simulatedPassword'] ? new UseThree('#fanLocal3D', '#fanLocal3DCSS') : new UseThree('#fanLocal3D');
-    model = new UseThree('#fanLocal3D', '#fanLocal3DCSS');
-    model.setEnvMap('test1.hdr');
-    model.renderer.toneMappingExposure = 1.0;
-    if (model.renderer) {
-      model.renderer.sortObjects = true;
-    }
-    resetCamera();
-    model.setGLTFModel([modelName]).then(async (gltf) => {
-      group = <THREE.Object3D>gltf[0];
-      const Fengtongbu01 = group?.getObjectByName('Cylinder1054') as THREE.Mesh;
-      if (Fengtongbu01) {
-        const textMaterial = new THREE.MeshBasicMaterial({
-          color: '#000',
-          transparent: true,
-          opacity: 0.3,
-          side: THREE.DoubleSide, // 这里是双面渲染的意思
-        });
-        Fengtongbu01.material = textMaterial;
-        Fengtongbu01.renderOrder = 300;
-      }
-
-      model?.scene?.add(group);
-      setModalPosition();
-      setControls();
-      await initFly();
-      model?.animate();
-      addLight(model?.scene);
-
-      fcFanObj = new fcFan(model);
-      await fcFanObj.mountedThree();
-
-      fmFanObj = new fmFan(model);
-      await fmFanObj.mountedThree();
-
-      startAnimation();
-      resolve(model);
-    });
-  });
-};
-
-export const destroy = () => {
-  if (model) {
-    model.isRender = false;
-    console.log('场景销毁后信息----------->', model.renderer?.info);
-    clearFly();
-    topSmoke = undefined;
-    downSmoke = undefined;
-    returnSmoke = undefined;
-    if (fcFanObj) fcFanObj.destroy();
-    if (fmFanObj) fmFanObj.destroy();
-    group = undefined;
-    model.destroy();
-    model = undefined;
-  }
-};

+ 636 - 0
src/views/vent/monitorManager/fanLocalMonitor/fanLocal.threejs.Two.ts

@@ -0,0 +1,636 @@
+import * as THREE from 'three';
+import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer';
+import { animateCamera, getTextCanvas, setModalCenter } from '/@/utils/threejs/util';
+import Smoke from '/@/views/vent/comment/threejs/Smoke';
+import fcFan from './fcfanLocal.three';
+import fmFan from './fmfanLocal.three';
+import gsap from 'gsap';
+// import { setModalCenter } from '/@/utils/threejs/util';
+// import * as dat from 'dat.gui';
+// const gui = new dat.GUI();
+// gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
+
+// 本模型的上下文对象,用于实现本模型的特定功能,代码参考了旧有的 fanLocal.three.ts
+class ModelContext {
+  model;
+  modelName = 'jbfj-two';
+  group: THREE.Object3D | null = null;
+  fanType?: string;
+  fcFanObj?: fcFan;
+  fmFanObj?: fmFan;
+  topSmoke?: Smoke;
+  downSmoke?: Smoke;
+  returnSmoke?: Smoke;
+  topLife?: number;
+  downLife?: number;
+
+  constructor(model) {
+    this.model = model;
+  }
+
+  addLight() {
+    // optional implementation
+  }
+
+  mountedThree() {
+    return new Promise((resolve) => {
+      this.model
+        .setGLTFModel([this.modelName])
+        .then(async (gltf) => {
+          debugger;
+          if (!gltf) resolve(false);
+          debugger;
+          this.group = gltf[0];
+          if (this.group) {
+            const Fengtongbu01 = this.group.getObjectByName('Cylinder1054') as THREE.Mesh;
+            const textMaterial = new THREE.MeshBasicMaterial({
+              color: '#000',
+              transparent: true,
+              opacity: 0.3,
+              side: THREE.DoubleSide, // 这里是双面渲染的意思
+            });
+            Fengtongbu01.material = textMaterial;
+            Fengtongbu01.renderOrder = 300;
+
+            setModalCenter(this.group);
+            this.addLight();
+            this.initFly();
+            this.setModalPosition();
+
+            this.fcFanObj = new fcFan(this.model);
+            await this.fcFanObj.mountedThree();
+
+            this.fmFanObj = new fmFan(this.model);
+            await this.fmFanObj.mountedThree();
+            resolve(true);
+          } else {
+            resolve(false);
+          }
+        })
+        .catch((err) => {
+          resolve(false);
+        });
+    });
+  }
+
+  destroy() {
+    if (this.model) {
+      this.model.isRender = false;
+      this.clearFly();
+      this.topSmoke = undefined;
+      this.downSmoke = undefined;
+      this.returnSmoke = undefined;
+      if (this.fcFanObj) this.fcFanObj.destroy();
+      if (this.fmFanObj) this.fmFanObj.destroy();
+      // @ts-ignore
+      this.group = undefined;
+      this.model.destroy();
+    }
+  }
+
+  async initFly() {
+    const topCurve = [
+      {
+        path0: new THREE.Vector3(-89.84, 2.359, 4.91),
+        path1: new THREE.Vector3(-85.678, 2.359, 3.61),
+        isSpread: true,
+        spreadDirection: -1, //
+      },
+      {
+        path0: new THREE.Vector3(-85.678, 2.352, 3.66),
+        path1: new THREE.Vector3(-85.636, 2.353, -3.829),
+        isSpread: false,
+        spreadDirection: 0,
+      },
+      {
+        path0: new THREE.Vector3(-85.636, 2.353, -3.829),
+        path1: new THREE.Vector3(-85.636, 1.026, -5.881),
+        isSpread: false,
+        spreadDirection: 0,
+      },
+      {
+        path0: new THREE.Vector3(-85.636, 1.026, -5.881),
+        path1: new THREE.Vector3(-85.618, 0.887, -12.862),
+        isSpread: false,
+        spreadDirection: 0,
+      },
+      {
+        path0: new THREE.Vector3(-85.618, 0.827, -12.962),
+        path1: new THREE.Vector3(80.404, 0.827, -12.962),
+        isSpread: false,
+        spreadDirection: 0,
+      },
+      {
+        path0: new THREE.Vector3(80.404, 0.827, -12.962),
+        path1: new THREE.Vector3(93.164, 0.85, -12.962),
+        isSpread: true,
+        spreadDirection: 1, // 1是由小变大,-1是由大变小
+      },
+    ];
+
+    const downCurve = [
+      {
+        path0: new THREE.Vector3(-94.84, -0.388, 3.61),
+        path1: new THREE.Vector3(-85.678, -0.393, 3.61),
+        isSpread: true,
+        spreadDirection: -1, //
+      },
+      {
+        path0: new THREE.Vector3(-85.678, -0.393, 3.275),
+        path1: new THREE.Vector3(-85.636, -0.392, -3.829),
+        isSpread: false,
+        spreadDirection: 0,
+      },
+      {
+        path0: new THREE.Vector3(-85.636, -0.392, -3.829),
+        path1: new THREE.Vector3(-85.636, 0.926, -5.881),
+        isSpread: false,
+        spreadDirection: 0,
+      },
+      {
+        path0: new THREE.Vector3(-85.636, 1.026, -5.881),
+        path1: new THREE.Vector3(-85.618, 0.887, -12.862),
+        isSpread: false,
+        spreadDirection: 0,
+      },
+      {
+        path0: new THREE.Vector3(-85.618, 0.887, -12.962),
+        path1: new THREE.Vector3(80.404, 0.887, -12.962),
+        isSpread: false,
+        spreadDirection: 0,
+      },
+      {
+        path0: new THREE.Vector3(80.404, 0.887, -12.962),
+        path1: new THREE.Vector3(93.164, 0.91, -12.962),
+        isSpread: true,
+        spreadDirection: 1, // 1是由小变大,-1是由大变小
+      },
+    ];
+
+    const returnCurve = [
+      {
+        path0: new THREE.Vector3(93.164, 0.85, -12.962),
+        path1: new THREE.Vector3(83.39, 0.827, -12.962),
+        isSpread: false,
+        spreadDirection: 2,
+      },
+      {
+        path0: new THREE.Vector3(83.39, 0.827, -12.962),
+        path1: new THREE.Vector3(80.39, 0.847, -17.658),
+        isSpread: false,
+        spreadDirection: 2,
+      },
+      {
+        path0: new THREE.Vector3(80.39, 0.847, -17.658),
+        path1: new THREE.Vector3(80.39, 0.827, -39.047),
+        isSpread: false,
+        spreadDirection: 2,
+      },
+    ];
+
+    if (!this.topSmoke) {
+      this.topSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
+      this.topSmoke.setPath(topCurve);
+      await this.topSmoke.setPoints();
+      this.group?.add(this.topSmoke.points);
+    }
+    if (!this.downSmoke) {
+      this.downSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.75, 0.5, 400);
+      this.downSmoke.setPath(downCurve);
+      await this.downSmoke.setPoints();
+      this.group?.add(this.downSmoke.points);
+    }
+
+    if (!this.returnSmoke) {
+      this.returnSmoke = new Smoke('/model/img/texture-smoke.png', '#777777', 0, 0.35, 1.5, 80);
+      this.returnSmoke.setPath(returnCurve);
+      await this.returnSmoke.setPoints();
+      this.group?.add(this.returnSmoke.points);
+    }
+  }
+
+  playSmoke(selectData) {
+    // debugger;
+    // console.log('selectData[Fan1fHz]------------》', selectData['Fan1fHz'], Number(selectData['Fan1fHz']));
+    if (selectData['Fan1StartStatus'] == '1') {
+      // 主风机打开
+      // setSmokeFrequency('top', Number(selectData['Fan1fHz']) || 40);
+      this.setSmokeFrequency('top', 40);
+      this.runFly('top', 'open');
+    } else {
+      // 备风机关闭
+      this.runFly('top', 'close');
+    }
+    if (selectData['Fan2StartStatus'] == '1') {
+      // 备风机打开
+      // setSmokeFrequency('down', Number(selectData['Fan2fHz']) || 40);
+      this.setSmokeFrequency('down', 40);
+      this.runFly('down', 'open');
+    } else {
+      // 备风机关闭
+      this.runFly('down', 'close');
+    }
+
+    if (selectData['Fan1StartStatus'] != '1' && selectData['Fan2StartStatus'] != '1') {
+      this.runFly('all', 'close');
+    }
+
+    // if (frequency) {
+    //   setSmokeFrequency(deviceType, frequency);
+    // }
+    // if (controlType === 'startSmoke') {
+    //   runFly(deviceType, state);
+    // }
+  }
+
+  runFly(deviceType, state) {
+    if (state === 'open') {
+      if (deviceType === 'top') {
+        if (this.downSmoke && this.downSmoke.frameId) {
+          this.downSmoke.stopSmoke();
+        }
+        if (this.topSmoke && !this.topSmoke.frameId) {
+          this.topSmoke.startSmoke();
+        }
+      } else {
+        if (this.topSmoke && this.topSmoke.frameId) {
+          this.topSmoke.stopSmoke();
+        }
+        if (this.downSmoke && !this.downSmoke.frameId) {
+          this.downSmoke.startSmoke();
+        }
+      }
+      if (this.returnSmoke && !this.returnSmoke.frameId) {
+        this.returnSmoke?.startSmoke();
+      }
+    } else {
+      if (deviceType === 'top') {
+        if (this.topSmoke && this.topSmoke.frameId) {
+          this.topSmoke.stopSmoke();
+        }
+      } else {
+        if (this.downSmoke && this.downSmoke.frameId) {
+          this.downSmoke.stopSmoke();
+        }
+      }
+    }
+    if (deviceType === 'all' && state === 'close') {
+      this.returnSmoke?.stopSmoke();
+    }
+  }
+
+  setSmokeFrequency(deviceType, frequency) {
+    const life = (frequency - 30) * 25;
+    let duration = 0;
+    let smoke;
+
+    if (deviceType === 'top') {
+      if (this.topLife == life) {
+        return;
+      }
+      this.topLife = life;
+      smoke = this.topSmoke;
+      duration = (Math.abs(life - smoke.life) / 500) * 25;
+    } else {
+      if (this.downLife == life) {
+        return;
+      }
+      this.downLife = life;
+      smoke = this.downSmoke;
+      duration = (Math.abs(life - smoke.life) / 500) * 25;
+    }
+    if (smoke) {
+      gsap.to(smoke, {
+        life: life,
+        duration: duration,
+        ease: 'easeInCubic',
+        overwrite: true,
+      });
+    }
+  }
+
+  addText(selectData) {
+    if (!this.group) {
+      return;
+    }
+    // @ts-ignore
+    const screenDownText = VENT_PARAM['modalText']
+      ? // @ts-ignore
+        VENT_PARAM['modalText']
+      : // @ts-ignore
+      History_Type['type'] == 'remote'
+      ? `国能神东煤炭集团监制`
+      : '煤炭科学技术研究院有限公司研制';
+
+    const screenDownTextX = 80 - (screenDownText.length - 10) * 6;
+    const textArr = [
+      {
+        text: `智能局部通风机监测与控制系统`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 20,
+        y: 108,
+      },
+      {
+        text: `供风距离(m):`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 152,
+      },
+      {
+        text: `${
+          selectData.airSupplyDistence_merge
+            ? selectData.airSupplyDistence_merge
+            : selectData.fchimenylength
+            ? selectData.fchimenylength
+            : selectData.airSupplyDistence_merge
+            ? selectData.airSupplyDistence_merge
+            : '-'
+        }`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 228,
+        y: 152,
+      },
+      {
+        text: `风筒直径(mm): `,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 200,
+      },
+      {
+        text: ` ${selectData.fchimenydiamlimit ? selectData.fchimenydiamlimit : selectData.ductDiameter_merge ? selectData.ductDiameter_merge : '-'}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 220,
+        y: 200,
+      },
+      {
+        text: `故障诊断:`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 245,
+      },
+      {
+        text: `${selectData.warnLevel_str ? selectData.warnLevel_str : '-'}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 220,
+        y: 245,
+      },
+      {
+        text: `型号功率:`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 285,
+      },
+      {
+        text: `${selectData.model_Power_merge ? selectData.model_Power_merge : '-'}`,
+        font: 'normal 26px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 220,
+        y: 285,
+      },
+      {
+        text: screenDownText,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: screenDownTextX,
+        y: 325,
+      },
+    ];
+    getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
+      const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+      const textMaterial = new THREE.MeshBasicMaterial({
+        // 关于材质并未讲解 实操即可熟悉                 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
+        map: textMap, // 设置纹理贴图
+        transparent: true,
+        side: THREE.FrontSide, // 这里是双面渲染的意思
+      });
+      textMaterial.blending = THREE.CustomBlending;
+      const monitorPlane = this.group?.getObjectByName('monitorText');
+      if (monitorPlane) {
+        // @ts-ignore-next-line
+        monitorPlane.material = textMaterial;
+      } else {
+        const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
+        const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+        planeMesh.name = 'monitorText';
+        planeMesh.scale.set(0.0135, 0.0135, 0.0135);
+        planeMesh.rotation.y = -Math.PI / 2;
+        planeMesh.position.set(-84.79, 0.82, 17.0);
+        this.group?.add(planeMesh);
+      }
+    });
+  }
+
+  addCssText() {
+    if (!this.group) return;
+
+    if (!this.group.getObjectByName('text1')) {
+      const element = document.getElementById('inputBox') as HTMLElement;
+      if (element) {
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text1';
+        fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(-85.68, 5.97, -3.39);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+
+    if (!this.group.getObjectByName('text2')) {
+      const element = document.getElementById('outBox') as HTMLElement;
+      if (element) {
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text2';
+        fanLocalCSS3D.scale.set(0.15, 0.15, 0.15);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(85.62, 17.65, 7.71);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+    if (!this.group.getObjectByName('text3')) {
+      const element = document.getElementById('returnBox') as HTMLElement;
+      if (element) {
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text3';
+        fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(-25.97, 9.3, -15.09);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+    if (!this.group.getObjectByName('text4')) {
+      const element = document.getElementById('gateBox') as HTMLElement;
+      if (element) {
+        // element.innerHTML = '';
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text4';
+        fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(-73.13, 8.44, -23.52);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+    if (!this.group.getObjectByName('text5')) {
+      const element = document.getElementById('windownBox') as HTMLElement;
+      if (element) {
+        // element.innerHTML = '';
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text5';
+        fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(-28.44, 9.78, -40.42);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+    if (!this.group.getObjectByName('text7')) {
+      const element = document.getElementById('inputBox0') as HTMLElement;
+      if (element) {
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text7';
+        fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(-84.23, 4.97, -18.92);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+    if (!this.group.getObjectByName('text6')) {
+      const element = document.getElementById('inputBox1') as HTMLElement;
+      if (element) {
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text6';
+        fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(-84.47, 6.56, -19.47);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+    if (!this.group.getObjectByName('text8')) {
+      const element = document.getElementById('gasBox3') as HTMLElement;
+      if (element) {
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text8';
+        fanLocalCSS3D.scale.set(0.03, 0.03, 0.03);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(-90.04, 6, 5);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+    if (!this.group.getObjectByName('text9')) {
+      const element = document.getElementById('gasBox2') as HTMLElement;
+      if (element) {
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text9';
+        fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(-8, 7.46, -35.28);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+    if (!this.group.getObjectByName('text10')) {
+      const element = document.getElementById('gasBox1') as HTMLElement;
+      if (element) {
+        const fanLocalCSS3D = new CSS3DObject(element);
+        fanLocalCSS3D.name = 'text10';
+        fanLocalCSS3D.scale.set(0.1, 0.1, 0.1);
+        fanLocalCSS3D.rotation.y = -Math.PI / 2;
+        fanLocalCSS3D.position.set(80, 9, -43);
+        this.group.add(fanLocalCSS3D);
+      }
+    }
+  }
+
+  /** 设置模型类型并切换,不同的类型通常对应不同的具体模型,在模型总控制器下的具体模型会根据传入的参数彼此交互、切换 */
+  setModelType(type: 'fm' | 'fc' | string) {
+    this.fanType = type;
+    return new Promise((resolve) => {
+      if (!this.group) return;
+      // 显示双道风窗
+      let childGroup;
+      if (this.fanType === 'fm' && this.fcFanObj && this.fcFanObj.group) {
+        if (this.group?.getObjectByName('jbfj-fc')) {
+          this.group?.remove(this.fcFanObj.group);
+        }
+        childGroup = this.fmFanObj?.group;
+        if (this.group && this.group?.getObjectByName('text5') && this.group?.getObjectByName('text4')) {
+          // @ts-ignore-next-line
+          this.group.getObjectByName('text5')['visible'] = false;
+          // @ts-ignore-next-line
+          this.group.getObjectByName('text4')['visible'] = true;
+        }
+      } else if (this.fanType === 'fc' && this.fmFanObj && this.fmFanObj.group) {
+        // 显示单道风窗
+        if (this.group?.getObjectByName('jbfj-fm')) {
+          this.group?.remove(this.fmFanObj.group);
+        }
+        childGroup = this.fcFanObj?.group;
+        if (this.group && this.group?.getObjectByName('text5') && this.group?.getObjectByName('text4')) {
+          // @ts-ignore-next-line
+          this.group.getObjectByName('text5')['visible'] = true;
+          // @ts-ignore-next-line
+          this.group.getObjectByName('text4')['visible'] = false;
+        }
+      } else {
+        if (this.group?.getObjectByName('jbfj-fc')) {
+          // @ts-ignore-next-line
+          this.group?.remove(this.fcFanObj.group);
+        }
+        if (this.group?.getObjectByName('jbfj-fm')) {
+          // @ts-ignore-next-line
+          this.group?.remove(this.fmFanObj.group);
+        }
+        if (this.group && this.group?.getObjectByName('text5') && this.group?.getObjectByName('text4')) {
+          // @ts-ignore-next-line
+          this.group.getObjectByName('text5')['visible'] = false;
+          // @ts-ignore-next-line
+          this.group.getObjectByName('text4')['visible'] = false;
+        }
+        childGroup = null;
+      }
+      setTimeout(async () => {
+        if (childGroup) this.group?.add(childGroup);
+        // const oldCameraPosition = { x: 615, y: 275, z: 744 };
+        // await animateCamera(
+        //   oldCameraPosition,
+        //   { x: 0, y: 0, z: 0 },
+        //   { x: 0.08, y: 21.73, z: 78.45 },
+        //   { x: 0.13, y: -0.82, z: 0.236 },
+        //   this.model,
+        //   0.8
+        // );
+        resolve(null);
+      }, 300);
+    });
+  }
+
+  clearFly() {
+    if (this.topSmoke) this.topSmoke.clearSmoke();
+    if (this.downSmoke) this.downSmoke.clearSmoke();
+    if (this.returnSmoke) this.returnSmoke.clearSmoke();
+  }
+
+  // 设置模型位置
+  setModalPosition() {
+    if (!this.group) return;
+    this.group.scale.set(0.7, 0.7, 0.7);
+    this.group.position.set(0, 6, -50);
+    this.group.rotation.y = Math.PI / 2;
+  }
+}
+export default ModelContext;

+ 19 - 1
src/views/vent/monitorManager/fanLocalMonitor/fanLocal.threejs.ts

@@ -1,6 +1,7 @@
 import * as THREE from 'three';
 import UseThree from '../../../../utils/threejs/useThree';
 import FanLocal from './fanLocal.threejs.base';
+import FanLocalTwo from './fanLocal.threejs.Two';
 import FanLocalDual from './fanLocalDual.threejs.base';
 import { animateCamera } from '/@/utils/threejs/util';
 import useEvent from '../../../../utils/threejs/useEvent';
@@ -16,7 +17,7 @@ const modelContextList: {
   /** 当前模型类型,在控制器下有多个具体模型时分辨它们 */
   type: string;
   /** 模型的具体内容,即负责模型导入、绘制的上下文对象,一个控制器可以新建多个 */
-  context?: FanLocal | FanLocalDual;
+  context?: FanLocal | FanLocalDual | FanLocalTwo;
 }[] = [];
 const { mouseDownFn } = useEvent();
 
@@ -101,6 +102,10 @@ export function setModelType(modelType: 'fanLocal' | 'fanLocalDual' | string, su
           const oldCameraPosition = { x: 615, y: 275, z: 744 };
           animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: -1.85, y: 13.58, z: 37.39 }, { x: -1.83, y: 2.58, z: -0.75 }, model, 0.8);
         }
+        if (type == 'fanLocalTwo') {
+          const oldCameraPosition = { x: 615, y: 275, z: 744 };
+          animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: -1.85, y: 13.58, z: 37.39 }, { x: -1.83, y: 2.58, z: -0.75 }, model, 0.8);
+        }
         if (type == 'fanLocalDual') {
           // if (!isUpdate) {
           const oldCameraPosition = { x: -693, y: 474, z: 398 };
@@ -132,6 +137,7 @@ export function mountedThree(sceneSelctor: string, cssSelectors: string[]) {
       type: 'fanLocal',
       context: model1,
     });
+
     const model2 = new FanLocalDual(model);
     await model2.mountedThree();
     // 暂时先不加双行
@@ -140,6 +146,15 @@ export function mountedThree(sceneSelctor: string, cssSelectors: string[]) {
       context: model2,
     });
 
+    const model3 = new FanLocalTwo(model);
+    const flag = await model3.mountedThree();
+    debugger;
+    if (flag)
+      modelContextList.push({
+        type: 'fanLocalTwo',
+        context: model3,
+      });
+
     initEventListender();
     setCamera();
     model.animate();
@@ -162,17 +177,20 @@ export function addText(d, e) {
     // @ts-ignore
     modelContextList[0].context?.addText(d);
     modelContextList[1].context?.addText(e);
+    modelContextList[2].context?.addText(e);
   }
 }
 export function addCssText() {
   if (modelContextList[0]) {
     // @ts-ignore
     modelContextList[0].context?.addCssText();
+    modelContextList[2].context?.addCssText();
   }
 }
 export function playSmoke(d) {
   if (modelContextList[0]) {
     // @ts-ignore
     modelContextList[0].context?.playSmoke(d);
+    modelContextList[2].context?.playSmoke(d);
   }
 }

+ 2 - 0
src/views/vent/monitorManager/fanLocalMonitor/index.vue

@@ -1307,6 +1307,7 @@
         // 根据安装类别分辨是单巷还是双巷模型,以及那个风机应该高亮
         if (data['install_kind']) {
           const keymap = {
+            fanLocalTwo: ['fanLocalTwo', modalType.value],
             single: ['fanLocal', modalType.value],
             dual_inner: ['fanLocalDual', 'inner'],
             dual_outer: ['fanLocalDual', 'outer'],
@@ -1316,6 +1317,7 @@
         } else {
           // 为了兼容没有添加 install_kind 的旧的单巷
           mainModelType.value = 'fanLocal';
+          // mainModelType.value = 'fanLocalTwo';
         }
       }
       setModelType(mainModelType.value, modalType.value, fanDualArray.value);

+ 1 - 1
src/views/vent/monitorManager/safetyMonitor/AlarmHistoryTable.vue

@@ -168,7 +168,7 @@
             field: 'startTime',
             label: '开始时间',
             component: 'DatePicker',
-            defaultValue: dayjs().add(-30, 'day').format('YYYY-MM-DD HH:mm:ss'),
+            defaultValue: dayjs().startOf('date'),
             required: true,
             componentProps: {
               showTime: true,

+ 7 - 3
src/views/vent/monitorManager/safetySensorMonitor/AlarmHistoryTable.vue

@@ -58,6 +58,7 @@
   const alarmHistory = ref();
   const columns = ref([]);
   const deviceOptions = ref([]);
+  const deviceTypeOptions = ref(getDictItemsByCode('safetySensorAlarm'));
   const dataTypeName = ref('');
 
   const tableScroll = props.scroll.y ? ref({ y: props.scroll.y - 100 }) : ref({});
@@ -123,6 +124,7 @@
     () => props.deviceType,
     async () => {
       if (alarmHistory.value) getForm().resetFields();
+      dataTypeName.value = deviceTypeOptions.value[0] ? deviceTypeOptions.value[0]['value'] : '';
       await getDeviceList();
     }
   );
@@ -169,7 +171,7 @@
             field: 'startTime',
             label: '开始时间',
             component: 'DatePicker',
-            defaultValue: dayjs().add(-30, 'day').format('YYYY-MM-DD HH:mm:ss'),
+            defaultValue: dayjs().startOf('date'),
             required: true,
             componentProps: {
               showTime: true,
@@ -198,9 +200,10 @@
           {
             label: '设备类型',
             field: 'dataTypeName',
-            component: 'ApiSelect',
+            component: 'Select',
+            defaultValue: deviceTypeOptions.value[0] ? deviceTypeOptions.value[0]['value'] : '',
             componentProps: {
-              api: getDictItemsByCode.bind(null, 'safetySensorAlarm'),
+              options: deviceTypeOptions.value,
               onChange: async (e, option) => {
                 dataTypeName.value = e;
                 await getDeviceList();
@@ -252,6 +255,7 @@
   const [registerTable, { reload, setLoading, getForm }] = tableContext;
 
   onMounted(async () => {
+    dataTypeName.value = deviceTypeOptions.value[0] ? deviceTypeOptions.value[0]['value'] : '';
     await getDeviceList();
   });
 

+ 39 - 0
src/views/vent/monitorManager/safetySensorMonitor/safety.api.ts

@@ -0,0 +1,39 @@
+import { defHttp } from '/@/utils/http/axios';
+
+enum Api {
+  list = '/monitor/device',
+  baseList = '/safety/ventanalyDeviceInfo/list',
+  deviceTypeList = '/safety/ventanalyDeviceInfo/DeviceKind/queryBySystem',
+  itemList = '/sys/dictItem/list',
+  safetyDeviceList = '/monitor/codeDict',
+  safetyList = '/monitor/history/getAlarmHistoryData',
+  export = '/safety/reportInfo/expComReport?tempName=aqjk',
+  subStationList = '/safety/ventanalySubStation/alllist',
+  initSubStation = '/monitor/initKafkaDeviceInfo',
+}
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) => defHttp.post({ url: Api.list, params });
+
+// 分站查询接口
+export const subStationList = (params) => defHttp.get({ url: Api.subStationList, params });
+// 同步分站
+export const initSubStation = (data) => defHttp.post({ url: Api.initSubStation, data });
+
+export const safetyList = (params) => defHttp.post({ url: Api.safetyList, params });
+
+export const safetyDeviceList = (params) => defHttp.post({ url: Api.safetyDeviceList, params });
+
+/**
+ * 保存或者更新用户
+ * @param params
+ */
+export const getDeviceList = (params) => defHttp.get({ url: Api.baseList, params });
+
+export const getDeviceTypeList = (params) => defHttp.get({ url: Api.deviceTypeList, params });
+
+export const itemList = (params) => defHttp.get({ url: Api.itemList, params });
+
+export const getExportUrl = Api.export;

+ 226 - 0
src/views/vent/monitorManager/safetySensorMonitor/safety.data.ts

@@ -0,0 +1,226 @@
+import { safetyDeviceList } from './safety.api';
+
+export const chartsColumns = (deviceType) => {
+  if (deviceType === '') {
+    return [];
+  }
+};
+
+export const formConfig = {
+  labelAlign: 'left',
+  showAdvancedButton: false,
+  showResetButton: false,
+  showSubmitButton: false,
+  schemas: [
+    {
+      label: '设备类型',
+      field: 'dataTypeName',
+      component: 'ApiSelect',
+      componentProps: {
+        api: safetyDeviceList.bind(null, { devicetype: 'safetymonitor', code: 'dataTypeName' }),
+        labelField: 'name',
+        valueField: 'code',
+      },
+    },
+    {
+      label: '设备安装地点',
+      field: 'strinstallpos',
+      component: 'Input',
+    },
+  ],
+};
+
+//测风装置
+export const chartsColumnsRect = [
+  {
+    legend: '风量',
+    seriesName: '(m³/min)',
+    ymax: 10000,
+    yname: 'm³/min',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#37BCF2',
+    sort: 1,
+    xRotate: 0,
+    dataIndex: 'm³',
+  },
+  {
+    legend: '气源压力',
+    seriesName: '(MPa)',
+    ymax: 50,
+    yname: 'MPa',
+    linetype: 'line',
+    yaxispos: 'right',
+    color: '#FC4327',
+    sort: 2,
+    xRotate: 0,
+    dataIndex: 'sourcePressure',
+  },
+];
+
+//局部风机
+export const chartsColumnsFan = [
+  {
+    legend: '风筒风量1',
+    seriesName: '(m³/min)',
+    ymax: 1000,
+    yname: 'm³/min',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#37BCF2',
+    sort: 1,
+    xRotate: 0,
+    dataIndex: 'windQuantity1',
+  },
+  {
+    legend: '风筒风量2',
+    seriesName: '(m³/min)',
+    ymax: 1000,
+    yname: 'm³/min',
+    linetype: 'line',
+    yaxispos: 'right',
+    color: '#FC4327',
+    sort: 2,
+    xRotate: 0,
+    dataIndex: 'windQuantity2',
+  },
+];
+
+//主风
+export const chartsColumnsMain = [
+  {
+    legend: '风量',
+    seriesName: '(m³/min)',
+    ymax: 1000,
+    yname: 'm³/min',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#37BCF2',
+    sort: 1,
+    xRotate: 0,
+    dataIndex: 'windQuantity1',
+  },
+  {
+    legend: '频率',
+    seriesName: '(Hz)',
+    ymax: 1000,
+    yname: 'Hz',
+    linetype: 'line',
+    yaxispos: 'right',
+    color: '#FC4327',
+    sort: 2,
+    xRotate: 0,
+    dataIndex: 'windQuantity2',
+  },
+];
+//光钎测温
+export const chartsColumnsFiber = [
+  {
+    legend: '最高温度',
+    seriesName: '(°C)',
+    ymax: 100,
+    yname: '°C',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#37BCF2',
+    sort: 1,
+    xRotate: 0,
+    dataIndex: 'fmax',
+  },
+  {
+    legend: '平均温度',
+    seriesName: '(°C)',
+    ymax: 100,
+    yname: '°C',
+    linetype: 'line',
+    yaxispos: 'right',
+    color: '#FC4327',
+    sort: 2,
+    xRotate: 0,
+    dataIndex: 'favg',
+  },
+];
+//密闭
+export const chartsColumnsObf = [
+  {
+    legend: '温度',
+    seriesName: '(°C)',
+    ymax: 100,
+    yname: '°C',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#37BCF2',
+    sort: 1,
+    xRotate: 0,
+    dataIndex: 'temperature',
+  },
+  {
+    legend: 'O2浓度',
+    seriesName: '(%)',
+    ymax: 100,
+    yname: '%',
+    linetype: 'line',
+    yaxispos: 'right',
+    color: '#FC4327',
+    sort: 2,
+    xRotate: 0,
+    dataIndex: 'o2val',
+  },
+];
+
+//束管
+
+export const chartsColumnsBun = [
+  {
+    legend: 'CO浓度',
+    seriesName: '(%)',
+    ymax: 100,
+    yname: '%',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#37BCF2',
+    sort: 1,
+    xRotate: 0,
+    dataIndex: 'coval',
+  },
+  {
+    legend: 'CO2浓度',
+    seriesName: '(%)',
+    ymax: 100,
+    yname: '%',
+    linetype: 'line',
+    yaxispos: 'right',
+    color: '#FC4327',
+    sort: 2,
+    xRotate: 0,
+    dataIndex: 'co2val',
+  },
+];
+
+export const chartsColumnsreal = [
+  {
+    legend: '压差',
+    seriesName: '(Pa)',
+    ymax: 100,
+    yname: 'Pa',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#37BCF2',
+    sort: 1,
+    xRotate: 0,
+    dataIndex: 'frontRearDP',
+  },
+  {
+    legend: '气源压力',
+    seriesName: '(MPa)',
+    ymax: 50,
+    yname: 'MPa',
+    linetype: 'line',
+    yaxispos: 'right',
+    color: '#FC4327',
+    sort: 2,
+    xRotate: 0,
+    dataIndex: 'sourcePressure',
+  },
+];
+export const isHaveNoAction = ['safetymonitor', 'wasichoufang'];