萤石云 ezuikit-js 视频监控

news2024/11/27 10:34:16

 

父组件

<template>
  <div class="securityProtectLargeScreen" v-if="waterWorks?.length > 0">
    <div class="leftSide">
      <ul class="leftItems flexColumnCenter">
        <li
          v-for="(item, index) in waterWorks"
          :key="index"
          @click="clickWaterWork(index)"
          :class="[
            activeWaterWork === index ? 'waterWorkSelectStyle' : '',
            'currentItem',
          ]"
          :title="item.name"
        >
          {{ item.name }}
        </li>
      </ul>
    </div>
    <div
      class="content-area"
      v-loading="loading"
      v-if="videoRecorderList.length > 0 && !loading"
    >
      <div class="jk">
        <div class="marginBottom15">
          <svg-icon
            iconName="icon-task-dange"
            :class="[
              activeNameIcon === 'singleIcon' ? 'selectStyle' : '',
              'marginRight20',
            ]"
            @click="selectCurrent('singleIcon')"
          ></svg-icon>
          <svg-icon
            iconName="icon-task-sige"
            :class="[activeNameIcon === 'fourIcon' ? 'selectStyle' : '']"
            @click="selectCurrent('fourIcon')"
          ></svg-icon>
        </div>
        <div class="items">
          <li
            v-for="(item, index) in videoRecorderList"
            :key="index"
            @click="clickLocation(index)"
            :class="[
              activeLocation === index ? 'locationSelectStyle' : '',
              'currentItem',
            ]"
            :title="item.thoroughfare_name"
          >
            {{ item.thoroughfare_name }}
          </li>
        </div>
      </div>
      <!-- 视频监控 -->
      <div v-if="videoList.length > 0" :key="Math.random()">
        <RecorderLook
          :width="`calc(100vw - 440px)`"
          :height="`calc(100vh - 188px)`"
          ref="recorderLook"
          :activeNameIcon="activeNameIcon"
          :videoList="videoList"
          @videoListIndex="getVideoListIndex"
        />
      </div>
    </div>
  </div>
  <!-- 无数据 -->
  <HomeNoData class="securityProtectLargeScreen" v-else />
</template>

<script setup>
import { ref, onMounted, nextTick } from "vue";
import RecorderLook from "@/components/videoSurveillance/RecorderLook.vue";
import { waterworksConfigList } from "@/api/waterPlantSystem";
import { waterConfigList } from "@/api/directDrinkingWaterSystem";
import { filterArrayByType } from "@/utils/deduplication";
import { useGlobalStore } from "@/stores/modules/global";
import { dvrCameraList } from "@/api/EquipmentManagementSystem/index.js";
import HomeNoData from "@/components/homeNoData/index.vue";
const props = defineProps({
  type: {
    type: String, // 判断是哪个系统
  },
});
const waterWorks = ref([]);
const videoRecorderList = ref([]);
const videoList = ref([]);

const globalStore = useGlobalStore();
const activeWaterWork = ref(0);
const activeLocation = ref(0);
const activeNameIcon = ref("singleIcon");
const fourVideoActive = ref(0); // 四个的选中
const loading = ref(false);
const codeString = ref(null);

const clickWaterWork = (index) => {
  activeWaterWork.value = index;
  videoRecorderList.value = waterWorks.value[index].recorder;
  let recorder = videoRecorderList.value;
  const idsString = recorder.map((item) => item.id).join(",");
  // 获取当前水厂的监控设备
  getDvrCameraList(idsString);
};

const recorderLook = ref(null);

const clickLocation = (index) => {
  activeLocation.value = index;
  if (activeNameIcon.value === "singleIcon") {
    videoList.value[0] = videoRecorderList.value[index];
  }
  if (activeNameIcon.value === "fourIcon") {
    videoList.value[fourVideoActive.value] = videoRecorderList.value[index];
  }
};

const getVideoListIndex = (index) => {
  if (activeNameIcon.value === "fourIcon") {
    fourVideoActive.value = index;
  }
};

const selectCurrent = (val) => {
  activeNameIcon.value = val;
  // 视频监控的第一个id
  const index = videoRecorderList.value?.findIndex(
    (item) => item.id === videoList?.value[0]?.id
  );
  activeLocation.value = index;
};

