hongrunxia 2 viikkoa sitten
vanhempi
commit
2a93d7851b

+ 185 - 0
src/views/vent/deviceManager/comment/DeviceReportInfo.vue

@@ -0,0 +1,185 @@
+<template>
+  <BasicForm ref="FormRef" @register="registerForm"/>
+  <div class="j-box-bottom-button offset-20" style="margin-top: 30px">
+    <div class="j-box-bottom-button-float">
+      <a-button preIcon="ant-design:sync-outlined" @click="onReset">重置</a-button>
+      <a-button type="primary" preIcon="ant-design:save-filled" @click="handleSubmit">保存</a-button>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+
+import { onMounted, ref, defineEmits, onUnmounted, watch, PropType, nextTick, inject, onBeforeMount } from 'vue';
+import { BasicForm, useForm } from '/@/components/Form/index';
+import { FormSchema } from '/@/components/Form';
+import { getFormSchemaColumns } from '/@/hooks/web/useWebColumns';
+import { list as substationList } from '/@/views/vent/deviceManager/substationTabel/substation.api';
+import {list, updateReportInfo, sysList, sysInput } from '../../monitorManager/comment/comment.api'
+const deviceData = inject('formData') as any;
+const emit = defineEmits(['close', 'register'])
+const FormRef = ref()
+const tabType = ref('')
+
+const formSchema = ref<any[]>([])
+const formData = ref(deviceData)
+const deviceTypeName = ref(deviceData.devicekind ? deviceData.devicekind : deviceData.strtype)
+
+const arrToFormColumns = (tableHeaderColumns = [], devicetype) => {
+  const columnList: any[] = [];
+  tableHeaderColumns.forEach((item: any) => {
+    let columnsItem;
+    if (item.type == 1 || item.type == 10) {
+      columnsItem = {
+        label: item.des, //_dictText
+        field: item.monitorcode,
+        component: item.type == 1 ? 'Input' : item.type == 10 ? 'InputTextArea' : '',
+      };
+    } else {
+      if (item.type == 2 && item['monitorcode'] == 'nsubstationid') {
+        columnsItem = {
+          label: item.des, //_dictText
+          field: item.monitorcode,
+          component: 'ApiSelect',
+          componentProps: {
+            api: substationList,
+            labelField: 'strname',
+            valueField: 'id',
+          },
+        };
+      }
+      if (item.type == 3) {
+        columnsItem = {
+          label: item.des, //_dictText
+          field: item.monitorcode,
+          component: 'RadioGroup',
+          defaultValue: 1,
+          componentProps: () => {
+            return {
+              options: [
+                { label: '是', value: 1, key: '1' },
+                { label: '否', value: 0, key: '2' },
+              ],
+              stringToNumber: true,
+            };
+          },
+        };
+      }
+      if (item.type == 4) {
+        columnsItem = {
+          label: item.des, //_dictText
+          field: item.monitorcode,
+          component: 'JDictSelectTag',
+          componentProps: {
+            dictCode: item.dict,
+            placeholder: '请选择',
+            stringToNumber: true,
+          },
+        };
+      }
+    }
+    columnList.push(columnsItem);
+  });
+  formSchema.value = columnList
+  if(tabType.value === 'deviceInfo'){
+    formSchema.value.unshift(
+      {
+        label: '设备id', //_dictText
+        field: 'id',
+        component: 'Input',
+        componentProps: {
+          disabled: true,
+          show: false
+        },
+      },
+      {
+        label: '点表',
+        field: 'strtype',
+        component: 'JDictSelectTag',
+        componentProps: {
+          dictCode: `${devicetype.split('_')[0]}kind`,
+          placeholder: '请选择点表',
+        },
+      })
+      formSchema.value.push(
+      {
+        label: '备用分站',
+        field: 'stationids',
+        component: 'ApiSelect',
+        componentProps: {
+          api: substationList,
+          labelField: 'strname',
+          valueField: 'id',
+        },
+      },
+    )
+  }else{
+    formSchema.value.unshift(
+      {
+        label: '设备id', //_dictText
+        field: 'id',
+        component: 'Input',
+        componentProps: {
+          disabled: true,
+          show: false
+        },
+      })
+  }
+};
+
+const [registerForm, { resetSchema, getFieldsValue, setFieldsValue, resetFields }] = useForm({
+  schemas: <FormSchema[]>formSchema.value,
+  showActionButtonGroup: false,
+});
+
+function getColumns() {
+  let formSchemaArr = getFormSchemaColumns( `${deviceData.devicekind ? deviceData.devicekind : deviceData.strtype}_input`) || []
+  if (formSchemaArr && formSchemaArr.length < 1) {
+    const arr = deviceTypeName.value.split('_')
+    formSchemaArr = getFormSchemaColumns(arr[0] + '_input') || []
+  }
+  arrToFormColumns(formSchemaArr, deviceTypeName.value)
+  resetSchema(formSchema.value)
+} 
+
+
+async function onReset() {
+  await resetFields();
+  await setFieldsValue({ ...deviceData });
+}
+
+async function handleSubmit() {
+  const data = await getFieldsValue()
+  if(!deviceData.devicekind) {
+    await sysInput(data)
+  }else{
+    await updateReportInfo(data)
+  }
+  
+}
+
+onBeforeMount(async() => {
+  
+})
+
+onMounted(async () => {
+  getColumns()
+  let result;
+  debugger;
+  if(!deviceData.devicekind) {
+     result = await sysList({ id: deviceData.id })
+  }else{
+     result = await list({ id: deviceData.id })
+  }
+  formData.value = result['records'][0] || []
+  await setFieldsValue({
+    ...formData.value,
+  });
+});
+onUnmounted(() => {
+
+});
+</script>
+<style scoped lang="less">
+@import '/@/design/vent/color.less';
+@import '/@/design/vent/modal.less';
+</style>

