有開發者提問怎麼做歷史記錄功能和即使不開啟聊天視窗有訊息提醒功能。簡單抽時間寫了點程式碼。不過只是基本思路,具體細節沒有實現。
正如前幾篇部落格中提到的,讀取歷史記錄什麼時候讀取呢?按照常理,應該是開啟聊天視窗的時候載入歷史記錄,當然也可以選擇非同步載入好,然後開啟哪個視窗就載入哪部分的記錄。當然我們並不知道使用者會開啟哪個視窗,所以,我還是建議,當使用者選擇人聊天的時候就讀取歷史記錄。那麼之前的功能已經做好了。我們需要充分利用 ctoc 方法。ctoc是什麼?不明白的就看看本系列前幾篇文章吧。
現在我們找到ctoc 後臺方法,可以看到我新增了GetHistoryMessage方法,引數為傳送人id和接收人id,那麼這個GetHistoryMessage方法就是做了讀取歷史記錄的操作,不管你從哪裡讀取的,是快取還是資料庫(前提是你發的訊息已經儲存了~~)
/// <summary> /// 人對人聊天 連線伺服器 /// </summary> /// <param name="sendid">傳送人</param> /// <param name="receiveid">接收人</param> /// <returns></returns> public Task ClientToClient(string sendid, string receiveid) { if (sendid == null || receiveid == null) { throw new ArgumentNullException("sendid or receiveid can't be null"); } //獲取組名 string groupName = MessageUtils.GetGroupName(sendid, receiveid); //將當前使用者新增到此組織內 Groups.Add(CurrentUserConnectionId, groupName); //構建系統連線成功訊息 //讀取歷史記錄 --- 2016-3-7 修改 var historyMsg = MessageUtils.GetHistoryMessage(sendid, receiveid); var msg = MessageUtils.GetSystemMessage(groupName, MessageConfig.ClientToClientConnectedSucceed, new { t = MessageConfig.ClientTypeCTC, currentid = sendid, receiveid = receiveid,history = historyMsg }); //將訊息推送到當前組 (A和B聊天的組) 同樣呼叫receiveMessage方法 return Clients.Caller.receiveMessage(msg); }
我們再來看看獲取歷史記錄的方法都做了什麼,首先他返回的訊息格式一定要符合我們設計的標準。以方便相容單條訊息傳送和接收
public static List<CSChatMessage> GetHistoryMessage(string sendid,string receiveid) { string groupName = GetGroupName(sendid, receiveid); List<CSChatMessage> historys = new List<CSChatMessage>(); //這裡歷史記錄作為demo使用,可以從資料庫或者快取讀取 historys.Add(new CSChatMessage { fromuser = new CSUser(groupName, null) { photo = "/photos/000.jpg", userid = int.Parse(sendid), username = "傳送方的名字" }, msg = "這一條是歷史記錄", msgtype = CSMessageType.Custom, touser = new CSUser(groupName, null) { photo = "/photos/001.jpg", userid = int.Parse(receiveid), username = "接收方的名字" }, other = new { t = MessageConfig.ClientTypeCTC }//這裡不要忘了加t引數 }); historys.Add(new CSChatMessage { touser = new CSUser(groupName, null) { photo = "/photos/000.jpg", userid = int.Parse(sendid), username = "傳送方的名字" }, msg = "這一條是歷史記錄", msgtype = CSMessageType.Custom, fromuser = new CSUser(groupName, null) { photo = "/photos/001.jpg", userid = int.Parse(receiveid), username = "接收方的名字" }, other = new { t = MessageConfig.ClientTypeCTC }//這裡不要忘了加t引數 }); historys.Add(new CSChatMessage { fromuser = new CSUser(groupName, null) { photo = "/photos/000.jpg", userid = int.Parse(sendid), username = "傳送方的名字" }, msg = "這一條是歷史記錄", msgtype = CSMessageType.Custom, touser = new CSUser(groupName, null) { photo = "/photos/001.jpg", userid = int.Parse(receiveid), username = "接收方的名字" }, other = new { t = MessageConfig.ClientTypeCTC }//這裡不要忘了加t引數 }); return historys; }
其實就加了這麼一個讀取歷史記錄的操作,我們來看看,連線成功之後,訊息返回JSON。
歷史記錄有了,我們剩下的要做的就很簡單了。修改前端處理 system 型別的訊息函式。(程式碼在client.hub.js /chat.handleSystemMsg)
handleSystemMsg: function (result) { if (result.other.t == 'one') { this.cache[result.other.receiveid] = "ok";//代表我已經和當前聊天人已經連線上了,下次點選沒必要再次連線 } else { this.cacheGroup[result.other.receiveid] = "ok"; } //然後在這裡處理歷史記錄 2016-3-7 if (result.other.history && result.other.history.length) { $(result.other.history).each(function (i,item) { //追加訊息 console.log(item); chat.handleCustomMsg(item);//每一個item就是一條訊息,這裡格式是通用的,所以,直接呼叫 handleCustomMsg方法就可以了。 }); } },
我們看一下效果:
是不是如此簡單就實現了歷史記錄的功能,當然實際專案中,如果把滾動條上拉可以看更多的歷史記錄,這裡就不需要signalR了,我們用一個ajax請求就可以了。
下面介紹一下,訊息通知。其實訊息通知的原理就是進入頁面的時候需要使用者連線伺服器,每當有使用者訊息的時候就會提示。因為之前的設計思路是當使用者點選某個人要聊天的時候才會連線,所以,即使使用者登入了網頁,也不會收到其他人給他傳送的訊息。所以我們要做的就是先讓使用者連線到伺服器。我這裡模擬了一下連線,就是開啟視窗,然後在關閉。(此時使用者處於連線狀態,能夠接收到訊息,只不過不會在視窗顯示)新增如下程式碼:(程式碼路徑:client.hub.js/chat.handleCustomMsg)
if (!log.imarea.length) { //這裡只有在連線過一次之後,並且關閉訊息框才會提示 if (result.touser.userid == hubConfig.currentUser.id) { alert("您收到訊息啦..."); } }
當對方在給我傳送訊息的時候就會提示啦:(PS:這裡只是一個思路,具體並沒有實現任何人傳送訊息就會提示。alert框是不是很難看,那麼讓你們的美工給優化一下吧。)
github 程式碼已經更新:https://github.com/fanpan26/LayIM/