前端部分
游客
var myId = '';
var fenpei_info = '';
// 假定 随机游客ID
myId = parseInt(Math.random() * (999999 - 100000 + 1) + 100000);
function getUrlParam(id) {
var regExp = new RegExp('([?]|&)' + id+ '=([^&]*)(&|$)');
var result = window.location.href.match(regExp);
if (result) {
return decodeURIComponent(result[2]);
} else {
return null;
}
};
var thisURL = document.location.href;
// 如果 url中包含这个参数
if (thisURL.indexOf('uid=') > 0)
{
// 包含uid参数 赋值myId 游客id不变
var v = getUrlParam('uid');
myId = v;
}
else
{
if (thisURL.indexOf("?") > 0)
{
thisURL = thisURL + "&" + "uid=" + myId;
}
else
{
thisURL = thisURL + "?" + "uid=" + myId;
};
location.href = thisURL;
};
// 如果 url中包含这个参数
if (thisURL.indexOf('kfid=') > 0)
{
// 包含kfid参数 赋值fenpei_info 客服id不变
var v = getUrlParam('kfid');
fenpei_info = v;
}
else
{
// 分配客服
$.ajax({
url:"/api/Chat/assignCustomerService",
type:'POST',
async:false,
data:{
url : 'baidu.com',
toid : myId
},
success:function(res){
console.log(res);
fenpei_info = res.data;
}
});
if (thisURL.indexOf("?") > 0)
{
thisURL = thisURL + "&" + "kfid=" + fenpei_info.data;
}
else
{
thisURL = thisURL + "?" + "kfid=" + fenpei_info.data;
};
location.href = thisURL;
};
// ws
var ws = new WebSocket('ws://ip:端口');
ws.onopen = function(){
// 首次连接
};
ws.onmessage = function(e){
// json数据转换成js对象
var data = eval("("+e.data+")");
var type = data.type || '';
console.log("服务端消息:");
console.log(data);
switch(type)
{
case 'init':
var sendBind = '{"type":"bind","myid":"'+myId+'","url":"baidu.com"}';
sendBind = eval('(' + sendBind + ')');
$.ajax({
url:"/api/Wsapi/bindUid",
type:'POST',
async:false,
data:{
client_id: data.client_id,
message: sendBind
},
success:function(res){
console.log('bindUid:');
console.log(res);
}
});
var sendJoin = '{"type":"join","toid":"'+fenpei_info+'","myid":"'+myId+'"}';
sendJoin = eval('(' + sendJoin + ')');
$.ajax({
url:"/api/Wsapi/joinGroup",
type:'POST',
data:{
client_id: data.client_id,
message: sendJoin
},
success:function(res){
console.log("joinGroup-returnData:");
console.log(res);
}
});
break;
case 'msg':
if( data.status != 1 )
{
// 接收消息 显示
console.log(data.message);
var div = "<div class='msg_row'><img src='__IMG__/a.jpg' class='img'><span class='msg_span'>"+ data.message +"</span></div>";
var id = $("button[name='btn']").attr("_id");
$(".r_top[_id='"+id+"']").append(div);
// 修改缩略框信息
$(".people[_id='"+ id +"']").children(".msg").children(".msg_c").html(data.message);
}
else
{
return false;
};
break;
default :
// Layer.alert(e.data);
return false;
};
};
//断开 web socket 连接成功触发事件
ws.onclose = function () {
console.log("连接已关闭...");
};
function sendMsg (){
var content = $("input[name='content']").val();
if(content == ""){
Layer.alert("message is null");
return false;
};
// var arr = '{"content":"'+content+',myId":"'+myId+',t_Id":"'+t_Id+'"}';
var t_id = {$data.user_id};//分配的客服ID
var send_data = '{"type":"user-admin","toid":"'+t_id+'","content":"'+content+'","myid":"'+myId+'","msg_type":"msg"}';
// 接口形式发送消息
send_data = eval('(' + send_data + ')');
$.ajax({
url:"/api/Wsapi/sendMsg",
type:'POST',
data:{
message: send_data
},
success:function(res){
console.log('sendMsg:');
console.log(res);
}
});
// ws.send(send_data);
console.log(send_data);
$("input[name='content']").val('');//重置输入框
// 添加信息
var data = "<div class='msg_row_mine'><span class='msg_span'>"+ content +"</span><img src='__IMG__/a.jpg' class='img_mine'></div>";
$("div[class='r_top']").append(data);
// 修改缩略框信息
var id = $("button[name='btn']").attr("_id");
$(".people[_id='"+ id +"']").children(".msg").children(".msg_c").html(content);
};
//心跳
setInterval(function(){
var heart = '{"type":"ping"}';
console.log("心跳:"+heart);
ws.send(heart);
},3000);
$("button[name='btn']").click(function(){
sendMsg();
return false;
});
$(window).keydown(function(event){
if(event.keyCode == 13) {
sendMsg();
return false;
};
});
// 对话框点击事件
$(".people").click(function(){
console.log("click");
$(".r_top").hide();
var id = $(this).attr("_id");
$(".r_top[_id='"+id+"']").show();
$(".btn").attr("_id",id);
});
// 发送信息
function run() {
var formData = new FormData();
var file = document.getElementById("coverPhoto-file").files[0];
formData.append("img", file); //这里的image是传给后端的字段,根据业务自行修改
formData.append("user", "1");
formData.append("toid", "2");
formData.append("mes", "1");
formData.append("addtime", 1650000000);
formData.append("mobile", 18012341234);
formData.append("type", 2);
formData.append("status", 1);
$.ajax({
url:"/api/Savemsg/saveImg",
type:"POST",
data:formData,
processData : false,
contentType : false,
dataType : 'json',
async : false,
success : function (result) {
console.log('saveImg:');
console.log(result);
//成功后的回调事件
if(result.code == 200)
{
var msg = '{"type":"user-admin","toid":"'+{$data.user_id}+'","content":"'+result.imgPath+'","myid":"'+myId+'","msg_type":"img"}'
// 接口形式发送消息
send_data = eval('(' + msg + ')');
$.ajax({
url:"/api/Wsapi/sendMsg",
type:'POST',
data:{
message: send_data
},
success:function(res){
console.log('sendMsg:');
console.log(res);
}
});
// 添加信息
var data = "<div class='msg_row_mine'><span class='msg_span'>"+ result.imgPath +"</span><img src='__IMG__/a.jpg' class='img_mine'></div>";
$("div[class='r_top']").append(data);
// 修改缩略框信息
var id = $("button[name='btn']").attr("_id");
$(".people[_id='"+ id +"']").children(".msg").children(".msg_c").html(result.imgPath);
}
else
{
console.log(result);
};
}
})
};
客服
var ws = new WebSocket('ws://ip:端口');
var divArr = new Array();
ws.onopen = function(){
// console.log("首次连接");
};
ws.onmessage = function(e){
// json数据转换成js对象
var data = eval("("+e.data+")");
var type = data.type || '';
switch(type)
{
case 'init':
var sendBind = '{"type":"bind","myid":"'+2+'"}';
ws.send(sendBind);
break;
case 'creat':
if( $.inArray(data.client_id, divArr) != -1 )
{
return false;
}
else
{
// 创建聊天窗口
var div = "<div class='people' _id='"+ data.client_id +"'><div style='width: 100%;height: 60px;' name='click_t_id' t_id='"+data.client_id+"'><div class='img_d'><img src='' class='img'></div><div class='msg'><div class='msg_t'>游客"+data.client_id+"</div><div class='msg_c'></div></div></div></div>";
$("div[name='add_div']").append(div);
var msgList = "<div class='r_top' style='display:none;' _id='"+data.client_id+"'>";
$("div[name='msgList']").prepend(msgList);
// 添加进数组
divArr.push(data.client_id);
console.log("add success");
};
break;
case 'msg':
if( data.status != 2 )
{
// 接收消息 显示
var div = "<div class='msg_row'><img src='__IMG__/a.jpg' class='img'><span class='msg_span'>"+ data.message +"</span></div>";
$(".r_top[_id='"+data.userId+"']").append(div);
// 修改缩略框信息
}
else
{
// 客服发的消息
var my_id = $("input[name='my_id']").val();
if(data.myId != my_id){
// 其他客服的消息
var my_avatar = $("input[name='my_avatar']").val();
var div = "<div class='msg_row_mine'><span class='msg_span'>" + data.message + "</span><img src='" +my_avatar +"' class='img_mine'></div>";
$(".r_top[_id='"+data.userId+"']").append(div);
};
};
// 修改缩略框信息
$(".people[_id='"+ data.userId +"']").children(".msg").children(".msg_c").html(data.message);
break;
default :
// Layer.alert(e.data);
return false;
};
};
//断开 web socket 连接成功触发事件
ws.onclose = function () {
console.log("连接已关闭...");
};
//心跳
setInterval(function(){
var heart = '{"code":'+5005+',"data":'+1+'}';
console.log("心跳:"+heart);
ws.send(heart);
},10000);
$(document).ready(function(){
// 头像
var my_avatar = $("input[name='my_avatar']").val();
var my_id = $("input[name='my_id']").val();
//发送信息
function sendMsg (){
var content = $("input[name='content']").val();
if(content == ""){
Layer.alert("message is null");
return false;
};
var t_id = $("#t_id").val();
if( t_id != 0 )
{
var send_data = '{"type":"admin-user","toid":"' + t_id + '","content":"' + content + '","myid":"'+my_id+'"}';
ws.send(send_data);
// console.log(send_data);
$("input[name='content']").val('');//重置输入框
// 添加信息
var data = "<div class='msg_row_mine'><span class='msg_span'>" + content + "</span><img src='" +my_avatar +"' class='img_mine'></div>";
$(".r_top[_id='"+t_id+"']").append(data);
// 修改缩略框信息
var id = $("button[name='btn']").attr("_id");
$(".people[_id='"+ id +"']").children(".msg").children(".msg_c").html(content);
}
else
{
Layer.alert("请选择聊天对象");
return false;
};
};
//发送操作
$("button[name='btn']").click(function(){
sendMsg();
return false;
});
$(window).keydown(function(event){
if(event.keyCode == 13) {
sendMsg();
return false;
};
});
});
功能部分
分配客服功能
use GatewayClient\Gateway;
#注册地址
private $registerAddress = 'ip:端口';
/**
* 引入GatewayClient\Gateway 类
*/
public function requireGateWayWorker()
{
$rootPath = Env::get('root_path');
require_once $rootPath . '../vendor/GatewayWorker/GatewayClient-master/Gateway.php';
Gateway::$registerAddress = $this->registerAddress;
}
/**
* 分配客服
*
* @ApiMethod (POST)
* @param $url 站点地址 string
* @param $toid 游客ID int
*/
public function assignCustomerService()
{
if (request()->isAjax()) {
$param = $this->request->param();
if( empty($param['url']) )
{
$this->success("missing parameter","",203);
};
$this->requireGateWayWorker();
$website = Db::name("website")->where("url",$param['url'])->find();//站点数据
if( $website )
{
// 查询站点负责小组
if( $website["group"] )
{
// 有负责的小组
$explodeGroup = explode(",", $website["group"]);
$users = [];
foreach ($explodeGroup as $key => $v) {
$res = Db::name("admingroup")->where("id",$v)->value("user");
$explodeRes = explode(",",$res);
foreach ($explodeRes as $k => $vo) {
array_push($users, $vo);
};
};
//所有负责的用户ID
$users = array_unique($users);//去重
$emptyArr = [];
$users = array_merge($users,$emptyArr);//下标重排
$onlineUidArr = Gateway::getAllUidList();//获取全局所有在线uid列表
$onlineList = [];//所有负责该站点的在线的客服列表
foreach ($users as $k => $v) {
if( in_array("user".$v, $onlineUidArr))
{
array_push($onlineList,$v);
};
};
if( $onlineList )
{
if( in_array("user".$users[$website['current']], $onlineUidArr) && $website['current']+1 >= count($users) )
{
// 分配的用户在线 重头计算下标
Db::name("website")->where("url",$param['url'])->update(["current"=>0]);
$data = $users[$website['current']];
}
else if( in_array("user".$users[$website['current']], $onlineUidArr) && $website['current']+1 < count($users) )
{
// 分配的用户在线 只需要增长下标
Db::name("website")->where("url",$param['url'])->update(["current"=>$website['current']+1]);
$data = $users[$website['current']];
}
else if( !in_array("user".$users[$website['current']], $onlineUidArr) && $website['current']+1 >= count($users) )
{
// 不在线 并且 要重头开始计算下标
$userKey = array_search($onlineList[0], $users);//返回 在线负责的客服列表中 第一个客服 在 本站点所有负责客服列表中的下标
Db::name("website")->where("url",$param['url'])->update(["current"=>$userKey+1]);
$data = $onlineList[0];
}
else if( !in_array("user".$users[$website['current']], $onlineUidArr) && $website['current']+1 < count($users) )
{
// 不在线 只需要下标+1
$afterList = [];//大于 当前分配的 不在线用户的下标 用户数组 (后半段用户数组 如3在[1,2,3,4,5]中 后半段为[4,5])
foreach ($users as $k => $v) {
if( $k > $website['current'] )
{
array_push($afterList,$v);
};
};
//对比在线列表
foreach ($afterList as $k => $v) {
if( in_array($v, $onlineList) )
{
// 后半数组中有在线的 从下一个在线的开始
$userKey = array_search($v, $users);
if( $userKey + 1 >= count($users) )
{
// 此为最后一个在线用户 重头计算
$userKey = 0;
}
else
{
// 正常加 1
$userKey = $userKey + 1;
};
Db::name("website")->where("url",$param['url'])->update(["current"=>$userKey]);
$data = $v;
break;
};
};
if( !isset($data) )
{
// 后半数组中没有在线的 从在线列表中第一个开始
$userKey = array_search($onlineList[0], $users);//返回 在线负责的客服列表中 第一个客服 在 本站点所有负责客服列表中的下标
Db::name("website")->where("url",$param['url'])->update(["current"=>$userKey+1]);
$data = $onlineList[0];
};
}
else
{
$this->success("Unknown error",null,203);
};
}
else
{
// 当前负责的客服全部是离线 全部离线-机器人回复
$this->success("All offline",null,203);
};
}
else
{
// 无负责小组
$this->success("No responsible team",null,203);
};
}
else
{
$this->success("No website info",null,203);
};
//data:分配的用户ID;room:当前用户所连接的房间数组;max:最大连接数;online:负责该站点的所有在线客服ID数组
$result = ["data"=>$data,"room"=>null,"max"=>null,"online"=>$onlineList];
// 客服当前连接
if($data)
{
// 最大接待数量
$result["max"] = Db::name("admin")->where("id",$data)->value("admit_number");
// 当前连接数
$clientIdArr = Gateway::getClientIdByUid("user".$data);
$session = Gateway::getSession($clientIdArr[0]);//根据客服uid获取客服client_id然后获取设置的session
$result["room"] = $session["room"];
// 客服自动回复
$map = [];
$map["user"] = ["=",$data];
$map["url"] = ["=",$website["id"]];
$map["state"] = ["=",2];//1:关闭;2:启用
$autoreply = Db::name("autoreply")->where($map)->find();
$defaultMes = "你好";
if( $autoreply )
{
$defaultMes = $autoreply["content"];
};
// 生成默认聊天数据
$info = [
'user' => $data,
'toid' => $param["toid"],
'mes' => $defaultMes,
'send_id' => "kf",
'addtime' => time(),
'type' => 1,
'status' => 1,
];
Db::name("message")->insert($info);
};
$this->success("success",$result,200);
};
}
获取聊天列表
/**
* 获取聊天列表
*
* @ApiMethod (POST)
* @param $userId 客服ID int
*/
public function getChatList()
{
if (request()->isajax()) {
$param = $this->request->param();
if( empty($param['userId']) )
{
$this->success("missing parameter","",203);
};
$where = [];
$where["user"] = ["=",$param['userId']];
$data = Db::name("message")
->field("user,toid,mes,send_id,type,status,addtime,mobile")
->where($where)
->order("addtime desc")
->buildSql();
$data = Db::table($data . ' t')->group("t.toid")->select();
$this->requireGateWayWorker();
// 获取客服client_id
$admin_client_id = Gateway::getClientIdByUid("user".$param['userId']);
//返回结果
$result = [
"myList" => [], //自己的聊天列表
"onlineList"=>[] //有权限查看并在线的房间ID列表
];
if( $data )
{
if( $admin_client_id )
{
foreach ($data as $k => $v) {
$arr = [];
$arr = Gateway::isUidOnline($v["toid"]);//判断uid是否在线
$this_user = [];
if( $arr )
{
// 游客仍在线 执行加入
$user_client_id = Gateway::getClientIdByUid($v["toid"]);//游客client_id
Gateway::joinGroup($user_client_id[0], $v["toid"]);//以游客ID为房间名创建房间
Gateway::joinGroup($admin_client_id[0],$v["toid"]);//客服加入房间
// 配置Session
$session = '';
$session = Gateway::getSession($admin_client_id[0]);//获取设置的session
if( $session )
{
if( !in_array($v["toid"],$session["room"]) )
{
array_push($session["room"], $v["toid"]);
Gateway::updateSession( $admin_client_id[0] , array('room'=>$session["room"]) );
};
};
$mes = Db::name("message")->where("toid",$v["toid"])->order("id","desc")->find();
// 未读信息数量返回
$where = [];
$where["toid"] = ["=",$v["toid"]];
$where["status"] = ["=",0];//状态 0:未读
$unread = Db::name("message")->where($where)->count();
// 发送creat至前端 执行添加列表操作
Gateway::sendToGroup($v["toid"],json_encode(array(
"type" => 'creat',
'client_id' => $v['toid'],
'last' => $mes["mes"],
'last_type' => $mes["type"]
)));
// 最后一条聊天记录返回前端预览
$this_user = [
"id" => $v["toid"],
"isOnline" => 1,
"lasttime" => $v["addtime"],
"last" => $mes["mes"],
"last_type" => $mes["type"],
"unread" => $unread
];
array_unshift($result["myList"], $this_user);
continue;
};
$this_user = [
"id" => $v["toid"],
"isOnline" => 0,
"lasttime" => $v["addtime"],
"last" => "",
"last_type" => "1"
];
array_push($result["myList"], $this_user);
};
}
else
{
$this->success("Admin client_id is undefind",null,203);
};
};
// 排序列表
if( $result["myList"] )
{
array_multisort(
array_column($result["myList"],"isOnline"),SORT_DESC,
array_column($result["myList"],"lasttime"),SORT_DESC,
$result["myList"]
);
// 截取
$sub_num = 20;//截取数量
if( count($result["myList"]) > $sub_num )
{
$pos = array_search(0, array_column($result["myList"], 'isOnline'));//0 第一次出现的下标值
if( $pos == "" )
{
// 全部为在线 直接全部返回
$pos = count($result["myList"]);
}
else
{
$pos = ($pos + 5 > count($result["myList"])) ? count($result["myList"]) : $pos + 5;
};
$result["myList"] = array_slice($result["myList"],0,$pos);
};
};
// 返回 有权限查看并在线的房间列表
$all_session = Gateway::getAllClientSessions();
$admin_session = Gateway::getSession($admin_client_id[0]);//获取当前客服的session
foreach ($all_session as $k => $v) {
if( isset($v["user_type"]) )
{
if( $v["user_type"] == "user" )
{
// 筛选为游客
if( in_array($v["website"] , $admin_session["website"]) && !in_array($v["uid"], $result["onlineList"]) )
{
// 当前游客的站点包含于本客服负责的站点
array_push($result["onlineList"], $v["uid"]);
};
};
};
};
$this->success("success",$result,200);
};
}
客服解散房间
/**
* 客服解散房间
*
* @param $roomId //房间ID
* @return string|\think\response\Json
*/
public function disbandedRoom($roomId)
{
if (request()->isajax()) {
if( empty($roomId) )
{
$this->success("missing parameter","",203);
};
$this->requireGateWayWorker();
// 更新session
$group_client_id_list = Gateway::getClientIdListByGroup($roomId);//获取小组里所有的client_id,包含游客/客服
if( $group_client_id_list )
{
foreach ($group_client_id_list as $k => $v) {
$session = "";
$session = Gateway::getSession($v);//获取当前用户session
if( $session["room"] )
{
// 有房间数据 更新房间session
$searchRes = "";
$searchRes = array_search($roomId,$session["room"]);
unset($session['room'][$searchRes]);
Gateway::updateSession($v, $session);
};
};
};
// 解散房间 并通知游客
Gateway::sendToGroup($roomId, json_encode(array(
"type" => "AdminUnsetRoom", //类别标识 用于前端操作判断。此处操作应为发送event消息通知游客,客服已结束会话,并且无法继续发送消息/图片等操作
"roomId" => $roomId
)));
Gateway::ungroup($roomId);
$this->success("success","",200);
};
}
将用户拉入房间
/**
* 将用户拉入房间
*
* @param $client_id //用户全局唯一的client_id
* @param $message //消息 '{"type":"join","group":"xxxxx"}'
* type join
* @return string|\think\response\Json
*/
public function joinGroup($client_id,$message)
{
if (request()->isajax()) {
if( empty($client_id) || empty($message))
{
$this->success("missing parameter","",203);
};
$this->requireGateWayWorker();
if( $message['type'] == 'join' )
{
/*
* 信息格式: '{"type":"join","toid":"负责该站点的所有在线客服ID: '1','2','...'","myid":"游客ID"}'
*/
Gateway::joinGroup($client_id, $message["myid"]);//以游客ID为房间名创建房间
$toid = explode(",",$message['toid']); //客户端传来的客服ID
// 负责该站点的所有在线客服 加入房间
foreach ($toid as $k => $v) {
$arr = Gateway::getClientIdByUid("user".$v);//根据客服uid获取客服client_id
if( $arr )
{
Gateway::joinGroup($arr[0],$message["myid"]);//客服加入房间
// 配置setSession
$session = '';
$session = Gateway::getSession($arr[0]);//获取设置的session
if( $session )
{
if( !in_array($message["myid"],$session["room"]) )
{
array_push($session["room"], $message["myid"]);
Gateway::updateSession($arr[0], array('room'=>$session["room"]));
};
};
};
};
$all_session = Gateway::getAllClientSessions();
$user_session = Gateway::getSession($client_id);//获取当前游客的session
foreach ($all_session as $k => $v) {
if( isset($v["user_type"]) )
{
if( $v["user_type"] == "admin" )
{
// 筛选为客服
if( in_array($user_session["website"], $v["website"]) )
{
// 当前游客的站点包含于该客服负责的站点 则返回信息添加列表内容
Gateway::sendToUid($v['uid'], json_encode(array(
"type" => 'creatList',
'client_id' => $message['myid']
)));
};
};
};
};
$mes = Db::name("message")->where("toid",$message['myid'])->order("id","desc")->find();
Gateway::sendToGroup($message["myid"],json_encode(array(
"type" => 'creat',
'client_id' => $message['myid'],
'last' => $mes["mes"],
'last_type' => $mes["type"]
)));
$this->success("success","",200);
}
else{
$this->success("error","",203);
};
};
}
绑定Uid
/**
* 绑定Uid
*
* @param $client_id
* @param $message
* type bind
* @return string|\think\response\Json
*/
public function bindUid($client_id, $message)
{
if (request()->isajax()) {
if( empty($client_id) || empty($message))
{
$this->success("missing parameter","",203);
};
// $message = '{"type":"bind","myid":"游客为ID/客服为"user"+ID","url":"域名"}'
$this->requireGateWayWorker();
if( $message['type'] == 'bind' )
{
Gateway::bindUid($client_id, $message["myid"]);//操作绑定 游客为ID/客服为"user"+ID
$explodeRes = explode("user", $message["myid"]);
if( count($explodeRes) > 1 )
{
// 客服
$allGroup = Db::name("admingroup")->select();//所有小组
$user_group = [];//客服所在小组
foreach ($allGroup as $k => $v) {
$ex = [];
$ex = explode(",", $v["user"]);
if( in_array($explodeRes[1], $ex) )
{
array_push($user_group, $v["id"]);
};
};
$allWebsite = Db::name("website")->field("id,group")->select();//所有站点
$user_website = [];//客服所负责站点ID
foreach ($allWebsite as $k => $v) {
$ex = [];
$ex = explode(",", $v["group"]);
if( in_array($explodeRes[1], $ex) )
{
array_push($user_website, $v["id"]);
};
};
// 配置session
Gateway::setSession($client_id, array(
'uid' => $message["myid"],
'client_id' => $client_id,
'room' => [],
'user_type' => "admin",
'website' => $user_website //站点
));
}
else
{
// 游客
$website = Db::name("website")->where("url",$message["url"])->find();
// 配置session
Gateway::setSession($client_id, array(
'uid' => $message["myid"],
'client_id' => $client_id,
'room' => [],
'user_type' => "user",
'project' => $website["p_id"], //项目
'region' => $website["r_id"], //地区
'website' => $website["id"] //站点
));
};
$this->success("success",Gateway::getSession($client_id),200);
}
else{
$this->success("error","",203);
};
};
}
发送消息
/**
* 发送消息
*
* @param $message
* type sendMsg
* @return string|\think\response\Json
*/
public function sendMsg($message)
{
if (request()->isajax()) {
if( empty($message))
{
$this->success("missing parameter","",203);
};
// $message = '{"type":"bind","myid":"游客为ID/客服为"user"+ID"}'
$this->requireGateWayWorker();
if( $message['type'] == 'user-admin' )
{
//游客发消息
/*
* 信息格式: '{"type":"user-admin","toid":"分配的客服ID","content":"content","myid":"游客ID","msg_type":"消息类型"}'
*/
if( Gateway::isUidOnline("user".$message["toid"]) )
{
$toid = $message['myid']; //客户端传来的游客ID,也是房间ID
if( Gateway::getUidCountByGroup($toid) )
{
// 向指定房间内所有人发送消息
Gateway::sendToGroup($toid, json_encode(array(
"type" => "msg",
"message" => $message["content"],
"userId" => $toid,
"msg_type" => $message["msg_type"],
"myId" => $message["toid"],
"status" => 1
)));
};
$this->success("success","",200);
}
else
{
$this->success("Offline","",206);
};
}
else if( $message['type'] == 'admin-user' )
{
//客服发消息
/*
* 信息格式: '{"type":"admin-user","toid":"游客ID/也是房间ID","content":"content","myid":"客服ID","msg_type":"消息类型"}'
*/
if( Gateway::isUidOnline($message["toid"]) )
{
$toid = $message['toid']; //客户端传来的目标游客id/也是房间id
if( Gateway::getUidCountByGroup($toid) )
{
// 向指定房间内所有人发送消息
Gateway::sendToGroup($toid, json_encode(array(
"type" => "msg",
"message" => $message["content"],
"userId" => $toid,
"msg_type" => $message["msg_type"],
"myId" => $message["myid"],
"status" => 2
)));
};
$this->success("success","",200);
}
else
{
$this->success("Offline","",206);
};
}
else{
$this->success("error","",203);
};
};
}
销毁session房间号
/**
* 销毁session房间号
*
* @param $client_id
* @param $message
* type unsetRoom
* @return string|\think\response\Json
*/
public function unsetRoom($client_id, $message)
{
if (request()->isAjax()) {
if( empty($client_id) || empty($message))
{
$this->success("missing parameter","",203);
};
$this->requireGateWayWorker();
if( $message['type'] == 'unsetRoom' )
{
/*
* 信息格式: '{"type":"unsetRoom","roomId":"roomId"}';
*/
$session = Gateway::getSession($client_id);
$searchRes = array_search($message["roomId"],$session["room"]);
unset($session['room'][$searchRes]);
Gateway::updateSession($client_id, $session);
$data = Gateway::getSession($client_id);
$this->success("success",$data,200);
}
else{
$this->success("error","",203);
};
};
}
Events部分
/**
* 当客户端连接时触发
* 如果业务不需此回调可以删除onConnect
* @param int $client_id 连接id
*/
public static function onConnect($client_id)
{
var_dump('type:init' . "client_id:" . $client_id);
Gateway::sendToClient($client_id, json_encode(array(
'type' => 'init',
'client_id' => $client_id,
'from' => 'ip'
)));
}
/**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param string $message 具体消息
*/
public static function onMessage($client_id, $message)
{
var_dump('client_id:' . $client_id . "message" . $message);
}
/**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id)
{
$uid = $_SESSION['uid'];//返回client_id绑定的uid 游客为ID/客服为"user"+ID
$explodeRes = explode("user", $uid);
if( count($explodeRes) > 1 )
{
// 客服
if( $_SESSION["room"] )
{
// 存在当前连接数session
foreach ($_SESSION["room"] as $k => $v) {
$onlineNum = 0;
$onlineNum = Gateway::getClientIdCountByGroup($v);//获取分组当前在线成员连接数(不包含退出连接的当前用户)
if( $onlineNum == 1)
{
// 无其余客服在线
var_dump("解散房间");
Gateway::sendToGroup($v, json_encode(array(
"type" => "dissolution"
)));
Gateway::ungroup($v);//解散房间
}
else
{
Gateway::sendToGroup($v, json_encode(array(
"type" => "adminOffline"
)));
};
};
};
}
else
{
// 删除当前游客房间内 所有客服中$_SESSION['room']的该房间号
Gateway::sendToGroup($uid, json_encode(array(
"type" => "unsetRoom",
"roomId" => $uid
)));
// 游客
Gateway::ungroup($uid);//解散房间
};
}