Prechádzať zdrojové kódy

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

lxh 1 týždeň pred
rodič
commit
dd19028898

+ 2 - 2
.env

@@ -13,10 +13,10 @@ VITE_GLOB_APP_SHORT_NAME = JeecgBootAdmin
 VITE_GLOB_APP_CAS_BASE_URL=https://id.shendong.com.cn/default
 
 # 是否开启单点登录
-VITE_GLOB_APP_OPEN_SSO=false
+VITE_GLOB_APP_OPEN_SSO=true
 
 # 开启微前端模式
 VITE_GLOB_APP_OPEN_QIANKUN=true
 
 # 文件预览地址
-VITE_GLOB_ONLINE_VIEW_URL=http://fileview.jeecg.com/onlinePreview
+VITE_GLOB_ONLINE_VIEW_URL=http://fileview.jeecg.com/onlinePreview

+ 2 - 2
.env.development

@@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = /
 
 # 跨域代理,您可以配置多个 ,请注意,没有换行符
 #VITE_PROXY = [["/jeecgboot","http://localhost:8080/jeecg-boot"],["/upload","http://localhost:3300/upload"]]
-VITE_PROXY = [["/jeecgsystem","http://182.92.126.35:9999"],["/upload","http://182.92.126.35:9999/upload"],["/documents", "http://182.92.126.35:9050"],["/modelreq", "http://182.92.126.35:9999"],["/webRtc", "http://182.92.126.35:8051"]]
+VITE_PROXY = [["/jeecgsystem","http://182.92.126.35:9999"],["/upload","http://182.92.126.35:9999/upload"],["/documents", "http://182.92.126.35:9050"],["/modelreq", "http://182.92.126.35:9999"],["/webRtc", "http://182.92.126.35:8051"], ["/python", "http://127.0.0.1:8008"], ["/tun2D", "http://127.0.0.1:8088/micro-vent-2dModal/tun2D"]]
 # VITE_PROXY = [["/jeecgsystem","http://192.168.183.88:9999"],["/upload","http://192.168.183.88:9999/upload"],["/documents", "http://192.168.183.88:9050"],["/modelreq", "http://192.168.183.88:9999"],["/webRtc", "http://192.168.183.88:8051"]]
 # VITE_PROXY = [["/jeecgsystem","http://10.10.150.72:9999"],["/upload","http://localhost:3300/upload"],["/documents", "http://10.10.150.72:9050"],["/modelreq", "http://10.10.150.72:9999"],["/webRtc", "http://192.168.183.216:8051"]]
 #VITE_PROXY = [["/jeecgsystem","http://192.168.1.8:9999"],["/upload","http://localhost:3300/upload"]]
@@ -31,5 +31,5 @@ VITE_GLOB_API_URL_PREFIX=
 #VITE_APP_SUB_APP = [["micro-need-air", "//10.10.150.72:8099/"], ["micro-vent-3dModal", "//localhost:8091/"], ["micro-fire-front", "//localhost:8090/"]]
 # VITE_APP_SUB_APP = [["micro-vent-3dModal", "//192.168.183.88:8091/", "micro-vent-3dModal"], ["micro-need-air", "//192.168.183.88:8093/", "micro-need-air"], ["micro-fire-front", "//localhost:8097/", "fire-Micro"]]
 # VITE_APP_SUB_APP = [["micro-vent-3dModal", "//192.168.183.154:8091/", "micro-vent-3dModal"], ["micro-need-air", "//192.168.183.88:8093/", "micro-need-air"], ["micro-fire-front", "//localhost:8097/", "fire-Micro"]]
-VITE_APP_SUB_APP = [["micro-vent-3dModal", "//182.92.126.35:8091/", "micro-vent-3dModal"], ["micro-need-air", "//182.92.126.35:8099/", "micro-need-air"], ["micro-fire-front", "//182.92.126.35:8097/", "fire-Micro"]]
+VITE_APP_SUB_APP = [["micro-vent-3dModal", "//182.92.126.35:8091/", "micro-vent-3dModal"],["micro-vent-2dModal", "//localhost:8088/", "micro-vent-2dModal"], ["micro-need-air", "//182.92.126.35:8099/", "micro-need-air"], ["micro-fire-front", "//182.92.126.35:8097/", "fire-Micro"]]
 # VITE_APP_SUB_APP = [["micro-vent-3dModal", "//localhost:8091/"], ["micro-need-air", "//localhost:8099/"], ["micro-fire-front", "//localhost:8090/"]]

