uniapp,使用websocket开发聊天客户端

聊天服务器端,使用上一个文章里面提到的websocket服务器端,

通讯地址格式ws://ip:7878:/c/sec/userid

大致思路,首先去app的服务器登录,返回用户信息,里面含有用户编号。通过获取配置的方式,获取聊天url,当然,在app里面写死也可以,我是做成了一个后台配置项。

app拿到链接地址,加上当前用户的id,使用uni.connectSocket进行链接,使用uni.onSocketMessage接收用户消息。接收到消息存到本地sqllite。

进入聊天界面,首先去查询本地sqllite,显示历史消息,然后通过回调方式,监听实时消息。并显示。

使用store存储实时消息,ws接收到消息以后,推送到store,页面对store里面的变量进行watch,实时更新页面。

效果图

uniapp,使用websocket开发聊天客户端

关键代码1:sqllite.js,完成数据库初始化,数据操作,注意uniapp使用sqllite需要勾选对应插件,必须真机调试。

/**
 * 封装了对sqllite基本操作
 */
module.exports = {
  dbName: 'chatapp', // 数据库名称
  dbPath: '_doc/chat.db', // 数据库地址,推荐以下划线为开头   _doc/xxx.db

 // 判断数据库是否打开
 isOpen() {
   // 数据库打开了就返回 true,否则返回 false
   var open = plus.sqlite.isOpenDatabase({
     name: this.dbName,  // 数据库名称
     path: this.dbPath  // 数据库地址
   })
   return open;
 },

 // 创建数据库 或 有该数据库就打开
 openSqlite() {
   return new Promise((resolve, reject) => {
     // 打开数据库
     plus.sqlite.openDatabase({
       name: this.dbName,
       path: this.dbPath,
       success(e) {
            console.log("open sql success")
           resolve(e); // 成功回调
       },
       fail(e) {
            console.log("open database error")
         reject(e);  // 失败回调
       }
     })
   })
 },
 // 关闭数据库
 closeSqlite() {
   return new Promise((resolve, reject) => {
     plus.sqlite.closeDatabase({
       name: this.dbName,
       success(e) {
         resolve(e);
       },
       fail(e) {
         reject(e);
       }
     })
   })
 },
 /**执行增删改,
  * @param {Object} sql
  */
 execQuery(sql){
     var db=this;
     if(this.isOpen()){

         return new Promise((resolve, reject) => {
                plus.sqlite.executeSql({
                  name: db.dbName,
                  sql: sql,
                  success(e) {
                    console.log("sql "+ sql+" exectue ok")
                    resolve(e);
                  },
                  fail(e) {
                    reject(e);
                  }
                })

        });
     }
     else{

     return new Promise((resolve, reject) => {
        db.openSqlite().then(res=>{
            plus.sqlite.executeSql({
              name: db.dbName,
              sql: sql,
              success(e) {
                resolve(e);
              },
              fail(e) {
                reject(e);
              }
            })
        }).catch(res=>{
            reject({code:1,msg:'open db '+db.dbName +' error'})
        })

     });

     }

 },
 //查询
 selectQuery(sql){
     var db=this;
     if(this.isOpen()){

         return new Promise((resolve, reject) => {
                plus.sqlite.selectSql({
                  name: db.dbName,
                  sql: sql,
                  success(e) {
                    console.log("sql "+ sql+" exectue ok")
                    resolve(e);
                  },
                  fail(e) {
                    reject(e);
                  }
                })

        });
     }
     else{

     return new Promise((resolve, reject) => {
        db.openSqlite().then(res=>{
            plus.sqlite.selectSql({
              name: db.dbName,
              sql: sql,
              success(e) {
                resolve(e);
              },
              fail(e) {
                reject(e);
              }
            })
        }).catch(res=>{
            reject({code:1,msg:'open db '+db.dbName +' error'})
        })

     });

     }

 },
 /**
  * 创建缓存表,
  */
  createDB(){
       var sql='create table if not exists temp("id" INTEGER PRIMARY KEY AUTOINCREMENT,"type" varchar(20),"val" varchar(20),"createtime" varchar(30))';
       return this.execQuery(sql);
  },
  /**
   * 创建聊天表
   */
  createDBChat(){
       var sql='create table if not exists chat("id" INTEGER PRIMARY KEY AUTOINCREMENT,"from" varchar(20),"to" varchar(20),"time" varchar(30),"msg" varchar(400))';
       return this.execQuery(sql);
  },
  /**删除一个缓存
   * @param {Object} id
   */
  deleteTemp(id){
      return this.execQuery("delete from temp where id="+id);
  },
  deleteByTypeVal(tp,val){
      return this.execQuery("delete from temp where val='"+val+"' and type='"+type+"'");
  },
  getTempByType(tp){
       return this.selectQuery("select * from temp where type='"+tp+"'");
  },
  getTempByID(id){
       return this.selectQuery("select * from temp where id='"+id+"'");
  },
  //修改数据
  updateData(dbTable,data){
      //var dbTable='temp';
      var db=this;
    var sql="update "+dbTable+" set ";
     for(var k in data){
        sql+="'"+k+"'='"+data[k]+"',"

     }
     sql=sql.substr(0,sql.length-1)+" where id="+data['id'];
     console.log(sql);
     return this.execQuery(sql);

  },

  //增加数据
  insertTemp(data){
       var dbTable='temp';
       var db=this;
        console.log(data);
      var s1="select count(*) as c from "+dbTable +" where val='"+val+"' and type='"+type+"'";
      this.selectQuery(s1).then(res=>{
          if(res.length>0 && res[0].c==0){

              data.createtime=db.getCurrentTime();

              // 判断传的参是否有值
              var sql="insert into "+dbTable +"(";
              var sql2=" values (";

              for(var k in data){
                sql+="'"+k+"',";
                sql2+="'"+data[k]+"',";
              }
              sql=sql.substr(0,sql.length-1)+")";
              sql2=sql2.substr(0,sql2.length-1)+")";
              sql=sql+sql2;

              //console.log(sql);
              db.execQuery(sql).then(res=>{});

          }

      })

  },
  //增加数据
  insertChat(data){
       var dbTable='chat';
       var db=this;
        console.log(data);

     // 判断传的参是否有值
    var sql="insert into "+dbTable +"(";
    var sql2=" values (";

     for(var k in data){
             sql+="'"+k+"',";
                sql2+="'"+data[k]+"',";
      }
              sql=sql.substr(0,sql.length-1)+")";
              sql2=sql2.substr(0,sql2.length-1)+")";
              sql=sql+sql2;

              //console.log(sql);
            return   this.execQuery(sql);

      },
getCurrentTime() {
      var date = new Date();//当前时间
      var month = this.zeroFill(date.getMonth() + 1);//月
      var day = this.zeroFill(date.getDate());//日
      var hour = this.zeroFill(date.getHours());//时
      var minute = this.zeroFill(date.getMinutes());//分
      var second = this.zeroFill(date.getSeconds());//秒

      //当前时间
      var curTime = date.getFullYear() + '-' + month + '-' + day + " " + hour + ':' + minute + ':' + second;

      return curTime;
  },
  zeroFill(t){
      if(t>=10)return t+"";
      else return "0"+t;
  }

}

