资讯专栏INFORMATION COLUMN

Vue+websocket+stompjs 实时监控坐席状态demo

yankeys / 1131人阅读

摘要:之后坐席状态改变,可以看到有事件推送过来。关于的重连程序后服务端使用这里我直接引用我的另一个项目的部分代码,这个没有使用,直接使用浏览器原生的。重连的原理很简单,就是检测到断开时,去调用我的方法,这里我也做了重连的次数限制。

由于是前后端分离的demo, 程序的后端我不管,我只负责把前端做好,这只是个demo, 还有很多不完善的地方。

2018-01-09新增:
后端的MQ事件结构现在也改了,该demo只能看看了。

html




    
    



当前状态 状态改变时间 姓名 工号 分机号 对方号码 呼入数 呼出数
{{item.agentStatus | transAgentStatus}} {{item.agentStatusTime}} {{item.userName}} {{item.loginName}} {{item.deviceId}}

js

var tm = (function(){
    var App = function(){};
    var app = App.prototype;
    var config = {
        dest: "http://xxx.xxx.xxx.xxx:58080/mvc/stomp",
        topic: "/topic/csta/namespace/testwdd2.com"
        // topic: "/topic/csta/device/8002@testwdd2.com"
    };


    var eventQueue = [];
    var vm = new Vue({
        el:"#event-queue",
        data:{
            eventQueue: eventQueue
        }
    });

    Vue.filter("transAgentStatus", function(status){
        switch(status){
            case "NotReady": return "未就绪";
            case "WorkNotReady": return "话后处理状态";
            case "Idle": return "就绪";
            case "OnCallIn": return "呼入通话";
            case "OnCallOut": return "呼出通话";
            case "Logout": return "登出";
            case "Ringing": return "振铃";
            case "OffHook": return "摘机";
            case "CallInternal": return "内部通话";
            case "Dailing": return "外线已经振铃";
            case "Ringback": return "回铃";
            case "Conference": return "会议";
            case "OnHold": return "保持";
            case "Other": return "其他";
        }

        return "";
    });

    /**
     * [render description]
     * @Author   Wdd
     * @DateTime 2016-12-26T16:06:16+0800
     * @param    {[string]} tpl [模板字符串]
     * @param    {[object]} data [data对象]
     * @return   {[string]} [渲染后的字符串]
     */
    app.render = function(tpl,data){
        var re = /{{([^}]+)?}}/g;

        while(match = re.exec(tpl)){
            tpl = tpl.replace(match[0],data[match[1]] || "");
        }

        return tpl;
    };

    app.initWebSocket = function(dest, topic){
        dest = dest || config.dest;
        topic = topic || config.topic;

        var socket = new SockJS(dest);
        var ws = Stomp.over(socket);

        ws.connect({}, function(frame) {

            ws.subscribe(topic, function(event) {
                // var eventInfo = JSON.parse(event.body);
                app.handerEvent(JSON.parse(event.body));
            });
        }, function(frame) {

            console.log(frame);
            console.error(new Date() + "websocket失去连接");
        });
    };

    /**
     * [findAgentIndex description]
     * @Author   Wdd
     * @DateTime 2016-12-28T10:34:13+0800
     * @param    {[string]} agentId [description]
     * @return   {[int]} [description]
     */
    app.findAgentIndex = function(agentId){
        for(var i = eventQueue.length - 1; i >= 0; i--){
            if(eventQueue[i].agentId === agentId){
                return i;
            }
        }

        return -1;
    };

    /**
     * [handerEvent 处理websocket事件]
     * @Author   Wdd
     * @DateTime 2016-12-28T10:33:03+0800
     * @param    {[object]} data [description]
     * @return   {[type]} [description]
     */
    app.handerEvent = function(data){
        if(data.eventType === "CallEvent"){
            return;
        }
        if(!data.eventSrc){
            return;
        }

        var eventItem = {
            agentStatus: "",
            eventName: data.eventName,
            agentId: "",
            loginName: "",
            userName: "",
            deviceId: data.deviceId,
            agentStatusTime: ""
        };

        var agent = data.eventSrc.agent || "";

        if(agent){
            eventItem.agentId = agent.agentId;
            eventItem.loginName = agent.loginName;
            eventItem.userName = agent.userName;
            eventItem.agentStatus = agent.agentStatus;
            eventItem.agentStatusTime = agent.agentStatusTime;
        }
        // 针对登出事件的agentId在外层
        else if(data.agentMode){
            eventItem.agentStatus = data.agentMode;
            eventItem.agentId = data.agentId;
        }
        else if(data.agentStatus){
            eventItem.agentStatus = data.agentStatus;
        }

        if(!eventItem.agentId){
            return;
        }

        var itemIndex = app.findAgentIndex(eventItem.agentId);

        // 新的座席加入
        if(itemIndex === -1){
            eventQueue.push(eventItem);
        }
        // 更新已有座席的状态
        else{
            eventQueue[itemIndex].agentStatus = eventItem.agentStatus;
            eventQueue[itemIndex].agentStatusTime = eventItem.agentStatusTime;
            eventQueue[itemIndex].eventName = eventItem.eventName;
        }

    };


    return new App();
})();

打开控制台,输入tm.initWebsocket()后,websocket连接正常。

之后坐席状态改变,可以看到有事件推送过来。

看下整个页面:

最后,这个小小的监控如果用jQuery写,也可以,不过就是太坑了,每次都要去找到Dom元素,再更新DOM,用了Vue这类的框架,页面的dom操作完全不用关心了,真是太舒服了。(^o^)/