const getWaterWorks = () => {
  let data = filterArrayByType(globalStore.subAuthList, props.type);
  codeString.value = data.map((item) => item.code).join(",");
  if (props.type === "ist_water") getrecorderInfo(waterConfigList);
  if (props.type === "ist_water_purification_plant")
    getrecorderInfo(waterworksConfigList);
};

const getrecorderInfo = (apiFunction) => {
  apiFunction({ codes: codeString.value })
    .then((res) => {
      if (res.status === 200) {
        let data = res.data;
        // 过滤掉有监控设备的子项目
        waterWorks.value = data.filter((item) => item?.recorder?.length > 0);
        if (waterWorks?.value.length === 0) {
          return;
        }

        let recorder = waterWorks.value[0].recorder;
        const idsString = recorder.map((item) => item.id).join(",");
        // 获取当前子项目的监控设备
        getDvrCameraList(idsString);
      }
    })
    .catch((error) => {});
};

// 当前子项目摄像头列表
const getDvrCameraList = (idsString) => {
  loading.value = true;
  dvrCameraList({ dvr_id: idsString })
    .then((res) => {
      loading.value = false;
      if (res.status === 200) {
        videoRecorderList.value = res.data?.list;
        videoList.value = res.data?.list.slice(0, 4);
        activeLocation.value = 0;
      }
    })
    .catch((error) => {
      loading.value = false;
    });
};

getWaterWorks();
onMounted(() => {});
</script>