关键代码2:wsocket.js,完成socket链接,监听,发送消息

import DB from "./sqlite.js"
import store from '@/store/store.js'//引入store,有消息直接存入
export default{
    url:'',//链接地址
    player:'',//用于播放消息声音

    setUrl(u){//外部通过这个函数,开启websocket监听
        var pg=this;
        console.log("ws",u);
        this.url=u;
        uni.connectSocket({//链接到ws
            url: u,
            fail:(err)=>{
                console.log("error",err);
            },
            success(r) {
                console.log("success",r)
            }
         });
         uni.onSocketMessage(res=>{

             pg.onMessage(res);//把消息交给当前对象处理

         })
    },

    onMessage(d){
        //当前对象处理消息
        this.playSound();//播放声音
        var msg=JSON.parse(d.data);//消息对象转换
        store.commit('pushMsg',msg);//存入到store
        DB.insertChat(msg);//存储到数据库
    },
    sendMessage(d){
        //把消息发出去
        uni.sendSocketMessage({
            data:JSON.stringify(d)
        })
    },
    playSound(){
        //播放声音
        if(this.player==''){
            this.player=uni.createInnerAudioContext();//创建播放对象
            this.player.autoplay = true;
            this.player.onPlay(() => {
              console.log('开始播放');
            });
            this.player.onError((res) => {
              console.log("playerror",res);

            });
        }
        this.player.src = '/static/msg.mp3';

    }
}

