此部落格參考https://fly.layui.com/jie/12624/
一,程式實作的邏輯:
- 後端還是和以前一樣,傳值給前端。
- 前端與GatewayWorker建立連接配接擷取特定的連接配接id
(這樣前端就有使用者id和連接配接id)
3.前端通過ajax方法發送使用者id和連結id給後端,後端進行綁定
4.監控前端發送消息,發送人id,當觸發該事件,傳到後端,後端根據使用者id值,發送給特定的人
5.監控前端接收消息,當有新消息過來就在頁面執行相應的代碼
二,環境的搭建
1,下載下傳GatewayWorker
(位址:http://www.workerman.net/download/GatewayWorker-for-win.zip)
2,修改Applications/YourApp/目錄下的start_geteway.php 24行左右 修改為$gateway = new Gateway("websocket://0.0.0.0:8282");(端口号和前端保持一緻)
3,下載下傳workerman的GatewayClient(https://github.com/walkor/GatewayClient);
4,将下載下傳好的Gateway重命名為Gateway.class.php并修改命名空間為namespace Org\Util;
- 将前面重命名Gateway.class.php複制到thinkphp/library/org/util/目錄下
- 輕按兩下啟動GatewayWorker根目錄下的start_for_win.bat()
如果出現下面:
說明啟動成功
如果沒有啟動成功将有以下解決方法
- 将php設定為全局環境變量(網上有很多方法)測試是否成功在指令行執行php –v,如果提示“php不是内部或外部指令“之類的就說明沒有設定好
- 如果有下圖之類的提示
上圖那樣有三個問題
- php_mcrypt.dll - 找不到指定的子產品。
- php_pdo.dll - 找不到指定的子產品。
- proc_open() has been disabled for security reasons.
找不到指定子產品:解決方法打開php.ini檔案,查找子產品名(比如上圖php_pdo.dll);找到在這句前面加上“;”。注釋掉即可
has been disabled for security reasons.解決方法:就是把這個方法的禁止打開,也是在php.ini檔案修改;找到這個方法,直接删掉即可
三,代碼部分
- 後端部分
- 因為該篇主要講即時通訊的實作,是以使用者資訊擷取那部邏輯就不做展示。
- 後端綁定和發送資訊
後端接收前端資料的時候,還做了把資料存入資料庫的處理,這樣就可以實作資料的持久化
前端部分
- 引入檔案
<script src="__PUBLIC__/jquery/2.0.0/jquery.js"></script>
<link rel="stylesheet" href="__PUBLIC__/layim/css/layui.mobile.css" target="_blank" rel="external nofollow" >
<script src="__PUBLIC__/layim/layui.js"></script>
- 自己資訊的初始化
layui.use('mobile', function(layim){
var mobile = layui.mobile
,layim = mobile.layim;
layim.config({
init: {
mine: {
"username": "{$user.name}" //我的昵稱
,"id": "user{$user.id}" //我的ID
,type: 'kh'//類型
,"avatar": "{$user.img}" //我的頭像
}
} , chatTitleColor:"#fff",
chatLog: '/chat/log/'
});
(3)建立客服資訊
layim.chat({
id: "kf{$kf.id}"
,name: '客服{$kf.id}'
,type: 'kefu' //friend、group等字元,如果是group,則建立的是群聊
,avatar: '/luntan/{$kf.img}'
});
(4)建立連接配接
var socket = new WebSocket('ws://localhost:8282');//伺服器改成ip位址加端口号
連接配接方法
第一次連接配接,會收到兩次資訊,接收後端傳來資料也是在這裡處理
我們可以在onmessage方法裡面進行處理,取出連接配接值,再傳給後端,這樣就綁定好了
除了是登入事件,登出事件,就是後端正常我們自己發送的資料了
我們把接收到的值,再進行展示,這樣就可以實作我們需要的效果了。
//連接配接成功時觸發
socket.onopen = function(e){
//這裡可以寫一些提示語
}
//監聽收到的消息
socket.onmessage = function(e){
var data = e.data
// console.log(e);
data=data.replace('\r\n','');//删除換行符
var arr=data.split(" ");
if(arr[0]=="Hello"){
var client_id=arr[1].trim();
//綁定client_id
$.ajax({type: "POST", url: "{:U('Workerman/bind')}", data: {
'uid':"user{$user['id']}",
'client_id': client_id}, dataType: 'json', success: function (res) {
console.log(res);
}});
}else if(arr[1]!="login"&&arr[1]!="logout"){
//接收伺服器資訊
data=JSON.parse(data);
if(data['sendid']=="kf{$kf.id}"){
$("#link").html("可點選進行評價");
//console.log(data['sendname']);
var obj = {};
obj = {
username:data['sendname']
,avatar: data['img']
,id: 'kf1'
,type:"kefu"
,content: data['content']
}
layim.getMessage(obj);
}
}
(5)監聽使用者發送資訊
layim.on('sendMessage', function(data){
console.log(data);
var sendid=data.mine.id;
var sendtype="kh";
var sendname=data.mine.username;
var sendimg=data.mine.avatar;
var contents=data.mine.content;
var toid=data.to.id;
var toname=data.to.name;
var totype=data.to.type;
var toimg=data.to.avatar;
var talkid=data.mine.id+"|"+data.to.id;
var talktip=data.mine.username+"|"+data.to.name;
$.ajax({
type: "POST",
url: "{:U('User/getcontents')}",
data: {
'sendid':sendid,
'sendname': sendname,
'sendtype':sendtype,
'sendimg':sendimg,
'contents':contents,
'toid':toid,
'toname':toname,
'totype':totype,
'toimg':toimg,
'talkid':talkid,
'talktip':talktip,
},
dataType: 'json',
success: function (res) {
console.log(res);
}
})
至此即時通訊的修改就出來
四,資料的持久化,跨裝置儲存
把聊天記錄根據自己的需求存入資料庫
單使用者進入聊天界面時,根據是誰與誰的聊天,讀取相應資料,然後前端得到資料再進行展示。
注意layim聊天記錄的要求時間戳是精确到毫秒的
(1),php擷取目前毫秒的方法
public function getMillisecond() {
$time = explode (" ", microtime () );
$time = $time [1] . ($time [0] * 1000);
$time2 = explode ( ".", $time );
$time = $time2 [0];
return $time;
}
(2),前端初始化資料
localStorage.clear();
(3),前端擷取資料,并展示
$.ajax({type: "POST", url: "{:U('User/getmsg')}", data: {
'uid':"user{$user['id']}",'kid':"kf{$kf.id}"},
dataType: 'json', success: function (res) {
if(res.stu==1){
$("#link").html("擷取曆史記錄成功");
var msg=res.msg;
// console.log(msg)
for ($i=0;$i<msg.length;$i++){
var isme=false;
if("user{$user['id']}"==msg[$i].sendid){
isme=true;
}
var obj = {};
obj = {
username:msg[$i].sendname//消息來源使用者名
,avatar: msg[$i].sendimg //消息來源使用者頭像
,id: msg[$i].sendid//消息的來源ID(如果是私聊,則是使用者id,如果是群聊,則是群組id)
,type:msg[$i].totype //聊天視窗來源類型,從發送消息傳遞的to裡面擷取
,content: msg[$i].contents //消息内容
,mine: isme
,timestamp: parseInt(msg[$i].time) //服務端時間戳毫秒數。注意:如果你傳回的是标準的 unix 時間戳,記得要 *1000
}
layim.getMessage(obj);
}
}
}})
這樣資料的持久化算是實作了
不過這裡還有一個小bug,當執行layim.getMessage()如果是對方資料的時候就有聲音提示(也就是上面isme變量為false的時候),是以一打開這個頁面就有聲音提示,這個是預設打開的,是以我們要把他關閉了
在layim.config裡面最後加上“,voice: false“
然後我們自己寫收到實時資訊的時候發送提示音
Js發送語音提示方法
function playSound() {
var borswer = window.navigator.userAgent.toLowerCase();
if ( borswer.indexOf( "ie" ) >= 0 )
{
//IE核心浏覽器
var strEmbed = '<embed name="embedPlay" src="/Public/layim/css/modules/layim/voice/default.wav" autostart="true" hidden="true" loop="false"></embed>';
if ( $( "body" ).find( "embed" ).length <= 0 )
$( "body" ).append( strEmbed );
var embed = document.embedPlay;
embed.volume = 100;
} else
{
//非IE核心浏覽器
var strAudio = "<audio id='audioPlay' src='/Public/layim/css/modules/layim/voice/default.wav' hidden='true'>";
if ( $( "body" ).find( "audio" ).length <= 0 )
$( "body" ).append( strAudio );
var audio = document.getElementById( "audioPlay" );
//浏覽器支援 audion
audio.play();
}
然後再自己需要提示音的時候調用這個方法即可
效果圖
最後提示:
- 如果在伺服器搭建的時候記得打開你程式設定的端口的防火牆
- 指令行視窗不能關閉
- 以上都是在windows系統搭建的 ,linux搭建這種websocket環境,網上也有很方法
- Layim如何修改預設展示的聊天記錄的條數
因為layim預設展示20條聊天記錄,多的話,以前的記錄會被折疊
可以修改lay\modules\mobile.js檔案 查找“c=20”後面的條數修改為你需要展示的條數,然後清除浏覽器緩存即可(此方法适用于引入moblie的手機版js,pc端可去試試其他檔案)
如若有誤或者有其他問題請與我交流:2359582968(微信qq同号)