add 聊天记录列表
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
package com.lld.im.common.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class ChatHistoryReq extends RequestBase {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
||||||
|
private String operater;
|
||||||
|
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
|
||||||
|
//单次拉取数量
|
||||||
|
private Integer limit;
|
||||||
|
|
||||||
|
//第几页
|
||||||
|
private Integer offset;
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.lld.im.service.message.controller;
|
package com.lld.im.service.message.controller;
|
||||||
|
|
||||||
import com.lld.im.common.ResponseVO;
|
import com.lld.im.common.ResponseVO;
|
||||||
|
import com.lld.im.common.model.ChatHistoryReq;
|
||||||
import com.lld.im.common.model.SyncReq;
|
import com.lld.im.common.model.SyncReq;
|
||||||
import com.lld.im.common.model.message.CheckSendMessageReq;
|
import com.lld.im.common.model.message.CheckSendMessageReq;
|
||||||
import com.lld.im.service.message.model.req.SendMessageReq;
|
import com.lld.im.service.message.model.req.SendMessageReq;
|
||||||
|
import com.lld.im.service.message.model.resp.ImMessageHistoryVo;
|
||||||
import com.lld.im.service.message.service.MessageSyncService;
|
import com.lld.im.service.message.service.MessageSyncService;
|
||||||
import com.lld.im.service.message.service.P2PMessageService;
|
import com.lld.im.service.message.service.P2PMessageService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -12,6 +14,8 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description:
|
* @description:
|
||||||
* @author: lld
|
* @author: lld
|
||||||
@@ -46,7 +50,33 @@ public class MessageController {
|
|||||||
return messageSyncService.syncOfflineMessage(req);
|
return messageSyncService.syncOfflineMessage(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会话列表
|
||||||
|
* @param req
|
||||||
|
* @param appId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@RequestMapping("/listMessage")
|
||||||
|
public ResponseVO listMessage(@RequestBody
|
||||||
|
@Validated SyncReq req, Integer appId) {
|
||||||
|
req.setAppId(appId);
|
||||||
|
List<Object> objects = messageSyncService.listSession(req);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会话列表
|
||||||
|
* @param req
|
||||||
|
* @param appId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@RequestMapping("/chatHistory")
|
||||||
|
public ResponseVO chatHistory(@RequestBody
|
||||||
|
@Validated ChatHistoryReq chatHistoryReq, Integer appId) {
|
||||||
|
chatHistoryReq.setAppId(appId);
|
||||||
|
List<ImMessageHistoryVo> imMessageHistoryVos = messageSyncService.chatHistory(chatHistoryReq);
|
||||||
|
return ResponseVO.successResponse(imMessageHistoryVos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.lld.im.service.message.model.resp;
|
||||||
|
|
||||||
|
import com.lld.im.service.message.dao.ImMessageHistoryEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Chackylee
|
||||||
|
* @description:
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class ImMessageHistoryVo extends ImMessageHistoryEntity {
|
||||||
|
|
||||||
|
private String messageBody;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
package com.lld.im.service.message.service;
|
package com.lld.im.service.message.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.lld.im.codec.pack.message.MessageReadedPack;
|
import com.lld.im.codec.pack.message.MessageReadedPack;
|
||||||
import com.lld.im.codec.pack.message.RecallMessageNotifyPack;
|
import com.lld.im.codec.pack.message.RecallMessageNotifyPack;
|
||||||
import com.lld.im.codec.proto.Message;
|
|
||||||
import com.lld.im.common.ResponseVO;
|
import com.lld.im.common.ResponseVO;
|
||||||
import com.lld.im.common.constant.Constants;
|
import com.lld.im.common.constant.Constants;
|
||||||
import com.lld.im.common.enums.ConversationTypeEnum;
|
import com.lld.im.common.enums.ConversationTypeEnum;
|
||||||
@@ -14,6 +15,7 @@ import com.lld.im.common.enums.MessageErrorCode;
|
|||||||
import com.lld.im.common.enums.command.Command;
|
import com.lld.im.common.enums.command.Command;
|
||||||
import com.lld.im.common.enums.command.GroupEventCommand;
|
import com.lld.im.common.enums.command.GroupEventCommand;
|
||||||
import com.lld.im.common.enums.command.MessageCommand;
|
import com.lld.im.common.enums.command.MessageCommand;
|
||||||
|
import com.lld.im.common.model.ChatHistoryReq;
|
||||||
import com.lld.im.common.model.ClientInfo;
|
import com.lld.im.common.model.ClientInfo;
|
||||||
import com.lld.im.common.model.SyncReq;
|
import com.lld.im.common.model.SyncReq;
|
||||||
import com.lld.im.common.model.SyncResp;
|
import com.lld.im.common.model.SyncResp;
|
||||||
@@ -24,12 +26,13 @@ import com.lld.im.common.model.message.RecallMessageContent;
|
|||||||
import com.lld.im.service.conversation.service.ConversationService;
|
import com.lld.im.service.conversation.service.ConversationService;
|
||||||
import com.lld.im.service.group.service.ImGroupMemberService;
|
import com.lld.im.service.group.service.ImGroupMemberService;
|
||||||
import com.lld.im.service.message.dao.ImMessageBodyEntity;
|
import com.lld.im.service.message.dao.ImMessageBodyEntity;
|
||||||
|
import com.lld.im.service.message.dao.ImMessageHistoryEntity;
|
||||||
import com.lld.im.service.message.dao.mapper.ImMessageBodyMapper;
|
import com.lld.im.service.message.dao.mapper.ImMessageBodyMapper;
|
||||||
|
import com.lld.im.service.message.dao.mapper.ImMessageHistoryMapper;
|
||||||
|
import com.lld.im.service.message.model.resp.ImMessageHistoryVo;
|
||||||
import com.lld.im.service.seq.RedisSeq;
|
import com.lld.im.service.seq.RedisSeq;
|
||||||
import com.lld.im.service.utils.ConversationIdGenerate;
|
import com.lld.im.service.utils.*;
|
||||||
import com.lld.im.service.utils.GroupMessageProducer;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import com.lld.im.service.utils.MessageProducer;
|
|
||||||
import com.lld.im.service.utils.SnowflakeIdWorker;
|
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.DefaultTypedTuple;
|
import org.springframework.data.redis.core.DefaultTypedTuple;
|
||||||
@@ -39,7 +42,9 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description:
|
* @description:
|
||||||
@@ -73,6 +78,8 @@ public class MessageSyncService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
GroupMessageProducer groupMessageProducer;
|
GroupMessageProducer groupMessageProducer;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ImMessageHistoryMapper imMessageHistoryMapper;
|
||||||
|
|
||||||
public void receiveMark(MessageReciveAckContent messageReciveAckContent){
|
public void receiveMark(MessageReciveAckContent messageReciveAckContent){
|
||||||
messageProducer.sendToUser(messageReciveAckContent.getToId(),
|
messageProducer.sendToUser(messageReciveAckContent.getToId(),
|
||||||
@@ -156,6 +163,103 @@ public class MessageSyncService {
|
|||||||
return ResponseVO.successResponse(resp);
|
return ResponseVO.successResponse(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Object> listSession(SyncReq req){
|
||||||
|
List<OfflineMessageContent> listOfflineMessage = listOfflineMessage(req);
|
||||||
|
|
||||||
|
List<ImMessageHistoryEntity> listReadMessage = listReadMessage(req);
|
||||||
|
Map<String, Long> collect = listReadMessage.stream().collect(Collectors.toMap(ImMessageHistoryEntity::getOwnerId, ImMessageHistoryEntity::getMessageKey));
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ImMessageHistoryVo> chatHistory(ChatHistoryReq chatHistoryReq){
|
||||||
|
Page<ImMessageHistoryEntity> objectPage = new Page<>(chatHistoryReq.getOffset(),chatHistoryReq.getLimit());
|
||||||
|
LambdaQueryWrapper<ImMessageHistoryEntity> and = new LambdaQueryWrapper<ImMessageHistoryEntity>().eq(ImMessageHistoryEntity::getOwnerId, chatHistoryReq.getOperater())
|
||||||
|
.and(x -> x.eq(ImMessageHistoryEntity::getFromId, chatHistoryReq.getUserId()).or().eq(ImMessageHistoryEntity::getToId, chatHistoryReq.getUserId()))
|
||||||
|
.orderByDesc(ImMessageHistoryEntity::getMessageKey);
|
||||||
|
Page<ImMessageHistoryEntity> imMessageHistoryEntities = imMessageHistoryMapper.selectPage(objectPage,and);
|
||||||
|
List<Long> messageKeys = imMessageHistoryEntities.getRecords().stream().map(x -> x.getMessageKey()).collect(Collectors.toList());
|
||||||
|
List<ImMessageBodyEntity> imMessageBodyEntities = imMessageBodyMapper.selectList(new LambdaQueryWrapper<ImMessageBodyEntity>().in(ImMessageBodyEntity::getMessageKey, messageKeys));
|
||||||
|
Map<Long, ImMessageBodyEntity> collect = imMessageBodyEntities.stream().collect(Collectors.toMap(ImMessageBodyEntity::getMessageKey, x -> x));
|
||||||
|
|
||||||
|
List<ImMessageHistoryVo> imMessageHistoryVos = BeanCopyUtils.copyList(imMessageHistoryEntities.getRecords(), ImMessageHistoryVo.class);
|
||||||
|
for (ImMessageHistoryVo imMessageHistoryVo : imMessageHistoryVos) {
|
||||||
|
ImMessageBodyEntity imMessageBodyEntity = collect.get(imMessageHistoryVo.getMessageKey());
|
||||||
|
imMessageHistoryVo.setMessageBody(imMessageBodyEntity.getMessageBody());
|
||||||
|
}
|
||||||
|
return imMessageHistoryVos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取离线消息
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<OfflineMessageContent> listOfflineMessage(SyncReq req) {
|
||||||
|
String key = req.getAppId() + ":" + Constants.RedisConstants.OfflineMessage + ":" + req.getOperater();
|
||||||
|
//获取最大的seq
|
||||||
|
Long maxSeq = 0L;
|
||||||
|
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
|
||||||
|
Set set = zSetOperations.reverseRangeWithScores(key, 0, 0);
|
||||||
|
if(!CollectionUtils.isEmpty(set)){
|
||||||
|
List list = new ArrayList(set);
|
||||||
|
DefaultTypedTuple o = (DefaultTypedTuple) list.get(0);
|
||||||
|
maxSeq = o.getScore().longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<OfflineMessageContent> respList = new ArrayList<>();
|
||||||
|
|
||||||
|
Set<ZSetOperations.TypedTuple> querySet = zSetOperations.rangeByScoreWithScores(key,
|
||||||
|
req.getLastSequence(), maxSeq, 0, -1);
|
||||||
|
for (ZSetOperations.TypedTuple<String> typedTuple : querySet) {
|
||||||
|
String value = typedTuple.getValue();
|
||||||
|
OfflineMessageContent offlineMessageContent = JSONObject.parseObject(value, OfflineMessageContent.class);
|
||||||
|
respList.add(offlineMessageContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// List<OfflineMessageContent> imMessageBodyIds = new ArrayList<>();
|
||||||
|
// Map<String, OfflineMessageContent> toIdMap = respList.stream().collect(Collectors.toMap(OfflineMessageContent::getToId, x -> x));
|
||||||
|
// Map<String, Optional<OfflineMessageContent>> toIdMap2 = respList.stream().
|
||||||
|
// collect(Collectors.groupingBy(x -> x.getFromId() + "-"+ x.getToId(),Collectors.maxBy(Comparator.comparingLong(OfflineMessageContent::getMessageKey))));
|
||||||
|
// for (OfflineMessageContent offlineMessageContent : respList) {
|
||||||
|
// OfflineMessageContent messageKey1 = toIdMap.get(offlineMessageContent.getToId());
|
||||||
|
// if (messageKey1 != null){
|
||||||
|
// imMessageBodyIds.add(messageKey1.getMessageKey() > offlineMessageContent.getMessageKey() ? messageKey1 : offlineMessageContent);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
return respList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取已读消息
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<ImMessageHistoryEntity> listReadMessage(SyncReq req) {
|
||||||
|
List<ImMessageHistoryEntity> imMessageHistoryEntities = imMessageHistoryMapper.selectMessageByOwnId(req.getOperater());
|
||||||
|
List<Long> imMessageBodyIds = new ArrayList<>();
|
||||||
|
|
||||||
|
Map<String, Long> fromIdMap = imMessageHistoryEntities.stream()
|
||||||
|
.filter(x -> !StringUtils.equals(x.getFromId(),req.getOperater()))
|
||||||
|
.collect(Collectors.toMap(ImMessageHistoryEntity::getFromId, ImMessageHistoryEntity::getMessageKey));
|
||||||
|
Map<String, Long> toIdMap = imMessageHistoryEntities.stream()
|
||||||
|
.filter(x -> !StringUtils.equals(x.getToId(),req.getOperater()))
|
||||||
|
.collect(Collectors.toMap(ImMessageHistoryEntity::getToId, ImMessageHistoryEntity::getMessageKey));
|
||||||
|
fromIdMap.forEach((key,value) -> {
|
||||||
|
toIdMap.merge(key,value,(x,y) -> {
|
||||||
|
if (value > y) return value;
|
||||||
|
return y;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
List<ImMessageBodyEntity> imMessageBodyEntities = imMessageBodyMapper.selectList(new LambdaQueryWrapper<ImMessageBodyEntity>().in(ImMessageBodyEntity::getMessageKey, imMessageBodyIds));
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
//修改历史消息的状态
|
//修改历史消息的状态
|
||||||
//修改离线消息的状态
|
//修改离线消息的状态
|
||||||
//ack给发送方
|
//ack给发送方
|
||||||
|
|||||||
Reference in New Issue
Block a user