socket.io实现一对多的在线咨询客服系统

目录

 

前言

1.需求场景

2.页面效果图

3.线上地址

4.项目分析


前言

大三的时候写过一个小demo,socket.io实现在线匿名聊天室

博客地址:https://blog.csdn.net/qq_30604453/article/details/64159036

demo地址:http://www.chunling.online:2800/(此处请不要计较样式,毕竟只是造着玩的demo)

示例图:

socket.io实现一对多的在线咨询客服系统_第1张图片socket.io实现一对多的在线咨询客服系统_第2张图片

 

 

1.需求场景

闲来无事,改造一下这个demo,做一个一对多的在线咨询客服的系统(不涉及数据库操作)。

很多企业官网都会有在线咨询客服的功能。【很想要找个样例截图一下,可是懒得找啊,看粗糙版的样例吧 = =】

socket.io实现一对多的在线咨询客服系统_第3张图片

希望达到的效果:(1)每个用户进入网站,立即生成一个匿名身份,可与客服进行在线交流。(2)单一客服,客服可以接收所有用户的信息,并进行回复交流。所以这是一个一对多的关系,多个用户,一个客服。

 

2.页面效果图

用户页面:如上的gif图。点击右下角“在线咨询”按钮,弹出对话框,点击“发送”按钮或者“回车”可以发送消息给客服。点击“关闭”按钮关闭对话框

客服页面:

左侧面板显示用户列表,点击可切换当前聊天对象,如有未读消息显示橙色背景,当前聊天对象显示蓝色背景。

中间面板则是聊天视窗。

右侧面板记录用户进入网站,离开网站的时间。


socket.io实现一对多的在线咨询客服系统_第4张图片

用户页面(潦草地做一下移动端的适配)

socket.io实现一对多的在线咨询客服系统_第5张图片    socket.io实现一对多的在线咨询客服系统_第6张图片

 

3.线上地址

代码地址:https://gitee.com/wuchunling/contact-online

demo地址:

客服页面:http://www.chunling.online:2666/serve

用户页面:http://www.chunling.online:2666

 

4.项目分析

在线客服系统主要用socket.io。简单回顾一下socketio的用法》》socket.io的基本用法

由于是基于之前的小demo改造的,此处就不用什么高大上的框架。后端采用:express + socket.io;前端采用:jQuery + socket.io

 

4.1 用户客户端

(1)一对多的关键在于如何标识一个用户?在这里,我采用最简单的方法,用时间戳来标识一个用户。当用户进入网站浏览时,生成一个时间戳,这个时间戳就标志这个用户。

$(document).ready(function () {
  if (!sessionStorage.username) {
    sessionStorage.username = new Date().getTime()
  }
  var username = sessionStorage.username;
})

(2)当用户进入网站浏览,告知服务端“用户进入网站”;当用户离开网站,告知服务端“用户离开了网站”

在这里触发两个事件 loginIn和loginOut(或者说两个消息),loginIn和loginOut需要服务端去监听,服务端再将这两个消息下发给客服端。

$(document).ready(function () {

  var iosocket = io.connect();

  if (!sessionStorage.username) {
    sessionStorage.username = new Date().getTime()
  }
  var username = sessionStorage.username;

  iosocket.emit('loginIn', username); // 进入页面
  window.onunload = function () {  // 关闭页面
    iosocket.emit('loginOut', username)
  }

})

(3)用户发送消息,主要是触发msgFromClient事件,将聊天信息和用户标识发送给服务端,服务端监听此事件,再将此消息转发给客服。

  $(".btn-blue").click(function () {  // 点击“发送”按钮进行发送消息
    var text = $(".mesbox").val();
    if (text != "") {
      var data = {
        name: username,   // sessionStorage.username:标识用户的时间戳
        content: text
      }
      iosocket.emit('msgFromClient', data);
      $('.mesbox').val('');
      sendHtml(username, text);   // dom操作,更新聊天窗的视图
    }
  });

document.onkeydown = function (e) {
  var ev = document.all ? window.event : e;
  if (ev.keyCode == 13) {  // 回车发送消息
    $(".btn-blue").click();
    stopDefaultKey(e)
  }
}

(4)接收客服发送来的消息,主要是监听发送给当前用户的消息,此处用username接收,username即一开始进入页面生成的时间戳。

  iosocket.on('connect', function () {
    iosocket.on(username, function (msg) { // 获取客服消息
      reciveHtml('客服', msg.content);  // dom操作,更新聊天窗视图
    });
  });

