Commit e48297f3 authored by lei's avatar lei

add:xiugai

parent 2cf53cfe
...@@ -6,4 +6,5 @@ ENV = 'production' ...@@ -6,4 +6,5 @@ ENV = 'production'
# 若依管理系统/生产环境 # 若依管理系统/生产环境
VUE_APP_BASE_API = '/prod-api' VUE_APP_BASE_API = '/prod-api'
VUE_APP_WS_URL = '/ws-api' VUE_APP_WS_URL = 'ws://192.168.3.248:8081'
VUE_APP_IFRAME_URL = 'http://192.168.3.248:5000/'
This source diff could not be displayed because it is too large. You can view the blob instead.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="text/javascript" src="./adapter.min.js"></script>
<script type="text/javascript" src="./webrtcstreamer.js"></script>
</head>
<script>
window.onload = function () {
this.webRtcServer = new WebRtcStreamer("video","http://127.0.0.1:8000/");
webRtcServer.connect(
"rtsp://admin:Gemho120611@192.168.0.15:554/h264/ch1/main/av_stream","rtptransport=tcp&timeout=60"
);
};
window.onbeforeunload = function () {
this.webRtcServer.disconnect();
};
</script>
</head>
<body>
<video id="video" muted playsinline controls></video>
</body>
</html>
This diff is collapsed.
...@@ -39,3 +39,11 @@ export function getVideoPlayUrl(query) { ...@@ -39,3 +39,11 @@ export function getVideoPlayUrl(query) {
method: 'get', method: 'get',
}) })
} }
//获取摄像头带有算法的视频播放地址
export function getVideoPlayUrlWithAlgorithm(query) {
return request({
url: '/system/task/listByCameraId',
method: 'get',
})
}
\ No newline at end of file
...@@ -176,7 +176,7 @@ export default { ...@@ -176,7 +176,7 @@ export default {
// 上传成功回调 // 上传成功回调
handleUploadSuccess(res, file) { handleUploadSuccess(res, file) {
if (res.code === 200) { if (res.code === 200) {
this.uploadList.push({ name: res.fileName, url: res.url }); this.uploadList.push({ name: res.fileName, url: res.fileName });
this.uploadedSuccessfully(); this.uploadedSuccessfully();
} else { } else {
this.number--; this.number--;
......
<template>
<!-- <map-video :showV="videoShow" :rtspIp="rtspIp"></map-video> -->
<video
:id="videoID"
class="video-js"
style="object-fit: fill"
controls
autoplay
autobuffer
muted
preload="auto"
></video>
</template>
<script>
import "video.js/dist/video-js.css";
import videojs from "video.js";
export default {
name: "TanchengkjWebDialogCom",
props: {
videoID: {
type: String,
default() {
return "videoID";
},
},
rtspIp: {
type: String,
default() {
return "";
},
},
videoShow: {
type: Boolean,
default() {
return false;
},
},
videoPlayName: {
type: String,
default() {
return "";
},
},
},
data() {
return {
dialogFromVisible: this.videoShow,
inDate: "",
t2: null,
getUrl: "http://127.0.0.1:8000",
player: null,
webRtcServer: null,
webRtcList: [],
playerList: [],
videoSeting: {
language: "zh-CN",
autoplay: true, // true/false 播放器准备好之后,是否自动播放 【默认false】
controls: true, // /false 是否拥有控制条 【默认true】,如果设为false ,那么只能通过api进行控制了。也就是说界面上不会出现任何控制按钮
/* height: 100, // 视频容器的高度,字符串或数字 单位像素 比如: height:300 or height:‘300px‘
width: 100, // 视频容器的宽度, 字符串或数字 单位像素*/
loop: false, // /false 视频播放结束后,是否循环播放
muted: true, // /false 是否静音
poster: "", // 播放前显示的视频画面,播放开始之后自动移除。通常传入一个URL
preload: "auto", // 预加载 ‘auto‘ 自动 ’metadata‘ 元数据信息 ,比如视频长度,尺寸等 ‘none‘ 不预加载任何数据,直到用户开始播放才开始下载
bigPlayButton: true,
},
};
},
watch: {
videoShow: {
immediate: false,
handler: function (value) {
this.dialogFromVisible = value;
if (value == false) {
console.log("视频关闭了!");
// this.playerList[0].pause();
// this.webRtcList[0].webRtcServer.disconnect();
} else {
this.$forceUpdate();
console.log("输出一下rtsp:", this.rtspIp);
setTimeout(() => {
this.getWebRtc();
}, 1000);
}
},
},
height: {
immediate: false,
handler: function (value) {
this.$forceUpdate();
},
},
},
mounted() {
let that = this;
this.initNDate();
let procedure1 = new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("1执行crtWebRtc成功!");
that.crtWebRtc();
resolve();
});
});
let procedure2 = new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("2执行getvideo成功!");
that.getVideo();
resolve();
});
});
let procedure3 = new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("3执行getWebRtc成功!");
that.getWebRtc();
resolve();
});
});
procedure1
.then((data) => {
return procedure2;
})
.then((data) => {
return procedure3;
});
console.log("mounted输出rtspip:", this.rtspIp);
// console.log("mounted输出videoID:", this.videoID);
// console.log("mounted输出getUrl:", this.getUrl);
},
created() {},
methods: {
/*设置当前系统时间*/
initNDate: function () {
this.t2 = setInterval(() => {
this.inDate = new Date().toLocaleString();
}, 1000);
},
getVideo() {
let that = this;
this.playerList[0] = videojs(
this.videoID,
this.videoSeting,
function onPlayerReady() {
videojs.log("Your player is ready!");
this.on("loadstart", function () {
console.log("开始请求数据 ");
});
this.on("progress", function () {
console.log("正在请求数据 ");
});
this.on("loadedmetadata", function () {
console.log("获取资源长度完成 ");
});
this.on("canplaythrough", function () {
console.log("视频源数据加载完成");
});
this.on("waiting", function () {
console.log("等待数据");
});
this.on("play", function () {
console.log("视频开始播放");
// that.getWebRtc();
});
this.on("playing", function () {
console.log("视频播放中");
});
this.on("pause", function () {
console.log("视频暂停播放");
that.webRtcList[0].webRtcServer.disconnect();
});
this.on("ended", function () {
console.log("视频播放结束");
});
this.on("error", function () {
console.log("加载错误");
});
this.on("seeking", function () {
console.log("视频跳转中");
});
this.on("seeked", function () {
console.log("视频跳转结束");
});
this.on("ratechange", function () {
console.log("播放速率改变");
});
this.on("timeupdate", function () {
console.log("播放时长改变");
});
this.on("volumechange", function () {
console.log("音量改变");
});
this.on("stalled", function () {
console.log("网速异常");
});
}
);
this.playerList.push(this.player);
console.log("playerList", this.playerList);
console.log("id_", this.playerList[0].id_);
},
crtWebRtc() {
console.log("webRtcList:", this.webRtcList);
for (const item of this.webRtcList) {
if (this.videoID == item.name) {
return;
}
}
console.log("进来了开始初始化webRtc模块:", this.videoID);
this.webRtcServer = new WebRtcStreamer(
this.videoID,
// "http://192.168.1.166:8000"
this.getUrl
);
let s = {};
s.name = this.videoID;
s.webRtcServer = this.webRtcServer;
this.webRtcList.push(s);
console.log("this.webrtc哈", this.webRtcList);
},
getWebRtc() {
console.log("将rtspip传递给webRtcServer.connect:", this.rtspIp);
console.log("打印:webrtclist", this.webRtcList);
this.webRtcList[0].webRtcServer.connect(this.rtspIp, this.rtspIp);
// for (const item of this.webRtcList) {
// if (this.videoID == item.name) {
// return;
// }
// item.webRtcServer.connect(this.rtspIp);
// }
},
},
beforeDestroy() {
console.log("运行销毁前生命周期事件");
this.webRtcList[0].webRtcServer.disconnect();
if (this.player) {
this.playerList[0].dispose();
}
},
};
</script>
<style scoped>
.lf20 {
margin-left: 20px;
}
/* // 覆盖层元素增加可穿透点击事件 */
.el-dialog__wrapper {
pointer-events: none;
}
/* // 弹窗层元素不可穿透点击事件(不影响弹窗层元素的点击事件) */
.el-dialog {
pointer-events: auto;
}
.el-dialog__title {
line-height: 24px !important;
font-size: 15px !important;
color: #303133;
}
.el-dialog__header {
padding: 5px 5px 0px 5px !important;
text-align: left;
}
.el-dialog__headerbtn {
position: absolute;
top: 5px !important;
right: 5px !important;
padding: 0;
background: 0 0;
border: none;
outline: 0;
cursor: pointer;
font-size: 16px;
}
.el-dialog__body {
padding: 2px !important;
color: #606266;
font-size: 14px;
word-break: break-all;
height: 40vh;
overflow-y: auto;
}
.el-divider--horizontal {
display: block;
height: 1px;
width: 100%;
margin: 0px 0 !important;
}
.el-menu:hover {
opacity: 1 !important;
}
.ve-line {
margin-left: 10px;
padding-top: 20px;
color: #fff4fd;
width: 540px !important;
}
.el-row {
margin-bottom: 2px;
&:last-child {
margin-bottom: 0;
}
}
.el-col {
border-radius: 4px;
}
.bg-purple-dark {
background: #99a9bf;
}
.bg-purple {
background: #d3dce6;
}
.bg-purple-light {
background: #e5e9f2;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
height: 230px;
}
.row-bg {
background-color: #f9fafc;
}
.cell-v {
display: flex;
flex-direction: column;
height: 30vh;
}
.player {
height: 100%;
}
.bk-button-group {
color: #00a0e9;
}
.video-js {
width: 100%;
height: 100%;
}
.video-js .vjs-big-play-button {
top: 50%;
left: 50%;
margin-left: -1.5em;
margin-top: -1em;
}
.vjs-loading-spinner:before,
.vjs-loading-spinner:after {
content: "";
position: absolute;
margin: -6px;
-webkit-box-sizing: inherit;
box-sizing: inherit;
width: inherit;
height: inherit;
border-radius: inherit;
opacity: 1;
border: inherit;
border-color: transparent;
border-top-color: white;
display: none;
}
</style>
...@@ -69,6 +69,17 @@ ...@@ -69,6 +69,17 @@
:value="item" :value="item"
></el-option> ></el-option>
</el-select> --> </el-select> -->
<el-cascader
v-model="selectVidoe"
@change="handleCascaderChange"
:options="videoList"
:props="{
value: 'value',
label: 'label',
children: 'children',
}"
clearable
></el-cascader>
</div> </div>
<!-- <VideoPlay <!-- <VideoPlay
:videoID="'video'" :videoID="'video'"
...@@ -78,7 +89,7 @@ ...@@ -78,7 +89,7 @@
></VideoPlay> --> ></VideoPlay> -->
<div class="video-box" ref="videoContainer"> <div class="video-box" ref="videoContainer">
<iframe <iframe
:src="selectVidoe.ifarme.url" :src="iframeSrc"
:style="{ :style="{
width: width + 'px', width: width + 'px',
height: height + 'px', height: height + 'px',
...@@ -156,23 +167,23 @@ ...@@ -156,23 +167,23 @@
<script> <script>
import PieChartScreen from "../dashboard/PieChartScreen.vue"; import PieChartScreen from "../dashboard/PieChartScreen.vue";
import LineChartScreen from "../dashboard/LineChartScreen.vue"; import LineChartScreen from "../dashboard/LineChartScreen.vue";
import VideoPlay from "@/components/VideoPlay/videoPlay.vue";
import { getCameraList } from "@/api/business/cameraconfig.js"; import { getCameraList } from "@/api/business/cameraconfig.js";
import { import {
getCameraOnlineData, getCameraOnlineData,
getVideoAnalysisOnlineData, getVideoAnalysisOnlineData,
getStatisticsData, getStatisticsData,
getAlarmStatisticsData, getAlarmStatisticsData,
getVideoPlayUrlWithAlgorithm,
} from "@/api/business/home.js"; } from "@/api/business/home.js";
import { getAlarmLogList } from "@/api/business/alarmlog.js"; import { getAlarmLogList } from "@/api/business/alarmlog.js";
export default { export default {
dicts: ["algorithm_level"], dicts: ["algorithm_level"],
name: "Screen", name: "Screen",
props: {}, props: {},
components: { PieChartScreen, VideoPlay, LineChartScreen }, components: { PieChartScreen, LineChartScreen },
data() { data() {
return { return {
selectVidoe: {}, // 选择视频 selectVidoe: [], // 选择视频
videoList: [], videoList: [],
webRtcServer: null, //webRtcServer上下文 webRtcServer: null, //webRtcServer上下文
videoShow: false, //视频是否显示 videoShow: false, //视频是否显示
...@@ -193,6 +204,8 @@ export default { ...@@ -193,6 +204,8 @@ export default {
width: 0, width: 0,
height: 0, height: 0,
resizeObserver: null, resizeObserver: null,
iframeSrc: "", // iframe的src
iframeUrl: process.env.VUE_APP_IFRAME_URL, // iframe的src
}; };
}, },
computed: {}, computed: {},
...@@ -244,12 +257,33 @@ export default { ...@@ -244,12 +257,33 @@ export default {
await Promise.all([ await Promise.all([
getCameraList().then((res) => { getCameraList().then((res) => {
if (res.code !== 200) return; if (res.code !== 200) return;
this.videoList = res.rows.map((item) => ({ // 在数据转换时保留原始字段
id: item.cameraId, this.videoList = res.rows.map((camera) => ({
name: `${item.cameraName}-${item.cameraPosition}`, value: camera.cameraId,
url: item.cameraAddress, label: camera.cameraName, // 这里保持摄像头名称
children: [
// 新增预览选项
{ value: "preview", label: "原始画面" },
// 原有算法列表
...camera.algorithmVo.map((algorithm) => ({
value: algorithm.algorithmId,
label: algorithm.algorithmName,
})),
],
})); }));
this.selectVidoe = this.videoList[0]; // 设置默认选中第一个摄像头的第一个算法
if (
this.videoList.length > 0 &&
this.videoList[0].children?.length > 0
) {
this.selectVidoe = [
this.videoList[0].value,
this.videoList[0].children[0].value,
];
this.cameraName = this.videoList[0].label; // 摄像头名称
this.algorithmName = this.videoList[0].children[0].label; // 算法名称
this.iframeSrc = `${this.iframeUrl}/view/${this.videoList[0].value}/${this.videoList[0].children[0].value}`;
}
this.videoShow = true; this.videoShow = true;
}), }),
...@@ -307,7 +341,25 @@ export default { ...@@ -307,7 +341,25 @@ export default {
this.$router.push({ path: "/index" }); this.$router.push({ path: "/index" });
}, },
lookDetails() { lookDetails() {
console.log("查看详情"); this.$router.push({ path: "/alarmlog" });
},
handleCascaderChange(value) {
console.log(value);
if (value.length === 2) {
this.cameraName = this.videoList.find(
(item) => item.value === value[0]
).label; // 摄像头名称
this.videoList.forEach((alg) => {
if (alg.value === value[0]) {
alg.children.forEach((item) => {
if (item.value === value[1]) {
this.algorithmName = item.label; // 摄像头名称
}
});
}
});
this.iframeSrc = `${this.iframeUrl}/view/${value[0]}/${value[1]}`;
}
}, },
}, },
}; };
......
...@@ -372,23 +372,22 @@ export default { ...@@ -372,23 +372,22 @@ export default {
}, },
// 修改后的复选框点击方法 // 修改后的复选框点击方法
handleCheckboxChange(item) { handleCheckboxChange(item) {
const index = this.checkAnalysisList.findIndex( // 清空原有选择(单选逻辑)
(i) => i.algorithmId === item.algorithmId this.checkAnalysisList = [];
);
if (index > -1) { // 添加当前选中项
this.checkAnalysisList.splice(index, 1);
} else {
// 新增时初始化摄像头列表
this.checkAnalysisList.push({ this.checkAnalysisList.push({
...item, ...item,
checkCameraList: [], checkCameraList: [],
}); });
this.selectedAlgorithmIndex = this.checkAnalysisList.length - 1;
// 将清空操作移到else内部 // 更新选中索引
this.selectedAlgorithmIndex = 0;
// 清空摄像头选择
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.cameraTable.clearSelection(); this.$refs.cameraTable.clearSelection();
}); });
}
}, },
// 摄像头选择 // 摄像头选择
cameraChange(val) { cameraChange(val) {
......
...@@ -36,18 +36,25 @@ ...@@ -36,18 +36,25 @@
<el-col :span="18"> <el-col :span="18">
<div class="status-container"> <div class="status-container">
<h3 class="status-title both-end"> <h3 class="status-title both-end">
<span <span>
><span>{{ selectVidoe.name }}</span <template v-if="selectVidoe.length === 2">
><span>正在查看</span></span <span>{{ cameraName }}{{ algorithmName }}</span>
</template>
<template v-else>
<span>请选择摄像头和算法</span>
</template></span
> >
<el-select v-model="selectVidoe" value-key="id" placeholder=""> <el-cascader
<el-option v-model="selectVidoe"
v-for="item in videoList" @change="handleCascaderChange"
:key="item.id" :options="videoList"
:label="item.name" :props="{
:value="item" value: 'value',
></el-option> label: 'label',
</el-select> children: 'children',
}"
clearable
></el-cascader>
</h3> </h3>
<div class="video-box" ref="videoContainer"> <div class="video-box" ref="videoContainer">
<iframe <iframe
...@@ -180,11 +187,11 @@ ...@@ -180,11 +187,11 @@
<script> <script>
import PieChart from "./dashboard/PieChart.vue"; import PieChart from "./dashboard/PieChart.vue";
import LineChart from "./dashboard/LineChart.vue"; import LineChart from "./dashboard/LineChart.vue";
import { getCameraList } from "@/api/business/cameraconfig.js";
import { import {
getCameraOnlineData, getCameraOnlineData,
getVideoAnalysisOnlineData, getVideoAnalysisOnlineData,
getStatisticsData, getStatisticsData,
getVideoPlayUrlWithAlgorithm,
} from "@/api/business/home.js"; } from "@/api/business/home.js";
import { getAlarmLogList } from "@/api/business/alarmlog.js"; import { getAlarmLogList } from "@/api/business/alarmlog.js";
export default { export default {
...@@ -193,7 +200,7 @@ export default { ...@@ -193,7 +200,7 @@ export default {
components: { PieChart, LineChart }, components: { PieChart, LineChart },
data() { data() {
return { return {
selectVidoe: {}, // 选择视频 selectVidoe: [], // 选择视频
videoList: [], videoList: [],
webRtcServer: null, //webRtcServer上下文 webRtcServer: null, //webRtcServer上下文
videoShow: false, //视频是否显示 videoShow: false, //视频是否显示
...@@ -210,10 +217,11 @@ export default { ...@@ -210,10 +217,11 @@ export default {
dialogVisible: false, dialogVisible: false,
currentAlarm: {}, currentAlarm: {},
lookBackVideo: 0, // 0-图片 1-视频 lookBackVideo: 0, // 0-图片 1-视频
iframeSrc: "http://192.168.2.22:5000/view/17/42", // 根据实际路径修改 iframeSrc: "", // 根据实际路径修改
width: 0, width: 0,
height: 0, height: 0,
resizeObserver: null, resizeObserver: null,
iframeUrl: process.env.VUE_APP_IFRAME_URL,
}; };
}, },
created() { created() {
...@@ -237,14 +245,36 @@ export default { ...@@ -237,14 +245,36 @@ export default {
async init() { async init() {
// 使用Promise.all等待所有请求完成 // 使用Promise.all等待所有请求完成
await Promise.all([ await Promise.all([
getCameraList().then((res) => { getVideoPlayUrlWithAlgorithm().then((res) => {
if (res.code !== 200) return; if (res.code !== 200) return;
this.videoList = res.rows.map((item) => ({
id: item.cameraId, // 在数据转换时保留原始字段
name: `${item.cameraName}-${item.cameraPosition}`, this.videoList = res.rows.map((camera) => ({
url: item.cameraAddress, value: camera.cameraId,
label: camera.cameraName, // 这里保持摄像头名称
children: [
// 新增预览选项
{ value: "preview", label: "原始画面" },
// 原有算法列表
...camera.algorithmVo.map((algorithm) => ({
value: algorithm.algorithmId,
label: algorithm.algorithmName,
})),
],
})); }));
this.selectVidoe = this.videoList[0]; // 设置默认选中第一个摄像头的第一个算法
if (
this.videoList.length > 0 &&
this.videoList[0].children?.length > 0
) {
this.selectVidoe = [
this.videoList[0].value,
this.videoList[0].children[0].value,
];
this.cameraName = this.videoList[0].label; // 摄像头名称
this.algorithmName = this.videoList[0].children[0].label; // 算法名称
this.iframeSrc = `${this.iframeUrl}/view/${this.videoList[0].value}/${this.videoList[0].children[0].value}`;
}
this.videoShow = true; this.videoShow = true;
}), }),
...@@ -303,6 +333,24 @@ export default { ...@@ -303,6 +333,24 @@ export default {
playBack() { playBack() {
this.lookBackVideo = this.lookBackVideo === 0 ? 1 : 0; this.lookBackVideo = this.lookBackVideo === 0 ? 1 : 0;
}, },
handleCascaderChange(value) {
console.log(value);
if (value.length === 2) {
this.cameraName = this.videoList.find(
(item) => item.value === value[0]
).label; // 摄像头名称
this.videoList.forEach((alg) => {
if (alg.value === value[0]) {
alg.children.forEach((item) => {
if (item.value === value[1]) {
this.algorithmName = item.label; // 摄像头名称
}
});
}
});
this.iframeSrc = `${this.iframeUrl}/view/${value[0]}/${value[1]}`;
}
},
}, },
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment