有開發者提問怎么做歷史記錄功能和即使不打開聊天窗口有消息提醒功能。簡單抽時間寫了點代碼。不過只是基本思路,具體細節沒有實現。
正如前幾篇博客中提到的,讀取歷史記錄什么時候讀取呢?按照常理,應該是打開聊天窗口的時候加載歷史記錄,當然也可以選擇異步加載好,然后打開哪個窗口就加載哪部分的記錄。當然我們並不知道用戶會打開哪個窗口,所以,我還是建議,當用戶選擇人聊天的時候就讀取歷史記錄。那么之前的功能已經做好了。我們需要充分利用 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/