feat:bug修改
This commit is contained in:
1 parent
e9fd667623
commit
f771123601
15 files changed
+106
-78
No files matched your search
@@ -12,7 +12,7 @@
|
||||
placeholder="请选择报警类型" />
|
||||
</el-form-item>
|
||||
<el-form-item style="width: 350px;" label="抓拍时间" prop="capTimeList">
|
||||
<el-date-picker v-model="state.queryForm.capTimeList" value-format="YYYY-MM-DD"
|
||||
<el-date-picker v-model="state.queryForm.capTimeList" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<dict-select v-model="state.queryForm.carDirect" :options="dh_car_direct" placeholder="请选择行车方向" />
|
||||
</el-form-item>
|
||||
<el-form-item style="width: 350px;" label="抓拍时间" prop="capTimeList">
|
||||
<el-date-picker v-model="state.queryForm.capTimeList" value-format="YYYY-MM-DD" type="daterange" />
|
||||
<el-date-picker v-model="state.queryForm.capTimeList" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="search" type="primary" @click="getDataList">
|
||||
|
||||
@@ -7,7 +7,7 @@ import API from "./api.js";
|
||||
*/
|
||||
class PlayerManager {
|
||||
constructor(opt) {
|
||||
if(!opt.el) {
|
||||
if (!opt.el) {
|
||||
console.warn(`请初始化播放器时传入必传参数:
|
||||
new PlayerManager({
|
||||
el: "wsplayer_id", // 播放器所在的容器ID
|
||||
@@ -37,24 +37,24 @@ new PlayerManager({
|
||||
* 在 ws/wss 直连模式下, serverIp 表示MTS流媒体服务 IP
|
||||
* 在 代理 模式下, serverIp 表示的是 代理服务器的IP 地址
|
||||
*/
|
||||
this.serverIp = opt.serverIp
|
||||
this.serverIp = opt.serverIp
|
||||
|
||||
/**
|
||||
* V1.2.8 版本新增字段
|
||||
* 解码库资源文件前缀
|
||||
*/
|
||||
this.prefixUrl = opt.prefixUrl || './static'
|
||||
/**
|
||||
* V1.2.8 版本新增字段
|
||||
* 优先级最高,该方法传入后
|
||||
* 结构如下:
|
||||
* eg:
|
||||
* (rtspUrl) => {
|
||||
* return "wss://{ip}:9102"
|
||||
* }
|
||||
* 配置后:protocol, isIntranet, proxyServerIp, streamServerIp
|
||||
*/
|
||||
this.setWSUrl = opt.setWSUrl
|
||||
/**
|
||||
* V1.2.8 版本新增字段
|
||||
* 解码库资源文件前缀
|
||||
*/
|
||||
this.prefixUrl = opt.prefixUrl || './static'
|
||||
/**
|
||||
* V1.2.8 版本新增字段
|
||||
* 优先级最高,该方法传入后
|
||||
* 结构如下:
|
||||
* eg:
|
||||
* (rtspUrl) => {
|
||||
* return "wss://{ip}:9102"
|
||||
* }
|
||||
* 配置后:protocol, isIntranet, proxyServerIp, streamServerIp
|
||||
*/
|
||||
this.setWSUrl = opt.setWSUrl
|
||||
/**
|
||||
* V1.2.8 版本新增字段
|
||||
* websocket协议,http支持wss协议拉流,因此增加protocol配置
|
||||
@@ -69,28 +69,28 @@ new PlayerManager({
|
||||
*/
|
||||
this.isIntranet = opt.isIntranet
|
||||
this.intranetMap = opt.intranetMap
|
||||
/**
|
||||
* V1.2.7 版本新增字段
|
||||
* 用于只有内网
|
||||
* @desc 代理 模式下,代理服务器的IP 地址
|
||||
* 如果代理服务有端口则拼接端口
|
||||
*
|
||||
*/
|
||||
this.proxyServerIp = opt.proxyServerIp
|
||||
/**
|
||||
* V1.2.7 版本新增字段
|
||||
* 用于只有内网
|
||||
* @desc 流媒体服务 IP 地址
|
||||
* 如果拉流的 9100 9320 端口发生修改,则需要后面拼接修改后的端口
|
||||
*/
|
||||
this.streamServerIp = opt.streamServerIp
|
||||
/**
|
||||
* V1.2.7 版本新增字段
|
||||
* @desc 模式类型 是直连模式/代理模式
|
||||
*/
|
||||
this.useNginxProxy = opt.useNginxProxy || false
|
||||
/**
|
||||
* V1.2.7 版本新增字段
|
||||
* 用于只有内网
|
||||
* @desc 代理 模式下,代理服务器的IP 地址
|
||||
* 如果代理服务有端口则拼接端口
|
||||
*
|
||||
*/
|
||||
this.proxyServerIp = opt.proxyServerIp
|
||||
/**
|
||||
* V1.2.7 版本新增字段
|
||||
* 用于只有内网
|
||||
* @desc 流媒体服务 IP 地址
|
||||
* 如果拉流的 9100 9320 端口发生修改,则需要后面拼接修改后的端口
|
||||
*/
|
||||
this.streamServerIp = opt.streamServerIp
|
||||
/**
|
||||
* V1.2.7 版本新增字段
|
||||
* @desc 模式类型 是直连模式/代理模式
|
||||
*/
|
||||
this.useNginxProxy = opt.useNginxProxy || false
|
||||
|
||||
if(opt.importLoad) {
|
||||
if (opt.importLoad) {
|
||||
this.loadWSPlayer(() => {
|
||||
this.initPlayer(opt)
|
||||
})
|
||||
@@ -104,9 +104,9 @@ new PlayerManager({
|
||||
dom.src = `${this.prefixUrl}/WSPlayer/WSPlayer.js`;
|
||||
document.head.appendChild(dom);
|
||||
var loaded = false;
|
||||
if(typeof callback === 'function') {
|
||||
dom.onload = dom.onreadystatechange = function() {
|
||||
if(!loaded && (!dom.readyState || /loaded|complete/.test(dom.readyState))) {
|
||||
if (typeof callback === 'function') {
|
||||
dom.onload = dom.onreadystatechange = function () {
|
||||
if (!loaded && (!dom.readyState || /loaded|complete/.test(dom.readyState))) {
|
||||
dom.onload = dom.onreadystatechange = null;
|
||||
loaded = true;
|
||||
callback();
|
||||
@@ -118,10 +118,10 @@ new PlayerManager({
|
||||
// 初始化播放器
|
||||
initPlayer(opt) {
|
||||
// 初始化播放器
|
||||
if(window.WSPlayer.WSPlayer) {
|
||||
if (window.WSPlayer.WSPlayer) {
|
||||
window.WSPlayer = window.WSPlayer.WSPlayer
|
||||
}
|
||||
switch(opt.type) {
|
||||
switch (opt.type) {
|
||||
case "real":
|
||||
this.initRealPlayer(opt);
|
||||
break;
|
||||
@@ -165,7 +165,7 @@ new PlayerManager({
|
||||
useNginxProxy: this.useNginxProxy, // V1.2.7 版本新增该配置 直连时需要改为 false, 代理模式为 true
|
||||
showIcons: opt.showIcons || {
|
||||
streamChangeSelect: true, // 主辅码流切换
|
||||
replayIcon:true, // 刷新重播按钮
|
||||
replayIcon: true, // 刷新重播按钮
|
||||
ivsIcon: true, // 控制智能帧按钮
|
||||
talkIcon: true, // 对讲功能按钮
|
||||
localRecordIcon: true, // 本地录像功能按钮
|
||||
@@ -196,7 +196,7 @@ new PlayerManager({
|
||||
})
|
||||
this.player = this.realPlayer;
|
||||
// 初始化云台控制组件
|
||||
if(opt.pztEl) {
|
||||
if (opt.pztEl) {
|
||||
this.realPlayer.initPanTilt({
|
||||
// 云台控制容器的id
|
||||
el: opt.pztEl,
|
||||
@@ -237,7 +237,7 @@ new PlayerManager({
|
||||
useNginxProxy: this.useNginxProxy, // V1.2.7 版本新增该配置 直连时需要改为 false, 【代理模式可不传】
|
||||
showIcons: opt.showIcons || {
|
||||
streamChangeSelect: true, // 主辅码流切换
|
||||
replayIcon:true, // 刷新重播按钮
|
||||
replayIcon: true, // 刷新重播按钮
|
||||
ivsIcon: true, // 控制智能帧按钮
|
||||
talkIcon: true, // 对讲功能按钮
|
||||
localRecordIcon: true, // 本地录像功能按钮
|
||||
@@ -425,7 +425,7 @@ new PlayerManager({
|
||||
* 关闭播放器
|
||||
* @param {number} index 可选,关闭指定索引的窗口的播放器,不传则表示关闭所有播放器
|
||||
*/
|
||||
close(index, closeReason="api") {
|
||||
close(index, closeReason = "api") {
|
||||
this.player && this.player.close(index, closeReason);
|
||||
}
|
||||
|
||||
@@ -565,7 +565,7 @@ new PlayerManager({
|
||||
|
||||
// ----------------- 播放器事件 ------------------------
|
||||
__receiveMessageFromWSPlayer(method, data) {
|
||||
switch(method) {
|
||||
switch (method) {
|
||||
// ------------- 公共事件 ---------------------
|
||||
case "initializationCompleted":
|
||||
// 初始化完成,可调用播放方法(适用于动态加载解码库)
|
||||
@@ -601,7 +601,7 @@ new PlayerManager({
|
||||
case "closeVideo": // 视频关闭
|
||||
// 点击关闭按钮引发的视频关闭进行提示
|
||||
// 切换视频引发的视频关闭不进行提示
|
||||
if(!data.changeVideoFlag) {
|
||||
if (!data.changeVideoFlag) {
|
||||
console.log(`窗口${data.selectIndex}的视频已关闭`)
|
||||
}
|
||||
// 关闭原因: btnClick-按钮关闭 chromeMemoryOut-浏览器内存不足 changeStream-切换视频调用 playSDKError-解码库报错关闭 recordFinish-录像回放完成 api-调用API关闭 destroy-解码库销毁关闭 otherCustom-可自定义关闭内容
|
||||
@@ -638,12 +638,12 @@ new PlayerManager({
|
||||
console.error(data)
|
||||
break;
|
||||
case "customDomInfo": // 窗口大小发生变化,视频播放时均会触发
|
||||
// data.customDomId 为每一个小窗口的自定义dom的id
|
||||
// data.width 为当前窗口的宽度
|
||||
// data.height 为当前窗口的高度
|
||||
// data.currentWindowPlaying 当前窗口是否正在播放视频
|
||||
// 根据上述内容 进行水印的添加,或其他操作
|
||||
break;
|
||||
// data.customDomId 为每一个小窗口的自定义dom的id
|
||||
// data.width 为当前窗口的宽度
|
||||
// data.height 为当前窗口的高度
|
||||
// data.currentWindowPlaying 当前窗口是否正在播放视频
|
||||
// 根据上述内容 进行水印的添加,或其他操作
|
||||
break;
|
||||
case "chromeMemoryOut":
|
||||
console.warn("浏览器资源不足!")
|
||||
break;
|
||||
@@ -660,7 +660,7 @@ new PlayerManager({
|
||||
case 'localRecordFile': // 本地录像停止时返回Blob数据
|
||||
break;
|
||||
case "notifyTalk": // 点击顶部对讲按钮,触发此回调
|
||||
// 当采用 realByUrl 进行实时预览时,点击顶部对讲按钮,会触发此回调,需要在此回调内 获取对讲rtsp发起对讲
|
||||
// 当采用 realByUrl 进行实时预览时,点击顶部对讲按钮,会触发此回调,需要在此回调内 获取对讲rtsp发起对讲
|
||||
case "switchStartTime":
|
||||
// 在调用 recordByUrl 中配置 playRecordByTime: false 后, 每次拖拽都会触发此回调,此回调需要重新获取rtsp拉流(不支持直接拖拽跳转的设备需要重新拉流,走此回调)
|
||||
break;
|
||||
|
||||
@@ -51,8 +51,7 @@ async function init(list: any) {
|
||||
channelIdList: list
|
||||
})
|
||||
if (cameraCode != 0) throw new Error()
|
||||
if (channelList == null || channelList.length == 0) throw new Error()
|
||||
channel.playList = channelList
|
||||
channel.playList = channelList ?? []
|
||||
initVideo()
|
||||
}
|
||||
} catch (error: any) {
|
||||
@@ -67,7 +66,7 @@ function initVideo() {
|
||||
realPlayer = new PlayerManager({
|
||||
el: "ws-real-player" /** 实时预览容器id,创建多个播放器,传入不同的容器id即可 **/,
|
||||
type: "real" /** real - 实时预览 record - 录像回放 **/,
|
||||
maxNum: 25 /** 一个播放器上限能播放的路数,可根据实际情况设置,支持 1 4 9 16 25 **/,
|
||||
maxNum: 16 /** 一个播放器上限能播放的路数,可根据实际情况设置,支持 1 4 9 16 25 **/,
|
||||
num: videoState.videoNum /** 初始化,页面显示的路数 **/,
|
||||
showControl: true /** 是否显示工具栏,默认显示 **/,
|
||||
prefixUrl: "lib" /** 解码库所在位置的前缀 **/,
|
||||
@@ -160,6 +159,7 @@ function destroy() {
|
||||
realPlayer.close(index)
|
||||
}
|
||||
}
|
||||
realPlayer.destroy()
|
||||
realPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ function initVideo(channelCode?: string) {
|
||||
realPlayer = new PlayerManager({
|
||||
el: "ws-real-player" /** 实时预览容器id,创建多个播放器,传入不同的容器id即可 **/,
|
||||
type: "real" /** real - 实时预览 record - 录像回放 **/,
|
||||
maxNum: 25 /** 一个播放器上限能播放的路数,可根据实际情况设置,支持 1 4 9 16 25 **/,
|
||||
maxNum: 16 /** 一个播放器上限能播放的路数,可根据实际情况设置,支持 1 4 9 16 25 **/,
|
||||
num: state.videoNum /** 初始化,页面显示的路数 **/,
|
||||
showControl: true /** 是否显示工具栏,默认显示 **/,
|
||||
prefixUrl: "lib" /** 解码库所在位置的前缀 **/,
|
||||
@@ -250,6 +250,7 @@ function destroy() {
|
||||
realPlayer.close(index)
|
||||
}
|
||||
}
|
||||
realPlayer.destroy()
|
||||
realPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ onUnmounted(() => {
|
||||
// 初始化播放器
|
||||
const init = (dataList: any, queryForm: any) => {
|
||||
destroy()
|
||||
if (!dataList || !dataList.length) return
|
||||
state.queryForm = queryForm
|
||||
if (dataList && dataList.length) {
|
||||
state.channelList = dataList
|
||||
@@ -50,7 +49,6 @@ const init = (dataList: any, queryForm: any) => {
|
||||
state.startTimestamp = dateRange.startTimestamp
|
||||
state.endTimestamp = dateRange.endTimestamp
|
||||
}
|
||||
|
||||
state.currentNum = findSuitableNum(state.channelList.length, state.numList)
|
||||
|
||||
replayVideo = new PlayerManager({
|
||||
@@ -159,6 +157,7 @@ function destroy() {
|
||||
replayVideo.close(index)
|
||||
}
|
||||
}
|
||||
replayVideo.destroy()
|
||||
replayVideo = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -314,6 +314,7 @@ function destroy() {
|
||||
replayVideo.close(index)
|
||||
}
|
||||
}
|
||||
replayVideo.destroy()
|
||||
replayVideo = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,8 @@ const onSubmit = async () => {
|
||||
const _form: any = { ...form }
|
||||
if (_form.panelViewCodes && _form.panelViewCodes.length) {
|
||||
_form.panelViewCodes = _form.panelViewCodes.join(',')
|
||||
} else {
|
||||
_form.panelViewCodes = ""
|
||||
}
|
||||
form.id ? await deviceGroupApi.putObj(_form) : await deviceGroupApi.addObj(_form);
|
||||
useMessage().success(form.id ? '修改成功' : '添加成功');
|
||||
|
||||
@@ -49,6 +49,13 @@
|
||||
<dict-tag :options="device_group_type" :value="row.bizType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="panelViewCodes" width="450" label="大屏预览分组">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center gap-2">
|
||||
<dict-tag v-for="v in row.panelViewCodes?.split(',')" :options="panel_type" :value="v" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" label="排序" />
|
||||
<el-table-column label="操作" width="210">
|
||||
<template #default="{ row }">
|
||||
|
||||
@@ -51,12 +51,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="previewTab">
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import * as deviceGroupApi from "/@/api/device/deviceGroup";
|
||||
import { useMessage } from "/@/hooks/message";
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
|
||||
import * as DeviceCameraApi from "/@/api/device/deviceCamera"
|
||||
import * as DeviceChannelApi from "/@/api/device/deviceChannel"
|
||||
|
||||
// 引入组件
|
||||
@@ -152,11 +149,9 @@ const getDataList = async () => {
|
||||
...state.replayForm,
|
||||
deviceChannelCodeList: state.channelCodeList
|
||||
})
|
||||
if (data && data.length) {
|
||||
state.dataList = data
|
||||
if (replayVideoRef.value) {
|
||||
replayVideoRef.value.init(state.dataList, state.replayForm)
|
||||
}
|
||||
state.dataList = data ?? []
|
||||
if (replayVideoRef.value) {
|
||||
replayVideoRef.value.init(state.dataList, state.replayForm)
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("获取回放列表错误", error);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
placeholder="请选择报警类型" />
|
||||
</el-form-item>
|
||||
<el-form-item style="width: 350px;" label="抓拍时间" prop="swingTimeList">
|
||||
<el-date-picker v-model="state.queryForm.swingTimeList" value-format="YYYY-MM-DD"
|
||||
<el-date-picker v-model="state.queryForm.swingTimeList" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
<dict-select v-model="state.queryForm.openType" :options="dh_door_open_type" placeholder="请选择进开门类型" />
|
||||
</el-form-item>
|
||||
<el-form-item style="width: 350px;" label="抓拍时间" prop="swingTimeList">
|
||||
<el-date-picker v-model="state.queryForm.swingTimeList" value-format="YYYY-MM-DD" type="daterange" />
|
||||
<el-date-picker v-model="state.queryForm.swingTimeList" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="search" type="primary" @click="getDataList">
|
||||
|
||||
@@ -1,20 +1,42 @@
|
||||
<!-- 视频预览 -->
|
||||
<template>
|
||||
<div class="w-full h-full pt-[10px]">
|
||||
<div class="w-full h-full flex flex-col pt-[10px]">
|
||||
<com-title title="监控预览">
|
||||
<select-device-group v-model="refreshForm.dutyId" autoFirst style="width: 250px;" />
|
||||
</com-title>
|
||||
<div class="h-[10px]" />
|
||||
<preview-video ref="previewVideoRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="videoPay">
|
||||
import * as deviceChannelApi from "/@/api/device/deviceChannel"
|
||||
|
||||
const comTitle = defineAsyncComponent(() => import('./com-title.vue'));
|
||||
const PreviewVideo = defineAsyncComponent(() => import("../../../device/components/preview-video/index.vue"));
|
||||
|
||||
const refreshForm = reactive<any>({
|
||||
dutyId: ""
|
||||
})
|
||||
|
||||
const previewVideoRef = ref<any>(null)
|
||||
|
||||
watch(
|
||||
() => refreshForm.dutyId,
|
||||
() => {
|
||||
refreshVideo()
|
||||
}
|
||||
)
|
||||
|
||||
const refreshVideo = async () => {
|
||||
const { code, data } = await deviceChannelApi.list({
|
||||
groupId: refreshForm.dutyId
|
||||
})
|
||||
if (code != 0) return
|
||||
const channelCode = data?.map((v: any) => v.channelCode) ?? []
|
||||
previewVideoRef.value.init(channelCode)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -12,7 +12,7 @@
|
||||
:options="car_alarm_type" multiple placeholder="请选择进开门类型" />
|
||||
</el-form-item>
|
||||
<el-form-item style="width: 350px;" label="抓拍时间" prop="capTimeList">
|
||||
<el-date-picker v-model="state.queryForm.capTimeList" value-format="YYYY-MM-DD"
|
||||
<el-date-picker v-model="state.queryForm.capTimeList" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
:options="door_alarm_type" multiple placeholder="请选择报警类型" />
|
||||
</el-form-item>
|
||||
<el-form-item style="width: 350px;" label="抓拍时间" prop="swingTimeList">
|
||||
<el-date-picker v-model="state.queryForm.swingTimeList" value-format="YYYY-MM-DD"
|
||||
<el-date-picker v-model="state.queryForm.swingTimeList" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
||||
Reference in new issue
Block a user