Files
td_official/src/views/monitorRoom/index.vue
2025-06-19 19:58:33 +08:00

608 lines
14 KiB
Vue

<template>
<div class="system-monitor-list wh100">
<div class="main">
<div class="app-container">
<!-- 左边视频窗口 -->
<div class="left" id="divPlugin">
<div class="hello-ezuikit-js" ref="videoBoxRef" v-loading="loading">
<!-- 最多16格 -->
<div
v-for="item in param.pageSize"
v-show="param.pageSize == 1 || param.pageSize == 4 || param.pageSize == 9"
:key="item"
:class="param.pageSize == 1 ? 'width' : param.pageSize == 4 ? 'width2' : 'width3'"
:id="'video-container-parent' + item"
>
<div :id="'video-container' + item"></div>
</div>
</div>
</div>
<img v-if="!tableData.data.length && !loading" src="./icon/em.png" alt="" class="image_position" />
<!-- 右边操作区 -->
<div class="right">
<el-table v-loading="loading" :data="tableData.data" @row-click="handleRowClick">
<el-table-column label="序号" align="center" type="index" :index="indexMethod" width="60" />
<el-table-column label="摄像头名称" align="center" prop="deviceName" min-width="100px" show-overflow-tooltip />
<!-- <el-table-column label="操作" align="center" class-name="small-padding" fixed="right">
<template #default="scope">
<el-switch v-model="scope.row.status" />
</template>
</el-table-column> -->
</el-table>
</div>
</div>
<!-- 底部切屏按钮 -->
<div class="btm-btns">
<div class="left">
<div style="width: 15%">
<div @click="changePage(1)">
<img class="rect" v-if="param.pageSize == 1" src="./icon/one_1.png" alt="" />
<img class="rect" v-else src="./icon/one.png" alt="" />
</div>
<div @click="changePage(4)">
<img class="rect" v-if="param.pageSize == 4" src="./icon/four_1.png" alt="" />
<img class="rect" v-else src="./icon/four.png" alt="" />
</div>
<div @click="changePage(9)">
<img class="rect" v-if="param.pageSize == 9" src="./icon/nine_1.png" alt="" />
<img class="rect" v-else src="./icon/nine.png" alt="" />
</div>
<!-- <div @click="select = 4">
<img class="rect" v-if="param.pageSize == 4" src="./icon/six_1.png" alt="" />
<img class="rect" v-else src="./icon/six.png" alt="" />
</div> -->
</div>
<div>
<el-pagination
background
v-show="tableData.total > 0"
layout="total, prev, pager, next"
:total="tableData.total"
:page-sizes="[1, 4, 9]"
v-model:current-page="param.pageNum"
v-model:page-size="param.pageSize"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
<div class="right"></div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { getCameraListByProjectId, getAccessToken } from '@/api/other/ys7Device';
import EZUIKit from 'ezuikit-js';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as any;
const loading = ref(false);
const videoBoxRef = ref<HTMLElement>();
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const tableData = ref({
data: [] as any[],
total: 0,
param: {
pageNum: 1,
pageSize: 4,
projectId: currentProject.value.id
}
});
const param = ref({
pageNum: 1,
pageSize: 4
});
const cameraList = ref<any[][]>([]);
const accessToken = ref('');
const templateType = ref<'standard' | 'pcLive'>('pcLive');
const pageSizes = ref([1, 4, 9]);
const changePage = (num: number) => {
param.value.pageNum = 1;
param.value.pageSize = num;
reRender();
};
const handleSizeChange = (val: number) => {
param.value.pageSize = val;
reRender();
};
const handleCurrentChange = (val: number) => {
param.value.pageNum = val;
reRender();
};
const getDeviceToken = async () => {
const res: any = await getAccessToken();
if (res.code === 200) {
accessToken.value = res.data;
}
};
const getCameraList = async () => {
loading.value = true;
await clearDom();
const res: any = await getCameraListByProjectId({
pageNum: 1,
pageSize: 10,
projectId: currentProject.value.id
});
let list = res.rows?.list ?? [];
tableData.value.data = res.rows;
tableData.value.total = res.rows?.total ?? 0;
cameraList.value = groupArr(tableData.value.data, param.value.pageSize);
console.log(cameraList.value, tableData.value.data);
if (cameraList.value.length) {
cameraList.value[param.value.pageNum - 1].forEach((item, index) => {
StructureEZUIKitPlayer(`ezopen://open.ys7.com/${item.deviceSerial}/1.hd.live`, item, index);
});
}
loading.value = false;
};
const clearDom = async () => {
tableData.value.data.forEach((item) => {
if (item.player) {
item.player.destroy().then((data: any) => {
console.log('clearDom destroy', data);
});
item.player = null;
}
});
for (let index = 0; index < param.value.pageSize; index++) {
let parentElement: HTMLElement | null = null;
if (templateType.value === 'standard') {
parentElement = document.getElementById(`video-container${index + 1}`);
} else if (templateType.value === 'pcLive') {
parentElement = document.getElementById(`video-container-parent${index + 1}`);
}
const child = document.createElement('div');
child.setAttribute('id', `video-container${index + 1}`);
if (parentElement) {
while (parentElement.firstChild) {
parentElement.removeChild(parentElement.firstChild);
}
if (templateType.value === 'pcLive') {
parentElement.appendChild(child);
}
}
}
};
const StructureEZUIKitPlayer = (url: string, item: any, index: number) => {
item.player = new EZUIKit.EZUIKitPlayer({
audio: '0',
id: `video-container${index + 1}`,
accessToken: accessToken.value,
url,
template: templateType.value,
width: (videoBoxRef.value?.children[0] as HTMLElement | undefined)?.offsetWidth,
height: (videoBoxRef.value?.children[0] as HTMLElement | undefined)?.offsetHeight,
plugin: ['talk']
});
};
const indexMethod = (index: number) => {
const pageNum = tableData.value.param.pageNum - 1;
return index + 1 + (pageNum > 0 ? pageNum * tableData.value.param.pageSize : 0);
};
const groupArr = (array: any[], subGroupLength: number) => {
const newArray: any[][] = [];
for (let i = 0; i < array.length; i += subGroupLength) {
newArray.push(array.slice(i, i + subGroupLength));
}
return newArray;
};
const reRender = async () => {
await clearDom();
cameraList.value = groupArr(tableData.value.data, param.value.pageSize);
if (cameraList.value.length) {
cameraList.value[param.value.pageNum - 1].forEach((item, index) => {
StructureEZUIKitPlayer(`ezopen://open.ys7.com/${item.deviceSerial}/1.hd.live`, item, index);
});
}
};
const handleRowClick = async (row: any) => {
if (param.value.pageSize === 1) {
for (let i = 0; i < tableData.value.data.length; i++) {
if (tableData.value.data[i].id === row.id) {
param.value.pageNum = i + 1;
break;
}
}
await reRender();
}
};
onMounted(async () => {
await getDeviceToken();
await getCameraList();
});
onBeforeUnmount(() => {
tableData.value.data.forEach((item) => {
if (item.player) {
item.player.destroy().then((data: any) => {
console.log('player destroyed', data);
});
item.player = null;
}
});
});
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.id,
(nid, oid) => {
// queryParams.value.projectId = nid;
// form.value.projectId = nid;
// resetMatrix();
// getList();
}
);
onUnmounted(() => {
listeningProject();
});
</script>
<style lang="scss" scoped>
.wh100 {
width: 100% !important;
height: 87.5vh !important;
}
.system-monitor-list {
.main {
width: 100%;
height: 100%;
.app-container {
width: 100%;
height: 95%;
left: 0;
// background-color: rgb(116, 228, 24);
margin: 0rem auto;
position: relative;
top: 0;
overflow: hidden;
display: flex;
flex-direction: row;
.image_position {
position: absolute;
top: 30%;
left: 40%;
transform: translateX(-40%);
}
.left {
overflow: hidden;
width: 85%;
// border: 0.125rem solid rgb(226, 181, 33);
height: 100%;
// position: absolute;
// left: 0;
// top: 0rem;
.title {
position: absolute;
top: 1rem;
left: 0.75rem;
font-size: 1rem;
font-weight: 600;
color: #000;
}
.time {
position: absolute;
top: 1rem;
right: 1.25rem;
font-size: 1rem;
font-weight: 600;
color: #000;
}
}
.left1 {
width: 85%;
border: 0.125rem solid rgb(37, 43, 102);
height: 100%;
top: 0rem;
position: absolute;
left: 0;
overflow: hidden;
}
.left2 {
top: 0rem;
width: 85%;
border: 0.125rem solid rgb(37, 43, 102);
height: 100%;
position: absolute;
overflow: hidden;
left: 0;
}
.right {
display: flex;
flex-direction: column;
justify-content: space-between;
background: rgb(255, 255, 255);
width: 15%;
height: 100%;
// top: 0;
// // border: .0625rem solid rgb(22, 21, 27);
// position: absolute;
// right: 0;
.right1 {
width: 100%;
text-align: start;
line-height: 2.5rem;
color: #6e727a;
margin: 0.3125rem auto;
height: 2.5rem;
padding: 0 1.25rem;
cursor: pointer;
}
.right1:hover {
background: #1393fc;
color: rgb(255, 255, 255);
border: none;
}
.right2 {
width: 100%;
padding: 0 1.25rem;
height: 2.5rem;
margin: 0.3125rem auto;
line-height: 2.5rem;
background: #1393fc;
color: rgb(255, 255, 255);
cursor: pointer;
}
}
}
.btm-btns {
width: 100%;
height: 5%;
background: #fff;
display: flex;
justify-content: space-between;
.left {
width: 90%;
display: flex;
justify-content: space-between;
> div {
height: 100%;
display: flex;
flex-direction: row;
align-content: center;
align-items: center;
justify-content: space-around;
background: #fff;
padding-left: 1.35rem;
> div {
cursor: pointer;
}
}
}
.right {
width: 10%;
}
}
}
.hello-ezuikit-js {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
overflow: hidden;
justify-content: space-between;
align-content: space-between;
background: #f5f5f5;
}
.width {
width: 100%;
height: 100%;
}
.width2 {
width: 49.5%;
height: 49%;
}
.width3 {
width: 33%;
height: 32.6%;
}
.width4 {
width: 25%;
height: 25%;
}
.video-active {
// border: 0.125rem solid rgb(255, 133, 62) !important;
}
.rect {
width: 1.625rem;
height: 1.625rem;
}
.video-cover {
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
color: rgb(153, 0, 0);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 5;
border-top: 0.0313rem solid #fff;
border-right: 0.0313rem solid #fff;
}
:deep(.el-dialog__wrapper) {
display: flex;
justify-content: center;
align-items: center;
}
:deep(.el-dialog__header) {
background: #efefef;
}
:deep(.el-dialog) {
width: 36rem;
}
:deep(.el-dialog__body) {
padding-top: 3.75rem;
display: flex;
justify-content: center;
}
:deep(.el-form) {
width: 28.125rem;
}
:deep(.el-form-item__label) {
width: 6.875rem !important;
}
:deep(.el-input) {
width: 20rem;
}
.tabs {
width: 100%;
height: 2.4375rem;
display: flex;
position: absolute;
top: 3.375rem;
left: 0;
border-top: 1px solid #f5f5f5;
.tab-item {
width: 50%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.tab-active {
background: #f5f5f5;
color: #fff;
}
}
.wheel {
position: relative;
width: 9.375rem;
height: 9.375rem;
border-radius: 50%;
background: rgb(77, 77, 77);
.camera {
position: absolute;
left: 3.75rem;
top: 3.75rem;
z-index: 5;
width: 1.875rem;
height: 1.875rem;
text-align: center;
line-height: 1.875rem;
font-size: 1.25rem;
color: #fff;
cursor: pointer;
}
.top {
height: 33.3%;
display: flex;
justify-content: center;
align-items: center;
}
.center {
height: 33.3%;
display: flex;
justify-content: space-between;
align-items: center;
.center-left,
.center-right {
width: 33.3%;
display: flex;
justify-content: center;
}
}
.bottom {
height: 33.3%;
display: flex;
justify-content: center;
align-items: center;
}
.triangle {
width: 0;
height: 0;
border: 0.625rem solid transparent;
cursor: pointer;
}
.triangle-top {
border-bottom: 0.9375rem solid #fff;
}
.triangle-bottom {
border-top: 0.9375rem solid #fff;
}
.triangle-left {
border-right: 0.9375rem solid #fff;
}
.triangle-right {
border-left: 0.9375rem solid #fff;
}
}
.bg-black {
display: flex;
justify-content: center;
align-items: center;
background: #000;
color: rgb(151, 0, 0);
font-size: 12px;
}
:deep(.el-button) {
background: rgb(77, 77, 77);
border-color: rgb(77, 77, 77);
}
:deep(.el-button.right-btn) {
width: 11.25rem;
margin: 0 auto 0.625rem;
}
}
</style>