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>

 

posted on 2024-07-23 14:05  小虾米吖~  阅读(367)  评论(0编辑  收藏  举报