Przeglądaj źródła

1、风窗、局部风机、主风机添加自制联动
2. 安全监控对接报表导出

hongrunxia 7 miesięcy temu
rodzic
commit
f3db261f5b

+ 6 - 5
.env.development

@@ -6,7 +6,8 @@ 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://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://182.92.126.35:9999"],["/upload","http://localhost:3300/upload"],["/documents", "http://10.10.150.72:9050"],["/modelreq", "http://182.92.126.35:9999"],["/webRtc", "http://192.168.183.216: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"]]
 
 # 控制台不输出
@@ -18,14 +19,14 @@ VITE_GLOB_API_URL=/modelreq
 
 
 #后台接口全路径地址(必填)
-VITE_GLOB_DOMAIN_URL=http://10.10.150.72:9999
-# VITE_GLOB_DOMAIN_URL=http://182.92.126.35:9999
+# VITE_GLOB_DOMAIN_URL=http://10.10.150.72:9999
+VITE_GLOB_DOMAIN_URL=http://182.92.126.35:9999
 
 # 接口前缀
 VITE_GLOB_API_URL_PREFIX=
 
 #微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
 #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.154:8091/", "micro-vent-3dModal"], ["micro-need-air", "//localhost:8099/", "micro-need-air"], ["micro-fire-front", "//localhost:8097/", "fire-Micro"]]
-# VITE_APP_SUB_APP = [["micro-vent-3dModal", "//localhost:8091/", "micro-vent-3dModal"], ["micro-need-air", "//localhost:8099/", "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", "//localhost:8099/", "micro-need-air"], ["micro-fire-front", "//localhost:8097/", "fire-Micro"]]
+VITE_APP_SUB_APP = [["micro-vent-3dModal", "//localhost:8091/", "micro-vent-3dModal"], ["micro-need-air", "//localhost:8099/", "micro-need-air"], ["micro-fire-front", "//localhost:8097/", "fire-Micro"]]
 # VITE_APP_SUB_APP = [["micro-vent-3dModal", "//localhost:8091/"], ["micro-need-air", "//localhost:8099/"], ["micro-fire-front", "//localhost:8090/"]]

+ 14 - 0
pnpm-lock.yaml

@@ -194,6 +194,9 @@ dependencies:
   vue-types:
     specifier: ^5.1.1
     version: 5.1.1(vue@3.3.6)
+  vue3-seamless-scroll:
+    specifier: ^2.0.1
+    version: 2.0.1
   vuedraggable:
     specifier: ^4.1.0
     version: 4.1.0(vue@3.3.6)
@@ -12815,6 +12818,11 @@ packages:
     resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==, tarball: http://registry.npm.taobao.org/throat/-/throat-6.0.2.tgz}
     dev: false
 
+  /throttle-debounce@5.0.0:
+    resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==}
+    engines: {node: '>=12.22'}
+    dev: false
+
   /through2@2.0.5:
     resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==, tarball: http://registry.npm.taobao.org/through2/-/through2-2.0.5.tgz}
     dependencies:
@@ -13849,6 +13857,12 @@ packages:
       vue-types: 4.2.1(vue@3.3.6)
     dev: false
 
+  /vue3-seamless-scroll@2.0.1:
+    resolution: {integrity: sha512-mI3BaDU3pjcPUhVSw3/xNKdfPBDABTi/OdZaZqKysx4cSdNfGRbVvGNDzzptBbJ5S7imv5T55l6x/SqgnxKreg==}
+    dependencies:
+      throttle-debounce: 5.0.0
+    dev: false
+
   /vue@3.3.6(typescript@4.9.5):
     resolution: {integrity: sha512-jJIDETeWJnoY+gfn4ZtMPMS5KtbP4ax+CT4dcQFhTnWEk8xMupFyQ0JxL28nvT/M4+p4a0ptxaV2WY0LiIxvRg==, tarball: http://registry.npm.taobao.org/vue/-/vue-3.3.6.tgz}
     peerDependencies:

+ 1 - 1
src/hooks/system/useCamera.ts

@@ -341,7 +341,7 @@ export function useCamera() {
       dom?.remove();
     });
     playerList.forEach((player) => {
-      if (player.destroy) player.destroy();
+      if (player && player.destroy) player.destroy();
       player = null;
     });
     videoParentDomList.length = 0;

+ 5 - 5
src/hooks/system/useMethods.ts

@@ -29,7 +29,7 @@ export function useMethods() {
     if (!name || typeof name != 'string') {
       name = '导出文件';
     }
-    let blobOptions = { type: 'application/vnd.ms-excel' };
+    const blobOptions = { type: 'application/vnd.ms-excel' };
     let fileSuffix = '.xls';
     if (isXlsx === true) {
       blobOptions['type'] = XLSX_MIME_TYPE;
@@ -38,8 +38,8 @@ export function useMethods() {
     if (typeof window.navigator.msSaveBlob !== 'undefined') {
       window.navigator.msSaveBlob(new Blob([data], blobOptions), name + fileSuffix);
     } else {
-      let url = window.URL.createObjectURL(new Blob([data], blobOptions));
-      let link = document.createElement('a');
+      const url = window.URL.createObjectURL(new Blob([data], blobOptions));
+      const link = document.createElement('a');
       link.style.display = 'none';
       link.href = url;
       link.setAttribute('download', name + fileSuffix);
@@ -60,11 +60,11 @@ export function useMethods() {
     const isReturn = (fileInfo) => {
       try {
         if (fileInfo.code === 201) {
-          let {
+          const {
             message,
             result: { msg, fileUrl, fileName },
           } = fileInfo;
-          let href = glob.uploadUrl + fileUrl;
+          const href = glob.uploadUrl + fileUrl;
           createWarningModal({
             title: message,
             centered: false,

+ 83 - 37
src/views/vent/monitorManager/compressor/components/nitrogenHome_dltj.vue

@@ -130,6 +130,30 @@
         </div>
         <!-- 右边控制状态 -->
         <div class="lr-box right-box">
+          <!-- <ventBox1 v-if="deviceType == 'nitrogen_52507'">
+            <template #title>
+              <div>注氮机监测</div>
+            </template>
+            <template #container>
+              <div class="input-item" v-for="(preFan, index) in nitrogenMonitor" :key="index">
+                <div class="title">{{ preFan.title }}</div>
+                <div v-if="preFan.unit !== 'signal' && preFan.unit !== 'warning'" class="value">{{
+                  monitorData[preFan.code] >= 0 ? formatNum(Number(monitorData[preFan.code])) : '-'
+                }}</div>
+
+                <div
+                  v-else
+                  :class="{
+                    'signal-round': true,
+                    'signal-round-warning': monitorData[preFan.code] == '1' && preFan.unit == 'warning',
+                    'signal-round-run': monitorData[preFan.code] == '1' && preFan.unit == 'signal',
+                    'signal-round-gry': monitorData[preFan.code] != '1',
+                  }"
+                ></div>
+                <div class="unit">{{ preFan.unit !== 'signal' && preFan.unit !== 'warning' ? `(${preFan.unit})` : '' }}</div>
+              </div>
+            </template>
+          </ventBox1> -->
           <ventBox1 class="vent-margin-t-10">
             <template #title>
               <div>设备实时监测曲线</div>
@@ -139,16 +163,16 @@
                 v-if="chartsColumns.length > 0"
                 xAxisPropType="readTime"
                 :dataSource="echartData"
-                height="340px"
+                height="320px"
                 :chartsColumns="chartsColumns"
                 chartsType="listMonitor"
                 :option="echatsOption"
               />
             </template>
           </ventBox1>
-          <div ref="playerRef" style="height: auto; width: 100%; margin-top: 10px"></div>
         </div>
       </div>
+      <div ref="playerRef" class="player-box" style=""> </div>
     </div>
   </div>
 </template>
@@ -559,11 +583,12 @@
       if (JSON.stringify(dataSoreDatas) === '{}') {
         airCompressor[`FluxTotal`] = monitorData.value['FluxTotal'] || 0;
       } else {
-        airCompressor[`InputFlux`] = monitorData.value['InputFlux1'] + monitorData.value['InputFlux2'] || null;
+        airCompressor[`InputFlux`] = Number(monitorData.value['InputFlux1']) + Number(monitorData.value['InputFlux2']) || null;
         monitorData.value['RunTime31'] = (Number(monitorData.value['RunTime31']) / 24).toFixed(0);
         monitorData.value['RunTime41'] = (Number(monitorData.value['RunTime41']) / 24).toFixed(0);
         monitorData.value['RunTime32'] = (Number(monitorData.value['RunTime32']) / 24).toFixed(0);
         monitorData.value['RunTime42'] = (Number(monitorData.value['RunTime42']) / 24).toFixed(0);
+        monitorData.value['FluxTotal'] = airCompressor[`InputFlux`];
       }
       //图表数据
       if (dataArr.length <= 5) {
@@ -649,7 +674,6 @@
   watch(
     () => unref(deviceType),
     async (type: string) => {
-      debugger;
       if (type == 'nitrogen_52507') {
         const { preMonitorList, preFanMonitorData, nitrogenMonitorData } = await import('../nitrogen.data.dlt1');
         preMonitorListData.value = preMonitorList;
@@ -675,11 +699,11 @@
 
   onUnmounted(() => {
     destroy();
-    removeCamera();
     if (timer) {
       clearTimeout(timer);
       timer = undefined;
     }
+    removeCamera();
   });
 </script>
 
@@ -725,6 +749,7 @@
       display: flex;
       justify-content: space-between;
       margin-bottom: 100px;
+      position: relative;
       .device-state {
         width: 100%;
         position: absolute;
@@ -814,6 +839,39 @@
           pointer-events: auto;
           overflow-y: auto;
           overflow-x: hidden;
+          .input-item {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 4px 8px;
+            margin: 6px 0;
+            background-image: linear-gradient(to right, #39deff15, #3977e500);
+
+            .title {
+              width: 200px;
+            }
+            .title-auto {
+              width: auto;
+            }
+
+            .input-value {
+              width: 80px;
+              height: 28px;
+              line-height: 28px !important;
+              background: transparent !important;
+              border-color: #228da2 !important;
+              color: #fff !important;
+            }
+            .value {
+              width: 100px;
+              color: #00d8ff;
+              padding-right: 20px;
+            }
+            .unit {
+              width: 80px;
+              text-align: right;
+            }
+          }
         }
 
         .item {
@@ -870,6 +928,9 @@
                 .unit {
                   // color: #ffffffbb;
                 }
+                .value {
+                  color: #00d8ff;
+                }
               }
               .state-val {
                 flex: 1;
@@ -981,6 +1042,11 @@
                 background-image: linear-gradient(to right, #3df6ff10, #3df6ff00);
               }
             }
+            .monitor-item {
+              .value {
+                color: #00d8ff;
+              }
+            }
           }
         }
 
@@ -992,38 +1058,6 @@
         .left-box {
           width: 335px;
           margin-top: 80px;
-          .input-item {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            padding: 4px 8px;
-            margin: 6px 0;
-            background-image: linear-gradient(to right, #39deff15, #3977e500);
-
-            .title {
-              width: 200px;
-            }
-            .title-auto {
-              width: auto;
-            }
-
-            .input-value {
-              width: 80px;
-              height: 28px;
-              line-height: 28px !important;
-              background: transparent !important;
-              border-color: #228da2 !important;
-              color: #fff !important;
-            }
-            .value {
-              width: 100px;
-              color: #00d8ff;
-              padding-right: 20px;
-            }
-            .unit {
-              width: 80px;
-            }
-          }
         }
       }
       &:deep(.win) {
@@ -1031,6 +1065,18 @@
         margin: 0 !important;
       }
     }
+    .player-box {
+      position: absolute;
+      height: auto;
+      // width: 100%;
+      right: 0px;
+      bottom: 110px;
+      z-index: 99999;
+      display: flex;
+      #LivePlayerBox {
+        width: auto !important;
+      }
+    }
   }
 
   &:deep(.main) {

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

@@ -620,6 +620,11 @@
         permission: 'fanLocal:kkjc',
       },
       {
+        key: 'zhlk',
+        value: '自主联控',
+        permission: 'fanLocal:zhlk',
+      },
+      {
         key: 'diameter',
         value: '风筒直径',
         permission: 'fanLocal:control',

+ 20 - 11
src/views/vent/monitorManager/gateMonitor/index.vue

@@ -42,6 +42,7 @@
             </template>
           </a-radio-group>
           <div class="button-box" @click="playAnimation(7)">切换模式</div>
+          <!-- <div class="button-box" @click="playAnimation(10)">自主联动控制</div> -->
         </div>
         <div class="vent-flex-m row" v-else>
           <div class="control-title">控制模式:</div>
@@ -585,16 +586,7 @@
         modalType.value = '4';
         modalIsShow.value = true;
         break;
-      case 8: // 打开中间门
-        modalTitle.value = '打开中间门';
-        modalType.value = '8';
-        modalIsShow.value = true;
-        break;
-      case 9: // 关闭中间门
-        modalTitle.value = '关闭中间门';
-        modalType.value = '9';
-        modalIsShow.value = true;
-        break;
+
       case 5: // 打开前后门
         modalTitle.value = '打开前后门';
         modalType.value = '5';
@@ -605,12 +597,26 @@
         modalType.value = '6';
         modalIsShow.value = true;
         break;
-
       case 7: // 控制模式切换
         modalTitle.value = '控制模式切换';
         modalType.value = '7';
         modalIsShow.value = true;
         break;
+      case 8: // 打开中间门
+        modalTitle.value = '打开中间门';
+        modalType.value = '8';
+        modalIsShow.value = true;
+        break;
+      case 9: // 关闭中间门
+        modalTitle.value = '关闭中间门';
+        modalType.value = '9';
+        modalIsShow.value = true;
+        break;
+      case 10: // 控制模式切换
+        modalTitle.value = '自主联动控制';
+        modalType.value = '10';
+        modalIsShow.value = true;
+        break;
     }
 
     if (globalConfig?.simulatedPassword) {
@@ -717,6 +723,9 @@
         data.paramcode = 'autoRoManualControl';
         data.value = selectData.contrlMod != 'loopCtrl' ? contrlValue : '';
         selectData.autoRoManual = null;
+
+      case '10': // 远程与就地
+        data.paramcode = 'ldkzControl';
     }
 
     if (data.paramcode) {

+ 2 - 1
src/views/vent/monitorManager/mainFanMonitor/index.vue

@@ -1140,12 +1140,13 @@
     align-items: center !important;
     justify-content: space-around !important;
     position: absolute !important;
-    width: 915px !important;
+    width: 1015px !important;
     height: 75px !important;
     left: 50% !important;
     top: 85px !important;
     transform: translateX(-50%) !important;
     background: url('/@/assets/images/vent/tab-group-bg.png') no-repeat !important;
+    background-size: 100% 75px !important;
     padding: 0 30px !important;
     .button-box {
       height: 35px !important;

+ 5 - 0
src/views/vent/monitorManager/mainFanMonitor/main.data.ts

@@ -608,6 +608,11 @@ export const modalTypeArr = {
       value: '工况辅助决策',
       permission: 'fan:kkjc',
     },
+    {
+      key: 'zhlk',
+      value: '自主联控',
+      permission: 'fan:zhlk',
+    },
   ],
 };
 

+ 1 - 1
src/views/vent/monitorManager/nitrogen/nitrogen.data.1.ts

@@ -63,7 +63,7 @@ export const bottomBtnList = ref([
 
 export async function getMonitorData() {
   const { sysOrgCode } = useGlobSetting();
-  // const sysOrgCode = 'hnqymdktymk';
+  // const sysOrgCode = 'sdmtjtdltmk';
   switch (sysOrgCode) {
     case 'yjmdsankuang': // 窑街三矿
       return await import('./nitrogen.dataYJ');

+ 50 - 1
src/views/vent/monitorManager/safetyMonitor/index.vue

@@ -210,13 +210,14 @@
         </div>
       </a-tab-pane>
     </a-tabs>
+    <div class="export-btn"><div class="btn btn1" @click="exportData">一键导出</div></div>
   </div>
 </template>
 
 <script setup lang="ts">
   import { ref, onMounted, onUnmounted, shallowRef, defineProps, watch, inject, unref } from 'vue';
   import BarAndLine from '/@/components/chart/BarAndLine.vue';
-  import { list, getDeviceList, safetyList } from './safety.api';
+  import { list, getDeviceList, safetyList, getExportUrl } from './safety.api';
   import AlarmHistoryCommentTable from '../comment/AlarmHistoryTable.vue';
   import AlarmHistoryTable from './AlarmHistoryTable.vue';
   import HistoryTable from './HistoryTable.vue';
@@ -229,11 +230,14 @@
   import { getDictItemsByCode } from '/@/utils/dict';
   import { usePermission } from '/@/hooks/web/usePermission';
   import { useGlobSetting } from '/@/hooks/setting';
+  import { useMethods } from '/@/hooks/system/useMethods';
 
   const { sysOrgCode } = useGlobSetting();
   const { hasPermission } = usePermission();
   const globalConfig = inject('globalConfig');
 
+  const { handleExportXls } = useMethods();
+
   // import { BorderBox8 as DvBorderBox8 } from '@kjgl77/datav-vue3';
 
   // const echartsOption = {
@@ -364,6 +368,10 @@
     }
   }
 
+  function exportData() {
+    handleExportXls('安全监控导出', getExportUrl);
+  }
+
   onMounted(async () => {
     const { currentRoute } = useRouter();
     if (unref(currentRoute)) {
@@ -534,6 +542,47 @@
       }
     }
   }
+  .export-btn {
+    position: absolute;
+    color: #fff;
+    right: 20px;
+    .btn {
+      padding: 8px 20px;
+      position: relative;
+      border-radius: 2px;
+      color: #fff;
+      width: fit-content;
+      cursor: pointer;
+
+      &::before {
+        position: absolute;
+        display: block;
+        content: '';
+        width: calc(100% - 4px);
+        height: calc(100% - 4px);
+        top: 2px;
+        left: 2px;
+        border-radius: 2px;
+        z-index: -1;
+      }
+    }
+
+    .btn1 {
+      border: 1px solid #5cfaff;
+
+      &::before {
+        background-image: linear-gradient(#2effee92, #0cb1d592);
+      }
+
+      &:hover {
+        border: 1px solid #5cfaffaa;
+
+        &::before {
+          background-image: linear-gradient(#2effee72, #0cb1d572);
+        }
+      }
+    }
+  }
 
   :deep(.@{ventSpace}-tabs-tabpane-active) {
     height: 100%;

+ 3 - 0
src/views/vent/monitorManager/safetyMonitor/safety.api.ts

@@ -7,6 +7,7 @@ enum Api {
   itemList = '/sys/dictItem/list',
   safetyDeviceList = '/ventanaly-device/monitor/codeDict',
   safetyList = '/ventanaly-device/history/getAlarmHistoryData',
+  export = '/ventanaly-device/safety/reportInfo/expComReport?tempName=aqjk',
 }
 /**
  * 列表接口
@@ -27,3 +28,5 @@ 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;

+ 16 - 5
src/views/vent/monitorManager/windowMonitor/index.vue

@@ -22,12 +22,14 @@
           <span class="input-title">风窗面积:</span>
           <a-input-number size="small" placeholder="0" :min="0" :max="90" :step="1" v-model:value="windowAngle" />
         </div> -->
-        <div class="row" v-if="hasPermission('window:control') && selectData.nwindownum > 1">
-          <div class="button-box" @click="setArea(1)">设定前窗面积</div>
-          <div class="button-box" @click="setArea(2)">设定后窗面积</div>
+        <div class="row" v-if="selectData.nwindownum > 1">
+          <div v-if="hasPermission('window:control')" class="button-box" @click="setArea(1)">设定前窗面积</div>
+          <div v-if="hasPermission('window:control')" class="button-box" @click="setArea(2)">设定后窗面积</div>
+          <div v-if="hasPermission('window:ldkz')" class="button-box" @click="setArea(3)">自主联动控制</div>
         </div>
-        <div class="row" v-if="hasPermission('window:control') && selectData.nwindownum == 1">
-          <div class="button-box" @click="setArea(1)">设定风窗面积</div>
+        <div class="row" v-if="selectData.nwindownum == 1">
+          <div v-if="hasPermission('window:control')" class="button-box" @click="setArea(1)">设定风窗面积</div>
+          <div v-if="hasPermission('window:ldkz')" class="button-box" @click="setArea(3)">自主联动控制</div>
         </div>
       </div>
       <div class="top-right row">
@@ -329,11 +331,20 @@
       modalTitle.value = '设定风窗面积';
     }
 
+    if (flag == 3) {
+      modalTitle.value = '自主联动控制';
+    }
+
     modalType.value = flag + '';
     modalIsShow.value = true;
   };
 
   const handleOK = (passWord, handlerState, windowAngleNum) => {
+    if (!passWord && !globalConfig?.simulatedPassword) {
+      message.warning('请输入密码!');
+      return;
+    }
+
     windowAngle.value = windowAngleNum;
     const data = {
       deviceid: selectData.deviceID,

+ 1 - 1
src/views/vent/monitorManager/windowMonitor/modal.vue

@@ -5,7 +5,7 @@
         <ExclamationCircleFilled style="color: #ffb700; font-size: 30px" />
         <div class="warning-text">您是否要进行{{ title }}操作?</div>
       </div>
-      <div class="vent-flex-row input-box">
+      <div class="vent-flex-row input-box" v-if="type !== '3'">
         <div class="label">风窗面积:</div>
         <a-input-number size="small" placeholder="0" :min="0" :max="90" v-model:value="area" />
       </div>