客服系统即时通讯IM开发(四)网站实现实时在线访客列表【唯一客服】网站在线客服系统...

news2024/11/16 19:05:06

在使用我的客服系统时,如果引入了我的js ,就可以实时看到网站上的所有访客了

  1. 使用 WebSocket 技术来实现实时通信。

  2. 在访客登录或退出时,向指定客服的 WebSocket 客户端发送消息。例如,你可以在访客登录时,向指定客服的 WebSocket 客户端发送一条消息,告诉客户端有一个新的访客登录。在客户端收到消息后,更新访客列表。例如,你可以在客户端收到新访客登录的消息后,在访客列表中新增一个访客。退出时也给客服发送消息,告诉访客已经退出,这样就会实时的获取到在线的访客了

  3. 利用全局变量存储访客信息

用Go语言Gin框架实现的一个客服系统的WebSocket服务端。它允许客户端使用WebSocket协议连接到服务器并实时交换消息。

服务器根据消息的“type”字段处理消息并根据需要执行不同的操作。

例如,如果消息类型为“monitorOnline”,服务器将发送访客上线的信息给客服。访客离线的时候,发送monitorOffline离线信息给客服

使用“MonitorList”的全局变量map,用于存储访客正在访问的标题、地址、时间等相关信息。

    //网站监控
    engine.GET("/ws_monitor", ws.NewMonitorServer)
package ws

import (
    "encoding/json"
    "github.com/gin-gonic/gin"
    "github.com/gorilla/websocket"
    "github.com/tidwall/gjson"
    "kefu/tools"
    "log"
    "net/http"
    "time"
)

type MonitorConnection struct {
    KefuName  string
    UinqId    string
    Title     string
    Url       string
    Refer     string
    StartTime string
    ClientIp  string
}

var MonitorList = make(map[*websocket.Conn]*MonitorConnection)

/**
网站监控
*/
func NewMonitorServer(c *gin.Context) {
    conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
    if err != nil {
        http.NotFound(c.Writer, c.Request)
        log.Println("upgrade error:", err)
        return
    }
    //获取GET参数
    kefuName := c.Query("kefu_name")
    if kefuName == "" {
        conn.Close()
        return
    }
    connection := &MonitorConnection{
        UinqId:    tools.Uuid(),
        ClientIp:  c.ClientIP(),
        KefuName:  kefuName,
        StartTime: tools.DateDefault(time.Now()),
    }
    MonitorList[conn] = connection
    conn.WriteMessage(websocket.TextMessage, []byte("ok"))
    for {
        //接受消息
        var receive []byte
        _, receive, err := conn.ReadMessage()
        if err != nil {
            msg := TypeMessage{
                Type: "monitorOffline",
                Data: connection,
            }
            str, _ := json.Marshal(msg)
            OneKefuMessage(kefuName, str)
            delete(MonitorList, conn)
            return
        }

        msgType := gjson.Get(string(receive), "type").String()

        switch msgType {
        case "monitorOnline":
            title := gjson.Get(string(receive), "data.title").String()
            url := gjson.Get(string(receive), "data.url").String()
            refer := gjson.Get(string(receive), "data.refer").String()
            connection.Title = title
            connection.Url = url
            connection.Refer = refer
            msg := TypeMessage{
                Type: "monitorOnline",
                Data: connection,
            }
            str, _ := json.Marshal(msg)
            OneKefuMessage(kefuName, str)
        case "cursor":

        }

    }
}

javascript客户端的代码

它使用WebSocket连接到服务器。当连接关闭时,会尝试重新连接。当收到服务器的“ok”时,会把当前访问的标题、网址、来源等信息发送给服务端

/**
 * 连接websocket
 */
