mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-14 06:03:42 +08:00
mallchat项目重构
This commit is contained in:
43
mallchat-chat-server/pom.xml
Normal file
43
mallchat-chat-server/pom.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>mallchat</artifactId>
|
||||
<groupId>com.abin.mallchat</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>mallchat-chat-server</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.abin.mallchat</groupId>
|
||||
<artifactId>mallchat-common-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.abin.mallchat</groupId>
|
||||
<artifactId>mallchat-transaction</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.knuddels</groupId>
|
||||
<artifactId>jtokkit</artifactId>
|
||||
<version>0.6.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.4.3</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.abin.mallchat.common;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
|
||||
/**
|
||||
* @author zhongzb
|
||||
* @date 2021/05/27
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = {"com.abin.mallchat"})
|
||||
@MapperScan({"com.abin.mallchat.common.**.mapper"})
|
||||
@ServletComponentScan
|
||||
public class MallchatCustomApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MallchatCustomApplication.class,args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.abin.mallchat.common.chat.consumer;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.ContactDao;
|
||||
import com.abin.mallchat.common.chat.dao.MessageDao;
|
||||
import com.abin.mallchat.common.chat.dao.RoomDao;
|
||||
import com.abin.mallchat.common.chat.dao.RoomFriendDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp;
|
||||
import com.abin.mallchat.common.chat.service.ChatService;
|
||||
import com.abin.mallchat.common.chat.service.WeChatMsgOperationService;
|
||||
import com.abin.mallchat.common.chat.service.cache.GroupMemberCache;
|
||||
import com.abin.mallchat.common.chat.service.cache.HotRoomCache;
|
||||
import com.abin.mallchat.common.chat.service.cache.RoomCache;
|
||||
import com.abin.mallchat.common.chatai.service.IChatAIService;
|
||||
import com.abin.mallchat.common.common.constant.MQConstant;
|
||||
import com.abin.mallchat.common.common.domain.dto.MsgSendMessageDTO;
|
||||
import com.abin.mallchat.common.user.service.WebSocketService;
|
||||
import com.abin.mallchat.common.user.service.adapter.WSAdapter;
|
||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||
import com.abin.mallchat.common.user.service.impl.PushService;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Description: 发送消息更新房间收信箱,并同步给房间成员信箱
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-08-12
|
||||
*/
|
||||
@RocketMQMessageListener(consumerGroup = MQConstant.SEND_MSG_GROUP, topic = MQConstant.SEND_MSG_TOPIC)
|
||||
@Component
|
||||
public class MsgSendConsumer implements RocketMQListener<MsgSendMessageDTO> {
|
||||
@Autowired
|
||||
private WebSocketService webSocketService;
|
||||
@Autowired
|
||||
private ChatService chatService;
|
||||
@Autowired
|
||||
private MessageDao messageDao;
|
||||
@Autowired
|
||||
private IChatAIService openAIService;
|
||||
@Autowired
|
||||
WeChatMsgOperationService weChatMsgOperationService;
|
||||
@Autowired
|
||||
private RoomCache roomCache;
|
||||
@Autowired
|
||||
private RoomDao roomDao;
|
||||
@Autowired
|
||||
private GroupMemberCache groupMemberCache;
|
||||
@Autowired
|
||||
private UserCache userCache;
|
||||
@Autowired
|
||||
private RoomFriendDao roomFriendDao;
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
@Autowired
|
||||
private ContactDao contactDao;
|
||||
@Autowired
|
||||
private HotRoomCache hotRoomCache;
|
||||
@Autowired
|
||||
private PushService pushService;
|
||||
|
||||
@Override
|
||||
public void onMessage(MsgSendMessageDTO dto) {
|
||||
Message message = messageDao.getById(dto.getMsgId());
|
||||
Room room = roomCache.get(message.getRoomId());
|
||||
ChatMessageResp msgResp = chatService.getMsgResp(message, null);
|
||||
//所有房间更新房间最新消息
|
||||
roomDao.refreshActiveTime(room.getId(), message.getId(), message.getCreateTime());
|
||||
roomCache.delete(room.getId());
|
||||
if (room.isHotRoom()) {//热门群聊推送所有在线的人
|
||||
//更新热门群聊时间-redis
|
||||
hotRoomCache.refreshActiveTime(room.getId(), message.getCreateTime());
|
||||
//推送所有人
|
||||
pushService.sendPushMsg(WSAdapter.buildMsgSend(msgResp));
|
||||
} else {
|
||||
List<Long> memberUidList = new ArrayList<>();
|
||||
if (Objects.equals(room.getType(), RoomTypeEnum.GROUP.getType())) {//普通群聊推送所有群成员
|
||||
memberUidList = groupMemberCache.getMemberUidList(room.getId());
|
||||
} else if (Objects.equals(room.getType(), RoomTypeEnum.FRIEND.getType())) {//单聊对象
|
||||
//对单人推送
|
||||
RoomFriend roomFriend = roomFriendDao.getByRoomId(room.getId());
|
||||
memberUidList = Arrays.asList(roomFriend.getUid1(), roomFriend.getUid2());
|
||||
}
|
||||
//更新所有群成员的会话时间
|
||||
contactDao.refreshOrCreateActiveTime(room.getId(), memberUidList, message.getId(), message.getCreateTime());
|
||||
//推送房间成员
|
||||
pushService.sendPushMsg(WSAdapter.buildMsgSend(msgResp), memberUidList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.abin.mallchat.common.chat.controller;
|
||||
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.dto.MsgReadInfoDTO;
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.*;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberListResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberStatisticResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageReadResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp;
|
||||
import com.abin.mallchat.common.chat.service.ChatService;
|
||||
import com.abin.mallchat.common.common.annotation.FrequencyControl;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.utils.RequestHolder;
|
||||
import com.abin.mallchat.common.user.domain.enums.BlackTypeEnum;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群聊相关接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-03-19
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/capi/chat")
|
||||
@Api(tags = "聊天室相关接口")
|
||||
@Slf4j
|
||||
public class ChatController {
|
||||
@Autowired
|
||||
private ChatService chatService;
|
||||
@Autowired
|
||||
private UserCache userCache;
|
||||
|
||||
@GetMapping("/public/member/page")
|
||||
@ApiOperation("群成员列表(废弃)")
|
||||
@Deprecated
|
||||
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid MemberReq request) {
|
||||
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(null, request);
|
||||
filterBlackMember(memberPage);
|
||||
return ApiResult.success(memberPage);
|
||||
}
|
||||
|
||||
@GetMapping("/member/list")
|
||||
@ApiOperation("房间内的所有群成员列表-@专用(废弃)")
|
||||
@Deprecated
|
||||
public ApiResult<List<ChatMemberListResp>> getMemberList(@Valid ChatMessageMemberReq chatMessageMemberReq) {
|
||||
return ApiResult.success(chatService.getMemberList(chatMessageMemberReq));
|
||||
}
|
||||
|
||||
private void filterBlackMember(CursorPageBaseResp<ChatMemberResp> memberPage) {
|
||||
Set<String> blackMembers = getBlackUidSet();
|
||||
memberPage.getList().removeIf(a -> blackMembers.contains(a.getUid().toString()));
|
||||
}
|
||||
|
||||
private Set<String> getBlackUidSet() {
|
||||
return userCache.getBlackMap().getOrDefault(BlackTypeEnum.UID.getType(), new HashSet<>());
|
||||
}
|
||||
|
||||
@GetMapping("public/member/statistic")
|
||||
@ApiOperation("群成员人数统计")
|
||||
@Deprecated
|
||||
public ApiResult<ChatMemberStatisticResp> getMemberStatistic() {
|
||||
return ApiResult.success(chatService.getMemberStatistic());
|
||||
}
|
||||
|
||||
@GetMapping("/public/msg/page")
|
||||
@ApiOperation("消息列表")
|
||||
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
||||
public ApiResult<CursorPageBaseResp<ChatMessageResp>> getMsgPage(@Valid ChatMessagePageReq request) {
|
||||
CursorPageBaseResp<ChatMessageResp> msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid());
|
||||
filterBlackMsg(msgPage);
|
||||
return ApiResult.success(msgPage);
|
||||
}
|
||||
|
||||
private void filterBlackMsg(CursorPageBaseResp<ChatMessageResp> memberPage) {
|
||||
Set<String> blackMembers = getBlackUidSet();
|
||||
memberPage.getList().removeIf(a -> blackMembers.contains(a.getFromUser().getUid().toString()));
|
||||
}
|
||||
|
||||
@PostMapping("/msg")
|
||||
@ApiOperation("发送消息")
|
||||
@FrequencyControl(time = 5, count = 3, target = FrequencyControl.Target.UID)
|
||||
@FrequencyControl(time = 30, count = 5, target = FrequencyControl.Target.UID)
|
||||
@FrequencyControl(time = 60, count = 10, target = FrequencyControl.Target.UID)
|
||||
public ApiResult<ChatMessageResp> sendMsg(@Valid @RequestBody ChatMessageReq request) {//todo 发送给单聊
|
||||
Long msgId = chatService.sendMsg(request, RequestHolder.get().getUid());
|
||||
//返回完整消息格式,方便前端展示
|
||||
return ApiResult.success(chatService.getMsgResp(msgId, RequestHolder.get().getUid()));
|
||||
}
|
||||
|
||||
@PutMapping("/msg/mark")
|
||||
@ApiOperation("消息标记")
|
||||
@FrequencyControl(time = 10, count = 5, target = FrequencyControl.Target.UID)
|
||||
public ApiResult<Void> setMsgMark(@Valid @RequestBody ChatMessageMarkReq request) {
|
||||
chatService.setMsgMark(RequestHolder.get().getUid(), request);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
@PutMapping("/msg/recall")
|
||||
@ApiOperation("撤回消息")
|
||||
@FrequencyControl(time = 20, count = 3, target = FrequencyControl.Target.UID)
|
||||
public ApiResult<Void> recallMsg(@Valid @RequestBody ChatMessageBaseReq request) {
|
||||
chatService.recallMsg(RequestHolder.get().getUid(), request);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
@GetMapping("/msg/read/page")
|
||||
@ApiOperation("消息的已读未读列表")
|
||||
public ApiResult<CursorPageBaseResp<ChatMessageReadResp>> getReadPage(@Valid ChatMessageReadReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
return ApiResult.success(chatService.getReadPage(uid, request));
|
||||
}
|
||||
|
||||
@GetMapping("/msg/read")
|
||||
@ApiOperation("获取消息的已读未读总数")
|
||||
public ApiResult<Collection<MsgReadInfoDTO>> getReadInfo(@Valid ChatMessageReadInfoReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
return ApiResult.success(chatService.getMsgReadInfo(uid, request));
|
||||
}
|
||||
|
||||
@PutMapping("/msg/read")
|
||||
@ApiOperation("消息阅读上报")
|
||||
public ApiResult<Void> msgRead(@Valid @RequestBody ChatMessageMemberReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
chatService.msgRead(uid, request);
|
||||
return ApiResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.abin.mallchat.common.chat.controller;
|
||||
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatRoomResp;
|
||||
import com.abin.mallchat.common.chat.service.ChatService;
|
||||
import com.abin.mallchat.common.chat.service.RoomAppService;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.IdReqVO;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.utils.RequestHolder;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 会话相关接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-03-19
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/capi/chat")
|
||||
@Api(tags = "聊天室相关接口")
|
||||
@Slf4j
|
||||
public class ContactController {
|
||||
@Autowired
|
||||
private ChatService chatService;
|
||||
@Autowired
|
||||
private RoomAppService roomService;
|
||||
|
||||
@GetMapping("/public/contact/page")
|
||||
@ApiOperation("会话列表")
|
||||
public ApiResult<CursorPageBaseResp<ChatRoomResp>> getRoomPage(@Valid CursorPageBaseReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
return ApiResult.success(roomService.getContactPage(request, uid));
|
||||
}
|
||||
|
||||
@GetMapping("/public/contact/detail")
|
||||
@ApiOperation("会话详情")
|
||||
public ApiResult<ChatRoomResp> getRoomPage(@Valid IdReqVO request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
return ApiResult.success(roomService.getContactDetail(uid, request.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.abin.mallchat.common.chat.controller;
|
||||
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.*;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberListResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.MemberResp;
|
||||
import com.abin.mallchat.common.chat.service.RoomAppService;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.IdReqVO;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.IdRespVO;
|
||||
import com.abin.mallchat.common.common.utils.RequestHolder;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 房间相关接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-03-19
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/capi/room")
|
||||
@Api(tags = "聊天室相关接口")
|
||||
@Slf4j
|
||||
public class RoomController {
|
||||
@Autowired
|
||||
private RoomAppService roomService;
|
||||
|
||||
@GetMapping("/public/group")
|
||||
@ApiOperation("群组详情")
|
||||
public ApiResult<MemberResp> groupDetail(@Valid IdReqVO request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
return ApiResult.success(roomService.getGroupDetail(uid, request.getId()));
|
||||
}
|
||||
|
||||
@GetMapping("/public/group/member/page")
|
||||
@ApiOperation("群成员列表")
|
||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid MemberReq request) {
|
||||
return ApiResult.success(roomService.getMemberPage(request));
|
||||
}
|
||||
|
||||
@GetMapping("/group/member/list")
|
||||
@ApiOperation("房间内的所有群成员列表-@专用")
|
||||
public ApiResult<List<ChatMemberListResp>> getMemberList(@Valid ChatMessageMemberReq request) {
|
||||
return ApiResult.success(roomService.getMemberList(request));
|
||||
}
|
||||
|
||||
@DeleteMapping("/group/member")
|
||||
@ApiOperation("移除成员")
|
||||
public ApiResult<Void> delMember(@Valid @RequestBody MemberDelReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
roomService.delMember(uid, request);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
@PostMapping("/group")
|
||||
@ApiOperation("新增群组")
|
||||
public ApiResult<IdRespVO> addGroup(@Valid @RequestBody GroupAddReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
Long roomId = roomService.addGroup(uid, request);
|
||||
return ApiResult.success(IdRespVO.id(roomId));
|
||||
}
|
||||
|
||||
@PostMapping("/group/member")
|
||||
@ApiOperation("邀请好友")
|
||||
public ApiResult<Void> addMember(@Valid @RequestBody MemberAddReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
roomService.addMember(uid, request);
|
||||
return ApiResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.abin.mallchat.common.chat.dao;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.abin.mallchat.common.chat.mapper.ContactMapper;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.utils.CursorUtils;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 会话列表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Service
|
||||
public class ContactDao extends ServiceImpl<ContactMapper, Contact> {
|
||||
|
||||
public Contact get(Long uid, Long roomId) {
|
||||
return lambdaQuery()
|
||||
.eq(Contact::getUid, uid)
|
||||
.eq(Contact::getRoomId, roomId)
|
||||
.one();
|
||||
}
|
||||
|
||||
public Integer getReadCount(Message message) {
|
||||
return lambdaQuery()
|
||||
.eq(Contact::getRoomId, message.getRoomId())
|
||||
.ne(Contact::getUid, message.getFromUid())//不需要查询出自己
|
||||
.ge(Contact::getReadTime, message.getCreateTime())
|
||||
.count();
|
||||
}
|
||||
|
||||
public Integer getTotalCount(Long roomId) {
|
||||
return lambdaQuery()
|
||||
.eq(Contact::getRoomId, roomId)
|
||||
.count();
|
||||
}
|
||||
|
||||
public Integer getUnReadCount(Message message) {
|
||||
return lambdaQuery()
|
||||
.eq(Contact::getRoomId, message.getRoomId())
|
||||
.lt(Contact::getReadTime, message.getCreateTime())
|
||||
.count();
|
||||
}
|
||||
|
||||
public CursorPageBaseResp<Contact> getReadPage(Message message, CursorPageBaseReq cursorPageBaseReq) {
|
||||
return CursorUtils.getCursorPageByMysql(this, cursorPageBaseReq, wrapper -> {
|
||||
wrapper.eq(Contact::getRoomId, message.getRoomId());
|
||||
wrapper.ne(Contact::getUid, message.getFromUid());//不需要查询出自己
|
||||
wrapper.ge(Contact::getReadTime, message.getCreateTime());//已读时间大于等于消息发送时间
|
||||
}, Contact::getReadTime);
|
||||
}
|
||||
|
||||
public CursorPageBaseResp<Contact> getUnReadPage(Message message, CursorPageBaseReq cursorPageBaseReq) {
|
||||
return CursorUtils.getCursorPageByMysql(this, cursorPageBaseReq, wrapper -> {
|
||||
wrapper.eq(Contact::getRoomId, message.getRoomId());
|
||||
wrapper.ne(Contact::getUid, message.getFromUid());//不需要查询出自己
|
||||
wrapper.lt(Contact::getReadTime, message.getCreateTime());//已读时间小于消息发送时间
|
||||
}, Contact::getReadTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户会话列表
|
||||
*/
|
||||
public CursorPageBaseResp<Contact> getContactPage(Long uid, CursorPageBaseReq request) {
|
||||
return CursorUtils.getCursorPageByMysql(this, request, wrapper -> {
|
||||
wrapper.eq(Contact::getUid, uid);
|
||||
}, Contact::getActiveTime);
|
||||
}
|
||||
|
||||
public List<Contact> getByRoomIds(List<Long> roomIds, Long uid) {
|
||||
return lambdaQuery()
|
||||
.eq(Contact::getRoomId, roomIds)
|
||||
.eq(Contact::getUid, uid)
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新所有人的会话时间,没有就直接插入
|
||||
*/
|
||||
public void refreshOrCreateActiveTime(Long roomId, List<Long> memberUidList, Long msgId, Date activeTime) {
|
||||
baseMapper.refreshOrCreateActiveTime(roomId, memberUidList, msgId, activeTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.abin.mallchat.common.chat.dao;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.GroupMember;
|
||||
import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum;
|
||||
import com.abin.mallchat.common.chat.mapper.GroupMemberMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群成员表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Service
|
||||
public class GroupMemberDao extends ServiceImpl<GroupMemberMapper, GroupMember> {
|
||||
|
||||
public List<Long> getMemberUidList(Long groupId) {
|
||||
List<GroupMember> list = lambdaQuery()
|
||||
.eq(GroupMember::getGroupId, groupId)
|
||||
.select(GroupMember::getUid)
|
||||
.list();
|
||||
return list.stream().map(GroupMember::getUid).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<Long> getMemberBatch(Long groupId, List<Long> uidList) {
|
||||
List<GroupMember> list = lambdaQuery()
|
||||
.eq(GroupMember::getGroupId, groupId)
|
||||
.in(GroupMember::getUid, uidList)
|
||||
.select(GroupMember::getUid)
|
||||
.list();
|
||||
return list.stream().map(GroupMember::getUid).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public GroupMember getMember(Long groupId, Long uid) {
|
||||
return lambdaQuery()
|
||||
.eq(GroupMember::getGroupId, groupId)
|
||||
.eq(GroupMember::getUid, uid)
|
||||
.one();
|
||||
}
|
||||
|
||||
public List<GroupMember> getSelfGroup(Long uid) {
|
||||
return lambdaQuery()
|
||||
.eq(GroupMember::getUid, uid)
|
||||
.eq(GroupMember::getRole, GroupRoleEnum.LEADER.getType())
|
||||
.list();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.abin.mallchat.common.chat.dao;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum;
|
||||
import com.abin.mallchat.common.chat.mapper.MessageMapper;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.utils.CursorUtils;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 消息表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-03-25
|
||||
*/
|
||||
@Service
|
||||
public class MessageDao extends ServiceImpl<MessageMapper, Message> {
|
||||
|
||||
public CursorPageBaseResp<Message> getCursorPage(Long roomId, CursorPageBaseReq request, Long lastMsgId) {
|
||||
return CursorUtils.getCursorPageByMysql(this, request, wrapper -> {
|
||||
wrapper.eq(Message::getRoomId, roomId);
|
||||
wrapper.eq(Message::getStatus, MessageStatusEnum.NORMAL.getStatus());
|
||||
wrapper.le(Objects.nonNull(lastMsgId), Message::getId, lastMsgId);
|
||||
}, Message::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 乐观更新消息类型
|
||||
*/
|
||||
public boolean riseOptimistic(Long id, Integer oldType, Integer newType) {
|
||||
return lambdaUpdate()
|
||||
.eq(Message::getId, id)
|
||||
.eq(Message::getType, oldType)
|
||||
.set(Message::getType, newType)
|
||||
.update();
|
||||
}
|
||||
|
||||
public Integer getGapCount(Long roomId, Long fromId, Long toId) {
|
||||
return lambdaQuery()
|
||||
.eq(Message::getRoomId, roomId)
|
||||
.gt(Message::getId, fromId)
|
||||
.le(Message::getId, toId)
|
||||
.count();
|
||||
}
|
||||
|
||||
public void invalidByUid(Long uid) {
|
||||
lambdaUpdate()
|
||||
.eq(Message::getFromUid, uid)
|
||||
.set(Message::getStatus, MessageStatusEnum.DELETE.getStatus())
|
||||
.update();
|
||||
}
|
||||
|
||||
public Integer getUnReadCount(Long roomId, Date readTime) {
|
||||
return lambdaQuery()
|
||||
.eq(Message::getRoomId, roomId)
|
||||
.gt(Objects.nonNull(readTime), Message::getCreateTime, readTime)
|
||||
.count();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.abin.mallchat.common.chat.dao;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
|
||||
import com.abin.mallchat.common.chat.mapper.MessageMarkMapper;
|
||||
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 消息标记表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
@Service
|
||||
public class MessageMarkDao extends ServiceImpl<MessageMarkMapper, MessageMark> {
|
||||
|
||||
public MessageMark get(Long uid, Long msgId, Integer markType) {
|
||||
return lambdaQuery().eq(MessageMark::getUid, uid)
|
||||
.eq(MessageMark::getMsgId, msgId)
|
||||
.eq(MessageMark::getType, markType)
|
||||
.one();
|
||||
}
|
||||
|
||||
public Integer getMarkCount(Long msgId, Integer markType) {
|
||||
return lambdaQuery().eq(MessageMark::getMsgId, msgId)
|
||||
.eq(MessageMark::getType, markType)
|
||||
.eq(MessageMark::getStatus, YesOrNoEnum.NO.getStatus())
|
||||
.count();
|
||||
}
|
||||
|
||||
public List<MessageMark> getValidMarkByMsgIdBatch(List<Long> msgIds) {
|
||||
return lambdaQuery()
|
||||
.in(MessageMark::getMsgId, msgIds)
|
||||
.eq(MessageMark::getStatus, YesOrNoEnum.NO.getStatus())
|
||||
.list();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.abin.mallchat.common.chat.dao;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.abin.mallchat.common.chat.mapper.RoomMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 房间表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Service
|
||||
public class RoomDao extends ServiceImpl<RoomMapper, Room> implements IService<Room> {
|
||||
|
||||
public void refreshActiveTime(Long roomId, Long msgId, Date msgTime) {
|
||||
lambdaUpdate()
|
||||
.eq(Room::getId, roomId)
|
||||
.set(Room::getLastMsgId, msgId)
|
||||
.set(Room::getActiveTime, msgTime)
|
||||
.update();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.abin.mallchat.common.chat.dao;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
import com.abin.mallchat.common.chat.mapper.RoomFriendMapper;
|
||||
import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 单聊房间表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-22
|
||||
*/
|
||||
@Service
|
||||
public class RoomFriendDao extends ServiceImpl<RoomFriendMapper, RoomFriend> {
|
||||
|
||||
public RoomFriend getByKey(String key) {
|
||||
return lambdaQuery().eq(RoomFriend::getRoomKey, key).one();
|
||||
}
|
||||
|
||||
public void restoreRoom(Long id) {
|
||||
lambdaUpdate()
|
||||
.eq(RoomFriend::getId, id)
|
||||
.set(RoomFriend::getStatus, NormalOrNoEnum.NORMAL.getStatus())
|
||||
.update();
|
||||
}
|
||||
|
||||
public void disableRoom(String key) {
|
||||
lambdaUpdate()
|
||||
.eq(RoomFriend::getRoomKey, key)
|
||||
.set(RoomFriend::getStatus, NormalOrNoEnum.NOT_NORMAL.getStatus())
|
||||
.update();
|
||||
}
|
||||
|
||||
public List<RoomFriend> listByRoomIds(List<Long> roomIds) {
|
||||
return lambdaQuery()
|
||||
.in(RoomFriend::getRoomId, roomIds)
|
||||
.list();
|
||||
}
|
||||
|
||||
public RoomFriend getByRoomId(Long roomID) {
|
||||
return lambdaQuery()
|
||||
.eq(RoomFriend::getRoomId, roomID)
|
||||
.one();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.abin.mallchat.common.chat.dao;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||
import com.abin.mallchat.common.chat.mapper.RoomGroupMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群聊房间表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-22
|
||||
*/
|
||||
@Service
|
||||
public class RoomGroupDao extends ServiceImpl<RoomGroupMapper, RoomGroup> {
|
||||
|
||||
public List<RoomGroup> listByRoomIds(List<Long> roomIds) {
|
||||
return lambdaQuery()
|
||||
.in(RoomGroup::getRoomId, roomIds)
|
||||
.list();
|
||||
}
|
||||
|
||||
public RoomGroup getByRoomId(Long roomId) {
|
||||
return lambdaQuery()
|
||||
.eq(RoomGroup::getRoomId, roomId)
|
||||
.one();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.abin.mallchat.common.chat.dao;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.WxMsg;
|
||||
import com.abin.mallchat.common.chat.mapper.WxMsgMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 微信消息表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-05-16
|
||||
*/
|
||||
@Service
|
||||
public class WxMsgDao extends ServiceImpl<WxMsgMapper, WxMsg> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.abin.mallchat.common.chat.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description: 消息标记请求
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-29
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageMarkDTO {
|
||||
|
||||
@ApiModelProperty("操作者")
|
||||
private Long uid;
|
||||
|
||||
@ApiModelProperty("消息id")
|
||||
private Long msgId;
|
||||
|
||||
/**
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum
|
||||
*/
|
||||
@ApiModelProperty("标记类型 1点赞 2举报")
|
||||
private Integer markType;
|
||||
|
||||
/**
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.MessageMarkActTypeEnum
|
||||
*/
|
||||
@ApiModelProperty("动作类型 1确认 2取消")
|
||||
private Integer actType;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.abin.mallchat.common.chat.domain.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description:消息撤回的推送类
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMsgRecallDTO {
|
||||
private Long msgId;
|
||||
private Long roomId;
|
||||
//撤回的用户
|
||||
private Long recallUid;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.abin.mallchat.common.chat.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-17
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MsgReadInfoDTO {
|
||||
@ApiModelProperty("消息id")
|
||||
private Long msgId;
|
||||
|
||||
@ApiModelProperty("已读数")
|
||||
private Integer readCount;
|
||||
|
||||
@ApiModelProperty("未读数")
|
||||
private Integer unReadCount;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.abin.mallchat.common.chat.domain.dto;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Description: 房间详情
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
@Data
|
||||
public class RoomBaseInfo {
|
||||
@ApiModelProperty("房间id")
|
||||
private Long roomId;
|
||||
@ApiModelProperty("会话名称")
|
||||
private String name;
|
||||
@ApiModelProperty("会话头像")
|
||||
private String avatar;
|
||||
/**
|
||||
* 房间类型 1群聊 2单聊
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 是否全员展示 0否 1是
|
||||
*
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.HotFlagEnum
|
||||
*/
|
||||
private Integer hotFlag;
|
||||
|
||||
/**
|
||||
* 群最后消息的更新时间
|
||||
*/
|
||||
@TableField("active_time")
|
||||
private Date activeTime;
|
||||
|
||||
/**
|
||||
* 最后一条消息id
|
||||
*/
|
||||
@TableField("last_msg_id")
|
||||
private Long lastMsgId;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 会话列表
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("contact")
|
||||
public class Contact implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* uid
|
||||
*/
|
||||
@TableField("uid")
|
||||
private Long uid;
|
||||
|
||||
/**
|
||||
* 房间id
|
||||
*/
|
||||
@TableField("room_id")
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 阅读到的时间
|
||||
*/
|
||||
@TableField("read_time")
|
||||
private Date readTime;
|
||||
|
||||
/**
|
||||
* 会话内消息最后更新的时间(只有普通会话需要维护,全员会话不需要维护)
|
||||
*/
|
||||
@TableField("active_time")
|
||||
private Date activeTime;
|
||||
|
||||
/**
|
||||
* 最后一条消息id
|
||||
*/
|
||||
@TableField("last_msg_id")
|
||||
private Long lastMsgId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群成员表
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("group_member")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GroupMember implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 群组id
|
||||
*/
|
||||
@TableField("group_id")
|
||||
private Long groupId;
|
||||
|
||||
/**
|
||||
* 成员uid
|
||||
*/
|
||||
@TableField("uid")
|
||||
private Long uid;
|
||||
|
||||
/**
|
||||
* 成员角色1群主(可撤回,可移除,可解散) 2管理员(可撤回,可移除) 3普通成员
|
||||
*
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum
|
||||
*/
|
||||
@TableField("role")
|
||||
private Integer role;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.msg.MessageExtra;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 消息表
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-03-25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName(value = "message", autoResultMap = true)
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Message implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 会话表id
|
||||
*/
|
||||
@TableField("room_id")
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 消息发送者uid
|
||||
*/
|
||||
@TableField("from_uid")
|
||||
private Long fromUid;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@TableField("content")
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 回复的消息内容
|
||||
*/
|
||||
@TableField("reply_msg_id")
|
||||
private Long replyMsgId;
|
||||
|
||||
/**
|
||||
* 消息状态 0正常 1删除
|
||||
*
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum
|
||||
*/
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 与回复消息的间隔条数
|
||||
*/
|
||||
@TableField("gap_count")
|
||||
private Integer gapCount;
|
||||
|
||||
/**
|
||||
* 消息类型 1正常文本 2.撤回消息
|
||||
*
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum
|
||||
*/
|
||||
@TableField("type")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 消息扩展字段
|
||||
*/
|
||||
@TableField(value = "extra", typeHandler = JacksonTypeHandler.class)
|
||||
private MessageExtra extra;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 消息标记表
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("message_mark")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MessageMark implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 消息表id
|
||||
*/
|
||||
@TableField("msg_id")
|
||||
private Long msgId;
|
||||
|
||||
/**
|
||||
* 标记人uid
|
||||
*/
|
||||
@TableField("uid")
|
||||
private Long uid;
|
||||
|
||||
/**
|
||||
* 标记类型 1点赞 2举报
|
||||
*
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum
|
||||
*/
|
||||
@TableField("type")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 消息状态 0正常 1取消
|
||||
*/
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.enums.HotFlagEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 房间表
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("room")
|
||||
public class Room implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 房间类型 1群聊 2单聊
|
||||
*
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum
|
||||
*/
|
||||
@TableField("type")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 是否全员展示 0否 1是
|
||||
*
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.HotFlagEnum
|
||||
*/
|
||||
@TableField("hot_flag")
|
||||
private Integer hotFlag;
|
||||
|
||||
/**
|
||||
* 群最后消息的更新时间(热点群不需要写扩散,更新这里就行)
|
||||
*/
|
||||
@TableField("active_time")
|
||||
private Date activeTime;
|
||||
|
||||
/**
|
||||
* 最后一条消息id
|
||||
*/
|
||||
@TableField("last_msg_id")
|
||||
private Long lastMsgId;
|
||||
|
||||
/**
|
||||
* 额外信息(根据不同类型房间有不同存储的东西)
|
||||
*/
|
||||
@TableField("ext_json")
|
||||
private String extJson;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isHotRoom() {
|
||||
return HotFlagEnum.of(this.hotFlag) == HotFlagEnum.YES;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isRoomFriend() {
|
||||
return RoomTypeEnum.of(this.type) == RoomTypeEnum.FRIEND;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isRoomGroup() {
|
||||
return RoomTypeEnum.of(this.hotFlag) == RoomTypeEnum.GROUP;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 单聊房间表
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-22
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("room_friend")
|
||||
public class RoomFriend implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 房间id
|
||||
*/
|
||||
@TableField("room_id")
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* uid1(更小的uid)
|
||||
*/
|
||||
@TableField("uid1")
|
||||
private Long uid1;
|
||||
|
||||
/**
|
||||
* uid2(更大的uid)
|
||||
*/
|
||||
@TableField("uid2")
|
||||
private Long uid2;
|
||||
|
||||
/**
|
||||
* 房间key由两个uid拼接,先做排序uid1_uid2
|
||||
*/
|
||||
@TableField("room_key")
|
||||
private String roomKey;
|
||||
|
||||
/**
|
||||
* 房间状态 0正常 1禁用(删好友了禁用)
|
||||
*/
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群聊房间表
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-22
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("room_group")
|
||||
public class RoomGroup implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 房间id
|
||||
*/
|
||||
@TableField("room_id")
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 群名称
|
||||
*/
|
||||
@TableField("name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 群头像
|
||||
*/
|
||||
@TableField("avatar")
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 额外信息(根据不同类型房间有不同存储的东西)
|
||||
*/
|
||||
@TableField("ext_json")
|
||||
private String extJson;
|
||||
|
||||
/**
|
||||
* 逻辑删除(0-正常,1-删除)
|
||||
*/
|
||||
@TableField("delete_status")
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
private Integer deleteStatus;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 微信消息表
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-05-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("wx_msg")
|
||||
public class WxMsg implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 微信openid用户标识
|
||||
*/
|
||||
@TableField("open_id")
|
||||
private String openId;
|
||||
|
||||
/**
|
||||
* 用户消息
|
||||
*/
|
||||
@TableField("msg")
|
||||
private String msg;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity.msg;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Description: 表情图片消息入参
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class EmojisMsgDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("下载地址")
|
||||
@NotBlank
|
||||
private String url;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity.msg;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Description: 语音消息入参
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class FileMsgDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ApiModelProperty("大小(字节)")
|
||||
@NotNull
|
||||
private Long size;
|
||||
|
||||
@ApiModelProperty("下载地址")
|
||||
@NotBlank
|
||||
private String url;
|
||||
|
||||
@ApiModelProperty("文件名(带后缀)")
|
||||
@NotBlank
|
||||
private String fileName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity.msg;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Description: 图片消息入参
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ImgMsgDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ApiModelProperty("大小(字节)")
|
||||
@NotNull
|
||||
private Long size;
|
||||
|
||||
@ApiModelProperty("宽度(像素)")
|
||||
@NotNull
|
||||
private Integer width;
|
||||
|
||||
@ApiModelProperty("高度(像素)")
|
||||
@NotNull
|
||||
private Integer height;
|
||||
|
||||
@ApiModelProperty("下载地址")
|
||||
@NotBlank
|
||||
private String url;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity.msg;
|
||||
|
||||
import com.abin.mallchat.common.common.utils.discover.domain.UrlInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Description: 消息扩展属性
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-05-28
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MessageExtra implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
//url跳转链接
|
||||
private Map<String, UrlInfo> urlContentMap;
|
||||
//消息撤回详情
|
||||
private MsgRecall recall;
|
||||
//艾特的uid
|
||||
private List<Long> atUidList;
|
||||
//文件消息
|
||||
private FileMsgDTO fileMsg;
|
||||
//图片消息
|
||||
private ImgMsgDTO imgMsgDTO;
|
||||
//语音消息
|
||||
private SoundMsgDTO soundMsgDTO;
|
||||
//文件消息
|
||||
private VideoMsgDTO videoMsgDTO;
|
||||
|
||||
/**
|
||||
* 表情图片信息
|
||||
*/
|
||||
private EmojisMsgDTO emojisMsgDTO;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Description: 消息撤回
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MsgRecall implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
//撤回消息的uid
|
||||
private Long recallUid;
|
||||
//撤回的时间点
|
||||
private Date recallTime;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity.msg;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Description: 语音消息入参
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SoundMsgDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ApiModelProperty("大小(字节)")
|
||||
@NotNull
|
||||
private Long size;
|
||||
|
||||
@ApiModelProperty("时长(秒)")
|
||||
@NotNull
|
||||
private Integer second;
|
||||
|
||||
@ApiModelProperty("下载地址")
|
||||
@NotBlank
|
||||
private String url;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.abin.mallchat.common.chat.domain.entity.msg;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Description: 视频消息入参
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class VideoMsgDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ApiModelProperty("大小(字节)")
|
||||
@NotNull
|
||||
private Long size;
|
||||
|
||||
@ApiModelProperty("下载地址")
|
||||
@NotBlank
|
||||
private String url;
|
||||
|
||||
@ApiModelProperty("缩略图宽度(像素)")
|
||||
@NotNull
|
||||
private Integer thumbWidth;
|
||||
|
||||
@ApiModelProperty("缩略图高度(像素)")
|
||||
@NotNull
|
||||
private Integer thumbHeight;
|
||||
|
||||
@ApiModelProperty("缩略图大小(字节)")
|
||||
@NotNull
|
||||
private Long thumbSize;
|
||||
|
||||
@ApiModelProperty("缩略图下载地址")
|
||||
@NotBlank
|
||||
private String thumbUrl;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.abin.mallchat.common.chat.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 热点枚举
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum GroupRoleAPPEnum {
|
||||
LEADER(1, "群主"),
|
||||
MANAGER(2, "管理"),
|
||||
MEMBER(3, "普通成员"),
|
||||
REMOVE(4, "被移除的成员"),
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
|
||||
private static Map<Integer, GroupRoleAPPEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(GroupRoleAPPEnum.values()).collect(Collectors.toMap(GroupRoleAPPEnum::getType, Function.identity()));
|
||||
}
|
||||
|
||||
public static GroupRoleAPPEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.abin.mallchat.common.chat.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 成员角色枚举
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum GroupRoleEnum {
|
||||
LEADER(1, "群主"),
|
||||
MANAGER(2, "管理"),
|
||||
MEMBER(3, "普通成员"),
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
|
||||
private static Map<Integer, GroupRoleEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(GroupRoleEnum.values()).collect(Collectors.toMap(GroupRoleEnum::getType, Function.identity()));
|
||||
}
|
||||
|
||||
public static GroupRoleEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.abin.mallchat.common.chat.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 热点枚举
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum HotFlagEnum {
|
||||
NOT(0, "非热点"),
|
||||
YES(1, "热点"),
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
|
||||
private static Map<Integer, HotFlagEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(HotFlagEnum.values()).collect(Collectors.toMap(HotFlagEnum::getType, Function.identity()));
|
||||
}
|
||||
|
||||
public static HotFlagEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.abin.mallchat.common.chat.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 消息标记动作类型
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum MessageMarkActTypeEnum {
|
||||
MARK(1, "确认标记"),
|
||||
UN_MARK(2, "取消标记"),
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
|
||||
private static Map<Integer, MessageMarkActTypeEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(MessageMarkActTypeEnum.values()).collect(Collectors.toMap(MessageMarkActTypeEnum::getType, Function.identity()));
|
||||
}
|
||||
|
||||
public static MessageMarkActTypeEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.abin.mallchat.common.chat.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 消息标记类型
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum MessageMarkTypeEnum {
|
||||
LIKE(1, "点赞", 10),
|
||||
DISLIKE(2, "点踩", 5),
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
private final Integer riseNum;//需要多少个标记升级
|
||||
|
||||
private static Map<Integer, MessageMarkTypeEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(MessageMarkTypeEnum.values()).collect(Collectors.toMap(MessageMarkTypeEnum::getType, Function.identity()));
|
||||
}
|
||||
|
||||
public static MessageMarkTypeEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.abin.mallchat.common.chat.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 消息状态
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum MessageStatusEnum {
|
||||
NORMAL(0, "正常"),
|
||||
DELETE(1, "删除"),
|
||||
;
|
||||
|
||||
private final Integer status;
|
||||
private final String desc;
|
||||
|
||||
private static Map<Integer, MessageStatusEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(MessageStatusEnum.values()).collect(Collectors.toMap(MessageStatusEnum::getStatus, Function.identity()));
|
||||
}
|
||||
|
||||
public static MessageStatusEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.abin.mallchat.common.chat.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 消息状态
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum MessageTypeEnum {
|
||||
TEXT(1, "正常消息"),
|
||||
RECALL(2, "撤回消息"),
|
||||
IMG(3, "图片"),
|
||||
FILE(4, "文件"),
|
||||
SOUND(5, "语音"),
|
||||
VIDEO(6, "视频"),
|
||||
EMOJI(7, "表情"),
|
||||
SYSTEM(8, "系统消息"),
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
|
||||
private static Map<Integer, MessageTypeEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(MessageTypeEnum.values()).collect(Collectors.toMap(MessageTypeEnum::getType, Function.identity()));
|
||||
}
|
||||
|
||||
public static MessageTypeEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.abin.mallchat.common.chat.domain.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 消息状态
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-19
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum RoomTypeEnum {
|
||||
GROUP(1, "群聊"),
|
||||
FRIEND(2, "单聊"),
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
|
||||
private static Map<Integer, RoomTypeEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(RoomTypeEnum.values()).collect(Collectors.toMap(RoomTypeEnum::getType, Function.identity()));
|
||||
}
|
||||
|
||||
public static RoomTypeEnum of(Integer type) {
|
||||
return cache.get(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* Description: 消息基础请求体
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-23
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageBaseReq {
|
||||
@NotNull
|
||||
@ApiModelProperty("消息id")
|
||||
private Long msgId;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("会话id")
|
||||
private Long roomId;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Description: 消息标记请求
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-29
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageMarkReq {
|
||||
@NotNull
|
||||
@ApiModelProperty("消息id")
|
||||
private Long msgId;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("标记类型 1点赞 2举报")
|
||||
private Integer markType;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("动作类型 1确认 2取消")
|
||||
private Integer actType;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Description: 消息列表请求
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-29
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageMemberReq {
|
||||
@NotNull
|
||||
@ApiModelProperty("会话id")
|
||||
private Long roomId;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Description: 消息列表请求
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-29
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessagePageReq extends CursorPageBaseReq {
|
||||
@NotNull
|
||||
@ApiModelProperty("会话id")
|
||||
private Long roomId;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-17
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageReadInfoReq {
|
||||
@ApiModelProperty("消息id集合(只查本人)")
|
||||
@Size(max = 20)
|
||||
private List<Long> msgIds;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-17
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageReadReq extends CursorPageBaseReq {
|
||||
@ApiModelProperty("消息id")
|
||||
@NotNull
|
||||
private Long msgId;
|
||||
|
||||
@ApiModelProperty("查询类型 1已读 2未读")
|
||||
@NotNull
|
||||
private Long searchType;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* 聊天信息点播
|
||||
* Description: 消息发送请求体
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-23
|
||||
*
|
||||
* @author zhaoyuhang
|
||||
* @date 2023/06/30
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageReq {
|
||||
@NotNull
|
||||
@ApiModelProperty("房间id")
|
||||
private Long roomId;
|
||||
|
||||
@ApiModelProperty("消息类型")
|
||||
@NotNull
|
||||
private Integer msgType;
|
||||
|
||||
@ApiModelProperty("消息内容,类型不同传值不同,见https://www.yuque.com/snab/mallcaht/rkb2uz5k1qqdmcmd")
|
||||
@NotNull
|
||||
private Object body;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Description: 新建群组
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-29
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GroupAddReq {
|
||||
@NotNull
|
||||
@Size(min = 1, max = 50)
|
||||
@ApiModelProperty("邀请的uid")
|
||||
private List<Long> uidList;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Description: 移除群成员
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-29
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MemberAddReq {
|
||||
@NotNull
|
||||
@ApiModelProperty("房间id")
|
||||
private Long roomId;
|
||||
|
||||
@NotNull
|
||||
@Size(min = 1, max = 50)
|
||||
@ApiModelProperty("邀请的uid")
|
||||
private List<Long> uidList;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Description: 移除群成员
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-29
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MemberDelReq {
|
||||
@NotNull
|
||||
@ApiModelProperty("会话id")
|
||||
private Long roomId;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("被移除的uid(主动退群填自己)")
|
||||
private Long uid;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request;
|
||||
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-17
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MemberReq extends CursorPageBaseReq {
|
||||
@ApiModelProperty("房间号")
|
||||
private Long roomId = 1L;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.request.msg;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Description: 文本消息入参
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TextMsgReq {
|
||||
|
||||
@NotBlank(message = "内容不能为空")
|
||||
@Size(max = 1024, message = "消息内容过长,服务器扛不住啊,兄dei")
|
||||
@ApiModelProperty("消息内容")
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty("回复的消息id,如果没有别传就好")
|
||||
private Long replyMsgId;
|
||||
|
||||
@ApiModelProperty("艾特的uid")
|
||||
@Size(max = 10, message = "一次别艾特这么多人")
|
||||
private List<Long> atUidList;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.response;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description: 群成员列表的成员信息
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-23
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMemberListResp {
|
||||
@ApiModelProperty("uid")
|
||||
private Long uid;
|
||||
@ApiModelProperty("用户名称")
|
||||
private String name;
|
||||
@ApiModelProperty("头像")
|
||||
private String avatar;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.response;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description: 群成员统计信息
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-23
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMemberStatisticResp {
|
||||
|
||||
@ApiModelProperty("在线人数")
|
||||
private Long onlineNum;//在线人数
|
||||
@ApiModelProperty("总人数")
|
||||
@Deprecated
|
||||
private Long totalNum;//总人数
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.response;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-17
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageReadInfoResp {
|
||||
@ApiModelProperty("消息id")
|
||||
private Long msgId;
|
||||
|
||||
@ApiModelProperty("已读数")
|
||||
private Integer readCount;
|
||||
|
||||
@ApiModelProperty("未读数")
|
||||
private Integer unReadCount;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.response;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-23
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageReadResp {
|
||||
@ApiModelProperty("已读或者未读的用户uid")
|
||||
private Long uid;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.response;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Description: 消息
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-23
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageResp {
|
||||
|
||||
@ApiModelProperty("发送者信息")
|
||||
private UserInfo fromUser;
|
||||
@ApiModelProperty("消息详情")
|
||||
private Message message;
|
||||
|
||||
@Data
|
||||
public static class UserInfo {
|
||||
@ApiModelProperty("用户id")
|
||||
private Long uid;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Message {
|
||||
@ApiModelProperty("消息id")
|
||||
private Long id;
|
||||
@ApiModelProperty("房间id")
|
||||
private Long roomId;
|
||||
@ApiModelProperty("消息发送时间")
|
||||
private Date sendTime;
|
||||
@ApiModelProperty("消息类型 1正常文本 2.撤回消息")
|
||||
private Integer type;
|
||||
@ApiModelProperty("消息内容不同的消息类型,内容体不同,见https://www.yuque.com/snab/mallcaht/rkb2uz5k1qqdmcmd")
|
||||
private Object body;
|
||||
@ApiModelProperty("消息标记")
|
||||
private MessageMark messageMark;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class MessageMark {
|
||||
@ApiModelProperty("点赞数")
|
||||
private Integer likeCount;
|
||||
@ApiModelProperty("该用户是否已经点赞 0否 1是")
|
||||
private Integer userLike;
|
||||
@ApiModelProperty("举报数")
|
||||
private Integer dislikeCount;
|
||||
@ApiModelProperty("该用户是否已经举报 0否 1是")
|
||||
private Integer userDislike;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.response;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Description: 群成员列表的成员信息
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-23
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatRoomResp {
|
||||
@ApiModelProperty("房间id")
|
||||
private Long roomId;
|
||||
@ApiModelProperty("房间类型 1群聊 2单聊")
|
||||
private Integer type;
|
||||
@ApiModelProperty("是否全员展示的会话 0否 1是")
|
||||
private Integer hot_Flag;
|
||||
@ApiModelProperty("最新消息")
|
||||
private String text;
|
||||
@ApiModelProperty("会话名称")
|
||||
private String name;
|
||||
@ApiModelProperty("会话头像")
|
||||
private String avatar;
|
||||
@ApiModelProperty("房间最后活跃时间(用来排序)")
|
||||
private Date activeTime;
|
||||
@ApiModelProperty("未读数")
|
||||
private Integer unreadCount;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.response;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-17
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MemberResp {
|
||||
@ApiModelProperty("房间id")
|
||||
private Long roomId;
|
||||
@ApiModelProperty("群名称")
|
||||
private String groupName;
|
||||
@ApiModelProperty("群头像")
|
||||
private String avatar;
|
||||
@ApiModelProperty("在线人数")
|
||||
private Long onlineNum;//在线人数
|
||||
/**
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.GroupRoleAPPEnum
|
||||
*/
|
||||
@ApiModelProperty("成员角色 1群主 2管理员 3普通成员 4踢出群聊")
|
||||
private Integer role;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.abin.mallchat.common.chat.domain.vo.response.msg;
|
||||
|
||||
import com.abin.mallchat.common.common.utils.discover.domain.UrlInfo;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Description: 文本消息返回体
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-04
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TextMsgResp {
|
||||
@ApiModelProperty("消息内容")
|
||||
private String content;
|
||||
@ApiModelProperty("消息链接映射")
|
||||
private Map<String, UrlInfo> urlContentMap;
|
||||
@ApiModelProperty("艾特的uid")
|
||||
private List<Long> atUidList;
|
||||
@ApiModelProperty("父消息,如果没有父消息,返回的是null")
|
||||
private TextMsgResp.ReplyMsg reply;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class ReplyMsg {
|
||||
@ApiModelProperty("消息id")
|
||||
private Long id;
|
||||
@ApiModelProperty("用户uid")
|
||||
private Long uid;
|
||||
@ApiModelProperty("用户名称")
|
||||
private String username;
|
||||
@ApiModelProperty("消息类型 1正常文本 2.撤回消息")
|
||||
private Integer type;
|
||||
@ApiModelProperty("消息内容不同的消息类型,见父消息内容体")
|
||||
private Object body;
|
||||
@ApiModelProperty("是否可消息跳转 0否 1是")
|
||||
private Integer canCallback;
|
||||
@ApiModelProperty("跳转间隔的消息条数")
|
||||
private Integer gapCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.abin.mallchat.common.chat.mapper;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 会话列表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
public interface ContactMapper extends BaseMapper<Contact> {
|
||||
|
||||
void refreshOrCreateActiveTime(@Param("roomId") Long roomId, @Param("memberUidList") List<Long> memberUidList, @Param("msgId") Long msgId, @Param("activeTime") Date activeTime);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.mapper;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.GroupMember;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群成员表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
public interface GroupMemberMapper extends BaseMapper<GroupMember> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.mapper;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 消息表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-03-25
|
||||
*/
|
||||
public interface MessageMapper extends BaseMapper<Message> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.mapper;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 消息标记表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
public interface MessageMarkMapper extends BaseMapper<MessageMark> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.mapper;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 单聊房间表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-22
|
||||
*/
|
||||
public interface RoomFriendMapper extends BaseMapper<RoomFriend> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.mapper;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群聊房间表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-22
|
||||
*/
|
||||
public interface RoomGroupMapper extends BaseMapper<RoomGroup> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.mapper;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 房间表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
public interface RoomMapper extends BaseMapper<Room> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.mapper;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.WxMsg;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 微信消息表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-05-16
|
||||
*/
|
||||
public interface WxMsgMapper extends BaseMapper<WxMsg> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?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.abin.mallchat.common.chat.mapper.RoomFriendMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?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.abin.mallchat.common.chat.mapper.RoomGroupMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?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.abin.mallchat.common.chat.mapper.RoomMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.dto.MsgReadInfoDTO;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.*;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberListResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberStatisticResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageReadResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Description: 消息处理类
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-26
|
||||
*/
|
||||
public interface ChatService {
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param request
|
||||
*/
|
||||
Long sendMsg(ChatMessageReq request, Long uid);
|
||||
|
||||
/**
|
||||
* 根据消息获取消息前端展示的物料
|
||||
*
|
||||
* @param message
|
||||
* @param receiveUid 接受消息的uid,可null
|
||||
* @return
|
||||
*/
|
||||
ChatMessageResp getMsgResp(Message message, Long receiveUid);
|
||||
|
||||
/**
|
||||
* 根据消息获取消息前端展示的物料
|
||||
*
|
||||
* @param msgId
|
||||
* @param receiveUid 接受消息的uid,可null
|
||||
* @return
|
||||
*/
|
||||
ChatMessageResp getMsgResp(Long msgId, Long receiveUid);
|
||||
|
||||
/**
|
||||
* 获取群成员列表
|
||||
*
|
||||
* @param memberUidList
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
CursorPageBaseResp<ChatMemberResp> getMemberPage(List<Long> memberUidList, CursorPageBaseReq request);
|
||||
|
||||
/**
|
||||
* 获取消息列表
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
CursorPageBaseResp<ChatMessageResp> getMsgPage(ChatMessagePageReq request, @Nullable Long receiveUid);
|
||||
|
||||
ChatMemberStatisticResp getMemberStatistic();
|
||||
|
||||
void setMsgMark(Long uid, ChatMessageMarkReq request);
|
||||
|
||||
void recallMsg(Long uid, ChatMessageBaseReq request);
|
||||
|
||||
List<ChatMemberListResp> getMemberList(ChatMessageMemberReq chatMessageMemberReq);
|
||||
|
||||
Collection<MsgReadInfoDTO> getMsgReadInfo(Long uid, ChatMessageReadInfoReq request);
|
||||
|
||||
CursorPageBaseResp<ChatMessageReadResp> getReadPage(Long uid, ChatMessageReadReq request);
|
||||
|
||||
void msgRead(Long uid, ChatMessageMemberReq request);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.dto.MsgReadInfoDTO;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 会话列表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
public interface ContactService {
|
||||
/**
|
||||
* 创建会话
|
||||
*/
|
||||
Contact createContact(Long uid, Long roomId);
|
||||
|
||||
Integer getMsgReadCount(Message message);
|
||||
|
||||
Integer getMsgUnReadCount(Message message);
|
||||
|
||||
Map<Long, MsgReadInfoDTO> getMsgReadInfo(List<Message> messages);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.GroupMember;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群成员表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
public interface IGroupMemberService extends IService<GroupMember> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 消息标记表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-04-08
|
||||
*/
|
||||
public interface IMessageMarkService extends IService<MessageMark> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 消息表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-03-25
|
||||
*/
|
||||
public interface IMessageService extends IService<Message> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.*;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberListResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatRoomResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.MemberResp;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
public interface RoomAppService {
|
||||
/**
|
||||
* 获取会话列表--支持未登录态
|
||||
*/
|
||||
CursorPageBaseResp<ChatRoomResp> getContactPage(CursorPageBaseReq request, Long uid);
|
||||
|
||||
/**
|
||||
* 获取群组信息
|
||||
*/
|
||||
MemberResp getGroupDetail(Long uid, long roomId);
|
||||
|
||||
CursorPageBaseResp<ChatMemberResp> getMemberPage(MemberReq request);
|
||||
|
||||
List<ChatMemberListResp> getMemberList(ChatMessageMemberReq request);
|
||||
|
||||
void delMember(Long uid, MemberDelReq request);
|
||||
|
||||
void addMember(Long uid, MemberAddReq request);
|
||||
|
||||
Long addGroup(Long uid, GroupAddReq request);
|
||||
|
||||
ChatRoomResp getContactDetail(Long uid, Long roomId);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Description: 房间底层管理
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
public interface RoomService {
|
||||
|
||||
/**
|
||||
* 创建一个单聊房间
|
||||
*/
|
||||
RoomFriend createFriendRoom(List<Long> uidList);
|
||||
|
||||
/**
|
||||
* 禁用一个单聊房间
|
||||
*/
|
||||
void disableFriendRoom(List<Long> uidList);
|
||||
|
||||
|
||||
/**
|
||||
* 创建一个群聊房间
|
||||
*/
|
||||
RoomGroup createGroupRoom(Long uid);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface WeChatMsgOperationService {
|
||||
/**
|
||||
* 向被at的用户微信推送群聊消息
|
||||
*
|
||||
* @param senderUid senderUid
|
||||
* @param receiverUidList receiverUidList
|
||||
* @param msg msg
|
||||
*/
|
||||
void publishChatMsgToWeChatUser(long senderUid, List<Long> receiverUidList, String msg);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.abin.mallchat.common.chat.service.adapter;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||
import com.abin.mallchat.common.chat.domain.enums.HotFlagEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum;
|
||||
import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
public class ChatAdapter {
|
||||
public static final String SEPARATOR = ",";
|
||||
|
||||
public static String generateRoomKey(List<Long> uidList) {
|
||||
return uidList.stream()
|
||||
.sorted()
|
||||
.map(String::valueOf)
|
||||
.collect(Collectors.joining(SEPARATOR));
|
||||
}
|
||||
|
||||
public static Room buildRoom(RoomTypeEnum typeEnum) {
|
||||
Room room = new Room();
|
||||
room.setType(typeEnum.getType());
|
||||
room.setHotFlag(HotFlagEnum.NOT.getType());
|
||||
return room;
|
||||
}
|
||||
|
||||
public static RoomFriend buildFriendRoom(Long roomId, List<Long> uidList) {
|
||||
List<Long> collect = uidList.stream().sorted().collect(Collectors.toList());
|
||||
RoomFriend roomFriend = new RoomFriend();
|
||||
roomFriend.setRoomId(roomId);
|
||||
roomFriend.setUid1(collect.get(0));
|
||||
roomFriend.setUid2(collect.get(1));
|
||||
roomFriend.setRoomKey(generateRoomKey(uidList));
|
||||
roomFriend.setStatus(NormalOrNoEnum.NORMAL.getStatus());
|
||||
return roomFriend;
|
||||
}
|
||||
|
||||
public static Contact buildContact(Long uid, Long roomId) {
|
||||
Contact contact = new Contact();
|
||||
contact.setRoomId(roomId);
|
||||
contact.setUid(uid);
|
||||
return contact;
|
||||
}
|
||||
|
||||
public static Set<Long> getFriendUidSet(Collection<RoomFriend> values, Long uid) {
|
||||
return values.stream()
|
||||
.map(a -> getFriendUid(a, uid))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取好友uid
|
||||
*/
|
||||
public static Long getFriendUid(RoomFriend roomFriend, Long uid) {
|
||||
return Objects.equals(uid, roomFriend.getUid1()) ? roomFriend.getUid2() : roomFriend.getUid1();
|
||||
}
|
||||
|
||||
public static RoomGroup buildGroupRoom(User user, Long roomId) {
|
||||
RoomGroup roomGroup = new RoomGroup();
|
||||
roomGroup.setName(user.getName() + "的群组");
|
||||
roomGroup.setAvatar(user.getAvatar());
|
||||
roomGroup.setRoomId(roomId);
|
||||
return roomGroup;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.abin.mallchat.common.chat.service.adapter;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.GroupMember;
|
||||
import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberListResp;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
import com.abin.mallchat.common.user.domain.entity.UserFriend;
|
||||
import com.abin.mallchat.common.user.domain.enums.WSBaseResp;
|
||||
import com.abin.mallchat.common.user.domain.enums.WSRespTypeEnum;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange;
|
||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange.CHANGE_TYPE_ADD;
|
||||
import static com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange.CHANGE_TYPE_REMOVE;
|
||||
|
||||
/**
|
||||
* Description: 成员适配器
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-26
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MemberAdapter {
|
||||
@Autowired
|
||||
private UserCache userCache;
|
||||
|
||||
public static List<ChatMemberResp> buildMember(List<User> list) {
|
||||
return list.stream().map(a -> {
|
||||
ChatMemberResp resp = new ChatMemberResp();
|
||||
resp.setActiveStatus(a.getActiveStatus());
|
||||
resp.setLastOptTime(a.getLastOptTime());
|
||||
resp.setUid(a.getId());
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<ChatMemberResp> buildMember(List<UserFriend> list, List<User> userList) {
|
||||
Map<Long, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, user -> user));
|
||||
return list.stream().map(userFriend -> {
|
||||
ChatMemberResp resp = new ChatMemberResp();
|
||||
resp.setUid(userFriend.getFriendUid());
|
||||
User user = userMap.get(userFriend.getFriendUid());
|
||||
if (Objects.nonNull(user)) {
|
||||
resp.setActiveStatus(user.getActiveStatus());
|
||||
resp.setLastOptTime(user.getLastOptTime());
|
||||
}
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
public static List<ChatMemberListResp> buildMemberList(List<User> memberList) {
|
||||
return memberList.stream()
|
||||
.map(a -> {
|
||||
ChatMemberListResp resp = new ChatMemberListResp();
|
||||
BeanUtils.copyProperties(a, resp);
|
||||
resp.setUid(a.getId());
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<ChatMemberListResp> buildMemberList(Map<Long, User> batch) {
|
||||
return buildMemberList(new ArrayList<>(batch.values()));
|
||||
}
|
||||
|
||||
public static List<GroupMember> buildMemberAdd(Long groupId, List<Long> waitAddUidList) {
|
||||
return waitAddUidList.stream().map(a -> {
|
||||
GroupMember member = new GroupMember();
|
||||
member.setGroupId(groupId);
|
||||
member.setUid(a);
|
||||
member.setRole(GroupRoleEnum.MEMBER.getType());
|
||||
return member;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static WSBaseResp<WSMemberChange> buildMemberAddWS(Long roomId, User user) {
|
||||
WSBaseResp<WSMemberChange> wsBaseResp = new WSBaseResp<>();
|
||||
wsBaseResp.setType(WSRespTypeEnum.MEMBER_CHANGE.getType());
|
||||
WSMemberChange wsMemberChange = new WSMemberChange();
|
||||
wsMemberChange.setActiveStatus(user.getActiveStatus());
|
||||
wsMemberChange.setLastOptTime(user.getLastOptTime());
|
||||
wsMemberChange.setUid(user.getId());
|
||||
wsMemberChange.setRoomId(roomId);
|
||||
wsMemberChange.setChangeType(CHANGE_TYPE_ADD);
|
||||
wsBaseResp.setData(wsMemberChange);
|
||||
return wsBaseResp;
|
||||
}
|
||||
|
||||
public static WSBaseResp<WSMemberChange> buildMemberRemoveWS(Long roomId, Long uid) {
|
||||
WSBaseResp<WSMemberChange> wsBaseResp = new WSBaseResp<>();
|
||||
wsBaseResp.setType(WSRespTypeEnum.MEMBER_CHANGE.getType());
|
||||
WSMemberChange wsMemberChange = new WSMemberChange();
|
||||
wsMemberChange.setUid(uid);
|
||||
wsMemberChange.setRoomId(roomId);
|
||||
wsMemberChange.setChangeType(CHANGE_TYPE_REMOVE);
|
||||
wsBaseResp.setData(wsMemberChange);
|
||||
return wsBaseResp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.abin.mallchat.common.chat.service.adapter;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.ChatMessageReq;
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.msg.TextMsgReq;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp;
|
||||
import com.abin.mallchat.common.chat.service.strategy.msg.AbstractMsgHandler;
|
||||
import com.abin.mallchat.common.chat.service.strategy.msg.MsgHandlerFactory;
|
||||
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 消息适配器
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-26
|
||||
*/
|
||||
public class MessageAdapter {
|
||||
public static final int CAN_CALLBACK_GAP_COUNT = 100;
|
||||
|
||||
public static Message buildMsgSave(ChatMessageReq request, Long uid) {
|
||||
|
||||
return Message.builder()
|
||||
.fromUid(uid)
|
||||
.roomId(request.getRoomId())
|
||||
.type(request.getMsgType())
|
||||
.status(MessageStatusEnum.NORMAL.getStatus())
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
public static List<ChatMessageResp> buildMsgResp(List<Message> messages, Map<Long, Message> replyMap, List<MessageMark> msgMark, Long receiveUid) {
|
||||
Map<Long, List<MessageMark>> markMap = msgMark.stream().collect(Collectors.groupingBy(MessageMark::getMsgId));
|
||||
return messages.stream().map(a -> {
|
||||
ChatMessageResp resp = new ChatMessageResp();
|
||||
resp.setFromUser(buildFromUser(a.getFromUid()));
|
||||
resp.setMessage(buildMessage(a, replyMap, markMap.getOrDefault(a.getId(), new ArrayList<>()), receiveUid));
|
||||
return resp;
|
||||
})
|
||||
.sorted(Comparator.comparing(a -> a.getMessage().getSendTime()))//帮前端排好序,更方便它展示
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static ChatMessageResp.Message buildMessage(Message message, Map<Long, Message> replyMap, List<MessageMark> marks, Long receiveUid) {
|
||||
ChatMessageResp.Message messageVO = new ChatMessageResp.Message();
|
||||
BeanUtil.copyProperties(message, messageVO);
|
||||
messageVO.setSendTime(message.getCreateTime());
|
||||
AbstractMsgHandler msgHandler = MsgHandlerFactory.getStrategyNoNull(message.getType());
|
||||
if (Objects.nonNull(msgHandler)) {
|
||||
messageVO.setBody(msgHandler.showMsg(message));
|
||||
}
|
||||
//消息标记
|
||||
messageVO.setMessageMark(buildMsgMark(marks, receiveUid));
|
||||
return messageVO;
|
||||
}
|
||||
|
||||
private static ChatMessageResp.MessageMark buildMsgMark(List<MessageMark> marks, Long receiveUid) {
|
||||
Map<Integer, List<MessageMark>> typeMap = marks.stream().collect(Collectors.groupingBy(MessageMark::getType));
|
||||
List<MessageMark> likeMarks = typeMap.getOrDefault(MessageMarkTypeEnum.LIKE.getType(), new ArrayList<>());
|
||||
List<MessageMark> dislikeMarks = typeMap.getOrDefault(MessageMarkTypeEnum.DISLIKE.getType(), new ArrayList<>());
|
||||
ChatMessageResp.MessageMark mark = new ChatMessageResp.MessageMark();
|
||||
mark.setLikeCount(likeMarks.size());
|
||||
mark.setUserLike(Optional.ofNullable(receiveUid).filter(uid -> likeMarks.stream().anyMatch(a -> Objects.equals(a.getUid(), uid))).map(a -> YesOrNoEnum.YES.getStatus()).orElse(YesOrNoEnum.NO.getStatus()));
|
||||
mark.setDislikeCount(dislikeMarks.size());
|
||||
mark.setUserDislike(Optional.ofNullable(receiveUid).filter(uid -> dislikeMarks.stream().anyMatch(a -> Objects.equals(a.getUid(), uid))).map(a -> YesOrNoEnum.YES.getStatus()).orElse(YesOrNoEnum.NO.getStatus()));
|
||||
return mark;
|
||||
}
|
||||
|
||||
private static ChatMessageResp.UserInfo buildFromUser(Long fromUid) {
|
||||
ChatMessageResp.UserInfo userInfo = new ChatMessageResp.UserInfo();
|
||||
userInfo.setUid(fromUid);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
public static ChatMessageReq buildAgreeMsg(Long roomId) {
|
||||
ChatMessageReq chatMessageReq = new ChatMessageReq();
|
||||
chatMessageReq.setRoomId(roomId);
|
||||
chatMessageReq.setMsgType(MessageTypeEnum.TEXT.getType());
|
||||
TextMsgReq textMsgReq = new TextMsgReq();
|
||||
textMsgReq.setContent("我们已经成为好友了,开始聊天吧");
|
||||
chatMessageReq.setBody(textMsgReq);
|
||||
return chatMessageReq;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.abin.mallchat.common.chat.service.adapter;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
||||
import com.abin.mallchat.common.chat.domain.entity.GroupMember;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||
import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.ChatMessageReq;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageReadResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatRoomResp;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 消息适配器
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-26
|
||||
*/
|
||||
public class RoomAdapter {
|
||||
|
||||
|
||||
public static List<ChatRoomResp> buildResp(List<Room> list) {
|
||||
return list.stream()
|
||||
.map(a -> {
|
||||
ChatRoomResp resp = new ChatRoomResp();
|
||||
BeanUtil.copyProperties(a, resp);
|
||||
resp.setActiveTime(a.getActiveTime());
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<ChatMessageReadResp> buildReadResp(List<Contact> list) {
|
||||
return list.stream().map(contact -> {
|
||||
ChatMessageReadResp resp = new ChatMessageReadResp();
|
||||
resp.setUid(contact.getUid());
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static List<GroupMember> buildGroupMemberBatch(List<Long> uidList, Long groupId) {
|
||||
return uidList.stream()
|
||||
.distinct()
|
||||
.map(uid -> {
|
||||
GroupMember member = new GroupMember();
|
||||
member.setRole(GroupRoleEnum.MEMBER.getType());
|
||||
member.setUid(uid);
|
||||
member.setGroupId(groupId);
|
||||
return member;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static ChatMessageReq buildGroupAddMessage(RoomGroup groupRoom, User inviter, Map<Long, User> member) {
|
||||
ChatMessageReq chatMessageReq = new ChatMessageReq();
|
||||
chatMessageReq.setRoomId(groupRoom.getRoomId());
|
||||
chatMessageReq.setMsgType(MessageTypeEnum.SYSTEM.getType());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("\"")
|
||||
.append(inviter.getName())
|
||||
.append("\"")
|
||||
.append("邀请")
|
||||
.append(member.values().stream().map(u -> "\"" + u.getName() + "\"").collect(Collectors.joining(",")))
|
||||
.append("加入群聊");
|
||||
chatMessageReq.setBody(sb.toString());
|
||||
return chatMessageReq;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.abin.mallchat.common.chat.service.cache;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.GroupMemberDao;
|
||||
import com.abin.mallchat.common.chat.dao.MessageDao;
|
||||
import com.abin.mallchat.common.chat.dao.RoomGroupDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Description: 群成员相关缓存
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-27
|
||||
*/
|
||||
@Component
|
||||
public class GroupMemberCache {
|
||||
|
||||
@Autowired
|
||||
private MessageDao messageDao;
|
||||
@Autowired
|
||||
private RoomGroupDao roomGroupDao;
|
||||
@Autowired
|
||||
private GroupMemberDao groupMemberDao;
|
||||
|
||||
@Cacheable(cacheNames = "member", key = "'groupMember'+#roomId")
|
||||
public List<Long> getMemberUidList(Long roomId) {
|
||||
RoomGroup roomGroup = roomGroupDao.getByRoomId(roomId);
|
||||
if (Objects.isNull(roomGroup)) {
|
||||
return null;
|
||||
}
|
||||
return groupMemberDao.getMemberUidList(roomGroup.getId());
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = "member", key = "'groupMember'+#roomId")
|
||||
public List<Long> evictMemberUidList(Long roomId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
42
mallchat-chat-server/src/main/java/com/abin/mallchat/common/chat/service/cache/HotRoomCache.java
vendored
Normal file
42
mallchat-chat-server/src/main/java/com/abin/mallchat/common/chat/service/cache/HotRoomCache.java
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.abin.mallchat.common.chat.service.cache;
|
||||
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import com.abin.mallchat.common.common.constant.RedisKey;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.utils.CursorUtils;
|
||||
import com.abin.mallchat.common.common.utils.RedisUtils;
|
||||
import org.springframework.data.redis.core.ZSetOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Description: 全局房间
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-23
|
||||
*/
|
||||
@Component
|
||||
public class HotRoomCache {
|
||||
|
||||
/**
|
||||
* 获取热门群聊翻页
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public CursorPageBaseResp<Pair<Long, Double>> getRoomCursorPage(CursorPageBaseReq pageBaseReq) {
|
||||
return CursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.HOT_ROOM_ZET), Long::parseLong);
|
||||
}
|
||||
|
||||
public Set<ZSetOperations.TypedTuple<String>> getRoomRange(Double hotStart, Double hotEnd) {
|
||||
return RedisUtils.zRangeByScoreWithScores(RedisKey.getKey(RedisKey.HOT_ROOM_ZET), hotStart, hotEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新热门群聊的最新时间
|
||||
*/
|
||||
public void refreshActiveTime(Long roomId, Date refreshTime) {
|
||||
RedisUtils.zAdd(RedisKey.getKey(RedisKey.HOT_ROOM_ZET), roomId, (double) refreshTime.getTime());
|
||||
}
|
||||
}
|
||||
39
mallchat-chat-server/src/main/java/com/abin/mallchat/common/chat/service/cache/MsgCache.java
vendored
Normal file
39
mallchat-chat-server/src/main/java/com/abin/mallchat/common/chat/service/cache/MsgCache.java
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.abin.mallchat.common.chat.service.cache;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.MessageDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.abin.mallchat.common.user.dao.BlackDao;
|
||||
import com.abin.mallchat.common.user.dao.RoleDao;
|
||||
import com.abin.mallchat.common.user.dao.UserDao;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Description: 消息相关缓存
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-27
|
||||
*/
|
||||
@Component
|
||||
public class MsgCache {
|
||||
|
||||
@Autowired
|
||||
private UserDao userDao;
|
||||
@Autowired
|
||||
private BlackDao blackDao;
|
||||
@Autowired
|
||||
private RoleDao roleDao;
|
||||
@Autowired
|
||||
private MessageDao messageDao;
|
||||
|
||||
@Cacheable(cacheNames = "msg", key = "'msg'+#msgId")
|
||||
public Message getMsg(Long msgId) {
|
||||
return messageDao.getById(msgId);
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = "msg", key = "'msg'+#msgId")
|
||||
public Message evictMsg(Long msgId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
46
mallchat-chat-server/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomCache.java
vendored
Normal file
46
mallchat-chat-server/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomCache.java
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.abin.mallchat.common.chat.service.cache;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.RoomDao;
|
||||
import com.abin.mallchat.common.chat.dao.RoomFriendDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.abin.mallchat.common.common.constant.RedisKey;
|
||||
import com.abin.mallchat.common.common.service.cache.AbstractRedisStringCache;
|
||||
import com.abin.mallchat.common.user.dao.UserDao;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 房间基本信息的缓存
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-10
|
||||
*/
|
||||
@Component
|
||||
public class RoomCache extends AbstractRedisStringCache<Long, Room> {
|
||||
@Autowired
|
||||
private UserDao userDao;
|
||||
@Autowired
|
||||
private RoomDao roomDao;
|
||||
@Autowired
|
||||
private RoomFriendDao roomFriendDao;
|
||||
|
||||
@Override
|
||||
protected String getKey(Long roomId) {
|
||||
return RedisKey.getKey(RedisKey.ROOM_INFO_STRING, roomId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long getExpireSeconds() {
|
||||
return 5 * 60L;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Long, Room> load(List<Long> roomIds) {
|
||||
List<Room> rooms = roomDao.listByIds(roomIds);
|
||||
return rooms.stream().collect(Collectors.toMap(Room::getId, Function.identity()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.abin.mallchat.common.chat.service.cache;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.RoomFriendDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
import com.abin.mallchat.common.common.constant.RedisKey;
|
||||
import com.abin.mallchat.common.common.service.cache.AbstractRedisStringCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 群组基本信息的缓存
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-10
|
||||
*/
|
||||
@Component
|
||||
public class RoomFriendCache extends AbstractRedisStringCache<Long, RoomFriend> {
|
||||
@Autowired
|
||||
private RoomFriendDao roomFriendDao;
|
||||
|
||||
@Override
|
||||
protected String getKey(Long groupId) {
|
||||
return RedisKey.getKey(RedisKey.GROUP_INFO_STRING, groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long getExpireSeconds() {
|
||||
return 5 * 60L;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Long, RoomFriend> load(List<Long> roomIds) {
|
||||
List<RoomFriend> roomGroups = roomFriendDao.listByRoomIds(roomIds);
|
||||
return roomGroups.stream().collect(Collectors.toMap(RoomFriend::getRoomId, Function.identity()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.abin.mallchat.common.chat.service.cache;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.RoomGroupDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||
import com.abin.mallchat.common.common.constant.RedisKey;
|
||||
import com.abin.mallchat.common.common.service.cache.AbstractRedisStringCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 群组基本信息的缓存
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-06-10
|
||||
*/
|
||||
@Component
|
||||
public class RoomGroupCache extends AbstractRedisStringCache<Long, RoomGroup> {
|
||||
@Autowired
|
||||
private RoomGroupDao roomGroupDao;
|
||||
|
||||
@Override
|
||||
protected String getKey(Long roomId) {
|
||||
return RedisKey.getKey(RedisKey.GROUP_INFO_STRING, roomId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long getExpireSeconds() {
|
||||
return 5 * 60L;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Long, RoomGroup> load(List<Long> roomIds) {
|
||||
List<RoomGroup> roomGroups = roomGroupDao.listByRoomIds(roomIds);
|
||||
return roomGroups.stream().collect(Collectors.toMap(RoomGroup::getRoomId, Function.identity()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.abin.mallchat.common.chat.service.helper;
|
||||
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum;
|
||||
|
||||
/**
|
||||
* Description: 成员列表工具类
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-28
|
||||
*/
|
||||
public class ChatMemberHelper {
|
||||
private static final String SEPARATOR = "_";
|
||||
|
||||
public static Pair<ChatActiveStatusEnum, String> getCursorPair(String cursor) {
|
||||
ChatActiveStatusEnum activeStatusEnum = ChatActiveStatusEnum.ONLINE;
|
||||
String timeCursor = null;
|
||||
if (StrUtil.isNotBlank(cursor)) {
|
||||
String activeStr = cursor.split(SEPARATOR)[0];
|
||||
String timeStr = cursor.split(SEPARATOR)[1];
|
||||
activeStatusEnum = ChatActiveStatusEnum.of(Integer.parseInt(activeStr));
|
||||
timeCursor = timeStr;
|
||||
}
|
||||
return Pair.of(activeStatusEnum, timeCursor);
|
||||
}
|
||||
|
||||
public static String generateCursor(ChatActiveStatusEnum activeStatusEnum, String timeCursor) {
|
||||
return activeStatusEnum.getStatus() + SEPARATOR + timeCursor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
package com.abin.mallchat.common.chat.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.DateUnit;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import com.abin.mallchat.common.chat.dao.*;
|
||||
import com.abin.mallchat.common.chat.domain.dto.MsgReadInfoDTO;
|
||||
import com.abin.mallchat.common.chat.domain.entity.*;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageMarkActTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.*;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberListResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberStatisticResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageReadResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp;
|
||||
import com.abin.mallchat.common.chat.service.ChatService;
|
||||
import com.abin.mallchat.common.chat.service.ContactService;
|
||||
import com.abin.mallchat.common.chat.service.adapter.MemberAdapter;
|
||||
import com.abin.mallchat.common.chat.service.adapter.MessageAdapter;
|
||||
import com.abin.mallchat.common.chat.service.adapter.RoomAdapter;
|
||||
import com.abin.mallchat.common.chat.service.cache.RoomCache;
|
||||
import com.abin.mallchat.common.chat.service.cache.RoomGroupCache;
|
||||
import com.abin.mallchat.common.chat.service.helper.ChatMemberHelper;
|
||||
import com.abin.mallchat.common.chat.service.strategy.mark.AbstractMsgMarkStrategy;
|
||||
import com.abin.mallchat.common.chat.service.strategy.mark.MsgMarkFactory;
|
||||
import com.abin.mallchat.common.chat.service.strategy.msg.AbstractMsgHandler;
|
||||
import com.abin.mallchat.common.chat.service.strategy.msg.MsgHandlerFactory;
|
||||
import com.abin.mallchat.common.chat.service.strategy.msg.RecallMsgHandler;
|
||||
import com.abin.mallchat.common.common.annotation.RedissonLock;
|
||||
import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.event.MessageSendEvent;
|
||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||
import com.abin.mallchat.common.user.dao.UserDao;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum;
|
||||
import com.abin.mallchat.common.user.domain.enums.RoleEnum;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||
import com.abin.mallchat.common.user.service.IRoleService;
|
||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||
import com.abin.mallchat.transaction.service.MQProducer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 消息处理类
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-26
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ChatServiceImpl implements ChatService {
|
||||
public static final long ROOM_GROUP_ID = 1L;
|
||||
@Autowired
|
||||
private MessageDao messageDao;
|
||||
@Autowired
|
||||
private UserDao userDao;
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
@Autowired
|
||||
private UserCache userCache;
|
||||
@Autowired
|
||||
private MemberAdapter memberAdapter;
|
||||
@Autowired
|
||||
private RoomDao roomDao;
|
||||
@Autowired
|
||||
private MessageMarkDao messageMarkDao;
|
||||
@Autowired
|
||||
private RoomFriendDao roomFriendDao;
|
||||
@Autowired
|
||||
private IRoleService iRoleService;
|
||||
@Autowired
|
||||
private RecallMsgHandler recallMsgHandler;
|
||||
@Autowired
|
||||
private ContactService contactService;
|
||||
@Autowired
|
||||
private ContactDao contactDao;
|
||||
@Autowired
|
||||
private RoomCache roomCache;
|
||||
@Autowired
|
||||
private GroupMemberDao groupMemberDao;
|
||||
@Autowired
|
||||
private RoomGroupCache roomGroupCache;
|
||||
@Autowired
|
||||
private MQProducer mqProducer;
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public Long sendMsg(ChatMessageReq request, Long uid) {
|
||||
check(request, uid);
|
||||
AbstractMsgHandler msgHandler = MsgHandlerFactory.getStrategyNoNull(request.getMsgType());//todo 这里先不扩展,后续再改
|
||||
msgHandler.checkMsg(request, uid);
|
||||
//同步获取消息的跳转链接标题
|
||||
Message insert = MessageAdapter.buildMsgSave(request, uid);
|
||||
messageDao.save(insert);
|
||||
msgHandler.saveMsg(insert, request);
|
||||
//发布消息发送事件
|
||||
applicationEventPublisher.publishEvent(new MessageSendEvent(this, insert.getId()));
|
||||
return insert.getId();
|
||||
}
|
||||
|
||||
private void check(ChatMessageReq request, Long uid) {
|
||||
Room room = roomCache.get(request.getRoomId());
|
||||
if (room.isHotRoom()) {//全员群跳过校验
|
||||
return;
|
||||
}
|
||||
if (room.isRoomFriend()) {
|
||||
RoomFriend roomFriend = roomFriendDao.getByRoomId(request.getRoomId());
|
||||
AssertUtil.equal(NormalOrNoEnum.NORMAL.getStatus(), roomFriend.getStatus(), "您已经被对方拉黑");
|
||||
AssertUtil.isTrue(uid.equals(roomFriend.getUid1()) || uid.equals(roomFriend.getUid2()), "您已经被对方拉黑");
|
||||
}
|
||||
if (room.isRoomGroup()) {
|
||||
RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
|
||||
GroupMember member = groupMemberDao.getMember(roomGroup.getId(), uid);
|
||||
AssertUtil.isNotEmpty(member, "您已经被移除该群");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatMessageResp getMsgResp(Message message, Long receiveUid) {
|
||||
return CollUtil.getFirst(getMsgRespBatch(Collections.singletonList(message), receiveUid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatMessageResp getMsgResp(Long msgId, Long receiveUid) {
|
||||
Message msg = messageDao.getById(msgId);
|
||||
return getMsgResp(msg, receiveUid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CursorPageBaseResp<ChatMemberResp> getMemberPage(List<Long> memberUidList, CursorPageBaseReq request) {
|
||||
Pair<ChatActiveStatusEnum, String> pair = ChatMemberHelper.getCursorPair(request.getCursor());
|
||||
ChatActiveStatusEnum activeStatusEnum = pair.getKey();
|
||||
String timeCursor = pair.getValue();
|
||||
List<ChatMemberResp> resultList = new ArrayList<>();//最终列表
|
||||
Boolean isLast = Boolean.FALSE;
|
||||
if (activeStatusEnum == ChatActiveStatusEnum.ONLINE) {//在线列表
|
||||
CursorPageBaseResp<User> cursorPage = userDao.getCursorPage(memberUidList, new CursorPageBaseReq(request.getPageSize(), timeCursor), ChatActiveStatusEnum.ONLINE);
|
||||
resultList.addAll(MemberAdapter.buildMember(cursorPage.getList()));//添加在线列表
|
||||
if (cursorPage.getIsLast()) {//如果是最后一页,从离线列表再补点数据
|
||||
activeStatusEnum = ChatActiveStatusEnum.OFFLINE;
|
||||
Integer leftSize = request.getPageSize() - cursorPage.getList().size();
|
||||
cursorPage = userDao.getCursorPage(memberUidList, new CursorPageBaseReq(leftSize, null), ChatActiveStatusEnum.OFFLINE);
|
||||
resultList.addAll(MemberAdapter.buildMember(cursorPage.getList()));//添加离线线列表
|
||||
}
|
||||
timeCursor = cursorPage.getCursor();
|
||||
isLast = cursorPage.getIsLast();
|
||||
} else if (activeStatusEnum == ChatActiveStatusEnum.OFFLINE) {//离线列表
|
||||
CursorPageBaseResp<User> cursorPage = userDao.getCursorPage(memberUidList, new CursorPageBaseReq(request.getPageSize(), timeCursor), ChatActiveStatusEnum.OFFLINE);
|
||||
resultList.addAll(MemberAdapter.buildMember(cursorPage.getList()));//添加离线线列表
|
||||
timeCursor = cursorPage.getCursor();
|
||||
isLast = cursorPage.getIsLast();
|
||||
}
|
||||
//组装结果
|
||||
return new CursorPageBaseResp<>(ChatMemberHelper.generateCursor(activeStatusEnum, timeCursor), isLast, resultList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CursorPageBaseResp<ChatMessageResp> getMsgPage(ChatMessagePageReq request, Long receiveUid) {
|
||||
//用最后一条消息id,来限制被踢出的人能看见的最大一条消息
|
||||
Long lastMsgId = getLastMsgId(request.getRoomId(), receiveUid);
|
||||
CursorPageBaseResp<Message> cursorPage = messageDao.getCursorPage(request.getRoomId(), request, lastMsgId);
|
||||
if (cursorPage.isEmpty()) {
|
||||
return CursorPageBaseResp.empty();
|
||||
}
|
||||
return CursorPageBaseResp.init(cursorPage, getMsgRespBatch(cursorPage.getList(), receiveUid));
|
||||
}
|
||||
|
||||
private Long getLastMsgId(Long roomId, Long receiveUid) {
|
||||
Room room = roomCache.get(roomId);
|
||||
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||
if (room.isHotRoom()) {
|
||||
return null;
|
||||
}
|
||||
AssertUtil.isNotEmpty(receiveUid, "请先登录");
|
||||
Contact contact = contactDao.get(receiveUid, roomId);
|
||||
return contact.getLastMsgId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatMemberStatisticResp getMemberStatistic() {
|
||||
System.out.println(Thread.currentThread().getName());
|
||||
Long onlineNum = userCache.getOnlineNum();
|
||||
// Long offlineNum = userCache.getOfflineNum();不展示总人数
|
||||
ChatMemberStatisticResp resp = new ChatMemberStatisticResp();
|
||||
resp.setOnlineNum(onlineNum);
|
||||
// resp.setTotalNum(onlineNum + offlineNum);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Override
|
||||
@RedissonLock(key = "#uid")
|
||||
public void setMsgMark(Long uid, ChatMessageMarkReq request) {
|
||||
AbstractMsgMarkStrategy strategy = MsgMarkFactory.getStrategyNoNull(request.getMarkType());
|
||||
switch (MessageMarkActTypeEnum.of(request.getActType())) {
|
||||
case MARK:
|
||||
strategy.mark(uid, request.getMsgId());
|
||||
break;
|
||||
case UN_MARK:
|
||||
strategy.unMark(uid, request.getMsgId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recallMsg(Long uid, ChatMessageBaseReq request) {
|
||||
Message message = messageDao.getById(request.getMsgId());
|
||||
//校验能不能执行撤回
|
||||
checkRecall(uid, message);
|
||||
//执行消息撤回
|
||||
recallMsgHandler.recall(uid, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = "member", key = "'memberList.'+#req.roomId")
|
||||
public List<ChatMemberListResp> getMemberList(ChatMessageMemberReq req) {
|
||||
if (Objects.equals(1L, req.getRoomId())) {//大群聊可看见所有人
|
||||
return userDao.getMemberList()
|
||||
.stream()
|
||||
.map(a -> {
|
||||
ChatMemberListResp resp = new ChatMemberListResp();
|
||||
BeanUtils.copyProperties(a, resp);
|
||||
resp.setUid(a.getId());
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MsgReadInfoDTO> getMsgReadInfo(Long uid, ChatMessageReadInfoReq request) {
|
||||
List<Message> messages = messageDao.listByIds(request.getMsgIds());
|
||||
messages.forEach(message -> {
|
||||
AssertUtil.equal(uid, message.getFromUid(), "只能查询自己发送的消息");
|
||||
});
|
||||
return contactService.getMsgReadInfo(messages).values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CursorPageBaseResp<ChatMessageReadResp> getReadPage(@Nullable Long uid, ChatMessageReadReq request) {
|
||||
Message message = messageDao.getById(request.getMsgId());
|
||||
AssertUtil.isNotEmpty(message, "消息id有误");
|
||||
AssertUtil.equal(uid, message.getFromUid(), "只能查看自己的消息");
|
||||
CursorPageBaseResp<Contact> page;
|
||||
if (request.getSearchType() == 1) {//已读
|
||||
page = contactDao.getReadPage(message, request);
|
||||
} else {
|
||||
page = contactDao.getUnReadPage(message, request);
|
||||
}
|
||||
if (CollectionUtil.isEmpty(page.getList())) {
|
||||
return CursorPageBaseResp.empty();
|
||||
}
|
||||
return CursorPageBaseResp.init(page, RoomAdapter.buildReadResp(page.getList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@RedissonLock(key = "#uid")
|
||||
public void msgRead(Long uid, ChatMessageMemberReq request) {
|
||||
Contact contact = contactDao.get(uid, request.getRoomId());
|
||||
if (Objects.nonNull(contact)) {
|
||||
Contact update = new Contact();
|
||||
update.setId(contact.getId());
|
||||
update.setReadTime(new Date());
|
||||
contactDao.updateById(update);
|
||||
} else {
|
||||
Contact insert = new Contact();
|
||||
insert.setUid(uid);
|
||||
insert.setRoomId(request.getRoomId());
|
||||
insert.setReadTime(new Date());
|
||||
contactDao.save(insert);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRecall(Long uid, Message message) {
|
||||
AssertUtil.isNotEmpty(message, "消息有误");
|
||||
AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL, "消息无法撤回");
|
||||
boolean hasPower = iRoleService.hasPower(uid, RoleEnum.CHAT_MANAGER);
|
||||
if (hasPower) {
|
||||
return;
|
||||
}
|
||||
boolean self = Objects.equals(uid, message.getFromUid());
|
||||
AssertUtil.isTrue(self, "抱歉,您没有权限");
|
||||
long between = DateUtil.between(message.getCreateTime(), new Date(), DateUnit.MINUTE);
|
||||
AssertUtil.isTrue(between < 2, "覆水难收,超过2分钟的消息不能撤回哦~~");
|
||||
}
|
||||
|
||||
public List<ChatMessageResp> getMsgRespBatch(List<Message> messages, Long receiveUid) {
|
||||
if (CollectionUtil.isEmpty(messages)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Map<Long, Message> replyMap = new HashMap<>();
|
||||
//批量查出回复的消息
|
||||
List<Long> replyIds = messages.stream().map(Message::getReplyMsgId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
||||
if (CollectionUtil.isNotEmpty(replyIds)) {
|
||||
replyMap = messageDao.listByIds(replyIds).stream().collect(Collectors.toMap(Message::getId, Function.identity()));
|
||||
}
|
||||
//查询消息标志
|
||||
List<MessageMark> msgMark = messageMarkDao.getValidMarkByMsgIdBatch(messages.stream().map(Message::getId).collect(Collectors.toList()));
|
||||
return MessageAdapter.buildMsgResp(messages, replyMap, msgMark, receiveUid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.abin.mallchat.common.chat.service.impl;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.ContactDao;
|
||||
import com.abin.mallchat.common.chat.dao.MessageDao;
|
||||
import com.abin.mallchat.common.chat.domain.dto.MsgReadInfoDTO;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||
import com.abin.mallchat.common.chat.service.ContactService;
|
||||
import com.abin.mallchat.common.chat.service.adapter.ChatAdapter;
|
||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description: 会话列表
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
@Service
|
||||
public class ContactServiceImpl implements ContactService {
|
||||
|
||||
@Autowired
|
||||
private ContactDao contactDao;
|
||||
@Autowired
|
||||
private MessageDao messageDao;
|
||||
|
||||
@Override
|
||||
public Contact createContact(Long uid, Long roomId) {
|
||||
Contact contact = contactDao.get(uid, roomId);
|
||||
if (Objects.isNull(contact)) {
|
||||
contact = ChatAdapter.buildContact(uid, roomId);
|
||||
contactDao.save(contact);
|
||||
}
|
||||
return contact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getMsgReadCount(Message message) {
|
||||
return contactDao.getReadCount(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getMsgUnReadCount(Message message) {
|
||||
return contactDao.getUnReadCount(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, MsgReadInfoDTO> getMsgReadInfo(List<Message> messages) {
|
||||
Map<Long, List<Message>> roomGroup = messages.stream().collect(Collectors.groupingBy(Message::getRoomId));
|
||||
AssertUtil.equal(roomGroup.size(), 1, "只能查相同房间下的消息");
|
||||
Long roomId = roomGroup.keySet().iterator().next();
|
||||
Integer totalCount = contactDao.getTotalCount(roomId);
|
||||
return messages.stream().map(message -> {
|
||||
MsgReadInfoDTO readInfoDTO = new MsgReadInfoDTO();
|
||||
readInfoDTO.setMsgId(message.getId());
|
||||
Integer readCount = contactDao.getReadCount(message);
|
||||
readInfoDTO.setReadCount(readCount);
|
||||
readInfoDTO.setUnReadCount(totalCount - readCount - 1);
|
||||
return readInfoDTO;
|
||||
}).collect(Collectors.toMap(MsgReadInfoDTO::getMsgId, Function.identity()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
package com.abin.mallchat.common.chat.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import com.abin.mallchat.common.chat.dao.ContactDao;
|
||||
import com.abin.mallchat.common.chat.dao.GroupMemberDao;
|
||||
import com.abin.mallchat.common.chat.dao.MessageDao;
|
||||
import com.abin.mallchat.common.chat.domain.dto.RoomBaseInfo;
|
||||
import com.abin.mallchat.common.chat.domain.entity.*;
|
||||
import com.abin.mallchat.common.chat.domain.enums.GroupRoleAPPEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.HotFlagEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.vo.request.*;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatMemberListResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.ChatRoomResp;
|
||||
import com.abin.mallchat.common.chat.domain.vo.response.MemberResp;
|
||||
import com.abin.mallchat.common.chat.service.ChatService;
|
||||
import com.abin.mallchat.common.chat.service.RoomAppService;
|
||||
import com.abin.mallchat.common.chat.service.RoomService;
|
||||
import com.abin.mallchat.common.chat.service.adapter.ChatAdapter;
|
||||
import com.abin.mallchat.common.chat.service.adapter.MemberAdapter;
|
||||
import com.abin.mallchat.common.chat.service.adapter.RoomAdapter;
|
||||
import com.abin.mallchat.common.chat.service.cache.*;
|
||||
import com.abin.mallchat.common.chat.service.strategy.msg.AbstractMsgHandler;
|
||||
import com.abin.mallchat.common.chat.service.strategy.msg.MsgHandlerFactory;
|
||||
import com.abin.mallchat.common.common.annotation.RedissonLock;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.common.common.event.GroupMemberAddEvent;
|
||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||
import com.abin.mallchat.common.user.dao.UserDao;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
import com.abin.mallchat.common.user.domain.enums.RoleEnum;
|
||||
import com.abin.mallchat.common.user.domain.enums.WSBaseResp;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||
import com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange;
|
||||
import com.abin.mallchat.common.user.service.IRoleService;
|
||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||
import com.abin.mallchat.common.user.service.cache.UserInfoCache;
|
||||
import com.abin.mallchat.common.user.service.impl.PushService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.redis.core.ZSetOperations;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
@Service
|
||||
public class RoomAppServiceImpl implements RoomAppService {
|
||||
|
||||
@Autowired
|
||||
private ContactDao contactDao;
|
||||
@Autowired
|
||||
private RoomCache roomCache;
|
||||
@Autowired
|
||||
private RoomGroupCache roomGroupCache;
|
||||
@Autowired
|
||||
private RoomFriendCache roomFriendCache;
|
||||
@Autowired
|
||||
private UserInfoCache userInfoCache;
|
||||
@Autowired
|
||||
private MessageDao messageDao;
|
||||
@Autowired
|
||||
private HotRoomCache hotRoomCache;
|
||||
@Autowired
|
||||
private UserCache userCache;
|
||||
@Autowired
|
||||
private GroupMemberDao groupMemberDao;
|
||||
@Autowired
|
||||
private UserDao userDao;
|
||||
@Autowired
|
||||
private ChatService chatService;
|
||||
@Autowired
|
||||
private IRoleService iRoleService;
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
@Autowired
|
||||
private RoomService roomService;
|
||||
@Autowired
|
||||
private GroupMemberCache groupMemberCache;
|
||||
@Autowired
|
||||
private PushService pushService;
|
||||
|
||||
@Override
|
||||
public CursorPageBaseResp<ChatRoomResp> getContactPage(CursorPageBaseReq request, Long uid) {
|
||||
//查出用户要展示的会话列表
|
||||
CursorPageBaseResp<Long> page;
|
||||
if (Objects.nonNull(uid)) {
|
||||
Double hotEnd = getCursorOrNull(request.getCursor());
|
||||
Double hotStart;
|
||||
//用户基础会话
|
||||
CursorPageBaseResp<Contact> contactPage = contactDao.getContactPage(uid, request);
|
||||
List<Long> baseRoomIds = contactPage.getList().stream().map(Contact::getRoomId).collect(Collectors.toList());
|
||||
hotStart = getCursorOrNull(contactPage.getCursor());
|
||||
//热门房间
|
||||
Set<ZSetOperations.TypedTuple<String>> typedTuples = hotRoomCache.getRoomRange(hotStart, hotEnd);
|
||||
List<Long> hotRoomIds = typedTuples.stream().map(ZSetOperations.TypedTuple::getValue).filter(Objects::nonNull).map(Long::parseLong).collect(Collectors.toList());
|
||||
baseRoomIds.addAll(hotRoomIds);
|
||||
//基础会话和热门房间合并
|
||||
page = CursorPageBaseResp.init(contactPage, baseRoomIds);
|
||||
} else {//用户未登录,只查全局房间
|
||||
CursorPageBaseResp<Pair<Long, Double>> roomCursorPage = hotRoomCache.getRoomCursorPage(request);
|
||||
List<Long> roomIds = roomCursorPage.getList().stream().map(Pair::getKey).collect(Collectors.toList());
|
||||
page = CursorPageBaseResp.init(roomCursorPage, roomIds);
|
||||
}
|
||||
//最后组装会话信息(名称,头像,未读数等)
|
||||
List<ChatRoomResp> result = buildContactResp(uid, page.getList());
|
||||
return CursorPageBaseResp.init(page, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatRoomResp getContactDetail(Long uid, Long roomId) {
|
||||
Room room = roomCache.get(roomId);
|
||||
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||
return buildContactResp(uid, Collections.singletonList(roomId)).get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemberResp getGroupDetail(Long uid, long roomId) {
|
||||
RoomGroup roomGroup = roomGroupCache.get(roomId);
|
||||
Room room = roomCache.get(roomId);
|
||||
AssertUtil.isNotEmpty(roomGroup, "roomId有误");
|
||||
Long onlineNum;
|
||||
if (isHotGroup(room)) {//热点群从redis取人数
|
||||
onlineNum = userCache.getOnlineNum();
|
||||
} else {
|
||||
List<Long> memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId());
|
||||
onlineNum = userDao.getOnlineCount(memberUidList).longValue();
|
||||
}
|
||||
GroupRoleAPPEnum groupRole = getGroupRole(uid, roomGroup, room);
|
||||
return MemberResp.builder()
|
||||
.avatar(roomGroup.getAvatar())
|
||||
.roomId(roomId)
|
||||
.groupName(roomGroup.getName())
|
||||
.onlineNum(onlineNum)
|
||||
.role(groupRole.getType())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CursorPageBaseResp<ChatMemberResp> getMemberPage(MemberReq request) {
|
||||
Room room = roomCache.get(request.getRoomId());
|
||||
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||
List<Long> memberUidList = null;
|
||||
if (isHotGroup(room)) {//全员群展示所有用户
|
||||
memberUidList = null;
|
||||
} else {//只展示房间内的群成员
|
||||
RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
|
||||
memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId());
|
||||
}
|
||||
return chatService.getMemberPage(memberUidList, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = "member", key = "'memberList.'+#request.roomId")
|
||||
public List<ChatMemberListResp> getMemberList(ChatMessageMemberReq request) {
|
||||
Room room = roomCache.get(request.getRoomId());
|
||||
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||
if (isHotGroup(room)) {//全员群展示所有用户100名
|
||||
List<User> memberList = userDao.getMemberList();
|
||||
return MemberAdapter.buildMemberList(memberList);
|
||||
} else {
|
||||
RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
|
||||
List<Long> memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId());
|
||||
Map<Long, User> batch = userInfoCache.getBatch(memberUidList);
|
||||
return MemberAdapter.buildMemberList(batch);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delMember(Long uid, MemberDelReq request) {
|
||||
Room room = roomCache.get(request.getRoomId());
|
||||
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||
RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
|
||||
AssertUtil.isNotEmpty(roomGroup, "房间号有误");
|
||||
GroupMember self = groupMemberDao.getMember(roomGroup.getId(), uid);
|
||||
AssertUtil.isNotEmpty(self, "您不是群管理");
|
||||
AssertUtil.isTrue(hasPower(self), "您不是群管理");
|
||||
GroupMember member = groupMemberDao.getMember(roomGroup.getId(), request.getUid());
|
||||
AssertUtil.isNotEmpty(self, "用户已经移除");
|
||||
groupMemberDao.removeById(member.getId());
|
||||
//发送移除事件告知群成员
|
||||
List<Long> memberUidList = groupMemberCache.getMemberUidList(roomGroup.getRoomId());
|
||||
WSBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), member.getUid());
|
||||
pushService.sendPushMsg(ws, memberUidList);
|
||||
groupMemberCache.evictMemberUidList(member.getId());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@RedissonLock(key = "#request.roomId")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void addMember(Long uid, MemberAddReq request) {
|
||||
Room room = roomCache.get(request.getRoomId());
|
||||
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||
AssertUtil.isFalse(isHotGroup(room), "全员群无需邀请好友");
|
||||
RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
|
||||
AssertUtil.isNotEmpty(roomGroup, "房间号有误");
|
||||
GroupMember self = groupMemberDao.getMember(roomGroup.getId(), uid);
|
||||
AssertUtil.isNotEmpty(self, "您不是群成员");
|
||||
List<Long> memberBatch = groupMemberDao.getMemberBatch(roomGroup.getId(), request.getUidList());
|
||||
Set<Long> existUid = new HashSet<>(memberBatch);
|
||||
List<Long> waitAddUidList = request.getUidList().stream().filter(a -> !existUid.contains(a)).collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(waitAddUidList)) {
|
||||
return;
|
||||
}
|
||||
List<GroupMember> groupMembers = MemberAdapter.buildMemberAdd(roomGroup.getId(), waitAddUidList);
|
||||
groupMemberDao.saveBatch(groupMembers);
|
||||
applicationEventPublisher.publishEvent(new GroupMemberAddEvent(this, roomGroup, groupMembers, uid));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Long addGroup(Long uid, GroupAddReq request) {
|
||||
RoomGroup roomGroup = roomService.createGroupRoom(uid);
|
||||
//批量保存群成员
|
||||
List<GroupMember> groupMembers = RoomAdapter.buildGroupMemberBatch(request.getUidList(), roomGroup.getId());
|
||||
groupMemberDao.saveBatch(groupMembers);
|
||||
//发送邀请加群消息==》触发每个人的会话
|
||||
applicationEventPublisher.publishEvent(new GroupMemberAddEvent(this, roomGroup, groupMembers, uid));
|
||||
return roomGroup.getRoomId();
|
||||
}
|
||||
|
||||
private boolean hasPower(GroupMember self) {
|
||||
return Objects.equals(self.getRole(), GroupRoleEnum.LEADER.getType())
|
||||
|| Objects.equals(self.getRole(), GroupRoleEnum.MANAGER.getType())
|
||||
|| iRoleService.hasPower(self.getUid(), RoleEnum.ADMIN);
|
||||
|
||||
}
|
||||
|
||||
private GroupRoleAPPEnum getGroupRole(Long uid, RoomGroup roomGroup, Room room) {
|
||||
GroupMember member = Objects.isNull(uid) ? null : groupMemberDao.getMember(roomGroup.getId(), uid);
|
||||
if (Objects.nonNull(member)) {
|
||||
return GroupRoleAPPEnum.of(member.getRole());
|
||||
} else if (isHotGroup(room)) {
|
||||
return GroupRoleAPPEnum.MEMBER;
|
||||
} else {
|
||||
return GroupRoleAPPEnum.REMOVE;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHotGroup(Room room) {
|
||||
return HotFlagEnum.YES.getType().equals(room.getHotFlag());
|
||||
}
|
||||
|
||||
private List<Contact> buildContact(List<Pair<Long, Double>> list, Long uid) {
|
||||
List<Long> roomIds = list.stream().map(Pair::getKey).collect(Collectors.toList());
|
||||
Map<Long, Room> batch = roomCache.getBatch(roomIds);
|
||||
Map<Long, Contact> contactMap = new HashMap<>();
|
||||
if (Objects.nonNull(uid)) {
|
||||
List<Contact> byRoomIds = contactDao.getByRoomIds(roomIds, uid);
|
||||
contactMap = byRoomIds.stream().collect(Collectors.toMap(Contact::getRoomId, Function.identity()));
|
||||
}
|
||||
Map<Long, Contact> finalContactMap = contactMap;
|
||||
return list.stream().map(pair -> {
|
||||
Long roomId = pair.getKey();
|
||||
Contact contact = finalContactMap.get(roomId);
|
||||
if (Objects.isNull(contact)) {
|
||||
contact = new Contact();
|
||||
contact.setRoomId(pair.getKey());
|
||||
Room room = batch.get(roomId);
|
||||
contact.setLastMsgId(room.getLastMsgId());
|
||||
}
|
||||
contact.setActiveTime(new Date(pair.getValue().longValue()));
|
||||
return contact;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Double getCursorOrNull(String cursor) {
|
||||
return Optional.ofNullable(cursor).map(Double::parseDouble).orElse(null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<ChatRoomResp> buildContactResp(Long uid, List<Long> roomIds) {
|
||||
//表情和头像
|
||||
Map<Long, RoomBaseInfo> roomBaseInfoMap = getRoomBaseInfoMap(roomIds, uid);
|
||||
//最后一条消息
|
||||
List<Long> msgIds = roomBaseInfoMap.values().stream().map(RoomBaseInfo::getLastMsgId).collect(Collectors.toList());
|
||||
List<Message> messages = CollectionUtil.isEmpty(msgIds) ? new ArrayList<>() : messageDao.listByIds(msgIds);
|
||||
Map<Long, Message> msgMap = messages.stream().collect(Collectors.toMap(Message::getId, Function.identity()));
|
||||
Map<Long, User> lastMsgUidMap = userInfoCache.getBatch(messages.stream().map(Message::getFromUid).collect(Collectors.toList()));
|
||||
//消息未读数
|
||||
Map<Long, Integer> unReadCountMap = getUnReadCountMap(uid, roomIds);
|
||||
return roomBaseInfoMap.values().stream().map(room -> {
|
||||
ChatRoomResp resp = new ChatRoomResp();
|
||||
RoomBaseInfo roomBaseInfo = roomBaseInfoMap.get(room.getRoomId());
|
||||
resp.setAvatar(roomBaseInfo.getAvatar());
|
||||
resp.setRoomId(room.getRoomId());
|
||||
resp.setActiveTime(room.getActiveTime());
|
||||
resp.setHot_Flag(roomBaseInfo.getHotFlag());
|
||||
resp.setType(roomBaseInfo.getType());
|
||||
resp.setName(roomBaseInfo.getName());
|
||||
Message message = msgMap.get(room.getLastMsgId());
|
||||
if (Objects.nonNull(message)) {
|
||||
AbstractMsgHandler strategyNoNull = MsgHandlerFactory.getStrategyNoNull(message.getType());
|
||||
resp.setText(lastMsgUidMap.get(message.getFromUid()).getName() + ":" + strategyNoNull.showContactMsg(message));
|
||||
}
|
||||
resp.setUnreadCount(unReadCountMap.getOrDefault(room.getRoomId(), 0));
|
||||
return resp;
|
||||
}).sorted(Comparator.comparing(ChatRoomResp::getActiveTime).reversed())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取未读数
|
||||
*/
|
||||
private Map<Long, Integer> getUnReadCountMap(Long uid, List<Long> roomIds) {
|
||||
if (Objects.isNull(uid)) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
List<Contact> contacts = contactDao.getByRoomIds(roomIds, uid);
|
||||
return contacts.parallelStream()
|
||||
.map(contact -> Pair.of(contact.getRoomId(), messageDao.getUnReadCount(contact.getRoomId(), contact.getReadTime())))
|
||||
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
|
||||
}
|
||||
|
||||
private Map<Long, User> getFriendRoomMap(List<Long> roomIds, Long uid) {
|
||||
if (CollectionUtil.isEmpty(roomIds)) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
Map<Long, RoomFriend> roomFriendMap = roomFriendCache.getBatch(roomIds);
|
||||
Set<Long> friendUidSet = ChatAdapter.getFriendUidSet(roomFriendMap.values(), uid);
|
||||
Map<Long, User> userBatch = userInfoCache.getBatch(new ArrayList<>(friendUidSet));
|
||||
return roomFriendMap.values()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(RoomFriend::getRoomId, roomFriend -> {
|
||||
Long friendUid = ChatAdapter.getFriendUid(roomFriend, uid);
|
||||
return userBatch.get(friendUid);
|
||||
}));
|
||||
}
|
||||
|
||||
private Map<Long, RoomBaseInfo> getRoomBaseInfoMap(List<Long> roomIds, Long uid) {
|
||||
Map<Long, Room> roomMap = roomCache.getBatch(roomIds);
|
||||
//房间根据好友和群组类型分组
|
||||
Map<Integer, List<Long>> groupRoomIdMap = roomMap.values().stream().collect(Collectors.groupingBy(Room::getType,
|
||||
Collectors.mapping(Room::getId, Collectors.toList())));
|
||||
//获取群组信息
|
||||
List<Long> groupRoomId = groupRoomIdMap.get(RoomTypeEnum.GROUP.getType());
|
||||
Map<Long, RoomGroup> roomInfoBatch = roomGroupCache.getBatch(groupRoomId);
|
||||
//获取好友信息
|
||||
List<Long> friendRoomId = groupRoomIdMap.get(RoomTypeEnum.FRIEND.getType());
|
||||
Map<Long, User> friendRoomMap = getFriendRoomMap(friendRoomId, uid);
|
||||
|
||||
return roomMap.values().stream().map(room -> {
|
||||
RoomBaseInfo roomBaseInfo = new RoomBaseInfo();
|
||||
roomBaseInfo.setRoomId(room.getId());
|
||||
roomBaseInfo.setType(room.getType());
|
||||
roomBaseInfo.setHotFlag(room.getHotFlag());
|
||||
roomBaseInfo.setLastMsgId(room.getLastMsgId());
|
||||
roomBaseInfo.setActiveTime(room.getActiveTime());
|
||||
if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.GROUP) {
|
||||
RoomGroup roomGroup = roomInfoBatch.get(room.getId());
|
||||
roomBaseInfo.setName(roomGroup.getName());
|
||||
roomBaseInfo.setAvatar(roomGroup.getAvatar());
|
||||
} else if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.FRIEND) {
|
||||
User user = friendRoomMap.get(room.getId());
|
||||
roomBaseInfo.setName(user.getName());
|
||||
roomBaseInfo.setAvatar(user.getAvatar());
|
||||
}
|
||||
return roomBaseInfo;
|
||||
}).collect(Collectors.toMap(RoomBaseInfo::getRoomId, Function.identity()));
|
||||
}
|
||||
|
||||
private void fillRoomActive(Long uid, Map<Long, Room> roomMap) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.abin.mallchat.common.chat.service.impl;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.GroupMemberDao;
|
||||
import com.abin.mallchat.common.chat.dao.RoomDao;
|
||||
import com.abin.mallchat.common.chat.dao.RoomFriendDao;
|
||||
import com.abin.mallchat.common.chat.dao.RoomGroupDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.GroupMember;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||
import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum;
|
||||
import com.abin.mallchat.common.chat.service.RoomService;
|
||||
import com.abin.mallchat.common.chat.service.adapter.ChatAdapter;
|
||||
import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum;
|
||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
import com.abin.mallchat.common.user.service.cache.UserInfoCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
@Service
|
||||
public class RoomServiceImpl implements RoomService {
|
||||
|
||||
@Autowired
|
||||
private RoomFriendDao roomFriendDao;
|
||||
@Autowired
|
||||
private RoomDao roomDao;
|
||||
@Autowired
|
||||
private GroupMemberDao groupMemberDao;
|
||||
@Autowired
|
||||
private UserInfoCache userInfoCache;
|
||||
@Autowired
|
||||
private RoomGroupDao roomGroupDao;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public RoomFriend createFriendRoom(List<Long> uidList) {
|
||||
AssertUtil.isNotEmpty(uidList, "房间创建失败,好友数量不对");
|
||||
AssertUtil.equal(uidList.size(), 2, "房间创建失败,好友数量不对");
|
||||
String key = ChatAdapter.generateRoomKey(uidList);
|
||||
|
||||
RoomFriend roomFriend = roomFriendDao.getByKey(key);
|
||||
if (Objects.nonNull(roomFriend)) { //如果存在房间就恢复,适用于恢复好友场景
|
||||
restoreRoomIfNeed(roomFriend);
|
||||
} else {//新建房间
|
||||
Room room = createRoom(RoomTypeEnum.FRIEND);
|
||||
roomFriend = createFriendRoom(room.getId(), uidList);
|
||||
}
|
||||
return roomFriend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableFriendRoom(List<Long> uidList) {
|
||||
AssertUtil.isNotEmpty(uidList, "房间创建失败,好友数量不对");
|
||||
AssertUtil.equal(uidList.size(), 2, "房间创建失败,好友数量不对");
|
||||
String key = ChatAdapter.generateRoomKey(uidList);
|
||||
roomFriendDao.disableRoom(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public RoomGroup createGroupRoom(Long uid) {
|
||||
List<GroupMember> selfGroup = groupMemberDao.getSelfGroup(uid);
|
||||
AssertUtil.isEmpty(selfGroup, "每个人只能创建一个群");
|
||||
User user = userInfoCache.get(uid);
|
||||
Room room = createRoom(RoomTypeEnum.GROUP);
|
||||
//插入群
|
||||
RoomGroup roomGroup = ChatAdapter.buildGroupRoom(user, room.getId());
|
||||
roomGroupDao.save(roomGroup);
|
||||
//插入群主
|
||||
GroupMember leader = GroupMember.builder()
|
||||
.role(GroupRoleEnum.LEADER.getType())
|
||||
.groupId(roomGroup.getId())
|
||||
.uid(uid)
|
||||
.build();
|
||||
groupMemberDao.save(leader);
|
||||
return roomGroup;
|
||||
}
|
||||
|
||||
private RoomFriend createFriendRoom(Long roomId, List<Long> uidList) {
|
||||
RoomFriend insert = ChatAdapter.buildFriendRoom(roomId, uidList);
|
||||
roomFriendDao.save(insert);
|
||||
return insert;
|
||||
}
|
||||
|
||||
private Room createRoom(RoomTypeEnum typeEnum) {
|
||||
Room insert = ChatAdapter.buildRoom(typeEnum);
|
||||
roomDao.save(insert);
|
||||
return insert;
|
||||
}
|
||||
|
||||
private void restoreRoomIfNeed(RoomFriend room) {
|
||||
if (Objects.equals(room.getStatus(), NormalOrNoEnum.NOT_NORMAL.getStatus())) {
|
||||
roomFriendDao.restoreRoom(room.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.abin.mallchat.common.chat.service.impl;
|
||||
|
||||
import cn.hutool.core.thread.NamedThreadFactory;
|
||||
import com.abin.mallchat.common.chat.service.WeChatMsgOperationService;
|
||||
import com.abin.mallchat.common.common.domain.dto.FrequencyControlDTO;
|
||||
import com.abin.mallchat.common.common.exception.FrequencyControlException;
|
||||
import com.abin.mallchat.common.common.handler.GlobalUncaughtExceptionHandler;
|
||||
import com.abin.mallchat.common.common.service.frequencycontrol.FrequencyControlUtil;
|
||||
import com.abin.mallchat.common.user.domain.entity.User;
|
||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
|
||||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.abin.mallchat.common.common.service.frequencycontrol.FrequencyControlStrategyFactory.TOTAL_COUNT_WITH_IN_FIX_TIME_FREQUENCY_CONTROLLER;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class WeChatMsgOperationServiceImpl implements WeChatMsgOperationService {
|
||||
|
||||
private static final ExecutorService executor = new ThreadPoolExecutor(1, 10, 3000L,
|
||||
TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(20),
|
||||
new NamedThreadFactory("wechat-operation-thread", null, false,
|
||||
GlobalUncaughtExceptionHandler.getInstance()));
|
||||
|
||||
// at消息的微信推送模板id
|
||||
private final String atMsgPublishTemplateId = "Xd7sWPZsuWa0UmpvLaZPvaJVjNj1KjEa0zLOm5_Z7IU";
|
||||
|
||||
private final String WE_CHAT_MSG_COLOR = "#A349A4";
|
||||
|
||||
@Autowired
|
||||
private UserCache userCache;
|
||||
|
||||
@Autowired
|
||||
WxMpService wxMpService;
|
||||
|
||||
@Override
|
||||
public void publishChatMsgToWeChatUser(long senderUid, List<Long> receiverUidList, String msg) {
|
||||
User sender = userCache.getUserInfo(senderUid);
|
||||
Set uidSet = new HashSet();
|
||||
uidSet.addAll(receiverUidList);
|
||||
Map<Long, User> userMap = userCache.getUserInfoBatch(uidSet);
|
||||
userMap.values().forEach(user -> {
|
||||
if (Objects.nonNull(user.getOpenId())) {
|
||||
executor.execute(() -> {
|
||||
WxMpTemplateMessage msgTemplate = getAtMsgTemplate(sender, user.getOpenId(), msg);
|
||||
publishTemplateMsgCheckLimit(msgTemplate);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void publishTemplateMsgCheckLimit(WxMpTemplateMessage msgTemplate) {
|
||||
try {
|
||||
FrequencyControlDTO frequencyControlDTO = new FrequencyControlDTO();
|
||||
frequencyControlDTO.setKey("TemplateMsg:" + msgTemplate.getToUser());
|
||||
frequencyControlDTO.setUnit(TimeUnit.HOURS);
|
||||
frequencyControlDTO.setCount(1);
|
||||
frequencyControlDTO.setTime(1);
|
||||
FrequencyControlUtil.executeWithFrequencyControl(TOTAL_COUNT_WITH_IN_FIX_TIME_FREQUENCY_CONTROLLER, frequencyControlDTO,
|
||||
() -> publishTemplateMsg(msgTemplate));
|
||||
} catch (FrequencyControlException e) {
|
||||
log.info("wx push limit openid:{}", msgTemplate.getToUser());
|
||||
} catch (Throwable e) {
|
||||
log.error("wx push error openid:{}", msgTemplate.getToUser());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 构造微信模板消息
|
||||
*/
|
||||
private WxMpTemplateMessage getAtMsgTemplate(User sender, String openId, String msg) {
|
||||
return WxMpTemplateMessage.builder()
|
||||
.toUser(openId)
|
||||
.templateId(atMsgPublishTemplateId)
|
||||
.data(generateAtMsgData(sender, msg))
|
||||
.build();
|
||||
}
|
||||
|
||||
/*
|
||||
* 构造微信消息模板的数据
|
||||
*/
|
||||
private List<WxMpTemplateData> generateAtMsgData(User sender, String msg) {
|
||||
List dataList = new ArrayList<WxMpTemplateData>();
|
||||
// todo: 没有消息模板,暂不实现
|
||||
dataList.add(new WxMpTemplateData("name", sender.getName(), WE_CHAT_MSG_COLOR));
|
||||
dataList.add(new WxMpTemplateData("content", msg, WE_CHAT_MSG_COLOR));
|
||||
return dataList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送微信模板消息
|
||||
*
|
||||
* @param templateMsg 微信模板消息
|
||||
*/
|
||||
protected void publishTemplateMsg(WxMpTemplateMessage templateMsg) {
|
||||
// WxMpTemplateMsgService wxMpTemplateMsgService = wxMpService.getTemplateMsgService();todo 等审核通过
|
||||
// try {
|
||||
// wxMpTemplateMsgService.sendTemplateMsg(templateMsg);
|
||||
// } catch (WxErrorException e) {
|
||||
// log.error("publish we chat msg failed! open id is {}, msg is {}.",
|
||||
// templateMsg.getToUser(), JsonUtils.toStr(templateMsg.getData()));
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.abin.mallchat.common.chat.service.strategy.mark;
|
||||
|
||||
import com.abin.mallchat.common.chat.dao.MessageMarkDao;
|
||||
import com.abin.mallchat.common.chat.domain.dto.ChatMessageMarkDTO;
|
||||
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageMarkActTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
|
||||
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
|
||||
import com.abin.mallchat.common.common.event.MessageMarkEvent;
|
||||
import com.abin.mallchat.common.common.exception.BusinessException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Description: 消息标记抽象类
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-05-30
|
||||
*/
|
||||
public abstract class AbstractMsgMarkStrategy {
|
||||
@Autowired
|
||||
private MessageMarkDao messageMarkDao;
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
protected abstract MessageMarkTypeEnum getTypeEnum();
|
||||
|
||||
@Transactional
|
||||
public void mark(Long uid, Long msgId) {
|
||||
doMark(uid, msgId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void unMark(Long uid, Long msgId) {
|
||||
doUnMark(uid, msgId);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
MsgMarkFactory.register(getTypeEnum().getType(), this);
|
||||
}
|
||||
|
||||
protected void doMark(Long uid, Long msgId) {
|
||||
exec(uid, msgId, MessageMarkActTypeEnum.MARK);
|
||||
}
|
||||
|
||||
protected void doUnMark(Long uid, Long msgId) {
|
||||
exec(uid, msgId, MessageMarkActTypeEnum.UN_MARK);
|
||||
}
|
||||
|
||||
protected void exec(Long uid, Long msgId, MessageMarkActTypeEnum actTypeEnum) {
|
||||
Integer markType = getTypeEnum().getType();
|
||||
Integer actType = actTypeEnum.getType();
|
||||
MessageMark oldMark = messageMarkDao.get(uid, msgId, markType);
|
||||
if (Objects.isNull(oldMark) && actTypeEnum == MessageMarkActTypeEnum.UN_MARK) {
|
||||
//取消的类型,数据库一定有记录,没有就直接跳过操作
|
||||
return;
|
||||
}
|
||||
//插入一条新消息,或者修改一条消息
|
||||
MessageMark insertOrUpdate = MessageMark.builder()
|
||||
.id(Optional.ofNullable(oldMark).map(MessageMark::getId).orElse(null))
|
||||
.uid(uid)
|
||||
.msgId(msgId)
|
||||
.type(markType)
|
||||
.status(transformAct(actType))
|
||||
.build();
|
||||
boolean modify = messageMarkDao.saveOrUpdate(insertOrUpdate);
|
||||
if (modify) {
|
||||
//修改成功才发布消息标记事件
|
||||
ChatMessageMarkDTO dto = new ChatMessageMarkDTO(uid, msgId, markType, actType);
|
||||
applicationEventPublisher.publishEvent(new MessageMarkEvent(this, dto));
|
||||
}
|
||||
}
|
||||
|
||||
private Integer transformAct(Integer actType) {
|
||||
if (actType == 1) {
|
||||
return YesOrNoEnum.NO.getStatus();
|
||||
} else if (actType == 2) {
|
||||
return YesOrNoEnum.YES.getStatus();
|
||||
}
|
||||
throw new BusinessException("动作类型 1确认 2取消");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.abin.mallchat.common.chat.service.strategy.mark;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Description: 点踩标记策略类
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-05-30
|
||||
*/
|
||||
@Component
|
||||
public class DisLikeStrategy extends AbstractMsgMarkStrategy {
|
||||
|
||||
@Override
|
||||
protected MessageMarkTypeEnum getTypeEnum() {
|
||||
return MessageMarkTypeEnum.DISLIKE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doMark(Long uid, Long msgId) {
|
||||
super.doMark(uid, msgId);
|
||||
//同时取消点赞的动作
|
||||
MsgMarkFactory.getStrategyNoNull(MessageMarkTypeEnum.LIKE.getType()).unMark(uid, msgId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.abin.mallchat.common.chat.service.strategy.mark;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Description: 点赞标记策略类
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-05-30
|
||||
*/
|
||||
@Component
|
||||
public class LikeStrategy extends AbstractMsgMarkStrategy {
|
||||
|
||||
@Override
|
||||
protected MessageMarkTypeEnum getTypeEnum() {
|
||||
return MessageMarkTypeEnum.LIKE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doMark(Long uid, Long msgId) {
|
||||
super.doMark(uid, msgId);
|
||||
//同时取消点踩的动作
|
||||
MsgMarkFactory.getStrategyNoNull(MessageMarkTypeEnum.DISLIKE.getType()).unMark(uid, msgId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.abin.mallchat.common.chat.service.strategy.mark;
|
||||
|
||||
import com.abin.mallchat.common.common.exception.CommonErrorEnum;
|
||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Description: 消息标记策略工厂
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-05-30
|
||||
*/
|
||||
public class MsgMarkFactory {
|
||||
private static final Map<Integer, AbstractMsgMarkStrategy> STRATEGY_MAP = new HashMap<>();
|
||||
|
||||
public static void register(Integer markType, AbstractMsgMarkStrategy strategy) {
|
||||
STRATEGY_MAP.put(markType, strategy);
|
||||
}
|
||||
|
||||
public static AbstractMsgMarkStrategy getStrategyNoNull(Integer markType) {
|
||||
AbstractMsgMarkStrategy strategy = STRATEGY_MAP.get(markType);
|
||||
AssertUtil.isNotEmpty(strategy, CommonErrorEnum.PARAM_VALID);
|
||||
return strategy;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user