详细讲解nodejs中使用socket.io的私聊的另一种方式

服务器端:

app.js

let express = require('express');
let bodyParser = require('body-parser');
let app = express();
let server = require('http').createServer(app);
const io = require('socket.io')(server);
let webSocket=require('./routers/websket')(io,app);
server.listen(80,function () {
    console.log("success")
});


websocket.js


const md5=require('md5');
const db=require('./../utils/db');

module.exports=function (io,app) {
    //设置聊天名字,返回聊天记录
    app.post("/qingwakuaiche/setName",function (req,res) {
        let data=req.body.fromName;
        let _toName=req.body.toName;
        let fromName=new Promise(function (resolve, reject) {
            db.find('chatList',{$or:[{fromName:data},{toName:data}]}).then(function (arr) {
                if(arr.length){
                    resolve(arr)
                }else {
                    reject([{
                        sayID:sort(_toName+data),
                        toName:_toName,
                        arr:[
                            {
                                toName:_toName,
                                msg:'',
                                fromName:data,
                                sayID:sort(_toName+data),
                                time:new Date().getTime(),
                            }
                        ]
                    }])
                }
            })
        });


        Promise.all([fromName]).then(function ([fromName]) {
            let result=fromName;
            result.sort(function (a,b) {
               return a.time-b.time
            });
            //整理toName
            let toNameArr=result.map(function (value, index, array) {
                 if(value.fromName!==data){
                     return JSON.stringify({
                         name:value.fromName,
                         sayID:value.sayID,
                     })
                 } else if(value.toName!==data){
                     return JSON.stringify({
                         name: value.toName,
                         sayID:value.sayID,
                     })
                 }
            });

            //toName去重
            toNameArr=Array.from(new Set(toNameArr));


            //整合后的result数组 和 toName再次整合
            result=toNameArr.map(function (val,index) {
                let nameObj=JSON.parse(val);

                return {
                    sayID:nameObj.sayID,
                    toName:nameObj.name,
                    arr:result.filter(function (value, index, array) {
                        return nameObj.sayID===value.sayID
                    })
                }
             });

            res.json(result)
        }).catch(function (err) {
            res.json(err)
        })
    });

    io.on('connection', function(socket){

        //用户想聊天对象发起聊天
        socket.on('sayTo',function (data) {
            let toName = data.toName;
            db.insertOne('chatList',{
                sayID:sort(toName+data.fromName),
                toName,
                msg:data.msg,
                fromName:data.fromName,
                time:new Date().getTime()
            });
            //发送信息给指定的用户
            io.emit('frog'+sort(toName+data.fromName),{
                msg:data.msg,
                fromName:data.fromName,
                toName,
                time:new Date().getTime()
            });

        });
    });

    //字符串排序
    function sort(str) {
        let a=(str.toString()).split("");
        let b=a.sort();
        return b.join("");
    }


};


//判断是否参数缺失
function isNot(req,res,arr) {
    return new Promise(function (resolve, reject) {
        let obj=req.body;
        for(let i in arr){
            if(obj[arr[i]]){
                resolve(true)
            }else {
                res.send('缺少参数');
            }
        }
    })
}


客户端:(基于vue开发)

基于的包

"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"jquery": "^3.3.1",
"js-cookie": "^2.2.0",
"jsencrypt": "^3.0.0-beta.1",
"vue": "^2.5.2",
"vue-axios": "^2.1.1",
"vue-router": "^3.0.1",
"vue-socket-io": "^0.3.2",
"vue-socket.io": "^2.1.1-b",
"vuex": "^3.0.1"

