仿牛客网社区项目(十七)私信列表

私信列表

  • 私信列表
    • 查询当前用户的会话列表, 每个会话只显示一条最新的私信。
    • 支持分页显示。
  • 私信详情
    • 查询某个会话所包含的私信。
    • 支持分页显示。

首先看一下数据库的设计,私信相当于一个对话功能,那么两个人就组成一个对话,这段对话里有A发给B的消息,有B发给A的消息,那么我们把发送者和接收者的id拼接到一起形成一个会话id,把id小的拼接在前面。还有一种私信是系统通知,那么只需要把from_id指定一个固定的值,这里指定为1。

image-20220426232035924

实体类#

新建Message实体类,对应数据库字段。

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Message {
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    private Integer fromId;
    private Integer toId;
    private String conversationId;
    private String content;
    private int status;//这里status是int类型的 不然sql语句会出问题
    private Date createTime;
}

数据层#

新建MessageMapper,定义好方法。私信列表需要显示的内容:

package com.neu.langsam.community.dao;


import com.neu.langsam.community.entity.Message;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface MessageMapper {

    //查询当前用户的会话列表,针对每个会话只返回一条最新的私信
    List<Message> selectConversations(int userId,int offset,int limit);

    //查询当前用户的会话数量
    int selectConversationCount(int userId);

    //查询某个会话所包含的私信列表
    List<Message> selectLetters(String conversationId,int offset,int limit);

    //查询某个会话所包含的私信数量
    int selectLetterCount(String conversationId);

    //查询未读私信的数量
    int selectLetterUnreadCount(int userId,String conversationId);


}


新建message-mapper.xml实现上面的方法。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huang.community.mapper.MessageMapper">

    <sql id="selectFields">
        id,from_id,to_id,conversation_id,content,status,create_time
    </sql>

    //status=2为已删除,from_id=1是系统通知
    //按照对话id进行分组,查出每个组里最大的id,那就是最新的私信
    <select id="selectConversations" resultType="Message">
        SELECT
        <include refid="selectFields"></include>
        FROM message
        WHERE id in (
        SELECT max(id) from message
        WHERE `status` !=2
        AND from_id !=1
        AND (from_id =#{userId} or to_id=#{userId})
        GROUP BY conversation_id
        )
        ORDER BY id desc
        limit #{offset},#{limit}
    </select>

    //统计会话数量
    <select id="selectConversationCount" resultType="int">
        select count(m.maxid)
        from (
                 SELECT max(id) as maxid
                 from message
                 WHERE `status` != 2
                   AND from_id != 1
                   AND (from_id = #{userId} or to_id = #{userId})
                 GROUP BY conversation_id
             ) as m
    </select>

    <select id="selectLetters" resultType="Message">
        select
        <include refid="selectFields"></include>
        from message
        where status != 2
        and from_id != 1
        and conversation_id = #{conversationId}
        order by id desc
        limit #{offset},#{limit}
    </select>

    <select id="selectLetterCount" resultType="int">
        select count(id)
        from message
        where status != 2
          and from_id != 1
          and conversation_id = #{conversationId}
    </select>

    <select id="selectLetterUnreadCount" resultType="int">
        select count(id)
        from message
        where status=0
        and from_id!=1
        and to_id=#{userId}
        <if test="conversationId!=null">
            and conversation_id=#{conversationId}
        </if>
    </select>
</mapper>

业务层#

新建MessageService,比较简单,之间返回查询到的数据。

package com.neu.langsam.community.service;

import com.neu.langsam.community.dao.MessageMapper;
import com.neu.langsam.community.entity.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class MessageService {
    @Autowired
    private MessageMapper messageMapper;

    public List<Message> findConversations(int userId, int offset, int limit) {
        return messageMapper.selectConversations(userId, offset, limit);
    }

    public int findConversationCount(int userId) {
        return messageMapper.selectConversationCount(userId);
    }

    public List<Message> 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);
    }
}


表现层#

要加载私信列表,从hostholder获取当前用户。将会话和私信内容,未读数量等封装到List<map<>>里。

package com.huang.community.controller;

import com.huang.community.model.NewPage;
import com.huang.community.pojo.Message;
import com.huang.community.pojo.User;
import com.huang.community.service.MessageService;
import com.huang.community.service.UserService;
import com.huang.community.util.CommunityUtil;
import com.huang.community.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

@Controller
public class MessageController {
    @Autowired
    private MessageService messageService;

    @Autowired
    private HostHolder hostHolder;

    @Autowired
    private UserService userService;

    // 私信列表
    @RequestMapping(path = "/letter/list", method = RequestMethod.GET)
    public String getLetterList(Model model, NewPage page) {
        User user = hostHolder.getUser();
        // 分页信息
        page.setLimit(5);
        page.setPath("/letter/list");
        page.setRows(messageService.findConversationCount(user.getId()));

        // 会话列表
        List<Message> conversationList = messageService.findConversations(
                user.getId(), page.getOffset(), page.getLimit());
        List<Map<String, Object>> conversations = new ArrayList<>();
        if (conversationList != null) {
            for (Message message : conversationList) {
                Map<String, Object> map = new HashMap<>();
                map.put("conversation", message);
                map.put("letterCount", messageService.findLetterCount(message.getConversationId()));
                //需要显示的是私信者的信息 所以需要排除自己,因为自己可能是from 或 to
                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";
    }

查看效果

img

然后继续开发会话详情功能。当前端点击会话列表中的某一个时,传入会话id,查询该会话id下的所有私信。页面上还需要显示发送私信的人,拆解conversationid,判断哪个是收信人。

@RequestMapping(path = "/letter/detail/{conversationId}",method = RequestMethod.GET)
    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<Message> letterList=messageService.findLetters(conversationId,page.getOffset(),page.getLimit());
        List<Map<String,Object>> letters=new ArrayList<>();
        if(letterList!=null){
            for (Message message:letterList){
                Map<String,Object> 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));

        return "/site/letter-detail";
    }

    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);
        }
    }

img

posted @   卷皇  阅读(282)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
点击右上角即可分享
微信分享提示
主题色彩