垃圾站 网站优化 vue使用WebSocket实现实时报警弹窗

vue使用WebSocket实现实时报警弹窗

使用WebSocket实现实时报警,实现当接收到报警时弹出弹窗显示报警内容和发错报警声音。

<template>
<section class="app-main">
<!-- 报警时的声音 controls -->
<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) {
// console.log('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() {
// http://192.168.31.240:8081/user/test?d=test02m202100001&i=1
// console.log('进入页面')
this.initWebSocket()
this.myAudio = this.$refs.myAudio
},
methods: {
setAudio() {
if (this.myAudio.paused) {
this.myAudio.play() // 播放
}
this.timer = setInterval(() => {
this.alarmTime--
}, 1000)
},
initWebSocket: function () {
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
// 用户token
let bindContent = getToken()
if (bindContent === 'undefined' || !bindContent) {
bindContent = ''
}
let url = ''
if (process.env.NODE_ENV === 'production') {
// 生产环境
// url = 'wss://192.168.31.46:30008/?bindType=2&bindContent=' + bindContent // 正试服
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 {
// development 开发环境
// url = 'ws://192.168.31.240:30008/?bindType=2&bindContent=' + bindContent
url = 'ws://192.168.31.46:30008/?bindType=2&bindContent=' + bindContent
return false
}
// console.log('初始化websocket', url)
// this.websock = new WebSocket('ws://192.168.31.240:30008/?bindType=2&bindContent=' + bindContent)
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连接成功')
//心跳检测重置
// this.heartCheck.reset().start()
},
// 连接失败后的回调函数
websocketOnerror: function (e) {
console.log('WebSocket连接发生错误', e)
this.reconnect()
},
// 当从服务器接受到信息时的回调函数
websocketOnmessage: function (e) {
// console.log('监听关闭' + e)
console.log('-----接收消息-------')

// 收到消息,添加报警声音(先判断声音报警是否开启)
if (this.pcAlarmVoice) {
this.alarmTime = 5
// console.log('先判断声音报警是否开启');
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, // 自动关闭的时间
// duration: 0, // 不自动关闭
customClass: customClass,
// position: 'bottom-right',
message: messageHTML
})
},
// 查看详情
notifyClick(alarmData) {
this.$store.dispatch('app/setReqId', alarmData.deviceId)
this.$router.push({ name: 'monitoringDeviceDetail' })
},
websocketOnclose: function (e) {
// console.log('connection closed (' + e.code + ')')
this.reconnect()
},
websocketSend(text) {
// 数据发送
try {
this.websock.send(text)
} catch (err) {
// console.log('send failed (' + err.code + ')')
}
},
reconnect() {
let context = this
if (context.lockReconnect) return
context.lockReconnect = true
//没连接上会一直重连,设置延迟避免请求过多
clearTimeout(this.time1)
this.time1 = setTimeout(function () {
// console.info('尝试重连...')
context.initWebSocket()
context.lockReconnect = false
}, 5000)
}
},
beforeDestroy() {
// this.websock.close()
// console.log('页面关闭websocket');
}
}
</script>

<style scoped lang="scss">
.app-main {
/*50 = navbar*/
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实现项目需求。

最终弹窗效果:

在这里插入图片描述

点击详情即可跳转页面

上一篇
下一篇
联系我们

联系我们

返回顶部