DarkMastar 5 månader sedan
förälder
incheckning
84e17d1d5a

+ 101 - 95
src/views/livePreview/components/toolBar.vue

@@ -1,91 +1,84 @@
 <template>
   <div class='toolBar'>
     <el-row style='display: flex;width: 100%;align-items: center;justify-content: flex-start'>
-<!--      <span style="margin-left: 10px;">分屏:</span>-->
-      <el-row v-show="!isPolling" :gutter="10" type="flex" align="middle" >
+      <!--      <span style="margin-left: 10px;">分屏:</span>-->
+      <el-row v-show="!isPolling" :gutter="10" type="flex" align="middle">
         <el-col :span="1.5">
-          <v-icon name="ri-checkbox-blank-fill" scale="2" :fill="active===1 ? '#3f9dfd' : '#ffffff'" @click.native="one"></v-icon>
-<!--          <el-button-->
-<!--              type="primary"-->
-<!--              plain-->
-<!--              size="mini"-->
-<!--              :disabled="isPolling"-->
-<!--              @click="one"-->
-<!--          >-->
-<!--          </el-button>-->
+          <v-icon name="ri-checkbox-blank-fill" scale="2" :fill="active===1 ? '#3f9dfd' : '#ffffff'"
+                  @click.native="one"></v-icon>
+          <!--          <el-button-->
+          <!--              type="primary"-->
+          <!--              plain-->
+          <!--              size="mini"-->
+          <!--              :disabled="isPolling"-->
+          <!--              @click="one"-->
+          <!--          >-->
+          <!--          </el-button>-->
         </el-col>
         <el-col :span="1.5">
-          <v-icon name="ri-function-fill" scale="2" :fill="active===4 ? '#3f9dfd' : '#ffffff'" @click.native="two"></v-icon>
-<!--          <el-button-->
-<!--              type="primary"-->
-<!--              plain-->
-<!--              size="mini"-->
-<!--              :disabled="isPolling"-->
-<!--              @click="two"-->
-<!--          >四分屏-->
-<!--          </el-button>-->
+          <v-icon name="ri-function-fill" scale="2" :fill="active===4 ? '#3f9dfd' : '#ffffff'"
+                  @click.native="two"></v-icon>
+          <!--          <el-button-->
+          <!--              type="primary"-->
+          <!--              plain-->
+          <!--              size="mini"-->
+          <!--              :disabled="isPolling"-->
+          <!--              @click="two"-->
+          <!--          >四分屏-->
+          <!--          </el-button>-->
         </el-col>
         <el-col :span="1.5">
-          <v-icon name="ri-grid-fill" scale="2" :fill="active===9 ? '#3f9dfd' : '#ffffff'" @click.native="three"></v-icon>
-<!--          <el-button-->
-<!--              type="primary"-->
-<!--              plain-->
-<!--              size="mini"-->
-<!--              :disabled="isPolling"-->
-<!--              @click="three"-->
-<!--          >九分屏-->
-<!--          </el-button>-->
+          <v-icon name="ri-grid-fill" scale="2" :fill="active===9 ? '#3f9dfd' : '#ffffff'"
+                  @click.native="three"></v-icon>
+          <!--          <el-button-->
+          <!--              type="primary"-->
+          <!--              plain-->
+          <!--              size="mini"-->
+          <!--              :disabled="isPolling"-->
+          <!--              @click="three"-->
+          <!--          >九分屏-->
+          <!--          </el-button>-->
         </el-col>
         <el-col :span="1.5">
