文章目录
# 私信列表
小id放前
1、创建message表对应的实体类
public class Message {
private int id;
private int fromId; //发送者id
private int toId; //接受者id
private String conversationId; //会话id 小的id在前面 111_112 和112_111属于同一个会话
private String content; //内容
private int status; //状态
}0表示未读 1表示已读 2表示删除
private Date createTime;
2、编写Message数据层方法
- 当前用户的会话列表需要分页显示 ,因此需要分页的属性offset,limit;
- 查询数据库中属于当前用户id的所有会话,形成会话列表;
- 查询当前用户的会话数量,为分页做准备
- 每一个会话里又有很多内容信息,因此也需要进行分页,需要相关参数;
- 根据会话id查找得到相应的私信列表;
- 查询当前会话包含的私信数量;
- 需要在页面显示未读消息的数量包括会话未读数量和私信未读数量,因此需要传入用户id和会话id,根据选择传入相应的值
@Mapper
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);
}
3、编写Mapper对应xml文件
- 首先查找status不等于2并且发送者id不等于1的有效信息 等于1的是系统消息
- 传入的userid 可能是from也可能是to
- 根据conversation_id排序 选择同组conversation_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>
4、编写MessageService
@Service
public class MessageService {
@Autowired(required = false)
private MessageMapper messageMapper;
@Autowired
private SensitiveFilter sensitiveFilter;
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);
}
}
5、编写MessageController
//会话列表
@RequestMapping(value = "",method = RequestMethod.GET)
public String getLetterList(Model model, Page 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来存储遍历得到的每一个会话的信息
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()));
//放入未读消息数量
map.put("unreadCount", messageService.findLetterUnreadCount(user.getId(), message.getConversationId()));
//放入目标用户信息来显示相应的用户名头像等信息
//如果当前用户对象和fromid一样,说明应该显示接受对象信息,反之一样
int targetId = user.getId() == message.getFromId() ? message.getToId() : message.getFromId();
map.put("target", userService.queryUserById(targetId));
conversations.add(map);
}
}
model.addAttribute("conversations", conversations);
// 查询当前用户所有会话中未读消息数量
int AllLetterUnreadCount = messageService.findLetterUnreadCount(user.getId(),null);
model.addAttribute("AllLetterUnreadCount", AllLetterUnreadCount);
return "/site/letter";
}
//私信:每一个会话中的详细消息
//查找私信列表 需要传入会话的id
@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.queryUserById(message.getFromId()));
letters.add(map);
}
}
model.addAttribute("letters", letters);
// 会话中需要显示来自谁的私信
// 私信目标 用户信息
model.addAttribute("target", getLetterTarget(conversationId));
return "/site/letter-detail";
}
//把会话id拆分,如果当前用户id和id0一样说明,id1是相应的目标
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.queryUserById(id1);
} else {
return userService.queryUserById(id0);
}
}
6、修改页面
<!-- 私信列表 -->
<ul class="list-unstyled">
<li class="media pb-3 pt-3 mb-3 border-bottom position-relative" th:each="map:${conversations}">
<span class="badge badge-danger" th:text="${map.unreadCount}" th:if="${map.unreadCount!=0}">3</span>
<a href="profile.html">
<img th:src="${map.target.headerUrl}" class="mr-4 rounded-circle user-header" alt="用户头像" >
</a>
<div class="media-body">
<h6 class="mt-0 mb-3">
<span class="text-success" th:utext="${map.target.username}">落基山脉下的闲人</span>
<span class="float-right text-muted font-size-12" th:text="${#dates.format(map.conversation.createTime,'yyyy-MM-dd HH:mm:ss')}">2019-04-28 14:13:25</span>
</h6>
<div>
<a th:href="@{|/letter/detail/${map.conversation.conversationId}|}" th:utext="${map.conversation.content}">米粉车, 你来吧!</a>
<ul class="d-inline font-size-12 float-right">
<li class="d-inline ml-2"><a href="#" class="text-primary">共<i th:text="${map.letterCount}">5</i>条会话</a></li>
</ul>
</div>
</div>
</li>
</ul>
发送私信
增加新增消息和修改消息状态的方法
//发送消息
@RequestMapping(value = "/letter/send",method = RequestMethod.POST)
@ResponseBody
public String sendLetter(String toName, String content) {
User target = userService.queryUserByName(toName);
if (target == null) {
return CommunityUtil.getJSONString(1, "目标用户不存在!");
}
Message message = new Message();
message.setFromId(hostHolder.getUser().getId());
message.setToId(target.getId());
if (message.getFromId() < message.getToId()) {
message.setConversationId(message.getFromId() + "_" + message.getToId());
} else {
message.setConversationId(message.getToId() + "_" + message.getFromId());
}
message.setContent(content);
message.setCreateTime(new Date());
messageService.addMessage(message);
return CommunityUtil.getJSONString(0);
}
修改js页面
$(function(){
$("#sendBtn").click(send_letter);
$(".close").click(delete_msg);
});
function send_letter() {
$("#sendModal").modal("hide");
var toName = $("#recipient-name").val();
var content = $("#message-text").val();
$.post(
CONTEXT_PATH + "/letter/send",
{"toName":toName,"content":content},
function(data) {
data = $.parseJSON(data);
if(data.code == 0) {
$("#hintBody").text("发送成功!");
} else {
$("#hintBody").text(data.msg);
}
$("#hintModal").modal("show");
setTimeout(function(){
$("#hintModal").modal("hide");
location.reload();
}, 2000);
}
);
}
function delete_msg() {
// TODO 删除数据
$(this).parents(".media").remove();
}
把未读的私信设置为已读
//获取当前用户的私信中该用户属于接收方并且私信状态为0的帖子
private List<Integer> getLetterIds(List<Message> letterList) {
List<Integer> 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;
}
// 设置已读
List<Integer> ids = getLetterIds(letterList);
if (!ids.isEmpty()) {
messageService.updateStatus(ids,1);
}