mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-13 21:53:41 +08:00
fix:联系人优化
This commit is contained in:
@@ -28,7 +28,7 @@ CREATE TABLE `user_apply` (
|
||||
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `uniq_target_id_uid` (`target_id`,`uid`) USING BTREE,
|
||||
KEY `idx_target_id_uid_status` (`target_id`,`uid`,`status`) USING BTREE,
|
||||
KEY `idx_target_id` (`target_id`) USING BTREE,
|
||||
KEY `idx_create_time` (`create_time`) USING BTREE,
|
||||
KEY `idx_update_time` (`update_time`) USING BTREE
|
||||
@@ -38,10 +38,11 @@ CREATE TABLE `user_friend` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`uid` bigint(20) NOT NULL COMMENT 'uid',
|
||||
`friend_uid` bigint(20) NOT NULL COMMENT '好友uid',
|
||||
`delete_status` int(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除(0-正常,1-删除)',
|
||||
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `uniq_uid_friend_uid` (`uid`,`friend_uid`) USING BTREE,
|
||||
KEY `idx_uid_friend_uid` (`uid`,`friend_uid`) USING BTREE,
|
||||
KEY `idx_create_time` (`create_time`) USING BTREE,
|
||||
KEY `idx_update_time` (`update_time`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户联系人表';
|
||||
@@ -50,7 +51,7 @@ CREATE TABLE `group_member` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`room_id` bigint(20) NOT NULL COMMENT '房间id',
|
||||
`uid` bigint(20) NOT NULL COMMENT '成员uid',
|
||||
`type` int(11) NOT NULL COMMENT '成员类型 1群主 2管理员 3普通成员',
|
||||
`role` int(11) NOT NULL COMMENT '成员角色 1群主 2管理员 3普通成员',
|
||||
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.abin.mallchat.common.chat.controller;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 会话列表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/contact")
|
||||
public class ContactController {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.abin.mallchat.common.chat.controller;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 群成员表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/groupMember")
|
||||
public class GroupMemberController {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.abin.mallchat.common.chat.controller;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 房间表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/room")
|
||||
public class RoomController {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
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.chat.service.IContactService;
|
||||
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;
|
||||
|
||||
@@ -15,6 +18,57 @@ import org.springframework.stereotype.Service;
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Service
|
||||
public class ContactDao extends ServiceImpl<ContactMapper, Contact> implements IContactService {
|
||||
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())
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ 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.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
@@ -20,11 +19,9 @@ import org.springframework.stereotype.Service;
|
||||
*/
|
||||
@Service
|
||||
public class MessageDao extends ServiceImpl<MessageMapper, Message> {
|
||||
@Autowired
|
||||
private CursorUtils cursorUtils;
|
||||
|
||||
public CursorPageBaseResp<Message> getCursorPage(Long roomId, CursorPageBaseReq request) {
|
||||
return cursorUtils.getCursorPageByMysql(this, request, wrapper -> {
|
||||
return CursorUtils.getCursorPageByMysql(this, request, wrapper -> {
|
||||
wrapper.eq(Message::getRoomId, roomId);
|
||||
wrapper.eq(Message::getStatus, MessageStatusEnum.NORMAL.getStatus());
|
||||
}, Message::getId);
|
||||
|
||||
@@ -2,7 +2,7 @@ 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.abin.mallchat.common.chat.service.IRoomService;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -15,6 +15,6 @@ import org.springframework.stereotype.Service;
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Service
|
||||
public class RoomDao extends ServiceImpl<RoomMapper, Room> implements IRoomService {
|
||||
public class RoomDao extends ServiceImpl<RoomMapper, Room> implements IService<Room> {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
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::getKey, key).one();
|
||||
}
|
||||
|
||||
public void restoreRoom(Long id) {
|
||||
lambdaUpdate()
|
||||
.eq(RoomFriend::getId, id)
|
||||
.set(RoomFriend::getStatus, NormalOrNoEnum.NORMAL.getStatus())
|
||||
.update();
|
||||
}
|
||||
|
||||
public List<RoomFriend> listByRoomIds(List<Long> roomIds) {
|
||||
return lambdaQuery()
|
||||
.eq(RoomFriend::getRoomId, roomIds)
|
||||
.list();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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,19 @@
|
||||
package com.abin.mallchat.common.chat.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -38,22 +38,10 @@ public class Contact implements Serializable {
|
||||
private Long uid;
|
||||
|
||||
/**
|
||||
* 聊天类型 1单聊 2普通群聊
|
||||
* 房间id
|
||||
*/
|
||||
@TableField("type")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 是否全员展示 0否 1是
|
||||
*/
|
||||
@TableField("hot_flag")
|
||||
private Integer hotFlag;
|
||||
|
||||
/**
|
||||
* 聊天对象type=1:uid,type=2:房间id
|
||||
*/
|
||||
@TableField("target_id")
|
||||
private Long targetId;
|
||||
@TableField("room_id")
|
||||
private Long roomId;
|
||||
|
||||
/**
|
||||
* 阅读到的时间
|
||||
@@ -67,6 +55,12 @@ public class Contact implements Serializable {
|
||||
@TableField("active_time")
|
||||
private LocalDateTime activeTime;
|
||||
|
||||
/**
|
||||
* 最后一条消息id
|
||||
*/
|
||||
@TableField("last_msg_id")
|
||||
private Long lastMsgId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
|
||||
@@ -44,10 +44,10 @@ public class GroupMember implements Serializable {
|
||||
private Long uid;
|
||||
|
||||
/**
|
||||
* 成员类型 1群主 2管理员 3普通成员
|
||||
* 成员角色1群主 2管理员 3普通成员
|
||||
*/
|
||||
@TableField("type")
|
||||
private Integer type;
|
||||
@TableField("role")
|
||||
private Integer role;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.time.LocalDateTime;
|
||||
public class Room implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@@ -32,25 +31,15 @@ public class Room implements Serializable {
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 群名称
|
||||
*/
|
||||
@TableField("name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 群头像
|
||||
*/
|
||||
@TableField("avatar")
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 房间类型 1群聊
|
||||
* 房间类型 1群聊 2单聊
|
||||
*/
|
||||
@TableField("type")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 是否全员展示 0否 1是
|
||||
*
|
||||
* @see com.abin.mallchat.common.chat.domain.enums.HotFlagEnum
|
||||
*/
|
||||
@TableField("hot_flag")
|
||||
private Integer hotFlag;
|
||||
|
||||
@@ -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.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <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("key")
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 房间状态 0正常 1禁用(删好友了禁用)
|
||||
*/
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private LocalDateTime 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.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <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 LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -16,17 +16,17 @@ import java.util.stream.Collectors;
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum RoomTypeEnum {
|
||||
GROUP(1, "大群聊"),
|
||||
BOILING(2, "沸点"),
|
||||
GROUP(1, "群聊"),
|
||||
FRIEND(2, "单聊"),
|
||||
;
|
||||
|
||||
private final Integer status;
|
||||
private final Integer type;
|
||||
private final String desc;
|
||||
|
||||
private static Map<Integer, RoomTypeEnum> cache;
|
||||
|
||||
static {
|
||||
cache = Arrays.stream(RoomTypeEnum.values()).collect(Collectors.toMap(RoomTypeEnum::getStatus, Function.identity()));
|
||||
cache = Arrays.stream(RoomTypeEnum.values()).collect(Collectors.toMap(RoomTypeEnum::getType, Function.identity()));
|
||||
}
|
||||
|
||||
public static RoomTypeEnum of(Integer type) {
|
||||
|
||||
@@ -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,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,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);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 会话列表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
public interface IContactService extends IService<Contact> {
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 房间表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
public interface IRoomService extends IService<Room> {
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.WxMsg;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 微信消息表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* @since 2023-05-16
|
||||
*/
|
||||
public interface IWxMsgService extends IService<WxMsg> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.abin.mallchat.common.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
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.enums.HotFlagEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum;
|
||||
import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum;
|
||||
|
||||
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.setKey(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();
|
||||
}
|
||||
}
|
||||
46
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomCache.java
vendored
Normal file
46
mallchat-common/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()));
|
||||
}
|
||||
}
|
||||
40
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomFriendCache.java
vendored
Normal file
40
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomFriendCache.java
vendored
Normal file
@@ -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()));
|
||||
}
|
||||
}
|
||||
40
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomGroupCache.java
vendored
Normal file
40
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomGroupCache.java
vendored
Normal file
@@ -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 groupId) {
|
||||
return RedisKey.getKey(RedisKey.GROUP_INFO_STRING, groupId);
|
||||
}
|
||||
|
||||
@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,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);
|
||||
return readInfoDTO;
|
||||
}).collect(Collectors.toMap(MsgReadInfoDTO::getMsgId, Function.identity()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.abin.mallchat.common.chat.service.impl;
|
||||
|
||||
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.chat.domain.entity.RoomFriend;
|
||||
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 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;
|
||||
|
||||
@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.GROUP);
|
||||
roomFriend = createFriendRoom(room.getId(), uidList);
|
||||
}
|
||||
return roomFriend;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,16 @@ public class RedisKey {
|
||||
*/
|
||||
public static final String USER_INFO_STRING = "userInfo:uid_%d";
|
||||
|
||||
/**
|
||||
* 房间详情
|
||||
*/
|
||||
public static final String ROOM_INFO_STRING = "roomInfo:roomId_%d";
|
||||
|
||||
/**
|
||||
* 群组详情
|
||||
*/
|
||||
public static final String GROUP_INFO_STRING = "groupInfo:roomId_%d";
|
||||
|
||||
/**
|
||||
* 用户token存放
|
||||
*/
|
||||
|
||||
@@ -36,13 +36,13 @@ public class PageBaseResp<T> {
|
||||
private List<T> list;
|
||||
|
||||
|
||||
public static PageBaseResp empty() {
|
||||
PageBaseResp r = new PageBaseResp();
|
||||
public static <T> PageBaseResp<T> empty() {
|
||||
PageBaseResp<T> r = new PageBaseResp<>();
|
||||
r.setPageNo(1);
|
||||
r.setPageSize(0);
|
||||
r.setIsLast(true);
|
||||
r.setTotalRecords(0L);
|
||||
r.setList(new ArrayList());
|
||||
r.setList(new ArrayList<>());
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.abin.mallchat.common.common.event;
|
||||
|
||||
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
||||
import lombok.Getter;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
@Getter
|
||||
public class UserApplyEvent extends ApplicationEvent {
|
||||
private UserApply userApply;
|
||||
|
||||
public UserApplyEvent(Object source, UserApply userApply) {
|
||||
super(source);
|
||||
this.userApply = userApply;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,9 @@ public abstract class AbstractRedisStringCache<IN, OUT> implements BatchCache<IN
|
||||
|
||||
@Override
|
||||
public Map<IN, OUT> getBatch(List<IN> req) {
|
||||
if (CollectionUtil.isEmpty(req)) {//防御性编程
|
||||
return new HashMap<>();
|
||||
}
|
||||
req = req.stream().distinct().collect(Collectors.toList());
|
||||
List<String> keys = req.stream().map(this::getKey).collect(Collectors.toList());
|
||||
List<OUT> valueList = RedisUtils.mget(keys, outClass);
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.springframework.data.redis.core.ZSetOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -24,10 +23,9 @@ import java.util.stream.Collectors;
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-03-28
|
||||
*/
|
||||
@Component
|
||||
public class CursorUtils {
|
||||
|
||||
public <T> CursorPageBaseResp<Pair<T, Double>> getCursorPageByRedis(CursorPageBaseReq cursorPageBaseReq, String redisKey, Function<String, T> typeConvert) {
|
||||
public static <T> CursorPageBaseResp<Pair<T, Double>> getCursorPageByRedis(CursorPageBaseReq cursorPageBaseReq, String redisKey, Function<String, T> typeConvert) {
|
||||
Set<ZSetOperations.TypedTuple<String>> typedTuples;
|
||||
if (StrUtil.isBlank(cursorPageBaseReq.getCursor())) {//第一次
|
||||
typedTuples = RedisUtils.zReverseRangeWithScores(redisKey, cursorPageBaseReq.getPageSize());
|
||||
@@ -47,7 +45,7 @@ public class CursorUtils {
|
||||
return new CursorPageBaseResp<>(cursor, isLast, result);
|
||||
}
|
||||
|
||||
public <T> CursorPageBaseResp<T> getCursorPageByMysql(IService<T> mapper, CursorPageBaseReq request, Consumer<LambdaQueryWrapper<T>> initWrapper, SFunction<T, ?> cursorColumn) {
|
||||
public static <T> CursorPageBaseResp<T> getCursorPageByMysql(IService<T> mapper, CursorPageBaseReq request, Consumer<LambdaQueryWrapper<T>> initWrapper, SFunction<T, ?> cursorColumn) {
|
||||
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
|
||||
initWrapper.accept(wrapper);
|
||||
if (StrUtil.isNotBlank(request.getCursor())) {
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
package com.abin.mallchat.common.user.dao;
|
||||
|
||||
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
||||
import com.abin.mallchat.common.user.domain.enums.ApplyStatusEnum;
|
||||
import com.abin.mallchat.common.user.domain.enums.ApplyTypeEnum;
|
||||
import com.abin.mallchat.common.user.mapper.UserApplyMapper;
|
||||
import com.abin.mallchat.common.user.service.IUserApplyService;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyReadStatusEnum.READ;
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyReadStatusEnum.UNREAD;
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyStatusEnum.AGREE;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户申请表 服务实现类
|
||||
@@ -15,6 +24,42 @@ import org.springframework.stereotype.Service;
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Service
|
||||
public class UserApplyDao extends ServiceImpl<UserApplyMapper, UserApply> implements IUserApplyService {
|
||||
public class UserApplyDao extends ServiceImpl<UserApplyMapper, UserApply> {
|
||||
|
||||
public UserApply getFriendApproving(Long uid, Long targetUid) {
|
||||
return lambdaQuery().eq(UserApply::getUid, uid)
|
||||
.eq(UserApply::getTargetId, targetUid)
|
||||
.eq(UserApply::getStatus, ApplyStatusEnum.WAIT_APPROVAL)
|
||||
.eq(UserApply::getType, ApplyTypeEnum.ADD_FRIEND.getCode())
|
||||
.one();
|
||||
}
|
||||
|
||||
public Integer getUnReadCount(Long targetId) {
|
||||
return lambdaQuery().eq(UserApply::getTargetId, targetId)
|
||||
.eq(UserApply::getReadStatus, UNREAD.getCode())
|
||||
.count();
|
||||
}
|
||||
|
||||
public IPage<UserApply> FriendApplyPage(Long uid, Page page) {
|
||||
return lambdaQuery()
|
||||
.eq(UserApply::getTargetId, uid)
|
||||
.eq(UserApply::getType, ApplyTypeEnum.ADD_FRIEND.getCode())
|
||||
.orderByAsc(UserApply::getCreateTime)
|
||||
.page(page);
|
||||
}
|
||||
|
||||
public void readApples(Long uid, List<Long> applyIds) {
|
||||
lambdaUpdate()
|
||||
.set(UserApply::getReadStatus, READ.getCode())
|
||||
.eq(UserApply::getReadStatus, UNREAD.getCode())
|
||||
.in(UserApply::getId, applyIds)
|
||||
.eq(UserApply::getTargetId, uid)
|
||||
.update();
|
||||
}
|
||||
|
||||
public void agree(Long applyId) {
|
||||
lambdaUpdate().set(UserApply::getStatus, AGREE.getCode())
|
||||
.eq(UserApply::getId, applyId)
|
||||
.update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ package com.abin.mallchat.common.user.dao;
|
||||
|
||||
import com.abin.mallchat.common.user.domain.entity.UserFriend;
|
||||
import com.abin.mallchat.common.user.mapper.UserFriendMapper;
|
||||
import com.abin.mallchat.common.user.service.IUserFriendService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户联系人表 服务实现类
|
||||
@@ -15,6 +16,17 @@ import org.springframework.stereotype.Service;
|
||||
* @since 2023-07-16
|
||||
*/
|
||||
@Service
|
||||
public class UserFriendDao extends ServiceImpl<UserFriendMapper, UserFriend> implements IUserFriendService {
|
||||
public class UserFriendDao extends ServiceImpl<UserFriendMapper, UserFriend> {
|
||||
|
||||
public List<UserFriend> getByFriends(Long uid, List<Long> uidList) {
|
||||
return lambdaQuery().eq(UserFriend::getUid, uid)
|
||||
.in(UserFriend::getFriendUid, uidList)
|
||||
.list();
|
||||
}
|
||||
|
||||
public UserFriend getByFriend(Long uid, Long targetUid) {
|
||||
return lambdaQuery().eq(UserFriend::getUid, uid)
|
||||
.eq(UserFriend::getFriendUid, targetUid)
|
||||
.one();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,4 @@ public class UserRole implements Serializable {
|
||||
*/
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -31,8 +31,6 @@ import java.util.stream.Collectors;
|
||||
@Component
|
||||
public class UserCache {
|
||||
|
||||
@Autowired
|
||||
private CursorUtils cursorUtils;
|
||||
@Autowired
|
||||
private UserDao userDao;
|
||||
@Autowired
|
||||
@@ -88,11 +86,11 @@ public class UserCache {
|
||||
}
|
||||
|
||||
public CursorPageBaseResp<Pair<Long, Double>> getOnlineCursorPage(CursorPageBaseReq pageBaseReq) {
|
||||
return cursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.ONLINE_UID_ZET), Long::parseLong);
|
||||
return CursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.ONLINE_UID_ZET), Long::parseLong);
|
||||
}
|
||||
|
||||
public CursorPageBaseResp<Pair<Long, Double>> getOfflineCursorPage(CursorPageBaseReq pageBaseReq) {
|
||||
return cursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.OFFLINE_UID_ZET), Long::parseLong);
|
||||
return CursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.OFFLINE_UID_ZET), Long::parseLong);
|
||||
}
|
||||
|
||||
public List<Long> getUserModifyTime(List<Long> uidList) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.abin.mallchat.custom.chat.controller;
|
||||
|
||||
|
||||
import com.abin.mallchat.common.chat.domain.dto.MsgReadInfoDTO;
|
||||
import com.abin.mallchat.common.common.annotation.FrequencyControl;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
||||
@@ -19,6 +20,7 @@ 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;
|
||||
@@ -51,7 +53,6 @@ public class ChatController {
|
||||
@ApiOperation("群成员列表")
|
||||
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid CursorPageBaseReq request) {
|
||||
// black(request);
|
||||
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(request);
|
||||
filterBlackMember(memberPage);
|
||||
return ApiResult.success(memberPage);
|
||||
@@ -59,6 +60,7 @@ public class ChatController {
|
||||
|
||||
@GetMapping("/member/list")
|
||||
@ApiOperation("房间内的所有群成员列表-@专用")
|
||||
@Deprecated
|
||||
public ApiResult<List<ChatMemberListResp>> getMemberList(@Valid ChatMessageMemberReq chatMessageMemberReq) {
|
||||
return ApiResult.success(chatService.getMemberList(chatMessageMemberReq));
|
||||
}
|
||||
@@ -74,6 +76,7 @@ public class ChatController {
|
||||
|
||||
@GetMapping("public/member/statistic")
|
||||
@ApiOperation("群成员人数统计")
|
||||
@Deprecated
|
||||
public ApiResult<ChatMemberStatisticResp> getMemberStatistic() {
|
||||
return ApiResult.success(chatService.getMemberStatistic());
|
||||
}
|
||||
@@ -85,7 +88,6 @@ public class ChatController {
|
||||
@ApiOperation("消息列表")
|
||||
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
||||
public ApiResult<CursorPageBaseResp<ChatMessageResp>> getMsgPage(@Valid ChatMessagePageReq request) {
|
||||
// black(request);
|
||||
CursorPageBaseResp<ChatMessageResp> msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid());
|
||||
filterBlackMsg(msgPage);
|
||||
return ApiResult.success(msgPage);
|
||||
@@ -101,7 +103,7 @@ public class ChatController {
|
||||
@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) {
|
||||
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()));
|
||||
@@ -122,5 +124,19 @@ public class ChatController {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.abin.mallchat.custom.chat.controller;
|
||||
|
||||
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
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.custom.chat.domain.vo.response.ChatRoomResp;
|
||||
import com.abin.mallchat.custom.chat.service.ChatService;
|
||||
import com.abin.mallchat.custom.chat.service.RoomService;
|
||||
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 RoomService 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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.abin.mallchat.custom.chat.controller;
|
||||
|
||||
|
||||
import com.abin.mallchat.common.common.annotation.FrequencyControl;
|
||||
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 com.abin.mallchat.common.user.service.cache.UserCache;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMemberReq;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.request.MemberAddReq;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.request.MemberDelReq;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.request.MemberReq;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberListResp;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.MemberResp;
|
||||
import com.abin.mallchat.custom.chat.service.ChatService;
|
||||
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 ChatService chatService;
|
||||
@Autowired
|
||||
private UserCache userCache;
|
||||
|
||||
@GetMapping("/public/group")
|
||||
@ApiOperation("群组详情")
|
||||
public ApiResult<MemberResp> groupDetail(@Valid IdReqVO request) {
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
@GetMapping("/public/group/member/page")
|
||||
@ApiOperation("群成员列表")
|
||||
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid MemberReq request) {
|
||||
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(request);
|
||||
return ApiResult.success(memberPage);
|
||||
}
|
||||
|
||||
@GetMapping("/group/member/list")
|
||||
@ApiOperation("房间内的所有群成员列表-@专用")
|
||||
public ApiResult<List<ChatMemberListResp>> getMemberList(@Valid ChatMessageMemberReq request) {
|
||||
return ApiResult.success(chatService.getMemberList(request));
|
||||
}
|
||||
|
||||
@DeleteMapping("/group/member")
|
||||
@ApiOperation("移除成员")
|
||||
public ApiResult<Void> delMember(@Valid @RequestBody MemberDelReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
@PostMapping("/group/member")
|
||||
@ApiOperation("邀请好友")
|
||||
public ApiResult<List<ChatMemberListResp>> addMember(@Valid @RequestBody MemberAddReq request) {
|
||||
Long uid = RequestHolder.get().getUid();
|
||||
return ApiResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.abin.mallchat.custom.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.custom.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;
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import javax.validation.constraints.NotNull;
|
||||
@NoArgsConstructor
|
||||
public class ChatMessageReq {
|
||||
@NotNull
|
||||
@ApiModelProperty("会话id")
|
||||
@ApiModelProperty("房间id")
|
||||
private Long roomId;
|
||||
|
||||
@ApiModelProperty("消息类型")
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.abin.mallchat.custom.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.custom.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,25 @@
|
||||
package com.abin.mallchat.custom.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 MemberReq extends CursorPageBaseReq {
|
||||
@ApiModelProperty("房间号")
|
||||
@NotNull
|
||||
private Long roomId;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.abin.mallchat.custom.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.custom.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;
|
||||
}
|
||||
@@ -18,12 +18,20 @@ import java.util.Date;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatRoomResp {
|
||||
@ApiModelProperty("会话id")
|
||||
private Long id;
|
||||
@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("会话类型 1大群聊 2沸点")
|
||||
private Integer type;
|
||||
@ApiModelProperty("房间最后活跃时间")
|
||||
@ApiModelProperty("会话头像")
|
||||
private String avatar;
|
||||
@ApiModelProperty("房间最后活跃时间(用来排序)")
|
||||
private Date lastActiveTime;
|
||||
@ApiModelProperty("未读数")
|
||||
private Integer unreadCount;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.abin.mallchat.custom.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 id;
|
||||
@ApiModelProperty("群名称")
|
||||
private Long groupName;
|
||||
@ApiModelProperty("在线人数")
|
||||
private Long onlineNum;//在线人数
|
||||
@ApiModelProperty("群聊描述")
|
||||
private String desc;//在线人数
|
||||
@ApiModelProperty("成员角色 1群主 2管理员 3普通成员 4踢出群聊")
|
||||
private Integer role;//在线人数
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.abin.mallchat.custom.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.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
@@ -7,6 +8,7 @@ import com.abin.mallchat.custom.chat.domain.vo.request.*;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -73,4 +75,8 @@ public interface ChatService {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.abin.mallchat.custom.chat.service;
|
||||
|
||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
public interface RoomService {
|
||||
/**
|
||||
* 获取会话列表--支持未登录态
|
||||
*/
|
||||
CursorPageBaseResp<ChatRoomResp> getContactPage(CursorPageBaseReq request, Long uid);
|
||||
}
|
||||
@@ -5,20 +5,16 @@ 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.common.domain.enums.YesOrNoEnum;
|
||||
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.request.msg.TextMsgReq;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
|
||||
import com.abin.mallchat.custom.chat.service.strategy.msg.AbstractMsgHandler;
|
||||
import com.abin.mallchat.custom.chat.service.strategy.msg.MsgHandlerFactory;
|
||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSApplyMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -99,4 +95,13 @@ public class MessageAdapter {
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.abin.mallchat.custom.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.Room;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageReadResp;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
|
||||
|
||||
import java.util.List;
|
||||
@@ -24,4 +26,12 @@ public class RoomAdapter {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,18 @@ 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.ContactDao;
|
||||
import com.abin.mallchat.common.chat.dao.MessageDao;
|
||||
import com.abin.mallchat.common.chat.dao.MessageMarkDao;
|
||||
import com.abin.mallchat.common.chat.dao.RoomDao;
|
||||
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.domain.entity.MessageMark;
|
||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageMarkActTypeEnum;
|
||||
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
|
||||
import com.abin.mallchat.common.chat.service.ContactService;
|
||||
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;
|
||||
@@ -44,6 +48,7 @@ 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;
|
||||
@@ -77,6 +82,10 @@ public class ChatServiceImpl implements ChatService {
|
||||
private IRoleService iRoleService;
|
||||
@Autowired
|
||||
private RecallMsgHandler recallMsgHandler;
|
||||
@Autowired
|
||||
private ContactService contactService;
|
||||
@Autowired
|
||||
private ContactDao contactDao;
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
@@ -205,6 +214,32 @@ public class ChatServiceImpl implements ChatService {
|
||||
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()));
|
||||
}
|
||||
|
||||
private void checkRecall(Long uid, Message message) {
|
||||
AssertUtil.isNotEmpty(message, "消息有误");
|
||||
AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL, "消息无法撤回");
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.abin.mallchat.custom.chat.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.abin.mallchat.common.chat.dao.ContactDao;
|
||||
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.RoomTypeEnum;
|
||||
import com.abin.mallchat.common.chat.service.adapter.ChatAdapter;
|
||||
import com.abin.mallchat.common.chat.service.cache.RoomCache;
|
||||
import com.abin.mallchat.common.chat.service.cache.RoomFriendCache;
|
||||
import com.abin.mallchat.common.chat.service.cache.RoomGroupCache;
|
||||
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.entity.User;
|
||||
import com.abin.mallchat.common.user.service.cache.UserInfoCache;
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
|
||||
import com.abin.mallchat.custom.chat.service.RoomService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
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 RoomServiceImpl implements RoomService {
|
||||
|
||||
@Autowired
|
||||
private ContactDao contactDao;
|
||||
@Autowired
|
||||
private RoomCache roomCache;
|
||||
@Autowired
|
||||
private RoomGroupCache roomGroupCache;
|
||||
@Autowired
|
||||
private RoomFriendCache roomFriendCache;
|
||||
@Autowired
|
||||
private UserInfoCache userInfoCache;
|
||||
@Autowired
|
||||
private MessageDao messageDao;
|
||||
|
||||
@Override
|
||||
public CursorPageBaseResp<ChatRoomResp> getContactPage(CursorPageBaseReq request, Long uid) {
|
||||
|
||||
if (Objects.nonNull(uid)) {
|
||||
CursorPageBaseResp<Contact> contactPage = contactDao.getContactPage(uid, request);
|
||||
List<Long> roomIds = contactPage.getList().stream().map(Contact::getRoomId).collect(Collectors.toList());
|
||||
//表情和头像
|
||||
Map<Long, RoomBaseInfo> roomBaseInfoMap = getRoomBaseInfoMap(roomIds, uid);
|
||||
//最后一条消息
|
||||
List<Long> msgIds = contactPage.getList().stream().map(Contact::getLastMsgId).collect(Collectors.toList());
|
||||
List<Message> messages = messageDao.listByIds(msgIds);
|
||||
Map<Long, Message> msgMap = messages.stream().collect(Collectors.toMap(Message::getId, Function.identity()));
|
||||
List<ChatRoomResp> collect = contactPage.getList().stream().map(contact -> {
|
||||
ChatRoomResp resp = new ChatRoomResp();
|
||||
BeanUtil.copyProperties(contact, resp);
|
||||
RoomBaseInfo roomBaseInfo = roomBaseInfoMap.get(contact.getRoomId());
|
||||
resp.setAvatar(roomBaseInfo.getAvatar());
|
||||
resp.setName(roomBaseInfo.getName());
|
||||
Message message = msgMap.get(contact.getLastMsgId());
|
||||
if (Objects.nonNull(message)) {
|
||||
resp.setText();
|
||||
}
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
CursorPageBaseResp.init(contactPage, collect);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<Long, User> getFriendRoomMap(List<Long> roomIds, Long uid) {
|
||||
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());
|
||||
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()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,14 +18,29 @@ public abstract class AbstractMsgHandler {
|
||||
MsgHandlerFactory.register(getMsgTypeEnum().getType(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
abstract MessageTypeEnum getMsgTypeEnum();
|
||||
|
||||
/**
|
||||
* 校验消息——保存前校验
|
||||
*/
|
||||
public abstract void checkMsg(ChatMessageReq req, Long uid);
|
||||
|
||||
/**
|
||||
* 保存消息
|
||||
*/
|
||||
public abstract void saveMsg(Message msg, ChatMessageReq req);
|
||||
|
||||
/**
|
||||
* 展示消息
|
||||
*/
|
||||
public abstract Object showMsg(Message msg);
|
||||
|
||||
/**
|
||||
* 被回复时——展示的消息
|
||||
*/
|
||||
public abstract Object showReplyMsg(Message msg);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.abin.mallchat.custom.common.event.listener;
|
||||
|
||||
import com.abin.mallchat.common.common.event.UserApplyEvent;
|
||||
import com.abin.mallchat.common.user.dao.UserApplyDao;
|
||||
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSFriendApply;
|
||||
import com.abin.mallchat.custom.user.service.WebSocketService;
|
||||
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
|
||||
/**
|
||||
* 好友申请监听器
|
||||
*
|
||||
* @author zhongzb create on 2022/08/26
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UserApplyListener {
|
||||
@Autowired
|
||||
private UserApplyDao userApplyDao;
|
||||
@Autowired
|
||||
private WebSocketService webSocketService;
|
||||
|
||||
@Async
|
||||
@TransactionalEventListener(classes = UserApplyEvent.class, fallbackExecution = true)
|
||||
public void notifyFriend(UserApplyEvent event) {
|
||||
UserApply userApply = event.getUserApply();
|
||||
Integer unReadCount = userApplyDao.getUnReadCount(userApply.getTargetId());
|
||||
webSocketService.sendToFriend(WSAdapter.buildApplySend(new WSFriendApply(userApply.getUid(), unReadCount)), userApply.getTargetId());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class FriendController {
|
||||
@PutMapping("/apply")
|
||||
@ApiOperation("申请审批")
|
||||
public ApiResult<Void> applyApprove(@Valid @RequestBody FriendApproveReq request) {
|
||||
friendService.applyApprove(request);
|
||||
friendService.applyApprove(RequestHolder.get().getUid(), request);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@ public enum WSRespTypeEnum {
|
||||
BLACK(7, "拉黑用户", WSBlack.class),
|
||||
MARK(8, "消息标记", WSMsgMark.class),
|
||||
RECALL(9, "消息撤回", WSMsgRecall.class),
|
||||
APPLY(10,"好友申请", WSApplyMessage.class),
|
||||
APPLY(10, "好友申请", WSFriendApply.class),
|
||||
MEMBER_CHANGE(11, "成员变动", WSMemberChange.class),
|
||||
MESSAGE_READ(12, "消息已读数", WSMessageRead.class),
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.abin.mallchat.custom.user.domain.vo.response.ws;
|
||||
|
||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author : limeng
|
||||
* @description : 好友申请消息推送
|
||||
* @date : 2023/07/21
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class WSApplyMessage extends ChatMessageResp {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.abin.mallchat.custom.user.domain.vo.response.ws;
|
||||
|
||||
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-19
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class WSFriendApply {
|
||||
@ApiModelProperty("申请人")
|
||||
private Long uid;
|
||||
@ApiModelProperty("申请未读数")
|
||||
private Integer unreadCount;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.abin.mallchat.custom.user.domain.vo.response.ws;
|
||||
|
||||
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-19
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class WSMemberChange {
|
||||
@ApiModelProperty("群组id")
|
||||
private Long roomId;
|
||||
@ApiModelProperty("变动人")
|
||||
private Long uid;
|
||||
@ApiModelProperty("变动类型 1加入群组 2移除群组")
|
||||
private Integer changeType;
|
||||
/**
|
||||
* @see com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum
|
||||
*/
|
||||
@ApiModelProperty("在线状态 1在线 2离线")
|
||||
private Integer activeStatus;
|
||||
@ApiModelProperty("最后一次上下线时间")
|
||||
private Date lastOptTime;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.abin.mallchat.custom.user.domain.vo.response.ws;
|
||||
|
||||
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-19
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class WSMessageRead {
|
||||
@ApiModelProperty("消息")
|
||||
private Long msgId;
|
||||
@ApiModelProperty("阅读人数(可能为0)")
|
||||
private Integer readCount;
|
||||
}
|
||||
@@ -21,7 +21,4 @@ import java.util.List;
|
||||
public class WSOnlineOfflineNotify {
|
||||
private List<ChatMemberResp> changeList = new ArrayList<>();//新的上下线用户
|
||||
private Long onlineNum;//在线人数
|
||||
@Deprecated
|
||||
private Long totalNum;//总人数
|
||||
|
||||
}
|
||||
|
||||
@@ -56,5 +56,5 @@ public interface FriendService {
|
||||
* @param uid uid
|
||||
* @param request 请求
|
||||
*/
|
||||
void applyApprove(FriendApproveReq request);
|
||||
void applyApprove(Long uid, FriendApproveReq request);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.abin.mallchat.custom.user.service.adapter;
|
||||
|
||||
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
||||
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApplyReq;
|
||||
import com.abin.mallchat.custom.user.domain.vo.response.friend.FriendApplyResp;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyReadStatusEnum.UNREAD;
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyStatusEnum.WAIT_APPROVAL;
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyTypeEnum.ADD_FRIEND;
|
||||
|
||||
/**
|
||||
* Description: 好友适配器
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
public class FriendAdapter {
|
||||
|
||||
|
||||
public static UserApply buildFriendApply(Long uid, FriendApplyReq request) {
|
||||
UserApply userApplyNew = new UserApply();
|
||||
userApplyNew.setUid(uid);
|
||||
userApplyNew.setMsg(request.getMsg());
|
||||
userApplyNew.setType(ADD_FRIEND.getCode());
|
||||
userApplyNew.setTargetId(request.getTargetUid());
|
||||
userApplyNew.setStatus(WAIT_APPROVAL.getCode());
|
||||
userApplyNew.setReadStatus(UNREAD.getCode());
|
||||
return userApplyNew;
|
||||
}
|
||||
|
||||
public static List<FriendApplyResp> buildFriendApplyList(List<UserApply> records) {
|
||||
return records.stream().map(userApply -> {
|
||||
FriendApplyResp friendApplyResp = new FriendApplyResp();
|
||||
friendApplyResp.setUid(userApply.getUid());
|
||||
friendApplyResp.setType(userApply.getType());
|
||||
friendApplyResp.setMsg(userApply.getMsg());
|
||||
friendApplyResp.setStatus(userApply.getStatus());
|
||||
return friendApplyResp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -133,8 +133,8 @@ public class WSAdapter {
|
||||
return wsBaseResp;
|
||||
}
|
||||
|
||||
public static WSBaseResp<WSApplyMessage> buildApplySend(WSApplyMessage resp) {
|
||||
WSBaseResp<WSApplyMessage> wsBaseResp = new WSBaseResp<>();
|
||||
public static WSBaseResp<WSFriendApply> buildApplySend(WSFriendApply resp) {
|
||||
WSBaseResp<WSFriendApply> wsBaseResp = new WSBaseResp<>();
|
||||
wsBaseResp.setType(WSRespTypeEnum.APPLY.getType());
|
||||
wsBaseResp.setData(resp);
|
||||
return wsBaseResp;
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
package com.abin.mallchat.custom.user.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.abin.mallchat.common.chat.dao.RoomFriendDao;
|
||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||
import com.abin.mallchat.common.chat.service.ContactService;
|
||||
import com.abin.mallchat.common.chat.service.RoomService;
|
||||
import com.abin.mallchat.common.common.annotation.RedissonLock;
|
||||
import com.abin.mallchat.common.common.domain.vo.request.PageBaseReq;
|
||||
import com.abin.mallchat.common.common.domain.vo.response.PageBaseResp;
|
||||
import com.abin.mallchat.common.common.event.UserApplyEvent;
|
||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||
import com.abin.mallchat.common.user.dao.UserApplyDao;
|
||||
import com.abin.mallchat.common.user.dao.UserFriendDao;
|
||||
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
||||
import com.abin.mallchat.common.user.domain.entity.UserFriend;
|
||||
import com.abin.mallchat.common.user.service.IUserApplyService;
|
||||
import com.abin.mallchat.common.user.service.IUserFriendService;
|
||||
import com.abin.mallchat.custom.chat.service.ChatService;
|
||||
import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter;
|
||||
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApplyReq;
|
||||
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApproveReq;
|
||||
@@ -13,27 +22,24 @@ import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendCheckReq;
|
||||
import com.abin.mallchat.custom.user.domain.vo.response.friend.FriendApplyResp;
|
||||
import com.abin.mallchat.custom.user.domain.vo.response.friend.FriendCheckResp;
|
||||
import com.abin.mallchat.custom.user.domain.vo.response.friend.FriendUnreadResp;
|
||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSApplyMessage;
|
||||
import com.abin.mallchat.custom.user.service.FriendService;
|
||||
import com.abin.mallchat.custom.user.service.WebSocketService;
|
||||
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import com.abin.mallchat.custom.user.service.adapter.FriendAdapter;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyReadStatusEnum.UNREAD;
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyStatusEnum.AGREE;
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyStatusEnum.WAIT_APPROVAL;
|
||||
import static com.abin.mallchat.common.user.domain.enums.ApplyTypeEnum.ADD_FRIEND;
|
||||
|
||||
/**
|
||||
* @author : limeng
|
||||
@@ -44,15 +50,24 @@ import static com.abin.mallchat.common.user.domain.enums.ApplyTypeEnum.ADD_FRIEN
|
||||
@Service
|
||||
public class FriendServiceImpl implements FriendService {
|
||||
|
||||
@Resource
|
||||
private IUserFriendService friendService;
|
||||
|
||||
@Resource
|
||||
private IUserApplyService applyService;
|
||||
|
||||
@Resource
|
||||
@Autowired
|
||||
private WebSocketService webSocketService;
|
||||
|
||||
@Autowired
|
||||
private UserFriendDao userFriendDao;
|
||||
@Autowired
|
||||
private UserApplyDao userApplyDao;
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
@Autowired
|
||||
private RoomFriendDao roomFriendDao;
|
||||
@Autowired
|
||||
private RoomService roomService;
|
||||
@Autowired
|
||||
private ContactService contactService;
|
||||
@Autowired
|
||||
private ChatService chatService;
|
||||
|
||||
/**
|
||||
* 检查
|
||||
* 检查是否是自己好友
|
||||
@@ -63,15 +78,13 @@ public class FriendServiceImpl implements FriendService {
|
||||
*/
|
||||
@Override
|
||||
public FriendCheckResp check(Long uid, FriendCheckReq request) {
|
||||
LambdaQueryChainWrapper<UserFriend> wrapper = friendService.lambdaQuery();
|
||||
wrapper.eq(UserFriend::getUid, uid)
|
||||
.in(UserFriend::getFriendUid, request.getUidList());
|
||||
List<UserFriend> friendList = friendService.list(wrapper);
|
||||
Map<Long, UserFriend> friendMap = friendList.stream().collect(Collectors.toMap(UserFriend::getFriendUid, friend -> friend));
|
||||
List<UserFriend> friendList = userFriendDao.getByFriends(uid, request.getUidList());
|
||||
|
||||
Set<Long> friendUidSet = friendList.stream().map(UserFriend::getFriendUid).collect(Collectors.toSet());
|
||||
List<FriendCheckResp.FriendCheck> friendCheckList = request.getUidList().stream().map(friendUid -> {
|
||||
FriendCheckResp.FriendCheck friendCheck = new FriendCheckResp.FriendCheck();
|
||||
friendCheck.setUid(friendUid);
|
||||
friendCheck.setIsFriend(friendMap.containsKey(friendUid));
|
||||
friendCheck.setIsFriend(friendUidSet.contains(friendUid));
|
||||
return friendCheck;
|
||||
}).collect(Collectors.toList());
|
||||
return new FriendCheckResp(friendCheckList);
|
||||
@@ -84,25 +97,20 @@ public class FriendServiceImpl implements FriendService {
|
||||
*/
|
||||
@Override
|
||||
public void apply(Long uid, FriendApplyReq request) {
|
||||
LambdaQueryChainWrapper<UserApply> wrapper = applyService.lambdaQuery();
|
||||
wrapper.eq(UserApply::getUid, uid)
|
||||
.eq(UserApply::getTargetId, request.getTargetUid());
|
||||
UserApply userApply = applyService.getOne(wrapper);
|
||||
if (Objects.nonNull(userApply)) {
|
||||
//是否有好友关系
|
||||
UserFriend friend = userFriendDao.getByFriend(uid, request.getTargetUid());
|
||||
AssertUtil.isEmpty(friend, "你们已经是好友了");
|
||||
//是否有待审批的申请记录
|
||||
UserApply friendApproving = userApplyDao.getFriendApproving(uid, request.getTargetUid());
|
||||
if (Objects.nonNull(friendApproving)) {
|
||||
log.info("已有好友申请记录,uid:{}, targetId:{}", uid, request.getTargetUid());
|
||||
return;
|
||||
}
|
||||
UserApply userApplyNew = new UserApply();
|
||||
userApplyNew.setUid(uid);
|
||||
userApplyNew.setMsg(request.getMsg());
|
||||
userApplyNew.setType(ADD_FRIEND.getCode());
|
||||
userApplyNew.setTargetId(request.getTargetUid());
|
||||
userApplyNew.setStatus(WAIT_APPROVAL.getCode());
|
||||
userApplyNew.setReadStatus(UNREAD.getCode());
|
||||
applyService.save(userApplyNew);
|
||||
|
||||
WSApplyMessage applyMessage = MessageAdapter.buildApplyResp(userApplyNew);
|
||||
webSocketService.sendToFriend(WSAdapter.buildApplySend(applyMessage), request.getTargetUid());
|
||||
//申请入库
|
||||
UserApply insert = FriendAdapter.buildFriendApply(uid, request);
|
||||
userApplyDao.save(insert);
|
||||
//申请事件
|
||||
applicationEventPublisher.publishEvent(new UserApplyEvent(this, insert));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,23 +121,15 @@ public class FriendServiceImpl implements FriendService {
|
||||
*/
|
||||
@Override
|
||||
public PageBaseResp<FriendApplyResp> pageApplyFriend(Long uid, PageBaseReq request) {
|
||||
// todo 分页
|
||||
LambdaQueryChainWrapper<UserApply> wrapper = applyService.lambdaQuery();
|
||||
wrapper.eq(UserApply::getUid, uid)
|
||||
.or()
|
||||
.eq(UserApply::getTargetId, uid);
|
||||
List<UserApply> userApplyList = applyService.list(wrapper);
|
||||
List<FriendApplyResp> friendApplyResps = userApplyList.stream().map(userApply -> {
|
||||
FriendApplyResp friendApplyResp = new FriendApplyResp();
|
||||
friendApplyResp.setUid(userApply.getUid());
|
||||
friendApplyResp.setType(userApply.getType());
|
||||
friendApplyResp.setMsg(userApply.getMsg());
|
||||
friendApplyResp.setStatus(userApply.getStatus());
|
||||
return friendApplyResp;
|
||||
}).collect(Collectors.toList());
|
||||
PageBaseResp<FriendApplyResp> pageBaseResp = new PageBaseResp<>();
|
||||
pageBaseResp.setList(friendApplyResps);
|
||||
return pageBaseResp;
|
||||
IPage<UserApply> userApplyIPage = userApplyDao.FriendApplyPage(uid, request.plusPage());
|
||||
if (CollectionUtil.isEmpty(userApplyIPage.getRecords())) {
|
||||
return PageBaseResp.empty();
|
||||
}
|
||||
//将这些申请列表设为已读
|
||||
List<Long> applyIds = userApplyIPage.getRecords().stream().map(UserApply::getId).collect(Collectors.toList());
|
||||
userApplyDao.readApples(uid, applyIds);
|
||||
//返回消息
|
||||
return PageBaseResp.init(userApplyIPage, FriendAdapter.buildFriendApplyList(userApplyIPage.getRecords()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,34 +139,38 @@ public class FriendServiceImpl implements FriendService {
|
||||
*/
|
||||
@Override
|
||||
public FriendUnreadResp unread(Long uid) {
|
||||
LambdaQueryChainWrapper<UserApply> wrapper = applyService.lambdaQuery();
|
||||
wrapper.eq(UserApply::getTargetId, uid)
|
||||
.eq(UserApply::getReadStatus, UNREAD.getCode());
|
||||
return new FriendUnreadResp(applyService.count(wrapper));
|
||||
Integer unReadCount = userApplyDao.getUnReadCount(uid);
|
||||
return new FriendUnreadResp(unReadCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void applyApprove(FriendApproveReq request) {
|
||||
UserApply userApply = applyService.getById(request.getApplyId());
|
||||
if (Objects.isNull(userApply)) {
|
||||
log.error("不存在申请记录:{}", request.getApplyId());
|
||||
return;
|
||||
}
|
||||
if (Objects.equals(userApply.getStatus(), AGREE.getCode())) {
|
||||
log.error("已同意好友申请:{}", request.getApplyId());
|
||||
return;
|
||||
}
|
||||
LambdaUpdateChainWrapper<UserApply> updateWrapper = applyService.lambdaUpdate();
|
||||
updateWrapper.set(UserApply::getStatus, AGREE.getCode())
|
||||
.eq(UserApply::getId, request.getApplyId());
|
||||
applyService.update(updateWrapper);
|
||||
@RedissonLock(key = "#uid")
|
||||
public void applyApprove(Long uid, FriendApproveReq request) {
|
||||
UserApply userApply = userApplyDao.getById(request.getApplyId());
|
||||
AssertUtil.isNotEmpty(userApply, "不存在申请记录");
|
||||
AssertUtil.equal(userApply.getTargetId(), uid, "不存在申请记录");
|
||||
AssertUtil.equal(userApply.getStatus(), AGREE.getCode(), "已同意好友申请");
|
||||
//同意申请
|
||||
userApplyDao.agree(request.getApplyId());
|
||||
//创建双方好友关系
|
||||
createFriend(uid, userApply.getUid());
|
||||
//创建一个聊天房间
|
||||
RoomFriend roomFriend = roomService.createFriendRoom(Arrays.asList(uid, userApply.getUid()));
|
||||
//创建双方的会话
|
||||
contactService.createContact(uid, roomFriend.getRoomId());
|
||||
contactService.createContact(userApply.getUid(), roomFriend.getRoomId());
|
||||
//发送一条同意消息。。我们已经是好友了,开始聊天吧
|
||||
chatService.sendMsg(MessageAdapter.buildAgreeMsg(roomFriend.getRoomId()), uid);
|
||||
}
|
||||
|
||||
private void createFriend(Long uid, Long targetUid) {
|
||||
UserFriend userFriend1 = new UserFriend();
|
||||
userFriend1.setUid(userApply.getUid());
|
||||
userFriend1.setFriendUid(userApply.getTargetId());
|
||||
userFriend1.setUid(uid);
|
||||
userFriend1.setFriendUid(targetUid);
|
||||
UserFriend userFriend2 = new UserFriend();
|
||||
userFriend2.setUid(userApply.getTargetId());
|
||||
userFriend2.setFriendUid(userApply.getUid());
|
||||
friendService.saveBatch(Lists.newArrayList(userFriend1, userFriend2));
|
||||
userFriend2.setUid(targetUid);
|
||||
userFriend2.setFriendUid(uid);
|
||||
userFriendDao.saveBatch(Lists.newArrayList(userFriend1, userFriend2))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.abin.mallchat.custom.common;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.abin.mallchat.custom.user.service.adapter.FriendAdapter.buildFriendRoomKey;
|
||||
|
||||
/**
|
||||
* Description:
|
||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||
* Date: 2023-07-22
|
||||
*/
|
||||
public class CommonTest {
|
||||
@Test
|
||||
public void test() {
|
||||
System.out.println(buildFriendRoomKey(100L, 102L));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user