diff --git a/docs/version/2023-07-17.sql b/docs/version/2023-07-17.sql index 49dac82..933526e 100644 --- a/docs/version/2023-07-17.sql +++ b/docs/version/2023-07-17.sql @@ -1,22 +1,5 @@ ###单聊群聊功能 -ALTER TABLE `user` add COLUMN `active_status` INT(11) DEFAULT "2" COMMENT '在线状态 1在线 2离线' AFTER `open_id` ; - -DROP TABLE IF EXISTS `room`; -CREATE TABLE `room` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', - `name` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '群名称', - `avatar` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '群头像', - `type` int(11) NOT NULL COMMENT '房间类型 1群聊', - `hot_flag` int(11) DEFAULT '0' COMMENT '是否全员展示 0否 1是', - `active_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '群最后消息的更新时间(热点群不需要写扩散,更新这里就行)', - `ext_json` json DEFAULT NULL COMMENT '额外信息(根据不同类型房间有不同存储的东西)', - `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, - 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='房间表'; - +DROP TABLE IF EXISTS `user_apply`; CREATE TABLE `user_apply` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `uid` bigint(20) NOT NULL COMMENT '申请人uid', @@ -33,7 +16,7 @@ CREATE TABLE `user_apply` ( 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='用户申请表'; - +DROP TABLE IF EXISTS `user_friend`; CREATE TABLE `user_friend` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `uid` bigint(20) NOT NULL COMMENT 'uid', @@ -46,33 +29,83 @@ CREATE TABLE `user_friend` ( 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='用户联系人表'; - -CREATE TABLE `group_member` ( +DROP TABLE IF EXISTS `room`; +CREATE TABLE `room` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `type` int(11) NOT NULL COMMENT '房间类型 1群聊 2单聊', + `hot_flag` int(11) DEFAULT '0' COMMENT '是否全员展示 0否 1是', + `active_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '群最后消息的更新时间(热点群不需要写扩散,只更新这里)', + `last_msg_id` bigint(20) DEFAULT NULL COMMENT '会话中的最后一条消息id', + `ext_json` json DEFAULT NULL COMMENT '额外信息(根据不同类型房间有不同存储的东西)', + `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, + 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='房间表'; +DROP TABLE IF EXISTS `room_friend`; +CREATE TABLE `room_friend` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `room_id` bigint(20) NOT NULL COMMENT '房间id', + `uid1` bigint(20) NOT NULL COMMENT 'uid1(更小的uid)', + `uid2` bigint(20) NOT NULL COMMENT 'uid2(更大的uid)', + `room_key` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '房间key由两个uid拼接,先做排序uid1_uid2', + `status` int(11) NOT NULL 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 `room_key` (`room_key`) USING BTREE, + KEY `idx_room_id` (`room_id`) 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='单聊房间表'; +DROP TABLE IF EXISTS `room_group`; +CREATE TABLE `room_group` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `room_id` bigint(20) NOT NULL COMMENT '房间id', + `name` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '群名称', + `avatar` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '群头像', + `ext_json` json DEFAULT NULL COMMENT '额外信息(根据不同类型房间有不同存储的东西)', + `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, + KEY `idx_room_id` (`room_id`) 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='群聊房间表'; +DROP TABLE IF EXISTS `group_member`; +CREATE TABLE `group_member` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `group_id` bigint(20) NOT NULL COMMENT '群主id', `uid` bigint(20) NOT NULL COMMENT '成员uid', `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, - KEY `idx_room_id_type` (`room_id`,`type`) USING BTREE, + KEY `idx_group_id_role` (`group_id`,`role`) 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='群成员表'; - +DROP TABLE IF EXISTS `contact`; CREATE TABLE `contact` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `uid` bigint(20) NOT NULL COMMENT 'uid', - `type` int(11) NOT NULL COMMENT '聊天类型 1单聊 2普通群聊', - `hot_flag` int(11) DEFAULT '0' COMMENT '是否全员展示 0否 1是', - `target_id` bigint(20) NOT NULL COMMENT '聊天对象type=1:uid,type=2:房间id', + `room_id` bigint(20) NOT NULL COMMENT '房间id', `read_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '阅读到的时间', - `active_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '会话内消息最后更新的时间(只有普通会话需要维护,全员会话不需要维护)', + `active_time` datetime(3) DEFAULT NULL COMMENT '会话内消息最后更新的时间(只有普通会话需要维护,全员会话不需要维护)', + `last_msg_id` bigint(20) DEFAULT NULL COMMENT '会话最新消息id', `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_target_id_type` (`uid`,`target_id`,`type`) USING BTREE, - KEY `idx_target_id_read_time` (`target_id`,`read_time`) USING BTREE, + UNIQUE KEY `uniq_uid_room_id` (`uid`,`room_id`) USING BTREE, + KEY `idx_room_id_read_time` (`room_id`,`read_time`) 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='会话列表'; \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会话列表'; + +ALTER TABLE `user` add COLUMN `active_status` INT(11) DEFAULT "2" COMMENT '在线状态 1在线 2离线' AFTER `open_id` ; +ALTER TABLE `user` add KEY `idx_active_status_last_opt_time` (`active_status`,`last_opt_time`) ; +INSERT INTO `user` (`id`, `name`, `avatar`, `sex`, `open_id`, `last_opt_time`, `ip_info`, `item_id`, `status`, `create_time`, `update_time`) VALUES (1, '系统消息', 'http://mms1.baidu.com/it/u=1979830414,2984779047&fm=253&app=138&f=JPEG&fmt=auto&q=75?w=500&h=500', NULL, '0', '2023-07-01 11:58:24.605', NULL, NULL, 0, '2023-07-01 11:58:24.605', '2023-07-01 12:02:56.900'); +insert INTO `room`(`id`,`type`,`hot_flag`) values (1,1,1); +insert INTO `room_group`(`id`,`room_id`,`name`,`avatar`) values (1,1,'抹茶全员群','https://mallchat.cn/assets/logo-e81cd252.jpeg'); diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/ContactDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/ContactDao.java index ca18abb..2aa648a 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/ContactDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/ContactDao.java @@ -9,6 +9,9 @@ import com.abin.mallchat.common.common.utils.CursorUtils; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import java.util.Date; +import java.util.List; + /** *

