父组件
<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>