Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
K
kd_control
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
zhanglw
kd_control
Commits
0a54817f
Commit
0a54817f
authored
Jun 29, 2023
by
zhanglw
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
安全帽sip语音通信
parent
33f3923a
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
937 additions
and
12 deletions
+937
-12
.env.development
.env.development
+6
-6
package.json
package.json
+2
-0
common.js
src/assets/js/common.js
+16
-1
AppMain.vue
src/layout/components/AppMain.vue
+14
-3
dialView.vue
src/layout/components/dialView.vue
+502
-0
dialView.vue
src/views/personnelPositioning/peopleLogData/dialView.vue
+355
-0
index.vue
src/views/personnelPositioning/peopleLogData/index.vue
+42
-2
No files found.
.env.development
View file @
0a54817f
...
...
@@ -5,14 +5,14 @@ ENV = 'development'
#VUE_APP_BASE_API = 'http://39.164.225.220:5002'
#VUE_APP_LOCAL_API = 'http://39.164.225.220:5002'
VUE_APP_BASE_API = 'http://192.168.3.23:9092'
VUE_APP_LOCAL_API = 'http://192.168.3.23:9092'
#
VUE_APP_BASE_API = 'http://192.168.3.23:9092'
#
VUE_APP_LOCAL_API = 'http://192.168.3.23:9092'
#
VUE_APP_BASE_API = 'http://192.168.3.216:9092'
#
VUE_APP_LOCAL_API = 'http://192.168.3.216:9092'
VUE_APP_BASE_API = 'http://192.168.3.216:9092'
VUE_APP_LOCAL_API = 'http://192.168.3.216:9092'
VUE_APP_LOCAL_API2 = 'http://
8.143.203.103:9091
/'
VUE_APP_WS_API = 'ws://
8.143.203.103
:9092/webSocket'
VUE_APP_LOCAL_API2 = 'http://
192.168.3.216:9092
/'
VUE_APP_WS_API = 'ws://
192.168.3.216
:9092/webSocket'
# 是否启用 babel-plugin-dynamic-import-node插件
VUE_CLI_BABEL_TRANSPILE_MODULES = true
package.json
View file @
0a54817f
...
...
@@ -48,10 +48,12 @@
"
file-saver
"
:
"
1.3.8
"
,
"
fuse.js
"
:
"
3.4.4
"
,
"
hls.js
"
:
"
^1.0.12
"
,
"
html2canvas
"
:
"
^1.4.1
"
,
"
jquery
"
:
"
^3.6.0
"
,
"
js-beautify
"
:
"
^1.10.2
"
,
"
js-cookie
"
:
"
2.2.0
"
,
"
jsencrypt
"
:
"
^3.0.0-rc.1
"
,
"
jssip
"
:
"
^3.10.0
"
,
"
jswebrtc
"
:
"
^1.0.0
"
,
"
jszip
"
:
"
3.1.5
"
,
"
mars3d
"
:
"
^3.1.3
"
,
...
...
src/assets/js/common.js
View file @
0a54817f
...
...
@@ -3000,6 +3000,22 @@ var HttpReq = function(){
responseType
:
'
blob
'
})
},
//获取安全帽拨号通话sip相关信息
propleGetSipInfo
:
function
(
param
){
return
request
({
url
:
'
/tab/perequipment/getdevicemsg
'
,
method
:
'
get
'
,
params
:
param
,
})
},
//获取安全帽SOS通话sip相关信息
propleGetSOSSipInfo
:
function
(
param
){
return
request
({
url
:
'
/tab/perequipment/getdeviceroomid
'
,
method
:
'
get
'
,
params
:
param
,
})
},
propleGetHisout
:
function
(
param
){
return
request
({
url
:
'
/tab/perhis/hisout
'
,
...
...
@@ -3150,7 +3166,6 @@ var HttpReq = function(){
},
...
...
src/layout/components/AppMain.vue
View file @
0a54817f
<
template
>
<section
class=
"app-main"
>
<dial-view
ref=
"dialView"
/>
<transition
name=
"fade-transform"
mode=
"out-in"
>
<keep-alive
:include=
"cachedViews"
>
<router-view
:key=
"key"
/>
...
...
@@ -12,14 +13,16 @@
</div>
-->
<!--
<div
class=
"page-inline"
>
</div>
-->
</section>
</
template
>
<
script
>
import
dialView
from
"
./dialView
"
;
export
default
{
name
:
'
AppMain
'
,
components
:
{
dialView
},
computed
:
{
cachedViews
()
{
return
this
.
$store
.
state
.
tagsView
.
cachedViews
...
...
@@ -27,7 +30,15 @@ export default {
key
()
{
return
this
.
$route
.
path
}
}
},
mounted
()
{
this
.
$nextTick
(()
=>
{
this
.
$refs
.
dialView
.
init
()
// setTimeout(()=>{
// this.$refs.dialView.init('123456')
// },5000)
})
},
}
</
script
>
...
...
@@ -52,7 +63,7 @@ export default {
.hasTagsView
{
.app-main
{
/* 84 = navbar + tags-view = 50 + 34
/* 84 = navbar + tags-view = 50 + 34
min-height: calc(100vh - 84px);*/
}
...
...
src/layout/components/dialView.vue
0 → 100644
View file @
0a54817f
<
template
>
<!-- 表单渲染 -->
<div
ref=
"dragArea"
v-show=
"visible"
class=
"fixed-View"
:class=
"isMousedown?'grabbing':'grab'"
>
<div
class=
"fixed-View-subTitle"
>
安全帽SOS请求通话:
</div>
<div
v-show=
"status"
class=
"corrugation"
>
<span
style=
"--d: 7"
></span>
<span
style=
"--d: 6"
></span>
<span
style=
"--d: 5"
></span>
<span
style=
"--d: 4"
></span>
<span
style=
"--d: 3"
></span>
<span
style=
"--d: 2"
></span>
<span
style=
"--d: 1"
></span>
<span
style=
"--d: 0"
></span>
<span
style=
"--d: 1"
></span>
<span
style=
"--d: 2"
></span>
<span
style=
"--d: 3"
></span>
<span
style=
"--d: 4"
></span>
<span
style=
"--d: 5"
></span>
<span
style=
"--d: 6"
></span>
<span
style=
"--d: 7"
></span>
</div>
<div
v-show=
"!status"
class=
"corrugation-s"
>
<span
style=
"--d: 7"
></span>
<span
style=
"--d: 6"
></span>
<span
style=
"--d: 5"
></span>
<span
style=
"--d: 4"
></span>
<span
style=
"--d: 3"
></span>
<span
style=
"--d: 2"
></span>
<span
style=
"--d: 1"
></span>
<span
style=
"--d: 0"
></span>
<span
style=
"--d: 1"
></span>
<span
style=
"--d: 2"
></span>
<span
style=
"--d: 3"
></span>
<span
style=
"--d: 4"
></span>
<span
style=
"--d: 5"
></span>
<span
style=
"--d: 6"
></span>
<span
style=
"--d: 7"
></span>
</div>
<div
style=
"text-align: center"
>
<i
v-if=
"status"
class=
"el-icon-phone-outline el-icon--left"
/>
<i
v-else
class=
"el-icon-phone el-icon--left"
/>
{{
message
}}
</div>
<audio
id=
"audioElement"
></audio>
<audio
id=
"localVideo"
></audio>
<div
class=
"fixed-footer"
style=
"text-align: center"
>
<el-button
type=
"success"
style=
"width:120px;font-size:20px"
@
click=
"uaCall"
>
接听
<i
class=
"el-icon-video-play el-icon--right"
></i></el-button>
<el-button
type=
"danger"
style=
"width:120px;font-size:20px"
@
click=
"uaHangup"
>
挂断
<i
class=
"el-icon-video-pause el-icon--right"
></i></el-button>
<el-button
style=
"width:120px;font-size:20px"
@
click=
"cancelView"
>
关闭
<i
class=
"el-icon-circle-close el-icon--right"
></i></el-button>
</div>
</div>
</
template
>
<
script
>
import
{
HttpReq
}
from
'
@/assets/js/common.js
'
;
import
JsSIP
from
'
jssip
'
export
default
{
data
()
{
return
{
isMousedown
:
false
,
visible
:
false
,
title
:
'
安全帽SOS请求通话
'
,
userAgent
:
null
,
session
:
null
,
uaSipInfo
:
null
,
callSipId
:
null
,
status
:
0
,
isReady
:
false
,
message
:
'
正在建立链接,等待服务器响应...
'
,
sosDialTimer
:
null
}
},
mounted
()
{
this
.
$nextTick
(()
=>
{
// 获取DOM元素
const
dragArea
=
this
.
$refs
.
dragArea
// 缓存 clientX clientY 的对象: 用于判断是点击事件还是移动事件
const
clientOffset
=
{}
dragArea
.
addEventListener
(
'
mousedown
'
,
(
event
)
=>
{
this
.
isMousedown
=
true
// const offsetX = dragArea.getBoundingClientRect().left // 获取当前的x轴距离
const
offsetY
=
dragArea
.
getBoundingClientRect
().
top
// 获取当前的y轴距离
// const innerX = event.clientX - offsetX // 获取鼠标在方块内的x轴距
const
innerY
=
event
.
clientY
-
offsetY
// 获取鼠标在方块内的y轴距
// 缓存 clientX clientY
clientOffset
.
clientX
=
event
.
clientX
clientOffset
.
clientY
=
event
.
clientY
document
.
onmousemove
=
(
event
)
=>
{
// dragArea.style.left = event.clientX - innerX + 'px'
dragArea
.
style
.
top
=
event
.
clientY
-
innerY
+
'
px
'
const
dragAreaTop
=
window
.
innerHeight
-
dragArea
.
getBoundingClientRect
().
height
// const dragAreaLeft = window.innerWidth - dragArea.getBoundingClientRect().width - 160
// if (dragArea.getBoundingClientRect().left
<=
0
)
{
// dragArea.style.left = '0px'
// }
// if (dragArea.getBoundingClientRect().left >= dragAreaLeft) {
// dragArea.style.left = dragAreaLeft + 'px'
// }
if
(
dragArea
.
getBoundingClientRect
().
top
<=
100
)
{
dragArea
.
style
.
top
=
'
100px
'
}
if
(
dragArea
.
getBoundingClientRect
().
top
>=
dragAreaTop
)
{
dragArea
.
style
.
top
=
dragAreaTop
+
'
px
'
}
}
document
.
onmouseup
=
()
=>
{
document
.
onmousemove
=
null
document
.
onmouseup
=
null
this
.
isMousedown
=
false
}
},
false
)
// 绑定鼠标松开事件
dragArea
.
addEventListener
(
'
mouseup
'
,
(
event
)
=>
{
// const clientX = event.clientX
// const clientY = event.clientY
// if (clientX === clientOffset.clientX && clientY === clientOffset.clientY) {
// console.log('click 事件')
// } else {
// console.log('drag 事件')
// }
})
})
},
methods
:
{
uaRegister
()
{
let
sip_uri_
=
`sip:
${
this
.
uaSipInfo
.
adminsip_id
}
@
${
this
.
uaSipInfo
.
adminwsip_host
}
`
;
let
sip_password_
=
`
${
this
.
uaSipInfo
.
adminsip_pwd
}
`
;
let
ws_uri_
=
`
${
this
.
uaSipInfo
.
adminwss_url
}
`
;
console
.
info
(
"
get input info: sip_uri =
"
,
sip_uri_
,
"
sip_password =
"
,
sip_password_
,
"
ws_uri =
"
,
ws_uri_
);
let
socket
=
new
JsSIP
.
WebSocketInterface
(
ws_uri_
);
let
configuration
=
{
sockets
:
[
socket
],
uri
:
sip_uri_
,
password
:
sip_password_
,
session_timers
:
false
,
// 启用会话计时器(根据RFC 4028)
user_agent
:
"
Aegis WebRTC v1.0
"
,
contact_uri
:
sip_uri_
,
autostart
:
true
,
// 自动连接
register
:
true
,
// 自动就绪
};
this
.
userAgent
=
new
JsSIP
.
UA
(
configuration
);
this
.
userAgent
.
on
(
"
connecting
"
,
(
args
)
=>
{
this
.
message
=
`开始尝试连接...`
;
console
.
info
(
"
开始尝试连接
"
,
args
);
});
this
.
userAgent
.
on
(
'
registered
'
,
(
data
)
=>
{
console
.
info
(
"
registered:
"
,
data
.
response
.
status_code
,
"
,
"
,
data
.
response
.
reason_phrase
);
this
.
message
=
`监测到安全帽SOS通话请求,请接听...`
;
this
.
isReady
=
true
});
this
.
userAgent
.
on
(
'
registrationFailed
'
,
(
data
)
=>
{
console
.
log
(
"
registrationFailed,
"
,
data
);
});
this
.
userAgent
.
on
(
'
registrationExpiring
'
,
()
=>
{
console
.
warn
(
"
registrationExpiring
"
);
});
this
.
userAgent
.
on
(
'
newRTCSession
'
,
(
e
)
=>
{
this
.
message
=
`注意:您有新的
${
e
.
originator
===
"
local
"
?
"
外呼
"
:
"
来电
"
}
`
;
console
.
log
(
`新的
${
e
.
originator
===
"
local
"
?
"
外呼
"
:
"
来电
"
}
`
,
e
);
const
session
=
e
.
session
;
this
.
session
=
session
;
const
peerconnection
=
session
.
connection
;
if
(
e
.
originator
===
"
local
"
)
{
// 打电话
peerconnection
.
addEventListener
(
"
addstream
"
,
(
event
)
=>
{
const
audio
=
document
.
getElementById
(
"
audioElement
"
);
audio
.
srcObject
=
event
.
stream
;
});
}
else
{
document
.
getElementById
(
"
localVideo
"
).
play
();
// 接电话
this
.
dialogVisible
=
true
;
this
.
isg
=
true
;
this
.
callers
=
session
.
remote_identity
.
uri
.
user
;
}
// 接通,在这一步可以处理音频播放
// 接通并不代表对方已经接受,接通代表 滴 滴 滴
session
.
on
(
"
confirmed
"
,
()
=>
{
console
.
info
(
"
接通中
"
);
this
.
message
=
`已接通,请通话...`
;
this
.
status
=
1
;
const
audioElement
=
document
.
getElementById
(
"
audioElement
"
);
audioElement
.
autoplay
=
true
;
const
stream
=
new
MediaStream
();
const
receivers
=
session
.
connection
.
getReceivers
();
if
(
receivers
)
{
receivers
.
forEach
((
receiver
)
=>
stream
.
addTrack
(
receiver
.
track
));
}
audioElement
.
srcObject
=
stream
;
audioElement
.
play
();
});
// 接听失败
session
.
on
(
"
failed
"
,
(
mdata
)
=>
{
const
myAuto
=
document
.
getElementById
(
"
localVideo
"
);
myAuto
.
pause
();
myAuto
.
load
();
this
.
message
=
`来电的时拒接或,未接听对方就挂断...`
;
console
.
info
(
"
来电的时候 拒接或者 还没接听对方自己就挂断了
"
);
});
// 接听成功
session
.
on
(
"
accepted
"
,
(
response
,
cause
)
=>
{
// 嘟嘟嘟
this
.
message
=
`接听成功...`
;
this
.
status
=
1
;
console
.
info
(
"
接听成功
"
);
});
// 接听成功后 挂断
session
.
on
(
"
ended
"
,
()
=>
{
this
.
dialogVisible
=
false
;
this
.
InCall
=
false
;
});
// 通话被挂起
session
.
on
(
"
hold
"
,
(
data
)
=>
{
const
org
=
data
.
originator
;
if
(
org
===
"
local
"
)
{
this
.
message
=
`通话被本地挂起...`
;
console
.
log
(
"
通话被本地挂起:
"
,
org
);
}
else
{
this
.
message
=
`通话被对方挂起...`
;
console
.
log
(
"
通话被对方挂起:
"
,
org
);
}
});
// 通话被继续
session
.
on
(
"
unhold
"
,
(
data
)
=>
{
const
org
=
data
.
originator
;
if
(
org
===
"
local
"
)
{
}
else
{
this
.
message
=
`对方要求继续通话...`
;
console
.
log
(
"
对方要求继续通话:
"
,
org
);
}
});
});
this
.
userAgent
.
on
(
'
newMessage
'
,
(
data
)
=>
{
if
(
data
.
originator
==
'
local
'
)
{
console
.
info
(
'
onNewMessage , OutgoingRequest -
'
,
data
.
request
);
}
else
{
console
.
info
(
'
onNewMessage , IncomingRequest -
'
,
data
.
request
);
}
});
console
.
info
(
"
call register
"
);
this
.
userAgent
.
start
();
},
uaCall
()
{
if
(
this
.
isReady
||
this
.
userAgent
)
{
let
sip_phone_number_
=
`sip:
${
this
.
uaSipInfo
.
room_id
}
@
${
this
.
uaSipInfo
.
adminwsip_host
}
`
;
let
options
=
{
'
pcConfig
'
:
{
'
rtcpMuxPolicy
'
:
"
negotiate
"
,
},
'
rtcOfferConstraints
'
:
{
'
offerToReceiveAudio
'
:
'
1
'
,
'
offerToReceiveVideo
'
:
'
0
'
,
},
'
eventHandlers
'
:
{
'
progress
'
:
(
e
)
=>
{
console
.
log
(
'
call is in progress
'
);
},
'
failed
'
:
(
e
)
=>
{
console
.
log
(
'
call failed:
'
,
e
);
},
'
ended
'
:
(
e
)
=>
{
console
.
log
(
'
call ended :
'
,
e
);
console
.
log
(
'
通话结束
'
);
this
.
message
=
`通话结束...`
this
.
status
=
0
this
.
isReady
=
false
},
'
confirmed
'
:
(
e
)
=>
{
console
.
log
(
'
call confirmed
'
);
}
},
'
mediaConstraints
'
:
{
'
audio
'
:
true
,
'
video
'
:
false
,
},
};
this
.
userAgent
.
call
(
sip_phone_number_
,
options
);
}
else
{
this
.
$message
({
message
:
"
尚未建立链接无法拨号通话,请确保链接通畅且对方在线!
"
,
type
:
'
error
'
});
}
},
uaHangup
()
{
if
(
this
.
isReady
||
this
.
userAgent
)
{
this
.
isReady
=
false
this
.
userAgent
.
terminateSessions
();
const
myAuto
=
document
.
getElementById
(
"
localVideo
"
);
myAuto
.
pause
();
myAuto
.
load
();
const
audioElement
=
document
.
getElementById
(
"
audioElement
"
);
audioElement
.
pause
();
audioElement
.
load
();
}
},
init
()
{
this
.
message
=
'
正在建立链接,等待服务器响应...
'
this
.
sosDialTimer
=
setInterval
(()
=>
{
if
(
this
.
isReady
)
{
return
}
HttpReq
.
truckDispatching
.
propleGetSOSSipInfo
({}).
then
((
res
)
=>
{
if
(
res
.
msg
)
{
this
.
$notify
({
title
:
res
.
msg
,
type
:
'
error
'
,
});
}
if
(
res
.
data
&&
res
.
data
.
room_id
)
{
this
.
uaSipInfo
=
res
.
data
this
.
showView
()
this
.
uaRegister
()
}
})
},
5000
)
},
showView
()
{
this
.
visible
=
true
},
hideView
()
{
this
.
visible
=
false
this
.
uaHangup
()
},
cancelView
()
{
this
.
hideView
()
}
},
beforeDestroy
()
{
this
.
hideView
()
if
(
this
.
sosDialTimer
)
{
clearInterval
(
this
.
sosDialTimer
);
this
.
sosDialTimer
=
null
;
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.touch
{
cursor
:
pointer
;
}
.grab
{
cursor
:
grab
;
}
.grabbing
{
cursor
:
grabbing
;
}
.fixed-View
{
position
:
fixed
;
margin-left
:
0
;
padding
:
10px
;
width
:
520px
;
height
:
226px
;
right
:
1vw
;
bottom
:
6vh
;
background
:
#FFFFFF
;
border
:
1px
solid
rgba
(
0
,
0
,
0
,
0
.8
);
box-shadow
:
1px
2px
8px
0
rgba
(
0
,
0
,
0
,
0
.8
);
border-radius
:
10px
;
font-weight
:
400
;
user-select
:
none
;
z-index
:
99
;
.cell-input
{
margin
:
5px
0
;
}
.fixed-footer
{
width
:
100%
;
padding
:
20px
;
}
.fixed-View-subTitle
{
color
:
#333
;
font-size
:
18px
;
padding-top
:
10px
;
padding-bottom
:
5px
;
}
.fixed-View-btn
{
padding
:
10px
;
width
:
100%
;
text-align
:
center
;
.btn
{
margin
:
auto
;
width
:
140px
;
padding
:
6px
;
background
:
#0156E5
;
border
:
1px
solid
rgba
(
0
,
0
,
0
,
0
.12
);
border-radius
:
5px
;
color
:
white
;
font-size
:
16px
;
opacity
:
0
.8
;
}
.btn
:hover
{
opacity
:
1
;
}
}
.fixed-View-title
{
text-align
:
center
;
color
:
#0342AB
;
font-size
:
20px
;
}
.fixed-View-location
{
height
:
38px
;
position
:
relative
;
color
:
#666
;
font-size
:
16px
;
img
{
position
:
absolute
;
top
:
9px
;
left
:
236px
;
}
div
{
position
:
absolute
;
top
:
12px
;
left
:
260px
;
}
}
}
.corrugation-s
{
height
:
80px
;
width
:
118px
;
margin
:
auto
;
display
:
flex
;
align-items
:
center
;
position
:
relative
;
}
.corrugation-s
span
{
background
:
linear-gradient
(
to
top
,
#d299c2
0%
,
#fef9d7
100%
);
width
:
4px
;
height
:
60%
;
border-radius
:
4px
;
margin-right
:
4px
;
}
.corrugation-s
span
:last-child
{
margin-right
:
0
;
}
.corrugation
{
height
:
80px
;
width
:
118px
;
margin
:
auto
;
display
:
flex
;
align-items
:
center
;
position
:
relative
;
}
.corrugation
span
{
background
:
linear-gradient
(
to
top
,
#d299c2
0%
,
#fef9d7
100%
);
width
:
4px
;
height
:
20%
;
border-radius
:
10px
;
margin-right
:
4px
;
animation
:
loading
2
.5s
infinite
linear
;
animation-delay
:
calc
(
0
.2s
*
var
(
--
d
));
}
.corrugation
span
:last-child
{
margin-right
:
0
;
}
@keyframes
loading
{
0
%
{
background-image
:
linear-gradient
(
to
right
,
#fa709a
0%
,
#fee140
100%
);
height
:
20%
;
border-radius
:
calc
(
var
(
--
h
)
*
0
.2
*
0
.5
);
}
50
%
{
background-image
:
linear-gradient
(
to
top
,
#d299c2
0%
,
#fef9d7
100%
);
height
:
100%
;
border-radius
:
calc
(
var
(
--
h
)
*
1
*
0
.5
);
}
100
%
{
background-image
:
linear-gradient
(
to
top
,
#a8edea
0%
,
#fed6e3
100%
);
height
:
20%
;
border-radius
:
calc
(
var
(
--
h
)
*
0
.2
*
0
.5
);
}
}
</
style
>
src/views/personnelPositioning/peopleLogData/dialView.vue
0 → 100644
View file @
0a54817f
<
template
>
<!-- 表单渲染 -->
<el-dialog
append-to-body
:close-on-click-modal=
"false"
destroy-on-close
:before-close=
"cancelView"
:visible=
"visible"
:title=
"title"
width=
"520px"
>
<div
v-show=
"status"
class=
"corrugation"
>
<span
style=
"--d: 7"
></span>
<span
style=
"--d: 6"
></span>
<span
style=
"--d: 5"
></span>
<span
style=
"--d: 4"
></span>
<span
style=
"--d: 3"
></span>
<span
style=
"--d: 2"
></span>
<span
style=
"--d: 1"
></span>
<span
style=
"--d: 0"
></span>
<span
style=
"--d: 1"
></span>
<span
style=
"--d: 2"
></span>
<span
style=
"--d: 3"
></span>
<span
style=
"--d: 4"
></span>
<span
style=
"--d: 5"
></span>
<span
style=
"--d: 6"
></span>
<span
style=
"--d: 7"
></span>
</div>
<div
v-show=
"!status"
class=
"corrugation-s"
>
<span
style=
"--d: 7"
></span>
<span
style=
"--d: 6"
></span>
<span
style=
"--d: 5"
></span>
<span
style=
"--d: 4"
></span>
<span
style=
"--d: 3"
></span>
<span
style=
"--d: 2"
></span>
<span
style=
"--d: 1"
></span>
<span
style=
"--d: 0"
></span>
<span
style=
"--d: 1"
></span>
<span
style=
"--d: 2"
></span>
<span
style=
"--d: 3"
></span>
<span
style=
"--d: 4"
></span>
<span
style=
"--d: 5"
></span>
<span
style=
"--d: 6"
></span>
<span
style=
"--d: 7"
></span>
</div>
<div
style=
"text-align: center"
>
<i
v-if=
"status"
class=
"el-icon-phone-outline el-icon--left"
/>
<i
v-else
class=
"el-icon-phone el-icon--left"
/>
{{
message
}}
</div>
<audio
id=
"audioElement"
></audio>
<audio
id=
"localVideo"
></audio>
<div
slot=
"footer"
class=
"dialog-footer"
style=
"text-align: center"
>
<el-button
type=
"success"
style=
"width:120px;font-size:20px"
@
click=
"uaCall"
>
拨号
<i
class=
"el-icon-video-play el-icon--right"
></i></el-button>
<el-button
type=
"danger"
style=
"width:120px;font-size:20px"
@
click=
"uaHangup"
>
挂断
<i
class=
"el-icon-video-pause el-icon--right"
></i></el-button>
<el-button
style=
"width:120px;font-size:20px"
@
click=
"cancelView"
>
关闭
<i
class=
"el-icon-circle-close el-icon--right"
></i></el-button>
</div>
</el-dialog>
</
template
>
<
script
>
import
{
HttpReq
}
from
'
@/assets/js/common.js
'
;
import
JsSIP
from
'
jssip
'
export
default
{
data
()
{
return
{
visible
:
false
,
title
:
'
安全帽语音通话
'
,
userAgent
:
null
,
session
:
null
,
uaSipInfo
:
{},
status
:
0
,
isReady
:
false
,
message
:
'
正在建立链接,等待服务器响应...
'
}
},
mounted
()
{
this
.
$nextTick
(()
=>
{
})
},
methods
:
{
uaRegister
()
{
let
sip_uri_
=
`sip:
${
this
.
uaSipInfo
.
adminsip_id
}
@
${
this
.
uaSipInfo
.
adminwsip_host
}
`
;
let
sip_password_
=
`
${
this
.
uaSipInfo
.
adminsip_pwd
}
`
;
let
ws_uri_
=
`
${
this
.
uaSipInfo
.
adminwss_url
}
`
;
console
.
info
(
"
get input info: sip_uri =
"
,
sip_uri_
,
"
sip_password =
"
,
sip_password_
,
"
ws_uri =
"
,
ws_uri_
);
let
socket
=
new
JsSIP
.
WebSocketInterface
(
ws_uri_
);
let
configuration
=
{
sockets
:
[
socket
],
uri
:
sip_uri_
,
password
:
sip_password_
,
session_timers
:
false
,
// 启用会话计时器(根据RFC 4028)
user_agent
:
"
Aegis WebRTC v1.0
"
,
contact_uri
:
sip_uri_
,
autostart
:
true
,
// 自动连接
register
:
true
,
// 自动就绪
};
this
.
userAgent
=
new
JsSIP
.
UA
(
configuration
);
this
.
userAgent
.
on
(
"
connecting
"
,
(
args
)
=>
{
this
.
message
=
`开始尝试连接...`
;
console
.
info
(
"
开始尝试连接
"
,
args
);
});
this
.
userAgent
.
on
(
'
registered
'
,
(
data
)
=>
{
console
.
info
(
"
registered:
"
,
data
.
response
.
status_code
,
"
,
"
,
data
.
response
.
reason_phrase
);
this
.
message
=
`已接通到服务器,监测到对方安全帽在线,请拨号...`
;
this
.
isReady
=
true
});
this
.
userAgent
.
on
(
'
registrationFailed
'
,
(
data
)
=>
{
console
.
log
(
"
registrationFailed,
"
,
data
);
});
this
.
userAgent
.
on
(
'
registrationExpiring
'
,
()
=>
{
console
.
warn
(
"
registrationExpiring
"
);
});
this
.
userAgent
.
on
(
'
newRTCSession
'
,
(
e
)
=>
{
this
.
message
=
`注意:您有新的
${
e
.
originator
===
"
local
"
?
"
外呼
"
:
"
来电
"
}
`
;
console
.
log
(
`新的
${
e
.
originator
===
"
local
"
?
"
外呼
"
:
"
来电
"
}
`
,
e
);
const
session
=
e
.
session
;
this
.
session
=
session
;
const
peerconnection
=
session
.
connection
;
if
(
e
.
originator
===
"
local
"
)
{
// 打电话
peerconnection
.
addEventListener
(
"
addstream
"
,
(
event
)
=>
{
const
audio
=
document
.
getElementById
(
"
audioElement
"
);
audio
.
srcObject
=
event
.
stream
;
});
}
else
{
document
.
getElementById
(
"
localVideo
"
).
play
();
// 接电话
this
.
dialogVisible
=
true
;
this
.
isg
=
true
;
this
.
callers
=
session
.
remote_identity
.
uri
.
user
;
}
// 接通,在这一步可以处理音频播放
// 接通并不代表对方已经接受,接通代表 滴 滴 滴
session
.
on
(
"
confirmed
"
,
()
=>
{
console
.
info
(
"
接通中
"
);
this
.
message
=
`已接通,请通话...`
;
this
.
status
=
1
;
const
audioElement
=
document
.
getElementById
(
"
audioElement
"
);
audioElement
.
autoplay
=
true
;
const
stream
=
new
MediaStream
();
const
receivers
=
session
.
connection
.
getReceivers
();
if
(
receivers
)
{
receivers
.
forEach
((
receiver
)
=>
stream
.
addTrack
(
receiver
.
track
));
}
audioElement
.
srcObject
=
stream
;
audioElement
.
play
();
});
// 接听失败
session
.
on
(
"
failed
"
,
(
mdata
)
=>
{
const
myAuto
=
document
.
getElementById
(
"
localVideo
"
);
myAuto
.
pause
();
myAuto
.
load
();
this
.
message
=
`来电的时拒接或,未接听对方就挂断...`
;
console
.
info
(
"
来电的时候 拒接或者 还没接听对方自己就挂断了
"
);
});
// 接听成功
session
.
on
(
"
accepted
"
,
(
response
,
cause
)
=>
{
// 嘟嘟嘟
this
.
message
=
`接听成功...`
;
this
.
status
=
1
;
console
.
info
(
"
接听成功
"
);
});
// 接听成功后 挂断
session
.
on
(
"
ended
"
,
()
=>
{
this
.
dialogVisible
=
false
;
this
.
InCall
=
false
;
});
// 通话被挂起
session
.
on
(
"
hold
"
,
(
data
)
=>
{
const
org
=
data
.
originator
;
if
(
org
===
"
local
"
)
{
this
.
message
=
`通话被本地挂起...`
;
console
.
log
(
"
通话被本地挂起:
"
,
org
);
}
else
{
this
.
message
=
`通话被对方挂起...`
;
console
.
log
(
"
通话被对方挂起:
"
,
org
);
}
});
// 通话被继续
session
.
on
(
"
unhold
"
,
(
data
)
=>
{
const
org
=
data
.
originator
;
if
(
org
===
"
local
"
)
{
}
else
{
this
.
message
=
`对方要求继续通话...`
;
console
.
log
(
"
对方要求继续通话:
"
,
org
);
}
});
});
this
.
userAgent
.
on
(
'
newMessage
'
,
(
data
)
=>
{
if
(
data
.
originator
==
'
local
'
)
{
console
.
info
(
'
onNewMessage , OutgoingRequest -
'
,
data
.
request
);
}
else
{
console
.
info
(
'
onNewMessage , IncomingRequest -
'
,
data
.
request
);
}
});
console
.
info
(
"
call register
"
);
this
.
userAgent
.
start
();
},
uaCall
()
{
if
(
this
.
isReady
||
this
.
userAgent
){
let
sip_phone_number_
=
`sip:
${
this
.
uaSipInfo
.
sip_id
}
@
${
this
.
uaSipInfo
.
adminwsip_host
}
`
;
let
options
=
{
'
pcConfig
'
:
{
'
rtcpMuxPolicy
'
:
"
negotiate
"
,
},
'
rtcOfferConstraints
'
:
{
'
offerToReceiveAudio
'
:
'
1
'
,
'
offerToReceiveVideo
'
:
'
0
'
,
},
'
eventHandlers
'
:
{
'
progress
'
:
(
e
)
=>
{
console
.
log
(
'
call is in progress
'
);
},
'
failed
'
:
(
e
)
=>
{
console
.
log
(
'
call failed:
'
,
e
);
},
'
ended
'
:
(
e
)
=>
{
console
.
log
(
'
call ended :
'
,
e
);
console
.
log
(
'
通话结束
'
);
this
.
message
=
`通话结束...`
this
.
status
=
0
this
.
isReady
=
false
},
'
confirmed
'
:
(
e
)
=>
{
console
.
log
(
'
call confirmed
'
);
}
},
'
mediaConstraints
'
:
{
'
audio
'
:
true
,
'
video
'
:
false
,
},
};
this
.
userAgent
.
call
(
sip_phone_number_
,
options
);
}
else
{
this
.
$message
({
message
:
"
尚未建立链接无法拨号通话,请确保链接通畅且对方在线!
"
,
type
:
'
error
'
});
}
},
uaHangup
()
{
if
(
this
.
isReady
||
this
.
userAgent
){
console
.
log
(
'
主动挂断
'
)
this
.
userAgent
.
terminateSessions
();
const
myAuto
=
document
.
getElementById
(
"
localVideo
"
);
myAuto
.
pause
();
myAuto
.
load
();
const
audioElement
=
document
.
getElementById
(
"
audioElement
"
);
audioElement
.
pause
();
audioElement
.
load
();
}
else
{
this
.
$message
({
message
:
"
尚未建立通信链接!
"
,
type
:
'
error
'
});
}
},
init
(
safetyhatmac
)
{
this
.
showView
()
this
.
message
=
'
正在建立链接,等待服务器响应...
'
HttpReq
.
truckDispatching
.
propleGetSipInfo
({
safetyhatmac
}).
then
((
res
)
=>
{
if
(
res
.
data
){
this
.
uaSipInfo
=
res
.
data
;
if
(
!
this
.
uaSipInfo
.
sip_id
){
this
.
message
=
'
对方安全帽未在线,无法通话!!
'
}
else
{
this
.
uaRegister
()
}
}
else
{
this
.
message
=
'
服务器通信失败!!
'
this
.
$notify
({
title
:
res
.
msg
,
type
:
'
error
'
,
});
}
})
},
showView
()
{
this
.
visible
=
true
},
hideView
()
{
this
.
visible
=
false
this
.
uaHangup
()
},
cancelView
()
{
this
.
hideView
()
}
},
beforeDestroy
()
{
this
.
hideView
()
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.corrugation-s
{
height
:
80px
;
width
:
118px
;
margin
:
auto
;
display
:
flex
;
align-items
:
center
;
position
:
relative
;
}
.corrugation-s
span
{
background
:
linear-gradient
(
to
top
,
#d299c2
0%
,
#fef9d7
100%
);
width
:
4px
;
height
:
60%
;
border-radius
:
4px
;
margin-right
:
4px
;
}
.corrugation-s
span
:last-child
{
margin-right
:
0
;
}
.corrugation
{
height
:
80px
;
width
:
118px
;
margin
:
auto
;
display
:
flex
;
align-items
:
center
;
position
:
relative
;
}
.corrugation
span
{
background
:
linear-gradient
(
to
top
,
#d299c2
0%
,
#fef9d7
100%
);
width
:
4px
;
height
:
20%
;
border-radius
:
10px
;
margin-right
:
4px
;
animation
:
loading
2
.5s
infinite
linear
;
animation-delay
:
calc
(
0
.2s
*
var
(
--
d
));
}
.corrugation
span
:last-child
{
margin-right
:
0
;
}
@keyframes
loading
{
0
%
{
background-image
:
linear-gradient
(
to
right
,
#fa709a
0%
,
#fee140
100%
);
height
:
20%
;
border-radius
:
calc
(
var
(
--
h
)
*
0
.2
*
0
.5
);
}
50
%
{
background-image
:
linear-gradient
(
to
top
,
#d299c2
0%
,
#fef9d7
100%
);
height
:
100%
;
border-radius
:
calc
(
var
(
--
h
)
*
1
*
0
.5
);
}
100
%
{
background-image
:
linear-gradient
(
to
top
,
#a8edea
0%
,
#fed6e3
100%
);
height
:
20%
;
border-radius
:
calc
(
var
(
--
h
)
*
0
.2
*
0
.5
);
}
}
</
style
>
src/views/personnelPositioning/peopleLogData/index.vue
View file @
0a54817f
...
...
@@ -41,6 +41,7 @@
<el-table-column
prop=
"phone"
label=
"电话"
align=
"center"
></el-table-column>
<el-table-column
label=
"操作"
align=
"center"
fixed=
"right"
>
<
template
slot-scope=
"scope"
>
<span
class=
"link-cell"
@
click=
"openDialView(scope.row)"
>
实时通话
</span>
<span
class=
"link-cell"
@
click=
"openTrailView(scope.row)"
>
轨迹回放
</span>
<span
class=
"link-cell"
@
click=
"openPosView(scope.row)"
>
轨迹数据
</span>
<span
v-show=
"scope.row.userid"
class=
"link-cell"
@
click=
"openvideoView(scope.row)"
>
视频回放
</span>
...
...
@@ -104,6 +105,7 @@
</el-dialog>
<!-- 视频 -->
<el-dialog
append-to-body
:close-on-click-modal=
"false"
:before-close=
"cancelFormViedoRtc"
:visible=
"videoRtc"
title=
"实况"
width=
"800px"
>
<el-button
style=
"position:absolute;top:70px;right:30px;z-index:99"
@
click=
"screenShot"
>
截屏
</el-button>
<video
id=
"remoteVideo"
controls
style=
"width:100%;height:440px;"
></video>
</el-dialog>
<el-dialog
append-to-body
:close-on-click-modal=
"false"
:before-close=
"cancelFormViedo"
:visible=
"videoDia"
title=
"回放"
width=
"800px"
>
...
...
@@ -153,7 +155,7 @@
<el-button
type=
"primary"
@
click=
"nextP()"
>
下一页
<i
class=
"el-icon-arrow-right el-icon--right"
></i></el-button>
</div>
</el-dialog>
<dial-view
ref=
"dialView"
/>
</div>
</template>
...
...
@@ -163,15 +165,17 @@ import {JSWebrtc} from '@/assets/js/jswebrtc.js';
import
'
video.js/dist/video-js.css
'
import
videojs
from
'
video.js
'
import
'
videojs-contrib-hls
'
import
html2canvas
from
'
html2canvas
'
import
mars3dViewerMap
from
"
../../../components/mars3d/Map5.vue
"
;
import
*
as
mars3d
from
"
mars3d
"
;
import
*
as
Cesium
from
"
mars3d-cesium
"
;
import
peopleIcon
from
"
../../../assets/images/point.png
"
;
import
dialView
from
"
./dialView
"
;
export
default
{
name
:
'
peopleLogData
'
,
components
:
{
mars3dViewerMap
,
mars3dViewerMap
,
dialView
},
data
()
{
const
basePathUrl
=
window
.
basePathUrl
||
''
...
...
@@ -244,6 +248,10 @@ export default {
this
.
map
=
map
;
this
.
graphicLayer
=
graphicLayer
;
},
openDialView
(
item
)
{
this
.
peoItem
=
item
;
this
.
$refs
.
dialView
.
init
(
this
.
peoItem
.
safetyhatmac
)
},
drawTrail
()
{
let
map
=
this
.
map
;
let
graphicLayer
=
this
.
graphicLayer
;
...
...
@@ -590,6 +598,30 @@ export default {
}
this
.
trailView
=
false
;
},
// 视频截图
screenShot
()
{
let
video
=
document
.
getElementById
(
'
remoteVideo
'
)
html2canvas
(
video
,
{
allowTaint
:
true
,
useCORS
:
true
}).
then
((
canvas
)
=>
{
const
capture
=
canvas
.
toDataURL
(
'
image/png
'
)
const
saveInfo
=
{
'
download
'
:
`MAC_
${
this
.
peoItem
.
safetyhatmac
}
_
${
this
.
getNowTime
()}
.png`
,
'
href
'
:
capture
}
const
element
=
document
.
createElement
(
'
a
'
)
element
.
style
.
display
=
'
none
'
for
(
const
key
in
saveInfo
)
{
element
.
setAttribute
(
key
,
saveInfo
[
key
])
}
document
.
body
.
appendChild
(
element
)
element
.
click
()
setTimeout
(()
=>
{
document
.
body
.
removeChild
(
element
)
},
300
)
})
},
// 点击搜索
toSearch
()
{
this
.
page
=
1
;
...
...
@@ -626,6 +658,14 @@ export default {
this
.
pageP
+=
1
;
this
.
loadDataP
()
},
//获取当前时间
getNowTime
()
{
let
date
=
new
Date
();
return
''
+
date
.
getFullYear
()
+
this
.
addZero
(
date
.
getMonth
()
+
1
)
+
this
.
addZero
(
date
.
getDate
())
+
this
.
addZero
(
date
.
getHours
())
+
this
.
addZero
(
date
.
getMinutes
())
+
this
.
addZero
(
date
.
getSeconds
());
},
addZero
(
s
)
{
return
s
<
10
?
(
'
0
'
+
s
)
:
s
;
},
},
}
</
script
>
...
...
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