html5客服系统源码(html可视化布局系统源码)

h5效果图

spring boot+vue实现H5聊天室客服功能

h5页面聊天

vue效果图

spring boot+vue实现H5聊天室客服功能

vue页面聊天

功能实现

spring boot + webSocket 实现官方地址 https://docs.spring.io/spring-framework/docs/5.0.8.RELEASE/spring-framework-reference/web.html#websocket

maven 配置文件

    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-thymeleaf</artifactId>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>1.2.78</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-websocket</artifactId>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies>

webSocket 配置

package com.example.webchat.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;/** * @author Mr.Fang * @title: WebSocketConfig * @Description: web socket 配置 * @date 2021/11/14 13:12 */@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer {    @Override    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {        registry.addHandler(myHandler(), "myHandler/") // 访问路径                .addInterceptors(new WebSocketHandlerInterceptor())  // 配置拦截器                .setAllowedOrigins("*"); // 跨域    }    @Bean    public ServletServerContainerFactoryBean createWebSocketContainer() {        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();        container.setMaxTextMessageBufferSize(8192);  // 例如消息缓冲区大小、空闲超时等        container.setMaxBinaryMessageBufferSize(8192);        return container;    }    @Bean    public WebSocketHandler myHandler() {        return new MyHandler();    }}

消息处理类

package com.example.webchat.config;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.example.webchat.pojo.DataVo;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.AbstractWebSocketHandler;import java.io.IOException;import java.util.*;import java.util.concurrent.ConcurrentHashMap;/** * @author Mr.Fang * @title: MyHandler * @Description: 消息处理类 * @date 2021/11/14 13:12 */public class MyHandler extends AbstractWebSocketHandler {    private static int onlineCount = 0;    //    线程安全    private static Map<String, WebSocketSession> userMap = new ConcurrentHashMap<>(); // 用户    private static Map<String, WebSocketSession> adminMap = new ConcurrentHashMap<>(); // 客服    /**     * @Description: 连接成功之后     * @param session     * @return void     * @Author Mr.Fang     * @date 2021/11/14 13:15     */    @Override    public void afterConnectionEstablished(WebSocketSession session) throws IOException {        addOnlineCount(); // 当前用户加 1        System.out.println(session.getId());        Map<String, Object> map = session.getAttributes();        Object token = map.get("token");        Object admin = map.get("admin");        DataVo dataVo = new DataVo();        dataVo.setCode(9001).setMsg("连接成功");        if (Objects.nonNull(admin)) {            adminMap.put(session.getId(), session); // 添加客服        } else  {            //        分配客服            userMap.put(session.getId(), session); // 添加当前用户            distribution(dataVo);        }        dataVo.setId(session.getId());        System.out.println("用户连接成功:" + admin);        System.out.println("用户连接成功:" + token);        System.out.println("在线用户:" + getOnlineCount());        this.sendMsg(session, JSONObject.toJSONString(dataVo));    }    /**     * @param vo     * @return void     * @Description: 分配客服     * @Author Mr.Fang     * @date 2021/11/14 13:13     */    private void distribution(DataVo vo) {        if (adminMap.size() != 0) {            Random random = new Random();            int x = random.nextInt(adminMap.size());            Set<String> values = adminMap.keySet();            int j = 0;            for (String str : values) {                if (j == x) {                    vo.setRecId(str);                    System.out.println("分配ID:" + str);                    break;                }                j++;            }        }    }    /**     * @param session     * @param message     * @return void     * @Description: 收发消息     * @Author Mr.Fang     * @date 2021/11/14 13:13     */    @Override    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {        System.out.print("用户ID:" + session.getId());        String payload = message.getPayload();        System.out.println("接受到的数据:" + payload);        DataVo dataVo = JSON.toJavaObject(JSON.parseObject(payload), DataVo.class); // json 转对象        if (Objects.isNull(dataVo.getRecId()) || dataVo.getRecId().equals("")) { // 用户客服为空 分配客服            WebSocketSession socketSession = adminMap.get(session.getId());            if (Objects.isNull(socketSession)) {                this.distribution(dataVo);            }        }        if (dataVo.getCode() == 9002) {            if (Objects.nonNull(dataVo.getRecId())) { // user -> admin                WebSocketSession socketSession = adminMap.get(dataVo.getRecId());                dataVo.setSelfId(session.getId()).setRecId("");                this.sendMsg(socketSession, JSONObject.toJSONString(dataVo));            } else if (Objects.nonNull(dataVo.getSelfId())) { // admin ->user                WebSocketSession socketSession = userMap.get(dataVo.getSelfId());                dataVo.setRecId(session.getId()).setSelfId("");                this.sendMsg(socketSession, JSONObject.toJSONString(dataVo));            }        }    }    /**     * @param session     * @param msg     * @return void     * @Description: 发送消息     * @Author Mr.Fang     * @date 2021/11/14 13:14     */    private void sendMsg(WebSocketSession session, String msg) throws IOException {        session.sendMessage(new TextMessage(msg));    }    /**     * @Description: 断开连接之后     * @param session     * @param status     * @return void     * @Author Mr.Fang     * @date 2021/11/14 13:14     */    @Override    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {        subOnlineCount(); // 当前用户加 1        adminMap.remove(session.getId());        userMap.remove(session.getId());        System.out.println("用户断开连接token:" + session.getId());        System.out.println("用户断开连接admin:" + session.getId());        System.out.println("在线用户:" + getOnlineCount());    }    public static synchronized int getOnlineCount() {        return onlineCount;    }    /**     * @Description: 在线用户 +1     * @return void     * @Author Mr.Fang     * @date 2021/11/14 13:16     */    public static synchronized void addOnlineCount() {        MyHandler.onlineCount++;    }    /**     * @Description: 在线用户 -1     * @return void     * @Author Mr.Fang     * @date 2021/11/14 13:16     */    public static synchronized void subOnlineCount() {        MyHandler.onlineCount--;    }}

配置拦截器

package com.example.webchat.config;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.http.server.ServletServerHttpRequest;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;import javax.servlet.http.HttpServletRequest;import java.util.Map;import java.util.Objects;/** * @author Mr.Fang * @title: WebSocketHandlerInterceptor * @Description: 拦截器 * @date 2021/11/14 13:12 */public class WebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {    /**     * @param request     * @param response     * @param wsHandler     * @param attributes     * @return boolean     * @Description: 握手之前     * @Author Mr.Fang     * @date 2021/11/14 13:18     */    @Override    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {        ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;        HttpServletRequest re = servletRequest.getServletRequest();        Object token = re.getParameter("token");        Object admin = re.getParameter("admin");        if (Objects.isNull(token)) {            return false;        }        re.getSession().setAttribute("admin", admin);        re.getSession().setAttribute("token", token);        return super.beforeHandshake(request, response, wsHandler, attributes);    }    /**     * @param request     * @param response     * @param wsHandler     * @param ex     * @return boolean     * @Description: 握手之后     * @Author Mr.Fang     * @date 2021/11/14 13:18     */    @Override    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {        super.afterHandshake(request, response, wsHandler, ex);    }}

h5服务端

<!DOCTYPE html><html><head><meta charset="utf-8"><title>服务端</title><style type="text/css">#client {margin: 0px auto;width: 500px;}input {width: 80%;height: 40px;border-radius: 5px;border-color: #CCCCCC;outline: #01FA01;}#button {width: 84px;height: 46px;background-color: #5af3a5;color: #fff;font-size: 20px;border-radius: 5px;border: none;box-shadow: 1px 1px 1px 1px #ccc;cursor: pointer;outline: #01FA01;}</style></head><body><div id="client"><h1 style="text-align: center;">服务端发送消息</h1><div id="content" contenteditable=truestyle="width: 500px;height: 500px;margin: 0px auto;border: 1px solid #000000;padding: 10px;border-radius: 10px;overflow: auto;"></div><div style="padding: 5px;0px"><input type="" value="" /> <button id="button" type="button">发送</button></div></div><script src="http://code.jquery.com/jquery-2.1.1.min.js"></script><script type="text/javascript">$(() => {var pushData = {code: 9002,msg: '',selfId: '',};var time = null;var path = 'ws://127.0.0.1:8009/myHandler/';if (typeof(WebSocket) === "undefined") {alert('不支持websocket')return;}let id = Math.random(); // 随机数// 实例化socketvar webSocket = new WebSocket(path + '?token=' + id+'&admin=1');// 监听连接webSocket.onopen = function(event) {console.log(event);interval();};// 监听消息webSocket.onmessage = function(event) {let data = JSON.parse(event.data); pushData.selfId = data.selfId;if (data.code == 9002) {$('#content').append(`<p style="text-align: right;"><span style="color:chocolate;">${data.msg}</span>:客户端</p>`)} else if (data.code == 9001) {$('#content').append(`<p style="color:#a09b9b;text-align:center;" >连接成功</p>`);}console.log(event)};// 监听错误webSocket.onerror = function(event) {console.log(event)$('#content').append(`<p style="color:#a09b9b;text-align:center;" >连接错误</p>`);clearInterval();};// 发送消息$('#button').click(() => {let v = $('input').val();if (v) {pushData.code = 9002;pushData.msg = v;webSocket.send(JSON.stringify(pushData));$('#content').append(`<p>服务端:<span style="color: blueviolet;">${v}</span></p>`)$('input').val('');}})function interval() {time = setInterval(() => {pushData.code = 9003;pushData.msg = '心跳';webSocket.send(JSON.stringify(pushData));}, 5000);}function clearInterval() {clearInterval(time);}})</script></body></html>

客户端

<!DOCTYPE html><html><head><meta charset="utf-8"><title>客户端</title><style type="text/css">#client {margin: 0px auto;width: 500px;}input {width: 80%;height: 40px;border-radius: 5px;border-color: #CCCCCC;outline: #01FA01;}#button {width: 84px;height: 46px;background-color: #5af3a5;color: #fff;font-size: 20px;border-radius: 5px;border: none;box-shadow: 1px 1px 1px 1px #ccc;cursor: pointer;outline: #01FA01;}</style></head><body><div id="client"><h1 style="text-align: center;">客户端发送消息</h1><div id="content" contenteditable=truestyle="width: 500px;height: 500px;margin: 0px auto;border: 1px solid #000000;padding: 10px;border-radius: 10px;overflow: auto;"></div><div style="padding: 5px;0px"><input type="" value="" /> <button id="button" type="button">发送</button></div></div><script src="http://code.jquery.com/jquery-2.1.1.min.js"></script><script type="text/javascript">$(() => {var pushData = {code: 9002,msg: '',recId: '',};var time = null;var path = 'ws://127.0.0.1:8009/myHandler/';if (typeof(WebSocket) === "undefined") {alert('不支持websocket')return;}let id = Math.random(); // 随机数// 实例化socketvar webSocket = new WebSocket(path + '?token=' + id);// 监听连接webSocket.onopen = function(event) {console.log(event);interval();};// 监听消息webSocket.onmessage = function(event) {let data = JSON.parse(event.data);if (data.code == 9002) {$('#content').append(`<p style="text-align: right;"><span style="color:chocolate;">${data.msg}</span>:服务端</p>`)} else if (data.code == 9001) {$('#content').append(`<p style="color:#a09b9b;text-align:center;" >连接成功</p>`);}console.log(event)};// 监听错误webSocket.onerror = function(event) {console.log(event)$('#content').append(`<p style="color:#a09b9b;text-align:center;" >连接错误</p>`);clearInterval();};// 发送消息$('#button').click(() => {let v = $('input').val();if (v) {pushData.code = 9002;pushData.msg = v;webSocket.send(JSON.stringify(pushData));$('#content').append(`<p>客户端:<span style="color: blueviolet;">${v}</span></p>`)$('input').val('');}})function interval() {time = setInterval(() => {pushData.code = 9003;pushData.msg = '心跳';webSocket.send(JSON.stringify(pushData));}, 5000);}function clearInterval() {clearInterval(time);}})</script></body></html>

原创文章,作者:admin,如若转载,请注明出处:https://www.qq65hfghe5.com/tg/48763.html