智感、智库-含视频组件的增加乐橙视频,且根据组件的需求修改增加功能
parent
f223377628
commit
5a09a108d6
|
|
@ -15,7 +15,12 @@
|
|||
{
|
||||
"title":"费县马庄镇陈家鱼后村南斜坡后村",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"可落",
|
||||
"videourl": "8H03AA1PAG8D9BF",
|
||||
"manufacturer": "乐橙"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -127,8 +127,26 @@
|
|||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
src="@/assets/images/chart/zhichu/component/SheXiangTouModal_Image.png"
|
||||
/>
|
||||
<PlayVideo
|
||||
v-if="!isEdit && videoItem.videourl && !videoItem.manufacturer"
|
||||
<MonitorHK
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '海康'"
|
||||
:index="index + '-' + videoIndex"
|
||||
:serialNumberValue="videoItem.videourl"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
<MonitorLC
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '乐橙'"
|
||||
:deviceId="videoItem.videourl"
|
||||
:channelId="0"
|
||||
:index="index + '-' + videoIndex"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:videoMuted="option.dataStyle.videoMuted"
|
||||
/>
|
||||
<MonitorTX
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '腾讯'"
|
||||
:videourl="videoItem.videourl"
|
||||
:index="index + '-' + videoIndex"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
|
|
@ -138,14 +156,6 @@
|
|||
:videoMuted="option.dataStyle.videoMuted"
|
||||
:videoFit="option.dataStyle.videoFit"
|
||||
/>
|
||||
<MulHKmonitor
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '海康'"
|
||||
:index="index + '-' + videoIndex"
|
||||
:serialNumberValue="videoItem.videourl"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 单个 -->
|
||||
|
|
@ -161,8 +171,26 @@
|
|||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
src="@/assets/images/chart/zhichu/component/SheXiangTouModal_Image.png"
|
||||
/>
|
||||
<PlayVideo
|
||||
v-if="!isEdit && item.videos.videourl && !item.videos.manufacturer"
|
||||
<MonitorHK
|
||||
v-if="!isEdit && item.videos.videourl && item.videos.manufacturer == '海康'"
|
||||
:index="index + '-' + videoIndex"
|
||||
:serialNumberValue="item.videos.videourl"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
<MonitorLC
|
||||
v-if="!isEdit && item.videos.videourl && item.videos.manufacturer == '乐橙'"
|
||||
:deviceId="item.videos.videourl"
|
||||
:channelId="0"
|
||||
:index="index"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:videoMuted="option.dataStyle.videoMuted"
|
||||
/>
|
||||
<MonitorTX
|
||||
v-if="!isEdit && item.videos.videourl && item.videos.manufacturer == '腾讯'"
|
||||
:videourl="item.videos.videourl"
|
||||
:index="index + '-0'"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
|
|
@ -172,14 +200,6 @@
|
|||
:videoMuted="option.dataStyle.videoMuted"
|
||||
:videoFit="option.dataStyle.videoFit"
|
||||
/>
|
||||
<MulHKmonitor
|
||||
v-if="!isEdit && item.videos.videourl && item.videos.manufacturer == '海康'"
|
||||
:index="index + '-' + videoIndex"
|
||||
:serialNumberValue="item.videos.videourl"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -198,7 +218,7 @@
|
|||
import { replaceSqlParams } from '@/utils/sqlHandler';
|
||||
import Title from './svg/title.vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { MulHKmonitor, PlayVideo } from './video/index';
|
||||
import { MonitorHK, MonitorLC, MonitorTX } from './video/index';
|
||||
|
||||
const props = defineProps({
|
||||
chartConfig: {
|
||||
|
|
@ -311,7 +331,7 @@
|
|||
|
||||
.timeLineVideoDivTitle {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
z-index: 100;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
font-size: v-bind('`${option.dataStyle.videoTitleFontSize}px`');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import MulHKmonitor from './mulHKmonitor.vue';
|
||||
import PlayVideo from './playVideo.vue';
|
||||
import MonitorHK from './monitorHK.vue';
|
||||
import MonitorLC from './monitorLC.vue';
|
||||
import MonitorTX from './monitorTX.vue';
|
||||
|
||||
export {
|
||||
MulHKmonitor,
|
||||
PlayVideo,
|
||||
MonitorHK,
|
||||
MonitorLC,
|
||||
MonitorTX,
|
||||
};
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<div class="box-container">
|
||||
<div :id="'root' + props.index + props.timestamp"></div>
|
||||
</div>
|
||||
<div class="box-controls">
|
||||
<div class="left-controls">
|
||||
<div>
|
||||
<n-button quaternary @click="playOrPauseClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Pause
|
||||
v-if="control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<CaretForward
|
||||
v-if="!control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
<div>
|
||||
<n-button quaternary @click="volumeClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<VolumeHigh
|
||||
v-if="!control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<VolumeMute
|
||||
v-if="control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-controls">
|
||||
<n-button quaternary @click="fullScreenClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ExpandOutlined
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, watch, ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { ExpandOutlined } from '@ant-design/icons-vue';
|
||||
import { Pause, CaretForward, VolumeHigh, VolumeMute } from '@vicons/ionicons5';
|
||||
|
||||
let BASE_URL = 'http://111.17.207.220:9001/api';
|
||||
|
||||
const props = defineProps([
|
||||
'deviceId',
|
||||
'channelId',
|
||||
'index',
|
||||
'width',
|
||||
'height',
|
||||
'timestamp',
|
||||
'videoMuted',
|
||||
]);
|
||||
let clPlayer: any = null;
|
||||
|
||||
// 开始播放/暂停播放
|
||||
const control_playOrPause = ref(true);
|
||||
// 音量:true为静音
|
||||
const control_volume = ref(true);
|
||||
// 全屏
|
||||
const control_fullScreen = ref(false);
|
||||
|
||||
// 开始播放/暂停播放方法
|
||||
function playOrPauseClick() {
|
||||
control_playOrPause.value = !control_playOrPause.value;
|
||||
if (control_playOrPause.value) {
|
||||
clPlayer.play();
|
||||
} else {
|
||||
clPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// 音量
|
||||
function volumeClick() {
|
||||
control_volume.value = !control_volume.value;
|
||||
if (control_volume.value) {
|
||||
clPlayer.volume(0);
|
||||
} else {
|
||||
clPlayer.volume(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 全屏
|
||||
function fullScreenClick() {
|
||||
clPlayer.fullScreen();
|
||||
}
|
||||
|
||||
// 获取kitToken
|
||||
function getKitToken(deviceId, channelId) {
|
||||
axios({
|
||||
method: 'post',
|
||||
url: BASE_URL + '/Camera/getKitToken?deviceId=' + deviceId + '&channelId=0' + '&type=0',
|
||||
}).then((res) => {
|
||||
let kitToken = res.data.result.data.kitToken;
|
||||
loadMonitorVideo(deviceId, kitToken, channelId);
|
||||
});
|
||||
}
|
||||
|
||||
// 开始
|
||||
function loadMonitorVideo(deviceId, kitToken, channelId) {
|
||||
// 结束上一个
|
||||
closeMonitorVideo();
|
||||
|
||||
clPlayer = new imouPlayer({
|
||||
id: 'root' + props.index + props.timestamp,
|
||||
width: props.width,
|
||||
height: props.height - 25,
|
||||
deviceId: deviceId,
|
||||
token: kitToken,
|
||||
channelId: channelId,
|
||||
type: 1,
|
||||
streamId: 0,
|
||||
recordType: 'cloud',
|
||||
code: '',
|
||||
controls: true,
|
||||
});
|
||||
clPlayer.volume(0);
|
||||
}
|
||||
|
||||
// 结束
|
||||
function closeMonitorVideo() {
|
||||
if (clPlayer != null) {
|
||||
clPlayer.destroy();
|
||||
clPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.deviceId,
|
||||
() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
control_volume.value = props.videoMuted;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
closeMonitorVideo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.box {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height}px`');
|
||||
z-index: 99;
|
||||
}
|
||||
.box-container {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height-25}px`');
|
||||
}
|
||||
|
||||
.box-controls {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
background: #000000;
|
||||
height: 25px;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.left-controls {
|
||||
display: flex;
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.right-controls {
|
||||
justify-self: end;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<n-select
|
||||
v-model:value="optionData.dataStyle.serialNumberValue"
|
||||
:options="option.dataset"
|
||||
label-field="name"
|
||||
label-field="title"
|
||||
value-field="serialNumber"
|
||||
placeholder="请选择默认视频"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -2,73 +2,79 @@
|
|||
"source": [
|
||||
{
|
||||
"id": 418015298064389,
|
||||
"name": "XZD148青山裕南山",
|
||||
"title": "XZD148青山裕南山",
|
||||
"serialNumber": "13b23c9b878143bc99269898964af54f",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015349661701,
|
||||
"name": "XZD153狼窝沟西南",
|
||||
"title": "XZD153狼窝沟西南",
|
||||
"serialNumber": "74b95e6575d741489b9a9061bb646467",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015349899269,
|
||||
"name": "XZD152青山裕水库东",
|
||||
"title": "XZD152青山裕水库东",
|
||||
"serialNumber": "ecdb49050c57452dbae7ec6f03e82667",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015350452229,
|
||||
"name": "XZD147大古台南山",
|
||||
"title": "XZD147大古台南山",
|
||||
"serialNumber": "edd84ccac34441c48c6a7bf030f9c13f",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015351681029,
|
||||
"name": "XZD151青山裕水库西",
|
||||
"title": "XZD151青山裕水库西",
|
||||
"serialNumber": "c10f9faea87d4f659e2bc01de24e29a9",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015351836677,
|
||||
"name": "XZD149青山裕北山",
|
||||
"title": "XZD149青山裕北山",
|
||||
"serialNumber": "909e98d192f649fea4c5269f5f7832e1",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015351025669,
|
||||
"name": "XZD150青山裕山里人家西北",
|
||||
"title": "XZD150青山裕山里人家西北",
|
||||
"serialNumber": "b56f09f8c64249379e42481c7b173dce",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 490483936976901,
|
||||
"name": "XZD155突围路广场",
|
||||
"title": "XZD155突围路广场",
|
||||
"serialNumber": "a8010ac49baa4b81a569ba24dc95a4e7",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 490483936976911,
|
||||
"name": "playerVideo",
|
||||
"title": "大青山林场机库摄像头",
|
||||
"serialNumber": "http://111.36.45.20:18000/flv/hls/H-fc4c09b5a3451bb9.flv",
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"id": 490483936976911,
|
||||
"title": "玉皇宫机库摄像头",
|
||||
"serialNumber": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"id": 490483936976912,
|
||||
"name": "店子分区",
|
||||
"title": "店子分区",
|
||||
"serialNumber": "8H03AA1PAGDC8C3",
|
||||
"manufacturer": "乐橙"
|
||||
},
|
||||
{
|
||||
"id": 490483936976913,
|
||||
"name": "白马关通天沟",
|
||||
"title": "白马关通天沟",
|
||||
"serialNumber": "8H03AA1PAG97234",
|
||||
"manufacturer": "乐橙"
|
||||
},
|
||||
{
|
||||
"id": 490483936976914,
|
||||
"name": "后白崖",
|
||||
"title": "后白崖",
|
||||
"serialNumber": "8H03AA1PAGF203B",
|
||||
"manufacturer": "乐橙"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<template #trigger>
|
||||
<n-button>
|
||||
<span
|
||||
calss="modalTitle_name"
|
||||
calss="modalTitle_title"
|
||||
:style="{
|
||||
color: option.dataStyle.titleFontColor,
|
||||
fontSize: option.dataStyle.titleFontSize + 'px',
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
<n-select
|
||||
v-model:value="option.dataStyle.serialNumberValue"
|
||||
:options="option.dataset"
|
||||
label-field="name"
|
||||
label-field="title"
|
||||
value-field="serialNumber"
|
||||
placeholder="请选择查看的视频"
|
||||
/>
|
||||
|
|
@ -49,10 +49,11 @@
|
|||
:width="`${w - 2 * option.dataStyle.padding - 2 * option.dataStyle.borderWidth}`"
|
||||
:height="`${h - option.dataStyle.modalTitleHeight - 2 * option.dataStyle.padding - 2 * option.dataStyle.borderWidth}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:videoMuted="option.dataStyle.videoMuted"
|
||||
/>
|
||||
<PlayVideo
|
||||
ref="PlayVideoRef"
|
||||
v-if="!isEdit && !manufacturer"
|
||||
<MonitorTX
|
||||
ref="MonitorTXRef"
|
||||
v-if="!isEdit && manufacturer == '腾讯'"
|
||||
:serialNumberValue="option.dataStyle.serialNumberValue"
|
||||
:width="`${w - 2 * option.dataStyle.padding - 2 * option.dataStyle.borderWidth}`"
|
||||
:height="`${h - option.dataStyle.modalTitleHeight - 2 * option.dataStyle.padding - 2 * option.dataStyle.borderWidth}`"
|
||||
|
|
@ -84,7 +85,7 @@
|
|||
import { EventBus } from '@/utils/eventBus';
|
||||
import { replaceSqlParams } from '@/utils/sqlHandler';
|
||||
import dayjs from 'dayjs';
|
||||
import { MonitorHK, MonitorLC, PlayVideo } from './video/index';
|
||||
import { MonitorHK, MonitorLC, MonitorTX } from './video/index';
|
||||
|
||||
const props = defineProps({
|
||||
chartConfig: {
|
||||
|
|
@ -107,8 +108,8 @@
|
|||
const MonitorHKRef = ref();
|
||||
// 乐橙
|
||||
const MonitorLCRef = ref();
|
||||
// 其他
|
||||
const PlayVideoRef = ref();
|
||||
// 腾讯
|
||||
const MonitorTXRef = ref();
|
||||
|
||||
// 是否是编辑状态
|
||||
const isEdit = window.location.href.includes('/chart/home/');
|
||||
|
|
@ -136,7 +137,7 @@
|
|||
() => option.dataStyle.serialNumberValue,
|
||||
(newValue) => {
|
||||
let data = getDataBySerialNumberValue(newValue);
|
||||
titleName.value = data.name;
|
||||
titleName.value = data.title;
|
||||
manufacturer.value = data.manufacturer;
|
||||
},
|
||||
);
|
||||
|
|
@ -157,7 +158,7 @@
|
|||
}
|
||||
|
||||
let data = getDataBySerialNumberValue(option.dataStyle.serialNumberValue);
|
||||
titleName.value = data.name;
|
||||
titleName.value = data.title;
|
||||
manufacturer.value = data.manufacturer;
|
||||
|
||||
// 组件通信
|
||||
|
|
@ -208,7 +209,7 @@
|
|||
align-items: center;
|
||||
justify-content: left;
|
||||
|
||||
.modalTitle_name {
|
||||
.modalTitle_title {
|
||||
padding-left: 10px;
|
||||
width: 100%;
|
||||
height: v-bind('`${option.dataStyle.modalTitleHeight}px`');
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import MonitorHK from './monitorHK.vue';
|
||||
import MonitorLC from './monitorLC.vue';
|
||||
import PlayVideo from './playVideo.vue';
|
||||
import MonitorTX from './monitorTX.vue';
|
||||
|
||||
export {
|
||||
MonitorHK,
|
||||
MonitorLC,
|
||||
PlayVideo,
|
||||
MonitorTX,
|
||||
};
|
||||
|
|
@ -132,24 +132,9 @@
|
|||
}),
|
||||
})
|
||||
.then(function (oData) {
|
||||
// 实际宽高
|
||||
let width = props.width;
|
||||
let height = props.height;
|
||||
const divElement = document.getElementById('camera-box');
|
||||
if (divElement) {
|
||||
const rect = divElement.getBoundingClientRect();
|
||||
const rectWidth = rect.width;
|
||||
const rectHeight = rect.height;
|
||||
if (rectWidth < width) {
|
||||
width = rectWidth;
|
||||
}
|
||||
if (rectHeight < height) {
|
||||
height = rectHeight;
|
||||
}
|
||||
}
|
||||
oWebControl.JS_Resize(width, height); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
|
||||
// 重定大小
|
||||
reSizeVideo();
|
||||
});
|
||||
|
||||
// 开始预览多个视频
|
||||
oWebControl.JS_RequestInterface({
|
||||
funcName: 'startPreview',
|
||||
|
|
@ -176,6 +161,26 @@
|
|||
}
|
||||
}
|
||||
|
||||
// 重定大小
|
||||
function reSizeVideo() {
|
||||
// 实际宽高
|
||||
let width = props.width;
|
||||
let height = props.height;
|
||||
const divElement = document.getElementById('camera-box');
|
||||
if (divElement) {
|
||||
const rect = divElement.getBoundingClientRect();
|
||||
const rectWidth = rect.width;
|
||||
const rectHeight = rect.height;
|
||||
if (rectWidth < width) {
|
||||
width = rectWidth;
|
||||
}
|
||||
if (rectHeight < height) {
|
||||
height = rectHeight;
|
||||
}
|
||||
}
|
||||
oWebControl.JS_Resize(width, height); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.serialNumberValue,
|
||||
() => {
|
||||
|
|
@ -212,10 +217,28 @@
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 启动视频窗口
|
||||
initPlugin();
|
||||
// 添加监听滚动事件
|
||||
const elements = document.querySelectorAll('.ZhiGan_ModalVideo');
|
||||
if (elements.length > 0) {
|
||||
// 遍历每个元素并绑定 scroll 事件
|
||||
elements.forEach((element) => {
|
||||
element.addEventListener('scroll', reSizeVideo);
|
||||
});
|
||||
}
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 销毁视频窗口
|
||||
closeHkVideo();
|
||||
// 移除监听滚动事件
|
||||
const elements = document.querySelectorAll('.ZhiGan_ModalVideo');
|
||||
if (elements.length > 0) {
|
||||
// 遍历每个元素并绑定 scroll 事件
|
||||
elements.forEach((element) => {
|
||||
element.removeEventListener('scroll', reSizeVideo);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
|
|
|
|||
|
|
@ -1,92 +1,66 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<div class="box-container">
|
||||
<div id="root"></div>
|
||||
<div :id="'root' + props.timestamp"></div>
|
||||
</div>
|
||||
<div class="box-controls">
|
||||
<div>
|
||||
<n-button quaternary @click="playOrPauseClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<svg
|
||||
v-if="control_playOrPause"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 512 512"
|
||||
enable-background="new 0 0 512 512"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<path d="M96,448h106.7V64H96V448z M309.3,64v384H416V64H309.3z"></path>
|
||||
</svg>
|
||||
<svg
|
||||
v-if="!control_playOrPause"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 512 512"
|
||||
enable-background="new 0 0 512 512"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<path d="M96,52v408l320-204L96,52z"></path>
|
||||
</svg>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<div class="left-controls">
|
||||
<div>
|
||||
<n-button quaternary @click="playOrPauseClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Pause
|
||||
v-if="control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<CaretForward
|
||||
v-if="!control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
<div>
|
||||
<n-button quaternary @click="volumeClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<VolumeHigh
|
||||
v-if="!control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<VolumeMute
|
||||
v-if="control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<n-button quaternary @click="volumeClick">
|
||||
<div class="right-controls">
|
||||
<n-button quaternary @click="fullScreenClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<svg
|
||||
v-if="control_volume"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 512 512"
|
||||
enable-background="new 0 0 512 512"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<path
|
||||
d="M64,192v128h85.334L256,431.543V80.458L149.334,192H64z M352,256c0-38.399-21.333-72.407-53.333-88.863v176.636
|
||||
C330.667,328.408,352,294.4,352,256z M298.667,64v44.978C360.531,127.632,405.334,186.882,405.334,256
|
||||
c0,69.119-44.803,128.369-106.667,147.022V448C384,428.254,448,349.257,448,256C448,162.744,384,83.746,298.667,64z"
|
||||
></path>
|
||||
</svg>
|
||||
<svg
|
||||
v-if="!control_volume"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 512 512"
|
||||
enable-background="new 0 0 512 512"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
d="M405.5,256c0,22.717-4.883,44.362-13.603,63.855l31.88,31.88C439.283,323.33,448,290.653,448,256
|
||||
c0-93.256-64-172.254-149-192v44.978C361,127.632,405.5,186.882,405.5,256z"
|
||||
></path>
|
||||
<polygon points="256,80.458 204.979,132.938 256,183.957 "></polygon>
|
||||
<path
|
||||
d="M420.842,396.885L91.116,67.157l-24,24l90.499,90.413l-8.28,10.43H64v128h85.334L256,431.543V280l94.915,94.686
|
||||
C335.795,387.443,318,397.213,299,403.022V448c31-7.172,58.996-22.163,82.315-42.809l39.61,39.693l24-24.043l-24.002-24.039
|
||||
L420.842,396.885z"
|
||||
></path>
|
||||
<path
|
||||
d="M352.188,256c0-38.399-21.188-72.407-53.188-88.863v59.82l50.801,50.801C351.355,270.739,352.188,263.454,352.188,256z"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
<ExpandOutlined
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
|
|
@ -97,18 +71,52 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, watch, ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { ExpandOutlined } from '@ant-design/icons-vue';
|
||||
import { Pause, CaretForward, VolumeHigh, VolumeMute } from '@vicons/ionicons5';
|
||||
|
||||
let BASE_URL = 'http://111.17.207.220:9001/api';
|
||||
|
||||
const props = defineProps(['deviceId', 'channelId', 'width', 'height', 'timestamp']);
|
||||
const props = defineProps([
|
||||
'deviceId',
|
||||
'channelId',
|
||||
'width',
|
||||
'height',
|
||||
'timestamp',
|
||||
'videoMuted',
|
||||
]);
|
||||
let clPlayer: any = null;
|
||||
|
||||
// 开始播放/暂停播放
|
||||
const control_playOrPause = ref(true);
|
||||
// 音量
|
||||
// 音量:true为静音
|
||||
const control_volume = ref(true);
|
||||
// 全屏
|
||||
const control_fullScreen = ref(true);
|
||||
const control_fullScreen = ref(false);
|
||||
|
||||
// 开始播放/暂停播放方法
|
||||
function playOrPauseClick() {
|
||||
control_playOrPause.value = !control_playOrPause.value;
|
||||
if (control_playOrPause.value) {
|
||||
clPlayer.play();
|
||||
} else {
|
||||
clPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// 音量
|
||||
function volumeClick() {
|
||||
control_volume.value = !control_volume.value;
|
||||
if (control_volume.value) {
|
||||
clPlayer.volume(0);
|
||||
} else {
|
||||
clPlayer.volume(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 全屏
|
||||
function fullScreenClick() {
|
||||
clPlayer.fullScreen();
|
||||
}
|
||||
|
||||
// 获取kitToken
|
||||
function getKitToken(deviceId, channelId) {
|
||||
|
|
@ -126,10 +134,10 @@
|
|||
// 结束上一个
|
||||
closeMonitorVideo();
|
||||
|
||||
clPlayer = new window.imouPlayer({
|
||||
id: 'root',
|
||||
clPlayer = new imouPlayer({
|
||||
id: 'root' + props.timestamp,
|
||||
width: props.width,
|
||||
height: props.height,
|
||||
height: props.height - 35,
|
||||
deviceId: deviceId,
|
||||
token: kitToken,
|
||||
channelId: channelId,
|
||||
|
|
@ -139,6 +147,7 @@
|
|||
code: '',
|
||||
controls: true,
|
||||
});
|
||||
clPlayer.volume(0);
|
||||
}
|
||||
|
||||
// 结束
|
||||
|
|
@ -158,6 +167,7 @@
|
|||
|
||||
onMounted(() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
control_volume.value = props.videoMuted;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
|
@ -170,22 +180,28 @@
|
|||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height}px`');
|
||||
z-index: 99;
|
||||
position: relative;
|
||||
}
|
||||
.box-container {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height}px`');
|
||||
height: v-bind('`${props.height-35}px`');
|
||||
}
|
||||
|
||||
.box-controls {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
display: inline-flex;
|
||||
background: #ffffff00;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
background: #000000;
|
||||
height: 35px;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
border: 1px solid red;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.left-controls {
|
||||
display: flex;
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.right-controls {
|
||||
justify-self: end;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,22 @@
|
|||
<template>
|
||||
<video
|
||||
:id="'ZhiGan_ModalVideo' + props.timestamp"
|
||||
class="TCPlayer-video-contaiiner"
|
||||
preload="auto"
|
||||
crossOrigin="anonymous"
|
||||
playsinline
|
||||
autoplay
|
||||
:loop="props.videoLoop"
|
||||
:muted="props.videoMuted"
|
||||
:width="props.width"
|
||||
:height="props.height"
|
||||
/>
|
||||
<div>
|
||||
<video
|
||||
:id="'ZhiGan_ModalVideo' + props.timestamp"
|
||||
class="TCPlayer-video-container"
|
||||
preload="auto"
|
||||
crossOrigin="anonymous"
|
||||
playsinline
|
||||
autoplay
|
||||
:loop="props.videoLoop"
|
||||
:muted="props.videoMuted"
|
||||
:style="{
|
||||
width: props.width + 'px',
|
||||
height: props.height + 'px',
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, ref, watch, nextTick } from 'vue';
|
||||
|
||||
|
|
@ -29,14 +34,14 @@
|
|||
let player: any = null;
|
||||
|
||||
function handlerPlayVideo() {
|
||||
setTimeout(function () {
|
||||
nextTick(() => {
|
||||
if (player) {
|
||||
player.src(props.serialNumberValue);
|
||||
} else {
|
||||
player = TCPlayer('ZhiGan_ModalVideo' + props.timestamp, {});
|
||||
player.src(props.serialNumberValue);
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
function closePlayerVideo() {
|
||||
|
|
@ -56,6 +61,7 @@
|
|||
onMounted(() => {
|
||||
handlerPlayVideo();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
closePlayerVideo();
|
||||
});
|
||||
|
|
@ -65,6 +71,7 @@
|
|||
closePlayerVideo,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
video {
|
||||
display: block;
|
||||
|
|
@ -68,10 +68,10 @@ export const option = {
|
|||
videoWidth: 956,
|
||||
videoHeight: 688,
|
||||
// 关闭按钮
|
||||
closeVideoIconColor: '#027734',
|
||||
closeVideoIconWidthAndHeight: 34,
|
||||
closeVideoIconColor: '#ffffff',
|
||||
closeVideoIconWidthAndHeight: 25,
|
||||
// 标题
|
||||
videoTitleFontSize: 16,
|
||||
videoTitleFontSize: 20,
|
||||
videoTitleFontColor: '#ffffff',
|
||||
|
||||
videoloop: false, // 视频-循环播放
|
||||
|
|
|
|||
|
|
@ -4,49 +4,41 @@
|
|||
"label": "费县林业防火监控列表",
|
||||
"value": [
|
||||
{
|
||||
"id": 418015298064389,
|
||||
"title": "XZD148青山裕南山",
|
||||
"videourl": "13b23c9b878143bc99269898964af54f",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015349661701,
|
||||
"title": "XZD153狼窝沟西南",
|
||||
"videourl": "74b95e6575d741489b9a9061bb646467",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015349899269,
|
||||
"title": "XZD152青山裕水库东",
|
||||
"videourl": "ecdb49050c57452dbae7ec6f03e82667",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015350452229,
|
||||
"title": "XZD147大古台南山",
|
||||
"videourl": "edd84ccac34441c48c6a7bf030f9c13f",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015351681029,
|
||||
"title": "XZD151青山裕水库西",
|
||||
"videourl": "c10f9faea87d4f659e2bc01de24e29a9",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015351836677,
|
||||
"title": "XZD149青山裕北山",
|
||||
"videourl": "909e98d192f649fea4c5269f5f7832e1",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 418015351025669,
|
||||
"title": "XZD150青山裕山里人家西北",
|
||||
"videourl": "b56f09f8c64249379e42481c7b173dce",
|
||||
"manufacturer": "海康"
|
||||
},
|
||||
{
|
||||
"id": 490483936976901,
|
||||
"title": "XZD155突围路广场",
|
||||
"videourl": "a8010ac49baa4b81a569ba24dc95a4e7",
|
||||
"manufacturer": "海康"
|
||||
|
|
@ -54,42 +46,47 @@
|
|||
{
|
||||
"title":"费县马庄镇陈家鱼后村南斜坡后村",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"费县东蒙镇天蒙景区二村东边南斜坡后村",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"费县东蒙镇沂蒙抽水蓄能业营地",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"费县薛庄镇火山后村南斜坡后村",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"费县冯庄镇陈家鱼后村南斜坡后村",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
},
|
||||
{
|
||||
"title":"费县东蒙镇天蒙景区二村东边南斜坡后村",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"费县冻蒙镇沂蒙抽水蓄能业营地",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"费县薛庄镇火山后村南斜坡后村",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"title": "店子分区",
|
||||
"videourl": "8H03AA1PAGDC8C3",
|
||||
"manufacturer": "乐橙"
|
||||
},
|
||||
{
|
||||
"title": "白马关通天沟",
|
||||
"videourl": "8H03AA1PAG97234",
|
||||
"manufacturer": "乐橙"
|
||||
},
|
||||
{
|
||||
"title": "后白崖",
|
||||
"videourl": "8H03AA1PAGF203B",
|
||||
"manufacturer": "乐橙"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
v-for="(videoItem, videoIndex) in option.videoList"
|
||||
:key="videoIndex"
|
||||
>
|
||||
<div class="rightVideoItemTitle" v-if="isEdit || videoItem.title">
|
||||
<div class="rightVideoItemTitle" v-if="isEdit">
|
||||
<span
|
||||
:style="{
|
||||
color: option.dataStyle.videoTitleFontColor,
|
||||
|
|
@ -84,15 +84,18 @@
|
|||
{{ videoItem.title ? videoItem.title : '视频标题' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="rightVideoItemCloseButton" v-if="isEdit || videoItem.videourl">
|
||||
<CloseVideoIcon :dataStyle="option.dataStyle" @click="closeThisVideo(videoIndex)" />
|
||||
<div class="rightVideoItemCloseButton" v-if="isEdit">
|
||||
<Close
|
||||
:style="{
|
||||
width: option.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
height: option.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
fontSize: option.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
color: option.dataStyle.closeVideoIconColor,
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:class="changeThisNum == videoIndex ? 'rightVideoItemDiv2' : 'rightVideoItemDiv'"
|
||||
@click="changeThisVideo(videoIndex)"
|
||||
>
|
||||
<!-- 无视频url的情况 -->
|
||||
<div :class="changeThisNum == videoIndex ? 'rightVideoItemDiv2' : 'rightVideoItemDiv'">
|
||||
<img
|
||||
v-if="isEdit || !videoItem.videourl"
|
||||
:width="videoWidthNoPadding"
|
||||
|
|
@ -100,24 +103,42 @@
|
|||
src="@/assets/images/chart/zhichu/component/SheXiangTouModal_Image.png"
|
||||
preview-disabled
|
||||
/>
|
||||
<MulHKmonitor
|
||||
<MonitorHK
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '海康'"
|
||||
:index="videoIndex"
|
||||
:serialNumberValue="videoItem.videourl"
|
||||
:width="videoWidthNoPadding"
|
||||
:height="videoHeightNoPadding"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:dataStyle="option.dataStyle"
|
||||
@changeThisVideo="changeThisVideo"
|
||||
@closeThisVideo="closeThisVideo"
|
||||
/>
|
||||
<PlayVideo
|
||||
v-if="!isEdit && videoItem.videourl && !videoItem.manufacturer"
|
||||
<MonitorLC
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '乐橙'"
|
||||
:title="videoItem.title"
|
||||
:deviceId="videoItem.videourl"
|
||||
:channelId="0"
|
||||
:index="videoIndex"
|
||||
:width="videoWidthNoPadding"
|
||||
:height="videoHeightNoPadding"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:videoMuted="option.dataStyle.videoMuted"
|
||||
:dataStyle="option.dataStyle"
|
||||
@changeThisVideo="changeThisVideo"
|
||||
@closeThisVideo="closeThisVideo"
|
||||
/>
|
||||
<MonitorTX
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '腾讯'"
|
||||
:title="videoItem.title"
|
||||
:videourl="videoItem.videourl"
|
||||
:index="videoIndex"
|
||||
:width="videoWidthNoPadding"
|
||||
:height="videoHeightNoPadding"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:videoLoop="option.dataStyle.videoLoop"
|
||||
:videoMuted="option.dataStyle.videoMuted"
|
||||
:videoFit="option.dataStyle.videoFit"
|
||||
:dataStyle="option.dataStyle"
|
||||
@changeThisVideo="changeThisVideo"
|
||||
@closeThisVideo="closeThisVideo"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -146,15 +167,15 @@
|
|||
import dayjs from 'dayjs';
|
||||
import { EventBus } from '@/utils/eventBus';
|
||||
import { replaceSqlParams } from '@/utils/sqlHandler';
|
||||
import { Close } from '@vicons/ionicons5';
|
||||
import {
|
||||
CloseButton,
|
||||
TypeButton,
|
||||
LeftTitleIcon1,
|
||||
LeftTitleIcon2,
|
||||
ListVideoNameIcon,
|
||||
CloseVideoIcon,
|
||||
} from './svg/index';
|
||||
import { MulHKmonitor, PlayVideo } from './video/index';
|
||||
import { MonitorHK, MonitorLC, MonitorTX } from './video/index';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
|
|
@ -639,8 +660,8 @@
|
|||
.rightVideoItemDiv2 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: v-bind('`${17 / Math.sqrt(parseInt(option.dataStyle.nowType))}px`');
|
||||
border: v-bind('`${3 / Math.sqrt(parseInt(option.dataStyle.nowType))}px`') solid #0fab3f;
|
||||
padding: v-bind('`${14 / Math.sqrt(parseInt(option.dataStyle.nowType))}px`');
|
||||
border: v-bind('`${6 / Math.sqrt(parseInt(option.dataStyle.nowType))}px`') solid #0fab3f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import MulHKmonitor from './mulHKmonitor.vue';
|
||||
import PlayVideo from './playVideo.vue';
|
||||
import MonitorHK from './monitorHK.vue';
|
||||
import MonitorLC from './monitorLC.vue';
|
||||
import MonitorTX from './monitorTX.vue';
|
||||
|
||||
export {
|
||||
MulHKmonitor,
|
||||
PlayVideo,
|
||||
MonitorHK,
|
||||
MonitorLC,
|
||||
MonitorTX,
|
||||
};
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
import { JSEncrypt } from 'jsencrypt';
|
||||
|
||||
const props = defineProps(['serialNumberValue', 'index', 'width', 'height', 'timestamp']);
|
||||
const emit = defineEmits(['changeThisVideo', 'closeThisVideo']);
|
||||
|
||||
//声明公用变量
|
||||
let initCount = 0;
|
||||
|
|
@ -110,7 +111,7 @@
|
|||
let encryptedFields = 'secret'; //加密字段,默认加密领域为secret
|
||||
let showToolbar = 1; //是否显示工具栏,0-不显示,非0-显示
|
||||
let showSmart = 1; //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示
|
||||
let buttonIDs = '0,16'; //自定义工具条按钮
|
||||
let buttonIDs = '0'; //自定义工具条按钮
|
||||
|
||||
oWebControl
|
||||
.JS_RequestInterface({
|
||||
|
|
@ -134,6 +135,26 @@
|
|||
.then(function (oData) {
|
||||
// 重定大小
|
||||
reSizeVideo();
|
||||
// 单击-选择+反选择
|
||||
oWebControl.JS_SetWindowControlCallback({
|
||||
cbIntegrationCallBack: function (oData) {
|
||||
// oData 是封装的视频 web 插件回调消息的消息体
|
||||
if (oData.responseMsg.type == '1' && oData.responseMsg.msg.result == '256') {
|
||||
// 选择这个视频
|
||||
emit('changeThisVideo', props.index);
|
||||
}
|
||||
// // oData 是封装的视频 web 插件回调消息的消息体
|
||||
// if (oData.responseMsg.type == '1' && oData.responseMsg.msg.result == '512') {
|
||||
// // 按下关闭按钮
|
||||
// emit('closeThisVideo', props.index);
|
||||
// }
|
||||
// oData 是封装的视频 web 插件回调消息的消息体
|
||||
if (oData.responseMsg.type == '2' && oData.responseMsg.msg.result == '816') {
|
||||
// 按下全部关闭按钮
|
||||
emit('closeThisVideo', props.index);
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 开始预览多个视频
|
||||
|
|
@ -227,10 +248,30 @@
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 启动视频窗口
|
||||
initPlugin();
|
||||
|
||||
// 添加监听滚动事件
|
||||
const elements = document.querySelectorAll('.ZhiGan_SheXiangTouModal');
|
||||
if (elements.length > 0) {
|
||||
// 遍历每个元素并绑定 scroll 事件
|
||||
elements.forEach((element) => {
|
||||
element.addEventListener('scroll', reSizeVideo);
|
||||
});
|
||||
}
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 销毁视频窗口
|
||||
closeHkVideo();
|
||||
|
||||
// 移除监听滚动事件
|
||||
const elements = document.querySelectorAll('.ZhiGan_SheXiangTouModal');
|
||||
if (elements.length > 0) {
|
||||
// 遍历每个元素并绑定 scroll 事件
|
||||
elements.forEach((element) => {
|
||||
element.removeEventListener('scroll', reSizeVideo);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<!-- 标题 -->
|
||||
<div class="box-title">
|
||||
<div class="left-controls">
|
||||
<span
|
||||
:style="{
|
||||
fontSize: props.dataStyle.videoTitleFontSize + 'px',
|
||||
color: props.dataStyle.videoTitleFontColor,
|
||||
marginLeft: '10px',
|
||||
}"
|
||||
>
|
||||
{{ props.title }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="right-controls">
|
||||
<n-button quaternary @click="closeVideo">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Close
|
||||
:style="{
|
||||
width: props.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
height: props.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
fontSize: props.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
color: props.dataStyle.closeVideoIconColor,
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 视频 -->
|
||||
<div class="box-container">
|
||||
<div :id="'root' + props.index + props.timestamp" @click="clickThisVideo" />
|
||||
</div>
|
||||
<!-- 控制栏 -->
|
||||
<div class="box-controls">
|
||||
<div class="left-controls">
|
||||
<div>
|
||||
<n-button quaternary @click="playOrPauseClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Pause
|
||||
v-if="control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<CaretForward
|
||||
v-if="!control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
<div>
|
||||
<n-button quaternary @click="volumeClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<VolumeHigh
|
||||
v-if="control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<VolumeMute
|
||||
v-if="!control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-controls">
|
||||
<n-button quaternary @click="fullScreenClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ExpandOutlined
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, watch, ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { ExpandOutlined } from '@ant-design/icons-vue';
|
||||
import { Close, Pause, CaretForward, VolumeHigh, VolumeMute } from '@vicons/ionicons5';
|
||||
|
||||
let BASE_URL = 'http://111.17.207.220:9001/api';
|
||||
|
||||
const props = defineProps([
|
||||
'title',
|
||||
'deviceId',
|
||||
'channelId',
|
||||
'index',
|
||||
'width',
|
||||
'height',
|
||||
'timestamp',
|
||||
'dataStyle',
|
||||
]);
|
||||
const emit = defineEmits(['changeThisVideo', 'closeThisVideo']);
|
||||
|
||||
let clPlayer: any = null;
|
||||
|
||||
// 点击视频内容
|
||||
function clickThisVideo() {
|
||||
emit('changeThisVideo', props.index);
|
||||
}
|
||||
|
||||
// 关闭此视频;
|
||||
function closeVideo() {
|
||||
closeMonitorVideo();
|
||||
emit('closeThisVideo', props.index);
|
||||
}
|
||||
|
||||
// 开始播放/暂停播放
|
||||
const control_playOrPause = ref(true);
|
||||
// 音量:true为静音
|
||||
const control_volume = ref(true);
|
||||
|
||||
// 开始播放/暂停播放方法
|
||||
function playOrPauseClick() {
|
||||
control_playOrPause.value = !control_playOrPause.value;
|
||||
if (control_playOrPause.value) {
|
||||
clPlayer.play();
|
||||
} else {
|
||||
clPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// 音量
|
||||
function volumeClick() {
|
||||
control_volume.value = !control_volume.value;
|
||||
if (control_volume.value) {
|
||||
clPlayer.volume(0);
|
||||
} else {
|
||||
clPlayer.volume(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 全屏
|
||||
function fullScreenClick() {
|
||||
clPlayer.fullScreen();
|
||||
}
|
||||
|
||||
// 获取kitToken
|
||||
let kitToken = null;
|
||||
function getKitToken(deviceId, channelId) {
|
||||
axios({
|
||||
method: 'post',
|
||||
url: BASE_URL + '/Camera/getKitToken?deviceId=' + deviceId + '&channelId=0' + '&type=0',
|
||||
}).then((res) => {
|
||||
kitToken = res.data.result.data.kitToken;
|
||||
loadMonitorVideo(deviceId, kitToken, channelId);
|
||||
});
|
||||
}
|
||||
|
||||
// 开始
|
||||
function loadMonitorVideo(deviceId, kitToken, channelId) {
|
||||
// 结束上一个
|
||||
closeMonitorVideo();
|
||||
|
||||
clPlayer = new imouPlayer({
|
||||
id: 'root' + props.index + props.timestamp,
|
||||
width: props.width,
|
||||
height: props.height - 70,
|
||||
deviceId: deviceId,
|
||||
token: kitToken,
|
||||
channelId: channelId,
|
||||
type: 1,
|
||||
streamId: 0,
|
||||
recordType: 'cloud',
|
||||
code: '',
|
||||
controls: true,
|
||||
});
|
||||
clPlayer.volume(0);
|
||||
}
|
||||
|
||||
// 结束
|
||||
function closeMonitorVideo() {
|
||||
if (clPlayer != null) {
|
||||
clPlayer.destroy();
|
||||
clPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 检测视频id
|
||||
watch(
|
||||
() => props.deviceId,
|
||||
() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
},
|
||||
);
|
||||
// 检测宽度
|
||||
watch(
|
||||
() => props.width,
|
||||
() => {
|
||||
clPlayer = new imouPlayer({
|
||||
id: 'root' + props.index + props.timestamp,
|
||||
width: props.width,
|
||||
height: props.height - 70,
|
||||
deviceId: props.deviceId,
|
||||
token: kitToken,
|
||||
channelId: props.channelId,
|
||||
type: 1,
|
||||
streamId: 0,
|
||||
recordType: 'cloud',
|
||||
code: '',
|
||||
controls: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
control_volume.value = props.dataStyle.videoMuted;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
closeMonitorVideo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.box {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height}px`');
|
||||
z-index: 12;
|
||||
}
|
||||
|
||||
.box-title {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
background: #000000;
|
||||
height: 35px;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.box-container {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height-70}px`');
|
||||
}
|
||||
|
||||
.box-controls {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
background: #000000;
|
||||
height: 35px;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.left-controls {
|
||||
display: flex;
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.right-controls {
|
||||
justify-self: end;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,277 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- 标题 -->
|
||||
<div class="box-title">
|
||||
<div class="left-title">
|
||||
<span
|
||||
:style="{
|
||||
fontSize: props.dataStyle.videoTitleFontSize + 'px',
|
||||
color: props.dataStyle.videoTitleFontColor,
|
||||
}"
|
||||
>
|
||||
{{ props.title }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="right-title">
|
||||
<n-button quaternary @click="closeVideo">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Close
|
||||
:style="{
|
||||
width: props.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
height: props.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
fontSize: props.dataStyle.closeVideoIconWidthAndHeight + 'px',
|
||||
color: props.dataStyle.closeVideoIconColor,
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 视频 -->
|
||||
<video
|
||||
:id="'ZhiGan_SheXiangTouModal' + props.index + props.timestamp"
|
||||
class="TCPlayer-video-contaiiner"
|
||||
preload="auto"
|
||||
crossOrigin="anonymous"
|
||||
playsinline
|
||||
autoplay
|
||||
:loop="props.dataStyle.videoLoop"
|
||||
:muted="props.dataStyle.videoMuted"
|
||||
@click="clickThisVideo"
|
||||
/>
|
||||
<!-- 控制栏 -->
|
||||
<div class="box-controls">
|
||||
<div class="left-controls">
|
||||
<div>
|
||||
<n-button quaternary @click="playOrPauseClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Pause
|
||||
v-if="control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<CaretForward
|
||||
v-if="!control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
<div>
|
||||
<n-button quaternary @click="volumeClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<VolumeHigh
|
||||
v-if="control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<VolumeMute
|
||||
v-if="!control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-controls">
|
||||
<n-button quaternary @click="fullScreenClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ExpandOutlined
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, onUnmounted, watch, ref } from 'vue';
|
||||
import { ExpandOutlined } from '@ant-design/icons-vue';
|
||||
import { Close, Pause, CaretForward, VolumeHigh, VolumeMute } from '@vicons/ionicons5';
|
||||
|
||||
const props = defineProps([
|
||||
'title',
|
||||
'videourl',
|
||||
'index',
|
||||
'width',
|
||||
'height',
|
||||
'timestamp',
|
||||
'dataStyle',
|
||||
]);
|
||||
const emit = defineEmits(['changeThisVideo', 'closeThisVideo']);
|
||||
|
||||
// 关闭此视频;
|
||||
function closeVideo() {
|
||||
closePlayerVideo();
|
||||
emit('closeThisVideo', props.index);
|
||||
}
|
||||
|
||||
// 开始播放/暂停播放
|
||||
const control_playOrPause = ref(true);
|
||||
// 音量:true为静音
|
||||
const control_volume = ref(true);
|
||||
|
||||
// 开始播放/暂停播放方法
|
||||
function playOrPauseClick() {
|
||||
control_playOrPause.value = !control_playOrPause.value;
|
||||
if (control_playOrPause.value) {
|
||||
txPlayer.play();
|
||||
} else {
|
||||
txPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// 音量
|
||||
function volumeClick() {
|
||||
control_volume.value = !control_volume.value;
|
||||
if (control_volume.value) {
|
||||
txPlayer.volume(0);
|
||||
} else {
|
||||
txPlayer.volume(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 全屏
|
||||
function fullScreenClick() {
|
||||
txPlayer.requestFullscreen();
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.videourl,
|
||||
() => {
|
||||
handlerPlayVideo();
|
||||
},
|
||||
);
|
||||
watch(
|
||||
() => props.width,
|
||||
() => {
|
||||
handlerPlayVideo();
|
||||
},
|
||||
);
|
||||
|
||||
// 视频控件初始化
|
||||
let txPlayer: any = null;
|
||||
function handlerPlayVideo() {
|
||||
nextTick(function () {
|
||||
if (txPlayer) {
|
||||
txPlayer.src(props.videourl);
|
||||
txPlayer.width(props.width);
|
||||
txPlayer.height(props.height - 70);
|
||||
} else {
|
||||
txPlayer = TCPlayer('ZhiGan_SheXiangTouModal' + props.index + props.timestamp, {
|
||||
width: props.width,
|
||||
height: props.height - 70,
|
||||
controls: false,
|
||||
});
|
||||
txPlayer.src(props.videourl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 关闭此视频
|
||||
function closePlayerVideo() {
|
||||
if (txPlayer) {
|
||||
txPlayer.dispose();
|
||||
txPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 点击视频内容
|
||||
function clickThisVideo() {
|
||||
emit('changeThisVideo', props.index);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
handlerPlayVideo();
|
||||
control_volume.value = props.videoMuted;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
closePlayerVideo();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
handlerPlayVideo,
|
||||
closePlayerVideo,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.box-title {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
background: #000000;
|
||||
height: 35px;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.left-title {
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
left: 0%;
|
||||
z-index: 100;
|
||||
width: 90%;
|
||||
}
|
||||
.right-title {
|
||||
position: absolute;
|
||||
top: -10%;
|
||||
right: 0%;
|
||||
z-index: 100;
|
||||
}
|
||||
video {
|
||||
display: block;
|
||||
object-fit: v-bind('props.dataStyle.videoFit');
|
||||
}
|
||||
|
||||
::v-deep .vjs-live-display {
|
||||
width: 40px !important;
|
||||
}
|
||||
|
||||
::v-deep .vjs-button {
|
||||
width: 20px !important;
|
||||
}
|
||||
|
||||
.box-controls {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
background: #000000;
|
||||
height: 35px;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.left-controls {
|
||||
display: flex;
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.right-controls {
|
||||
justify-self: end;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<video
|
||||
:id="'ZhiGan_SheXiangTouModal' + props.index + props.timestamp"
|
||||
class="TCPlayer-video-contaiiner"
|
||||
preload="auto"
|
||||
crossOrigin="anonymous"
|
||||
playsinline
|
||||
autoplay
|
||||
:loop="props.videoLoop"
|
||||
:muted="props.videoMuted"
|
||||
:style="{
|
||||
width: props.width + 'px',
|
||||
height: props.height + 'px',
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, onUnmounted, watch } from 'vue';
|
||||
|
||||
const props = defineProps([
|
||||
'videourl',
|
||||
'index',
|
||||
'width',
|
||||
'height',
|
||||
'timestamp',
|
||||
'videoLoop',
|
||||
'videoMuted',
|
||||
'videoFit',
|
||||
]);
|
||||
|
||||
watch(
|
||||
() => props.videourl,
|
||||
() => {
|
||||
handlerPlayVideo();
|
||||
},
|
||||
);
|
||||
watch(
|
||||
() => props.width,
|
||||
() => {
|
||||
handlerPlayVideo();
|
||||
},
|
||||
);
|
||||
|
||||
// 视频控件初始化
|
||||
let player: any = null;
|
||||
|
||||
function handlerPlayVideo() {
|
||||
nextTick(function () {
|
||||
if (player) {
|
||||
player.src(props.videourl);
|
||||
} else {
|
||||
player = TCPlayer('ZhiGan_SheXiangTouModal' + props.index + props.timestamp, {});
|
||||
player.src(props.videourl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closePlayerVideo() {
|
||||
if (player) {
|
||||
player.dispose();
|
||||
player = null;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
handlerPlayVideo();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
closePlayerVideo();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
handlerPlayVideo,
|
||||
closePlayerVideo,
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
video {
|
||||
display: block;
|
||||
object-fit: v-bind('props.videoFit');
|
||||
}
|
||||
|
||||
::v-deep .vjs-live-display {
|
||||
width: 40px !important;
|
||||
}
|
||||
|
||||
::v-deep .vjs-button {
|
||||
width: 20px !important;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -23,32 +23,47 @@
|
|||
{
|
||||
"title":"DJA-72无人机监控画面",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"DJ-057无人机监控画面",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"DJA-20无人机监控画面",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"DJA-035无人机监控画面",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"DJA-11无人机监控画面",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"DJ-021无人机监控画面",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title": "白马关通天沟",
|
||||
"videourl": "8H03AA1PAG97234",
|
||||
"manufacturer": "乐橙"
|
||||
},
|
||||
{
|
||||
"title": "可落",
|
||||
"videourl": "8H03AA1PAG8D9BF",
|
||||
"manufacturer": "乐橙"
|
||||
},
|
||||
{
|
||||
"title": "天宝山林场",
|
||||
"videourl": "8L0995DPAG11E58",
|
||||
"manufacturer": "乐橙"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
:height="`${option.dataStyle.videoheight - 2 * option.dataStyle.borderWidth - 2 * option.dataStyle.padding}`"
|
||||
src="@/assets/images/chart/zhichu/component/SheXiangTouModal_Image.png"
|
||||
/>
|
||||
<MulHKmonitor
|
||||
<MonitorHK
|
||||
v-if="!isEdit && item.manufacturer == '海康'"
|
||||
:index="index"
|
||||
:serialNumberValue="item.videourl"
|
||||
|
|
@ -65,8 +65,18 @@
|
|||
:height="`${option.dataStyle.videoheight - 2 * option.dataStyle.borderWidth - 2 * option.dataStyle.padding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
<PlayVideo
|
||||
v-if="!isEdit && !item.manufacturer"
|
||||
<MonitorLC
|
||||
v-if="!isEdit && item.manufacturer == '乐橙'"
|
||||
:deviceId="item.videourl"
|
||||
:channelId="0"
|
||||
:index="index"
|
||||
:width="`${option.dataStyle.videowidth - 2 * option.dataStyle.borderWidth - 2 * option.dataStyle.padding}`"
|
||||
:height="`${option.dataStyle.videoheight - 2 * option.dataStyle.borderWidth - 2 * option.dataStyle.padding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:videoMuted="option.dataStyle.videoMuted"
|
||||
/>
|
||||
<MonitorTX
|
||||
v-if="!isEdit && item.manufacturer == '腾讯'"
|
||||
:videourl="item.videourl"
|
||||
:index="index"
|
||||
:width="`${option.dataStyle.videowidth - 2 * option.dataStyle.borderWidth - 2 * option.dataStyle.padding}`"
|
||||
|
|
@ -109,7 +119,7 @@
|
|||
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
|
||||
import dayjs from 'dayjs';
|
||||
import Title from './svg/title.vue';
|
||||
import { MulHKmonitor, PlayVideo } from './video/index';
|
||||
import { MonitorHK, MonitorLC, MonitorTX } from './video/index';
|
||||
|
||||
const props = defineProps({
|
||||
chartConfig: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import MulHKmonitor from './mulHKmonitor.vue';
|
||||
import PlayVideo from './playVideo.vue';
|
||||
import MonitorHK from './monitorHK.vue';
|
||||
import MonitorLC from './monitorLC.vue';
|
||||
import MonitorTX from './monitorTX.vue';
|
||||
|
||||
export {
|
||||
MulHKmonitor,
|
||||
PlayVideo,
|
||||
MonitorHK,
|
||||
MonitorLC,
|
||||
MonitorTX,
|
||||
};
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, watch, defineProps, defineExpose, ref, computed } from 'vue';
|
||||
import { onMounted, onUnmounted, watch, nextTick, ref, computed } from 'vue';
|
||||
import { JSEncrypt } from 'jsencrypt';
|
||||
|
||||
const props = defineProps(['serialNumberValue', 'index', 'width', 'height', 'timestamp']);
|
||||
|
|
@ -132,27 +132,12 @@
|
|||
}),
|
||||
})
|
||||
.then(function (oData) {
|
||||
// 实际宽高
|
||||
let width = props.width;
|
||||
let height = props.height;
|
||||
const divElement = document.getElementById('camera-box-' + props.index);
|
||||
if (divElement) {
|
||||
const rect = divElement.getBoundingClientRect();
|
||||
const rectWidth = rect.width;
|
||||
const rectHeight = rect.height;
|
||||
if (rectWidth < width) {
|
||||
width = rectWidth;
|
||||
}
|
||||
if (rectHeight < height) {
|
||||
height = rectHeight;
|
||||
}
|
||||
}
|
||||
oWebControl.JS_Resize(width, height); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
|
||||
|
||||
// 重定大小
|
||||
reSizeVideo();
|
||||
// 双击-全屏
|
||||
oWebControl.JS_SetWindowControlCallback({
|
||||
cbIntegrationCallBack: function (oData) {
|
||||
// oData 是封装的视频 web 插件回调消息的消息体
|
||||
// 双击-全屏
|
||||
if (oData.responseMsg.type == '7') {
|
||||
setFullScreen();
|
||||
}
|
||||
|
|
@ -210,6 +195,27 @@
|
|||
return encrypt.encrypt(value);
|
||||
}
|
||||
|
||||
// 重定大小
|
||||
function reSizeVideo() {
|
||||
if (oWebControl != null) {
|
||||
// 实际宽高
|
||||
let width = props.width;
|
||||
let height = props.height;
|
||||
const divElement = document.getElementById('camera-box-' + props.index);
|
||||
if (divElement) {
|
||||
const rect = divElement.getBoundingClientRect();
|
||||
const rectWidth = rect.width;
|
||||
const rectHeight = rect.height;
|
||||
if (rectWidth < width) {
|
||||
width = rectWidth;
|
||||
}
|
||||
if (rectHeight < height) {
|
||||
height = rectHeight;
|
||||
}
|
||||
}
|
||||
oWebControl.JS_Resize(width, height); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
|
||||
}
|
||||
}
|
||||
// 全屏
|
||||
function setFullScreen() {
|
||||
oWebControl.JS_RequestInterface({
|
||||
|
|
@ -217,16 +223,42 @@
|
|||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.serialNumberValue,
|
||||
() => {
|
||||
// 初始化播放内容
|
||||
init();
|
||||
},
|
||||
);
|
||||
|
||||
// 推送消息
|
||||
function cbIntegrationCallBack(oData) {
|
||||
// showCBInfo(JSON.stringify(oData.responseMsg));
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 启动视频窗口
|
||||
initPlugin();
|
||||
// 添加监听滚动事件
|
||||
const elements = document.querySelectorAll('.ZhiGan_WuRenJiShiShiHuaMian');
|
||||
if (elements.length > 0) {
|
||||
// 遍历每个元素并绑定 scroll 事件
|
||||
elements.forEach((element) => {
|
||||
element.addEventListener('scroll', reSizeVideo);
|
||||
});
|
||||
}
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 销毁视频窗口
|
||||
closeHkVideo();
|
||||
// 移除监听滚动事件
|
||||
const elements = document.querySelectorAll('.ZhiGan_WuRenJiShiShiHuaMian');
|
||||
if (elements.length > 0) {
|
||||
// 遍历每个元素并绑定 scroll 事件
|
||||
elements.forEach((element) => {
|
||||
element.removeEventListener('scroll', reSizeVideo);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<div class="box-container">
|
||||
<div :id="'root' + props.index + props.timestamp"></div>
|
||||
</div>
|
||||
<div class="box-controls">
|
||||
<div class="left-controls">
|
||||
<div>
|
||||
<n-button quaternary @click="playOrPauseClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Pause
|
||||
v-if="control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<CaretForward
|
||||
v-if="!control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
<div>
|
||||
<n-button quaternary @click="volumeClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<VolumeHigh
|
||||
v-if="!control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<VolumeMute
|
||||
v-if="control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-controls">
|
||||
<n-button quaternary @click="fullScreenClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ExpandOutlined
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, watch, ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { ExpandOutlined } from '@ant-design/icons-vue';
|
||||
import { Pause, CaretForward, VolumeHigh, VolumeMute } from '@vicons/ionicons5';
|
||||
|
||||
let BASE_URL = 'http://111.17.207.220:9001/api';
|
||||
|
||||
const props = defineProps([
|
||||
'deviceId',
|
||||
'channelId',
|
||||
'index',
|
||||
'width',
|
||||
'height',
|
||||
'timestamp',
|
||||
'videoMuted',
|
||||
]);
|
||||
let clPlayer: any = null;
|
||||
|
||||
// 开始播放/暂停播放
|
||||
const control_playOrPause = ref(true);
|
||||
// 音量:true为静音
|
||||
const control_volume = ref(true);
|
||||
// 全屏
|
||||
const control_fullScreen = ref(false);
|
||||
|
||||
// 开始播放/暂停播放方法
|
||||
function playOrPauseClick() {
|
||||
control_playOrPause.value = !control_playOrPause.value;
|
||||
if (control_playOrPause.value) {
|
||||
clPlayer.play();
|
||||
} else {
|
||||
clPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// 音量
|
||||
function volumeClick() {
|
||||
control_volume.value = !control_volume.value;
|
||||
if (control_volume.value) {
|
||||
clPlayer.volume(0);
|
||||
} else {
|
||||
clPlayer.volume(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 全屏
|
||||
function fullScreenClick() {
|
||||
clPlayer.fullScreen();
|
||||
}
|
||||
|
||||
// 获取kitToken
|
||||
function getKitToken(deviceId, channelId) {
|
||||
axios({
|
||||
method: 'post',
|
||||
url: BASE_URL + '/Camera/getKitToken?deviceId=' + deviceId + '&channelId=0' + '&type=0',
|
||||
}).then((res) => {
|
||||
let kitToken = res.data.result.data.kitToken;
|
||||
loadMonitorVideo(deviceId, kitToken, channelId);
|
||||
});
|
||||
}
|
||||
|
||||
// 开始
|
||||
function loadMonitorVideo(deviceId, kitToken, channelId) {
|
||||
// 结束上一个
|
||||
closeMonitorVideo();
|
||||
|
||||
clPlayer = new imouPlayer({
|
||||
id: 'root' + props.index + props.timestamp,
|
||||
width: props.width,
|
||||
height: props.height - 35,
|
||||
deviceId: deviceId,
|
||||
token: kitToken,
|
||||
channelId: channelId,
|
||||
type: 1,
|
||||
streamId: 0,
|
||||
recordType: 'cloud',
|
||||
code: '',
|
||||
controls: true,
|
||||
});
|
||||
clPlayer.volume(0);
|
||||
}
|
||||
|
||||
// 结束
|
||||
function closeMonitorVideo() {
|
||||
if (clPlayer != null) {
|
||||
clPlayer.destroy();
|
||||
clPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.deviceId,
|
||||
() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
control_volume.value = props.videoMuted;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
closeMonitorVideo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.box {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height}px`');
|
||||
z-index: 99;
|
||||
}
|
||||
.box-container {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height-35}px`');
|
||||
}
|
||||
|
||||
.box-controls {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
background: #000000;
|
||||
height: 35px;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.left-controls {
|
||||
display: flex;
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.right-controls {
|
||||
justify-self: end;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -15,7 +15,12 @@
|
|||
{
|
||||
"title":"费县马庄镇陈家鱼后村南斜坡后村",
|
||||
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
|
||||
"manufacturer": ""
|
||||
"manufacturer": "腾讯"
|
||||
},
|
||||
{
|
||||
"title":"可落",
|
||||
"videourl": "8H03AA1PAG8D9BF",
|
||||
"manufacturer": "乐橙"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -126,10 +126,27 @@
|
|||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
src="@/assets/images/chart/zhichu/component/SheXiangTouModal_Image.png"
|
||||
preview-disabled
|
||||
/>
|
||||
<PlayVideo
|
||||
v-if="!isEdit && videoItem.videourl && !videoItem.manufacturer"
|
||||
<MonitorHK
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '海康'"
|
||||
:index="index + '-' + videoIndex"
|
||||
:serialNumberValue="videoItem.videourl"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
<MonitorLC
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '乐橙'"
|
||||
:deviceId="videoItem.videourl"
|
||||
:channelId="0"
|
||||
:index="index + '-' + videoIndex"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:videoMuted="option.dataStyle.videoMuted"
|
||||
/>
|
||||
<MonitorTX
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '腾讯'"
|
||||
:videourl="videoItem.videourl"
|
||||
:index="index + '-' + videoIndex"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
|
|
@ -139,14 +156,6 @@
|
|||
:videoMuted="option.dataStyle.videoMuted"
|
||||
:videoFit="option.dataStyle.videoFit"
|
||||
/>
|
||||
<MulHKmonitor
|
||||
v-if="!isEdit && videoItem.videourl && videoItem.manufacturer == '海康'"
|
||||
:index="index + '-' + videoIndex"
|
||||
:serialNumberValue="videoItem.videourl"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 单个 -->
|
||||
|
|
@ -161,10 +170,27 @@
|
|||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
src="@/assets/images/chart/zhichu/component/SheXiangTouModal_Image.png"
|
||||
preview-disabled
|
||||
/>
|
||||
<PlayVideo
|
||||
v-if="!isEdit && item.videos.videourl && !item.videos.manufacturer"
|
||||
<MonitorHK
|
||||
v-if="!isEdit && item.videos.videourl && item.videos.manufacturer == '海康'"
|
||||
:index="index + '-' + videoIndex"
|
||||
:serialNumberValue="item.videos.videourl"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
<MonitorLC
|
||||
v-if="!isEdit && item.videos.videourl && item.videos.manufacturer == '乐橙'"
|
||||
:deviceId="item.videos.videourl"
|
||||
:channelId="0"
|
||||
:index="index"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
:videoMuted="option.dataStyle.videoMuted"
|
||||
/>
|
||||
<MonitorTX
|
||||
v-if="!isEdit && item.videos.videourl && item.videos.manufacturer == '腾讯'"
|
||||
:videourl="item.videos.videourl"
|
||||
:index="index + '-0'"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
|
|
@ -174,14 +200,6 @@
|
|||
:videoMuted="option.dataStyle.videoMuted"
|
||||
:videoFit="option.dataStyle.videoFit"
|
||||
/>
|
||||
<MulHKmonitor
|
||||
v-if="!isEdit && item.videos.videourl && item.videos.manufacturer == '海康'"
|
||||
:index="index + '-' + videoIndex"
|
||||
:serialNumberValue="item.videos.videourl"
|
||||
:width="`${option.dataStyle.videoWidth - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:height="`${option.dataStyle.videoHeight - 2 * option.dataStyle.videoBorderWidth - 2 * option.dataStyle.videoPadding}`"
|
||||
:timestamp="option.dataStyle.timestamp"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -200,7 +218,7 @@
|
|||
import { replaceSqlParams } from '@/utils/sqlHandler';
|
||||
import Title from './svg/title.vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { MulHKmonitor, PlayVideo } from './video/index';
|
||||
import { MonitorHK, MonitorLC, MonitorTX } from './video/index';
|
||||
|
||||
const props = defineProps({
|
||||
chartConfig: {
|
||||
|
|
@ -313,7 +331,7 @@
|
|||
|
||||
.timeLineVideoDivTitle {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
z-index: 100;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
font-size: v-bind('`${option.dataStyle.videoTitleFontSize}px`');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import MulHKmonitor from './mulHKmonitor.vue';
|
||||
import PlayVideo from './playVideo.vue';
|
||||
import MonitorHK from './monitorHK.vue';
|
||||
import MonitorLC from './monitorLC.vue';
|
||||
import MonitorTX from './monitorTX.vue';
|
||||
|
||||
export {
|
||||
MulHKmonitor,
|
||||
PlayVideo,
|
||||
MonitorHK,
|
||||
MonitorLC,
|
||||
MonitorTX,
|
||||
};
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
<template>
|
||||
<div class="box">
|
||||
<div class="box-container">
|
||||
<div :id="'root' + props.index + props.timestamp"></div>
|
||||
</div>
|
||||
<div class="box-controls">
|
||||
<div class="left-controls">
|
||||
<div>
|
||||
<n-button quaternary @click="playOrPauseClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<Pause
|
||||
v-if="control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<CaretForward
|
||||
v-if="!control_playOrPause"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
<div>
|
||||
<n-button quaternary @click="volumeClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<VolumeHigh
|
||||
v-if="!control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
<VolumeMute
|
||||
v-if="control_volume"
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-controls">
|
||||
<n-button quaternary @click="fullScreenClick">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ExpandOutlined
|
||||
:style="{
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
}"
|
||||
/>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, watch, ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { ExpandOutlined } from '@ant-design/icons-vue';
|
||||
import { Pause, CaretForward, VolumeHigh, VolumeMute } from '@vicons/ionicons5';
|
||||
|
||||
let BASE_URL = 'http://111.17.207.220:9001/api';
|
||||
|
||||
const props = defineProps([
|
||||
'deviceId',
|
||||
'channelId',
|
||||
'index',
|
||||
'width',
|
||||
'height',
|
||||
'timestamp',
|
||||
'videoMuted',
|
||||
]);
|
||||
let clPlayer: any = null;
|
||||
|
||||
// 开始播放/暂停播放
|
||||
const control_playOrPause = ref(true);
|
||||
// 音量:true为静音
|
||||
const control_volume = ref(true);
|
||||
// 全屏
|
||||
const control_fullScreen = ref(false);
|
||||
|
||||
// 开始播放/暂停播放方法
|
||||
function playOrPauseClick() {
|
||||
control_playOrPause.value = !control_playOrPause.value;
|
||||
if (control_playOrPause.value) {
|
||||
clPlayer.play();
|
||||
} else {
|
||||
clPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// 音量
|
||||
function volumeClick() {
|
||||
control_volume.value = !control_volume.value;
|
||||
if (control_volume.value) {
|
||||
clPlayer.volume(0);
|
||||
} else {
|
||||
clPlayer.volume(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 全屏
|
||||
function fullScreenClick() {
|
||||
clPlayer.fullScreen();
|
||||
}
|
||||
|
||||
// 获取kitToken
|
||||
function getKitToken(deviceId, channelId) {
|
||||
axios({
|
||||
method: 'post',
|
||||
url: BASE_URL + '/Camera/getKitToken?deviceId=' + deviceId + '&channelId=0' + '&type=0',
|
||||
}).then((res) => {
|
||||
let kitToken = res.data.result.data.kitToken;
|
||||
loadMonitorVideo(deviceId, kitToken, channelId);
|
||||
});
|
||||
}
|
||||
|
||||
// 开始
|
||||
function loadMonitorVideo(deviceId, kitToken, channelId) {
|
||||
// 结束上一个
|
||||
closeMonitorVideo();
|
||||
|
||||
clPlayer = new imouPlayer({
|
||||
id: 'root' + props.index + props.timestamp,
|
||||
width: props.width,
|
||||
height: props.height - 25,
|
||||
deviceId: deviceId,
|
||||
token: kitToken,
|
||||
channelId: channelId,
|
||||
type: 1,
|
||||
streamId: 0,
|
||||
recordType: 'cloud',
|
||||
code: '',
|
||||
controls: true,
|
||||
});
|
||||
clPlayer.volume(0);
|
||||
}
|
||||
|
||||
// 结束
|
||||
function closeMonitorVideo() {
|
||||
if (clPlayer != null) {
|
||||
clPlayer.destroy();
|
||||
clPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.deviceId,
|
||||
() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
getKitToken(props.deviceId, props.channelId);
|
||||
control_volume.value = props.videoMuted;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
closeMonitorVideo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.box {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height}px`');
|
||||
z-index: 99;
|
||||
}
|
||||
.box-container {
|
||||
width: v-bind('`${props.width}px`');
|
||||
height: v-bind('`${props.height-25}px`');
|
||||
}
|
||||
|
||||
.box-controls {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
background: #000000;
|
||||
height: 25px;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.left-controls {
|
||||
display: flex;
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.right-controls {
|
||||
justify-self: end;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<video
|
||||
:id="'ZhiGan_ModalTimeLine' + props.index + props.timestamp"
|
||||
:id="'HuoQingDetailTimeLine' + props.index + props.timestamp"
|
||||
class="TCPlayer-video-contaiiner"
|
||||
preload="auto"
|
||||
crossOrigin="anonymous"
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
if (player) {
|
||||
player.src(props.videourl);
|
||||
} else {
|
||||
player = TCPlayer('ZhiGan_ModalTimeLine' + props.index + props.timestamp, {});
|
||||
player = TCPlayer('HuoQingDetailTimeLine' + props.index + props.timestamp, {});
|
||||
player.src(props.videourl);
|
||||
}
|
||||
});
|
||||
Loading…
Reference in New Issue