Blogger Information
Blog 64
fans 6
comment 2
visits 82814
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
laravel--IM即时通讯系统--页面美化
王娇
Original
1289 people have browsed it

学习总结

1.在workerman框架中判断某个连接是否掉线,需要添加onclose()方法。

2.在服务端如果客户登录,则新建一个消息列表给该客户,存放此客户和客服的聊天记录,并且模拟点击一下。

1.workerman框架中的websocket文件ws_test.php

  1. <?php
  2. use Workerman\Worker;
  3. require_once __DIR__ . '/../Workerman/Autoloader.php';
  4. /// 注意:这里与上个例子不同,使用的是websocket协议
  5. $ws_worker = new Worker("websocket://0.0.0.0:2001");
  6. // 启动4个进程对外提供服务
  7. $ws_worker->count = 4;
  8. //连接信息定义为全局变量
  9. $m_list = []; //客户连接信息
  10. $a_list = [];//客服人员连接信息
  11. // 当收到客户端发来的数据后返回hello $data给客户端
  12. $ws_worker->onMessage = function($connection, $data)
  13. {
  14. global $m_list;
  15. global $a_list;
  16. $data = json_decode($data,true);
  17. print_r($data);
  18. // echo $connection->getRemoteIp(); 获取当前连接的ip
  19. //登录
  20. if($data['type']==='login'){
  21. //无论是客户还是客服人员在登录的时候,都需要把连接注册在大数组中
  22. $connection->from_id = $connection->id;
  23. //如果是客户登录,则把连接数据放在$m_list数组中
  24. if($data['group']==='member'){
  25. $m_list[$connection->id] = $connection;
  26. $data['from_id'] = $connection->from_id;
  27. if($a_list):
  28. $index = array_rand($a_list);
  29. $a_list[$index]->to_id = $m_list[$connection->id]->from_id;
  30. $m_list[$connection->id]->to_id = $a_list[$index]->from_id;
  31. $res['code'] = 0;
  32. $res['msg'] = '连接成功';
  33. $res['type'] = 'login';
  34. $res['id'] = $m_list[$connection->id]->from_id;
  35. $a_list[$index]->send(json_encode($res));
  36. $res['id'] = $a_list[$index]->from_id;
  37. $m_list[$connection->id]->send(json_encode($res));
  38. else:
  39. $connection->send(json_encode(['code'=>1,'msg'=>'没有客服在线,请稍候']));
  40. endif;
  41. }
  42. //如果是客服登录,就把客服登录链接放在$a_list数组中
  43. if($data['group']==='admin'){
  44. $a_list[$connection->id] = $connection;
  45. }
  46. }
  47. //发送信息
  48. if($data['type']==='msg')
  49. {
  50. $res =['code'=>0,'msg'=>$data['msg'],'type'=>'msg','id'=>$connection->id];
  51. if($data['group']==='member'){
  52. $a_list[$data['to_id']]->send(json_encode($res));
  53. }
  54. if($data['group']==='admin'){
  55. $m_list[$data['to_id']]->send(json_encode($res));
  56. }
  57. }
  58. //$connection->send(json_encode($data));
  59. };
  60. $ws_worker->onClose = function($connection)
  61. {
  62. global $m_list;
  63. global $a_list;
  64. $index = $connection->id;
  65. //客户掉线
  66. if(array_key_exists($index,$m_list)){
  67. // echo '客户'.$index.'掉线了!';
  68. if(isset($m_list[$index]->to_id))
  69. {
  70. $to_id = $m_list[$index]->to_id; //to_id是在和哪个客服通信
  71. $res = [];
  72. $res['code'] = 0;
  73. $res['msg'] = '客户掉线';
  74. $res['type'] = 'logout';
  75. $res['id'] = $index;
  76. $a_list[$to_id]->send(json_encode($res));//通知客服人员该客户掉线了
  77. }
  78. unset($m_list[$index]);//从客户大数组中删除该客户
  79. $m_list = array_filter($m_list);//清除大数组中的空值
  80. // print_r($m_list);
  81. }
  82. //客服掉线
  83. if(array_key_exists($index,$a_list)){//判断数组中是否存在$index这个key
  84. echo '客服'.$index.'掉线了!';
  85. unset($a_list[$index]);//删除键名为$index这个key的键和值,位置保存
  86. $a_list = array_filter($a_list); //把数组值为空的去掉
  87. print_r($a_list);
  88. }
  89. };
  90. // 运行worker
  91. Worker::runAll();
  92. ?>