<template>
    <div v-show="chatBool">
      <div class="min-box clearfix" v-show="min==='true'"  @click="maximize('false')">
        <div class="fl">
          <span class="icon"><i></i><sub></sub></span>
          <span class="news">42条新消息</span>
        </div>
        <div class="fr"></div>
      </div>
      <div class="chat" v-if="min==='false'">
        <p class="operate">
          <span class="min" @click="maximize('true')"></span>
          <span class="close" @click="closeFn"></span>
        </p>
        <div class="fl">
          <h3>消息(1</h3>
          <ul v-show="chatList.length">
            <li class="clearfix" :class="{active:chatIndex===index}" v-for="(item,index) in chatList" @click="chooseChat(index)">
              <div class="img fl active">
                <img src="../assets/images/userImg-circle.png" >
                <div class="line" v-if="item.isReader"></div>
              </div>
              <div class="name fl">
                <h3>{{item.toName}}</h3>
                <p>{{item.arr[item.arr.length-1].msg}}</p>
              </div>
              <div class="news fl">...</div>
            </li>
          </ul>
        </div>
        <div class="fr">
          <h3>{{toName}}</h3>
          <div class="text">
            <div v-if="item.msg" class="clearfix" :class="[((index+1)%2)===0 && index!==0?'active':'', tel===item.fromName?'hover':'']" v-for="(item,index) in chooseChatData">
              <div class="img fl"> <img src="../assets/images/userImg-circle.png" ></div>
              <div class="text fl">
                <div class="sjx"></div>
                <div class="content">{{item.msg}}</div>
              </div>
            </div>
          </div>
          <div class="sendMes">
            <textarea v-model="sendMes" @keyup.enter="sendMesFn(toName)" placeholder="输入消息文本" maxlength="50"></textarea>
            <div><button @click="sendMesFn(toName)">发送</button></div>
          </div>
        </div>
      </div>
    </div>
</template>

<script>
    export default {
        name: "chat",
       data(){
          return{
            chatIndex:'',//默认聊天的数组
            min:sessionStorage.getItem('chatMin') || 'false',//聊天窗口是否最小化
            sendMes:'',//发送的数据
            chatList:[],//关于我的聊天数据
            chooseChatData:[],//选择与那个用户的聊天记录
            chatId:'',//聊天id
            toName:'',//对谁聊天
            sameSayArr:[],//相同的聊天id
            tel:this.getCookie('tel'),
            init:1,//聊天初始化
          }
       },
        created(){

        },
        computed:{
          chatBool(){
            let toName=this.$store.state.common.chatBool;
            if(toName){
              this.getChatList(this.$store.state.common.chatBool);
              this.getMsg(this.getCookie('tel'),this.toName);

            }
            return this.$store.state.common.chatBool
          }
        },
        mounted(){

        },
        updated(){

        },
        watch:{
          chooseChatData(){
            let talk=$('.chat > div.fr > .text');
            talk.scrollTop(talk[0].scrollHeight);
          }
        },
        methods:{
          //获取聊天历史记录
          getChatList(toName){
            let tel=this.getCookie('tel');
            this.axios.post(this.hostUrl+'/setName', {fromName:tel,toName}).then((obj) => {
              let arr=obj.data;
              this.chatList=arr;
              /*if(arr[0].msg){
                this.chatList=arr;
              }*/
            });
          },
          //选择聊天的人
          chooseChat(index){
            this.chatIndex=index;
            if(this.chatList.length){
              this.toName=(this.chatList)[index].toName;
              this.chooseChatData=(this.chatList)[index].arr;
              let talk=$('.chat > div.fr > .text');
              talk.scrollTop(talk[0].scrollHeight);
            }
          },
          //发送消息
          sendMesFn(toName){
            let tel=this.getCookie('tel');
            if(!tel){
              return false
            }
            if(!toName){
              alert("请选择聊天对象");
              return false
            }
            this.$socket.emit('sayTo',{
              toName,
              fromName:tel,
              msg:this.sendMes
            });
          },

          //获取聊天消息
          getMsg(tel,toName){
            this.$socket.on('frog'+this.sort(tel+toName), (data)=> {
              this.sendMes='';
              console.log(data)
              if(this.chatList.length){
                this.chatList=this.chatList.map(val=>{
                  if(val.toName===toName){
                    let arr=val.arr;
                    arr.push(data);
                    return{
                      sayID:val.sayID,
                      toName:val.toName,
                      arr
                    }
                  }
                });
              }

              this.chooseChatData.push(data);
            });
          },
          maximize(bool){
            this.min=bool;
            sessionStorage.setItem('chatMin',bool);
          },
          closeFn(){
           this.$store.commit('chatFn',false)
          },
        }
    }
</script>

<style scoped>
  @import "../assets/less/chat.css";
</style>

猜你喜欢

转载自blog.csdn.net/qq_24745557/article/details/80830691