Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
AI_VUE2_Ruoyi
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lei
AI_VUE2_Ruoyi
Commits
e48297f3
Commit
e48297f3
authored
Jun 30, 2025
by
lei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add:xiugai
parent
2cf53cfe
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
157 additions
and
4341 deletions
+157
-4341
.env.production
.env.production
+2
-1
adapter.min.js
public/video/adapter.min.js
+0
-3514
text.html
public/video/text.html
+0
-27
webrtcstreamer.js
public/video/webrtcstreamer.js
+0
-370
home.js
src/api/business/home.js
+8
-0
index.vue
src/components/ImageUpload/index.vue
+1
-1
videoPlay.vue
src/components/VideoPlay/videoPlay.vue
+0
-381
index.vue
src/views/Screen/index.vue
+62
-10
addVideoAnlysisTasks.vue
...views/VideoAnalysisTasks/modules/addVideoAnlysisTasks.vue
+16
-17
index.vue
src/views/index.vue
+68
-20
No files found.
.env.production
View file @
e48297f3
...
...
@@ -6,4 +6,5 @@ ENV = 'production'
# 若依管理系统/生产环境
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/'
public/video/adapter.min.js
deleted
100644 → 0
View file @
2cf53cfe
This source diff could not be displayed because it is too large. You can
view the blob
instead.
public/video/text.html
deleted
100644 → 0
View file @
2cf53cfe
<!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>
public/video/webrtcstreamer.js
deleted
100644 → 0
View file @
2cf53cfe
var
WebRtcStreamer
=
(
function
()
{
/**
* Interface with WebRTC-streamer API
* @constructor
* @param {string} videoElement - id of the video element tag
* @param {string} srvurl - url of webrtc-streamer (default is current location)
*/
var
WebRtcStreamer
=
function
WebRtcStreamer
(
videoElement
,
srvurl
)
{
if
(
typeof
videoElement
===
"
string
"
)
{
this
.
videoElement
=
document
.
getElementById
(
videoElement
);
}
else
{
this
.
videoElement
=
videoElement
;
}
this
.
srvurl
=
srvurl
||
location
.
protocol
+
"
//
"
+
window
.
location
.
hostname
+
"
:
"
+
window
.
location
.
port
;
this
.
pc
=
null
;
this
.
mediaConstraints
=
{
offerToReceiveAudio
:
true
,
offerToReceiveVideo
:
true
};
this
.
iceServers
=
null
;
this
.
earlyCandidates
=
[];
}
WebRtcStreamer
.
prototype
.
_handleHttpErrors
=
function
(
response
)
{
if
(
!
response
.
ok
)
{
throw
Error
(
response
.
statusText
);
}
return
response
;
}
/**
* Connect a WebRTC Stream to videoElement
* @param {string} videourl - id of WebRTC video stream
* @param {string} audiourl - id of WebRTC audio stream
* @param {string} options - options of WebRTC call
* @param {string} stream - local stream to send
* @param {string} prefmime - prefered mime
*/
WebRtcStreamer
.
prototype
.
connect
=
function
(
videourl
,
audiourl
,
options
,
localstream
,
prefmime
)
{
this
.
disconnect
();
// getIceServers is not already received
if
(
!
this
.
iceServers
)
{
console
.
log
(
"
Get IceServers
"
);
fetch
(
this
.
srvurl
+
"
/api/getIceServers
"
)
.
then
(
this
.
_handleHttpErrors
)
.
then
(
(
response
)
=>
(
response
.
json
())
)
.
then
(
(
response
)
=>
this
.
onReceiveGetIceServers
(
response
,
videourl
,
audiourl
,
options
,
localstream
,
prefmime
))
.
catch
(
(
error
)
=>
this
.
onError
(
"
getIceServers
"
+
error
))
}
else
{
this
.
onReceiveGetIceServers
(
this
.
iceServers
,
videourl
,
audiourl
,
options
,
localstream
,
prefmime
);
}
}
/**
* Disconnect a WebRTC Stream and clear videoElement source
*/
WebRtcStreamer
.
prototype
.
disconnect
=
function
()
{
if
(
this
.
videoElement
?.
srcObject
)
{
this
.
videoElement
.
srcObject
.
getTracks
().
forEach
(
track
=>
{
track
.
stop
()
this
.
videoElement
.
srcObject
.
removeTrack
(
track
);
});
}
if
(
this
.
pc
)
{
fetch
(
this
.
srvurl
+
"
/api/hangup?peerid=
"
+
this
.
pc
.
peerid
)
.
then
(
this
.
_handleHttpErrors
)
.
catch
(
(
error
)
=>
this
.
onError
(
"
hangup
"
+
error
))
try
{
this
.
pc
.
close
();
}
catch
(
e
)
{
console
.
log
(
"
Failure close peer connection:
"
+
e
);
}
this
.
pc
=
null
;
}
}
WebRtcStreamer
.
prototype
.
filterPreferredCodec
=
function
(
sdp
,
prefmime
)
{
const
lines
=
sdp
.
split
(
'
\n
'
);
const
[
prefkind
,
prefcodec
]
=
prefmime
.
toLowerCase
().
split
(
'
/
'
);
let
currentMediaType
=
null
;
let
sdpSections
=
[];
let
currentSection
=
[];
// Group lines into sections
lines
.
forEach
(
line
=>
{
if
(
line
.
startsWith
(
'
m=
'
))
{
if
(
currentSection
.
length
)
{
sdpSections
.
push
(
currentSection
);
}
currentSection
=
[
line
];
}
else
{
currentSection
.
push
(
line
);
}
});
sdpSections
.
push
(
currentSection
);
// Process each section
const
processedSections
=
sdpSections
.
map
(
section
=>
{
const
firstLine
=
section
[
0
];
if
(
!
firstLine
.
startsWith
(
'
m=
'
+
prefkind
))
{
return
section
.
join
(
'
\n
'
);
}
// Get payload types for preferred codec
const
rtpLines
=
section
.
filter
(
line
=>
line
.
startsWith
(
'
a=rtpmap:
'
));
const
preferredPayloads
=
rtpLines
.
filter
(
line
=>
line
.
toLowerCase
().
includes
(
prefcodec
))
.
map
(
line
=>
line
.
split
(
'
:
'
)[
1
].
split
(
'
'
)[
0
]);
if
(
preferredPayloads
.
length
===
0
)
{
return
section
.
join
(
'
\n
'
);
}
// Modify m= line to only include preferred payloads
const
mLine
=
firstLine
.
split
(
'
'
);
const
newMLine
=
[...
mLine
.
slice
(
0
,
3
),
...
preferredPayloads
].
join
(
'
'
);
// Filter related attributes
const
filteredLines
=
section
.
filter
(
line
=>
{
if
(
line
===
firstLine
)
return
false
;
if
(
line
.
startsWith
(
'
a=rtpmap:
'
))
{
return
preferredPayloads
.
some
(
payload
=>
line
.
startsWith
(
`a=rtpmap:
${
payload
}
`
));
}
if
(
line
.
startsWith
(
'
a=fmtp:
'
)
||
line
.
startsWith
(
'
a=rtcp-fb:
'
))
{
return
preferredPayloads
.
some
(
payload
=>
line
.
startsWith
(
`a=
${
line
.
split
(
'
:
'
)[
0
].
split
(
'
a=
'
)[
1
]}
:
${
payload
}
`
));
}
return
true
;
});
return
[
newMLine
,
...
filteredLines
].
join
(
'
\n
'
);
});
return
processedSections
.
join
(
'
\n
'
);
}
/*
* GetIceServers callback
*/
WebRtcStreamer
.
prototype
.
onReceiveGetIceServers
=
function
(
iceServers
,
videourl
,
audiourl
,
options
,
stream
,
prefmime
)
{
this
.
iceServers
=
iceServers
;
this
.
pcConfig
=
iceServers
||
{
"
iceServers
"
:
[]
};
try
{
this
.
createPeerConnection
();
let
callurl
=
this
.
srvurl
+
"
/api/call?peerid=
"
+
this
.
pc
.
peerid
+
"
&url=
"
+
encodeURIComponent
(
videourl
);
if
(
audiourl
)
{
callurl
+=
"
&audiourl=
"
+
encodeURIComponent
(
audiourl
);
}
if
(
options
)
{
callurl
+=
"
&options=
"
+
encodeURIComponent
(
options
);
}
if
(
stream
)
{
this
.
pc
.
addStream
(
stream
);
}
// clear early candidates
this
.
earlyCandidates
.
length
=
0
;
// create Offer
this
.
pc
.
createOffer
(
this
.
mediaConstraints
).
then
((
sessionDescription
)
=>
{
console
.
log
(
"
Create offer:
"
+
JSON
.
stringify
(
sessionDescription
));
console
.
log
(
`video codecs:
${
Array
.
from
(
new
Set
(
RTCRtpReceiver
.
getCapabilities
(
"
video
"
)?.
codecs
?.
map
(
codec
=>
codec
.
mimeType
)))}
`)
console.log(`
audio
codecs
:
$
{
Array
.
from
(
new
Set
(
RTCRtpReceiver
.
getCapabilities
(
"
audio
"
)?.
codecs
?.
map
(
codec
=>
codec
.
mimeType
)))}
`)
if (prefmime != undefined) {
//set prefered codec
let [prefkind] = prefmime.split('/');
if (prefkind != "video" && prefkind != "audio") {
prefkind = "video";
prefmime = prefkind + "/" + prefmime;
}
console.log("sdp:" + sessionDescription.sdp);
sessionDescription.sdp = this.filterPreferredCodec(sessionDescription.sdp, prefmime);
console.log("sdp:" + sessionDescription.sdp);
}
this.pc.setLocalDescription(sessionDescription)
.then(() => {
fetch(callurl, { method: "POST", body: JSON.stringify(sessionDescription) })
.then(this._handleHttpErrors)
.then( (response) => (response.json()) )
.catch( (error) => this.onError("call " + error ))
.then( (response) => this.onReceiveCall(response) )
.catch( (error) => this.onError("call " + error ))
}, (error) => {
console.log ("setLocalDescription error:" + JSON.stringify(error));
});
}, (error) => {
alert("Create offer error:" + JSON.stringify(error));
});
} catch (e) {
this.disconnect();
alert("connect error: " + e);
}
}
WebRtcStreamer.prototype.getIceCandidate = function() {
fetch(this.srvurl + "/api/getIceCandidate?peerid=" + this.pc.peerid)
.then(this._handleHttpErrors)
.then( (response) => (response.json()) )
.then( (response) => this.onReceiveCandidate(response))
.catch( (error) => this.onError("getIceCandidate " + error ))
}
/*
* create RTCPeerConnection
*/
WebRtcStreamer.prototype.createPeerConnection = function() {
console.log("createPeerConnection config: " + JSON.stringify(this.pcConfig));
this.pc = new RTCPeerConnection(this.pcConfig);
let pc = this.pc;
pc.peerid = Math.random();
pc.onicecandidate = (evt) => this.onIceCandidate(evt);
pc.onaddstream = (evt) => this.onAddStream(evt);
pc.oniceconnectionstatechange = (evt) => {
console.log("oniceconnectionstatechange state: " + pc.iceConnectionState);
if (this.videoElement) {
if (pc.iceConnectionState === "connected") {
this.videoElement.style.opacity = "1.0";
}
else if (pc.iceConnectionState === "disconnected") {
this.videoElement.style.opacity = "0.25";
}
else if ( (pc.iceConnectionState === "failed") || (pc.iceConnectionState === "closed") ) {
this.videoElement.style.opacity = "0.5";
} else if (pc.iceConnectionState === "new") {
this.getIceCandidate();
}
}
}
pc.ondatachannel = function(evt) {
console.log("remote datachannel created:"+JSON.stringify(evt));
evt.channel.onopen = function () {
console.log("remote datachannel open");
this.send("remote channel openned");
}
evt.channel.onmessage = function (event) {
console.log("remote datachannel recv:"+JSON.stringify(event.data));
}
}
try {
let dataChannel = pc.createDataChannel("ClientDataChannel");
dataChannel.onopen = function() {
console.log("local datachannel open");
this.send("local channel openned");
}
dataChannel.onmessage = function(evt) {
console.log("local datachannel recv:"+JSON.stringify(evt.data));
}
} catch (e) {
console.log("Cannor create datachannel error: " + e);
}
console.log("Created RTCPeerConnnection with config: " + JSON.stringify(this.pcConfig) );
return pc;
}
/*
* RTCPeerConnection IceCandidate callback
*/
WebRtcStreamer.prototype.onIceCandidate = function (event) {
if (event.candidate) {
if (this.pc.currentRemoteDescription) {
this.addIceCandidate(this.pc.peerid, event.candidate);
} else {
this.earlyCandidates.push(event.candidate);
}
}
else {
console.log("End of candidates.");
}
}
WebRtcStreamer.prototype.addIceCandidate = function(peerid, candidate) {
fetch(this.srvurl + "/api/addIceCandidate?peerid="+peerid, { method: "POST", body: JSON.stringify(candidate) })
.then(this._handleHttpErrors)
.then( (response) => (response.json()) )
.then( (response) => {console.log("addIceCandidate ok:" + response)})
.catch( (error) => this.onError("addIceCandidate " + error ))
}
/*
* RTCPeerConnection AddTrack callback
*/
WebRtcStreamer.prototype.onAddStream = function(event) {
console.log("Remote track added:" + JSON.stringify(event));
this.videoElement.srcObject = event.stream;
let promise = this.videoElement.play();
if (promise !== undefined) {
promise.catch((error) => {
console.warn("error:"+error);
this.videoElement.setAttribute("controls", true);
});
}
}
/*
* AJAX /call callback
*/
WebRtcStreamer.prototype.onReceiveCall = function(dataJson) {
console.log("offer: " + JSON.stringify(dataJson));
let descr = new RTCSessionDescription(dataJson);
this.pc.setRemoteDescription(descr).then(() => {
console.log ("setRemoteDescription ok");
while (this.earlyCandidates.length) {
let candidate = this.earlyCandidates.shift();
this.addIceCandidate(this.pc.peerid, candidate);
}
this.getIceCandidate()
}
, (error) => {
console.log ("setRemoteDescription error:" + JSON.stringify(error));
});
}
/*
* AJAX /getIceCandidate callback
*/
WebRtcStreamer.prototype.onReceiveCandidate = function(dataJson) {
console.log("candidate: " + JSON.stringify(dataJson));
if (dataJson) {
for (let i=0; i<dataJson.length; i++) {
let candidate = new RTCIceCandidate(dataJson[i]);
console.log("Adding ICE candidate :" + JSON.stringify(candidate) );
this.pc.addIceCandidate(candidate).then( () => { console.log ("addIceCandidate OK"); }
, (error) => { console.log ("addIceCandidate error:" + JSON.stringify(error)); } );
}
this.pc.addIceCandidate();
}
}
/*
* AJAX callback for Error
*/
WebRtcStreamer.prototype.onError = function(status) {
console.log("onError:" + status);
}
return WebRtcStreamer;
})();
if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
window.WebRtcStreamer = WebRtcStreamer;
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = WebRtcStreamer;
}
src/api/business/home.js
View file @
e48297f3
...
...
@@ -38,4 +38,12 @@ export function getVideoPlayUrl(query) {
url
:
'
/system/cameraConfig/getPlayUrl?cameraId=
'
+
query
.
cameraId
,
method
:
'
get
'
,
})
}
//获取摄像头带有算法的视频播放地址
export
function
getVideoPlayUrlWithAlgorithm
(
query
)
{
return
request
({
url
:
'
/system/task/listByCameraId
'
,
method
:
'
get
'
,
})
}
\ No newline at end of file
src/components/ImageUpload/index.vue
View file @
e48297f3
...
...
@@ -176,7 +176,7 @@ export default {
// 上传成功回调
handleUploadSuccess
(
res
,
file
)
{
if
(
res
.
code
===
200
)
{
this
.
uploadList
.
push
({
name
:
res
.
fileName
,
url
:
res
.
url
});
this
.
uploadList
.
push
({
name
:
res
.
fileName
,
url
:
res
.
fileName
});
this
.
uploadedSuccessfully
();
}
else
{
this
.
number
--
;
...
...
src/components/VideoPlay/videoPlay.vue
deleted
100644 → 0
View file @
2cf53cfe
<
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
>
src/views/Screen/index.vue
View file @
e48297f3
...
...
@@ -69,6 +69,17 @@
:value=
"item"
></el-option>
</el-select>
-->
<el-cascader
v-model=
"selectVidoe"
@
change=
"handleCascaderChange"
:options=
"videoList"
:props=
"
{
value: 'value',
label: 'label',
children: 'children',
}"
clearable
>
</el-cascader>
</div>
<!--
<VideoPlay
:videoID=
"'video'"
...
...
@@ -78,7 +89,7 @@
></VideoPlay>
-->
<div
class=
"video-box"
ref=
"videoContainer"
>
<iframe
:src=
"
selectVidoe.ifarme.url
"
:src=
"
iframeSrc
"
:style=
"
{
width: width + 'px',
height: height + 'px',
...
...
@@ -156,23 +167,23 @@
<
script
>
import
PieChartScreen
from
"
../dashboard/PieChartScreen.vue
"
;
import
LineChartScreen
from
"
../dashboard/LineChartScreen.vue
"
;
import
VideoPlay
from
"
@/components/VideoPlay/videoPlay.vue
"
;
import
{
getCameraList
}
from
"
@/api/business/cameraconfig.js
"
;
import
{
getCameraOnlineData
,
getVideoAnalysisOnlineData
,
getStatisticsData
,
getAlarmStatisticsData
,
getVideoPlayUrlWithAlgorithm
,
}
from
"
@/api/business/home.js
"
;
import
{
getAlarmLogList
}
from
"
@/api/business/alarmlog.js
"
;
export
default
{
dicts
:
[
"
algorithm_level
"
],
name
:
"
Screen
"
,
props
:
{},
components
:
{
PieChartScreen
,
VideoPlay
,
LineChartScreen
},
components
:
{
PieChartScreen
,
LineChartScreen
},
data
()
{
return
{
selectVidoe
:
{}
,
// 选择视频
selectVidoe
:
[]
,
// 选择视频
videoList
:
[],
webRtcServer
:
null
,
//webRtcServer上下文
videoShow
:
false
,
//视频是否显示
...
...
@@ -193,6 +204,8 @@ export default {
width
:
0
,
height
:
0
,
resizeObserver
:
null
,
iframeSrc
:
""
,
// iframe的src
iframeUrl
:
process
.
env
.
VUE_APP_IFRAME_URL
,
// iframe的src
};
},
computed
:
{},
...
...
@@ -244,12 +257,33 @@ export default {
await
Promise
.
all
([
getCameraList
().
then
((
res
)
=>
{
if
(
res
.
code
!==
200
)
return
;
this
.
videoList
=
res
.
rows
.
map
((
item
)
=>
({
id
:
item
.
cameraId
,
name
:
`
${
item
.
cameraName
}
-
${
item
.
cameraPosition
}
`
,
url
:
item
.
cameraAddress
,
// 在数据转换时保留原始字段
this
.
videoList
=
res
.
rows
.
map
((
camera
)
=>
({
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
;
}),
...
...
@@ -307,7 +341,25 @@ export default {
this
.
$router
.
push
({
path
:
"
/index
"
});
},
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
]}
`
;
}
},
},
};
...
...
src/views/VideoAnalysisTasks/modules/addVideoAnlysisTasks.vue
View file @
e48297f3
...
...
@@ -372,23 +372,22 @@ export default {
},
// 修改后的复选框点击方法
handleCheckboxChange
(
item
)
{
const
index
=
this
.
checkAnalysisList
.
findIndex
(
(
i
)
=>
i
.
algorithmId
===
item
.
algorithmId
);
if
(
index
>
-
1
)
{
this
.
checkAnalysisList
.
splice
(
index
,
1
);
}
else
{
// 新增时初始化摄像头列表
this
.
checkAnalysisList
.
push
({
...
item
,
checkCameraList
:
[],
});
this
.
selectedAlgorithmIndex
=
this
.
checkAnalysisList
.
length
-
1
;
// 将清空操作移到else内部
this
.
$nextTick
(()
=>
{
this
.
$refs
.
cameraTable
.
clearSelection
();
});
}
// 清空原有选择(单选逻辑)
this
.
checkAnalysisList
=
[];
// 添加当前选中项
this
.
checkAnalysisList
.
push
({
...
item
,
checkCameraList
:
[],
});
// 更新选中索引
this
.
selectedAlgorithmIndex
=
0
;
// 清空摄像头选择
this
.
$nextTick
(()
=>
{
this
.
$refs
.
cameraTable
.
clearSelection
();
});
},
// 摄像头选择
cameraChange
(
val
)
{
...
...
src/views/index.vue
View file @
e48297f3
...
...
@@ -36,18 +36,25 @@
<el-col
:span=
"18"
>
<div
class=
"status-container"
>
<h3
class=
"status-title both-end"
>
<span
><span>
{{
selectVidoe
.
name
}}
</span
><span>
正在查看
</span></span
<span>
<template
v-if=
"selectVidoe.length === 2"
>
<span>
{{
cameraName
}}
的
{{
algorithmName
}}
</span>
</
template
>
<
template
v-else
>
<span>
请选择摄像头和算法
</span>
</
template
></span
>
<el-select
v-model=
"selectVidoe"
value-key=
"id"
placeholder=
""
>
<el-option
v-for=
"item in videoList"
:key=
"item.id"
:label=
"item.name"
:value=
"item"
></el-option>
</el-select>
<el-cascader
v-model=
"selectVidoe"
@
change=
"handleCascaderChange"
:options=
"videoList"
:props=
"{
value: 'value',
label: 'label',
children: 'children',
}"
clearable
></el-cascader>
</h3>
<div
class=
"video-box"
ref=
"videoContainer"
>
<iframe
...
...
@@ -180,11 +187,11 @@
<
script
>
import
PieChart
from
"
./dashboard/PieChart.vue
"
;
import
LineChart
from
"
./dashboard/LineChart.vue
"
;
import
{
getCameraList
}
from
"
@/api/business/cameraconfig.js
"
;
import
{
getCameraOnlineData
,
getVideoAnalysisOnlineData
,
getStatisticsData
,
getVideoPlayUrlWithAlgorithm
,
}
from
"
@/api/business/home.js
"
;
import
{
getAlarmLogList
}
from
"
@/api/business/alarmlog.js
"
;
export
default
{
...
...
@@ -193,7 +200,7 @@ export default {
components
:
{
PieChart
,
LineChart
},
data
()
{
return
{
selectVidoe
:
{}
,
// 选择视频
selectVidoe
:
[]
,
// 选择视频
videoList
:
[],
webRtcServer
:
null
,
//webRtcServer上下文
videoShow
:
false
,
//视频是否显示
...
...
@@ -210,10 +217,11 @@ export default {
dialogVisible
:
false
,
currentAlarm
:
{},
lookBackVideo
:
0
,
// 0-图片 1-视频
iframeSrc
:
"
http://192.168.2.22:5000/view/17/42
"
,
// 根据实际路径修改
iframeSrc
:
""
,
// 根据实际路径修改
width
:
0
,
height
:
0
,
resizeObserver
:
null
,
iframeUrl
:
process
.
env
.
VUE_APP_IFRAME_URL
,
};
},
created
()
{
...
...
@@ -237,14 +245,36 @@ export default {
async
init
()
{
// 使用Promise.all等待所有请求完成
await
Promise
.
all
([
get
CameraList
().
then
((
res
)
=>
{
get
VideoPlayUrlWithAlgorithm
().
then
((
res
)
=>
{
if
(
res
.
code
!==
200
)
return
;
this
.
videoList
=
res
.
rows
.
map
((
item
)
=>
({
id
:
item
.
cameraId
,
name
:
`
${
item
.
cameraName
}
-
${
item
.
cameraPosition
}
`
,
url
:
item
.
cameraAddress
,
// 在数据转换时保留原始字段
this
.
videoList
=
res
.
rows
.
map
((
camera
)
=>
({
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
;
}),
...
...
@@ -303,6 +333,24 @@ export default {
playBack
()
{
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
()
{
this
.
$nextTick
(()
=>
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment