Просмотр исходного кода

[Feat 0000]导航组件优化 可配置组件开发

bobo04052021@163.com 1 месяц назад
Родитель
Сommit
f5580656fc

+ 6 - 2
src/views/vent/home/configurable/belt/belt.vue

@@ -3,8 +3,8 @@
   <div class="company-home">
     <div class="border">
       <customHeader>皮带巷三级防灭火系统</customHeader>
-      <div style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 0">
-        <SubApp />
+      <div class="test" style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 0">
+        <!-- <SubApp /> -->
       </div>
       <div class="box-container">
         <ModuleCommon
@@ -342,5 +342,9 @@ onMounted(() => {
     background-size: 100% 100%;
     margin-top: 50px;
   }
+  .test {
+    background: url('./test.png') no-repeat;
+    background-size: 100% 100%;
+  }
 }
 </style>

+ 11 - 21
src/views/vent/home/configurable/belt/components/BeltNav.vue

@@ -28,7 +28,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted, computed } from 'vue';
+import { ref, onMounted } from 'vue';
 import { useRouter, useRoute } from 'vue-router';
 const router = useRouter();
 const route = useRoute();
@@ -53,33 +53,23 @@ const menuList = ref([
     pageType: 'emergencyControl',
   },
 ]);
-
-// 点击事件
 function handleNavClick(data: any) {
   activeIndex.value = data.index;
-  const pageType = `${data.item.pageType}`;
+  const pageType = data.item.pageType;
   router.replace({
-    query: {
-      ...router.currentRoute.value.query, // 保留原有参数
-      pageType: pageType,
-    },
+    path: `/belt/fireS/${pageType}`,
   });
 }
 
 onMounted(() => {
-  const pageTypePath = computed(() => {
-    const queryType = route.query.pageType;
-    if (queryType) {
-      return queryType;
-    } else {
-      const isFireMonitorPath = window.location.href.includes('fireMonitor');
-      const isEmergencyControlPath = window.location.href.includes('emergencyControl');
-      const isSprayControlPath = window.location.href.includes('sprayControl');
-      return isFireMonitorPath ? 'fireMonitor' : isEmergencyControlPath ? 'emergencyControl' : isSprayControlPath ? 'sprayControl' : 'fireMonitor';
+  const currentType = route.params.type as string;
+
+  if (currentType) {
+    const idx = menuList.value.findIndex((item) => item.pageType === currentType);
+    if (idx !== -1) {
+      activeIndex.value = idx;
     }
-  });
-  const idx = menuList.value.findIndex((item) => item.pageType === pageTypePath.value);
-  if (idx !== -1) activeIndex.value = idx;
+  }
 });
 </script>
 
@@ -196,4 +186,4 @@ onMounted(() => {
 .btn-right.nav-menu-active {
   background-image: url('/@/assets/images/beltFire/yjkf/navBtnRight-1.png');
 }
-</style>
+</style>

+ 1 - 1
src/views/vent/home/configurable/belt/components/Header.vue

@@ -43,7 +43,7 @@
 <script lang="ts" setup>
 import { ref, watch } from 'vue';
 import { Config } from '../../../../deviceManager/configurationTable/types';
-import { useInitModule } from '../../../../home/configurable/hooks/useInit';
+import { useInitModule } from '../../hooks/useInit';
 import { MenuItem, Menu, Dropdown } from 'ant-design-vue';
 import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons-vue';
 const props = defineProps<{

+ 2 - 0
src/views/vent/home/configurable/belt/components/ModuleCommon.vue

@@ -89,6 +89,8 @@ watch(
   (d) => {
     init(d);
     if (!selectedDeviceID.value) {
+      console.log(selectedDeviceID.value, '------');
+
       selectedDeviceID.value = options.value[0]?.value;
     }
   },

+ 0 - 95
src/views/vent/home/configurable/belt/components/customHeader.vue

@@ -1,95 +0,0 @@
-<template>
-  <div class="vent-custom-header">
-    <div class="vent-home-header">
-      <div class="header-text"><slot></slot></div>
-    </div>
-  </div>
-</template>
-<script lang="ts">
-import { defineComponent, computed } from 'vue';
-import { Decoration5 } from '@kjgl77/datav-vue3';
-export default defineComponent({
-  name: 'CustomHeader',
-  components: { Decoration5 },
-  props: {},
-  emits: ['change'],
-});
-</script>
-<style lang="less">
-@import '/@/design/vent/modal.less';
-
-.@{ventSpace}-select-dropdown.drop {
-  background-color: transparent !important;
-
-  .@{ventSpace}-select-item-option-selected,
-  .@{ventSpace}-select-item-option-active {
-    background-color: #ffffff33 !important;
-  }
-  .@{ventSpace}-select-item {
-    color: inherit;
-    &:hover {
-      background-color: #ffffff33 !important;
-    }
-  }
-  .@{ventSpace}-select-tree {
-    .@{ventSpace}-select-tree-treenode {
-      color: inherit;
-    }
-    .@{ventSpace}-select-tree-switcher-icon {
-      color: inherit;
-    }
-  }
-}
-</style>
-<style lang="less" scoped>
-@import '/@/design/theme.less';
-@ventSpace: zxm;
-
-.vent-custom-header {
-  --image-vent-header1: url('/@/assets/images/beltFire/top.png');
-  width: 100%;
-  position: relative;
-  z-index: 9999;
-  pointer-events: none;
-  .vent-home-header {
-    width: 100%;
-    position: fixed;
-    top: 0;
-    // background: url('/@/assets/images/vent/new-home/header-bg.png') no-repeat;
-    // height: 100px;
-    background: var(--image-vent-header1) no-repeat;
-    height: 89px;
-    background-size: contain;
-    display: flex;
-    justify-content: center;
-    .header-icon {
-      margin-top: 45px;
-    }
-    .header-text {
-      position: fixed;
-      top: 5px;
-      color: #fff;
-      font-size: 32px;
-      font-family: 'ysbtFont';
-      background-image: linear-gradient(#ffffff 50%, @vent-base-light-bg);
-      -webkit-background-clip: text;
-      color: transparent;
-    }
-  }
-}
-:deep(.zxm-select) {
-  width: 300px;
-  .@{ventSpace}-select-selector {
-    background: transparent !important;
-    border: none !important;
-    box-shadow: none !important;
-    .zxm-select-selection-item {
-      color: #fff !important;
-      font-size: 20px;
-    }
-  }
-  .@{ventSpace}-select-arrow {
-    color: #fff !important;
-  }
-}
-</style>

+ 0 - 94
src/views/vent/home/configurable/belt/components/headerBelt.vue

@@ -1,94 +0,0 @@
-<template>
-  <div class="vent-custom-header">
-    <div class="vent-home-header">
-      <div class="header-text"><slot></slot></div>
-    </div>
-  </div>
-</template>
-<script lang="ts">
-  import { defineComponent, computed } from 'vue';
-  import { Decoration5 } from '@kjgl77/datav-vue3';
-  export default defineComponent({
-    name: 'CustomHeader',
-    components: { Decoration5 },
-    props: {},
-    emits: ['change'],
-  });
-</script>
-<style lang="less">
-  @import '/@/design/vent/modal.less';
-
-  .@{ventSpace}-select-dropdown.drop {
-    background-color: transparent !important;
-
-    .@{ventSpace}-select-item-option-selected,
-    .@{ventSpace}-select-item-option-active {
-      background-color: #ffffff33 !important;
-    }
-    .@{ventSpace}-select-item {
-      color: inherit;
-      &:hover {
-        background-color: #ffffff33 !important;
-      }
-    }
-    .@{ventSpace}-select-tree {
-      .@{ventSpace}-select-tree-treenode {
-        color: inherit;
-      }
-      .@{ventSpace}-select-tree-switcher-icon {
-        color: inherit;
-      }
-    }
-  }
-</style>
-<style lang="less" scoped>
-  @import '/@/design/theme.less';
-  @ventSpace: zxm;
-
-  .vent-custom-header {
-    --image-vent-header1: url('/@/assets/images/beltFire/top.png');
-    width: 100%;
-    position: relative;
-    z-index: 9999;
-    pointer-events: none;
-    .vent-home-header {
-      width: 100%;
-      position: fixed;
-      top: 0;
-      // background: url('/@/assets/images/vent/new-home/header-bg.png') no-repeat;
-      // height: 100px;
-      height: 89px;
-      background-size: contain;
-      display: flex;
-      justify-content: center;
-      .header-icon {
-        margin-top: 45px;
-      }
-      .header-text {
-        position: fixed;
-        top: 5px;
-        color: #fff;
-        font-size: 32px;
-        font-family: 'ysbtFont';
-        background-image: linear-gradient(#ffffff 50%, @vent-base-light-bg);
-        -webkit-background-clip: text;
-        color: transparent;
-      }
-    }
-  }
-  :deep(.zxm-select) {
-    width: 300px;
-    .@{ventSpace}-select-selector {
-      background: transparent !important;
-      border: none !important;
-      box-shadow: none !important;
-      .zxm-select-selection-item {
-        color: #fff !important;
-        font-size: 20px;
-      }
-    }
-    .@{ventSpace}-select-arrow {
-      color: #fff !important;
-    }
-  }
-</style>

+ 16 - 17
src/views/vent/home/configurable/belt/configurable.data.ts

@@ -1,4 +1,3 @@
-import { title } from 'process';
 import { Config } from '../../../deviceManager/configurationTable/types';
 // 皮带巷三级防灭火首页
 export const testBeltLaneFire: Config[] = [
@@ -375,9 +374,9 @@ export const testYjkf: Config[] = [
       // mock: doorMock,
     },
     showStyle: {
-      size: 'width:440px;height:825px;',
+      size: 'width:440px;height:820px;',
       version: '原版',
-      position: 'top:20px;left:25px;',
+      position: 'top:30px;left:25px;',
     },
   },
   {
@@ -425,8 +424,8 @@ export const testYjkf: Config[] = [
             title: 'name',
             contents: [
               {
-                code: '${id}',
-                value: '${warnLevel}',
+                code: '',
+                value: '',
                 info: '',
               },
             ],
@@ -436,16 +435,16 @@ export const testYjkf: Config[] = [
       // mock: BDfireMock,
     },
     showStyle: {
-      size: 'width:440px;height:820px;',
+      size: 'width:440px;height:850px;',
       version: '原版',
-      position: 'top:20px;right:25px;',
+      position: 'top:0px;right:25px;',
     },
   },
 ];
 export const testBeltNew: Config[] = [
   // ==================== 左侧栏:火灾监测设备状态 ====================
   {
-    deviceType: '',
+    deviceType: 'fireMonitor',
     moduleName: '火灾监测设备报警与分析',
     pageType: 'fireMonitorLeft',
     moduleData: {
@@ -683,15 +682,15 @@ export const testBeltNew: Config[] = [
       ],
     },
     showStyle: {
-      size: 'width:400px;height:790px;',
+      size: 'width:400px;height:800px;',
       version: '原版',
-      position: 'top:50px;left:25px;',
+      position: 'top:60px;left:25px;',
     },
   },
 
   // ==================== 中央中部:预警结果列表 ====================
   {
-    deviceType: '',
+    deviceType: 'fireMonitor',
     moduleName: '预警结果',
     pageType: 'fireMonitorMid',
     moduleData: {
@@ -779,7 +778,7 @@ export const testBeltNew: Config[] = [
   },
 
   {
-    deviceType: '',
+    deviceType: 'fireMonitor',
     moduleName: '火灾监测设备状态',
     pageType: 'fireMonitor',
     moduleData: {
@@ -878,7 +877,7 @@ export const testBeltNew: Config[] = [
 
   // ==================== 右侧下部:车辆定位与CO浓度关联分析 ====================
   {
-    deviceType: '',
+    deviceType: 'fireMonitor',
     moduleName: '车辆定位与CO浓度关联分析',
     pageType: 'fireMonitor',
     moduleData: {
@@ -1145,9 +1144,9 @@ export const testSpary: Config[] = [
       },
     },
     showStyle: {
-      size: 'width:440px;height:825px;',
+      size: 'width:440px;height:820px;',
       version: '原版',
-      position: 'top:20px;left:25px;',
+      position: 'top:30px;left:25px;',
     },
   },
   {
@@ -1192,9 +1191,9 @@ export const testSpary: Config[] = [
       // mock: BDfireMock,
     },
     showStyle: {
-      size: 'width:440px;height:820px;',
+      size: 'width:440px;height:850px;',
       version: '原版',
-      position: 'top:20px;right:25px;',
+      position: 'top:0px;right:25px;',
     },
   },
 ];

BIN
src/views/vent/home/configurable/belt/test.png


+ 38 - 82
src/views/vent/home/configurable/components/belt/CameraList.vue

@@ -1,100 +1,59 @@
 <template>
   <div class="camera-modal">
-    <!-- 遍历每个设备组 -->
-    <div v-for="(group, groupIndex) in props.data" :key="groupIndex" class="sensor-group">
-      <div class="group-title">{{ group.strname }}</div>
-      <div class="camera-area">
-        <div v-for="camera in group.cameras || []" :key="camera.id" :ref="(el) => setPlayerRef(el, group.deviceID)" class="single-camera-container">
-        </div>
-      </div>
+    <div class="camrea-area">
+      <!-- 完全沿用你成熟的播放器容器 -->
+      <div v-if="renderPlayer" ref="playerRef" style="display: flex; width: 100%; height: 100%; overflow-y: auto; pointer-events: none"></div>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { onMounted, ref, reactive, computed, onBeforeUnmount } from 'vue';
-import { useCamera } from '/@/hooks/system/useCamera';
-const props = defineProps<{
-  config: Array<{
-    title: string;
-    contents: Array<{ code: string }>;
-  }>;
-  data: any[];
-}>();
-const renderPlayer = ref(true);
-const { getCamera, removeCamera } = useCamera();
-const deviceDomMap = reactive<Record<string, HTMLElement>>({});
-const setPlayerRef = (el: HTMLElement | null, deviceId: string) => {
-  if (el) {
-    deviceDomMap[deviceId] = el;
-  } else {
-    delete deviceDomMap[deviceId];
-  }
-};
-const allVideos = computed(() => {
-  return (
-    props.data?.flatMap((item) => {
-      const cameras = item.cameras || [];
-      return [item, ...cameras];
-    }) || []
-  );
+import { onMounted, ref, onBeforeUnmount } from 'vue';
+// 用你成熟的摄像头hooks
+import { useCamera } from '/@/hooks/system/useCameraPianation';
+
+const props = defineProps({
+  data: {
+    type: Array,
+    default: () => [],
+  },
 });
 
-onMounted(async () => {
-  const videos = allVideos.value;
-  for (const video of videos) {
-    if (video.deviceID) {
-      const targetDom = deviceDomMap[video.deviceID];
-      if (targetDom) {
-        await getCamera(video.deviceID, targetDom, renderPlayer);
-      } else {
-        console.warn(`未找到设备 ${video.deviceID} 的 DOM 容器`);
-      }
+const { getCamera, removeCamera } = useCamera();
+const playerRef = ref();
+const renderPlayer = ref(true);
+
+// 提取所有摄像头
+const allCameras = () => {
+  const list = [];
+  props.data.forEach((device) => {
+    if (device.cameras && device.cameras.length > 0) {
+      device.cameras.forEach((item) => {
+        list.push({
+          ...item,
+          deviceID: device.deviceID, // 携带设备ID
+        });
+      });
     }
-  }
+  });
+  return list;
+};
+onMounted(async () => {
+  const cameras = allCameras();
+  await getCamera('', playerRef, renderPlayer, '', cameras);
 });
 
+// 销毁
 onBeforeUnmount(() => {
-  removeCamera(Object.values(deviceDomMap));
+  removeCamera(playerRef);
 });
 </script>
 
 <style lang="less" scoped>
 .camera-modal {
   width: 100%;
-  height: 95%;
-  padding: 5px 10px;
-  box-sizing: border-box; // 防止 padding 撑破容器
-  .sensor-group {
-    background: url('@/assets/images/beltFire/fireMonitor/2-1.png') no-repeat;
-    background-size: 100% 100%;
-    padding: 10px;
-    height: 580px;
-    margin-bottom: 10px; // 增加组间距
-  }
-  .group-title {
-    background: url('@/assets/images/beltFire/fireMonitor/2-2.png') no-repeat;
-    background-size: 45% 100%;
-    color: #fff;
-    font-size: 12px;
-    font-weight: bold;
-    font-style: italic;
-    margin-bottom: 8px;
-    padding-bottom: 5px;
-    padding-left: 10px;
-  }
-  .camera-area {
-    width: 100%;
-    height: calc(100% - 40px); // 减去标题高度
-    display: flex;
-    flex-wrap: wrap; // 允许换行
-    align-content: flex-start;
-    overflow-y: auto;
-  }
-  .single-camera-container {
-    // 这里可以根据需要调整大小,或者让内部的播放器自适应
-    flex: 0 0 auto;
-    width: 100%; // 或者根据需求设置为 50% 等
+  .camrea-area {
+    width: 90%;
     height: 100%;
   }
 }
@@ -105,19 +64,16 @@ onBeforeUnmount(() => {
   justify-content: flex-start;
   flex-wrap: wrap;
   pointer-events: none;
-
   .liveVideo {
-    width: 462px !important;
+    width: 430px !important;
     height: 276px !important;
     padding: 15px !important;
     align-self: auto !important;
     margin: 10px 8px !important;
     background-size: 100% 100% !important;
   }
-
   .video-parent {
     pointer-events: auto !important;
-    align-self: auto !important;
   }
 }
 </style>

+ 1 - 1
src/views/vent/home/configurable/components/content.vue

@@ -202,7 +202,7 @@
           <SprayControl class="content__module" :config="config.config" :data="data" />
         </template>
         <template v-if="config.name === 'cameraList'">
-          <CameraList class="content__module" style="height: calc(100% - 20px)" :config="config.config" :data="config.data" />
+          <CameraList class="content__module" :config="config.config" :data="config.data" />
         </template>
         <!-- <template v-if="config.key === 'fire_control'">
         <FIreControl class="content__module" />