* 会话列表 服务实现类 @@ -71,4 +74,18 @@ public class ContactDao extends ServiceImpl { wrapper.eq(Contact::getUid, uid); }, Contact::getActiveTime); } + + public List getByRoomIds(List roomIds, Long uid) { + return lambdaQuery() + .eq(Contact::getRoomId, roomIds) + .eq(Contact::getUid, uid) + .list(); + } + + /** + * 更新所有人的会话时间,没有就直接插入 + */ + public void refreshOrCreateActiveTime(Long roomId, List memberUidList, Long msgId, Date activeTime) { + baseMapper.refreshOrCreateActiveTime(roomId, memberUidList, msgId, activeTime); + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/GroupMemberDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/GroupMemberDao.java index 9a7dbdb..7d80749 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/GroupMemberDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/GroupMemberDao.java @@ -1,11 +1,14 @@ package com.abin.mallchat.common.chat.dao; import com.abin.mallchat.common.chat.domain.entity.GroupMember; +import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum; import com.abin.mallchat.common.chat.mapper.GroupMemberMapper; -import com.abin.mallchat.common.chat.service.IGroupMemberService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.stream.Collectors; + /** *

* 群成员表 服务实现类 @@ -15,6 +18,36 @@ import org.springframework.stereotype.Service; * @since 2023-07-16 */ @Service -public class GroupMemberDao extends ServiceImpl implements IGroupMemberService { +public class GroupMemberDao extends ServiceImpl { + public List getMemberUidList(Long groupId) { + List list = lambdaQuery() + .eq(GroupMember::getGroupId, groupId) + .select(GroupMember::getUid) + .list(); + return list.stream().map(GroupMember::getUid).collect(Collectors.toList()); + } + + public List getMemberBatch(Long groupId, List uidList) { + List list = lambdaQuery() + .eq(GroupMember::getGroupId, groupId) + .in(GroupMember::getUid, uidList) + .select(GroupMember::getUid) + .list(); + return list.stream().map(GroupMember::getUid).collect(Collectors.toList()); + } + + public GroupMember getMember(Long groupId, Long uid) { + return lambdaQuery() + .eq(GroupMember::getGroupId, groupId) + .eq(GroupMember::getUid, uid) + .one(); + } + + public List getSelfGroup(Long uid) { + return lambdaQuery() + .eq(GroupMember::getUid, uid) + .eq(GroupMember::getRole, GroupRoleEnum.LEADER.getType()) + .list(); + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/MessageDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/MessageDao.java index 6ba262c..480edd6 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/MessageDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/MessageDao.java @@ -9,6 +9,9 @@ import com.abin.mallchat.common.common.utils.CursorUtils; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import java.util.Date; +import java.util.Objects; + /** *

* 消息表 服务实现类 @@ -52,4 +55,11 @@ public class MessageDao extends ServiceImpl { .set(Message::getStatus, MessageStatusEnum.DELETE.getStatus()) .update(); } + + public Integer getUnReadCount(Long roomId, Date readTime) { + return lambdaQuery() + .eq(Message::getRoomId, roomId) + .gt(Objects.nonNull(readTime), Message::getCreateTime, readTime) + .count(); + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomDao.java index ef28254..b5d52ea 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomDao.java @@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import java.util.Date; + /** *

* 房间表 服务实现类 @@ -17,4 +19,11 @@ import org.springframework.stereotype.Service; @Service public class RoomDao extends ServiceImpl implements IService { + public void refreshActiveTime(Long roomId, Long msgId, Date msgTime) { + lambdaUpdate() + .eq(Room::getId, roomId) + .set(Room::getLastMsgId, msgId) + .set(Room::getActiveTime, msgTime) + .update(); + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomFriendDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomFriendDao.java index 540ba16..f8d928e 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomFriendDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomFriendDao.java @@ -20,7 +20,7 @@ import java.util.List; public class RoomFriendDao extends ServiceImpl { public RoomFriend getByKey(String key) { - return lambdaQuery().eq(RoomFriend::getKey, key).one(); + return lambdaQuery().eq(RoomFriend::getRoomKey, key).one(); } public void restoreRoom(Long id) { @@ -32,7 +32,13 @@ public class RoomFriendDao extends ServiceImpl { public List listByRoomIds(List roomIds) { return lambdaQuery() - .eq(RoomFriend::getRoomId, roomIds) + .in(RoomFriend::getRoomId, roomIds) .list(); } + + public RoomFriend getByRoomId(Long roomID) { + return lambdaQuery() + .eq(RoomFriend::getRoomId, roomID) + .one(); + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomGroupDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomGroupDao.java index 52e38f4..89c23f7 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomGroupDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/dao/RoomGroupDao.java @@ -23,4 +23,10 @@ public class RoomGroupDao extends ServiceImpl { .in(RoomGroup::getRoomId, roomIds) .list(); } + + public RoomGroup getByRoomId(Long roomId) { + return lambdaQuery() + .eq(RoomGroup::getRoomId, roomId) + .one(); + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/dto/RoomBaseInfo.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/dto/RoomBaseInfo.java index b491f05..f2023dd 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/dto/RoomBaseInfo.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/dto/RoomBaseInfo.java @@ -1,8 +1,11 @@ package com.abin.mallchat.common.chat.domain.dto; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.util.Date; + /** * Description: 房间详情 * Author: abin @@ -16,4 +19,27 @@ public class RoomBaseInfo { private String name; @ApiModelProperty("会话头像") private String avatar; + /** + * 房间类型 1群聊 2单聊 + */ + private Integer type; + + /** + * 是否全员展示 0否 1是 + * + * @see com.abin.mallchat.common.chat.domain.enums.HotFlagEnum + */ + private Integer hotFlag; + + /** + * 群最后消息的更新时间 + */ + @TableField("active_time") + private Date activeTime; + + /** + * 最后一条消息id + */ + @TableField("last_msg_id") + private Long lastMsgId; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/Contact.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/Contact.java index 0a2afbc..643725f 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/Contact.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/Contact.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -47,13 +47,13 @@ public class Contact implements Serializable { * 阅读到的时间 */ @TableField("read_time") - private LocalDateTime readTime; + private Date readTime; /** * 会话内消息最后更新的时间(只有普通会话需要维护,全员会话不需要维护) */ @TableField("active_time") - private LocalDateTime activeTime; + private Date activeTime; /** * 最后一条消息id @@ -65,13 +65,13 @@ public class Contact implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/GroupMember.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/GroupMember.java index 2add870..53ae885 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/GroupMember.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/GroupMember.java @@ -4,11 +4,10 @@ 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 lombok.*; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -21,6 +20,9 @@ import java.time.LocalDateTime; @Data @EqualsAndHashCode(callSuper = false) @TableName("group_member") +@Builder +@AllArgsConstructor +@NoArgsConstructor public class GroupMember implements Serializable { private static final long serialVersionUID = 1L; @@ -32,10 +34,10 @@ public class GroupMember implements Serializable { private Long id; /** - * 房间id + * 群组id */ - @TableField("room_id") - private Long roomId; + @TableField("group_id") + private Long groupId; /** * 成员uid @@ -44,7 +46,9 @@ public class GroupMember implements Serializable { private Long uid; /** - * 成员角色1群主 2管理员 3普通成员 + * 成员角色1群主(可撤回,可移除,可解散) 2管理员(可撤回,可移除) 3普通成员 + * + * @see com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum */ @TableField("role") private Integer role; @@ -53,13 +57,13 @@ public class GroupMember implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/Room.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/Room.java index 6ac70ac..5597d0e 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/Room.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/Room.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -32,6 +32,8 @@ public class Room implements Serializable { /** * 房间类型 1群聊 2单聊 + * + * @see com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum */ @TableField("type") private Integer type; @@ -48,7 +50,13 @@ public class Room implements Serializable { * 群最后消息的更新时间(热点群不需要写扩散,更新这里就行) */ @TableField("active_time") - private LocalDateTime activeTime; + private Date activeTime; + + /** + * 最后一条消息id + */ + @TableField("last_msg_id") + private Long lastMsgId; /** * 额外信息(根据不同类型房间有不同存储的东西) @@ -60,13 +68,13 @@ public class Room implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/RoomFriend.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/RoomFriend.java index c118540..f10168c 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/RoomFriend.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/RoomFriend.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -52,8 +52,8 @@ public class RoomFriend implements Serializable { /** * 房间key由两个uid拼接,先做排序uid1_uid2 */ - @TableField("key") - private String key; + @TableField("room_key") + private String roomKey; /** * 房间状态 0正常 1禁用(删好友了禁用) @@ -65,12 +65,12 @@ public class RoomFriend implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/RoomGroup.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/RoomGroup.java index 0df77d8..e238e19 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/RoomGroup.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/RoomGroup.java @@ -5,7 +5,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -63,13 +63,13 @@ public class RoomGroup implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/enums/GroupRoleEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/enums/GroupRoleEnum.java new file mode 100644 index 0000000..ccb8eea --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/enums/GroupRoleEnum.java @@ -0,0 +1,36 @@ +package com.abin.mallchat.common.chat.domain.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Description: 成员角色枚举 + * Author: abin + * Date: 2023-03-19 + */ +@AllArgsConstructor +@Getter +public enum GroupRoleEnum { + LEADER(1, "群主"), + MANAGER(2, "管理"), + MEMBER(3, "普通成员"), + ; + + private final Integer type; + private final String desc; + + private static Map cache; + + static { + cache = Arrays.stream(GroupRoleEnum.values()).collect(Collectors.toMap(GroupRoleEnum::getType, Function.identity())); + } + + public static GroupRoleEnum of(Integer type) { + return cache.get(type); + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/enums/MessageTypeEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/enums/MessageTypeEnum.java index 73d7b97..05bff05 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/enums/MessageTypeEnum.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/enums/MessageTypeEnum.java @@ -23,6 +23,7 @@ public enum MessageTypeEnum { SOUND(5, "语音"), VIDEO(6, "视频"), EMOJI(7, "表情"), + SYSTEM(8, "系统消息"), ; private final Integer type; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMessageRespV1.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/vo/response/ChatMessageResp.java similarity index 94% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMessageRespV1.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/vo/response/ChatMessageResp.java index c43507b..87758ca 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMessageRespV1.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/vo/response/ChatMessageResp.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.chat.domain.vo.response; +package com.abin.mallchat.common.chat.domain.vo.response; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -17,7 +17,7 @@ import java.util.Date; @Builder @AllArgsConstructor @NoArgsConstructor -public class ChatMessageRespV1 { +public class ChatMessageResp { @ApiModelProperty("发送者信息") private UserInfo fromUser; @@ -42,7 +42,6 @@ public class ChatMessageRespV1 { private Object body; @ApiModelProperty("消息标记") private MessageMark messageMark; - } @Data @@ -56,5 +55,4 @@ public class ChatMessageRespV1 { @ApiModelProperty("该用户是否已经举报 0否 1是") private Integer userDislike; } - } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/mapper/ContactMapper.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/mapper/ContactMapper.java index 5e9aa15..6f64aa1 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/mapper/ContactMapper.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/mapper/ContactMapper.java @@ -2,6 +2,10 @@ package com.abin.mallchat.common.chat.mapper; import com.abin.mallchat.common.chat.domain.entity.Contact; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; /** *

@@ -13,4 +17,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface ContactMapper extends BaseMapper { + void refreshOrCreateActiveTime(@Param("roomId") Long roomId, @Param("memberUidList") List memberUidList, @Param("msgId") Long msgId, @Param("activeTime") Date activeTime); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/RoomService.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/RoomService.java index 1f7c8d8..f4c069d 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/RoomService.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/RoomService.java @@ -1,6 +1,7 @@ package com.abin.mallchat.common.chat.service; import com.abin.mallchat.common.chat.domain.entity.RoomFriend; +import com.abin.mallchat.common.chat.domain.entity.RoomGroup; import java.util.List; @@ -15,4 +16,9 @@ public interface RoomService { * 创建一个单聊房间 */ RoomFriend createFriendRoom(List uidList); + + /** + * 创建一个群聊房间 + */ + RoomGroup createGroupRoom(Long uid); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/adapter/ChatAdapter.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/adapter/ChatAdapter.java index 8b1a59b..78f54db 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/adapter/ChatAdapter.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/adapter/ChatAdapter.java @@ -3,9 +3,11 @@ package com.abin.mallchat.common.chat.service.adapter; import com.abin.mallchat.common.chat.domain.entity.Contact; import com.abin.mallchat.common.chat.domain.entity.Room; import com.abin.mallchat.common.chat.domain.entity.RoomFriend; +import com.abin.mallchat.common.chat.domain.entity.RoomGroup; import com.abin.mallchat.common.chat.domain.enums.HotFlagEnum; import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum; import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum; +import com.abin.mallchat.common.user.domain.entity.User; import java.util.Collection; import java.util.List; @@ -41,7 +43,7 @@ public class ChatAdapter { roomFriend.setRoomId(roomId); roomFriend.setUid1(collect.get(0)); roomFriend.setUid2(collect.get(1)); - roomFriend.setKey(generateRoomKey(uidList)); + roomFriend.setRoomKey(generateRoomKey(uidList)); roomFriend.setStatus(NormalOrNoEnum.NORMAL.getStatus()); return roomFriend; } @@ -65,4 +67,12 @@ public class ChatAdapter { public static Long getFriendUid(RoomFriend roomFriend, Long uid) { return Objects.equals(uid, roomFriend.getUid1()) ? roomFriend.getUid2() : roomFriend.getUid1(); } + + public static RoomGroup buildGroupRoom(User user, Long roomId) { + RoomGroup roomGroup = new RoomGroup(); + roomGroup.setName(user.getName() + "的群组"); + roomGroup.setAvatar(user.getAvatar()); + roomGroup.setRoomId(roomId); + return roomGroup; + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/GroupMemberCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/GroupMemberCache.java new file mode 100644 index 0000000..b930b43 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/GroupMemberCache.java @@ -0,0 +1,44 @@ +package com.abin.mallchat.common.chat.service.cache; + +import com.abin.mallchat.common.chat.dao.GroupMemberDao; +import com.abin.mallchat.common.chat.dao.MessageDao; +import com.abin.mallchat.common.chat.dao.RoomGroupDao; +import com.abin.mallchat.common.chat.domain.entity.RoomGroup; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; + +/** + * Description: 群成员相关缓存 + * Author: abin + * Date: 2023-03-27 + */ +@Component +public class GroupMemberCache { + + @Autowired + private MessageDao messageDao; + @Autowired + private RoomGroupDao roomGroupDao; + @Autowired + private GroupMemberDao groupMemberDao; + + @Cacheable(cacheNames = "member", key = "'groupMember'+#roomId") + public List getMemberUidList(Long roomId) { + RoomGroup roomGroup = roomGroupDao.getByRoomId(roomId); + if (Objects.isNull(roomGroup)) { + return null; + } + return groupMemberDao.getMemberUidList(roomGroup.getId()); + } + + @CacheEvict(cacheNames = "member", key = "'groupMember'+#roomId") + public List evictMemberUidList(Long roomId) { + return null; + } + +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/HotRoomCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/HotRoomCache.java new file mode 100644 index 0000000..2d05c1b --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/HotRoomCache.java @@ -0,0 +1,42 @@ +package com.abin.mallchat.common.chat.service.cache; + +import cn.hutool.core.lang.Pair; +import com.abin.mallchat.common.common.constant.RedisKey; +import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq; +import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; +import com.abin.mallchat.common.common.utils.CursorUtils; +import com.abin.mallchat.common.common.utils.RedisUtils; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.Set; + +/** + * Description: 全局房间 + * Author: abin + * Date: 2023-07-23 + */ +@Component +public class HotRoomCache { + + /** + * 获取热门群聊翻页 + * + * @return + */ + public CursorPageBaseResp> getRoomCursorPage(CursorPageBaseReq pageBaseReq) { + return CursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.HOT_ROOM_ZET), Long::parseLong); + } + + public Set> getRoomRange(Double hotStart, Double hotEnd) { + return RedisUtils.zRangeByScoreWithScores(RedisKey.getKey(RedisKey.HOT_ROOM_ZET), hotStart, hotEnd); + } + + /** + * 更新热门群聊的最新时间 + */ + public void refreshActiveTime(Long roomId, Date refreshTime) { + RedisUtils.zAdd(RedisKey.getKey(RedisKey.HOT_ROOM_ZET), roomId, (double) refreshTime.getTime()); + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/MsgCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/MsgCache.java index 4ca0a9e..f7169d7 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/MsgCache.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/MsgCache.java @@ -2,7 +2,6 @@ package com.abin.mallchat.common.chat.service.cache; import com.abin.mallchat.common.chat.dao.MessageDao; import com.abin.mallchat.common.chat.domain.entity.Message; -import com.abin.mallchat.common.common.utils.CursorUtils; import com.abin.mallchat.common.user.dao.BlackDao; import com.abin.mallchat.common.user.dao.RoleDao; import com.abin.mallchat.common.user.dao.UserDao; @@ -19,8 +18,6 @@ import org.springframework.stereotype.Component; @Component public class MsgCache { - @Autowired - private CursorUtils cursorUtils; @Autowired private UserDao userDao; @Autowired diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomGroupCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomGroupCache.java index 28ba198..f85a570 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomGroupCache.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/RoomGroupCache.java @@ -23,8 +23,8 @@ public class RoomGroupCache extends AbstractRedisStringCache { private RoomGroupDao roomGroupDao; @Override - protected String getKey(Long groupId) { - return RedisKey.getKey(RedisKey.GROUP_INFO_STRING, groupId); + protected String getKey(Long roomId) { + return RedisKey.getKey(RedisKey.GROUP_INFO_STRING, roomId); } @Override diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/impl/RoomServiceImpl.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/impl/RoomServiceImpl.java index 4903fa3..47022e4 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/impl/RoomServiceImpl.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/impl/RoomServiceImpl.java @@ -1,14 +1,21 @@ package com.abin.mallchat.common.chat.service.impl; +import com.abin.mallchat.common.chat.dao.GroupMemberDao; import com.abin.mallchat.common.chat.dao.RoomDao; import com.abin.mallchat.common.chat.dao.RoomFriendDao; +import com.abin.mallchat.common.chat.dao.RoomGroupDao; +import com.abin.mallchat.common.chat.domain.entity.GroupMember; import com.abin.mallchat.common.chat.domain.entity.Room; import com.abin.mallchat.common.chat.domain.entity.RoomFriend; +import com.abin.mallchat.common.chat.domain.entity.RoomGroup; +import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum; import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum; import com.abin.mallchat.common.chat.service.RoomService; import com.abin.mallchat.common.chat.service.adapter.ChatAdapter; import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum; import com.abin.mallchat.common.common.utils.AssertUtil; +import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.common.user.service.cache.UserInfoCache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -28,6 +35,12 @@ public class RoomServiceImpl implements RoomService { private RoomFriendDao roomFriendDao; @Autowired private RoomDao roomDao; + @Autowired + private GroupMemberDao groupMemberDao; + @Autowired + private UserInfoCache userInfoCache; + @Autowired + private RoomGroupDao roomGroupDao; @Override @Transactional(rollbackFor = Exception.class) @@ -40,12 +53,32 @@ public class RoomServiceImpl implements RoomService { if (Objects.nonNull(roomFriend)) { //如果存在房间就恢复,适用于恢复好友场景 restoreRoomIfNeed(roomFriend); } else {//新建房间 - Room room = createRoom(RoomTypeEnum.GROUP); + Room room = createRoom(RoomTypeEnum.FRIEND); roomFriend = createFriendRoom(room.getId(), uidList); } return roomFriend; } + @Override + @Transactional(rollbackFor = Exception.class) + public RoomGroup createGroupRoom(Long uid) { + List selfGroup = groupMemberDao.getSelfGroup(uid); + AssertUtil.isEmpty(selfGroup, "每个人只能创建一个群"); + User user = userInfoCache.get(uid); + Room room = createRoom(RoomTypeEnum.GROUP); + //插入群 + RoomGroup roomGroup = ChatAdapter.buildGroupRoom(user, room.getId()); + roomGroupDao.save(roomGroup); + //插入群主 + GroupMember leader = GroupMember.builder() + .role(GroupRoleEnum.LEADER.getType()) + .groupId(roomGroup.getId()) + .uid(uid) + .build(); + groupMemberDao.save(leader); + return roomGroup; + } + private RoomFriend createFriendRoom(Long roomId, List uidList) { RoomFriend insert = ChatAdapter.buildFriendRoom(roomId, uidList); roomFriendDao.save(insert); diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java index 96bbb5a..38ee20d 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java @@ -16,6 +16,11 @@ public class RedisKey { */ public static final String OFFLINE_UID_ZET = "offline"; + /** + * 热门房间列表 + */ + public static final String HOT_ROOM_ZET = "hotRoom"; + /** * 用户信息 */ diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/GroupMemberAddEvent.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/GroupMemberAddEvent.java new file mode 100644 index 0000000..c131608 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/GroupMemberAddEvent.java @@ -0,0 +1,24 @@ +package com.abin.mallchat.common.common.event; + +import com.abin.mallchat.common.chat.domain.entity.GroupMember; +import com.abin.mallchat.common.chat.domain.entity.RoomGroup; +import lombok.Getter; +import org.springframework.context.ApplicationEvent; + +import java.util.List; + +@Getter +public class GroupMemberAddEvent extends ApplicationEvent { + + private final List memberList; + private final RoomGroup roomGroup; + private final Long inviteUid; + + public GroupMemberAddEvent(Object source, RoomGroup roomGroup, List memberList, Long inviteUid) { + super(source); + this.memberList = memberList; + this.roomGroup = roomGroup; + this.inviteUid = inviteUid; + } + +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/WSPushEvent.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/WSPushEvent.java new file mode 100644 index 0000000..197f217 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/event/WSPushEvent.java @@ -0,0 +1,50 @@ +package com.abin.mallchat.common.common.event; + +import com.abin.mallchat.common.user.domain.enums.WSBaseResp; +import com.abin.mallchat.common.user.domain.enums.WSPushTypeEnum; +import lombok.Getter; +import org.springframework.context.ApplicationEvent; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Getter +public class WSPushEvent extends ApplicationEvent { + /** + * 推送的ws消息 + */ + private final WSBaseResp wsBaseMsg; + /** + * 推送的uid + */ + private final List uidList; + + /** + * 推送类型 1个人 2全员 + * + * @see com.abin.mallchat.common.user.domain.enums.WSPushTypeEnum + */ + private final Integer pushType; + + public WSPushEvent(Object source, Long uid, WSBaseResp wsBaseMsg) { + super(source); + this.uidList = Collections.singletonList(uid); + this.wsBaseMsg = wsBaseMsg; + this.pushType = WSPushTypeEnum.USER.getType(); + } + + public WSPushEvent(Object source, List uidList, WSBaseResp wsBaseMsg) { + super(source); + this.uidList = uidList; + this.wsBaseMsg = wsBaseMsg; + this.pushType = WSPushTypeEnum.USER.getType(); + } + + public WSPushEvent(Object source, WSBaseResp wsBaseMsg) { + super(source); + this.uidList = new ArrayList<>(); + this.wsBaseMsg = wsBaseMsg; + this.pushType = WSPushTypeEnum.ALL.getType(); + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/CursorUtils.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/CursorUtils.java index ced5b1d..1cecfb2 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/CursorUtils.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/CursorUtils.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.data.redis.core.ZSetOperations; +import java.util.Date; import java.util.List; import java.util.Optional; import java.util.Set; @@ -55,10 +56,18 @@ public class CursorUtils { Page page = mapper.page(request.plusPage(), wrapper); String cursor = Optional.ofNullable(CollectionUtil.getLast(page.getRecords())) .map(cursorColumn) - .map(String::valueOf) + .map(CursorUtils::parseCursor) .orElse(null); Boolean isLast = page.getRecords().size() != request.getPageSize(); return new CursorPageBaseResp<>(cursor, isLast, page.getRecords()); } + private static String parseCursor(Object o) { + if (o instanceof Date) { + return String.valueOf(((Date) o).getTime()); + } else { + return o.toString(); + } + } + } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/RedisUtils.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/RedisUtils.java index 4d42b54..1676f94 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/RedisUtils.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/RedisUtils.java @@ -849,6 +849,10 @@ public class RedisUtils { return stringRedisTemplate.opsForZSet().range(key, start, end); } + public static Set zAll(String key) { + return stringRedisTemplate.opsForZSet().range(key, 0, -1); + } + /** * 获取集合元素, 并且把score值也获取 * @@ -882,8 +886,14 @@ public class RedisUtils { * @param max 最大值 * @return */ - public Set> zRangeByScoreWithScores(String key, - double min, double max) { + public static Set> zRangeByScoreWithScores(String key, + Double min, Double max) { + if (Objects.isNull(min)) { + min = Double.MIN_VALUE; + } + if (Objects.isNull(max)) { + max = Double.MAX_VALUE; + } return stringRedisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserApplyDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserApplyDao.java index 5def2ca..b52920f 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserApplyDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserApplyDao.java @@ -44,7 +44,7 @@ public class UserApplyDao extends ServiceImpl { return lambdaQuery() .eq(UserApply::getTargetId, uid) .eq(UserApply::getType, ApplyTypeEnum.ADD_FRIEND.getCode()) - .orderByAsc(UserApply::getCreateTime) + .orderByDesc(UserApply::getCreateTime) .page(page); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java index 0f4f7cb..ce9d558 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java @@ -1,10 +1,16 @@ package com.abin.mallchat.common.user.dao; +import cn.hutool.core.collection.CollectionUtil; import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum; +import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq; +import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; +import com.abin.mallchat.common.common.utils.CursorUtils; import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum; import com.abin.mallchat.common.user.mapper.UserMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; @@ -47,7 +53,7 @@ public class UserDao extends ServiceImpl { public List getMemberList() { return lambdaQuery() .eq(User::getStatus, NormalOrNoEnum.NORMAL.getStatus()) - .orderByDesc(User::getUpdateTime)//最近活跃的1000个人,可以用lastOptTime字段,但是该字段没索引,updateTime可平替 + .orderByDesc(User::getLastOptTime)//最近活跃的1000个人,可以用lastOptTime字段,但是该字段没索引,updateTime可平替 .last("limit 1000")//毕竟是大群聊,人数需要做个限制 .select(User::getId, User::getName, User::getAvatar) .list(); @@ -62,4 +68,23 @@ public class UserDao extends ServiceImpl { .list(); } + + public Integer getOnlineCount() { + return getOnlineCount(null); + } + + public Integer getOnlineCount(List memberUidList) { + return lambdaQuery() + .eq(User::getActiveStatus, ChatActiveStatusEnum.ONLINE.getStatus()) + .in(CollectionUtil.isNotEmpty(memberUidList), User::getId, memberUidList) + .count(); + } + + public CursorPageBaseResp getCursorPage(List memberUidList, CursorPageBaseReq request, ChatActiveStatusEnum online) { + return CursorUtils.getCursorPageByMysql(this, request, wrapper -> { + wrapper.eq(User::getActiveStatus, online.getStatus());//筛选上线或者离线的 + wrapper.in(CollectionUtils.isNotEmpty(memberUidList), User::getId, memberUidList);//普通群对uid列表做限制 + }, User::getLastOptTime); + } + } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/User.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/User.java index 95a6146..abca542 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/User.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/User.java @@ -28,6 +28,8 @@ public class User implements Serializable { private static final long serialVersionUID = 1L; + public static Long UID_SYSTEM = 1L;//系统uid + /** * 用户id */ diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserApply.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserApply.java index cf84697..f16a6a0 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserApply.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserApply.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -71,13 +71,13 @@ public class UserApply implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserFriend.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserFriend.java index 45a8d28..a587ca3 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserFriend.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserFriend.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -47,13 +47,13 @@ public class UserFriend implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserRole.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserRole.java index 075ffc9..76828b0 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserRole.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserRole.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -47,11 +47,11 @@ public class UserRole implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/OssSceneEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/OssSceneEnum.java similarity index 94% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/OssSceneEnum.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/OssSceneEnum.java index 67a5214..b922690 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/OssSceneEnum.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/OssSceneEnum.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.enums; +package com.abin.mallchat.common.user.domain.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBaseResp.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSBaseResp.java similarity index 69% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBaseResp.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSBaseResp.java index 1326bda..d02087b 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBaseResp.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSBaseResp.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.enums; import lombok.Data; @@ -12,7 +12,7 @@ public class WSBaseResp { /** * ws推送给前端的消息 * - * @see com.abin.mallchat.custom.user.domain.enums.WSRespTypeEnum + * @see WSRespTypeEnum */ private Integer type; private T data; diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSPushTypeEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSPushTypeEnum.java new file mode 100644 index 0000000..f5dae6b --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSPushTypeEnum.java @@ -0,0 +1,35 @@ +package com.abin.mallchat.common.user.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: abin + * Date: 2023-07-29 + */ +@AllArgsConstructor +@Getter +public enum WSPushTypeEnum { + USER(1, "个人"), + ALL(2, "全部连接用户"), + ; + + private final Integer type; + private final String desc; + + private static Map cache; + + static { + cache = Arrays.stream(WSPushTypeEnum.values()).collect(Collectors.toMap(WSPushTypeEnum::getType, Function.identity())); + } + + public static WSPushTypeEnum of(Integer type) { + return cache.get(type); + } +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSReqTypeEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSReqTypeEnum.java similarity index 94% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSReqTypeEnum.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSReqTypeEnum.java index af5a726..a7e8c32 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSReqTypeEnum.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSReqTypeEnum.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.enums; +package com.abin.mallchat.common.user.domain.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSRespTypeEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSRespTypeEnum.java similarity index 89% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSRespTypeEnum.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSRespTypeEnum.java index a201691..be8bcc1 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSRespTypeEnum.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/WSRespTypeEnum.java @@ -1,6 +1,6 @@ -package com.abin.mallchat.custom.user.domain.enums; +package com.abin.mallchat.common.user.domain.enums; -import com.abin.mallchat.custom.user.domain.vo.response.ws.*; +import com.abin.mallchat.common.user.domain.vo.response.ws.*; import lombok.AllArgsConstructor; import lombok.Getter; @@ -28,7 +28,6 @@ public enum WSRespTypeEnum { RECALL(9, "消息撤回", WSMsgRecall.class), APPLY(10, "好友申请", WSFriendApply.class), MEMBER_CHANGE(11, "成员变动", WSMemberChange.class), - MESSAGE_READ(12, "消息已读数", WSMessageRead.class), ; private final Integer type; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/ws/WSAuthorize.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/request/ws/WSAuthorize.java similarity index 84% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/ws/WSAuthorize.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/request/ws/WSAuthorize.java index c12fb05..f4cc37f 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/ws/WSAuthorize.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/request/ws/WSAuthorize.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.request.ws; +package com.abin.mallchat.common.user.domain.vo.request.ws; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/ws/WSBaseReq.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/request/ws/WSBaseReq.java similarity index 76% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/ws/WSBaseReq.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/request/ws/WSBaseReq.java index 58f64cb..ecffe56 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/ws/WSBaseReq.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/request/ws/WSBaseReq.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.request.ws; +package com.abin.mallchat.common.user.domain.vo.request.ws; import lombok.Data; @@ -12,7 +12,7 @@ public class WSBaseReq { /** * 请求类型 1.请求登录二维码,2心跳检测 * - * @see com.abin.mallchat.custom.user.domain.enums.WSReqTypeEnum + * @see com.abin.mallchat.common.user.domain.enums.WSReqTypeEnum */ private Integer type; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberResp.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/ChatMemberResp.java similarity index 92% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberResp.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/ChatMemberResp.java index a2f07fb..25aa117 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberResp.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/ChatMemberResp.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.chat.domain.vo.response; +package com.abin.mallchat.common.user.domain.vo.response.ws; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBlack.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSBlack.java similarity index 83% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBlack.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSBlack.java index 8619c01..03399e6 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBlack.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSBlack.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSFriendApply.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSFriendApply.java similarity index 88% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSFriendApply.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSFriendApply.java index 07cb8b4..1cd4b32 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSFriendApply.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSFriendApply.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSLoginSuccess.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSLoginSuccess.java similarity index 88% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSLoginSuccess.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSLoginSuccess.java index f27de78..e4a7677 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSLoginSuccess.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSLoginSuccess.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSLoginUrl.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSLoginUrl.java similarity index 84% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSLoginUrl.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSLoginUrl.java index ff3f486..86f0773 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSLoginUrl.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSLoginUrl.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMemberChange.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMemberChange.java similarity index 79% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMemberChange.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMemberChange.java index d6f291c..4e07989 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMemberChange.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMemberChange.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -18,9 +18,11 @@ import java.util.Date; @AllArgsConstructor @NoArgsConstructor public class WSMemberChange { + public static final Integer CHANGE_TYPE_ADD = 1; + public static final Integer CHANGE_TYPE_REMOVE = 2; @ApiModelProperty("群组id") private Long roomId; - @ApiModelProperty("变动人") + @ApiModelProperty("变动uid集合") private Long uid; @ApiModelProperty("变动类型 1加入群组 2移除群组") private Integer changeType; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMessage.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMessage.java similarity index 63% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMessage.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMessage.java index a3259d3..a506e17 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMessage.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMessage.java @@ -1,6 +1,6 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp; +import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp; import lombok.Data; /** diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMessageRead.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMessageRead.java similarity index 88% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMessageRead.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMessageRead.java index 37e56d7..398c4e2 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMessageRead.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMessageRead.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMsgMark.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMsgMark.java similarity index 94% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMsgMark.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMsgMark.java index 4e9aa93..872c9fb 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMsgMark.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMsgMark.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMsgRecall.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMsgRecall.java similarity index 82% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMsgRecall.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMsgRecall.java index e11b83b..ac089f9 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSMsgRecall.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSMsgRecall.java @@ -1,4 +1,4 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; import com.abin.mallchat.common.chat.domain.dto.ChatMsgRecallDTO; import lombok.Data; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSOnlineOfflineNotify.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSOnlineOfflineNotify.java similarity index 79% rename from mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSOnlineOfflineNotify.java rename to mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSOnlineOfflineNotify.java index f0f077e..1efb9b1 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSOnlineOfflineNotify.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/vo/response/ws/WSOnlineOfflineNotify.java @@ -1,6 +1,5 @@ -package com.abin.mallchat.custom.user.domain.vo.response.ws; +package com.abin.mallchat.common.user.domain.vo.response.ws; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java index c5cc861..819773f 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java @@ -70,6 +70,13 @@ public class UserCache { RedisUtils.zAdd(onlineKey, uid, optTime.getTime()); } + //获取用户上线列表 + public List getOnlineUidList() { + String onlineKey = RedisKey.getKey(RedisKey.ONLINE_UID_ZET); + Set strings = RedisUtils.zAll(onlineKey); + return strings.stream().map(Long::parseLong).collect(Collectors.toList()); + } + public boolean isOnline(Long uid) { String onlineKey = RedisKey.getKey(RedisKey.ONLINE_UID_ZET); return RedisUtils.zIsMember(onlineKey, uid); diff --git a/mallchat-common/src/main/resources/application.yml b/mallchat-common/src/main/resources/application.yml index fc98e64..ae8591f 100644 --- a/mallchat-common/src/main/resources/application.yml +++ b/mallchat-common/src/main/resources/application.yml @@ -12,7 +12,7 @@ mybatis-plus: spring: profiles: #运行的环境 - active: test + active: my-prod application: name: mallchat datasource: diff --git a/mallchat-common/src/main/resources/mapper/chat/ContactMapper.xml b/mallchat-common/src/main/resources/mapper/chat/ContactMapper.xml index 87c4137..f27251b 100644 --- a/mallchat-common/src/main/resources/mapper/chat/ContactMapper.xml +++ b/mallchat-common/src/main/resources/mapper/chat/ContactMapper.xml @@ -2,4 +2,14 @@ + + insert into contact(`room_id`,`uid`,`last_msg_id`,`active_time`) + values + + (#{roomId},#{uid},#{msgId},#{activeTime}) + + on DUPLICATE KEY UPDATE + `last_msg_id`=VALUES(last_msg_id), + `active_time`=VALUES(active_time) + diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java index 1cf8b36..8a12690 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java @@ -2,17 +2,19 @@ package com.abin.mallchat.custom.chat.controller; import com.abin.mallchat.common.chat.domain.dto.MsgReadInfoDTO; +import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp; 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; import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; import com.abin.mallchat.common.common.utils.RequestHolder; import com.abin.mallchat.common.user.domain.enums.BlackTypeEnum; +import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp; import com.abin.mallchat.common.user.service.cache.UserCache; import com.abin.mallchat.custom.chat.domain.vo.request.*; -import com.abin.mallchat.custom.chat.domain.vo.response.*; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberListResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageReadResp; import com.abin.mallchat.custom.chat.service.ChatService; -import com.abin.mallchat.custom.user.service.impl.UserServiceImpl; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -43,17 +45,12 @@ public class ChatController { @Autowired private UserCache userCache; - @GetMapping("/public/room/page") - @ApiOperation("会话列表") - public ApiResult> getRoomPage(@Valid CursorPageBaseReq request) { - return ApiResult.success(chatService.getRoomPage(request, RequestHolder.get().getUid())); - } - @GetMapping("/public/member/page") @ApiOperation("群成员列表") + @Deprecated @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP) - public ApiResult> getMemberPage(@Valid CursorPageBaseReq request) { - CursorPageBaseResp memberPage = chatService.getMemberPage(request); + public ApiResult> getMemberPage(@Valid MemberReq request) { + CursorPageBaseResp memberPage = chatService.getMemberPage(null, request); filterBlackMember(memberPage); return ApiResult.success(memberPage); } @@ -81,9 +78,6 @@ public class ChatController { return ApiResult.success(chatService.getMemberStatistic()); } - @Autowired - private UserServiceImpl userService; - @GetMapping("/public/msg/page") @ApiOperation("消息列表") @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP) @@ -138,5 +132,13 @@ public class ChatController { Long uid = RequestHolder.get().getUid(); return ApiResult.success(chatService.getMsgReadInfo(uid, request)); } + + @PutMapping("/msg/read") + @ApiOperation("消息阅读上报") + public ApiResult msgRead(@Valid @RequestBody ChatMessageMemberReq request) { + Long uid = RequestHolder.get().getUid(); + chatService.msgRead(uid, request); + return ApiResult.success(); + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ContactController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ContactController.java index cbb5ee5..b627161 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ContactController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ContactController.java @@ -2,12 +2,13 @@ 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.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.custom.chat.domain.vo.response.ChatRoomResp; import com.abin.mallchat.custom.chat.service.ChatService; -import com.abin.mallchat.custom.chat.service.RoomService; +import com.abin.mallchat.custom.chat.service.RoomAppService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -34,7 +35,7 @@ public class ContactController { @Autowired private ChatService chatService; @Autowired - private RoomService roomService; + private RoomAppService roomService; @GetMapping("/public/contact/page") @ApiOperation("会话列表") @@ -43,6 +44,11 @@ public class ContactController { return ApiResult.success(roomService.getContactPage(request, uid)); } - + @GetMapping("/public/contact/detail") + @ApiOperation("会话详情") + public ApiResult getRoomPage(@Valid IdReqVO request) { + Long uid = RequestHolder.get().getUid(); + return ApiResult.success(roomService.getContactDetail(uid, request.getId())); + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/RoomController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/RoomController.java index fb71cbf..fe280e5 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/RoomController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/RoomController.java @@ -1,20 +1,16 @@ 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.domain.vo.response.IdRespVO; 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.common.user.domain.vo.response.ws.ChatMemberResp; +import com.abin.mallchat.custom.chat.domain.vo.request.*; 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 com.abin.mallchat.custom.chat.service.RoomAppService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -38,41 +34,48 @@ import java.util.List; @Slf4j public class RoomController { @Autowired - private ChatService chatService; - @Autowired - private UserCache userCache; + private RoomAppService roomService; @GetMapping("/public/group") @ApiOperation("群组详情") public ApiResult groupDetail(@Valid IdReqVO request) { - return ApiResult.success(); + Long uid = RequestHolder.get().getUid(); + return ApiResult.success(roomService.getGroupDetail(uid, request.getId())); } @GetMapping("/public/group/member/page") @ApiOperation("群成员列表") - @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP) public ApiResult> getMemberPage(@Valid MemberReq request) { - CursorPageBaseResp memberPage = chatService.getMemberPage(request); - return ApiResult.success(memberPage); + return ApiResult.success(roomService.getMemberPage(request)); } @GetMapping("/group/member/list") @ApiOperation("房间内的所有群成员列表-@专用") public ApiResult> getMemberList(@Valid ChatMessageMemberReq request) { - return ApiResult.success(chatService.getMemberList(request)); + return ApiResult.success(roomService.getMemberList(request)); } @DeleteMapping("/group/member") @ApiOperation("移除成员") public ApiResult delMember(@Valid @RequestBody MemberDelReq request) { Long uid = RequestHolder.get().getUid(); + roomService.delMember(uid, request); return ApiResult.success(); } + @PostMapping("/group") + @ApiOperation("新增群组") + public ApiResult addGroup(@Valid @RequestBody GroupAddReq request) { + Long uid = RequestHolder.get().getUid(); + Long roomId = roomService.addGroup(uid, request); + return ApiResult.success(IdRespVO.id(roomId)); + } + @PostMapping("/group/member") @ApiOperation("邀请好友") - public ApiResult> addMember(@Valid @RequestBody MemberAddReq request) { + public ApiResult addMember(@Valid @RequestBody MemberAddReq request) { Long uid = RequestHolder.get().getUid(); + roomService.addMember(uid, request); return ApiResult.success(); } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/enums/GroupRoleAPPEnum.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/enums/GroupRoleAPPEnum.java new file mode 100644 index 0000000..810af3c --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/enums/GroupRoleAPPEnum.java @@ -0,0 +1,37 @@ +package com.abin.mallchat.custom.chat.domain.vo.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: abin + * Date: 2023-03-19 + */ +@AllArgsConstructor +@Getter +public enum GroupRoleAPPEnum { + LEADER(1, "群主"), + MANAGER(2, "管理"), + MEMBER(3, "普通成员"), + REMOVE(4, "被移除的成员"), + ; + + private final Integer type; + private final String desc; + + private static Map cache; + + static { + cache = Arrays.stream(GroupRoleAPPEnum.values()).collect(Collectors.toMap(GroupRoleAPPEnum::getType, Function.identity())); + } + + public static GroupRoleAPPEnum of(Integer type) { + return cache.get(type); + } +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/GroupAddReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/GroupAddReq.java new file mode 100644 index 0000000..a5ade0b --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/GroupAddReq.java @@ -0,0 +1,27 @@ +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: abin + * Date: 2023-03-29 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class GroupAddReq { + @NotNull + @Size(min = 1, max = 50) + @ApiModelProperty("邀请的uid") + private List uidList; +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/MemberAddReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/MemberAddReq.java index 661148a..3c0ce8e 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/MemberAddReq.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/MemberAddReq.java @@ -21,7 +21,7 @@ import java.util.List; @NoArgsConstructor public class MemberAddReq { @NotNull - @ApiModelProperty("会话id") + @ApiModelProperty("房间id") private Long roomId; @NotNull diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/MemberReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/MemberReq.java index ce41b7c..75f78b1 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/MemberReq.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/MemberReq.java @@ -7,8 +7,6 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; - /** * Description: * Author: abin @@ -20,6 +18,5 @@ import javax.validation.constraints.NotNull; @NoArgsConstructor public class MemberReq extends CursorPageBaseReq { @ApiModelProperty("房间号") - @NotNull - private Long roomId; + private Long roomId = 1L; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberRespV1.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberRespV1.java deleted file mode 100644 index bf7d24d..0000000 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberRespV1.java +++ /dev/null @@ -1,30 +0,0 @@ -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; - -import java.util.Date; - -/** - * Description: 群成员列表的成员信息 - * Author: abin - * Date: 2023-03-23 - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class ChatMemberRespV1 { - @ApiModelProperty("uid") - private Long uid; - /** - * @see com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum - */ - @ApiModelProperty("在线状态 1在线 2离线") - private Integer activeStatus; - @ApiModelProperty("最后一次上下线时间") - private Date lastOptTime; -} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMessageResp.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMessageResp.java deleted file mode 100644 index 9d40c8d..0000000 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMessageResp.java +++ /dev/null @@ -1,77 +0,0 @@ -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; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; -import java.util.Date; - -/** - * Description: 消息 - * Author: abin - * Date: 2023-03-23 - */ -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class ChatMessageResp { - - @ApiModelProperty("发送者信息") - private UserInfo fromUser; - @ApiModelProperty("消息详情") - private Message message; - - @ApiModelProperty("申请消息") - private ApplyMessage applyMessage; - - @Data - public static class UserInfo { - @ApiModelProperty("用户id") - private Long uid; - } - - @Data - public static class Message { - @ApiModelProperty("消息id") - private Long id; - @ApiModelProperty("消息发送时间") - private Date sendTime; - @ApiModelProperty("消息类型 1正常文本 2.撤回消息") - private Integer type; - @ApiModelProperty("消息内容不同的消息类型,内容体不同,见https://www.yuque.com/snab/mallcaht/rkb2uz5k1qqdmcmd") - private Object body; - @ApiModelProperty("消息标记") - private MessageMark messageMark; - } - - @Data - public static class MessageMark { - @ApiModelProperty("点赞数") - private Integer likeCount; - @ApiModelProperty("该用户是否已经点赞 0否 1是") - private Integer userLike; - @ApiModelProperty("举报数") - private Integer dislikeCount; - @ApiModelProperty("该用户是否已经举报 0否 1是") - private Integer userDislike; - } - - @Data - public static class ApplyMessage { - @ApiModelProperty("申请id") - private Long applyId; - - @ApiModelProperty("申请信息") - private String applyMsg; - - @ApiModelProperty("申请发送时间") - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") - private LocalDateTime sendTime; - - } -} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatRoomResp.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatRoomResp.java index 9913bf8..2faec3f 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatRoomResp.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatRoomResp.java @@ -31,7 +31,7 @@ public class ChatRoomResp { @ApiModelProperty("会话头像") private String avatar; @ApiModelProperty("房间最后活跃时间(用来排序)") - private Date lastActiveTime; + private Date activeTime; @ApiModelProperty("未读数") private Integer unreadCount; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/MemberResp.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/MemberResp.java index 0bc8c79..2c39a5a 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/MemberResp.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/MemberResp.java @@ -16,14 +16,17 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class MemberResp { - @ApiModelProperty("群id") - private Long id; + @ApiModelProperty("房间id") + private Long roomId; @ApiModelProperty("群名称") - private Long groupName; + private String groupName; + @ApiModelProperty("群头像") + private String avatar; @ApiModelProperty("在线人数") private Long onlineNum;//在线人数 - @ApiModelProperty("群聊描述") - private String desc;//在线人数 + /** + * @see com.abin.mallchat.custom.chat.domain.vo.enums.GroupRoleAPPEnum + */ @ApiModelProperty("成员角色 1群主 2管理员 3普通成员 4踢出群聊") - private Integer role;//在线人数 + private Integer role; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java index 48c083f..5f9e973 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java @@ -2,10 +2,14 @@ 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.chat.domain.vo.response.ChatMessageResp; import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq; import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; +import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp; import com.abin.mallchat.custom.chat.domain.vo.request.*; -import com.abin.mallchat.custom.chat.domain.vo.response.*; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberListResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageReadResp; import javax.annotation.Nullable; import java.util.Collection; @@ -46,10 +50,11 @@ public interface ChatService { /** * 获取群成员列表 * + * @param memberUidList * @param request * @return */ - CursorPageBaseResp getMemberPage(CursorPageBaseReq request); + CursorPageBaseResp getMemberPage(List memberUidList, CursorPageBaseReq request); /** * 获取消息列表 @@ -59,15 +64,6 @@ public interface ChatService { */ CursorPageBaseResp getMsgPage(ChatMessagePageReq request, @Nullable Long receiveUid); - /** - * 获取会话列表 - * - * @param request - * @param uid - * @return - */ - CursorPageBaseResp getRoomPage(CursorPageBaseReq request, Long uid); - ChatMemberStatisticResp getMemberStatistic(); void setMsgMark(Long uid, ChatMessageMarkReq request); @@ -79,4 +75,6 @@ public interface ChatService { Collection getMsgReadInfo(Long uid, ChatMessageReadInfoReq request); CursorPageBaseResp getReadPage(Long uid, ChatMessageReadReq request); + + void msgRead(Long uid, ChatMessageMemberReq request); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/RoomAppService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/RoomAppService.java new file mode 100644 index 0000000..8b5685d --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/RoomAppService.java @@ -0,0 +1,40 @@ +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.common.user.domain.vo.response.ws.ChatMemberResp; +import com.abin.mallchat.custom.chat.domain.vo.request.*; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberListResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp; +import com.abin.mallchat.custom.chat.domain.vo.response.MemberResp; + +import java.util.List; + +/** + * Description: + * Author: abin + * Date: 2023-07-22 + */ +public interface RoomAppService { + /** + * 获取会话列表--支持未登录态 + */ + CursorPageBaseResp getContactPage(CursorPageBaseReq request, Long uid); + + /** + * 获取群组信息 + */ + MemberResp getGroupDetail(Long uid, long roomId); + + CursorPageBaseResp getMemberPage(MemberReq request); + + List getMemberList(ChatMessageMemberReq request); + + void delMember(Long uid, MemberDelReq request); + + void addMember(Long uid, MemberAddReq request); + + Long addGroup(Long uid, GroupAddReq request); + + ChatRoomResp getContactDetail(Long uid, Long roomId); +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/RoomService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/RoomService.java deleted file mode 100644 index 0266882..0000000 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/RoomService.java +++ /dev/null @@ -1,17 +0,0 @@ -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: abin - * Date: 2023-07-22 - */ -public interface RoomService { - /** - * 获取会话列表--支持未登录态 - */ - CursorPageBaseResp getContactPage(CursorPageBaseReq request, Long uid); -} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MemberAdapter.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MemberAdapter.java index e44695d..88c4dbd 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MemberAdapter.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MemberAdapter.java @@ -1,21 +1,29 @@ package com.abin.mallchat.custom.chat.service.adapter; -import cn.hutool.core.lang.Pair; +import com.abin.mallchat.common.chat.domain.entity.GroupMember; +import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum; import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.domain.entity.UserFriend; -import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum; +import com.abin.mallchat.common.user.domain.enums.WSBaseResp; +import com.abin.mallchat.common.user.domain.enums.WSRespTypeEnum; +import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp; +import com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange; import com.abin.mallchat.common.user.service.cache.UserCache; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberListResp; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.Date; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import static com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange.CHANGE_TYPE_ADD; +import static com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange.CHANGE_TYPE_REMOVE; + /** * Description: 成员适配器 * Author: abin @@ -27,12 +35,12 @@ public class MemberAdapter { @Autowired private UserCache userCache; - public List buildMember(List> list, ChatActiveStatusEnum statusEnum) { + public static List buildMember(List list) { return list.stream().map(a -> { ChatMemberResp resp = new ChatMemberResp(); - resp.setActiveStatus(statusEnum.getStatus()); - resp.setLastOptTime(new Date(a.getValue().longValue())); - resp.setUid(a.getKey()); + resp.setActiveStatus(a.getActiveStatus()); + resp.setLastOptTime(a.getLastOptTime()); + resp.setUid(a.getId()); return resp; }).collect(Collectors.toList()); } @@ -50,4 +58,53 @@ public class MemberAdapter { return resp; }).collect(Collectors.toList()); } + + + public static List buildMemberList(List memberList) { + return memberList.stream() + .map(a -> { + ChatMemberListResp resp = new ChatMemberListResp(); + BeanUtils.copyProperties(a, resp); + resp.setUid(a.getId()); + return resp; + }).collect(Collectors.toList()); + } + + public static List buildMemberList(Map batch) { + return buildMemberList(new ArrayList<>(batch.values())); + } + + public static List buildMemberAdd(Long groupId, List waitAddUidList) { + return waitAddUidList.stream().map(a -> { + GroupMember member = new GroupMember(); + member.setGroupId(groupId); + member.setUid(a); + member.setRole(GroupRoleEnum.MEMBER.getType()); + return member; + }).collect(Collectors.toList()); + } + + public static WSBaseResp buildMemberAddWS(Long roomId, User user) { + WSBaseResp wsBaseResp = new WSBaseResp<>(); + wsBaseResp.setType(WSRespTypeEnum.MEMBER_CHANGE.getType()); + WSMemberChange wsMemberChange = new WSMemberChange(); + wsMemberChange.setActiveStatus(user.getActiveStatus()); + wsMemberChange.setLastOptTime(user.getLastOptTime()); + wsMemberChange.setUid(user.getId()); + wsMemberChange.setRoomId(roomId); + wsMemberChange.setChangeType(CHANGE_TYPE_ADD); + wsBaseResp.setData(wsMemberChange); + return wsBaseResp; + } + + public static WSBaseResp buildMemberRemoveWS(Long roomId, Long uid) { + WSBaseResp wsBaseResp = new WSBaseResp<>(); + wsBaseResp.setType(WSRespTypeEnum.MEMBER_CHANGE.getType()); + WSMemberChange wsMemberChange = new WSMemberChange(); + wsMemberChange.setUid(uid); + wsMemberChange.setRoomId(roomId); + wsMemberChange.setChangeType(CHANGE_TYPE_REMOVE); + wsBaseResp.setData(wsMemberChange); + return wsBaseResp; + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java index 5fa2a71..a368954 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java @@ -6,11 +6,10 @@ import com.abin.mallchat.common.chat.domain.entity.MessageMark; import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum; import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum; import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum; +import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp; 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; @@ -79,22 +78,6 @@ public class MessageAdapter { return userInfo; } - public static WSApplyMessage buildApplyResp(UserApply userApply) { - WSApplyMessage wsApplyMessage = new WSApplyMessage(); - wsApplyMessage.setApplyMessage(buildApplyMessage(userApply)); - wsApplyMessage.setFromUser(buildFromUser(userApply.getUid())); - return wsApplyMessage; - } - - private static ChatMessageResp.ApplyMessage buildApplyMessage(UserApply userApply) { - ChatMessageResp.ApplyMessage applyMessage = new ChatMessageResp.ApplyMessage(); - applyMessage.setApplyId(userApply.getId()); - applyMessage.setApplyMsg(userApply.getMsg()); - applyMessage.setSendTime(userApply.getCreateTime()); - return applyMessage; - } - - public static ChatMessageReq buildAgreeMsg(Long roomId) { ChatMessageReq chatMessageReq = new ChatMessageReq(); chatMessageReq.setRoomId(roomId); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/RoomAdapter.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/RoomAdapter.java index 360883d..9d28841 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/RoomAdapter.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/RoomAdapter.java @@ -2,11 +2,18 @@ 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.GroupMember; import com.abin.mallchat.common.chat.domain.entity.Room; +import com.abin.mallchat.common.chat.domain.entity.RoomGroup; +import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum; +import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum; +import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageReadResp; import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -22,7 +29,7 @@ public class RoomAdapter { .map(a -> { ChatRoomResp resp = new ChatRoomResp(); BeanUtil.copyProperties(a, resp); - resp.setLastActiveTime(a.getActiveTime()); + resp.setActiveTime(a.getActiveTime()); return resp; }).collect(Collectors.toList()); } @@ -34,4 +41,31 @@ public class RoomAdapter { return resp; }).collect(Collectors.toList()); } + + public static List buildGroupMemberBatch(List uidList, Long groupId) { + return uidList.stream() + .distinct() + .map(uid -> { + GroupMember member = new GroupMember(); + member.setRole(GroupRoleEnum.MEMBER.getType()); + member.setUid(uid); + member.setGroupId(groupId); + return member; + }).collect(Collectors.toList()); + } + + public static ChatMessageReq buildGroupAddMessage(RoomGroup groupRoom, User inviter, Map member) { + ChatMessageReq chatMessageReq = new ChatMessageReq(); + chatMessageReq.setRoomId(groupRoom.getRoomId()); + chatMessageReq.setMsgType(MessageTypeEnum.SYSTEM.getType()); + StringBuilder sb = new StringBuilder(); + sb.append("\"") + .append(inviter.getName()) + .append("\"") + .append("邀请") + .append(member.values().stream().map(u -> "\"" + u.getName() + "\"").collect(Collectors.joining(","))) + .append("加入群聊"); + chatMessageReq.setBody(sb.toString()); + return chatMessageReq; + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java index cb9539b..6171cc8 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java @@ -13,9 +13,9 @@ 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.domain.vo.response.ChatMessageResp; 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; @@ -23,13 +23,17 @@ import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; import com.abin.mallchat.common.common.event.MessageSendEvent; import com.abin.mallchat.common.common.utils.AssertUtil; import com.abin.mallchat.common.user.dao.UserDao; +import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum; import com.abin.mallchat.common.user.domain.enums.RoleEnum; +import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp; import com.abin.mallchat.common.user.service.IRoleService; import com.abin.mallchat.common.user.service.cache.ItemCache; import com.abin.mallchat.common.user.service.cache.UserCache; import com.abin.mallchat.custom.chat.domain.vo.request.*; -import com.abin.mallchat.custom.chat.domain.vo.response.*; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberListResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageReadResp; import com.abin.mallchat.custom.chat.service.ChatService; import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter; import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter; @@ -116,26 +120,26 @@ public class ChatServiceImpl implements ChatService { } @Override - public CursorPageBaseResp getMemberPage(CursorPageBaseReq request) { + public CursorPageBaseResp getMemberPage(List memberUidList, CursorPageBaseReq request) { Pair pair = ChatMemberHelper.getCursorPair(request.getCursor()); ChatActiveStatusEnum activeStatusEnum = pair.getKey(); String timeCursor = pair.getValue(); List resultList = new ArrayList<>();//最终列表 Boolean isLast = Boolean.FALSE; if (activeStatusEnum == ChatActiveStatusEnum.ONLINE) {//在线列表 - CursorPageBaseResp> cursorPage = userCache.getOnlineCursorPage(new CursorPageBaseReq(request.getPageSize(), timeCursor)); - resultList.addAll(memberAdapter.buildMember(cursorPage.getList(), ChatActiveStatusEnum.ONLINE));//添加在线列表 + CursorPageBaseResp cursorPage = userDao.getCursorPage(memberUidList, request, ChatActiveStatusEnum.ONLINE); + resultList.addAll(MemberAdapter.buildMember(cursorPage.getList()));//添加在线列表 if (cursorPage.getIsLast()) {//如果是最后一页,从离线列表再补点数据 - Integer leftSize = request.getPageSize() - cursorPage.getList().size(); - cursorPage = userCache.getOfflineCursorPage(new CursorPageBaseReq(leftSize, null)); - resultList.addAll(memberAdapter.buildMember(cursorPage.getList(), ChatActiveStatusEnum.OFFLINE));//添加离线线列表 activeStatusEnum = ChatActiveStatusEnum.OFFLINE; + Integer leftSize = request.getPageSize() - cursorPage.getList().size(); + cursorPage = userDao.getCursorPage(memberUidList, new CursorPageBaseReq(leftSize, null), ChatActiveStatusEnum.OFFLINE); + resultList.addAll(MemberAdapter.buildMember(cursorPage.getList()));//添加离线线列表 } timeCursor = cursorPage.getCursor(); isLast = cursorPage.getIsLast(); } else if (activeStatusEnum == ChatActiveStatusEnum.OFFLINE) {//离线列表 - CursorPageBaseResp> cursorPage = userCache.getOfflineCursorPage(new CursorPageBaseReq(request.getPageSize(), timeCursor)); - resultList.addAll(memberAdapter.buildMember(cursorPage.getList(), ChatActiveStatusEnum.OFFLINE));//添加离线线列表 + CursorPageBaseResp cursorPage = userDao.getCursorPage(memberUidList, request, ChatActiveStatusEnum.OFFLINE); + resultList.addAll(MemberAdapter.buildMember(cursorPage.getList()));//添加离线线列表 timeCursor = cursorPage.getCursor(); isLast = cursorPage.getIsLast(); } @@ -152,18 +156,6 @@ public class ChatServiceImpl implements ChatService { return CursorPageBaseResp.init(cursorPage, getMsgRespBatch(cursorPage.getList(), receiveUid)); } - @Override - public CursorPageBaseResp getRoomPage(CursorPageBaseReq request, Long uid) { - CursorPageBaseResp cursorPage = roomDao.getCursorPage(request); - ArrayList rooms = new ArrayList<>(cursorPage.getList()); - if (request.isFirstPage()) { - //第一页插入置顶的大群聊 - Room group = roomDao.getById(ROOM_GROUP_ID); - rooms.add(0, group); - } - return CursorPageBaseResp.init(cursorPage, RoomAdapter.buildResp(rooms)); - } - @Override public ChatMemberStatisticResp getMemberStatistic() { System.out.println(Thread.currentThread().getName()); @@ -240,6 +232,24 @@ public class ChatServiceImpl implements ChatService { return CursorPageBaseResp.init(page, RoomAdapter.buildReadResp(page.getList())); } + @Override + @RedissonLock(key = "#uid") + public void msgRead(Long uid, ChatMessageMemberReq request) { + Contact contact = contactDao.get(uid, request.getRoomId()); + if (Objects.nonNull(contact)) { + Contact update = new Contact(); + update.setId(contact.getId()); + update.setReadTime(new Date()); + contactDao.updateById(update); + } else { + Contact insert = new Contact(); + insert.setUid(uid); + insert.setRoomId(request.getRoomId()); + insert.setReadTime(new Date()); + contactDao.save(insert); + } + } + private void checkRecall(Long uid, Message message) { AssertUtil.isNotEmpty(message, "消息有误"); AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL, "消息无法撤回"); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/RoomAppServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/RoomAppServiceImpl.java new file mode 100644 index 0000000..70d3054 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/RoomAppServiceImpl.java @@ -0,0 +1,377 @@ +package com.abin.mallchat.custom.chat.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.lang.Pair; +import com.abin.mallchat.common.chat.dao.ContactDao; +import com.abin.mallchat.common.chat.dao.GroupMemberDao; +import com.abin.mallchat.common.chat.dao.MessageDao; +import com.abin.mallchat.common.chat.domain.dto.RoomBaseInfo; +import com.abin.mallchat.common.chat.domain.entity.*; +import com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum; +import com.abin.mallchat.common.chat.domain.enums.HotFlagEnum; +import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum; +import com.abin.mallchat.common.chat.service.RoomService; +import com.abin.mallchat.common.chat.service.adapter.ChatAdapter; +import com.abin.mallchat.common.chat.service.cache.*; +import com.abin.mallchat.common.common.annotation.RedissonLock; +import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq; +import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; +import com.abin.mallchat.common.common.event.GroupMemberAddEvent; +import com.abin.mallchat.common.common.event.WSPushEvent; +import com.abin.mallchat.common.common.utils.AssertUtil; +import com.abin.mallchat.common.user.dao.UserDao; +import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.common.user.domain.enums.RoleEnum; +import com.abin.mallchat.common.user.domain.enums.WSBaseResp; +import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp; +import com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange; +import com.abin.mallchat.common.user.service.IRoleService; +import com.abin.mallchat.common.user.service.cache.UserCache; +import com.abin.mallchat.common.user.service.cache.UserInfoCache; +import com.abin.mallchat.custom.chat.domain.vo.enums.GroupRoleAPPEnum; +import com.abin.mallchat.custom.chat.domain.vo.request.*; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberListResp; +import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp; +import com.abin.mallchat.custom.chat.domain.vo.response.MemberResp; +import com.abin.mallchat.custom.chat.service.ChatService; +import com.abin.mallchat.custom.chat.service.RoomAppService; +import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter; +import com.abin.mallchat.custom.chat.service.adapter.RoomAdapter; +import com.abin.mallchat.custom.chat.service.strategy.msg.AbstractMsgHandler; +import com.abin.mallchat.custom.chat.service.strategy.msg.MsgHandlerFactory; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Description: + * Author: abin + * Date: 2023-07-22 + */ +@Service +public class RoomAppServiceImpl implements RoomAppService { + + @Autowired + private ContactDao contactDao; + @Autowired + private RoomCache roomCache; + @Autowired + private RoomGroupCache roomGroupCache; + @Autowired + private RoomFriendCache roomFriendCache; + @Autowired + private UserInfoCache userInfoCache; + @Autowired + private MessageDao messageDao; + @Autowired + private HotRoomCache hotRoomCache; + @Autowired + private UserCache userCache; + @Autowired + private GroupMemberDao groupMemberDao; + @Autowired + private UserDao userDao; + @Autowired + private ChatService chatService; + @Autowired + private IRoleService iRoleService; + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + @Autowired + private RoomService roomService; + @Autowired + private GroupMemberCache groupMemberCache; + + @Override + public CursorPageBaseResp getContactPage(CursorPageBaseReq request, Long uid) { + //查出用户要展示的会话列表 + CursorPageBaseResp page; + if (Objects.nonNull(uid)) { + Double hotStart = getCursorOrNull(request.getCursor()); + Double hotEnd; + //用户基础会话 + CursorPageBaseResp contactPage = contactDao.getContactPage(uid, request); + List baseRoomIds = contactPage.getList().stream().map(Contact::getRoomId).collect(Collectors.toList()); + hotEnd = getCursorOrNull(contactPage.getCursor()); + //热门房间 + Set> typedTuples = hotRoomCache.getRoomRange(hotStart, hotEnd); + List hotRoomIds = typedTuples.stream().map(ZSetOperations.TypedTuple::getValue).filter(Objects::nonNull).map(Long::parseLong).collect(Collectors.toList()); + baseRoomIds.addAll(hotRoomIds); + //基础会话和热门房间合并 + page = CursorPageBaseResp.init(contactPage, baseRoomIds); + } else {//用户未登录,只查全局房间 + CursorPageBaseResp> roomCursorPage = hotRoomCache.getRoomCursorPage(request); + List roomIds = roomCursorPage.getList().stream().map(Pair::getKey).collect(Collectors.toList()); + page = CursorPageBaseResp.init(roomCursorPage, roomIds); + } + //最后组装会话信息(名称,头像,未读数等) + List result = buildContactResp(uid, page.getList()); + return CursorPageBaseResp.init(page, result); + } + + @Override + public ChatRoomResp getContactDetail(Long uid, Long roomId) { + Room room = roomCache.get(roomId); + AssertUtil.isNotEmpty(room, "房间号有误"); + return buildContactResp(uid, Collections.singletonList(roomId)).get(0); + } + + @Override + public MemberResp getGroupDetail(Long uid, long roomId) { + RoomGroup roomGroup = roomGroupCache.get(roomId); + Room room = roomCache.get(roomId); + AssertUtil.isNotEmpty(roomGroup, "roomId有误"); + Long onlineNum; + if (isHotGroup(room)) {//热点群从redis取人数 + onlineNum = userCache.getOnlineNum(); + } else { + List memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId()); + onlineNum = userDao.getOnlineCount(memberUidList).longValue(); + } + GroupRoleAPPEnum groupRole = getGroupRole(uid, roomGroup, room); + return MemberResp.builder() + .avatar(roomGroup.getAvatar()) + .roomId(roomId) + .groupName(roomGroup.getName()) + .onlineNum(onlineNum) + .role(groupRole.getType()) + .build(); + } + + @Override + public CursorPageBaseResp getMemberPage(MemberReq request) { + Room room = roomCache.get(request.getRoomId()); + AssertUtil.isNotEmpty(room, "房间号有误"); + List memberUidList = null; + if (isHotGroup(room)) {//全员群展示所有用户 + memberUidList = null; + } else {//只展示房间内的群成员 + RoomGroup roomGroup = roomGroupCache.get(request.getRoomId()); + memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId()); + } + return chatService.getMemberPage(memberUidList, request); + } + + @Override + @Cacheable(cacheNames = "member", key = "'memberList.'+#request.roomId") + public List getMemberList(ChatMessageMemberReq request) { + Room room = roomCache.get(request.getRoomId()); + AssertUtil.isNotEmpty(room, "房间号有误"); + if (isHotGroup(room)) {//全员群展示所有用户100名 + List memberList = userDao.getMemberList(); + return MemberAdapter.buildMemberList(memberList); + } else { + RoomGroup roomGroup = roomGroupCache.get(request.getRoomId()); + List memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId()); + Map batch = userInfoCache.getBatch(memberUidList); + return MemberAdapter.buildMemberList(batch); + } + } + + @Override + public void delMember(Long uid, MemberDelReq request) { + Room room = roomCache.get(request.getRoomId()); + AssertUtil.isNotEmpty(room, "房间号有误"); + RoomGroup roomGroup = roomGroupCache.get(request.getRoomId()); + AssertUtil.isNotEmpty(roomGroup, "房间号有误"); + GroupMember self = groupMemberDao.getMember(roomGroup.getId(), uid); + AssertUtil.isNotEmpty(self, "您不是群管理"); + AssertUtil.isTrue(hasPower(self), "您不是群管理"); + GroupMember member = groupMemberDao.getMember(roomGroup.getId(), request.getUid()); + AssertUtil.isNotEmpty(self, "用户已经移除"); + groupMemberDao.removeById(member.getId()); + //发送移除事件告知群成员 + List memberUidList = groupMemberCache.getMemberUidList(roomGroup.getRoomId()); + WSBaseResp ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), member.getUid()); + applicationEventPublisher.publishEvent(new WSPushEvent(this, memberUidList, ws)); + groupMemberCache.evictMemberUidList(member.getId()); + } + + + @Override + @RedissonLock(key = "#request.roomId") + @Transactional(rollbackFor = Exception.class) + public void addMember(Long uid, MemberAddReq request) { + Room room = roomCache.get(request.getRoomId()); + AssertUtil.isNotEmpty(room, "房间号有误"); + AssertUtil.isFalse(isHotGroup(room), "全员群无需邀请好友"); + RoomGroup roomGroup = roomGroupCache.get(request.getRoomId()); + AssertUtil.isNotEmpty(roomGroup, "房间号有误"); + GroupMember self = groupMemberDao.getMember(roomGroup.getId(), uid); + AssertUtil.isNotEmpty(self, "您不是群成员"); + List memberBatch = groupMemberDao.getMemberBatch(roomGroup.getId(), request.getUidList()); + Set existUid = new HashSet<>(memberBatch); + List waitAddUidList = request.getUidList().stream().filter(a -> !existUid.contains(a)).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(waitAddUidList)) { + return; + } + List groupMembers = MemberAdapter.buildMemberAdd(roomGroup.getId(), waitAddUidList); + groupMemberDao.saveBatch(groupMembers); + applicationEventPublisher.publishEvent(new GroupMemberAddEvent(this, roomGroup, groupMembers, uid)); + } + + @Override + @Transactional + public Long addGroup(Long uid, GroupAddReq request) { + RoomGroup roomGroup = roomService.createGroupRoom(uid); + //批量保存群成员 + List groupMembers = RoomAdapter.buildGroupMemberBatch(request.getUidList(), roomGroup.getId()); + groupMemberDao.saveBatch(groupMembers); + //发送邀请加群消息==》触发每个人的会话 + applicationEventPublisher.publishEvent(new GroupMemberAddEvent(this, roomGroup, groupMembers, uid)); + return roomGroup.getRoomId(); + } + + private boolean hasPower(GroupMember self) { + return Objects.equals(self.getRole(), GroupRoleEnum.LEADER.getType()) + || Objects.equals(self.getRole(), GroupRoleEnum.MANAGER.getType()) + || iRoleService.hasPower(self.getUid(), RoleEnum.ADMIN); + + } + + private GroupRoleAPPEnum getGroupRole(Long uid, RoomGroup roomGroup, Room room) { + GroupMember member = Objects.isNull(uid) ? null : groupMemberDao.getMember(roomGroup.getId(), uid); + if (Objects.nonNull(member)) { + return GroupRoleAPPEnum.of(member.getRole()); + } else if (isHotGroup(room)) { + return GroupRoleAPPEnum.MEMBER; + } else { + return GroupRoleAPPEnum.REMOVE; + } + } + + private boolean isHotGroup(Room room) { + return HotFlagEnum.YES.getType().equals(room.getHotFlag()); + } + + private List buildContact(List> list, Long uid) { + List roomIds = list.stream().map(Pair::getKey).collect(Collectors.toList()); + Map batch = roomCache.getBatch(roomIds); + Map contactMap = new HashMap<>(); + if (Objects.nonNull(uid)) { + List byRoomIds = contactDao.getByRoomIds(roomIds, uid); + contactMap = byRoomIds.stream().collect(Collectors.toMap(Contact::getRoomId, Function.identity())); + } + Map finalContactMap = contactMap; + return list.stream().map(pair -> { + Long roomId = pair.getKey(); + Contact contact = finalContactMap.get(roomId); + if (Objects.isNull(contact)) { + contact = new Contact(); + contact.setRoomId(pair.getKey()); + Room room = batch.get(roomId); + contact.setLastMsgId(room.getLastMsgId()); + } + contact.setActiveTime(new Date(pair.getValue().longValue())); + return contact; + }).collect(Collectors.toList()); + } + + private Double getCursorOrNull(String cursor) { + return Optional.ofNullable(cursor).map(Double::parseDouble).orElse(null); + } + + @NotNull + private List buildContactResp(Long uid, List roomIds) { + //表情和头像 + Map roomBaseInfoMap = getRoomBaseInfoMap(roomIds, uid); + //最后一条消息 + List msgIds = roomBaseInfoMap.values().stream().map(RoomBaseInfo::getLastMsgId).collect(Collectors.toList()); + List messages = CollectionUtil.isEmpty(msgIds) ? new ArrayList<>() : messageDao.listByIds(msgIds); + Map msgMap = messages.stream().collect(Collectors.toMap(Message::getId, Function.identity())); + Map lastMsgUidMap = userInfoCache.getBatch(messages.stream().map(Message::getFromUid).collect(Collectors.toList())); + //消息未读数 + Map unReadCountMap = getUnReadCountMap(uid, roomIds); + return roomBaseInfoMap.values().stream().map(room -> { + ChatRoomResp resp = new ChatRoomResp(); + RoomBaseInfo roomBaseInfo = roomBaseInfoMap.get(room.getRoomId()); + resp.setAvatar(roomBaseInfo.getAvatar()); + resp.setRoomId(room.getRoomId()); + resp.setActiveTime(room.getActiveTime()); + resp.setHot_Flag(roomBaseInfo.getHotFlag()); + resp.setType(roomBaseInfo.getType()); + resp.setName(roomBaseInfo.getName()); + Message message = msgMap.get(room.getLastMsgId()); + if (Objects.nonNull(message)) { + AbstractMsgHandler strategyNoNull = MsgHandlerFactory.getStrategyNoNull(message.getType()); + resp.setText(lastMsgUidMap.get(message.getFromUid()).getName() + ":" + strategyNoNull.showContactMsg(message)); + } + resp.setUnreadCount(unReadCountMap.getOrDefault(room.getRoomId(), 0)); + return resp; + }).sorted(Comparator.comparing(ChatRoomResp::getActiveTime).reversed()) + .collect(Collectors.toList()); + } + + /** + * 获取未读数 + */ + private Map getUnReadCountMap(Long uid, List roomIds) { + if (Objects.isNull(uid)) { + return new HashMap<>(); + } + List contacts = contactDao.getByRoomIds(roomIds, uid); + return contacts.parallelStream() + .map(contact -> Pair.of(contact.getRoomId(), messageDao.getUnReadCount(contact.getRoomId(), contact.getReadTime()))) + .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); + } + + private Map getFriendRoomMap(List roomIds, Long uid) { + if (CollectionUtil.isEmpty(roomIds)) { + return new HashMap<>(); + } + Map roomFriendMap = roomFriendCache.getBatch(roomIds); + Set friendUidSet = ChatAdapter.getFriendUidSet(roomFriendMap.values(), uid); + Map 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 getRoomBaseInfoMap(List roomIds, Long uid) { + Map roomMap = roomCache.getBatch(roomIds); + //房间根据好友和群组类型分组 + Map> groupRoomIdMap = roomMap.values().stream().collect(Collectors.groupingBy(Room::getType, + Collectors.mapping(Room::getId, Collectors.toList()))); + //获取群组信息 + List groupRoomId = groupRoomIdMap.get(RoomTypeEnum.GROUP.getType()); + Map roomInfoBatch = roomGroupCache.getBatch(groupRoomId); + //获取好友信息 + List friendRoomId = groupRoomIdMap.get(RoomTypeEnum.FRIEND.getType()); + Map friendRoomMap = getFriendRoomMap(friendRoomId, uid); + + return roomMap.values().stream().map(room -> { + RoomBaseInfo roomBaseInfo = new RoomBaseInfo(); + roomBaseInfo.setRoomId(room.getId()); + roomBaseInfo.setType(room.getType()); + roomBaseInfo.setHotFlag(room.getHotFlag()); + roomBaseInfo.setLastMsgId(room.getLastMsgId()); + roomBaseInfo.setActiveTime(room.getActiveTime()); + if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.GROUP) { + RoomGroup roomGroup = roomInfoBatch.get(room.getId()); + roomBaseInfo.setName(roomGroup.getName()); + roomBaseInfo.setAvatar(roomGroup.getAvatar()); + } else if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.FRIEND) { + User user = friendRoomMap.get(room.getId()); + roomBaseInfo.setName(user.getName()); + roomBaseInfo.setAvatar(user.getAvatar()); + } + return roomBaseInfo; + }).collect(Collectors.toMap(RoomBaseInfo::getRoomId, Function.identity())); + } + + private void fillRoomActive(Long uid, Map roomMap) { + } + +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/RoomServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/RoomServiceImpl.java deleted file mode 100644 index 001ef38..0000000 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/RoomServiceImpl.java +++ /dev/null @@ -1,114 +0,0 @@ -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: abin - * 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 getContactPage(CursorPageBaseReq request, Long uid) { - - if (Objects.nonNull(uid)) { - CursorPageBaseResp contactPage = contactDao.getContactPage(uid, request); - List roomIds = contactPage.getList().stream().map(Contact::getRoomId).collect(Collectors.toList()); - //表情和头像 - Map roomBaseInfoMap = getRoomBaseInfoMap(roomIds, uid); - //最后一条消息 - List msgIds = contactPage.getList().stream().map(Contact::getLastMsgId).collect(Collectors.toList()); - List messages = messageDao.listByIds(msgIds); - Map msgMap = messages.stream().collect(Collectors.toMap(Message::getId, Function.identity())); - List 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 getFriendRoomMap(List roomIds, Long uid) { - Map roomFriendMap = roomFriendCache.getBatch(roomIds); - Set friendUidSet = ChatAdapter.getFriendUidSet(roomFriendMap.values(), uid); - Map 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 getRoomBaseInfoMap(List roomIds, Long uid) { - Map roomMap = roomCache.getBatch(roomIds); - Map> groupRoomIdMap = roomMap.values().stream().collect(Collectors.groupingBy(Room::getType, - Collectors.mapping(Room::getId, Collectors.toList()))); - //获取群组信息 - List groupRoomId = groupRoomIdMap.get(RoomTypeEnum.GROUP.getType()); - Map roomInfoBatch = roomGroupCache.getBatch(groupRoomId); - //获取好友信息 - List friendRoomId = groupRoomIdMap.get(RoomTypeEnum.FRIEND.getType()); - Map 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())); - } - -} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java index 6ea052b..76a82f1 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java @@ -43,4 +43,9 @@ public abstract class AbstractMsgHandler { */ public abstract Object showReplyMsg(Message msg); + /** + * 会话列表——展示的消息 + */ + public abstract String showContactMsg(Message msg); + } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/EmojisMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/EmojisMsgHandler.java index d7f93a5..3c219aa 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/EmojisMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/EmojisMsgHandler.java @@ -54,4 +54,9 @@ public class EmojisMsgHandler extends AbstractMsgHandler { public Object showReplyMsg(Message msg) { return "表情"; } + + @Override + public String showContactMsg(Message msg) { + return "[表情包]"; + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/FileMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/FileMsgHandler.java index 0ce1c21..9fec9bc 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/FileMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/FileMsgHandler.java @@ -54,4 +54,9 @@ public class FileMsgHandler extends AbstractMsgHandler { public Object showReplyMsg(Message msg) { return "文件:" + msg.getExtra().getFileMsg().getFileName(); } + + @Override + public String showContactMsg(Message msg) { + return "[文件]" + msg.getExtra().getFileMsg().getFileName(); + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/ImgMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/ImgMsgHandler.java index 6e2cf98..ac52bce 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/ImgMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/ImgMsgHandler.java @@ -54,4 +54,9 @@ public class ImgMsgHandler extends AbstractMsgHandler { public Object showReplyMsg(Message msg) { return "图片"; } + + @Override + public String showContactMsg(Message msg) { + return "[图片]"; + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java index a5fd9e4..6d5cc1e 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java @@ -76,4 +76,9 @@ public class RecallMsgHandler extends AbstractMsgHandler { applicationEventPublisher.publishEvent(new MessageRecallEvent(this, new ChatMsgRecallDTO(message.getId(), message.getRoomId(), recallUid))); } + + @Override + public String showContactMsg(Message msg) { + return "撤回了一条消息"; + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/SoundMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/SoundMsgHandler.java index 470df61..1321ab3 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/SoundMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/SoundMsgHandler.java @@ -54,4 +54,9 @@ public class SoundMsgHandler extends AbstractMsgHandler { public Object showReplyMsg(Message msg) { return "语音"; } + + @Override + public String showContactMsg(Message msg) { + return "[语音]"; + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/SystemMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/SystemMsgHandler.java new file mode 100644 index 0000000..5dfbedb --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/SystemMsgHandler.java @@ -0,0 +1,52 @@ +package com.abin.mallchat.custom.chat.service.strategy.msg; + +import com.abin.mallchat.common.chat.dao.MessageDao; +import com.abin.mallchat.common.chat.domain.entity.Message; +import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum; +import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * Description:系统消息 + * Author: abin + * Date: 2023-06-04 + */ +@Component +public class SystemMsgHandler extends AbstractMsgHandler { + + @Autowired + private MessageDao messageDao; + + @Override + MessageTypeEnum getMsgTypeEnum() { + return MessageTypeEnum.SYSTEM; + } + + @Override + public void checkMsg(ChatMessageReq request, Long uid) { + } + + @Override + public void saveMsg(Message msg, ChatMessageReq request) { + Message update = new Message(); + update.setId(msg.getId()); + update.setContent((String) request.getBody()); + messageDao.updateById(update); + } + + @Override + public Object showMsg(Message msg) { + return msg.getContent(); + } + + @Override + public Object showReplyMsg(Message msg) { + return msg.getContent(); + } + + @Override + public String showContactMsg(Message msg) { + return msg.getContent(); + } +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java index 5ec867a..def0a19 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java @@ -135,4 +135,9 @@ public class TextMsgHandler extends AbstractMsgHandler { public Object showReplyMsg(Message msg) { return msg.getContent(); } + + @Override + public String showContactMsg(Message msg) { + return msg.getContent(); + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/VideoMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/VideoMsgHandler.java index f2bef5f..e9707a4 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/VideoMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/VideoMsgHandler.java @@ -54,4 +54,9 @@ public class VideoMsgHandler extends AbstractMsgHandler { public Object showReplyMsg(Message msg) { return "视频"; } + + @Override + public String showContactMsg(Message msg) { + return "[视频]"; + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/GroupMemberAddListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/GroupMemberAddListener.java new file mode 100644 index 0000000..1ed7d90 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/GroupMemberAddListener.java @@ -0,0 +1,85 @@ +package com.abin.mallchat.custom.common.event.listener; + +import com.abin.mallchat.common.chat.dao.GroupMemberDao; +import com.abin.mallchat.common.chat.domain.entity.GroupMember; +import com.abin.mallchat.common.chat.domain.entity.RoomGroup; +import com.abin.mallchat.common.chat.service.cache.GroupMemberCache; +import com.abin.mallchat.common.chat.service.cache.MsgCache; +import com.abin.mallchat.common.common.event.GroupMemberAddEvent; +import com.abin.mallchat.common.common.event.WSPushEvent; +import com.abin.mallchat.common.user.dao.UserDao; +import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.common.user.domain.enums.WSBaseResp; +import com.abin.mallchat.common.user.domain.vo.response.ws.WSMemberChange; +import com.abin.mallchat.common.user.service.cache.UserInfoCache; +import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; +import com.abin.mallchat.custom.chat.service.ChatService; +import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter; +import com.abin.mallchat.custom.chat.service.adapter.RoomAdapter; +import com.abin.mallchat.custom.user.service.WebSocketService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionalEventListener; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 添加群成员监听器 + * + * @author zhongzb create on 2022/08/26 + */ +@Slf4j +@Component +public class GroupMemberAddListener { + @Autowired + private WebSocketService webSocketService; + @Autowired + private ChatService chatService; + @Autowired + private MsgCache msgCache; + @Autowired + private UserInfoCache userInfoCache; + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + @Autowired + private GroupMemberDao groupMemberDao; + @Autowired + private UserDao userDao; + @Autowired + private GroupMemberCache groupMemberCache; + + + @Async + @TransactionalEventListener(classes = GroupMemberAddEvent.class, fallbackExecution = true) + public void sendAddMsg(GroupMemberAddEvent event) { + List memberList = event.getMemberList(); + RoomGroup roomGroup = event.getRoomGroup(); + Long inviteUid = event.getInviteUid(); + User user = userInfoCache.get(inviteUid); + List uidList = memberList.stream().map(GroupMember::getUid).collect(Collectors.toList()); + ChatMessageReq chatMessageReq = RoomAdapter.buildGroupAddMessage(roomGroup, user, userInfoCache.getBatch(uidList)); + chatService.sendMsg(chatMessageReq, User.UID_SYSTEM); + } + + @Async + + @TransactionalEventListener(classes = GroupMemberAddEvent.class, fallbackExecution = true) + public void sendChangePush(GroupMemberAddEvent event) { + List memberList = event.getMemberList(); + RoomGroup roomGroup = event.getRoomGroup(); + List memberUidList = groupMemberCache.getMemberUidList(roomGroup.getRoomId()); + List uidList = memberList.stream().map(GroupMember::getUid).collect(Collectors.toList()); + List users = userDao.listByIds(uidList); + users.forEach(user -> { + WSBaseResp ws = MemberAdapter.buildMemberAddWS(roomGroup.getRoomId(), user); + applicationEventPublisher.publishEvent(new WSPushEvent(this, memberUidList, ws)); + }); + //移除缓存 + groupMemberCache.evictMemberUidList(roomGroup.getRoomId()); + } + +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/MessageSendListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/MessageSendListener.java index e87bc0a..b670a2c 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/MessageSendListener.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/MessageSendListener.java @@ -1,22 +1,38 @@ package com.abin.mallchat.custom.common.event.listener; +import com.abin.mallchat.common.chat.dao.ContactDao; import com.abin.mallchat.common.chat.dao.MessageDao; +import com.abin.mallchat.common.chat.dao.RoomDao; +import com.abin.mallchat.common.chat.dao.RoomFriendDao; import com.abin.mallchat.common.chat.domain.entity.Message; +import com.abin.mallchat.common.chat.domain.entity.Room; +import com.abin.mallchat.common.chat.domain.entity.RoomFriend; +import com.abin.mallchat.common.chat.domain.enums.HotFlagEnum; +import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum; +import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp; +import com.abin.mallchat.common.chat.service.cache.GroupMemberCache; +import com.abin.mallchat.common.chat.service.cache.HotRoomCache; +import com.abin.mallchat.common.chat.service.cache.RoomCache; import com.abin.mallchat.common.common.event.MessageSendEvent; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp; +import com.abin.mallchat.common.common.event.WSPushEvent; +import com.abin.mallchat.common.user.service.cache.UserCache; import com.abin.mallchat.custom.chat.service.ChatService; import com.abin.mallchat.custom.chat.service.WeChatMsgOperationService; -import com.abin.mallchat.custom.chat.service.impl.WeChatMsgOperationServiceImpl; import com.abin.mallchat.custom.chatai.service.IChatAIService; import com.abin.mallchat.custom.user.service.WebSocketService; import com.abin.mallchat.custom.user.service.adapter.WSAdapter; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionalEventListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Objects; /** @@ -35,22 +51,67 @@ public class MessageSendListener { private MessageDao messageDao; @Autowired private IChatAIService openAIService; - @Autowired WeChatMsgOperationService weChatMsgOperationService; + @Autowired + private RoomCache roomCache; + @Autowired + private RoomDao roomDao; + @Autowired + private GroupMemberCache groupMemberCache; + @Autowired + private UserCache userCache; + @Autowired + private RoomFriendDao roomFriendDao; + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + @Autowired + private ContactDao contactDao; + @Autowired + private HotRoomCache hotRoomCache; @Async @TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true) - public void notifyAllOnline(MessageSendEvent event) { + public void messageRoute(MessageSendEvent event) { Message message = messageDao.getById(event.getMsgId()); + Room room = roomCache.get(message.getRoomId()); ChatMessageResp msgResp = chatService.getMsgResp(message, null); - webSocketService.sendToAllOnline(WSAdapter.buildMsgSend(msgResp), message.getFromUid()); + //更新房间最新消息 + roomDao.refreshActiveTime(room.getId(), message.getId(), message.getCreateTime()); + roomCache.delete(room.getId()); + if (isHotRoom(room)) {//热门群聊推送所有在线的人 + //更新热门群聊列表 + hotRoomCache.refreshActiveTime(room.getId(), message.getCreateTime()); + //推送所有人 + applicationEventPublisher.publishEvent(new WSPushEvent(this, WSAdapter.buildMsgSend(msgResp))); + } else { + List memberUidList = new ArrayList<>(); + if (Objects.equals(room.getType(), RoomTypeEnum.GROUP.getType())) {//普通群聊推送所有群成员 + memberUidList = groupMemberCache.getMemberUidList(room.getId()); + } else if (Objects.equals(room.getType(), RoomTypeEnum.FRIEND.getType())) {//单聊对象 + //对单人推送 + RoomFriend roomFriend = roomFriendDao.getByRoomId(room.getId()); + memberUidList = Arrays.asList(roomFriend.getUid1(), roomFriend.getUid2()); + } + //更新所有群成员的会话时间 + contactDao.refreshOrCreateActiveTime(room.getId(), memberUidList, message.getId(), message.getCreateTime()); + //推送房间成员 + applicationEventPublisher.publishEvent(new WSPushEvent(this, memberUidList, WSAdapter.buildMsgSend(msgResp))); + } } @TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true) public void handlerMsg(@NotNull MessageSendEvent event) { Message message = messageDao.getById(event.getMsgId()); - openAIService.chat(message); + Room room = roomCache.get(message.getRoomId()); + if (isHotRoom(room)) { + openAIService.chat(message); + } + } + + @Transactional + public boolean isHotRoom(Room room) { + return Objects.equals(HotFlagEnum.YES.getType(), room.getHotFlag()); } @TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true) diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserApplyListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserApplyListener.java index a95cd23..54c94b8 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserApplyListener.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserApplyListener.java @@ -3,7 +3,7 @@ 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.common.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; @@ -30,7 +30,7 @@ public class UserApplyListener { 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()); + webSocketService.sendToUid(WSAdapter.buildApplySend(new WSFriendApply(userApply.getUid(), unReadCount)), userApply.getTargetId()); } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserBlackListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserBlackListener.java index 8f7ba89..9d05f12 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserBlackListener.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserBlackListener.java @@ -2,10 +2,10 @@ package com.abin.mallchat.custom.common.event.listener; import com.abin.mallchat.common.chat.dao.MessageDao; import com.abin.mallchat.common.common.event.UserBlackEvent; +import com.abin.mallchat.common.user.domain.enums.WSBaseResp; +import com.abin.mallchat.common.user.domain.enums.WSRespTypeEnum; +import com.abin.mallchat.common.user.domain.vo.response.ws.WSBlack; import com.abin.mallchat.common.user.service.cache.UserCache; -import com.abin.mallchat.custom.user.domain.enums.WSRespTypeEnum; -import com.abin.mallchat.custom.user.domain.vo.response.ws.WSBaseResp; -import com.abin.mallchat.custom.user.domain.vo.response.ws.WSBlack; import com.abin.mallchat.custom.user.service.WebSocketService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserOfflineListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserOfflineListener.java index 8d4203c..eb27a74 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserOfflineListener.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserOfflineListener.java @@ -3,6 +3,7 @@ package com.abin.mallchat.custom.common.event.listener; import com.abin.mallchat.common.common.event.UserOfflineEvent; import com.abin.mallchat.common.user.dao.UserDao; import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum; import com.abin.mallchat.common.user.service.cache.UserCache; import com.abin.mallchat.custom.user.service.WebSocketService; import com.abin.mallchat.custom.user.service.adapter.WSAdapter; @@ -45,6 +46,7 @@ public class UserOfflineListener { User update = new User(); update.setId(user.getId()); update.setLastOptTime(user.getLastOptTime()); + update.setActiveStatus(ChatActiveStatusEnum.OFFLINE.getStatus()); userDao.updateById(update); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserOnlineListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserOnlineListener.java index a794a6a..38cb34e 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserOnlineListener.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/UserOnlineListener.java @@ -3,6 +3,7 @@ package com.abin.mallchat.custom.common.event.listener; import com.abin.mallchat.common.common.event.UserOnlineEvent; import com.abin.mallchat.common.user.dao.UserDao; import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum; import com.abin.mallchat.common.user.service.IpService; import com.abin.mallchat.common.user.service.cache.UserCache; import com.abin.mallchat.custom.user.service.WebSocketService; @@ -49,6 +50,7 @@ public class UserOnlineListener { update.setId(user.getId()); update.setLastOptTime(user.getLastOptTime()); update.setIpInfo(user.getIpInfo()); + update.setActiveStatus(ChatActiveStatusEnum.ONLINE.getStatus()); userDao.updateById(update); //更新用户ip详情 ipService.refreshIpDetailAsync(user.getId()); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/WSPushListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/WSPushListener.java new file mode 100644 index 0000000..c6bd81a --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/WSPushListener.java @@ -0,0 +1,37 @@ +package com.abin.mallchat.custom.common.event.listener; + +import com.abin.mallchat.common.common.event.WSPushEvent; +import com.abin.mallchat.common.user.domain.enums.WSPushTypeEnum; +import com.abin.mallchat.custom.user.service.WebSocketService; +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 WSPushListener { + @Autowired + private WebSocketService webSocketService; + + @Async + @TransactionalEventListener(classes = WSPushEvent.class, fallbackExecution = true) + public void wsPush(WSPushEvent event) { + WSPushTypeEnum wsPushTypeEnum = WSPushTypeEnum.of(event.getPushType()); + switch (wsPushTypeEnum) { + case USER: + webSocketService.sendToUidList(event.getWsBaseMsg(), event.getUidList()); + break; + case ALL: + webSocketService.sendToAllOnline(event.getWsBaseMsg(), null); + break; + } + } + +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/FriendController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/FriendController.java index 49a3f5e..e67be0e 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/FriendController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/FriendController.java @@ -7,9 +7,7 @@ import com.abin.mallchat.common.common.domain.vo.response.ApiResult; import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; import com.abin.mallchat.common.common.domain.vo.response.PageBaseResp; 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.response.ChatMemberResp; -import com.abin.mallchat.custom.chat.service.ChatService; +import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp; import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApplyReq; import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApproveReq; import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendCheckReq; @@ -21,7 +19,6 @@ import com.abin.mallchat.custom.user.service.FriendService; 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.annotation.Resource; @@ -40,11 +37,6 @@ import javax.validation.Valid; @Api(tags = "好友相关接口") @Slf4j public class FriendController { - @Autowired - private ChatService chatService; - @Autowired - private UserCache userCache; - @Resource private FriendService friendService; @@ -86,13 +78,13 @@ public class FriendController { } @PutMapping("/apply") - @ApiOperation("申请审批") + @ApiOperation("审批申请") public ApiResult applyApprove(@Valid @RequestBody FriendApproveReq request) { friendService.applyApprove(RequestHolder.get().getUid(), request); return ApiResult.success(); } - @PutMapping("/page") + @GetMapping("/page") @ApiOperation("联系人列表") public ApiResult> friendList(@Valid CursorPageBaseReq request) { Long uid = RequestHolder.get().getUid(); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/friend/FriendApplyReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/friend/FriendApplyReq.java index b0a5c0c..6897ddd 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/friend/FriendApplyReq.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/friend/FriendApplyReq.java @@ -7,6 +7,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; /** @@ -24,7 +25,7 @@ public class FriendApplyReq { @ApiModelProperty("申请信息") private String msg; - @NotBlank + @NotNull @ApiModelProperty("好友uid") private Long targetUid; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/friend/FriendDeleteReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/friend/FriendDeleteReq.java index b10e7fc..6f01201 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/friend/FriendDeleteReq.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/friend/FriendDeleteReq.java @@ -6,7 +6,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; /** @@ -20,7 +20,7 @@ import javax.validation.constraints.NotBlank; @NoArgsConstructor public class FriendDeleteReq { - @NotBlank + @NotNull @ApiModelProperty("好友uid") private Long targetUid; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/FriendService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/FriendService.java index f6b85d9..cf1edd6 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/FriendService.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/FriendService.java @@ -4,7 +4,7 @@ import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq; import com.abin.mallchat.common.common.domain.vo.request.PageBaseReq; import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; import com.abin.mallchat.common.common.domain.vo.response.PageBaseResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; +import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp; import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApplyReq; import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApproveReq; import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendCheckReq; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/WebSocketService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/WebSocketService.java index f33571a..1d43210 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/WebSocketService.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/WebSocketService.java @@ -1,10 +1,12 @@ package com.abin.mallchat.custom.user.service; import com.abin.mallchat.common.user.domain.entity.User; -import com.abin.mallchat.custom.user.domain.vo.request.ws.WSAuthorize; -import com.abin.mallchat.custom.user.domain.vo.response.ws.WSBaseResp; +import com.abin.mallchat.common.user.domain.enums.WSBaseResp; +import com.abin.mallchat.common.user.domain.vo.request.ws.WSAuthorize; import io.netty.channel.Channel; +import java.util.List; + public interface WebSocketService { /** * 处理用户登录请求,需要返回一张带code的二维码 @@ -66,7 +68,9 @@ public interface WebSocketService { */ void sendToAllOnline(WSBaseResp wsBaseResp); - void sendToFriend(WSBaseResp wsBaseResp, Long friendUid); + void sendToUid(WSBaseResp wsBaseResp, Long uid); + + void sendToUidList(WSBaseResp wsBaseResp, List uidList); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/adapter/FriendAdapter.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/adapter/FriendAdapter.java index 6525007..48b61a7 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/adapter/FriendAdapter.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/adapter/FriendAdapter.java @@ -35,6 +35,7 @@ public class FriendAdapter { FriendApplyResp friendApplyResp = new FriendApplyResp(); friendApplyResp.setUid(userApply.getUid()); friendApplyResp.setType(userApply.getType()); + friendApplyResp.setApplyId(userApply.getId()); friendApplyResp.setMsg(userApply.getMsg()); friendApplyResp.setStatus(userApply.getStatus()); return friendApplyResp; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/adapter/WSAdapter.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/adapter/WSAdapter.java index 4956491..5c2f0aa 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/adapter/WSAdapter.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/adapter/WSAdapter.java @@ -3,14 +3,14 @@ package com.abin.mallchat.custom.user.service.adapter; import cn.hutool.core.bean.BeanUtil; import com.abin.mallchat.common.chat.domain.dto.ChatMessageMarkDTO; import com.abin.mallchat.common.chat.domain.dto.ChatMsgRecallDTO; +import com.abin.mallchat.common.chat.domain.vo.response.ChatMessageResp; import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; +import com.abin.mallchat.common.user.domain.enums.WSBaseResp; +import com.abin.mallchat.common.user.domain.enums.WSRespTypeEnum; +import com.abin.mallchat.common.user.domain.vo.response.ws.*; import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp; import com.abin.mallchat.custom.chat.service.ChatService; -import com.abin.mallchat.custom.user.domain.enums.WSRespTypeEnum; -import com.abin.mallchat.custom.user.domain.vo.response.ws.*; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -87,7 +87,6 @@ public class WSAdapter { private void assembleNum(WSOnlineOfflineNotify onlineOfflineNotify) { ChatMemberStatisticResp memberStatistic = chatService.getMemberStatistic(); onlineOfflineNotify.setOnlineNum(memberStatistic.getOnlineNum()); - onlineOfflineNotify.setTotalNum(memberStatistic.getTotalNum()); } private static ChatMemberResp buildOnlineInfo(User user) { diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/FriendServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/FriendServiceImpl.java index 7e90547..ef2fdca 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/FriendServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/FriendServiceImpl.java @@ -17,7 +17,7 @@ import com.abin.mallchat.common.user.dao.UserFriendDao; import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.domain.entity.UserApply; import com.abin.mallchat.common.user.domain.entity.UserFriend; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; +import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp; import com.abin.mallchat.custom.chat.service.ChatService; import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter; import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter; @@ -36,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; import java.util.Arrays; import java.util.List; @@ -43,7 +44,7 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -import static com.abin.mallchat.common.user.domain.enums.ApplyStatusEnum.AGREE; +import static com.abin.mallchat.common.user.domain.enums.ApplyStatusEnum.WAIT_APPROVAL; /** * @author : limeng @@ -148,22 +149,22 @@ public class FriendServiceImpl implements FriendService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) @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(), "已同意好友申请"); + AssertUtil.equal(userApply.getStatus(), WAIT_APPROVAL.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()); +// //创建双方的会话 +// contactService.createContact(uid, roomFriend.getRoomId()); +// contactService.createContact(userApply.getUid(), roomFriend.getRoomId()); //发送一条同意消息。。我们已经是好友了,开始聊天吧 chatService.sendMsg(MessageAdapter.buildAgreeMsg(roomFriend.getRoomId()), uid); } @@ -188,6 +189,9 @@ public class FriendServiceImpl implements FriendService { @Override public CursorPageBaseResp friendList(Long uid, CursorPageBaseReq request) { CursorPageBaseResp friendPage = userFriendDao.getFriendPage(uid, request); + if (CollectionUtils.isEmpty(friendPage.getList())) { + return CursorPageBaseResp.empty(); + } List friendUids = friendPage.getList() .stream().map(UserFriend::getFriendUid) .collect(Collectors.toList()); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/OssServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/OssServiceImpl.java index fa533e8..f3bc0fe 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/OssServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/OssServiceImpl.java @@ -4,7 +4,7 @@ import com.abin.mallchat.common.common.utils.AssertUtil; import com.abin.mallchat.common.common.utils.oss.MinIOTemplate; import com.abin.mallchat.common.common.utils.oss.domain.OssReq; import com.abin.mallchat.common.common.utils.oss.domain.OssResp; -import com.abin.mallchat.custom.user.domain.enums.OssSceneEnum; +import com.abin.mallchat.common.user.domain.enums.OssSceneEnum; import com.abin.mallchat.custom.user.domain.vo.request.oss.UploadUrlReq; import com.abin.mallchat.custom.user.service.OssService; import org.springframework.beans.factory.annotation.Autowired; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/WebSocketServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/WebSocketServiceImpl.java index a27a64e..396a572 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/WebSocketServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/WebSocketServiceImpl.java @@ -10,11 +10,11 @@ import com.abin.mallchat.common.common.event.UserOnlineEvent; import com.abin.mallchat.common.user.dao.UserDao; import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.domain.enums.RoleEnum; +import com.abin.mallchat.common.user.domain.enums.WSBaseResp; +import com.abin.mallchat.common.user.domain.vo.request.ws.WSAuthorize; import com.abin.mallchat.common.user.service.IRoleService; import com.abin.mallchat.common.user.service.cache.UserCache; import com.abin.mallchat.custom.user.domain.dto.ws.WSChannelExtraDTO; -import com.abin.mallchat.custom.user.domain.vo.request.ws.WSAuthorize; -import com.abin.mallchat.custom.user.domain.vo.response.ws.WSBaseResp; import com.abin.mallchat.custom.user.service.LoginService; import com.abin.mallchat.custom.user.service.WebSocketService; import com.abin.mallchat.custom.user.service.adapter.WSAdapter; @@ -98,7 +98,7 @@ public class WebSocketServiceImpl implements WebSocketService { */ @SneakyThrows @Override - @FrequencyControl(time = 100, count = 5, spEl = "T(com.abin.mallchat.common.common.utils.RequestHolder).get().getIp()") + @FrequencyControl(time = 1000, count = 50, spEl = "T(com.abin.mallchat.common.common.utils.RequestHolder).get().getIp()") public void handleLoginReq(Channel channel) { //生成随机不重复的登录码 Integer code = generateLoginCode(channel); @@ -245,7 +245,7 @@ public class WebSocketServiceImpl implements WebSocketService { @Override public void sendToAllOnline(WSBaseResp wsBaseResp, Long skipUid) { ONLINE_WS_MAP.forEach((channel, ext) -> { - if (ObjectUtil.equal(ext.getUid(), skipUid)) { + if (Objects.nonNull(skipUid) && Objects.equals(ext.getUid(), skipUid)) { return; } threadPoolTaskExecutor.execute(() -> sendMsg(channel, wsBaseResp)); @@ -258,13 +258,21 @@ public class WebSocketServiceImpl implements WebSocketService { } @Override - public void sendToFriend(WSBaseResp wsBaseResp, Long friendUid) { - CopyOnWriteArrayList channels = ONLINE_UID_MAP.get(friendUid); + public void sendToUid(WSBaseResp wsBaseResp, Long uid) { + CopyOnWriteArrayList channels = ONLINE_UID_MAP.get(uid); if (CollectionUtil.isEmpty(channels)) { - log.info("用户:{}不在线", friendUid); + log.info("用户:{}不在线", uid); return; } - threadPoolTaskExecutor.execute(() -> sendMsg(channels.get(0), wsBaseResp)); + channels.forEach(channel -> { + threadPoolTaskExecutor.execute(() -> sendMsg(channel, wsBaseResp)); + }); + + } + + @Override + public void sendToUidList(WSBaseResp wsBaseResp, List uidList) { + uidList.forEach(uid -> sendToUid(wsBaseResp, uid)); } private void sendMsg(Channel channel, WSBaseResp wsBaseResp) { diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServerHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServerHandler.java index fe8a92a..8ca5ac6 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServerHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/websocket/NettyWebSocketServerHandler.java @@ -3,9 +3,9 @@ package com.abin.mallchat.custom.user.websocket; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.json.JSONUtil; -import com.abin.mallchat.custom.user.domain.enums.WSReqTypeEnum; -import com.abin.mallchat.custom.user.domain.vo.request.ws.WSAuthorize; -import com.abin.mallchat.custom.user.domain.vo.request.ws.WSBaseReq; +import com.abin.mallchat.common.user.domain.enums.WSReqTypeEnum; +import com.abin.mallchat.common.user.domain.vo.request.ws.WSAuthorize; +import com.abin.mallchat.common.user.domain.vo.request.ws.WSBaseReq; import com.abin.mallchat.custom.user.service.WebSocketService; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; diff --git a/mallchat-custom-server/src/test/java/com/abin/mallchat/custom/common/CommonTest.java b/mallchat-custom-server/src/test/java/com/abin/mallchat/custom/common/CommonTest.java deleted file mode 100644 index 96fb649..0000000 --- a/mallchat-custom-server/src/test/java/com/abin/mallchat/custom/common/CommonTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.abin.mallchat.custom.common; - -import org.junit.Test; - -import static com.abin.mallchat.custom.user.service.adapter.FriendAdapter.buildFriendRoomKey; - -/** - * Description: - * Author: abin - * Date: 2023-07-22 - */ -public class CommonTest { - @Test - public void test() { - System.out.println(buildFriendRoomKey(100L, 102L)); - } - -}