关键代码3,store.js 全局的消息,供页面监听

//引用Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

//实例store并导出
export default new Vuex.Store({
    state: {
        count: 0,//用来触发消息列表更新,直接监听chats无法触发watch,
        msg:{},//最后一条消息,用来给页面监听
        chats:{},//存储全局的聊天列表,以用户标识为key,
        users:{},//全局存储用户列表,以用户标识为key
    },
    mutations: {
        pushMsg(state,msg){
            /*消息触发 */
            console.log("pushMsg",msg)
            state.msg=msg;//消息改变,触发给前台
            state.count++;//计数器增加,为了让页面刷新
            var cs=state.chats;//先存储到一个数组
            var name=msg.from;//默认是用户的标识
            if(state.users[msg.from]!=null)name=state.users[msg.from].name;//显示名称使用存储的用户名
            cs[msg.from]={user:name,lastmsg:msg.msg};//聊天信息,姓名及最后消息
            state.chats=cs;//再保存回去
        },
        pushMsgTo(state,msg){
            /*用户主动发送消息*/
            state.msg=msg;//消息改变,触发给前台
            state.count++;//计数器增加,为了让页面刷新
            var cs=state.chats;//先存储到一个数组
            var name=msg.to;//默认是用户的标识
            if(state.users[msg.to]!=null)name=state.users[msg.to].name;//显示名称使用存储的用户名
            cs[msg.to]={user:name,lastmsg:msg.msg};//聊天信息,姓名及最后消息
            state.chats=cs;//再保存回去
        },
        setUsers(state,users){
            /* 设置用户列表 ,这个是有app页面,发起请求,获取用户列表,全局存储*/
            for(var i=0;i<users.length;i++){ var u="users[i];" state.users[u.id]="users[i];//&#x66F4;&#x65B0;&#x6216;&#x8005;&#x5B58;&#x50A8;&#x7528;&#x6237;&#x4FE1;&#x606F;" } }) < code></users.length;i++){>

关键代码4,main.js 将wssocket加入原型链,启用store。

import Vue from 'vue'
import App from './App'
import store from './store/store.js'
import ws from "pages/components/wscoket.js"
Vue.config.productionTip = false

App.mpType = 'app'
Vue.prototype.$ws=ws;//&#x6302;&#x8F7D;websocket

const app = new Vue({
    ...App,
    store
})
app.$mount()

关键代码4,在app.vue 里面对数据库进行初始化

<script>
    import DB from "pages/components/sqlite.js"
    export default {
        onLaunch: function() {
            /**
             * 数据库初始化
             */
            DB.createDB().then(res=>{
                console.log(res);
                DB.createDBChat().then(res=>{
                    console.log(res);
                })
            })
            console.log('App Launch')
        },
        onShow: function() {
            console.log('App Show')
        },
        onHide: function() {
            console.log('App Hide')
        }
    }
</script>

<style>
    /*每个页面公共css */
</style>

Original: https://blog.csdn.net/qujia121qu/article/details/120183923
Author: 曲大家
Title: uniapp,使用websocket开发聊天客户端

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/816310/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球