2.服务端index.blade.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  9. <title>客户服务</title>
  10. <style>
  11. .main{
  12. width: 600px;
  13. height: 450px;
  14. margin: 20px;
  15. box-sizing: border-box;
  16. border: 1px solid #c2c2c2;
  17. display: flex;
  18. flex-flow: row nowrap;
  19. }
  20. .main>.member{
  21. width: 30%;
  22. padding: 10px 10px;
  23. border-right: 1px solid #c2c2c2;
  24. }
  25. /* 客户列表 */
  26. .main>.member>.m_item{
  27. height: 20px;
  28. padding: 5px 5px;
  29. margin-bottom: 5px;
  30. background-color: #f1f1f1;
  31. border-radius: 5px;
  32. border: 1px solid #cdcdcd;
  33. text-align: center;
  34. }
  35. /* 客户列表被点击 */
  36. .main>.member>.m_item.active{
  37. background-color: #3FADFF;
  38. color: white;
  39. }
  40. .main>.member>div:hover{
  41. background-color: #3FADFF;
  42. cursor: pointer;
  43. }
  44. .main>.admin{
  45. width: 70%;
  46. display: flex;
  47. flex-flow: column nowrap;
  48. }
  49. /* 客服消息列表 */
  50. .main>.admin>.msg_list{
  51. padding: 10px 10px;
  52. height: 65%;
  53. border-bottom: 1px solid #c2c2c2;
  54. }
  55. /* 客户发来的消息 */
  56. .main>.admin>.msg_list .msg_item{
  57. text-align: left;
  58. background-color: #f1f1f1;
  59. border-radius: 5px;
  60. height: 25px;
  61. margin: 5px 5px;
  62. padding: 5px 5px;
  63. }
  64. /* 客服自己的消息 */
  65. .main>.admin>.msg_list .msg_item.me{
  66. text-align: right;
  67. background-color: lightgreen;
  68. }
  69. /* 客服消息输入框 */
  70. .main>.admin>.msg_input{
  71. padding: 10px 10px;
  72. height: 35%;
  73. overflow: auto;
  74. }
  75. /* 客服消息发送按钮 */
  76. .main>.admin>.btn_send>button{
  77. margin-left: 84%;
  78. margin-bottom: 5px;
  79. }
  80. </style>
  81. </head>
  82. <body>
  83. <div class="main">
  84. <div class="member">
  85. {{-- 客户列表 --}}
  86. {{-- <div class="m_item active" m_id="2" onclick="back(2)">客户2</div>
  87. <div class="m_item" m_id="3" onclick="back(3)">客户3</div> --}}
  88. </div>
  89. <div class="admin">
  90. <div class="msg_list">
  91. {{-- 消息列表 --}}
  92. {{-- <div msg_list_id='2'>
  93. <div class="msg_item me">我说:您好</div>
  94. <div class="msg_item">客户2说:华为手机多少钱?</div>
  95. <div class="msg_item me">我说:您好</div>
  96. <div class="msg_item">客户2说:华为手机多少钱?</div>
  97. </div>
  98. <div msg_list_id='3'>
  99. <div class="msg_item me">我说:您好</div>
  100. <div class="msg_item">客户3说:华为手机多少钱?</div>
  101. <div class="msg_item me">我说:您好</div>
  102. <div class="msg_item">客户3说:华为手机多少钱?</div>
  103. </div> --}}
  104. </div>
  105. <div class="msg_input" contenteditable="true">
  106. {{-- 消息输入框 --}}
  107. </div>
  108. <div class="btn_send">
  109. <button class="layui-btn layui-btn-normal" type="button" onclick="send()">发送</button>
  110. </div>
  111. </div>
  112. </div>
  113. </body>
  114. </html>
  115. <script>
  116. layui.use(['layer'],function(){
  117. layer = layui.layer;
  118. $ = layui.jquery;
  119. // 假设服务端ip为127.0.0.1
  120. ws = new WebSocket("ws://127.0.0.1:2001");
  121. data = {};
  122. data.type = 'login';//当前是登录操作
  123. data.group='admin';//角色是客服
  124. ws.onopen = function() {
  125. ws.send(JSON.stringify(data));
  126. };
  127. ws.onmessage = function(e) {
  128. res = JSON.parse(e.data);
  129. console.log(res);
  130. if(res.code>0)
  131. {
  132. alert(res.msg);
  133. }
  134. else
  135. {
  136. to_id = res.id;
  137. switch (res.type)
  138. {
  139. case 'login':
  140. //在客户列表中添加对应的客户
  141. html = '<div class="m_item" m_id='+res.id+' onclick="back('+res.id+')">客户'+res.id+'</div>';
  142. $('.member').append(html);
  143. //客户登录时添加这个客户的消息列表div
  144. $('.msg_list').append('<div msg_list_id="'+res.id+'"></div>');
  145. //点击事件
  146. back(res.id);
  147. break;
  148. //客户发来消息
  149. case 'msg':
  150. html = '<div class="msg_item">'+res.msg+'</div>';
  151. //哪个客户发来的的消息,添加到对应的消息列表div中
  152. $('div[msg_list_id="'+res.id+'"]').append(html);
  153. break;
  154. case 'logout':
  155. //在客户列表中删除对应的客户
  156. $('.m_item[m_id="'+res.id+'"]').remove();
  157. break;
  158. default:
  159. alert(res.msg);
  160. }
  161. }
  162. };
  163. });
  164. function back(id)
  165. {
  166. to_id = id;
  167. //给当前点击的客户添加active样式,其它的客户取消active样式
  168. $('.m_item[m_id="'+id+'"]').addClass('active').siblings().removeClass('active');
  169. //点击哪个客户,显示和哪个客户的聊天信息
  170. $('div[msg_list_id="'+id+'"]').show().siblings().hide();//显示点击客户的聊天记录
  171. }
  172. // //客服向客户发送消息
  173. function send()
  174. {
  175. data['type'] = 'msg';
  176. data['group'] = 'admin';
  177. data['msg'] =$('.msg_input').text();
  178. data['to_id'] =to_id;
  179. ws.send(JSON.stringify(data));
  180. html = '<div class="msg_item me">'+$('.msg_input').text()+'</div>';
  181. //是发给哪个客户的消息,添加到对应的消息列表div中
  182. $('div[msg_list_id="'+to_id+'"]').append(html);
  183. $('.msg_input').text('');
  184. }
  185. </script>

