摘要:我們的平臺上有虛擬商品和實體商品兩大分類,當時也考慮到了消息的讀取狀態。商家發送時間是否已讀。看前端代碼當前的所有代碼并不是最終的,目前只是階段性開發,后期在項目中逐步完善。
前段時間公司提了一個新的需求,在商品的詳情頁要實現站內買家和商品賣家實時通訊的功能以方便溝通促成交易,要開發此功能當時首先考慮到的就是swoole和workerman了,從網上大概了解了一下關于這兩款工具的闡述,功能都是相當強大的,考慮到項目的進度問題,還是選擇上手容易比較快的GatewayWorker。
先看一下我們前端設計高大上的模板,分別是用戶和賣家后臺。 功能還是比較全的,幾乎模仿的是QQ。
業務上的大概需求是,用戶在進入某個商品詳情頁下,給用戶提供一個和賣家溝通的接口,根據商品的ID找到對應的賣家,類似于淘寶,還有發送圖片,發送對應的商品鏈接;商戶后臺也差不多。
我們的平臺上有虛擬商品和實體商品兩大分類,當時也考慮到了消息的讀取狀態。我的表最初設計如下,沒有加任何的索引,考慮的或許也不夠周全,有見地的前輩還望指點一二!
DROP TABLE IF EXISTS `hp_chat_log`; CREATE TABLE `hp_chat_log` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT "聊天記錄表主鍵id", `user_id` int(10) unsigned NOT NULL DEFAULT "0" COMMENT "用戶id", `merchant_id` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT "" COMMENT "商家id", `send_message` text COLLATE utf8_unicode_ci NOT NULL, `send_message_type` tinyint(1) NOT NULL DEFAULT "1" COMMENT "發送消息類型(1:普通文本;2:商品鏈接,3:用戶發送圖片)", `sender` tinyint(1) NOT NULL DEFAULT "1" COMMENT "發送方。1:用戶。2:商家", `send_time` int(11) NOT NULL DEFAULT "0" COMMENT "發送時間", `read_status` tinyint(1) unsigned NOT NULL DEFAULT "0" COMMENT "是否已讀。0:未讀取。1:已讀取", `acc_isonline` tinyint(1) NOT NULL DEFAULT "0" COMMENT "接收方是否在線 (0:不在線;1:在線)", PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=157 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
模板有了,表設計好了,接下來就是搭建服務了,當前項目開發的框架用的是TP5,選擇的Websocket框架是GatewayWorker框架,關于GatewayWorker與TP5的整合方法可以看我的這篇文章,講到了在Linux和
Windows下的整合安裝。
http://www.cnblogs.com/wt645631686/p/7219519.html
整合好了之后需要根據當前服務器的一些端口配置在修改一些默認的配置,因為需要客戶端通過指定的端口建立連接。
TP5整合好了之后Gateway和workerman的主體目錄結構都在TP5的框架目錄vendor下的workerman目錄下。需要修改里面gateway目錄下的一些文件的端口及IP地址配置。
配置完成之后,進入項目目錄,按照workerman官方手冊提供的使用方法,用命令php start.php start啟動socket服務,如以下截圖,分別是1238和8282端口。當然可以在后臺運行,詳細的使用方法請參考手冊。
啟動好了之后那么就需要在客戶端開始下手了,我們項目里是在前端頁面里用建立的鏈接。看前端代碼
當前的所有代碼并不是最終的,目前只是階段性開發,后期在項目中逐步完善。
var ws; // 連接服務端 function connect() { // 創建websocket ws = new WebSocket("ws://"+document.domain+":8282"); //當時為了方便以后的維護,這里在php的全局文件里定義了一個常量來定義ip,后來本地開發完提交到linux服務器環境之后發現鏈接失敗! console.log(ws); ws.onopen = onopen; ws.onmessage = onmessage; ws.onclose = function(e) { console.log(e); console.log("連接關閉,定時重連"); connect(); }; ws.onerror = function(e) { console.log(e); console.log("出現錯誤"); }; } // 握手 function onopen() { var joint = "{"type":"handshake","role":"user"}"; ws.send(joint); } // 服務端發來消息時 function onmessage(e) { var data = JSON.parse(e.data); console.log(data); switch(data["type"]){ // 服務端ping客戶端 case "ping": ws.send("{"type":"pong"}"); break; // 登錄 更新用戶列表 case "handshake": bindUid(data.client_id); $("#client_id").val(data.client_id); break; // 提醒 case "reception": //{"type":"say","from_client_id":xxx,"to_client_id":"all/client_id","content":"xxx","time":"xxx"} warn(data["content"], data["time"], data["timestamp"]); break; } } //綁定uid function bindUid (client_id) { var bindUrl = "{:url("push/push/BindUserClientId")}"; $.post(bindUrl, {client_id: client_id}, function(data){ console.log(data); }, "json"); } //發送連接 function sendLink () { sendTrigger("link"); } // 發送信息 function sendMessage (){ sendTrigger("message"); } function sendTrigger(sendType) { var toMid = $("#toMid").val(); var pid = $("#pid").val(); var message = $("footer .send_content").val(); var client_id = $("#client_id").val(); var sendUrl = "{:url("push/push/SendMessageToMerchant")}"; $.ajax({ url:sendUrl, type:"POST", data:{message:message,toMid:toMid,pid:pid,client_id:client_id,sendType:sendType}, async:false, dataType:"JSON", success:function(data){ data = JSON.parse(data); if (data.status < 0) { alert("發送失敗,請稍后再試!"); } else { $("#send_timestamp").val(data.timeStamp); $("#send_timestr").val(data.timeStr); if (sendType == "link") { $("#main").append(data.html); } } } }) } // 提醒 function warn(content, time, prevTmestamp){ var V_image = $("#V_image").val(); var str = "" + timestampWarn(prevTmestamp, time) + "" // $("#main").append(str); // } var t = 0; var i = 0, length = images.localId.length; images.serverId = []; /* upload 方法 -------- start */ function upload() { wx.uploadImage( { localId: images.localId[i], success: function (res) { i++; images.serverId.push(res.serverId); if (i < length) { upload(); } var str = "" $("#main").append(str); if(i >= length ) uploadImageToDb(images.serverId); }, fail: function (res){ } }); } /* upload 方法 -------- end */ upload(); } }) }); function uploadImageToDb(images){ var str = ""; var upUrl = "http://xxxxxx.com/push/push/uploadImgage"; var toMid = $("#toMid").val(); var client_id = $("#client_id").val(); $.post(upUrl,{images:images,toMid:toMid,client_id:client_id},function(data){ if(data == 1){ for(var n = 0 ; n < $(".chat-sender").length ; n++){ str = $(".chat-sender").eq(n).attr("serverId")+","; for(var z=0;z上傳失敗
后臺部分
//微信上傳圖片 public function uploadImgageAction () { if (!Request::instance()->isPost()) { notFund(); } $images = $_POST["images"]; if (empty($images)) die; $toMid = input("post.toMid", "" , "string"); $client_id = input("post.client_id", "", "string"); if (strlen($client_id) != 20 ) { //客戶端錯誤 return json_encode(["status" => -1]); } if (!is_not_empty_string($toMid)) { //系統錯誤 return json_encode(["status" => -2]); } require_once dirname(dirname(__FILE__)) . "/Events.php"; $accIsOnline = Gateway::isUidOnline($toMid) == 1 ? 1 : 0; //判讀商家是否在線 $message_type = 3; //微信上傳圖片處理Start $res = json_decode(file_get_contents("access_token.json")); foreach ($res as $key => $value) { if($key == "access_token"){ $access_token = $value; } } $data = []; foreach ($images as $k => $v) { $str = date("YmdHis").rand(1000,9999).".jpg"; $targetName = "./upload/chat/".$str; if (!file_exists("./upload/chat/")) { mkdir("./upload/chat/", 0777, true); } $ch = curl_init("http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=".$access_token."&media_id=".$v); $fp = fopen($targetName, "wb"); curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); $msg["status"] = curl_exec($ch); $msg["filename"] = $str; curl_close($ch); fclose($fp); $data[] = $targetName; } //微信上傳圖片處理End if (!is_not_empty_array($data)) { //微信服務器端圖片上傳錯誤 return json_encode(["status" => -2]); } $message = json_encode($data); //Log入庫 $insertId = PmodelPush::addChatLog(self::$uid, $toMid, $message, $message_type, 1, $accIsOnline); if ($insertId === false) { //入庫失敗(服務器故障) return json_encode(["status" => -3]); } $Worker = new Events; $message_json = "{"type":"send","source":"U_" . self::$uid . "","toClientUid":"" . $toMid . "","content":" . $message .", "c_type": " . $message_type .", "Db_id":" . $insertId . "}"; $Worker::onMessage($client_id, $message_json); //成功返回相關數據 return json_encode([ "status" => 1, "timeStamp" => time(), "timeStr" => date("H:i:s") ]); }
其他一些不是很重要的代碼就不拿出來了。
當前項目只是一個簡單的需求,并沒有把GatewayWorker很多強大的功能體現出來,大家以后在項目開發中遇到更為復雜的需求,參考官方手冊提供的一些Demo就可以慢慢實現并開發出更為健壯的項目!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/113052.html
摘要:我們的平臺上有虛擬商品和實體商品兩大分類,當時也考慮到了消息的讀取狀態。商家發送時間是否已讀。看前端代碼當前的所有代碼并不是最終的,目前只是階段性開發,后期在項目中逐步完善。 前段時間公司提了一個新的需求,在商品的詳情頁要實現站內買家和商品賣家實時通訊的功能以方便溝通促成交易,要開發此功能當時首先考慮到的就是swoole和workerman了,從網上大概了解了一下關于這兩款工具的闡述,...
摘要:我們的平臺上有虛擬商品和實體商品兩大分類,當時也考慮到了消息的讀取狀態。商家發送時間是否已讀。看前端代碼當前的所有代碼并不是最終的,目前只是階段性開發,后期在項目中逐步完善。 前段時間公司提了一個新的需求,在商品的詳情頁要實現站內買家和商品賣家實時通訊的功能以方便溝通促成交易,要開發此功能當時首先考慮到的就是swoole和workerman了,從網上大概了解了一下關于這兩款工具的闡述,...
摘要:我們的平臺上有虛擬商品和實體商品兩大分類,當時也考慮到了消息的讀取狀態。商家發送時間是否已讀。看前端代碼當前的所有代碼并不是最終的,目前只是階段性開發,后期在項目中逐步完善。 前段時間公司提了一個新的需求,在商品的詳情頁要實現站內買家和商品賣家實時通訊的功能以方便溝通促成交易,要開發此功能當時首先考慮到的就是swoole和workerman了,從網上大概了解了一下關于這兩款工具的闡述,...
摘要:背景最近在一些項目需要用到實時推送給分組的用戶,前端需要傳輸給后端的信息比較少,通過多方考慮選擇了通過框架基于搭建微服務。擁有定時器異步客戶端異步異步異步異步消息隊列等眾多高性能組件。配合的定時器,也可以定時推送數據。 背景 最近在一些項目需要用到Websocket實時推送給分組的用戶,前端需要傳輸給后端的信息比較少,通過多方考慮選擇了通過GatewayWorker框架(基于Worke...
摘要:即時通訊中,最重要的是響應速度,我們需要展示消息列表那么這時會有未讀消息,未讀數量,最后一條消息內容,時間等等。目前設計是單表單庫。這里只是對即時通訊設計上做了一些簡要的闡述,如有疑問和建議,請在評論區回復。 詳解即時通訊設計實現(PHP+GatewayWorker+Redis) 需要實現的功能 一對一聊天(私聊) 一對多聊天(群聊) 類似QQ,微信等聊天列表 實時消息 顯示 工具...
閱讀 1815·2023-04-26 01:55
閱讀 1078·2021-09-30 09:47
閱讀 1673·2019-08-30 15:54
閱讀 740·2019-08-30 15:53
閱讀 692·2019-08-30 15:52
閱讀 1133·2019-08-30 15:44
閱讀 2409·2019-08-30 14:06
閱讀 1057·2019-08-29 16:39