+ 297 - 0
src/views/vent/monitorManager/windowMonitor/dandaoFcYjl.threejs.ts

@@ -0,0 +1,297 @@
+import * as THREE from 'three';
+
+import { getTextCanvas, renderVideo } from '/@/utils/threejs/util';
+import gsap from 'gsap';
+
+class singleWindowYjl {
+  model;
+  modelName = 'ddFcGroup';
+  group: THREE.Object3D = new THREE.Object3D();
+  animationTimer;
+  isLRAnimation = true;
+  direction = 1;
+  windowsActionArr = {
+    frontWindow: [],
+  };
+  player1;
+  player2;
+  playerStartClickTime1 = new Date().getTime();
+  constructor(model) {
+    this.model = model;
+    this.group.name = 'ddFcGroup';
+  }
+  addLight = () => {
+    if (!this.group || !this.group) return;
+
+    const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
+    directionalLight.position.set(-437, 61, 559);
+    this.group.add(directionalLight);
+  };
+  // 设置模型位置
+  setModalPosition() {
+    this.group?.scale.set(22, 22, 22);
+    this.group?.position.set(-35, 25, 15);
+  }
+
+  addMonitorText(selectData) {
+    if (!this.group) {
+      return;
+    }
+    const screenDownText = VENT_PARAM['modalText']
+      ? VENT_PARAM['modalText']
+      : History_Type['type'] == 'remote'
+      ? `国能神东煤炭集团监制`
+      : '煤炭科学技术研究院有限公司研制';
+
+    const screenDownTextX = 90 - (screenDownText.length - 10) * 6;
+    const textArr = [
+      {
+        text: `远程定量调节自动风窗`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 100,
+        y: 95,
+      },
+      {
+        text: `${selectData.OpenDegree ? '开度值(%)' : selectData.forntArea ? '过风面积(㎡)' : '过风面积(㎡)'}:`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 5,
+        y: 145,
+      },
+      {
+        text: selectData.OpenDegree
+          ? Number(`${selectData.OpenDegree}`).toFixed(2)
+          : selectData.forntArea
+          ? Number(`${selectData.forntArea}`).toFixed(2)
+          : '-',
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 330,
+        y: 145,
+      },
+      {
+        text: `${selectData.frontRearDP ? '风窗压差(Pa)' : selectData.windSpeed ? '风速(m/s)' : '通信状态:'}:`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 5,
+        y: 200,
+      },
+      {
+        text: `${
+          selectData.frontRearDP
+            ? selectData.frontRearDP
+            : selectData.windSpeed
+            ? selectData.windSpeed
+            : selectData.netStatus == '0'
+            ? '断开'
+            : '连接'
+        }`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 330,
+        y: 200,
+      },
+      {
+        text: `${selectData.fWindowM3 ? '过风量(m³/min)' : '风窗道数'}: `,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 5,
+        y: 250,
+      },
+      {
+        text: `${selectData.fWindowM3 ? selectData.fWindowM3 : selectData.nwindownum}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 330,
+        y: 250,
+      },
+      {
+        text: screenDownText,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: screenDownTextX,
+        y: 300,
+      },
+    ];
+    getTextCanvas(750, 546, textArr, '').then((canvas: HTMLCanvasElement) => {
+      const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+      const textMaterial = new THREE.MeshBasicMaterial({
+        // 关于材质并未讲解 实操即可熟悉                 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
+        map: textMap, // 设置纹理贴图
+        transparent: true,
+        side: THREE.DoubleSide, // 这里是双面渲染的意思
+      });
+      textMap.dispose();
+      textMaterial.blending = THREE.CustomBlending;
+      const monitorPlane = this.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.0038, 0.004, 0.0038);
+        planeMesh.position.set(4.44, -0.165, -0.46);
+        this.group?.add(planeMesh);
+      }
+    });
+  }
+
+  /* 提取风门序列帧,初始化前后门动画 */
+  initAnimation() {
+    const meshArr01: THREE.Object3D[] = [];
+    this.group?.children.forEach((obj) => {
+      if (obj.type === 'Mesh' && obj.name && obj.name.startsWith('FCshanye')) {
+        obj.rotateOnAxis(new THREE.Vector3(0, 1, 0), 0);
+        meshArr01.push(obj);
+      }
+    });
+    this.windowsActionArr.frontWindow = meshArr01;
+  }
+
+  play(rotationParam, flag) {
+    if (!this.windowsActionArr.frontWindow) {
+      return;
+    }
+    if (flag === 1) {
+      // 前风窗动画
+      this.windowsActionArr.frontWindow.forEach((mesh: THREE.Mesh) => {
+        gsap.to(mesh.rotation, {
+          y: THREE.MathUtils.degToRad(rotationParam.frontDeg1),
+          duration: (1 / 9) * Math.abs(rotationParam.frontDeg1 - mesh.rotation.y),
+          overwrite: true,
+        });
+      });
+    } else if (flag === 0) {
+      ([...this.windowsActionArr.frontWindow] as THREE.Mesh[]).forEach((mesh) => {
+        gsap.to(mesh.rotation, {
+          y: 0,
+          overwrite: true,
+        });
+      });
+    }
+  }
+
+  /* 点击风窗,风窗全屏 */
+  mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {
+    this.isLRAnimation = false;
+    if (this.animationTimer) {
+      clearTimeout(this.animationTimer);
+      this.animationTimer = null;
+    }
+    // 判断是否点击到视频
+    intersects.find((intersect) => {
+      const mesh = intersect.object;
+      if (mesh.name === 'player1') {
+        if (new Date().getTime() - this.playerStartClickTime1 < 400) {
+          // 双击,视频放大
+          if (this.player1) {
+            this.player1.requestFullscreen();
+          }
+        }
+        this.playerStartClickTime1 = new Date().getTime();
+        return true;
+      }
+      return false;
+    });
+  }
+
+  mouseUpModel() {
+    // 10s后开始摆动
+    if (!this.animationTimer && !this.isLRAnimation) {
+      this.animationTimer = setTimeout(() => {
+        this.isLRAnimation = true;
+      }, 10000);
+    }
+  }
+
+  /* 风门动画 */
+  render() {
+    if (!this.model) {
+      return;
+    }
+    if (this.isLRAnimation && this.group) {
+      // 左右摇摆动画
+      if (Math.abs(this.group.rotation.y) >= 0.2) {
+        this.direction = -this.direction;
+        this.group.rotation.y += 0.00002 * 30 * this.direction;
+      } else {
+        this.group.rotation.y += 0.00002 * 30 * this.direction;
+      }
+    }
+  }
+
+  async initCamera(dom1?) {
+    const videoPlayer1 = dom1;
+    let monitorPlane: THREE.Mesh | null = null;
+    const canvas = await getTextCanvas(320, 180, '', 'noSinge.png');
+    const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+    const textMaterial = new THREE.MeshBasicMaterial({
+      map: textMap, // 设置纹理贴图
+      transparent: true,
+      side: THREE.DoubleSide, // 这里是双面渲染的意思
+    });
+    textMaterial.blending = THREE.CustomBlending;
+    monitorPlane = this.group?.getObjectByName('noPlayer');
+    if (monitorPlane) {
+      monitorPlane.material = textMaterial;
+    } else {
+      const planeGeometry = new THREE.PlaneGeometry(100, 100); // 平面3维几何体PlaneGeometry
+      monitorPlane = new THREE.Mesh(planeGeometry, textMaterial);
+      textMaterial.dispose();
+      planeGeometry.dispose();
+    }
+    const videoPlayer = this.group.getObjectByName('player1');
+    if (videoPlayer) {
+      this.model.clearMesh(videoPlayer);
+      this.group.remove(videoPlayer);
+    }
+    const noPlayer1 = this.group.getObjectByName('noPlayer1');
+    if (noPlayer1) {
+      this.model.clearMesh(noPlayer1);
+      this.group.remove(noPlayer1);
+    }
+    if (!videoPlayer1 && videoPlayer1 === null) {
+      monitorPlane.name = 'noPlayer1';
+      monitorPlane.scale.set(0.015, 0.007, 0.011);
+      monitorPlane.position.set(4.04, 0.02, -0.46);
+      this.group?.add(monitorPlane);
+    } else if (videoPlayer1) {
+      const mesh = renderVideo(this.group, videoPlayer1, 'player1');
+      if (mesh) {
+        mesh?.scale.set(-0.038, 0.029, 1);
+        mesh?.position.set(-4.302, 0.15, -0.23);
+        mesh.rotation.y = -Math.PI;
+        this.group.add(mesh);
+      }
+    }
+  }
+
+  mountedThree() {
+    return new Promise((resolve) => {
+      this.model.setGLTFModel(['ddFc-yjl'], this.group).then(() => {
+        this.setModalPosition();
+        this.initAnimation();
+        this.addLight();
+        resolve(null);
+      });
+    });
+  }
+
+  destroy() {
+    this.model.clearGroup(this.group);
+    this.windowsActionArr.frontWindow = undefined;
+    this.model = null;
+    this.group = null;
+  }
+}
+export default singleWindowYjl;

+ 357 - 0
src/views/vent/monitorManager/windowMonitor/shuangdaoFcYjl.threejs.ts

@@ -0,0 +1,357 @@
+import * as THREE from 'three';
+import { getTextCanvas, renderVideo } from '/@/utils/threejs/util';
+import gsap from 'gsap';
+
+class doubleWindowYjl {
+  model;
+  modelName = 'sdFc';
+  group: THREE.Object3D = new THREE.Object3D();
+  animationTimer;
+  isLRAnimation = true;
+  direction = 1;
+  windowsActionArr = {
+    frontWindow: <THREE.Mesh[]>[],
+    backWindow: <THREE.Mesh[]>[],
+  };
+  playerStartClickTime1 = new Date().getTime();
+  playerStartClickTime2 = new Date().getTime();
+
+  constructor(model) {
+    this.model = model;
+    // this.group.name = this.modelName;
+  }
+
+  // 设置模型位置
+  setModalPosition() {
+    // this.group.getObjectByName(this.modelName)?.scale.set(9, 9, 9);
+    // this.group?.scale.set(22, 22, 22);
+    // this.group?.position.set(-15, 25, 15);
+  }
+
+  addMonitorText(selectData) {
+    if (!this.group) {
+      return;
+    }
+    const screenDownText = VENT_PARAM['modalText']
+      ? VENT_PARAM['modalText']
+      : History_Type['type'] == 'remote'
+      ? `国能神东煤炭集团监制`
+      : '煤炭科学技术研究院有限公司研制';
+
+    const screenDownTextX = 120 - (screenDownText.length - 10) * 6;
+    const textArr = [
+      {
+        text: `远程定量调节自动风窗`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 95,
+        y: 97,
+      },
+      {
+        text: `${selectData.OpenDegree ? '开度值(%)' : selectData.forntArea ? '过风面积(㎡)' : '过风面积(㎡)'}:`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 5,
+        y: 150,
+      },
+      {
+        text: selectData.OpenDegree
+          ? Number(`${selectData.OpenDegree}`).toFixed(2)
+          : selectData.forntArea
+          ? Number(`${selectData.forntArea}`).toFixed(2)
+          : '-',
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 330,
+        y: 150,
+      },
+      {
+        text: `${selectData.frontRearDP ? '风窗压差(Pa)' : selectData.windSpeed ? '风速' : '通信状态'}:`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 5,
+        y: 210,
+      },
+      {
+        text: `${
+          selectData.frontRearDP
+            ? selectData.frontRearDP
+            : selectData.windSpeed
+            ? selectData.windSpeed
+            : selectData.netStatus == '0'
+            ? '断开'
+            : '连接'
+        }`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 325,
+        y: 210,
+      },
+      {
+        text: `${selectData.fWindowM3 ? '过风量(m³/min)' : '风窗道数'}: `,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 5,
+        y: 266,
+      },
+      {
+        text: `${selectData.fWindowM3 ? selectData.fWindowM3 : selectData.nwindownum}`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 330,
+        y: 266,
+      },
+
+      {
+        text: screenDownText,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: screenDownTextX,
+        y: 322,
+      },
+    ];
+
+    getTextCanvas(570, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
+      const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+      const textMaterial = new THREE.MeshBasicMaterial({
+        // 关于材质并未讲解 实操即可熟悉                 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
+        map: textMap, // 设置纹理贴图
+        transparent: true,
+        side: THREE.DoubleSide, // 这里是双面渲染的意思
+      });
+      textMaterial.blending = THREE.CustomBlending;
+      const monitorPlane = this.group?.getObjectByName('monitorText');
+      if (monitorPlane) {
+        monitorPlane.material = textMaterial;
+      } else {
+        const planeGeometry = new THREE.PlaneGeometry(570, 346); // 平面3维几何体PlaneGeometry
+        const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+        planeMesh.name = 'monitorText';
+        planeMesh.scale.set(0.0018, 0.0018, 0.0018);
+        planeMesh.position.set(4.04, 0.178, -0.2);
+        this.group?.add(planeMesh);
+      }
+      textMap.dispose();
+    });
+  }
+
+  /* 风门动画 */
+  render() {
+    if (!this.model) {
+      return;
+    }
+    if (this.isLRAnimation && this.group) {
+      // 左右摇摆动画
+      if (Math.abs(this.group.rotation.y) >= 0.2) {
+        this.direction = -this.direction;
+        this.group.rotation.y += 0.00002 * 30 * this.direction;
+      } else {
+        this.group.rotation.y += 0.00002 * 30 * this.direction;
+      }
+    }
+  }
+
+  /* 提取风门序列帧,初始化前后门动画 */
+  initAnimation() {
+    const meshArr01: THREE.Object3D[] = [];
+    const meshArr02: THREE.Object3D[] = [];
+    const windowGroup = new THREE.Group();
+    windowGroup.name = 'hiddenGroup';
+    this.group.getObjectByName('sdFc')?.children.forEach((obj) => {
+      if (obj.type === 'Mesh' && obj.name && (obj.name.startsWith('shanye') || obj.name.startsWith('FCshanye'))) {
+        if (obj.name.startsWith('FCshanye')) {
+          obj.rotateOnAxis(new THREE.Vector3(0, 1, 0), 0);
+          meshArr01.push(obj);
+        } else if (obj.name.startsWith('shanye')) {
+          obj.rotateOnAxis(new THREE.Vector3(0, 1, 0), 0);
+          meshArr02.push(obj);
+        }
+      }
+    });
+    this.windowsActionArr.frontWindow = meshArr01;
+    this.windowsActionArr.backWindow = meshArr02;
+    this.group?.add(windowGroup);
+  }
+
+  /* 点击风窗,风窗全屏 */
+  mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {
+    this.isLRAnimation = false;
+    if (this.animationTimer) {
+      clearTimeout(this.animationTimer);
+      this.animationTimer = null;
+    }
+    // 判断是否点击到视频
+    intersects.find((intersect) => {
+      const mesh = intersect.object;
+      return false;
+    });
+  }
+
+  mouseUpModel() {
+    // 10s后开始摆动
+    if (!this.animationTimer && !this.isLRAnimation) {
+      this.animationTimer = setTimeout(() => {
+        this.isLRAnimation = true;
+      }, 10000);
+    }
+  }
+
+  play(rotationParam, flag) {
+    if (this.windowsActionArr.frontWindow.length <= 0 || this.windowsActionArr.backWindow.length <= 0) {
+      return;
+    }
+    if (flag === 1) {
+      // 前风窗动画
+      this.windowsActionArr.frontWindow.forEach((mesh) => {
+        gsap.to(mesh.rotation, {
+          y: THREE.MathUtils.degToRad(rotationParam.frontDeg1),
+          duration: (1 / 9) * Math.abs(rotationParam.frontDeg1 - mesh.rotation.y),
+          overwrite: true,
+        });
+      });
+    } else if (flag === 2) {
+      // 后风窗动画
+      this.windowsActionArr.backWindow.forEach((mesh) => {
+        gsap.to(mesh.rotation, {
+          y: THREE.MathUtils.degToRad(rotationParam.backDeg1),
+          duration: (1 / 9) * Math.abs(rotationParam.backDeg1 - mesh.rotation.y),
+          overwrite: true,
+        });
+      });
+    } else if (flag === 0) {
+      ([...this.windowsActionArr.frontWindow, ...this.windowsActionArr.backWindow] as THREE.Mesh[]).forEach((mesh) => {
+        gsap.to(mesh.rotation, {
+          y: 0,
+          overwrite: true,
+        });
+      });
+    }
+  }
+
+  async initCamera(dom1?, dom2?) {
+    const videoPlayer1 = dom1;
+    const videoPlayer2 = dom2;
+    let monitorPlane: THREE.Mesh | null = null;
+    if (!videoPlayer1 || !videoPlayer2) {
+      const textArr = [
+        {
+          text: `无信号输入`,
+          font: 'normal 40px Arial',
+          color: '#009900',
+          strokeStyle: '#002200',
+          x: 170,
+          y: 40,
+        },
+      ];
+      const canvas = await getTextCanvas(320, 180, '', 'noSinge.png');
+      let textMaterial: THREE.MeshBasicMaterial | null = null;
+      if (canvas) {
+        const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+        textMaterial = new THREE.MeshBasicMaterial({
+          map: textMap, // 设置纹理贴图
+          transparent: true,
+          side: THREE.DoubleSide, // 这里是双面渲染的意思
+        });
+        textMaterial.blending = THREE.CustomBlending;
+
+        const planeGeometry = new THREE.PlaneGeometry(100, 100); // 平面3维几何体PlaneGeometry
+        monitorPlane = new THREE.Mesh(planeGeometry, textMaterial);
+
+        textMaterial.dispose();
+        planeGeometry.dispose();
+        textMap.dispose();
+      }
+    }
+    const player1 = this.group.getObjectByName('player1');
+    if (player1) {
+      this.model.clearMesh(player1);
+      this.group.remove(player1);
+    }
+    const noPlayer1 = this.group.getObjectByName('noPlayer1');
+    if (noPlayer1) {
+      this.model.clearMesh(noPlayer1);
+      this.group.remove(noPlayer1);
+    }
+    if (!videoPlayer1 && videoPlayer1 === null) {
+      if (monitorPlane && !this.group.getObjectByName('noPlayer1')) {
+        const planeMesh = monitorPlane.clone();
+        planeMesh.name = 'noPlayer1';
+        planeMesh.scale.set(0.011, 0.0053, 0.012);
+        planeMesh.position.set(-4.3, 0.13, -0.23);
+        this.group?.add(planeMesh.clone());
+      }
+    } else if (videoPlayer1) {
+      try {
+        const mesh = renderVideo(this.group, videoPlayer1, 'player1');
+        if (mesh) {
+          mesh?.scale.set(-0.034, 0.024, 1);
+          mesh?.position.set(-3.332, 0.11, -0.23);
+          mesh.rotation.y = -Math.PI;
+          this.group.add(mesh);
+        }
+      } catch (error) {
+        console.log('视频信号异常');
+      }
+    }
+    const player2 = this.group.getObjectByName('player2');
+    if (player2) {
+      this.model.clearMesh(player2);
+      this.group.remove(player2);
+    }
+    const noPlayer2 = this.group.getObjectByName('noPlayer2');
+    if (noPlayer2) {
+      this.model.clearMesh(noPlayer2);
+      this.group.remove(noPlayer2);
+    }
+    if (!videoPlayer2 && videoPlayer2 === null) {
+      if (monitorPlane && !this.group.getObjectByName('noPlayer2')) {
+        const planeMesh = monitorPlane.clone();
+        planeMesh.name = 'noPlayer2';
+        planeMesh.scale.set(0.0085, 0.0056, 0.012);
+        planeMesh.position.set(4.29, 0.02, -0.41);
+        this.group?.add(planeMesh.clone());
+      }
+    } else if (videoPlayer2) {
+      try {
+        const mesh = renderVideo(this.group, videoPlayer2, 'player2');
+        if (mesh) {
+          mesh?.scale.set(-0.034, 0.024, 1);
+          mesh?.position.set(-3.332, 0.11, -0.23);
+          mesh.rotation.y = -Math.PI;
+          this.group.add(mesh);
+        }
+      } catch (error) {
+        console.log('视频信号异常');
+      }
+    }
+  }
+
+  mountedThree(playerDom) {
+    return new Promise((resolve) => {
+      this.model.setGLTFModel(['sdFc-yjl'], this.group).then(() => {
+        this.setModalPosition();
+        this.initAnimation();
+        resolve(null);
+        // this.initCamera(playerDom);
+      });
+    });
+  }
+
+  destroy() {
+    this.model.clearGroup(this.group);
+    this.windowsActionArr.frontWindow = undefined;
+    this.windowsActionArr.backWindow = undefined;
+    this.model = null;
+    this.group = null;
+  }
+}
+
+export default doubleWindowYjl;

+ 32 - 5
src/views/vent/monitorManager/windowMonitor/window.threejs.ts

@@ -6,6 +6,7 @@ import singleWindowXk from './dandaoFcXk.threejs';
 import { animateCamera } from '/@/utils/threejs/util';
 import useEvent from '../../../../utils/threejs/useEvent';
 import { useGlobSetting } from '/@/hooks/setting';
+import { modal } from 'vxe-table';
 
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
@@ -81,6 +82,7 @@ const mouseEvent = (event) => {
         singleWindowXkObj.mousedownModel.call(singleWindowXkObj, intersects);
       }
     });
+    console.log('摄像头控制信息', model.orbitControls, model.camera);
   }
 };
 
@@ -149,7 +151,7 @@ export const play = (rotationParam, flag) => {
 // 切换风窗类型
 export const setModelType = (type) => {
   // if (!model || !model.scene) return;
-
+  const { sysOrgCode } = useGlobSetting();
   windowType = type;
   return new Promise((resolve) => {
     // 显示双道风窗
@@ -158,10 +160,18 @@ export const setModelType = (type) => {
       model.scene?.remove(group);
       group = doubleWindowObj.group;
       const oldCameraPosition = { x: 100, y: 0, z: 10 };
+      let newP, newT;
+      if (sysOrgCode === 'sdmtjtyjlmk') {
+        newP = { x: 34.294433107431956, y: 19.284123769585108, z: 47.717286013509835 };
+        newT = { x: 12.311816240141978, y: -5.691930035759495, z: -5.57302688985693 };
+      } else {
+        newP = { x: 66.257, y: 57.539, z: 94.313 };
+        newT = { x: 0, y: 0, z: 0 };
+      }
       model.scene?.add(doubleWindowObj.group);
       setTimeout(async () => {
         resolve(null);
-        await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: 66.257, y: 57.539, z: 94.313 }, { x: 0, y: 0, z: 0 }, model);
+        await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, newP, newT, model);
       }, 1000);
     } else if (windowType === 'singleWindow') {
       // 显示单道风窗
@@ -169,10 +179,18 @@ export const setModelType = (type) => {
       model.scene?.remove(group);
       group = singleWindowObj.group;
       const oldCameraPosition = { x: 100, y: 0, z: 10 };
+      let newP, newT;
+      if (sysOrgCode === 'sdmtjtyjlmk') {
+        newP = { x: 66.257, y: 57.539, z: 94.313 };
+        newT = { x: 0, y: 0, z: 0 };
+      } else {
+        newP = { x: 66.257, y: 57.539, z: 94.313 };
+        newT = { x: 0, y: 0, z: 0 };
+      }
       model.scene?.add(singleWindowObj.group);
       setTimeout(async () => {
         resolve(null);
-        await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: 66.257, y: 57.539, z: 94.313 }, { x: 0, y: 0, z: 0 }, model);
+        await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, newP, newT, model);
       }, 1000);
     } else if (windowType === 'singleXkWindow') {
       // 显示单道风窗
@@ -196,20 +214,29 @@ export const setModelType = (type) => {
 };
 
 export const mountedThree = (playerDom) => {
-  const { sysOrgCode } = useGlobSetting();
+  let { sysOrgCode } = useGlobSetting();
+  sysOrgCode = 'sdmtjtyjlmk';
   return new Promise(async (resolve) => {
     model = new UseThree('#window3D');
     if (!model || !model.renderer || !model.camera) return;
     model.setEnvMap('test1');
 
     model.camera.position.set(100, 0, 1000);
-    doubleWindowObj = new doubleWindow(model);
+
     singleWindowXkObj = new singleWindowXk(model);
     if (sysOrgCode === 'sdmtjtbetmk') {
       const singleWindowBet = await import('./dandaoFcBet.threejs');
       if (singleWindowBet) singleWindowObj = new singleWindowBet.default(model);
+      doubleWindowObj = new doubleWindow(model);
+    } else if (sysOrgCode === 'sdmtjtyjlmk') {
+      // 单双
+      const singleWindowYjl = await import('./dandaoFcYjl.threejs');
+      if (singleWindowYjl) singleWindowObj = new singleWindowYjl.default(model);
+      const doubleWindowYjl = await import('./shuangdaoFcYjl.threejs');
+      if (doubleWindowYjl) doubleWindowObj = new doubleWindowYjl.default(model);
     } else {
       singleWindowObj = new singleWindow(model);
+      doubleWindowObj = new doubleWindow(model);
     }
     doubleWindowObj.mountedThree(playerDom);
     singleWindowXkObj.mountedThree();

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

@@ -106,7 +106,7 @@
             </div>
           </a-tab-pane>
           <a-tab-pane key="4" tab="报警历史">
-            <div class="tab-item" v-if="activeKey === '4'">
+            <div class="tab-item" v-if="activeKey === '4'"> 
               <AlarmHistoryTable columns-type="alarm" :device-type="deviceType" designScope="alarm-history" :scroll="scroll" />
             </div>
           </a-tab-pane>