介绍
随机分配客服,一个客服可同时与多人聊天.
源码
workerman.php
<?php
use Workerman\worker;
require_once __DIR__ . '/Autoloader.php';
$ws_worker = new Worker("websocket://0.0.0.0:2000");
$ws_worker->count = 4;
$ws_worker->onMessage = function ($connection, $data) {
global $ws_worker;
$adminlist = [];
$msg = json_decode($data);
switch ($msg->type) {
case 'login':
if ($msg->group === 'user') {
$connection->group = 'user';
foreach ($ws_worker->connections as $value) {
if ($value->group === 'admin')
$adminlist[] = $value->id;
}
if (!$adminlist) {
$edata = new stdClass();
$edata->fid = $connection->id;
$edata->msg = '没有客服在线';
$edata->name = '系统提示';
$connection->send(json_encode($edata));
return;
}
$connection->toid = $ws_worker->connections[$adminlist[array_rand($adminlist, 1)]];
}
if ($msg->group === 'admin_user') {
$connection->group = 'admin';
}
break;
case 'msg':
if ($msg->group === 'user') {
$fdata = new stdClass();
$fdata->fid = $connection->id;
$fdata->msg = $msg->msg;
$fdata->name = '客户' . $connection->id;
if (in_array ($connection->toid->id ,(array_column ((array) $ws_worker->connections,'id')))){
$connection->toid->send(json_encode($fdata));
}else{
$edata = new stdClass();
$edata->fid = $connection->id;
$edata->msg = '已与客服断开连接,请刷新后重试';
$edata->name = '系统提示';
$connection->send(json_encode($edata));
return;
}
}
if ($msg->group === 'admin_user') {
if ($msg->toid != null) {
$fdata = new stdClass();
$fdata->fid = $connection->id;
$fdata->msg = $msg->msg;
$fdata->name = '客服' . $connection->id;
$ws_worker->connections[$msg->toid]->send(json_encode($fdata));
}
}
break;
default:
# code...
break;
}
// $connection->send('hello ' . $data);
};
// 运行worker
Worker::runAll();
kehu.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.item {
margin: 10px;
margin-bottom: 10px;
padding-left: 5px;
padding-right: 5px;
}
</style>
<title>Document</title>
</head>
<body>
<div id="msg" style="width:100%;border: 1px solid;overflow-y:scroll;">
</div>
<div id="content" contenteditable="true" style="width:100%;margin-top: 2px;border: 1px solid;overflow-y:scroll;"></div>
</body>
<script>
window.onload = function() {
document.getElementById('msg').style.height = '65vh';
document.getElementById('content').style.height = '30vh';
}
function send() {
var text = document.getElementById('content').innerText;
data=new Object();
data.group='user';
data.type='msg';
data.msg=text;
ws.send(JSON.stringify(data));
document.getElementById('content').innerText = '';
add_msg(text);
var scrollTarget = document.getElementById("msg");
scrollTarget.scrollTop = scrollTarget.scrollHeight;
}
ws = new WebSocket("ws://php.edu:2000");
ws.onopen = function() {
console.log("连接成功");
data=new Object();
data.group='user';
data.type='login';
ws.send(JSON.stringify(data));
};
ws.onmessage = function(e) {
fdata = JSON.parse(e.data);
add_msg(fdata.msg, fdata.name);
var scrollTarget = document.getElementById("msg");
scrollTarget.scrollTop = scrollTarget.scrollHeight;
};
function add_msg(text, id) {
var item = document.createElement('item');
if (id == null) {
id = '我说';
style = 'style="display:flex;flex-direction: column;align-items: flex-end;"'
} else {
style = '';
}
r = '<div class="item" ' + style + '><div>' + id + '<span style="color: #f55;">' + ' ' + new Date().toLocaleTimeString('cn', {
hour12: false
}) + '</span></div> <div style="padding-left: 10px;">' + text + '</div></div>'
item.innerHTML = r;
document.getElementById('msg').append(item);
}
</script>
</html>
kefu.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.item {
margin: 10px;
margin-bottom: 10px;
padding-left: 5px;
padding-right: 5px;
}
.navid {
position: absolute;
height: 70.3vh;
width: 10vw;
border: 1px solid;
overflow-y: scroll;
left: 8.7vw;
}
.up {
position: absolute;
height: 50vh;
width: 80vw;
border: 1px solid;
overflow-y: scroll;
right: 1vw;
}
.hide {
display: none;
}
.down {
position: absolute;
top: 51vh;
width: 80vw;
height: 20vh;
margin-top: 2px;
border: 1px solid;
overflow-y: scroll;
right: 1vw;
}
.btn {
position: absolute;
top: 72vh;
right: 1vw;
width: 100px;
height: 30px;
margin-top: 0.3vh;
}
.kehuitem {
width: 98%;
height: 5vh;
border-bottom: 1px solid;
line-height: 5vh;
text-align: center;
}
.kehuitem:hover {
background-color: cornflowerblue;
cursor: default;
}
</style>
<title>Document</title>
</head>
<body>
<div class="navid" id="idlist">
{{-- <div class="kehuitem">客户5686</div> --}}
</div>
<div class="up" id="msg">
</div>
<div class="down" id="content" contenteditable="true"></div>
<input class="btn" type="button" value="发送" onclick="send()">
</body>
<script>
var toid;
function send() {
var text = document.getElementById('content').innerText;
data = new Object();
data.group = 'admin_user';
data.type = 'msg';
data.msg = text;
all_list = document.getElementsByClassName('up');
for (const key in all_list) {
if (all_list.hasOwnProperty(key)) {
const element = all_list[key];
if (element.style.display == 'block') {
toid = element.getAttribute('toid');
console.log(data.toid);
break;
}
}
}
if (toid == undefined) {
data.toid = null;
} else {
data.toid = toid;
}
ws.send(JSON.stringify(data));
document.getElementById('content').innerText = '';
add_msg(text);
var scrollTarget = document.getElementById("msg");
scrollTarget.scrollTop = scrollTarget.scrollHeight;
}
function add_msg(text, id) {
var item = document.createElement('div');
if (id == null) {
id = '我说';
style = 'style="display:flex;flex-direction: column;align-items: flex-end;"'
} else {
style = '';
}
r = '<div class="item" ' + style + '><div>' + id + '<span style="color: #f55;">' + ' ' + new Date()
.toLocaleTimeString('cn', {
hour12: false
}) + '</span></div> <div style="padding-left: 10px;">' + text + '</div></div>'
item.innerHTML = r;
document.getElementById('msg').append(item);
}
ws = new WebSocket("ws://php.edu:2000");
ws.onopen = function () {
console.log("连接成功");
data = new Object();
data.group = 'admin_user';
data.type = 'login';
ws.send(JSON.stringify(data));
};
ws.onmessage = function (e) {
fdata = JSON.parse(e.data);
show_msg(fdata.name, fdata.fid, fdata.msg);
add_msg(fdata.msg, fdata.name);
var scrollTarget = document.getElementById("msg");
scrollTarget.scrollTop = scrollTarget.scrollHeight;
};
//收到消息后处理
function show_msg(s_title, s_id, s_msg) {
exist = false;
all_list = document.getElementsByClassName('kehuitem');
for (const key in all_list) {
if (all_list.hasOwnProperty(key)) {
const element = all_list[key];
if (element.getAttribute('toid') == s_id) {
exist = true;
break;
}
}
}
if (exist) {
all_chat_box = document.getElementsByClassName('up');
for (const key in all_chat_box) {
if (all_chat_box.hasOwnProperty(key)) {
const element = all_chat_box[key];
element.setAttribute('id', 'null');
if (element.getAttribute('toid') == s_id) {
element.setAttribute('id', 'msg');
}
}
}
all_list = document.getElementsByClassName('kehuitem');
for (const key in all_list) {
if (all_list.hasOwnProperty(key)) {
const element = all_list[key];
if (element.getAttribute('toid') == s_id) {
element.style.backgroundColor = 'cornflowerblue';
element.setAttribute('new', 'on');
}
}
}
} else {
add_user(s_title, s_id, s_msg);
all_list = document.getElementsByClassName('kehuitem');
for (const key in all_list) {
if (all_list.hasOwnProperty(key)) {
const element = all_list[key];
if (element.getAttribute('toid') == s_id) {
element.style.backgroundColor = 'cornflowerblue';
}
}
}
}
}
//添加聊天标签
function add_user(title, to_id, msg) {
//在消息列表添加一个用户框
userlist = document.createElement('div');
userlist.setAttribute('class', 'kehuitem');
userlist.setAttribute('toid', to_id);
userlist.setAttribute('new', 'on');
userlist.innerText = title;
document.getElementById('idlist').append(userlist);
//添加一个聊天框
all_chat_box = document.getElementsByClassName('up');
for (const key in all_chat_box) {
if (all_chat_box.hasOwnProperty(key)) {
const element = all_chat_box[key];
element.setAttribute('id', 'null');
element.style.display = 'none';
}
}
chat_box = document.createElement('div');
chat_box.setAttribute('class', 'up');
chat_box.setAttribute('toid', to_id);
chat_box.setAttribute('id', 'msg');
chat_box.style.display = 'block';
document.getElementsByTagName('body')[0].append(chat_box);
//用户列表被点击
userlist.addEventListener('click', function () {
all_list = document.getElementsByClassName('kehuitem');
for (const key in all_list) {
if (all_list.hasOwnProperty(key)) {
const element = all_list[key];
if (element.getAttribute('new')=='off'){
element.style.backgroundColor = '';
}
}
}
this.style.backgroundColor = 'cornflowerblue';
this.setAttribute('new','off');
to_id = this.getAttribute('toid');
console.log(to_id);
all_chat_box = document.getElementsByClassName('up');
for (const key in all_chat_box) {
if (all_chat_box.hasOwnProperty(key)) {
const element = all_chat_box[key];
element.setAttribute('id', 'null');
if (element.getAttribute('toid') == to_id) {
element.style.display = 'block';
element.setAttribute('id', 'msg');
} else {
element.style.display = 'none';
}
}
}
});
}
</script>
</html>