智感、智库-含视频组件的增加乐橙视频,且根据组件的需求修改增加功能

main
滕嵩 2025-04-26 11:38:52 +08:00
parent f223377628
commit 5a09a108d6
33 changed files with 1702 additions and 385 deletions

View File

@ -15,7 +15,12 @@
{
"title":"费县马庄镇陈家鱼后村南斜坡后村",
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
"manufacturer": ""
"manufacturer": "腾讯"
},
{
"title":"可落",
"videourl": "8H03AA1PAG8D9BF",
"manufacturer": "乐橙"
}
]
},

View File

@ -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`');

View File

@ -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,
};

View File

@ -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>

View File

@ -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="请选择默认视频"
/>

View File

@ -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": "乐橙"
}

View File

@ -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`');

View File

@ -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,
};

View File

@ -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); // resizefirefoxDIV
//
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); // resizefirefoxDIV
}
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({

View File

@ -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>

View File

@ -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;

View File

@ -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, // 视频-循环播放

View File

@ -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": "乐橙"
}
]
}

View File

@ -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;
}
}
}

View File

@ -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,
};

View File

@ -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({

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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": "乐橙"
}
]
}

View File

@ -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: {

View File

@ -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,
};

View File

@ -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); // resizefirefoxDIV
//
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); // resizefirefoxDIV
}
}
//
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({

View File

@ -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>

View File

@ -15,7 +15,12 @@
{
"title":"费县马庄镇陈家鱼后村南斜坡后村",
"videourl": "http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv",
"manufacturer": ""
"manufacturer": "腾讯"
},
{
"title":"可落",
"videourl": "8H03AA1PAG8D9BF",
"manufacturer": "乐橙"
}
]
},

View File

@ -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`');

View File

@ -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,
};

View File

@ -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>

View File

@ -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);
}
});