Echo 的私信列表与详情页是怎么做的

2021-05-14 16:17:43 浏览数 (1)

先看效果图吧:

私信列表

私信详情

从图片上可以看出来,我们要做的事情大概有这些:

1)私信列表:

  • 查询当前用户的会话列表,且每个会话只显示一条最新的私信
  • 查询某个会话的私信数量
  • 支持分页显示
  • 显示未读消息数量
    • 显示与某个用户对话的未读消息数量
    • 显示所有对话的未读消息消息

2)私信详情:

  • 查询某个会话所包含的私信
  • 支持分页显示
  • 访问私信详情时,将显示的私信设为已读状态

OK,先回顾下私信表的结构:

  • id:私信/系统通知的唯一标识
  • from_id:私信/系统通知的发送方 id
  • to_id:私信/系统通知的接收方 id
  • conversation_id:标识两个用户之间的对话。比如用户 id 112 给 113 发消息,或者 113 给 112 发消息,我们规定这两个会话的 conservation_id 都是 112_113。这样,通过这个字段我们就能迅速查出 112 和 113 之间的私信往来。当然,这个字段是冗余的,我们可以通过 from_id 和 to_id 推演出来,但是有了这个字段方便后面的查询等操作
  • content:私信/系统通知的内容
  • status:私信/系统通知的状态(这个字段就是我们实现未读消息的关键)
    • 0 - 未读(默认)
    • 1 - 已读
    • 2 - 删除(暂未使用)
  • create_time:私信/系统通知的发送时间

需要注意的是:这张表不仅存储用户之间的私信,也存储系统通知,不同的是,系统通知的 from_id 特定为 1,而这个 id 为 1 的用户是我们手动内置进去的。

Dao 层

根据上述罗列的大致需要做的事情,我们来定义下 Dao 层的操作。

分页查询这里就不再说了,直接复用我们封装好的模型即可,不明白的小伙伴可以看这里 Echo 的帖子列表与分页是怎么做的,需要注意的是,分页查询需要获得该用户的所有会话数量(该方法是 selectConversationCount,与接下来介绍的 selectConversations 差不多,这里),从而计算页数。

首先,对于私信列表页:

1)询问当前用户的会话列表,针对每个会话只返回一条最新的私信:selectConversations

对于当前用户来说,它的会话列表中,不仅包含别人发给他的,也包含他发给别人的,所以在查询的时候,只要这条私信的 from_id 或者 to_id 的其中一个字段与该用户的 id 相同,那么就认为这条私信属于该用户。

至于这条私信需不需要显示在会话列表中呢?

我们说了,针对每个会话只返回一条最新的私信。这个也好办,首先按照 conversion_id 也就是会话 id 进行分组归类,查到这个分组所拥有的所有私信后,私信记录 id 最大的那条就是这个分组会话中最新的私信。

看代码,不难理解:

2)查询某个会话的私信数量:selectLetterCount

这个简单,直接按照 conversation_id 查就行。

3)显示该用户的未读消息数量,这个功能包含两点:显示与某个用户对话的未读消息数量;显示所有对话的未读消息消息。

轻车熟路,使用动态 SQL,一个方法搞定:selectLetterUnreadCount

如果传入的参数 conversationId == null,就查询该用户所有会话的未读私信数量;如果传入的 conversationId != null,则查询这个会话的未读私信数量。

另外,未读消息即状态 status = 0。既然是未读消息,那肯定是别人发给我的对吧,我发给别人的消息谈何未读呢?所以这里需要指定 to_id 等于该用户的 id。

再来看私信详细页需要做的事情:

1)查询某个会话所包含的私信:selectLetters

和查询某个会话的私信数量 selectLetterCount 方法差不多,没啥难度,直接按照 conversation_id 查就行。

2)访问私信详情时,将显示的私信设为已读状态

具体的业务逻辑我们下文会讲,这里只解释下 Dao 层批量修改私信状态的操作:updateStatus

表现层

前端部分我就不写了,直接获取后台存入 Model 中的值就行。

首先,对于私信列表:getLetterList

这段代码大部分没啥好说的,需要注意的是查询未读消息数量这块,各位应该注意到在我们的界面顶部也会显示一个未读消息数量,这个数量是未读私信的数量和未读系统通知数量(后续文章会写)的总和,这个怎么做呢?怎么把未读私信的数量和未读系统通知数量实时的传过来呢?

没错,拦截器。

这样,前端读取 allUnreadCount 这个属性就行了。

再来看私信详情:getLetterDetail

这里需要注意的就是上图粉红色框中的代码。

可能有些小伙伴会疑惑私信目标 target 是干啥的,这个不难理解,看下图:

这里需要做个简单的判断,上文说过, conservation_id 的生成是需要遵守一个规则的,比如用户 id 112 给 113 发消息,或者 113 给 112 发消息,我们规定这两个会话的 conservation_id 都是 112_113。也就是说 id 按照从小到大排的。

那如果当前登录用户是 112,这个会话里显示的私信目标就应该是用户 113;如果当前登录用户是 113,那这个会话里显示的私信目标就应该是用户 112。具体判断代码看这里:

OK,再来看如何将私信列表中的未读消息改为已读。

具体流程是这样的:进入私信详情页后,先从当前页的私信列表 letterList 中获取当前登录用户未读私信的 id,然后批量的将这些 id 对应的私信状态设置为已读。

这里多提一嘴,防止有小伙伴懵逼,我们的私信列表 letterList 是按照分页查询的,每次进入新的一页,letterList 就会发生新的变化。所以你看到的效果就是这样的:

当你点开一个会话后,你会先进入第一页,然后第一页消息列表中的所有未读消息的状态都会被设置为已读;你进入第二页,于是第二页消息列表中的所有未读消息的状态都会被设置为已读......

至于如何获取当前登录用户未读私信的 id,没啥好说的,这里直接贴个图吧:

0 人点赞