-          <v-icon name="md-dashboardcustomize" scale="2" :fill="active===16 ? '#3f9dfd' : '#ffffff'" @click.native="four"></v-icon>
-<!--          <el-button-->
-<!--              type="primary"-->
-<!--              plain-->
-<!--              size="mini"-->
-<!--              :disabled="isPolling"-->
-<!--              @click="four"-->
-<!--          >十六分屏-->
-<!--          </el-button>-->
+          <v-icon name="md-dashboardcustomize" scale="2" :fill="active===16 ? '#3f9dfd' : '#ffffff'"
+                  @click.native="four"></v-icon>
+          <!--          <el-button-->
+          <!--              type="primary"-->
+          <!--              plain-->
+          <!--              size="mini"-->
+          <!--              :disabled="isPolling"-->
+          <!--              @click="four"-->
+          <!--          >十六分屏-->
+          <!--          </el-button>-->
         </el-col>
       </el-row>
     </el-row>
     <el-row style="display: flex;align-items:center; margin-right: 10px">
-      <el-col :span="5">
+      <el-col :span="12">
         <v-icon
-        v-if="!isPolling" title="开始轮询" @click.native="openPolling = true"
-        name="bi-bootstrap-reboot" scale="2" fill="#ffffff"
-       ></v-icon>
-       <v-icon
-        v-if="isPolling" title="停止轮询" @click.native="endPolling"
-        name="md-cached-outlined" animation="spin" speed="slow" scale="2" fill="#3f9dfd"
-       ></v-icon>
-        <!-- <el-button
-            v-if="!isPolling"
-            type="primary"
-            plain
-            size="mini"
-            @click="openPolling = true"
-        >开始轮询
-        </el-button> -->
-        <!-- <el-button
-            v-if="isPolling"
-            type="warning"
-            icon="el-icon-loading"
-            plain
-            size="mini"
-            @click="endPolling"
-        >停止轮询
-        </el-button> -->
+          v-if="!isPolling" title="开始轮询" @click.native="openPolling = true"
+          name="bi-bootstrap-reboot" scale="2" fill="#ffffff"
+        ></v-icon>
+        <v-icon
+          v-if="isPolling" title="停止轮询" @click.native="endPolling"
+          name="md-cached-outlined" animation="spin" speed="slow" scale="2" fill="#3f9dfd"
+        ></v-icon>
+      </el-col>
+      <el-col :span="12" style="margin-left: 20px">
+        <v-icon
+          title="清空预览" @click.native="handleCloseAll"
+          name="md-cleaningservices-outlined" scale="2" fill="#ffffff"
+        ></v-icon>
       </el-col>
     </el-row>
     <el-dialog title="轮询参数" :visible.sync="openPolling" width="450px" append-to-body class="dialog-class">
       <el-row style="display: flex;align-items: center;margin-bottom: 15px">
         画面数量:
         <el-radio-group v-model="count" style="width: 70%" size="small">
-          <el-radio-button label="one" >1</el-radio-button>
-          <el-radio-button label="two" >4</el-radio-button>
-          <el-radio-button label="three" >9</el-radio-button>
-          <el-radio-button label="four" >16</el-radio-button>
+          <el-radio-button label="one">1</el-radio-button>
+          <el-radio-button label="two">4</el-radio-button>
+          <el-radio-button label="three">9</el-radio-button>
+          <el-radio-button label="four">16</el-radio-button>
         </el-radio-group>
       </el-row>
       <el-row style="display: flex;align-items: center;margin-bottom: 15px">
@@ -112,9 +105,19 @@
 
 <script>
 import {mapGetters} from 'vuex'
