• 好用的在线客服系统PHP源码(开源代码+终身使用+安装教程)


    ​在线客服系统是一套交互式沟通工具,采用PHP+MYSQL开发。高性能,不卡顿。使用它可以迅速缩小你的选择范围,联系多个供应商、客户等,也可以给你的企业一个关于用户体验的重大影响。(尾部下载完整版PHP客服系统源码)
    在这里插入图片描述
    在这里插入图片描述

    一,思路梳理

    1,首先思考群聊的实现方式。
    ​2,再来举一反三,思考单聊的实现方式。
    有一个地方需要提一下,比如要给A用户发送消息,就要根据A的userId得到连接对象,然后就会把消息发送给A用户。

    二,代码分析

    1,首先是用户聊天框的js代码(html忽略)
    此为用户点击在线客服按钮进入聊天框页面就执行的js代码。

    说明:下面接收人id写死了为超级管理员,我这里省事情了,因为超级管理员的账号(也就是唯一标识)就是超级管理员这五个字,当真正开发时就要动态获取唯一标识了!

    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    2,其次为后台系统客服聊天框的js代码

    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108

    3,最后为服务端的websocket实例

    package com.qianlong.controller;
    
    import com.qianlong.service.SelectService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import javax.websocket.OnClose;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    /**
     * 聊天室的服务端程序
     * @author Administrator
     *
     */
    //声明websocket某个服务端的地址
    @ServerEndpoint(value = "/charRoomServer/{param}")
    @Component
    public class ChatRoomServer {
        @Autowired
        public static SelectService selectService;
        private boolean firstFlag=true;
        private Session session;
        private String userName;
    
        //发送人id
        private String userId;
        //key代表此次客户端的userId,value代表此次连接对象
        private static final HashMap connectMap=new HashMap();
        //保存所有用户昵称信息
        //key是session的id,value是用户昵称
        private static final HashMap userMap=new HashMap();
        //服务端收到客户端的连接请求,连接成功后会执行此方法
        @OnOpen
        public void start(@PathParam(value = "param") String param, Session session) {
            this.session=session;
            this.userId=param; //接收参数
            connectMap.put(param,this);
        }
    
        //客户端发来的信息,服务端接收
        @OnMessage              //接收人userId
        public void chat(String clientMessage,Session session) {
            //firstFlag为true是第一次进入,第二次进入之后设为false
            ChatRoomServer client=null;
            if(firstFlag) {
                this.userName=clientMessage;
                //将新进来的用户保存到用户map
                userMap.put(session.getId(), userName);
    
                try {
                   if("超级管理员".equals(userId)){
    
                   }else{
                       //构造发送给客户端的提示信息
                       String message=htmlMessage("大白机器人:","亲爱的"+userId+",您想了解点儿啥?");
                       client=(ChatRoomServer) connectMap.get(userId);
                       //给对应的web端发送一个文本信息
                       client.session.getBasicRemote().sendText(message);
                   }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                firstFlag=false;
            }else {
                System.err.println("clientMessage:"+userName);
                //给对方发消息
                String message1=htmlMessage(userId,clientMessage);
                client  = (ChatRoomServer) connectMap.get(userName);
               if(client!=null){
                   try {
                       client.session.getBasicRemote().sendText(message1);
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
                //给自己窗口发消息
                String message2=htmlMessage(userId,clientMessage);
                client  = (ChatRoomServer) connectMap.get(userId);
                try {
                    client.session.getBasicRemote().sendText(message2);
                } catch (IOException e) {
                    e.printStackTrace();
                }
               
                //这是将前台用户发送的消息存数据库并标记为未读,和上面通信没关系
                if("超级管理员".equals(userId)){
    
                }else{
                    Map map=new HashMap();
                    map.put("account",userId);
                    map.put("message",clientMessage);
                    map.put("addtime",new Date());
                    int i = selectService.chatInsert(map);
                    System.out.println(i);
                }
            }
            }
        
        /**
         * 前台js的ws.close事件,会触发后台的标注onClose的方法
         */
        @OnClose
        public void close() {
            userMap.remove(session.getId());
            connectMap.remove(userId);
        }
        /**
         * 渲染页面,把信息构造好标签再发送
         */
        public String htmlMessage(String userName,String message) {
            StringBuffer stringBuffer=new StringBuffer();
            SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            stringBuffer.append("
    "); stringBuffer.append(""+sf.format(new Date())+""); stringBuffer.append("
    "); stringBuffer.append("

    "+userName+"

    "
    ); stringBuffer.append("
    "
    ); stringBuffer.append("
    "); stringBuffer.append("
    "
    ); stringBuffer.append("
    "+message+"
    "
    ); stringBuffer.append("
    "
    ); stringBuffer.append("
    "
    ); //这里拼接了消息发送人的userId,在前台进行截取字符串接收发送人的userId stringBuffer.append("|"+userName); return stringBuffer.toString(); } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136

    三,依赖注入

    在websocket中进行依赖注入service并调用service方法进行数据库存储,如果按常规的方式是走不通的。

    解决方式:

    在该springboot项目中添加一个WebsocketConfig配置类,对service进行配置。

    @Configuration
    public class WebSocketConfig {
        /**
         * ServerEndpointExporter 用于扫描和注册所有携带 ServerEndPoint 注解的实例,
         * 若部署到外部容器 则无需提供此类。
         */
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    
        
    
        
         * 因 SpringBoot WebSocket 对每个客户端连接都会创建一个 WebSocketServer(@ServerEndpoint 注解对应的对象,Bean 注入操作会被直接略过,因而手动注入一个全局变量
         */
        @Autowired
        public void setSelectService(SelectService selectService) {
            ChatRoomServer.selectService = selectService;
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    然后在websocket中注入service。

    四,效果展示

    在这里插入图片描述
    在这里插入图片描述

    五,源码下载

    php客服系统源码包下载地址:
    https://yfi.lanzouj.com/iHN4A061ok5c

  • 相关阅读:
    【开源】SpringBoot框架开发房屋出售出租系统
    『C++成长记』类和对象
    一些资源收集
    “轻松实现文件复制备份,自动编号轻松管理
    在找工作时的准备工作:结合现状,针对意向企业做好充分准备
    IO流总结
    图数据库(Neo4j)入门
    微信小程序案例3-1 比较数字
    go语言中的结构体和组合思想入门示例
    阶段五-Day02-jQuery
  • 原文地址:https://blog.csdn.net/q906270629/article/details/126248962