socket封装使用(uniapp)
1、封装socketjs
import store from '@/store'class socketIO {
constructor() {
this.socketTask = null
this.is_open_socket = false //避免重复连接
this.is_show_Loading = false
// 为空就为1 admin
this.url = store.state.baseUrl.socketUrl + (store.state.user.userinfo.personId || '1') //连接地址
this.connectNum = 1 // 重连次数
this.followFlake = true // traderDetailIndex == true 重连
//心跳检测
this.timeout = 15000 //多少秒执行检测
this.heartbeatInterval = null //
this.reconnectTimeOut = null //
}
// 进入这个页面的时候创建websocket连接【整个页面随时使用】
connectSocketInit() {
this.socketTask = uni.connectSocket({
url: this.url,
success: () => {
// 返回实例
return this.socketTask
},
fail:(err)=>{
console.log(err)
}
});
this.socketTask.onOpen((res) => {
console.log('连接成功');
if(this.connectNum>1){
if(store.state.baseUrl.socketUrl.indexOf('10.43')>-1){
store.commit('SET_SOCKET_URL','outIp')
}else{
store.commit('SET_SOCKET_URL','inIp')
}
this.url = store.state.baseUrl.socketUrl + (store.state.user.userinfo.personId || '1') //连接地址(必须要,否则请求的地址还是没变)
}
this.connectNum = 1
clearInterval(this.reconnectTimeOut)
clearInterval(this.heartbeatInterval)
this.is_open_socket = true;
// this.is_show_Loading = true;
uni.hideLoading()
this.start();
// 注:只有连接正常打开中 ,才能正常收到消息
this.socketTask?.onMessage((res) => {
// 字符串转json
const {data} = res
const index = data.indexOf('alarm') || data.indexOf('confirm') // 两种类型:alarm 和 confirm
if(index > -1 ){
const arr = JSON.parse(data.slice(data.indexOf('[')))
uni.$emit('socket', arr[1])
}
});
})
// 监听连接失败,这里代码我注释掉的原因是因为如果服务器关闭后,和下面的onclose方法一起发起重连操作,这样会导致重复连接
uni.onSocketError((res) => {
console.log('连接打开失败url',store.state.baseUrl.socketUrl);
if(store.state.baseUrl.socketUrl.indexOf('10.43')>-1){
store.commit('SET_SOCKET_URL','outIp')
}else{
store.commit('SET_SOCKET_URL','inIp')
}
this.url = store.state.baseUrl.socketUrl + (store.state.user.userinfo.personId || '1') //连接地址(必须要,否则请求的地址还是没变)
this.socketTask = null
this.is_open_socket = false;
// this.is_show_Loading = false;
clearInterval(this.heartbeatInterval)
clearInterval(this.reconnectTimeOut)
// uni.$off('getPositonsOrder')
// if (this.connectNum < 6000) {
this.reconnect();
this.connectNum += 1
// } else {
// uni.$emit('connectError');
// this.connectNum = 1
// }
});
// 这里仅是事件监听【如果socket关闭了会执行】
this.socketTask.onClose(() => {
console.log("已经被关闭了-------")
clearInterval(this.heartbeatInterval)
clearInterval(this.reconnectTimeOut)
this.is_open_socket = false;
// this.is_show_Loading = false;
this.socketTask = null
// uni.$off('getPositonsOrder')
if (this.connectNum < 6) {
// this.reconnect();
} else {
uni.$emit('connectError');
this.connectNum = 1
}
})
}
// 主动关闭socket连接
Close() {
if (!this.is_open_socket) {
return
}
this.socketTask.close({
});
}
//发送消息
send(data) {
// console.log("data---------->", data);
// 注:只有连接正常打开中 ,才能正常成功发送消息
if (this.socketTask) {
this.socketTask.send({
data: '',
async success() {
// console.log("消息发送成功");
},
});
}
}
//开启心跳检测
start() {
this.heartbeatInterval = setInterval(() => {
this.send('');
}, this.timeout)
}
//重新连接
reconnect() {
//停止发送心跳
clearInterval(this.heartbeatInterval)
//如果不是人为关闭的话,进行重连
if (!this.is_open_socket && this.followFlake) {
this.reconnectTimeOut = setInterval(() => {
this.connectSocketInit(this.data);
}, 3000)
}
}
}
module.exports = socketIO
2、页面使用
<template>
<view>
<view class="notification" v-show="show">
<view class="flex align-center justify-between title">
<view class="flex align-center">
<image src="./images/alarm.svg" class="icon"></image>
<text class="margin-left-sm text-lg text-bold">{{title}}</text>
</view>
<uni-icons type="closeempty" size="20" @click="show = false"></uni-icons>
</view>
<view class="padding-top-sm">
<div>{{alarmContent}}</div>
<img @click="previewImage(content)" :src="content" mode="widthFix" alt="" style="width: 100%;" />
</view>
</view>
<!-- 确认报警弹框 -->
<u-modal
title="告警确认处理"
:show="confirmShow"
:showCancelButton='false'
:showConfirmButton='false'
>
<view class="my_confirm" v-if="confirmDataInfo">
<view class="confirm_info">
<view>规则类型:<span>{{confirmDataInfo.ruleTypeName || ''}}</span></view>
<view>确认内容:<span>{{confirmDataInfo.confirmContent}}</span></view>
<view>规则名:<span>【{{confirmDataInfo.ruleName}}】{{confirmDataInfo.alarmValue}}</span></view>
<view>推送类型:<span>{{confirmDataInfo.pushTypeName}}</span></view>
</view>
<view class="operate_btns">
<u-button
text="误报"
size="small"
type="warning"
@click="dealWithConfirm(0)"
></u-button>
<u-button
text="正确报警"
size="small"
type="success"
@click="dealWithConfirm(1)"
></u-button>
<u-button
text="正确报警并执行控制指令"
type="primary"
size="small"
@click="dealWithConfirm(2)"
></u-button>
</view>
</view>
</u-modal>
</view>
</template>
<script>
import { generalOptions1 } from '@/utils/options.js'
import {handleConfirm} from '@/api/alarm/alarm.js'
function base64ToFile (base64Str, fileName, callback) {
// 去除base64前缀
var index=base64Str.indexOf(',')
var base64Str=base64Str.slice(index+1,base64Str.length)
plus.io.requestFileSystem(plus.io.PRIVATE_DOC,function(fs){
fs.root.getFile(fileName,{create:true},function(entry){
var fullPath = entry.fullPath;
let platform = uni.getSystemInfoSync().platform
if(platform == 'android'){
var Base64 = plus.android.importClass("android.util.Base64");
var FileOutputStream = plus.android.importClass("java.io.FileOutputStream");
try{
var out = new FileOutputStream(fullPath);
// 此处Base64.decode有长度限制,如果不能满足需求,可以考虑换成官方原生插件市场的【Base64转文件】
var bytes = Base64.decode(base64Str, Base64.DEFAULT);
out.write(bytes);
out.close();
// 回调
callback && callback(entry.toLocalURL());
}catch(e){
console.log(e.message);
}
}else if(platform == 'ios'){
var NSData = plus.ios.importClass('NSData');
var nsData = new NSData();
nsData = nsData.initWithBase64EncodedStringoptions(base64Str,0);
if (nsData) {
nsData.plusCallMethod({writeToFile: fullPath,atomically:true});
plus.ios.deleteObject(nsData);
}
// 回调
callback && callback(entry.toLocalURL());
}
})
})
}
export default {
data () {
return {
show: false,
title:'',
alarmContent:'',
content:'',
baseUrl:'',
confirmShow:false,
confirmDataInfo:{},
ruleType: generalOptions1(['维修规则', '生产规则', '故障规则']),//规则类型
pushType: generalOptions1(['视频', '告警内容', '视角算法动图', '视角算法文字']),
}
},
mounted(){
uni.$on('socket', this.getalarm) // 监听socket alarm
uni.$on('socket', this.getconfirm) // 监听socket confirm
},
methods:{
getalarm({receive,record,voiceBase64}) {
this.title = record?.ruleName || '';
this.alarmContent = record?.pushContent || '';
this.content = record?.algorithmImg[0] || ''; // 告警图片
if(record){
this.show = true
base64ToFile(voiceBase64,(new Date()).valueOf() + '.mp3',(res)=>{
let music = uni.createInnerAudioContext();
music.src = res;
music.volume = 1; // 音量
if(this.content){ // 动图出来了再播放声音
music.play(); //执行播放
}
music.onEnded(() => {
//播放结束
music.pause()
music.destroy()
})
})
}
},
getconfirm({confirm}){
if(confirm.createTime){
let pushType = [];
this.pushType?.map(item=>{
if(confirm.pushType.indexOf(item.value)>-1){
pushType.push(item.label)
}
})
this.$set(confirm,'pushTypeName',pushType?.join(','));
this.$set(confirm,'ruleTypeName',this.ruleType?.filter(item=> item.value == confirm.ruleType)[0]['label']);
this.confirmDataInfo = this.deepClone(confirm);
this.confirmShow = true;
}
},
// 告警确认处理
dealWithConfirm(_type){
let params = {
alarmRecordNo: this.confirmDataInfo.alarmRecordNo,
confirmStatus: _type
}
handleConfirm(params).then(res=>{
this.$modal.msg(res.message);
this.confirmShow = false;
this.confirmDataInfo = {};
})
}
}
}
</script>
<style scoped lang="scss">
.notification{
background: #ffffff;
border-radius: 6rpx;
position: fixed;
z-index: 1000;
width: 90vw;
left: 5vw;
top:5rpx;
box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 3px 1px;
padding: 20rpx;
.icon{
width: 64rpx;
height: 64rpx;
}
.title{
padding-bottom: 20rpx;
border-bottom: 1px #ebeef5 solid;
}
}
.confirm_info{
width: 100%;
margin-bottom: 50rpx;
font-size: 28rpx;
color: #666;
&>view{
margin-bottom: 26rpx;
& span{
color: #000;
font-size: 30rpx;
margin-left: 20rpx;
}
}
}
.operate_btns{
display: grid;
grid-template-columns: auto auto 290rpx;
grid-template-rows: auto;
grid-gap: 20rpx;
}
</style>
本文来自博客园,作者:小虾米吖~,转载请注明原文链接:https://www.cnblogs.com/LindaBlog/p/18318248