<style lang="scss" scoped>
.securityProtectLargeScreen {
  width: 100vw;
  height: calc(100vh - 100px);
  padding: 6px 10px 40px 10px;
  display: flex;
}
.leftSide {
  height: calc(100vh - 146px);
  width: 195px;
  background: transparent;
  border: 1px solid #0862ad;
  box-shadow: inset 0 0 12px rgba(0, 206, 255, 0.51);
  padding: 18px 25px;
  overflow-y: auto;
}
.leftItems {
  list-style-type: none;
  padding: 0;
}
.currentItem {
  cursor: pointer;
  width: 144px;
  height: 38px;
  line-height: 36px;
  background: linear-gradient(359.57deg, #075281 0%, #032c46 100%);
  border: 1px solid #15598e;
  font-weight: 500;
  font-size: 16px;
  text-align: center;
  color: #338ac1;
  margin-bottom: 22px;
  z-index: 9999;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  padding: 0 4px;
}
.waterWorkSelectStyle {
  background: linear-gradient(359.57deg, #1c6fa3 0%, #033f65 100%);
  border: 1px solid #05d9ff;
  box-shadow: inset 0 0 12px #7cb4ff;
  color: #fff;
}
.locationSelectStyle {
  background: #05436a;
  border: 1px solid #05c5ff;
  box-shadow: inset 0 0 12px #7cb4ff;
  color: #fff;
}

:deep(.svg-icon) {
  width: 30px;
  height: 30px;
  background: linear-gradient(359.57deg, #075281 0%, #032c46 100%);
  color: rgba(0, 206, 255, 0.51);
}
.selectStyle {
  background: linear-gradient(359.57deg, #1c6fa3 0%, #033f65 100%);
  color: rgba(0, 206, 255);
}
.content-area {
  flex: 1;
  margin-left: 16px;
  box-shadow: inset 0 0 12px rgba(0, 206, 255, 0.51);
  padding: 20px;
  border: 1px solid #0862ad;
  display: flex;
  justify-content: space-between;
  .jk {
    overflow-y: auto;
  }
}
</style>

监控子组件

<template>
  <div
    class="hello-ezuikit-js"
    :style="{ width: props.width, height: props.height }"
    ref="videoBox"
  >
    <!-- 最多4格 -->
    <div
      v-for="(key, index) in 4"
      :key="key"
      :class="props.activeNameIcon == 'singleIcon' ? 'width' : 'width2'"
      style="position: relative"
      :loading="loading"
      @click="changeVideo(index)"
      v-loading="loading"
    >
      <div
        :id="'video-cover' + index"
        class="video-cover"
        :class="{
          'video-active':
            selectVideo === index && props.activeNameIcon !== 'singleIcon',
        }"
      >
        <div
          class="videoTitle"
          v-if="props.fromPage !== 'SecondaryWpsHomePage'"
        >
          {{ titleArr[index] }}
        </div>
        <div :id="'video-container' + index + props.second"></div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {
  ref,
  reactive,
  computed,
  watch,
  watchEffect,
  onMounted,
  onBeforeUnmount,
  nextTick,
} from "vue";
import { dvrCameraLive } from "@/api/EquipmentManagementSystem/index.js";
const loading = ref(false);
import EZUIKit from "ezuikit-js";
const props = defineProps({
  videoList: {
    type: Array,
    required: true,
  },
  activeNameIcon: {
    type: String,
    default: () => {
      return "singleIcon";
    },
  },
  fromPage: {
    type: String,
    default: () => {
      return "";
    },
  },
  width: {
    type: String,
  },
  height: {
    type: String,
  },
  second: {
    type: String,
    default: () => {
      return "";
    },
  },
});

const titleArr = ref([]);
const selectVideo = ref(null); // 当前选中的video序号
// 打开监控
const showVideo = (id, titleName, index) => {
  titleArr.value[index] = titleName;
  loading.value = true;
  getDvrCameraLive(id, index);
};
const UIKitDEMO = ref(null);

const videoBox = ref(null);

// 获取直播信息
const getDvrCameraLive = (id, index) => {
  console.log(8888888, id, index);
  dvrCameraLive(id).then((res) => {
    loading.value = false;
    if (res.status === 200) {
      let width = null;
      let height = null;
      if (props.activeNameIcon === "singleIcon") {
        width = videoBox?.value?.offsetWidth;
        if (props.fromPage === "SecondaryWpsHomePage") {
          height = videoBox?.value?.offsetHeight + 36;
        } else {
          height = videoBox?.value?.offsetHeight + 4;
        }
      } else {
        width = videoBox?.value?.offsetWidth / 2 - 2;
        height = videoBox?.value?.offsetHeight / 2 + 1.5;
      }

      if (res?.data?.url && res?.data?.access_token) {
        var player = new EZUIKit.EZUIKitPlayer({
          id: `video-container${index}${props.second}`, // 视频容器ID
          url: res.data.url,
          width: width,
          height: height,
          plugin: ["talk"],
          template: "pcLive",
          accessToken: res.data.access_token,
        });
        props.videoList[index].player = player;
        console.log(" UIKitDEMO.value", UIKitDEMO.value);
      }
    }
  });
};

const emits = defineEmits(["videoListIndex"]);
const changeVideo = (index) => {
  selectVideo.value = index;
  // alert(index)
  emits("videoListIndex", index);
};

const getResizeCss = () => {
  props.videoList.forEach((item, index) => {
    console.log("getResizeCss", item, index);
    if (props.activeNameIcon === "singleIcon") {
      nextTick(() => {
        // 二供首页无监控标题
        if (props.fromPage === "SecondaryWpsHomePage") {
          item?.player?.reSize(
            videoBox?.value?.offsetWidth,
            videoBox?.value?.offsetHeight + 36
          );
        } else {
          item?.player?.reSize(
            videoBox?.value?.offsetWidth,
            videoBox?.value?.offsetHeight + 4
          );
        }
      });
    } else {
      nextTick(() => {
        item?.player?.reSize(
          videoBox?.value?.offsetWidth / 2 - 2,
          videoBox?.value?.offsetHeight / 2 + 1.5
        );
      });
    }
  });
};

onMounted(() => {
  if (props.activeNameIcon === "singleIcon") {
    const firstVideo = props.videoList[0];
    showVideo(firstVideo.id, firstVideo.thoroughfare_name, 0);
  } else {
    props.videoList.forEach((item, index) => {
      console.log(999999, item, index);
      showVideo(item.id, item.thoroughfare_name, index);
    });
  }
  window.addEventListener("resize", getResizeCss);
});

// 需要销毁,不然会导致页面卡死问题
onBeforeUnmount(() => {
  props.videoList.forEach((item) => {
    if (item.player) {
      item.player.stop();
      // 假设ezuikit - js有closeInputStream方法
      if (item.player.closeInputStream) {
        item.player.closeInputStream();
      }
    }
  });
  window.removeEventListener("resize", getResizeCss);
  const audiolefts = document.body.querySelectorAll("#audioleft");
  audiolefts.forEach((div) => {
    div.remove();
  });
  const audiorights = document.body.querySelectorAll("#audioright");
  audiorights.forEach((div) => {
    div.remove();
  });
});

// 暴露方法
defineExpose({ showVideo });
</script>
<style lang="scss" scoped>
.videoTitle {
  height: 44px;
  background: #090a0a;
  color: #fff;
  font-size: 16px;
  padding-left: 20px;
  line-height: 44px;
}

:deep(.el-loading-mask) {
  background-color: #000;
}

:deep(.header-controls) {
  display: none !important;
}

.hello-ezuikit-js {
  // width: calc(100vw - 440px);
  // height: calc(100vh - 188px);
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
  background: #000;

  .width {
    width: 100%;
    height: 100%;
  }

  .width2 {
    width: 50%;
    height: 50%;
  }
}

.video-cover {
  display: flex;
  flex-direction: column;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 5;
  box-sizing: border-box;
}

.video-active {
  border: 1px solid red !important;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2204547.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java | Leetcode Java题解之第470题用Rand7()实现Rand10()

题目&#xff1a; 题解&#xff1a; class Solution extends SolBase {public int rand10() {int a, b, idx;while (true) {a rand7();b rand7();idx b (a - 1) * 7;if (idx < 40) {return 1 (idx - 1) % 10;}a idx - 40;b rand7();// get uniform dist from 1 - 63…

安卓13禁止用户打开开发者选项 android13禁止用户打开开发者选项

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 设置 =》关于平板电脑 =》版本号,一般的话,在这里连续点击就可以打开我们的开发者选项了。但是有些系统要进行保密,因此要禁止用户进入。 2.问题分析 这里我们是通过点…

FastAPI框架使用枚举来型来限定参数、FastApi框架隐藏没多大意义的Schemes模型部分内容以及常见的WSGI服务器Gunicorn、uWSGI了解

一、FastAPI框架使用枚举来型来限定参数 FastAPI框架验证时&#xff0c;有时需要通过枚举的方式来限定参数只能为某几个值中的一个&#xff0c;这时就可以使用FastAPI框架的枚举类型Enum了。publish:December 23, 2020 -Wednesday 代码如下&#xff1a; #引入Enum模块 from fa…

【自注意力与Transformer架构在自然语言处理中的演变与应用】

背景介绍 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;序列到序列&#xff08;seq2seq&#xff09;模型和Transformer架构的出现&#xff0c;极大地推动了机器翻译、文本生成和其他语言任务的进展。传统的seq2seq模型通常依赖于循环神经网络&#xff08;RNN&…

【idea】切换多个仓库到一个分支

需求描述 打开个一个Project 里面包含多个子项目&#xff0c;每一个子项目都有一个自己的git仓库。在idea 中有没有一次性把多个项目切换到同一个分支上面。 解决方案 右键git -> branch 点击右上角的此轮 勾选Execute Branch Operations on All Roots 点击ommon Remote …

萱仔求职复习系列——2 Linux的常用方法(包含基础进阶高级操作)

由于最近接了一个笔试&#xff0c;发现笔试可能涉及到Linux&#xff0c;我准备临时抱佛脚一下赶紧复习一下Linux的用法哈哈。Linux 的基础用法包含文件系统操作、权限管理、网络配置、进程管理等基本命令&#xff1b;进阶操作包括网络调试、包管理、服务管理和用户管理等&#…

【jdk19虚拟线程 VS 普通线程】

文章目录 一.什么是虚拟线程二.虚拟线程与普通线程的区别1.普通线程2.虚拟线程3. 实际应用中的区别 三.上demo对比性能。1.线程池配置2.Service实现3.测试结果 四.小结 一.什么是虚拟线程 虚拟线程&#xff0c;也称作轻量级线程&#xff0c;是由JVM直接管理的线程类型&#xf…

jmeter入门:脚本录制

1.设置代理。 网络连接-》代理-》手动设置代理. ip&#xff1a; 127.0.0.1&#xff0c; port&#xff1a;8888 2. add thread group 3. add HTTP(s) test script recorder, target controller chooses Test plan-> thread Group 4. click start. then open the browser …

Golang | Leetcode Golang题解之第467题环绕字符串中唯一的子字符串

题目&#xff1a; 题解&#xff1a; func findSubstringInWraproundString(p string) (ans int) {dp : [26]int{}k : 0for i, ch : range p {if i > 0 && (byte(ch)-p[i-1]26)%26 1 { // 字符之差为 1 或 -25k} else {k 1}dp[ch-a] max(dp[ch-a], k)}for _, v :…

Java主流框架项目实战——SpringBoot入门

单元1-1 1&#xff09; IDEA工具安装好 2&#xff09; Maven安装&#xff0c;配置好 IDEA安装及永久试用 配置maven 单元1-2 使用aliyun(https://start.aliyun.com/)创建一个spring boot项目&#xff0c;hello world&#xff01; 构建项目 1&#xff09;构建项目 直接默认…

MicroFlow:一种高效的基于Rust的TinyML推理引擎

英文论文标题&#xff1a;MICROFLOW: AN EFFICIENT RUST-BASED INFERENCE ENGINE FOR TINYML 中文论文标题&#xff1a;MicroFlow&#xff1a;一种高效的基于Rust的TinyML推理引擎 作者信息&#xff1a; Matteo Carnelos&#xff0c;意大利帕多瓦大学&#xff0c;Grepit AB,…

什么软件可以晚上睡觉录音

什么软件可以晚上睡觉录音&#xff0c;在日常生活中&#xff0c;我们常常忽略夜间的声音&#xff0c;然而这些声音有时可能会揭示重要信息&#xff0c;比如打鼾情况、说梦话、甚至是潜在的睡眠问题。因此&#xff0c;一款适合夜间录音的软件对于关注健康及生活细节的人来说至关…

在IDEA中配置Selenium和WebDriver

前言&#xff1a; 在当今自动化测试和网络爬虫的领域&#xff0c;Selenium是一个被广泛使用的工具。它不仅能够模拟用户与浏览器的交互&#xff0c;还能进行网页测试和数据抓取。而为了使用Selenium与谷歌/Edge浏览器进行自动化测试&#xff0c;配置合适的WebDriver至关重要。本…

【时时三省】(C语言基础)指针笔试题8

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 笔试题8 c是个数组 它的每个元素是char* 它初始化了四个字符串 把这四个字符串的首字符的地址 传到了c里面 cp有四个元素 每个元素的类型是char** 所以c3指向FORST c2指向POINT c1指向NE…

数学建模算法与应用 第9章 支持向量机及其方法

目录 9.1 支持向量机的基本原理 核函数的种类&#xff1a; 9.2 支持向量机的Matlab命令及应用 Matlab代码示例&#xff1a;二分类支持向量机 9.3 乳腺癌的诊断案例 Matlab代码示例&#xff1a;乳腺癌数据分类 9.4 支持向量回归&#xff08;SVR&#xff09; Matlab代码示…

uibot发送邮件:自动化邮件发送教程详解!

uibot发送邮件的操作指南&#xff1f;uibot发送邮件的两种方式&#xff1f; 在现代办公环境中&#xff0c;自动化流程的引入极大地提高了工作效率。uibot发送邮件功能成为了许多企业和个人实现邮件自动化发送的首选工具。AokSend将详细介绍如何使用uibot发送邮件。 uibot发送…

【AIGC】寻找ChatGPT最佳推理步骤:CoT思维链技术的探索与应用

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;CoT思维链概述&#x1f4af;CoT思维链在大型语言模型中的应用&#x1f4af;CoT思维链改变对模型推理能力的理解和改进方式多样化应用场景挑战与未来发展总结 &#x1f4a…

鸿蒙NEXT开发-动画(基于最新api12稳定版)

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

用FPGA做一个全画幅无反相机

做一个 FPGA 驱动的全画幅无反光镜数码相机是不是觉得很酷&#xff1f; 就是上图这样。 Sitina 一款开源 35 毫米全画幅 (3624 毫米) CCD 无反光镜可换镜头相机 (MILC)&#xff0c;这个项目最初的目标是打造一款数码相机&#xff0c;将 SLR [单镜头反光] 相机转换为 DSLR [数码…

探索Semantic Kernel:开启AI编程新篇章(入门篇)

文章目录 一、引言二、什么是Semantic Kernel&#xff1f;三、为什么选择Semantic Kernel&#xff1f;四、Semantic Kernel的核心特性4.1企业级4.2 自动化业务流程4.3 模块化和可扩展性 五、Semantic Kernel入门5.1 安装SDK5.2 编写控制台应用1. 配置2.实例3.示例一&#xff1a…