首页 > 其他分享 >socket封装使用(uniapp)

socket封装使用(uniapp)

时间:2024-07-23 14:10:45浏览次数:7  
标签:uniapp 封装 socket confirm socketTask uni data store

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>

 

标签:uniapp,封装,socket,confirm,socketTask,uni,data,store
From: https://www.cnblogs.com/LindaBlog/p/18318248

相关文章

  • 封装 static静态关键字 可变参数 递归
    一.封装1.this1.当成员变量和局部变量重名时,调用遵循"就近原则",先调用局部的2.this代表的是当前对象,哪个对象调用this所在的方法,this就代表哪个对象3.作用:区分重名的成员变量和局部变量(this后面肯定是成员的)publicclassPerson{Stringname;/**......
  • android在一个TextView中设置不同字体大小、不同字体颜色封装
    一、概述在开发过程中遇到过这样一种业务,有很多单行文本字体。字符串中每一部分的字体样式、大小、颜色都不相同。传统的做法是放多个TextView以达到效果。但是当这个页面中的这样的元素非常多,且非常复杂的时候,就会出现页面加载缓慢的问题(view加载=深度(递归)+平铺),也就是......
  • python面向对象三大特性(继承、多态、封装)之继承
    来吧,下面来具体说一下面向对象的三大特性:所谓封装、多态和继承。我们先来说一下继承。所谓继承,顾名思义,子类继承父类的属性,包括数据属性和函数属性。写个简单的例子吧:1.简单的继承classAnimal:need_substance='water'def__init__(self):print('这是一......
  • C++ 学习笔记十一 封装
    封装4.1.1封装的意义封装是C++面向对象三大特性之一封装的意义:将属性和行为作为一个整体,表现生活中的事物将属性和行为加以权限控制封装意义一:​在设计类的时候,属性和行为写在一起,表现事物语法:class类名{访问权限:属性/行为};**示例1:**设计一个圆类,求圆的周......
  • uniapp中使用echarts关系图
    首先看一下页面效果:<template><viewclass="page"><!--导航栏--><b-nav-barclass="b-nav-bar"><templateslot="left"><view@click="goBack"class="iconfonticon-zuofanhuinBackml15&quo......
  • LocalStorage封装
    前言localStorage 使用是一个老生常谈的话题,本文不讲解基础 api,主要教你如何封装一个优雅的localStorage 工具,以及一些 localStorage中一些你不知道的知识点。优雅的 Storage 工具类如何封装(支持前缀key、加密存储、过期时间,ts封装等)localStorage 真实存储大小......
  • 封装C项目为dll
    这是头文件,定义了一个接口MyHeader.h。#ifndefMYHEADER_H#defineMYHEADER_H//定义导出DLL函数的宏#defineMY_API__declspec(dllexport)#ifdef__cplusplusextern"C"{ //告诉编译器下面是C语言代码#endif //函数声明 MY_APIint__stdcalladd(intx,inty......
  • 我猜ESP8266陷入了无限的socket.accept()循环?
    我一直在使用ESP8266,并遇到了一个似乎不知从何而来且无法解决的问题。至少-对我来说。基本上我继续了这个构建一个简单的服务器套接字的教程。然而我的esp突然停止允许与其自身的连接。代码正常工作,直到main.py:whileTrue:conn,addr=s.ac......
  • Java面向对象程序三大特性:封装、继承、多态
    目录 引言一.封装二.继承三.多态四.结论 引言 在现代软件开发中,面向对象编程(OOP)已成为一种流行且有效的编程范式,其中Java语言以其高效性和灵活性深受开发者的喜爱。面向对象编程的核心在于其三大特性:封装、继承和多态。这些特性不仅提高了代码的重用性和可维......
  • 基于SpringBoot+Vue+uniapp的新闻资讯系统(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......