-import { addIcons } from "oh-vue-icons";
-import { RiNumber1,RiCheckboxBlankFill,RiFunctionFill,RiGridFill,MdDashboardcustomize,BiBootstrapReboot,MdCachedOutlined} from "oh-vue-icons/icons";
-addIcons(RiNumber1,RiCheckboxBlankFill,RiFunctionFill,RiGridFill,MdDashboardcustomize,BiBootstrapReboot,MdCachedOutlined);
+import {addIcons} from "oh-vue-icons";
+import {
+  RiNumber1,
+  RiCheckboxBlankFill,
+  RiFunctionFill,
+  RiGridFill,
+  MdDashboardcustomize,
+  BiBootstrapReboot,
+  MdCachedOutlined,
+  MdCleaningservicesOutlined
+} from "oh-vue-icons/icons";
+
+addIcons(RiNumber1, RiCheckboxBlankFill, RiFunctionFill, RiGridFill, MdDashboardcustomize, BiBootstrapReboot, MdCachedOutlined,MdCleaningservicesOutlined);
 
 export default {
   name: 'toolBar',
@@ -129,7 +132,7 @@ export default {
     }
   },
   computed: {
-    ...mapGetters(['boxList', 'active','boxListIndex'])
+    ...mapGetters(['boxList', 'active', 'boxListIndex'])
   },
   watch: {
     // count(newData, oldData) {
@@ -167,7 +170,7 @@ export default {
           break
       }
       this.openPolling = false;
-      this.count='one'
+      this.count = 'one'
       this.$emit('startPolling', this.duration, this.interval)
     },
     endPolling() {
@@ -177,13 +180,16 @@ export default {
     changePollingStatus() {
       this.isPolling = false;
     },
-
+    // 点击按钮时,通过自定义事件通知父组件
+    handleCloseAll() {
+      this.$emit('closeAllVideos'); // 触发自定义事件
+    },
     async one() {
       this.$store.commit('updateBoxListIndex', 0)
-      if(!this.boxList.some(item=>item.recording===true)){
+      if (!this.boxList.some(item => item.recording === true)) {
         this.$store.commit('updateActive', 1)
         // this.$store.commit('updateBoxList', this.boxList.filter((item, index) => index < 1))
-      }else {
+      } else {
         this.$message.warning('正在录像中,请先结束录像!')
       }
 
@@ -191,31 +197,31 @@ export default {
     },
     two() {
       this.$store.commit('updateBoxListIndex', 0)
-      if(!this.boxList.some(item=>item.recording===true)){
-      //   // 处理右侧视频容器 少则新增,多则筛选
-      //   let boxList = []
-      //   switch (this.boxList.length) {
-      //     case 1:
-      //       boxList = this.boxList.filter((item, index) => index < 1)
-      //       boxList.push({boxId: 2}, {boxId: 3}, {boxId: 4})
-      //       break
-      //     case 9:
-      //       boxList = this.boxList.filter((item, index) => index < 4)
-      //       break
-      //     case 16:
-      //       boxList = this.boxList.filter((item, index) => index < 4)
-      //       break
+      if (!this.boxList.some(item => item.recording === true)) {
+        //   // 处理右侧视频容器 少则新增,多则筛选
+        //   let boxList = []
+        //   switch (this.boxList.length) {
+        //     case 1:
+        //       boxList = this.boxList.filter((item, index) => index < 1)
+        //       boxList.push({boxId: 2}, {boxId: 3}, {boxId: 4})
+        //       break
+        //     case 9:
+        //       boxList = this.boxList.filter((item, index) => index < 4)
+        //       break
+        //     case 16:
+        //       boxList = this.boxList.filter((item, index) => index < 4)
+        //       break
         // }
         this.$store.commit('updateActive', 4)
         // this.$store.commit('updateBoxList', boxList)
-      }else {
+      } else {
         this.$message.warning('正在录像中,请先结束录像!')
       }
 
     },
     three() {
       this.$store.commit('updateBoxListIndex', 0)
-      if(!this.boxList.some(item=>item.recording===true)){
+      if (!this.boxList.some(item => item.recording === true)) {
         // 处理右侧视频容器 少则新增,多则筛选
         // let boxList = []
         // switch (this.boxList.length) {
@@ -233,13 +239,13 @@ export default {
         // }
         this.$store.commit('updateActive', 9)
         // this.$store.commit('updateBoxList', boxList)
-      }else {
+      } else {
         this.$message.warning('正在录像中,请先结束录像!')
       }
     },
     four() {
       this.$store.commit('updateBoxListIndex', 0)
-      if(!this.boxList.some(item=>item.recording===true)){
+      if (!this.boxList.some(item => item.recording === true)) {
         // 处理右侧视频容器 少则新增,多则筛选
         // let boxList = []
         // switch (this.boxList.length) {
@@ -258,7 +264,7 @@ export default {
         // }
         this.$store.commit('updateActive', 16)
         // this.$store.commit('updateBoxList', boxList)
-      }else {
+      } else {
         this.$message.warning('正在录像中,请先结束录像!')
       }
     }
@@ -276,7 +282,7 @@ export default {
 </script>
 
 <style scoped>
-.toolBar{
+.toolBar {
   margin: 10px 0 0 5px;
   width: 99.6%;
   z-index: 1;

+ 28 - 0
src/views/livePreview/components/videoBox.vue

@@ -91,6 +91,34 @@ export default {
     // this.rectZoomInit()
   },
   methods: {
+    // 新增:关闭所有视频的方法
+    closeAllVideos() {
+      // 遍历所有视频窗口
+      this.boxList.forEach(item => {
+        if (item.mainUrl || item.auxiliaryUrl) {
+          // 1. 先设置当前选中窗口(用于触发播放器销毁逻辑)
+          this.setActiveBox(item);
+
+          // 2. 清空视频流地址和相关信息
+          item.mainUrl = '';
+          item.auxiliaryUrl = '';
+          item.code = '';
+          item.cameraId = '';
+          item.name = '';
+          item.rtc = '';
+          item.rtsp = '';
+        }
+      });
+
+      // 3. 清除选中状态和红色边框
+      this.$store.commit('updateSelectedMonitor', {});
+      this.showRedBorder = false;
+
+      // 4. 通知父组件清除树节点选中状态
+      this.$emit('clearTreeSelected');
+
+      this.$message.success('所有预览已关闭');
+    },
     // 双击窗口转换成单画面播放
     changeToOne(item) {
       console.log(this.boxList)

+ 22 - 4
src/views/livePreview/index.vue

@@ -303,7 +303,7 @@
 
       <!--监控预览-->
       <div class="tree-card" style="flex: 1; margin-left: 5px; flex-direction: column-reverse">
-        <toolbar style="height: 35px" ref="toolbar" @startPolling="startPolling" @endPolling="endPolling"></toolbar>
+        <toolbar style="height: 35px" ref="toolbar" @startPolling="startPolling" @endPolling="endPolling" @closeAllVideos="handleCloseAllVideos"></toolbar>
         <div style="
             display: flex;
             align-items: flex-start;
@@ -524,6 +524,13 @@ export default {
     this.closeSSE()
   },
   methods: {
+    // 新增:处理关闭所有视频的逻辑
+    handleCloseAllVideos() {
+      // 通过 ref 调用 videoBox 组件的 closeAllVideos 方法
+      if (this.$refs.video) {
+        this.$refs.video.closeAllVideos();
+      }
+    },
     getEquipmentOptions() {
       cameraSelect().then((response) => {
         this.cameraList = response.rows
@@ -617,7 +624,7 @@ export default {
           setTimeout(() => {
             if (node) {
               this.$nextTick(() => {
-                node.scrollIntoView({ block: 'center' }) // 通过scrollIntoView方法将对应的dom元素定位到可见区域 【block: 'center'】这个属性是在垂直方向居中显示
+                node.scrollIntoView({ block: 'nearest' }) // 通过scrollIntoView方法将对应的dom元素定位到可见区域 【block: 'center'】这个属性是在垂直方向居中显示
               })
             }
           }, 100)
@@ -1760,10 +1767,21 @@ export default {
   margin: 0 0 0px;
   background-color: #304156;
 }
-
-::v-deep .el-tabs__content {
+::v-deep .head-container .el-tabs__content {
   height: 35vh;
   flex-grow: 1;
+  //background-color: #030c18;
+  overflow-y: auto;
+
+  /* 滚动槽 */
+
+  &::-webkit-scrollbar-track {
+    background-color: transparent;
+  }
+}
+::v-deep .tool-tab .el-tabs__content {
+  //height: 35vh;
+  flex-grow: 1;
   background-color: #1a2c43;
   overflow-y: auto;