关于stomp的重连

程序后服务端使用RabbitMQ
这里我直接引用我的另一个项目的部分代码,这个没有使用SockJS, 直接使用浏览器原生的WebSocket。
重连的原理很简单,就是检测到断开时,去调用我的reconnectWs方法,这里我也做了重连的次数限制。

initWebSocket: function(callback, errorCallback) {
            callback = callback || function(){};

            if(ws && ws.connected){
                return;
            }

            Config.isManCloseWs = false;

            var url = Config.wsProtocol + Config.SDK + Config.eventPort + Config.eventBasePath + "/websocket";

            if(typeof WebSocket != "function"){
                alert("您的浏览器版本太太太老了,请升级你的浏览器到IE11,或使用任何支持原生WebSocket的浏览器");
                return;
            }

            try{
                var socket = new WebSocket(url);
            }
            catch(e){
                console.log(e);
                return;
            }


            var wsHeartbeatId = "";

            ws = Stomp.over(socket);

            if(!Config.useWsLog){
                ws.debug = null;
            }

            ws.connect({}, function(frame) {

                Config.currentReconnectTimes = 0;

                var dest = Config.newWsTopic + env.loginId.replace(/./g,"_");

                var lastEventSerial = "";

                ws.subscribe(dest, function(event) {
                    var eventInfo = {};

                    try{
                        eventInfo = JSON.parse(event.body);
                        delete eventInfo.params;
                        delete eventInfo._type;
                        delete eventInfo.topics;
                    }
                    catch(e){
                        console.log(e);
                        return;
                    }

                    if(lastEventSerial === eventInfo.serial){
                        util.error("Error: event repeat sent !");
                        return;
                    }
                    else{
                        lastEventSerial = eventInfo.serial;
                    }

                    if(Config.useEventLog){
                        util.debugout.log(" " + JSON.stringify(eventInfo));
                    }

                    eventHandler.deliverEvent(eventInfo);
                });
                callback();

            }, function(frame) {
                // websocket upexpected disconnected
                // maybe network disconnection, or browser in offline
                // this condition will emit wsDisconnected event
                if(Config.isManCloseWs){return;}
                errorCallback();

                util.log(frame);
                util.error(new Date() + "websocket disconnect");
                // clearInterval(wsHeartbeatId);

                if(Config.currentReconnectTimes < Config.maxReconnectTimes){
                    Config.currentReconnectTimes++;
                    util.reconnectWs();
                }
                else{
                    var errorMsg = {
                        eventName: "wsDisconnected",
                        msg: "websocket disconnect"
                    };
                    wellClient.ui.main({
                        eventName:"wsDisconnected"
                    });
                    util.debugout.log(">>> websocket disconnect");

                    wellClient.triggerInnerOn(errorMsg);
                }
            });
        },

        reconnectWs: function(){
            setTimeout(function(){
                util.log(">>> try to reconnect");
                util.debugout.log(">>> try to reconnect");
                util.initWebSocket(function(){},function(){});

            }, Config.timeout * 1000);
        },
参考

STOMP Over WebSocket

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86669.html

相关文章

  • Vue+websocket+stompjs 实时监控坐席状态demo

    摘要:之后坐席状态改变,可以看到有事件推送过来。关于的重连程序后服务端使用这里我直接引用我的另一个项目的部分代码,这个没有使用,直接使用浏览器原生的。重连的原理很简单,就是检测到断开时,去调用我的方法,这里我也做了重连的次数限制。 由于是前后端分离的demo, 程序的后端我不管,我只负责把前端做好,这只是个demo, 还有很多不完善的地方。 2018-01-09新增:后端的MQ事件结构现在也...

    EdwardUp 评论0 收藏0
  • websocket+sockjs+stompjs详解及实例

    摘要:面向消息的简单文本协议。为提供了备选方案。但无论哪种场景,对于实际应用来说,这种通信形式层级过低。协议,来为浏览器和间的通信增加适当的消息语义。协议解决了浏览器发起请求以及服务器响应请求的细节,假设协议并不存在,只能使用套接字来编写应用。 最近有项目需求要用到websocket,刚开始以为很简单,但是随着遇到问题,深入了解,才知道websocket并不是想象中的那么简单,这篇文章主要是...

    remcarpediem 评论0 收藏0
  • websocket+sockjs+stompjs详解及实例

    摘要:面向消息的简单文本协议。为提供了备选方案。但无论哪种场景,对于实际应用来说,这种通信形式层级过低。协议,来为浏览器和间的通信增加适当的消息语义。协议解决了浏览器发起请求以及服务器响应请求的细节,假设协议并不存在,只能使用套接字来编写应用。 最近有项目需求要用到websocket,刚开始以为很简单,但是随着遇到问题,深入了解,才知道websocket并不是想象中的那么简单,这篇文章主要是...

    keithyau 评论0 收藏0
  • websocket+sockjs+stompjs详解及实例

    摘要:面向消息的简单文本协议。为提供了备选方案。但无论哪种场景,对于实际应用来说,这种通信形式层级过低。协议,来为浏览器和间的通信增加适当的消息语义。协议解决了浏览器发起请求以及服务器响应请求的细节,假设协议并不存在,只能使用套接字来编写应用。 最近有项目需求要用到websocket,刚开始以为很简单,但是随着遇到问题,深入了解,才知道websocket并不是想象中的那么简单,这篇文章主要是...

    Corwien 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<