KEFU.connect=function () {
    var _this=this;
    var domain=getDomainFromUrl(_this.KEFU_URL);
    var protocol=getProtocolFromUrl(_this.KEFU_URL);
    var wsProtocol="ws://";
    if(protocol=="https"){
        wsProtocol="wss://";
    }
    let ws = new WebSocket(wsProtocol+domain+"/ws_monitor?kefu_name="+this.KEFU_KEFU_ID);

   ws.onopen = function () {
        console.log('WebSocket 连接已打开');
        _this.reconnectTimes = 0;
    };

    ws.onclose = function () {
        console.log('WebSocket 连接已关闭');
        // 尝试重连
        _this.reconnect();
    };
    ws.onmessage = function (event) {
        console.log(`收到服务器的消息:${event.data}`);
        let data=event.data;
        let message={
            "type":"monitorOnline",
            "data":{
                "url":window.location.href,
                "title":document.title,
                "refer":document.referrer
            }
        }
        if(data=="ok"){
            ws.send(JSON.stringify(message))
        }
        // // 解析消息
        // const message = JSON.parse(event.data);
        // if (message.type === 'message') {
        //     console.log(`收到消息:${message.data}`);
        // }
    };
    _this.ws=ws;
}
// 尝试重连
KEFU.reconnect=function(){
    var _this=this;
    if (_this.reconnectTimes >= _this.MAX_RECONNECT_TIMES) {
        console.log('重连失败');
        return;
    }

    _this.reconnectTimes++;
    console.log(`正在尝试重连(第 ${_this.reconnectTimes} 次)`);

    setTimeout(function () {
        _this.connect();
    }, _this.RECONNECT_INTERVAL);
}

唯一在线客服系统

https://gofly.v1kf.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150110.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

测试用例的设计? 万能公式

万能公式(必背):功能测试性能测试界面测试兼容性测试易用性测试安全测试功能测试 :可能来自于需求文档,也可能来自生活经验性能测试 :功能没有问题不代表性能是ok的,性能往往体现在一些极端情况界面测试 :颜…

Prometheus-基于Consul的自动注册

一、背景介绍 如果我们的物理机有很多,不管是基于"file_sd_config"还是"kubernetes_sd_config",我们都需要手动写入目标target及创建目标service,这样才能被prometheus自动发现,为了避免重复性工作过多&#…

【182】Java8利用二叉查找树实现Map

本文利用二叉查找树写了一个Map,用来保存键值对。 二叉查找树的定义 二叉查找树又名二叉搜索树,英文名称是 Binary Search Tree,缩写BST。 二叉排序树,英文名称是 Binary Sorted Tree,缩写BST。 二叉查找树、二叉搜…

excel实用技巧:如何构建多级下拉菜单

使用数据有效性制作下拉菜单对大多数小伙伴来说都不陌生,但说到二级和三级下拉菜单大家可能就不是那么熟悉了。什么是二级和三级下拉菜单呢?举个例子,在一个单元格选择某个省后,第二个单元格选项只能出现该省份所属的市&#xff0…

vue-router原理简单实现

vue-router简单实现 初步预习 动态路由 获取id方式 第一种强依赖路由 第二种父传子方式(推荐) 嵌套路由 相同的头和尾,默认index,替换为detail 编程时导航 this.$router.push() this.$router.repleace() this.$router.g…

吊炸天,springboot的多环境配置一下搞明白了!

1、 使用springboot的profile命名规则profile用于多环境的激活和配置,用来切换生产,测试,本地等多套不通环境的配置。如果每次去更改配置就非常麻烦,profile就是用来切换多环境配置的。在Spring Boot框架中,使用Profil…

漏洞优先级排序的六大关键因素

当我们谈及开源漏洞时,我们会发现其数量永远处于增长状态。根据安全公司 Mend 研究发现,在 2022 年前九个月发现并添加到其漏洞数据库中的开源漏洞数量比 2021 年增加了 33%。该报告从 2022 年 1 月到 2022 年 9 月对大约 1,000 家北美公司进行了代表性抽…

一篇文章解决C语言操作符

我的主页:一只认真写代码的程序猿本文章是关于C语言操作符的讲解收录于专栏【C语言的学习】 目录 1、算术操作符 2、赋值操作符 3、关系操作符 4、条件操作符(三目) 5、逻辑操作符 6、单目操作符 7、移位操作符 8、位操作符 9、逗号…