3.客户端index.blade.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  9. <title>百度商桥IM通讯</title>
  10. <style>
  11. .msg{
  12. margin:10px 10px;
  13. height: 95vh;
  14. }
  15. .msg>.list{
  16. padding: 10px;
  17. border: 1px solid #c2c2c2;
  18. border-radius: 5px;
  19. height: 70%;
  20. margin-bottom: 10px;
  21. }
  22. /* 客服发来的消息 */
  23. .msg>.list>.item{
  24. text-align: left;
  25. background-color: #f1f1f1;
  26. border-radius: 5px;
  27. height: 25px;
  28. margin: 5px 5px;
  29. padding: 5px 5px;
  30. }
  31. /* 客户自己发送的消息 */
  32. .msg>.list>.item.me{
  33. text-align: right;
  34. background-color: lightgreen;
  35. }
  36. /* 消息输入框 */
  37. .msg>.msg_input>{
  38. height: 30%;
  39. }
  40. </style>
  41. </head>
  42. <body>
  43. <div class="msg">
  44. <div class="list">
  45. {{-- <div class="item me">您好,华为手机多少钱?</div>
  46. <div class="item">1988元</div> --}}
  47. </div>
  48. <div class="msg_input">
  49. <textarea class="layui-textarea" name="msg"></textarea>
  50. </div>
  51. </div>
  52. </body>
  53. </html>
  54. <script>
  55. layui.use(['layer'],function(){
  56. layer = layui.layer;
  57. $ = layui.jquery;
  58. // 假设服务端ip为127.0.0.1
  59. ws = new WebSocket("ws://127.0.0.1:2001");
  60. data = {};
  61. data.type = 'login';//当前是登录操作
  62. data.group='member';//角色是客户
  63. ws.onopen = function() {
  64. ws.send(JSON.stringify(data));
  65. };
  66. ws.onmessage = function(e) {
  67. res = JSON.parse(e.data);
  68. console.log(res);
  69. if(res.code>0)
  70. {
  71. alert(res.msg);
  72. }
  73. else
  74. {
  75. switch (res.type)
  76. {
  77. case 'login':
  78. html = '<div class="item">您好,客服'+res.id+'为您服务...</div>';
  79. break;
  80. case 'msg':
  81. html = '<div class="item">客服'+res.id+': '+res.msg+'</div>';
  82. break;
  83. default:
  84. }
  85. to_id = res.id;//记录是哪个客服为我服务
  86. $('.list').append(html);
  87. }
  88. };
  89. });
  90. // //客户向服务器的客服人员发送消息
  91. function send()
  92. {
  93. data['type'] = 'msg';
  94. data['group'] = 'member';
  95. data['msg'] =$('textarea[name="msg"]').val();
  96. data['to_id'] =to_id;
  97. ws.send(JSON.stringify(data));
  98. html = '<div class="item me">'+$('textarea[name="msg"]').val()+'</div>';
  99. $('.list').append(html);
  100. $('textarea[name="msg"]').val('');
  101. }
  102. </script>

Correcting teacher:GuanhuiGuanhui

Correction status:qualified

Teacher's comments:可以!
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post