Echo 的私信列表與詳情頁是怎么做的
先看效果圖吧:


從圖片上可以看出來,我們要做的事情大概有這些:
1)私信列表:
查詢當前用戶的會話列表,且每個會話只顯示一條最新的私信 查詢某個會話的私信數(shù)量 支持分頁顯示 顯示未讀消息數(shù)量 顯示與某個用戶對話的未讀消息數(shù)量 顯示所有對話的未讀消息消息
2)私信詳情:
查詢某個會話所包含的私信 支持分頁顯示 訪問私信詳情時,將顯示的私信設為已讀狀態(tài)
OK,先回顧下私信表的結(jié)構(gòu):
id:私信/系統(tǒng)通知的唯一標識 from_id:私信/系統(tǒng)通知的發(fā)送方 id to_id:私信/系統(tǒng)通知的接收方 id conversation_id:標識兩個用戶之間的對話。比如用戶 id 112 給 113 發(fā)消息,或者 113 給 112 發(fā)消息,我們規(guī)定這兩個會話的 conservation_id都是112_113。這樣,通過這個字段我們就能迅速查出 112 和 113 之間的私信往來。當然,這個字段是冗余的,我們可以通過 from_id 和 to_id 推演出來,但是有了這個字段方便后面的查詢等操作content:私信/系統(tǒng)通知的內(nèi)容 status:私信/系統(tǒng)通知的狀態(tài)(這個字段就是我們實現(xiàn)未讀消息的關鍵) 0 - 未讀(默認) 1 - 已讀 2 - 刪除(暫未使用) create_time:私信/系統(tǒng)通知的發(fā)送時間
需要注意的是:這張表不僅存儲用戶之間的私信,也存儲系統(tǒng)通知,不同的是,系統(tǒng)通知的 from_id 特定為 1,而這個 id 為 1 的用戶是我們手動內(nèi)置進去的。

Dao 層
根據(jù)上述羅列的大致需要做的事情,我們來定義下 Dao 層的操作。
分頁查詢這里就不再說了,直接復用我們封裝好的模型即可,不明白的小伙伴可以看這里 Echo 的帖子列表與分頁是怎么做的,需要注意的是,分頁查詢需要獲得該用戶的所有會話數(shù)量(該方法是 selectConversationCount,與接下來介紹的 selectConversations 差不多,這里),從而計算頁數(shù)。
首先,對于私信列表頁:
1)詢問當前用戶的會話列表,針對每個會話只返回一條最新的私信:selectConversations
對于當前用戶來說,它的會話列表中,不僅包含別人發(fā)給他的,也包含他發(fā)給別人的,所以在查詢的時候,只要這條私信的 from_id 或者 to_id 的其中一個字段與該用戶的 id 相同,那么就認為這條私信屬于該用戶。
至于這條私信需不需要顯示在會話列表中呢?
我們說了,針對每個會話只返回一條最新的私信。這個也好辦,首先按照 conversion_id 也就是會話 id 進行分組歸類,查到這個分組所擁有的所有私信后,私信記錄 id 最大的那條就是這個分組會話中最新的私信。
看代碼,不難理解:

2)查詢某個會話的私信數(shù)量:selectLetterCount
這個簡單,直接按照 conversation_id 查就行。

3)顯示該用戶的未讀消息數(shù)量,這個功能包含兩點:顯示與某個用戶對話的未讀消息數(shù)量;顯示所有對話的未讀消息消息。
輕車熟路,使用動態(tài) SQL,一個方法搞定:selectLetterUnreadCount
如果傳入的參數(shù) conversationId == null,就查詢該用戶所有會話的未讀私信數(shù)量;如果傳入的 conversationId != null,則查詢這個會話的未讀私信數(shù)量。
另外,未讀消息即狀態(tài) status = 0。既然是未讀消息,那肯定是別人發(fā)給我的對吧,我發(fā)給別人的消息談何未讀呢?所以這里需要指定 to_id 等于該用戶的 id。

再來看私信詳細頁需要做的事情:
1)查詢某個會話所包含的私信:selectLetters
和查詢某個會話的私信數(shù)量 selectLetterCount 方法差不多,沒啥難度,直接按照 conversation_id 查就行。

2)訪問私信詳情時,將顯示的私信設為已讀狀態(tài)
具體的業(yè)務邏輯我們下文會講,這里只解釋下 Dao 層批量修改私信狀態(tài)的操作:updateStatus

表現(xiàn)層
前端部分我就不寫了,直接獲取后臺存入 Model 中的值就行。
首先,對于私信列表:getLetterList

這段代碼大部分沒啥好說的,需要注意的是查詢未讀消息數(shù)量這塊,各位應該注意到在我們的界面頂部也會顯示一個未讀消息數(shù)量,這個數(shù)量是未讀私信的數(shù)量和未讀系統(tǒng)通知數(shù)量(后續(xù)文章會寫)的總和,這個怎么做呢?怎么把未讀私信的數(shù)量和未讀系統(tǒng)通知數(shù)量實時的傳過來呢?

沒錯,攔截器。

這樣,前端讀取 allUnreadCount 這個屬性就行了。
再來看私信詳情:getLetterDetail

這里需要注意的就是上圖粉紅色框中的代碼。
可能有些小伙伴會疑惑私信目標 target 是干啥的,這個不難理解,看下圖:

這里需要做個簡單的判斷,上文說過, conservation_id 的生成是需要遵守一個規(guī)則的,比如用戶 id 112 給 113 發(fā)消息,或者 113 給 112 發(fā)消息,我們規(guī)定這兩個會話的 conservation_id 都是 112_113。也就是說 id 按照從小到大排的。
那如果當前登錄用戶是 112,這個會話里顯示的私信目標就應該是用戶 113;如果當前登錄用戶是 113,那這個會話里顯示的私信目標就應該是用戶 112。具體判斷代碼看這里:

OK,再來看如何將私信列表中的未讀消息改為已讀。
具體流程是這樣的:進入私信詳情頁后,先從當前頁的私信列表 letterList 中獲取當前登錄用戶未讀私信的 id,然后批量的將這些 id 對應的私信狀態(tài)設置為已讀。
這里多提一嘴,防止有小伙伴懵逼,我們的私信列表 letterList 是按照分頁查詢的,每次進入新的一頁,letterList 就會發(fā)生新的變化。所以你看到的效果就是這樣的:
當你點開一個會話后,你會先進入第一頁,然后第一頁消息列表中的所有未讀消息的狀態(tài)都會被設置為已讀;你進入第二頁,于是第二頁消息列表中的所有未讀消息的狀態(tài)都會被設置為已讀......
至于如何獲取當前登錄用戶未讀私信的 id,沒啥好說的,這里直接貼個圖吧:

