# 私信列表 --- 本节实现的功能: - 私信列表: - 查询当前用户的会话列表 - 每个会话只显示一条最新的私信 - 支持分页显示 - 私信详情 - 查询某个会话所包含的私信 - 支持分页显示 - 访问私信详情时,将显示的私信设为已读状态 `message` 表中有个字段 `conservation_id` ,这个字段的设计方式是:比如用户 id 112 给 113 发消息,或者 113 给 112 发消息,这两个会话的 `conservation_id` 都是 `112_113`。当然,这个字段是冗余的,我们可以通过 from_id 和 to_id 推演出来,但是有了这个字段方便于后面的查询等操作 注意:`from_id = 1` 代表这是一个系统通知,后续会开发此功能 ## DAO ```java @Mapper public interface MessageMapper { /** * 查询当前用户的会话列表,针对每个会话只返回一条最新的私信 * @param userId 用户 id * @param offset 每页的起始索引 * @param limit 每页显示多少条数据 * @return */ List selectConversations(int userId, int offset, int limit); /** * 查询当前用户的会话数量 * @param userId * @return */ int selectConversationCount(int userId); /** * 查询某个会话所包含的私信列表 * @param conversationId * @param offset * @param limit * @return */ List selectLetters(String conversationId, int offset, int limit); /** * 查询某个会话所包含的私信数量 * @param conversationId * @return */ int selectLetterCount(String conversationId); /** * 查询未读私信的数量 * @param userId * @param conversationId conversationId = null, 则查询该用户所有会话的未读私信数量 * conversationId != null, 则查询该用户某个会话的未读私信数量 * @return */ int selectLetterUnreadCount(int userId, String conversationId); /** * 修改消息的状态 * @param ids * @param status * @return */ int updateStatus(List ids, int status); } ``` 对应的 `mapper.xml` ```xml id, from_id, to_id, conversation_id, content, status, create_time update message set status = #{status} where id in #{id} ``` ## Service ```java @Service public class MessageService { @Autowired private MessageMapper messageMapper; // 查询当前用户的会话列表,针对每个会话只返回一条最新的私信 public List findConversations(int userId, int offset, int limit) { return messageMapper.selectConversations(userId, offset, limit); } // 查询当前用户的会话数量 public int findConversationCout(int userId) { return messageMapper.selectConversationCount(userId); } // 查询某个会话所包含的私信列表 public List findLetters(String conversationId, int offset, int limit) { return messageMapper.selectLetters(conversationId, offset, limit); } // 查询某个会话所包含的私信数量 public int findLetterCount(String conversationId) { return messageMapper.selectLetterCount(conversationId); } // 查询未读私信的数量 public int findLetterUnreadCount(int userId, String conversationId) { return messageMapper.selectLetterUnreadCount(userId, conversationId); } // 读取私信(将私信状态设置为已读) public int readMessage(List ids) { return messageMapper.updateStatus(ids, 1); } } ``` ## Controller ```java @Controller public class MessageController { @Autowired private HostHolder hostHolder; @Autowired private MessageService messageService; @Autowired private UserService userService; /** * 私信列表 * @param model * @param page * @return */ @GetMapping("/letter/list") public String getLetterList(Model model, Page page) { User user = hostHolder.getUser(); // 分页信息 page.setLimit(5); page.setPath("/letter/list"); page.setRows(messageService.findConversationCout(user.getId())); // 会话列表 List conversationList = messageService.findConversations( user.getId(), page.getOffset(), page.getLimit()); List> conversations = new ArrayList<>(); if (conversationList != null) { for (Message message : conversationList) { Map map = new HashMap<>(); map.put("conversation", message); // 私信 map.put("letterCount", messageService.findLetterCount( message.getConversationId())); // 私信数量 map.put("unreadCount", messageService.findLetterUnreadCount( user.getId(), message.getConversationId())); // 未读私信数量 int targetId = user.getId() == message.getFromId() ? message.getToId() : message.getFromId(); map.put("target", userService.findUserById(targetId)); // 私信对方 conversations.add(map); } } model.addAttribute("conversations", conversations); // 查询当前用户的所有未读私信数量 int letterUnreadCount = messageService.findLetterUnreadCount(user.getId(), null); model.addAttribute("letterUnreadCount", letterUnreadCount); return "/site/letter"; } /** * 私信详情页 * @param conversationId * @param page * @param model * @return */ @GetMapping("/letter/detail/{conversationId}") public String getLetterDetail(@PathVariable("conversationId") String conversationId, Page page, Model model) { // 分页信息 page.setLimit(5); page.setPath("/letter/detail/" + conversationId); page.setRows(messageService.findLetterCount(conversationId)); // 私信列表 List letterList = messageService.findLetters(conversationId, page.getOffset(), page.getLimit()); List> letters = new ArrayList<>(); if (letterList != null) { for (Message message : letterList) { Map map = new HashMap<>(); map.put("letter", message); map.put("fromUser", userService.findUserById(message.getFromId())); letters.add(map); } } model.addAttribute("letters", letters); // 私信目标 model.addAttribute("target", getLetterTarget(conversationId)); // 将私信列表中的未读消息改为已读 List ids = getUnreadLetterIds(letterList); if (!ids.isEmpty()) { messageService.readMessage(ids); } return "/site/letter-detail"; } /** * 获取私信对方对象 * @param conversationId * @return */ private User getLetterTarget(String conversationId) { String[] ids = conversationId.split("_"); int id0 = Integer.parseInt(ids[0]); int id1 = Integer.parseInt(ids[1]); if (hostHolder.getUser().getId() == id0) { return userService.findUserById(id1); } else { return userService.findUserById(id0); } } /** * 获取当前登录用户未读私信的 id * @param letterList * @return */ private List getUnreadLetterIds(List letterList) { List ids = new ArrayList<>(); if (letterList != null) { for (Message message : letterList) { // 当前用户是私信的接收者且该私信处于未读状态 if (hostHolder.getUser().getId() == message.getToId() && message.getStatus() == 0) { ids.add(message.getId()); } } } return ids; } } ``` ## 前端 `letter-detail` ```html li th:each="map:${letters}"> 用户头像
```