使用Docker+Nignx部署vue项目

文章目录一、前言二、vue项目打包三、nginx基本介绍①nginx常用的功能:②nginx默认的主题配置文件解读③nginx目录解读三、docker内部署nginx①拉取nginx镜像②创建数据持久化目录☆☆☆③创建需要映射进去的文件④运行nginx四、大工告成最近(之前&#…

2023年DAMA-CDGA/CDGP数据治理工程师认证(线上班)报名

DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业…

gcc、g++,linux升级gcc、g++

安装cv-cuda库,要求gcc11,cmake>3.22版本。 Linux distro:Ubuntu x86_64 > 18.04WSL2 with Ubuntu > 20.04 (tested with 20.04) CUDA Driver > 11.7 (Not tested on 12.0) GCC > 11.0 Python > 3.7 cmake > 3.22gcc、g介绍 参考&…

手把手安装GNN必备库 —— pytorch_geometric

0 BackGround GNN:图神经网络,由于传统的CNN网络无法表示顶点和边这种关系型数据,便出现了图神经网络解决这种图数据的表示问题,这属于CNN往图方向的应用扩展。 GCN:图卷积神经网络,GNN在训练过程中&#…

【ONE·R || 两次作业(二):GEO数据处理下载分析】

总言 两次作业汇报其二:GEO数据处理学习汇报。    文章目录总言2、作业二:GEO数据处理下载分析2.1、GEO数据库下载前准备2.2、GEO数据库下载及数据初步处理2.2.1、分阶段解析演示2.2.1.1、编号下载流程2.2.1.2、对gset[ 1 ]初步分析2.2.1.3、对gset[ 2…

基于requests框架实现接口自动化测试项目实战

requests库是一个常用的用于http请求的模块,它使用python语言编写,在当下python系列的接口自动化中应用广泛,本文将带领大家深入学习这个库,Python环境的安装就不在这里赘述了,我们直接开干。 01 requests的安装 win…

销售结束语话术

销售要记住,结束语不代表结束,而是下一次沟通的开始,所以销售要学会通过结束语来为自己争取下次沟通的机会。 前言 不论是哪一行业,对于销售而言,大多数成交的客户都是经过持续有效的跟踪的,还会出现有很多…

Java设计模式-原型模式Prototype

介绍 当我们有一个类的实例(Prototype)并且我们想通过复制原型来创建新对象时,通常使用Prototype模式。 原型模式是一种创建型设计模式。能够复制已有对象, 而又无需使代码依赖它们所属的类。 场景举例 现在有一只羊 tom&#xf…

iTerm2连接ssh配置

iTerm2连接ssh配置 #首先在/Users目录下按照如下命令创建sh脚本 cd /Users/#创建iterm文件夹 mkdir iterm#进入iterm文件夹 cd iterm#创建myserver.sh文件 touch myserver.sh#编辑myserver.sh文件 vi myserver.sh如果出现没有权限,就命令前面加上sudo 键盘输入i编…

斯皮尔曼相关(spearman)相关性分析一文详解+python实例代码

前言 相关性分析算是很多算法以及建模的基础知识之一了,十分经典。关于许多特征关联关系以及相关趋势都可以利用相关性分析计算表达。其中常见的相关性系数就有三种:person相关系数,spearman相关系数,Kendalls tau-b等级相关系数…

Java + OpenCv 根据PID/VID调用指定摄像头

问题: 主机接入了多个USB摄像头,传统的OpenCv是用摄像头插入usb的下标调取的,如过只接入一个摄像头那直接使用capture.open(0);这种方式调用没有任何问题,多个的话,就会出现问题,因为USB拔插时候对应摄像头…

用原生的方式写vue组件之深度剖析组件内部的原理

目录前言一,对组件的复习及理解二,模块化与组件化三,用原生的方式写vue组件3.1 准备工作3.2 创建组件3.3 组件中的data为什么是函数式写法3.4 组件中的template四,注册组件五,使用组件六,全局组件七&#x…