使用WebSocket实现实时报警,实现当接收到报警时弹出弹窗显示报警内容和发错报警声音。
<template>
<section class="app-main">
<audio
loop="true"
ebkit-playsinline="true"
playsinline="true"
ref="myAudio"
src="../../assets/alarm.mp3"
></audio>
</section>
</template>
<script>
import { mapGetters } from 'vuex'
import { parseTime } from '@/utils/index'
import { getToken } from '@/utils/auth'
export default {
name: 'AppMain',
components: {
},
watch: {
alarmTime(after) {
clearInterval(this.timer)
if (after > 0) {
this.setAudio()
} else {
this.myAudio.pause()
clearInterval(this.timer)
this.$store.commit('user/SET_ALARMTIME', 0)
}
}
},
computed: {
...mapGetters(['pcAlarmVoice', 'catchComponents']),
key() {
return this.$route.path
}
},
data() {
return {
websock: null,
infoText: '',
showInfo: false,
lockReconnect: false,
alarmBox: [],
alarmBG: ['', 'bgCC6966', 'bg969696', 'bgCC6966 ', 'bg969696', 'bgCC6966', 'bgCC6966', 'bgCC6966'],
alarmTime: 0,
timer: null,
myAudio: null,
alarmType: ['', '超限报警', '超限预警', '断电报警 ', '离线报警', '设备异常', '上线通知', '来电通知'],
time1: null
}
},
created() {},
mounted() {
this.initWebSocket()
this.myAudio = this.$refs.myAudio
},
methods: {
setAudio() {
if (this.myAudio.paused) {
this.myAudio.play()
}
this.timer = setInterval(() => {
this.alarmTime--
}, 1000)
},
initWebSocket: function () {
let bindContent = getToken()
if (bindContent === 'undefined' || !bindContent) {
bindContent = ''
}
let url = ''
if (process.env.NODE_ENV === 'production') {
url = 'ws://192.168.31.46:30008/?bindType=2&bindContent=' + bindContent
} else if (process.env.NODE_ENV === 'staging') {
url = 'ws://ws.lenglh.cn:30008/?bindType=2&bindContent=' + bindContent
} else {
url = 'ws://192.168.31.46:30008/?bindType=2&bindContent=' + bindContent
return false
}
this.websock = new WebSocket(url)
this.websock.onopen = this.websocketOnopen
this.websock.onerror = this.websocketOnerror
this.websock.onmessage = this.websocketOnmessage
this.websock.onclose = this.websocketOnclose
},
websocketOnopen: function () {
console.log('页面WebSocket连接成功')
},
websocketOnerror: function (e) {
console.log('WebSocket连接发生错误', e)
this.reconnect()
},
websocketOnmessage: function (e) {
console.log('-----接收消息-------')
if (this.pcAlarmVoice) {
this.alarmTime = 5
this.$store.commit('user/SET_ALARMTIME', this.alarmTime)
}
const h = this.$createElement
let alarmData = JSON.parse(e.data).bindContent
alarmData.alarmTime = parseTime(alarmData.alarmTime)
if (this.$route.path === '/screen') {
alarmData.alarmBG = this.alarmBG[alarmData.alarmType]
alarmData.alarmBTN=this.alarmBG[alarmData.alarmType]+'btn'
} else {
alarmData.alarmBG = ''
alarmData.alarmBTN = ''
}
alarmData.alarmType = this.alarmType[alarmData.alarmType]
alarmData.groupName = alarmData.groupName ? alarmData.groupName : '未分配'
let title = alarmData.deviceName + '(' + alarmData.deviceSerial + ')'
let index = this.alarmBox.length
if (index === 3) {
this.alarmBox[0].close()
this.alarmBox.pop()
}
let messageHTML = null
if (alarmData.channelName) {
messageHTML = h(
'div',
{
class: 'alarm-box'
},
[
h('p', this.$t('device.d409') + ':' + alarmData.alarmType),
h('p', this.$t('device.d746') + ':' + alarmData.channelName),
h('p', this.$t('monitor.m15') + ':' + alarmData.groupName),
h('p', this.$t('device.d497') + ':' + alarmData.alarmTime),
h('p', this.$t('user.u258') + ':' + alarmData.alarmContent.cn),
h(
'div',
{
class: 'btn-box'
},
[
h(
'button',
{
class: 'btn el-button--primary ' + alarmData.alarmBTN,
on: {
click: () => this.notifyClick(alarmData)
}
},
'查看详情'
)
]
)
]
)
} else {
messageHTML = h(
'div',
{
class: 'alarm-box'
},
[
h('p', this.$t('device.d409') + ':' + alarmData.alarmType),
h('p', this.$t('user.u489') + ':' + alarmData.objectName),
h('p', this.$t('device.d497') + ':' + alarmData.alarmTime),
h('p', this.$t('user.u258') + ':' + alarmData.alarmContent.cn),
h(
'div',
{
class: 'btn-box'
},
[
h(
'button',
{
class: 'btn el-button--primary ' + alarmData.alarmBTN,
on: {
click: () => this.notifyClick(alarmData)
}
},
this.$t('global.detailBtn')
)
]
)
]
)
}
this.open(title, messageHTML, index, alarmData.alarmBG)
},
open(title, messageHTML, index, bg) {
console.log('当前页面', this.$route, bg)
let customClass = 'alarm-notify'
if (this.$route.path === '/screen') {
customClass = 'alarm-notify screen-box ' + bg
}
this.alarmBox[index] = this.$notify({
title: title,
dangerouslyUseHTMLString: true,
duration: 5000,
customClass: customClass,
message: messageHTML
})
},
notifyClick(alarmData) {
this.$store.dispatch('app/setReqId', alarmData.deviceId)
this.$router.push({ name: 'monitoringDeviceDetail' })
},
websocketOnclose: function (e) {
this.reconnect()
},
websocketSend(text) {
try {
this.websock.send(text)
} catch (err) {
}
},
reconnect() {
let context = this
if (context.lockReconnect) return
context.lockReconnect = true
clearTimeout(this.time1)
this.time1 = setTimeout(function () {
context.initWebSocket()
context.lockReconnect = false
}, 5000)
}
},
beforeDestroy() {
}
}
</script>
<style scoped lang="scss">
.app-main {
min-height: calc(100vh - 60px);
width: 100%;
position: relative;
}
.fixed-header + .app-main {
padding-top: 50px;
}
.info {
position: relative;
width: 100%;
padding: 10px;
}
::v-deep .el-notification__group {
width: 100% !important;
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 15px;
}
}
.alarm-notify {
width: 400px;
.el-notification__group {
width: 100%;
.alarm-box {
> p {
line-height: 1.4;
margin-top: 10px;
}
}
}
}
.screen-box {
// background-color: #103064;
// border: 1px solid #2154b2;
opacity: 95%;
.el-notification__title {
color: #fff !important;
}
p {
color: #fff !important;
}
}
.bgCC6966 {
background-color: #cc6966;
border: 1px solid #cc2e29;
}
.bgCC6966btn {
background-color: #ffffff !important;
color: #cc6966 !important;
}
.bg969696 {
background-color: #969696;
border: 1px solid #ffffff;
}
.bg969696btn {
background-color: #ffffff !important;
color: #323232 !important;
}
.btn {
box-sizing: border-box;
height: 35px;
border-radius: 4px;
border: none;
}
.btn-box {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-top: 20px;
}
// -----------------------
.isOn {
width: 28px;
height: 28px;
-webkit-animation: rotating 1.2s linear infinite;
animation: rotating 1.2s linear infinite;
}
@keyframes rotating {
from {
-webkit-transform: rotate(0);
}
to {
-webkit-transform: rotate(360deg);
}
}
@-webkit-keyframes rotating {
from {
-webkit-transform: rotate(0);
}
to {
-webkit-transform: rotate(360deg);
}
}
.isOff {
width: 28px;
height: 28px;
}
</style>
注:
- 使用
this.$t('') 是项目做了中英文翻译 - 使用
this.$createElement 创建弹窗的html片段是因为要求使用返回的数据的值做显示,使用原始html片段不能实现,而使用模板字符串的html片段时不能执行方法,最终使用vue的this.$createElement 实现项目需求。
最终弹窗效果: 点击详情即可跳转页面
|