当前位置:首页 > 生活百科

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

栏目:生活百科日期:2025-03-12浏览:0

h5效果图

h5页面聊天

vue效果图

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&>&<p id="client"&>&<h1&>服务端发送消息&</h1&>&<p id="content" contenteditable=truestyle="width: 500px;height: 500px;margin: 0px auto;border: 1px solid #000000;padding: 10px;border-radius: 10px;overflow: auto;"&>&</p&>&<p&>&<input type="" value="" /&> &<button id="button" type="button"&>发送&</button&>&</p&>&</p&>&<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&>&<span&>${data.msg}&</span&>:客户端&</p&>`)} else if (data.code == 9001) {$('#content').append(`&<p &>连接成功&</p&>`);}console.log(event)};// 监听错误webSocket.onerror = function(event) {console.log(event)$('#content').append(`&<p &>连接错误&</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&>${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&>&<p id="client"&>&<h1&>客户端发送消息&</h1&>&<p id="content" contenteditable=truestyle="width: 500px;height: 500px;margin: 0px auto;border: 1px solid #000000;padding: 10px;border-radius: 10px;overflow: auto;"&>&</p&>&<p&>&<input type="" value="" /&> &<button id="button" type="button"&>发送&</button&>&</p&>&</p&>&<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&>&<span&>${data.msg}&</span&>:服务端&</p&>`)} else if (data.code == 9001) {$('#content').append(`&<p &>连接成功&</p&>`);}console.log(event)};// 监听错误webSocket.onerror = function(event) {console.log(event)$('#content').append(`&<p &>连接错误&</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&>${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&>

“html5客服系统源码(html可视化布局系统源码)” 的相关文章

国际网络营销师是做什么的,网络营销师速成班对小白有效

最近几年出现了许多的新兴职业,例如狗粮试吃员这个职业就曾出现在各大媒体的首页职业狗粮试吃员先要通过训练来掌握狗类喜欢或厌恶的味道。经过训练后,他们就要品尝各类狗...

lol五个位置的英文简称(电竞所有专业术语)

英雄联盟作为一款5v5的游戏,有着各种各样的定位,战术以玩法,每个人心目中都有每个位置的玩法,如果用一个字形容你心目中位置的玩法会是什么呢?ADC,俗称射手-猛...

a5创业网靠谱吗,简述a5创业网发展历程

2020年1月,新型冠状病毒肺炎疫情在全国肆虐。疫情不仅牵动着我们每个人的生活,更是对中国经济造成了严重的影响。餐饮、旅游、农业、制造业等行业因为停工造成的产能...

mysql安装包安装步骤(mysql安装教程详细教程)

部署mysql5.7.251、下载rpm安装包。2、上传到服务器,解压。3、卸载之前的版本。4、按照顺序安装:rpm-ivhmysql-community-co...

你没发现摆地摊和互联网推广是有多相似吗-

摆地摊一直受到城管等各种因素的限制,有过逛夜市的朋友肯定都看过城管追着摆地摊的人跑,甚至是砸了他们的摊子;就算你没见过,在电影里这样的场景应该不陌生吧?其实地摊...

产品推广策划书案例(5步教你写出精美好文)

小西牛乳品——从2亿到10亿,小西牛如何跨越?小西牛全案策划纪实酸奶在青海有悠久的历史,早在公元641年文成公主进藏的民间故事中,就有关于酸奶的记述,凝固型酸奶...

为什么英雄联盟老是掉线(英雄联盟掉线最完美的解决法)

肯定有不少召唤师在游戏时卡掉线,在即将五杀的时候突然冒出吉格斯的笑脸肯定不好受,不但要被扣分还要被队友责怪,教你几招解决掉线问题。卸载wegame很多人已经离不...

人工智能类专业(人工智能就业前景堪忧)

首先,如果未来明确要往人工智能方向发展,本科期间可以直接选择人工智能专业,除此之外,还可以考虑计算机专业和大数据专业,这两个专业与人工智能之间的关系也非常紧密,...

公众号网页客服系统,公众号客服功能怎么用

今晚微信悄悄开放了公众平台的客服功能,多客服功能正式向所有微信认证的服务号和订阅号开放。“多客服功能”简单的说,就是将人工客服团队,可以全部搬到微信公众平台上。...

传奇破解辅助哪里有(神途挂机自动打怪脚本用法)

传奇霸主辅助可独立使用,绿色,免费,安全无毒,设置轻松便捷。新浪传奇霸主辅助脚本可一键副本模式、一键活跃模式、一键竞技模式、一键自动签到、自动打BOSS。传奇霸...