+ 45 - 0
src/components/vent/micro/ventModal2D.vue

@@ -0,0 +1,45 @@
+<template>
+  <div style="position: absolute; width: 100%; height: 100%">
+    <a-spin class="loading-box" size="large" :spinning="loading" tip="正在加载,请稍等。。。" />
+  </div>
+  <div id="micro-vent-2dModal"></div>
+</template>
+<script lang="ts">
+  import { onMounted, onBeforeUnmount, defineComponent, ref, unref } from 'vue';
+  import { unmountMicroApps, mountMicroApp } from '/@/qiankun';
+  import { resetMicroContentWH } from '/@/utils/domUtils';
+  import { useRouter } from 'vue-router';
+  export default defineComponent({
+    name: 'Vent2dModal',
+    setup() {
+      const loading = ref(true);
+      const { currentRoute } = useRouter();
+      onMounted(() => {
+        mountMicroApp(unref(currentRoute).fullPath);
+        resetMicroContentWH('micro-vent-2dModal', () => {
+          loading.value = false;
+        });
+      });
+
+      onBeforeUnmount(() => {
+        unmountMicroApps(currentRoute);
+      });
+
+      return { loading };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .loading-box {
+    position: fixed;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    height: 100%;
+  }
+  #micro-vent-2dModal {
+    width: 100vw;
+    height: 100vh;
+  }
+</style>

+ 163 - 0
src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.tun.ts

@@ -0,0 +1,163 @@
+import * as THREE from 'three';
+import { setModalCenter, getTextCanvas, renderVideo } from '/@/utils/threejs/util';
+import Smoke from '/@/views/vent/comment/threejs/Smoke';
+
+// import * as dat from 'dat.gui';
+// const gui = new dat.GUI();
+// gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
+
+class balancePressTun {
+  model;
+  modelName = 'balancePressTun';
+  group: THREE.Object3D | null = null;
+  topSmoke: Smoke | null = null;
+  downSmoke: Smoke | null = null;
+  outSmoke: Smoke | null = null;
+
+  constructor(model) {
+    this.model = model;
+  }
+
+  addLight() {
+    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
+    directionalLight.position.set(34, 7, -61);
+    this.group?.add(directionalLight);
+    directionalLight.target = this.group as THREE.Object3D;
+
+    // gui.add(directionalLight.position, 'x', -200, 200);
+    // gui.add(directionalLight.position, 'y', -200, 200);
+    // gui.add(directionalLight.position, 'z', -200, 200);
+
+    const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120);
+    pointLight5.position.set(75, -44, 75);
+    pointLight5.shadow.bias = 0.05;
+    this.group?.add(pointLight5);
+
+    const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000);
+    pointLight7.position.set(-7, 100, 8.5);
+    pointLight7.shadow.bias = 0.05;
+    this.group?.add(pointLight7);
+
+    // gui.add(directionalLight.position, 'x', -100, 100);
+    // gui.add(directionalLight.position, 'y', -100, 100);
+    // gui.add(directionalLight.position, 'z', -100, 100);
+    // gui.add(pointLight5.position, 'x', -500, 500);
+    // gui.add(pointLight5.position, 'y', -500, 500);
+    // gui.add(pointLight5.position, 'z', -500, 500);
+  }
+
+  /* 添加监控数据 */
+  addText(selectData) {
+    if (!this.group) {
+      return;
+    }
+    const textArr = [
+      {
+        text: `煤矿巷道远程局部风机系统`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 50,
+        y: 105,
+      },
+      {
+        text: `进风量(m³/min):`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 160,
+      },
+      {
+        text: `${selectData.frontRearDP}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 290,
+        y: 160,
+      },
+      {
+        text: `供风量(m³/min): `,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 217,
+      },
+      {
+        text: ` ${selectData.sourcePressure}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 280,
+        y: 217,
+      },
+      {
+        text: `故障诊断:`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 275,
+      },
+      {
+        text: `${selectData.warnLevel_str ? selectData.warnLevel_str : '-'}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 280,
+        y: 275,
+      },
+      {
+        text: `煤炭科学技术研究院有限公司研制`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 20,
+        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') as THREE.Mesh;
+      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.position.set(57.66, 0.81, 18.19);
+        this.group?.add(planeMesh);
+      }
+    });
+  }
+
+  mountedThree() {
+    return new Promise((resolve) => {
+      this.model.setGLTFModel([this.modelName]).then(async (gltf) => {
+        this.group = gltf[0];
+        if (this.group) {
+          this.group?.scale.set(0.1, 0.1, 0.1);
+          setModalCenter(this.group);
+          resolve(null);
+          this.addLight();
+        }
+      });
+    });
+  }
+
+  destroy() {
+    this.model.clearGroup(this.group);
+    this.model = null;
+    this.group = null;
+  }
+}
+export default balancePressTun;

+ 350 - 0
src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome1.vue

@@ -0,0 +1,350 @@
+<template>
+  <a-spin tip="Loading..." :spinning="loading">
+    <div class="monitor-container">
+      <div class="lr left-box">
+        <div class="monitor-info item-box">
+          <!-- <ventBox1>
+            <template #title>
+              <div>均压与低氧参数监测与设置</div>
+            </template>
+            <template #container>
+              <div class="vent-flex-row-between auto-control">
+                <div class="title">自动调节:</div>
+                <a-radio-group v-model:value="isAutoControl" name="radioGroup" @change="changeType(isAutoControl)">
+                  <a-radio value="1">关闭</a-radio>
+                  <a-radio value="2">开启</a-radio>
+                </a-radio-group>
+              </div>
+              <div class="input-box">
+                <div class="divider-line">开始条件</div>
+                <div v-for="(item, index) in settingParam1" class="input-item" :key="index">
+                  <div class="title">{{ item.title }}:</div>
+                  <a-input-number class="input-value" v-model:value="formData[item.code]" placeholder="" />
+                  <div class="unit">{{ item.unit }}</div>
+                </div>
+                <div class="divider-line">调节参数</div>
+                <div v-for="(item, index) in settingParam2" class="input-item" :key="index">
+                  <div class="title">{{ item.title }}:</div>
+                  <a-input-number class="input-value" v-model:value="formData[item.code]" placeholder="" />
+                  <div class="unit">{{ item.unit }}</div>
+                </div>
+                <div class="divider-line">结束时间</div>
+                <div v-for="(item, index) in settingParam3" class="input-item" :key="index">
+                  <div class="title">{{ item.title }}:</div>
+                  <a-input-number class="input-value" v-model:value="formData[item.code]" placeholder="" />
+                  <div class="unit">{{ item.unit }}</div>
+                </div>
+              </div>
+              <div class="btn-box" style="text-align: center">
+                <div class="btn btn1" @click="onSubmit">提交</div>
+              </div>
+            </template>
+          </ventBox1> -->
+          <ventBox1 class="vent-margin-t-10">
+            <template #title>
+              <div>设备监测详情</div>
+            </template>
+            <template #container>
+              <div class="overflow-y-auto max-h-700px">
+                <template v-for="monitor in windrectMonitorData" :key="monitor.deviceId">
+                  <div class="parameter-title group-parameter-title"
+                    ><SvgIcon class="icon" size="14" name="fiber-title" />
+                    <span>测风装置:{{ monitor.strinstallpos }}</span>
+                  </div>
+                  <div class="input-box">
+                    <div v-for="(item, index) in windrectParam" class="input-item" :key="index">
+                      <div class="title">{{ item.title }}</div>
+                      <div class="value">{{ get(monitor, item.code, '-') }}</div>
+                      <div class="unit">{{ item.unit }}</div>
+                    </div>
+                  </div>
+                </template>
+                <template v-for="monitor in windowMonitorData" :key="monitor.deviceId">
+                  <div class="parameter-title group-parameter-title"
+                    ><SvgIcon class="icon" size="14" name="fiber-title" />
+                    <span>风窗:{{ monitor.strinstallpos }}</span>
+                  </div>
+                  <div class="input-box">
+                    <div v-for="(item, index) in windowParam" class="input-item" :key="index">
+                      <div class="title">{{ item.title }}</div>
+                      <div class="value">{{ get(monitor, item.code, '-') }}</div>
+                      <div class="unit">{{ item.unit }}</div>
+                    </div>
+                  </div>
+                </template>
+                <template v-for="monitor in fanlocalMonitorData" :key="monitor.deviceId">
+                  <div class="parameter-title group-parameter-title"
+                    ><SvgIcon class="icon" size="14" name="fiber-title" />
+                    <span>局扇:{{ monitor.strinstallpos }}</span>
+                  </div>
+                  <div class="input-box">
+                    <div class="input-item">
+                      <div class="title">运行风机</div>
+                      <div class="value">{{ monitor.FanRun }}</div>
+                    </div>
+                    <div v-for="(item, index) in fanlocalColumn" class="input-item" :key="index">
+                      <div class="title">{{ item.title }}</div>
+                      <div class="value">{{
+                        get(
+                          monitor,
+                          item.dataIndex.startsWith('Fan')
+                            ? get(monitor, 'Fan1StartStatus') == 1
+                              ? item.dataIndex.replace('Fan', 'Fan1')
+                              : item.dataIndex.replace('Fan', 'Fan2')
+                            : get(monitor, item.dataIndex),
+                          '-'
+                        )
+                      }}</div>
+                      <!-- <div class="unit">{{ item.unit }}</div> -->
+                    </div>
+                  </div>
+                </template>
+              </div>
+            </template>
+          </ventBox1>
+        </div>
+      </div>
+      <div class="lr right-box ml-5px">
+        <div class="item-box sensor-container">
+          <ventBox1>
+            <template #title>
+              <!-- <div>CO与O2监测</div> -->
+              <div>传感器/安全监控监测</div>
+            </template>
+            <template #container>
+              <div class="overflow-y-auto max-h-700px">
+                <template v-for="monitor in safetyMonitorData" :key="monitor.deviceId">
+                  <div class="parameter-title group-parameter-title"
+                    ><SvgIcon class="icon" size="14" name="fiber-title" />
+                    <span>{{ monitor.strinstallpos }}</span>
+                  </div>
+                  <div class="input-box">
+                    <div v-for="(item, index) in monitorParam" class="input-item" :key="index">
+                      <div class="title">{{ item.title }}</div>
+                      <div class="value" style="width: 50%">{{ get(monitor, item.code, '-') }}</div>
+                    </div>
+                  </div>
+                </template>
+              </div>
+            </template>
+          </ventBox1>
+        </div>
+      </div>
+    </div>
+  </a-spin>
+</template>
+<script setup lang="ts">
+  import { onBeforeMount, ref, onMounted, onUnmounted, reactive, defineProps, watch } from 'vue';
+  import ventBox1 from '/@/components/vent/ventBox1.vue';
+  import { SvgIcon } from '/@/components/Icon';
+  import { mountedThree, destroy, setModelType, updateText, play } from '../balancePress.threejs';
+  import { settingParam1, settingParam2, settingParam3, windowParam, localFanParam, monitorParam, windrectParam } from '../balancePress.data';
+  import { list } from '../balancePress.api';
+  import { message } from 'ant-design-vue';
+  import { get } from 'lodash-es';
+  import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
+  import { object } from 'vue-types';
+
+  const props = defineProps({
+    deviceId: {
+      type: String,
+      require: true,
+    },
+  });
+
+  const loading = ref(false);
+
+  // 默认初始是第一行
+  const isAutoControl = ref('1');
+
+  // 监测数据
+  const selectData = reactive({
+    frontRearDP: '-',
+    sourcePressure: '-',
+    fault: '-',
+  });
+
+  const changeType = (isAutoControl) => {
+    isAutoControl;
+    //
+  };
+
+  // https获取监测数据
+  let timer: any = null;
+  function getMonitor(flag?) {
+    if (Object.prototype.toString.call(timer) === '[object Null]') {
+      timer = setTimeout(
+        async () => {
+          if (props.deviceId) {
+            const data = await getDataSource(props.deviceId);
+            Object.assign(selectData, data);
+            updateText(selectData);
+          }
+          if (timer) {
+            timer = null;
+          }
+          await getMonitor();
+          loading.value = false;
+        },
+        flag ? 0 : 1000
+      );
+    }
+  }
+
+  const safetyMonitorData = ref<any[]>([]);
+  const fanlocalMonitorData = ref<any[]>([]);
+  const windowMonitorData = ref<any[]>([]);
+  const windrectMonitorData = ref<any[]>([]);
+  const fanlocalColumn = ref<any[]>([]);
+  const windowColumn = ref<any[]>([]);
+
+  async function getDataSource(systemID) {
+    const res = await list({ devicetype: 'sys', systemID });
+    const result = res.msgTxt;
+    safetyMonitorData.value = [];
+    fanlocalMonitorData.value = [];
+    windowMonitorData.value = [];
+    windrectMonitorData.value = [];
+    result.forEach((item) => {
+      if (item.type.startsWith('safetymonitor') || item.type.startsWith('avgpressure_lowoxygen')) {
+        safetyMonitorData.value.push(...item.datalist);
+      }
+      if (item.type.startsWith('fanlocal')) {
+        item.datalist.forEach((e) => {
+          fanlocalColumn.value = getTableHeaderColumns('sys_surface_junya_fanlocal') || localFanParam;
+          Object.assign(e, e.readData);
+          const f1Run = e.readData.Fan1StartStatus == '1';
+          e.FanfHz = f1Run ? e.readData.Fan1_Frequency : e.readData.Fan2_Frequency;
+          e.FanRun = f1Run ? '1#风机' : '2#风机';
+        });
+        fanlocalMonitorData.value.push(...item.datalist);
+      }
+      if (item.type.startsWith('window')) {
+        windowMonitorData.value.push(...item.datalist);
+      }
+      if (item.type.startsWith('windrect')) {
+        windrectMonitorData.value.push(...item.datalist);
+      }
+    });
+  }
+
+  // 喷粉操作
+  function onSubmit() {
+    sessionStorage.setItem('lalance-press-formdata', JSON.stringify(formData.value));
+    message.success('提交成功');
+  }
+
+  // watch(
+  //   () => props.deviceId,
+  //   (newVal, oldVal) => {
+  //     if (newVal && oldVal != undefined) {
+  //       setModelType('balancePressBase');
+  //     }
+
+  //     loading.value = true;
+  //   }
+  // );
+
+  const formData = ref({
+    a: 0,
+    b: 0,
+    c: 0,
+    d: 0,
+    e: 0,
+    f: 0,
+    g: 0,
+    h: 0,
+    i: 0,
+    j: 0,
+    k: 0,
+    l: 0,
+    m: 0,
+  });
+
+  onBeforeMount(() => {});
+
+  onMounted(() => {
+    // getMonitor()
+    loading.value = true;
+    const storage = sessionStorage.getItem('lalance-press-formdata');
+    if (storage) formData.value = JSON.parse(storage);
+    mountedThree().then(async () => {
+      await setModelType('balancePressTun'); //balancePressBase
+      loading.value = false;
+      timer = null;
+      await getMonitor(true);
+      play('startSmoke', 'top', 30, 'open', 0);
+    });
+  });
+
+  onUnmounted(() => {
+    destroy();
+    if (timer) {
+      clearTimeout(timer);
+    }
+  });
+</script>
+<style lang="less" scoped>
+  @import '/@/design/vent/modal.less';
+  @import '../../comment/less/workFace.less';
+  @ventSpace: zxm;
+  .monitor-container {
+    margin-top: 60px;
+  }
+  .lr {
+    width: 340px !important;
+  }
+  .auto-control {
+    padding: 10px 8px;
+    margin: 0 4px 4px 4px;
+    border-radius: 4px;
+    border: 1px solid #ffffff05;
+    background-image: linear-gradient(to left, #39deff15, #3977e500, #39deff15);
+  }
+  .divider-line {
+    position: relative;
+    color: aqua;
+    padding-left: 20px;
+    font-size: 14px;
+    &::before {
+      position: absolute;
+      content: '';
+      display: block;
+      top: 10px;
+      left: 0;
+      height: 1px;
+      width: 15px;
+      background-color: #ffffff33;
+    }
+    &::after {
+      position: absolute;
+      content: '';
+      display: block;
+      top: 10px;
+      right: 0;
+      height: 1px;
+      width: calc(100% - 85px);
+      background-color: #ffffff33;
+    }
+  }
+  .input-value {
+    width: 120px !important;
+  }
+  .unit {
+    text-align: right;
+  }
+  .btn-box {
+    margin: 10px 4px;
+    .btn1 {
+      padding: 4px 0;
+    }
+  }
+
+  :deep(.@{ventSpace}-tabs-tabpane-active) {
+    overflow: auto;
+  }
+
+  :deep(.@{ventSpace}-input-number) {
+    border-color: #ffffff88 !important;
+  }
+</style>

+ 223 - 0
src/views/vent/monitorManager/balancePressMonitor/index1.vue

@@ -0,0 +1,223 @@
+<template>
+  <customHeader :fieldNames="{ label: 'systemname', value: 'id', options: 'children' }" :options = 'options' @change="getSelectRow" :optionValue="optionValue">均压与低氧管控</customHeader>
+
+  <div class="scene-box">
+    <div class="center-container">
+      <balancePressHome v-if="activeKey == 'monitor'" :deviceId = 'optionValue' />
+      <div v-else class="history-group">
+        <div class="device-button-group" v-if="deviceList.length > 0">
+          <div class="device-button" :class="{ 'device-active': deviceActive == device.deviceType }" v-for="(device, index) in deviceList" :key="index" @click="deviceChange(index)">{{ device.deviceName }}</div>
+        </div>
+        <div class="history-container">
+          <balancePressHistory v-if="activeKey == 'monitor_history'" ref="historyTable" class="vent-margin-t-20" :deviceId = 'optionValue' :device-type="deviceType"/>
+          <balancePressHandleHistoryVue v-if="activeKey == 'handler_history'" ref="alarmHistoryTable" class="vent-margin-t-20" :deviceId = 'optionValue' :device-type="deviceType" />
+          <balancePressAlarmHistory v-if="activeKey == 'faultRecord'" ref="handlerHistoryTable" class="vent-margin-t-20" :deviceId = 'optionValue' :device-type="deviceType"/>
+        </div> 
+      </div>      
+    </div>
+    <BottomMenu @change="changeActive"/>
+  </div>
+  <Vent2dModal style="width: 100vw; height: 100vh; position: absolute; top: 0; left: 0;" />
+</template>
+
+<script setup lang="ts">
+import customHeader from '/@/components/vent/customHeader.vue';
+import { onBeforeMount, ref, onMounted, onUnmounted, reactive, onBeforeUnmount } from 'vue';
+import { list, getTableList } from './balancePress.api';
+import BottomMenu from '/@/views/vent/comment/components/bottomMenu.vue';
+import balancePressHome from './components/balancePressHome1.vue';
+import balancePressHistory from './components/balancePressHistory.vue';
+import balancePressHandleHistoryVue from './components/balancePressHandleHistory.vue';
+import balancePressAlarmHistory from './components/balancePressAlarmHistory.vue';
+import { useRouter } from 'vue-router';
+import { unmountMicroApps } from '/@/qiankun';
+import Vent2dModal from '/@/components/vent/micro/ventModal2D.vue';
+import { getActions } from '/@/qiankun/state';
+
+type DeviceType = { deviceType: string, deviceName: string, datalist: any[] };
+const actions = getActions();
+const { currentRoute } = useRouter();
+const activeKey = ref('monitor');
+const loading = ref(false);
+
+const historyTable = ref()
+const alarmHistoryTable = ref()
+const handlerHistoryTable = ref()
+
+
+//关联设备
+const deviceList = ref<DeviceType[]>([])
+const deviceActive = ref('')
+const deviceType = ref('')
+
+const options = ref()
+const optionValue = ref('')
+
+
+function changeActive(activeValue) {
+  activeKey.value = activeValue
+}
+
+function deviceChange(index) {
+  deviceActive.value = deviceType.value = deviceList.value[index].deviceType
+}
+
+// 查询关联设备列表
+async function getDeviceList() {
+  const res = await list({ devicetype: 'sys', systemID: optionValue.value });
+  
+  const result = res.msgTxt;
+  const deviceArr = <DeviceType[]>[]
+  result.forEach(item => {
+    const data = item['datalist'].filter((data: any) => {
+      const readData = data.readData;
+      return Object.assign(data, readData);
+    })
+    if (item.type != 'sys') {
+      deviceArr.unshift({ deviceType: item.type, deviceName: item['typeName'] ? item['typeName'] : item['datalist'][0]['typeName'], datalist: data })
+    }
+  })
+  deviceList.value = deviceArr
+  deviceActive.value = deviceArr[0].deviceType
+  deviceChange(0)
+};
+
+async function getSysDataSource () {
+  const res = await getTableList({ strtype: 'sys_surface_junya', pagetype: 'normal' });
+  if (!options.value) {
+    // 初始时选择第一条数据
+    options.value = res.records || [];
+    if (!optionValue.value) {
+      optionValue.value = options.value[0]['id']
+      getDeviceList()
+    }
+  }
+};
+
+// 切换检测数据
+function getSelectRow(deviceID){
+  // const currentData = options.value.find((item: any) => {
+  //   return item.id == deviceID
+  // })
+  optionValue.value = deviceID
+  getDeviceList()
+}
+
+onBeforeMount(() => {
+
+});
+
+onMounted(async() => {
+  if (currentRoute.value && currentRoute.value['query'] && currentRoute.value['query']['id']) optionValue.value = currentRoute.value['query']['id']
+  await getSysDataSource()
+  actions.onGlobalStateChange((newState) => {
+    const isMounted = newState['isMounted'];
+    if (isMounted) {
+      actions.setGlobalState({ isMounted: false, pageObj:{modalId: '1909406023414272001'} });
+      loading.value = false;
+    }
+  });
+  
+});
+
+onUnmounted(() => {
+ 
+});
+onBeforeUnmount(() => {
+  unmountMicroApps(['/micro-vent-2dModal']);
+});
+</script>
+<style lang="less" scoped>
+@import '/@/design/vent/modal.less';
+@ventSpace: zxm;
+.scene-box{
+  width: 100%;
+  height: 100%;
+  margin-top: 20px;
+  pointer-events: none;
+  position: relative;
+  .history-group{
+    padding: 0 20px;
+    .history-container{
+      position: relative;
+      background: #6195af1a;
+      width: calc(100% + 10px);
+      top: 0px;
+      left: -10px;
+      border: 1px solid #00fffd22;
+      padding: 10px 0;
+      box-shadow: 0 0 20px #44b4ff33 inset;
+    }
+  }
+  .device-button-group{
+    // margin: 0 20px;
+    display: flex;
+    pointer-events: auto;
+    position: relative;
+    margin-top: 90px;
+    &::after{
+      position:absolute;
+      content: '';
+      width: calc(100% + 10px);
+      height: 2px;
+      top: 30px;
+      left: -10px;
+      border-bottom: 1px solid #0efcff;
+    }
+    .device-button{
+      padding: 4px 15px;
+      position: relative;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      font-size: 14px;
+      
+      color: #fff;
+      cursor: pointer;
+      margin: 0 3px;
+
+      &::before{
+        content: '';
+        position: absolute;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        left: 0;
+        border: 1px solid #6176AF;
+        transform: skewX(-38deg);
+        background-color: rgba(0, 77, 103,85%);
+        z-index: -1;
+      }
+    }
+    .device-active{
+      // color: #0efcff;
+      &::before{
+        border-color: #0efcff;
+        box-shadow: 1px 1px 3px 1px #0efcff inset;
+      }
+    }
+  }
+}
+.center-container{
+  width: 100%;
+  height: calc(100% - 200px);
+}
+
+
+.input-box {
+  display: flex;
+  align-items: center;
+  padding-left: 10px;
+
+  .input-title {
+    color: #73e8fe;
+    width: auto;
+  }
+
+  .@{ventSpace}-input-number {
+    border-color: #ffffff88 !important;
+  }
+
+  margin-right: 10px;
+}
+</style>

+ 213 - 0
src/views/vent/monitorManager/balancePressMonitor/index2.vue

@@ -0,0 +1,213 @@
+<template>
+  <customHeader :fieldNames="{ label: 'systemname', value: 'id', options: 'children' }" :options = 'options' @change="getSelectRow" :optionValue="optionValue">均压与低氧管控</customHeader>
+  <div class="bg"
+    style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden">
+    <a-spin :spinning="loading" />
+    <div id="balancePress3D" v-show="!loading" style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
+  </div>
+  <div class="scene-box">
+    <div class="center-container">
+      <balancePressHome v-if="activeKey == 'monitor'" :deviceId = 'optionValue' />
+      <div v-else class="history-group">
+        <div class="device-button-group" v-if="deviceList.length > 0">
+          <div class="device-button" :class="{ 'device-active': deviceActive == device.deviceType }" v-for="(device, index) in deviceList" :key="index" @click="deviceChange(index)">{{ device.deviceName }}</div>
+        </div>
+        <div class="history-container">
+          <balancePressHistory v-if="activeKey == 'monitor_history'" ref="historyTable" class="vent-margin-t-20" :deviceId = 'optionValue' :device-type="deviceType"/>
+          <balancePressHandleHistoryVue v-if="activeKey == 'handler_history'" ref="alarmHistoryTable" class="vent-margin-t-20" :deviceId = 'optionValue' :device-type="deviceType" />
+          <balancePressAlarmHistory v-if="activeKey == 'faultRecord'" ref="handlerHistoryTable" class="vent-margin-t-20" :deviceId = 'optionValue' :device-type="deviceType"/>
+        </div> 
+      </div>      
+    </div>
+    <BottomMenu @change="changeActive"/>
+  </div>
+  
+</template>
+
+<script setup lang="ts">
+import customHeader from '/@/components/vent/customHeader.vue';
+import { onBeforeMount, ref, onMounted, onUnmounted, reactive, toRaw } from 'vue';
+import { list, getTableList } from './balancePress.api';
+import BottomMenu from '/@/views/vent/comment/components/bottomMenu.vue';
+import balancePressHome from './components/balancePressHome1.vue';
+import balancePressHistory from './components/balancePressHistory.vue';
+import balancePressHandleHistoryVue from './components/balancePressHandleHistory.vue';
+import balancePressAlarmHistory from './components/balancePressAlarmHistory.vue';
+import { useRouter } from 'vue-router';
+import { setModelType } from './balancePress.threejs';
+
+type DeviceType = { deviceType: string, deviceName: string, datalist: any[] };
+
+const { currentRoute } = useRouter();
+const activeKey = ref('monitor');
+const loading = ref(false);
+
+const historyTable = ref()
+const alarmHistoryTable = ref()
+const handlerHistoryTable = ref()
+
+
+//关联设备
+const deviceList = ref<DeviceType[]>([])
+const deviceActive = ref('')
+const deviceType = ref('')
+
+const options = ref()
+const optionValue = ref('')
+
+
+function changeActive(activeValue) {
+  activeKey.value = activeValue
+}
+
+function deviceChange(index) {
+  deviceActive.value = deviceType.value = deviceList.value[index].deviceType
+}
+
+// 查询关联设备列表
+async function getDeviceList() {
+  const res = await list({ devicetype: 'sys', systemID: optionValue.value });
+  
+  const result = res.msgTxt;
+  const deviceArr = <DeviceType[]>[]
+  result.forEach(item => {
+    const data = item['datalist'].filter((data: any) => {
+      const readData = data.readData;
+      return Object.assign(data, readData);
+    })
+    if (item.type != 'sys') {
+      deviceArr.unshift({ deviceType: item.type, deviceName: item['typeName'] ? item['typeName'] : item['datalist'][0]['typeName'], datalist: data })
+    }
+  })
+  deviceList.value = deviceArr
+  deviceActive.value = deviceArr[0].deviceType
+  deviceChange(0)
+};
+
+async function getSysDataSource () {
+  const res = await getTableList({ strtype: 'sys_surface_junya', pagetype: 'normal' });
+  if (!options.value) {
+    // 初始时选择第一条数据
+    options.value = res.records || [];
+    if (!optionValue.value) {
+      optionValue.value = options.value[0]['id']
+      getDeviceList()
+    }
+  }
+};
+
+// 切换检测数据
+function getSelectRow(deviceID){
+  // const currentData = options.value.find((item: any) => {
+  //   return item.id == deviceID
+  // })
+  optionValue.value = deviceID
+  getDeviceList()
+  setModelType('balancePressTun')
+}
+
+onBeforeMount(() => {
+
+});
+
+onMounted(async() => {
+  if (currentRoute.value && currentRoute.value['query'] && currentRoute.value['query']['id']) optionValue.value = currentRoute.value['query']['id']
+  await getSysDataSource()
+  
+});
+
+onUnmounted(() => {
+ 
+});
+</script>
+<style lang="less" scoped>
+@import '/@/design/vent/modal.less';
+@ventSpace: zxm;
+.scene-box{
+  margin-top: 20px;
+  pointer-events: none;
+  .history-group{
+    padding: 0 20px;
+    .history-container{
+      position: relative;
+      background: #6195af1a;
+      width: calc(100% + 10px);
+      top: 0px;
+      left: -10px;
+      border: 1px solid #00fffd22;
+      padding: 10px 0;
+      box-shadow: 0 0 20px #44b4ff33 inset;
+    }
+  }
+  .device-button-group{
+    // margin: 0 20px;
+    display: flex;
+    pointer-events: auto;
+    position: relative;
+    margin-top: 90px;
+    &::after{
+      position:absolute;
+      content: '';
+      width: calc(100% + 10px);
+      height: 2px;
+      top: 30px;
+      left: -10px;
+      border-bottom: 1px solid #0efcff;
+    }
+    .device-button{
+      padding: 4px 15px;
+      position: relative;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      font-size: 14px;
+      
+      color: #fff;
+      cursor: pointer;
+      margin: 0 3px;
+
+      &::before{
+        content: '';
+        position: absolute;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        left: 0;
+        border: 1px solid #6176AF;
+        transform: skewX(-38deg);
+        background-color: rgba(0, 77, 103,85%);
+        z-index: -1;
+      }
+    }
+    .device-active{
+      // color: #0efcff;
+      &::before{
+        border-color: #0efcff;
+        box-shadow: 1px 1px 3px 1px #0efcff inset;
+      }
+    }
+  }
+}
+.center-container{
+  width: 100%;
+  height: calc(100% - 200px);
+}
+
+
+.input-box {
+  display: flex;
+  align-items: center;
+  padding-left: 10px;
+
+  .input-title {
+    color: #73e8fe;
+    width: auto;
+  }
+
+  .@{ventSpace}-input-number {
+    border-color: #ffffff88 !important;
+  }
+
+  margin-right: 10px;
+}
+</style>