此时,用户端的socket操作都已完成,剩下的都是dom操作,此处不赘述。

 

4.2 客服客户端

(1)客服端有一个很重要的数据结构,需要存储所有用户的消息记录。

var currentClient = { flag: -1, name: null } // 当前客户
var clientList = {}  // 聊天记录

① currentClient表示当前聊天对象,name为用户标识(时间戳),flag为服务端传过来的客户计数(表示第几个用户),例如:

{
  "name": "1573104726051",
  "flag": "11"
}

② clientList存储所有用户的所有聊天记录,例如:

{
  "1573104726051": {
    "list": [
      {
        "from": "client",
        "content": "helo world"
      },
      {
        "from": "client",
        "content": "this is Peter!"
      },
      {
        "from": "client",
        "content": "在吗?"
      },
      {
        "from": "serve",
        "content": "(*´▽`)ノノ"
      }
    ],
    "flag": 11,
    "noread": false
  },
  "1573105081440": {
    "list": [
      {
        "from": "client",
        "content": "this is Jessica!"
      },
      {
        "from": "client",
        "content": "Hello!"
      }
    ],
    "flag": 12,
    "noread": true
  },
  "1573105218701": {
    "list": [],
    "flag": 13,
    "noread": false
  },
  "1573105224254": {
    "list": [],
    "flag": 14,
    "noread": false
  },
  "1573109712098": {
    "list": [
      {
        "from": "client",
        "content": "你好呀"
      },
      {
        "from": "client",
        "content": "咨询一下"
      }
    ],
    "flag": 15,
    "noread": true
  }
}

(2)客服发送消息给用户

  $('.btn-blue').click(function () { // 点击发送按钮
    if (currentClient) {
      var text = $(".mesbox").val();
      if (text != "") {
        var data = {
          from: 'serve',
          to: currentClient,
          content: text
        }
        iosocketServe.emit('msgFromServe', data); // data发送给服务端
        $('.mesbox').val(''); // 清空输入框
        updateRoomView(0, data, currentClient.name); // dom操作
      }
    }
  })
document.onkeydown = function (e) { // 回车发送
  var ev = document.all ? window.event : e;
  if (ev.keyCode == 13) {
    $(".btn-blue").click();
  }
}

(3)用户进入网站,通知客服端

$(document).ready(function () {
  const iosocketServe = io.connect();
  iosocketServe.on('connect', function () {
    iosocketServe.on('clientInto', function (client) { // 用户进入网站
      clientIn(client)
    })
    iosocketServe.on('clientLeave', function (client) { // 用户离开网站
      clientOut(client)
    })
    iosocketServe.on('reciveClientMsg', function (msg) { // 接收用户消息
      updateRoomView(1, msg, msg.name)
    })
  })
})

自此,客服端的socket操作已经完成,剩下的是dom操作,此处不赘述。

 

4.3 服务端

服务端主要起到桥梁的作用,连接用户与客服,将用户发送的消息转发给客服,将客服的消息转发给用户。

const path = require('path');
const express = require('express');
const socketio = require("socket.io");
const app = new express();
const port = 2666;
app.use(express.static('public'));

app.get('/*', (req, res) => {
  const pathname = req.params['0'];
  if (!pathname) {
    res.sendFile(path.join(__dirname, 'views', 'index.html'));
    return;
  }
  res.sendFile(path.join(__dirname, 'views', pathname + '.html'))
});
var server = app.listen(port, (error) => {
  if (error) {
    console.error(error);
  } else {
    console.info('==> Listening on port %s. Open up http://localhost:%s/ in your browser.', port, port);
  }
});
const clientList = []
let onlinePeople = 0
socketio.listen(server).on('connection', function (socket) {
  socket.on('msgFromClient', function (msg) { // 接收客户端发送的消息
    socket.broadcast.emit('reciveClientMsg', {
      from: 'client',
      content: msg.content,
      name: msg.name
    })  // 发送给客服:客户发送消息
  });
  socket.on('loginIn', function (msg) { // 客户进入页面
    onlinePeople++
    let obj = {
      name: msg,  // 用时间戳来标识用户
      flag: onlinePeople // 第几个
    }
    clientList.push(obj)
    console.log( obj.name + '进入页面' )
    socket.broadcast.emit('clientInto', obj) // 发送给客服:有新客户进入页面
  });
  socket.on('loginOut', function (msg) { // 客户退出页面
    let obj = null
    for(let i=0;i

完整代码戳:》》https://gitee.com/wuchunling/contact-online

你可能感兴趣的:(JavaScript,nodeJS)