mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-20 10:46:47 +08:00
单聊群聊功能提交
This commit is contained in:
@@ -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 `user_apply`;
|
||||||
|
|
||||||
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='房间表';
|
|
||||||
|
|
||||||
CREATE TABLE `user_apply` (
|
CREATE TABLE `user_apply` (
|
||||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
`uid` bigint(20) NOT NULL COMMENT '申请人uid',
|
`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_create_time` (`create_time`) USING BTREE,
|
||||||
KEY `idx_update_time` (`update_time`) USING BTREE
|
KEY `idx_update_time` (`update_time`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户申请表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户申请表';
|
||||||
|
DROP TABLE IF EXISTS `user_friend`;
|
||||||
CREATE TABLE `user_friend` (
|
CREATE TABLE `user_friend` (
|
||||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
`uid` bigint(20) NOT NULL COMMENT 'uid',
|
`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_create_time` (`create_time`) USING BTREE,
|
||||||
KEY `idx_update_time` (`update_time`) USING BTREE
|
KEY `idx_update_time` (`update_time`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户联系人表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户联系人表';
|
||||||
|
DROP TABLE IF EXISTS `room`;
|
||||||
CREATE TABLE `group_member` (
|
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',
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
`room_id` bigint(20) NOT NULL 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',
|
`uid` bigint(20) NOT NULL COMMENT '成员uid',
|
||||||
`role` int(11) NOT NULL COMMENT '成员角色 1群主 2管理员 3普通成员',
|
`role` int(11) NOT NULL COMMENT '成员角色 1群主 2管理员 3普通成员',
|
||||||
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
`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 '修改时间',
|
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
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_create_time` (`create_time`) USING BTREE,
|
||||||
KEY `idx_update_time` (`update_time`) USING BTREE
|
KEY `idx_update_time` (`update_time`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='群成员表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='群成员表';
|
||||||
|
DROP TABLE IF EXISTS `contact`;
|
||||||
CREATE TABLE `contact` (
|
CREATE TABLE `contact` (
|
||||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
`uid` bigint(20) NOT NULL COMMENT 'uid',
|
`uid` bigint(20) NOT NULL COMMENT 'uid',
|
||||||
`type` int(11) NOT NULL COMMENT '聊天类型 1单聊 2普通群聊',
|
`room_id` bigint(20) NOT NULL COMMENT '房间id',
|
||||||
`hot_flag` int(11) DEFAULT '0' COMMENT '是否全员展示 0否 1是',
|
|
||||||
`target_id` bigint(20) NOT NULL COMMENT '聊天对象type=1:uid,type=2:房间id',
|
|
||||||
`read_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '阅读到的时间',
|
`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 '创建时间',
|
`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 '修改时间',
|
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
UNIQUE KEY `uniq_uid_target_id_type` (`uid`,`target_id`,`type`) USING BTREE,
|
UNIQUE KEY `uniq_uid_room_id` (`uid`,`room_id`) USING BTREE,
|
||||||
KEY `idx_target_id_read_time` (`target_id`,`read_time`) USING BTREE,
|
KEY `idx_room_id_read_time` (`room_id`,`read_time`) USING BTREE,
|
||||||
KEY `idx_create_time` (`create_time`) USING BTREE,
|
KEY `idx_create_time` (`create_time`) USING BTREE,
|
||||||
KEY `idx_update_time` (`update_time`) USING BTREE
|
KEY `idx_update_time` (`update_time`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会话列表';
|
) 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');
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import com.abin.mallchat.common.common.utils.CursorUtils;
|
|||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 会话列表 服务实现类
|
* 会话列表 服务实现类
|
||||||
@@ -71,4 +74,18 @@ public class ContactDao extends ServiceImpl<ContactMapper, Contact> {
|
|||||||
wrapper.eq(Contact::getUid, uid);
|
wrapper.eq(Contact::getUid, uid);
|
||||||
}, Contact::getActiveTime);
|
}, Contact::getActiveTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Contact> getByRoomIds(List<Long> roomIds, Long uid) {
|
||||||
|
return lambdaQuery()
|
||||||
|
.eq(Contact::getRoomId, roomIds)
|
||||||
|
.eq(Contact::getUid, uid)
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新所有人的会话时间,没有就直接插入
|
||||||
|
*/
|
||||||
|
public void refreshOrCreateActiveTime(Long roomId, List<Long> memberUidList, Long msgId, Date activeTime) {
|
||||||
|
baseMapper.refreshOrCreateActiveTime(roomId, memberUidList, msgId, activeTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package com.abin.mallchat.common.chat.dao;
|
package com.abin.mallchat.common.chat.dao;
|
||||||
|
|
||||||
import com.abin.mallchat.common.chat.domain.entity.GroupMember;
|
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.mapper.GroupMemberMapper;
|
||||||
import com.abin.mallchat.common.chat.service.IGroupMemberService;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 群成员表 服务实现类
|
* 群成员表 服务实现类
|
||||||
@@ -15,6 +18,36 @@ import org.springframework.stereotype.Service;
|
|||||||
* @since 2023-07-16
|
* @since 2023-07-16
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class GroupMemberDao extends ServiceImpl<GroupMemberMapper, GroupMember> implements IGroupMemberService {
|
public class GroupMemberDao extends ServiceImpl<GroupMemberMapper, GroupMember> {
|
||||||
|
|
||||||
|
public List<Long> getMemberUidList(Long groupId) {
|
||||||
|
List<GroupMember> list = lambdaQuery()
|
||||||
|
.eq(GroupMember::getGroupId, groupId)
|
||||||
|
.select(GroupMember::getUid)
|
||||||
|
.list();
|
||||||
|
return list.stream().map(GroupMember::getUid).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getMemberBatch(Long groupId, List<Long> uidList) {
|
||||||
|
List<GroupMember> list = lambdaQuery()
|
||||||
|
.eq(GroupMember::getGroupId, groupId)
|
||||||
|
.in(GroupMember::getUid, uidList)
|
||||||
|
.select(GroupMember::getUid)
|
||||||
|
.list();
|
||||||
|
return list.stream().map(GroupMember::getUid).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupMember getMember(Long groupId, Long uid) {
|
||||||
|
return lambdaQuery()
|
||||||
|
.eq(GroupMember::getGroupId, groupId)
|
||||||
|
.eq(GroupMember::getUid, uid)
|
||||||
|
.one();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GroupMember> getSelfGroup(Long uid) {
|
||||||
|
return lambdaQuery()
|
||||||
|
.eq(GroupMember::getUid, uid)
|
||||||
|
.eq(GroupMember::getRole, GroupRoleEnum.LEADER.getType())
|
||||||
|
.list();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import com.abin.mallchat.common.common.utils.CursorUtils;
|
|||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 消息表 服务实现类
|
* 消息表 服务实现类
|
||||||
@@ -52,4 +55,11 @@ public class MessageDao extends ServiceImpl<MessageMapper, Message> {
|
|||||||
.set(Message::getStatus, MessageStatusEnum.DELETE.getStatus())
|
.set(Message::getStatus, MessageStatusEnum.DELETE.getStatus())
|
||||||
.update();
|
.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getUnReadCount(Long roomId, Date readTime) {
|
||||||
|
return lambdaQuery()
|
||||||
|
.eq(Message::getRoomId, roomId)
|
||||||
|
.gt(Objects.nonNull(readTime), Message::getCreateTime, readTime)
|
||||||
|
.count();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 房间表 服务实现类
|
* 房间表 服务实现类
|
||||||
@@ -17,4 +19,11 @@ import org.springframework.stereotype.Service;
|
|||||||
@Service
|
@Service
|
||||||
public class RoomDao extends ServiceImpl<RoomMapper, Room> implements IService<Room> {
|
public class RoomDao extends ServiceImpl<RoomMapper, Room> implements IService<Room> {
|
||||||
|
|
||||||
|
public void refreshActiveTime(Long roomId, Long msgId, Date msgTime) {
|
||||||
|
lambdaUpdate()
|
||||||
|
.eq(Room::getId, roomId)
|
||||||
|
.set(Room::getLastMsgId, msgId)
|
||||||
|
.set(Room::getActiveTime, msgTime)
|
||||||
|
.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import java.util.List;
|
|||||||
public class RoomFriendDao extends ServiceImpl<RoomFriendMapper, RoomFriend> {
|
public class RoomFriendDao extends ServiceImpl<RoomFriendMapper, RoomFriend> {
|
||||||
|
|
||||||
public RoomFriend getByKey(String key) {
|
public RoomFriend getByKey(String key) {
|
||||||
return lambdaQuery().eq(RoomFriend::getKey, key).one();
|
return lambdaQuery().eq(RoomFriend::getRoomKey, key).one();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restoreRoom(Long id) {
|
public void restoreRoom(Long id) {
|
||||||
@@ -32,7 +32,13 @@ public class RoomFriendDao extends ServiceImpl<RoomFriendMapper, RoomFriend> {
|
|||||||
|
|
||||||
public List<RoomFriend> listByRoomIds(List<Long> roomIds) {
|
public List<RoomFriend> listByRoomIds(List<Long> roomIds) {
|
||||||
return lambdaQuery()
|
return lambdaQuery()
|
||||||
.eq(RoomFriend::getRoomId, roomIds)
|
.in(RoomFriend::getRoomId, roomIds)
|
||||||
.list();
|
.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RoomFriend getByRoomId(Long roomID) {
|
||||||
|
return lambdaQuery()
|
||||||
|
.eq(RoomFriend::getRoomId, roomID)
|
||||||
|
.one();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,4 +23,10 @@ public class RoomGroupDao extends ServiceImpl<RoomGroupMapper, RoomGroup> {
|
|||||||
.in(RoomGroup::getRoomId, roomIds)
|
.in(RoomGroup::getRoomId, roomIds)
|
||||||
.list();
|
.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RoomGroup getByRoomId(Long roomId) {
|
||||||
|
return lambdaQuery()
|
||||||
|
.eq(RoomGroup::getRoomId, roomId)
|
||||||
|
.one();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.abin.mallchat.common.chat.domain.dto;
|
package com.abin.mallchat.common.chat.domain.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description: 房间详情
|
* Description: 房间详情
|
||||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
@@ -16,4 +19,27 @@ public class RoomBaseInfo {
|
|||||||
private String name;
|
private String name;
|
||||||
@ApiModelProperty("会话头像")
|
@ApiModelProperty("会话头像")
|
||||||
private String avatar;
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -47,13 +47,13 @@ public class Contact implements Serializable {
|
|||||||
* 阅读到的时间
|
* 阅读到的时间
|
||||||
*/
|
*/
|
||||||
@TableField("read_time")
|
@TableField("read_time")
|
||||||
private LocalDateTime readTime;
|
private Date readTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 会话内消息最后更新的时间(只有普通会话需要维护,全员会话不需要维护)
|
* 会话内消息最后更新的时间(只有普通会话需要维护,全员会话不需要维护)
|
||||||
*/
|
*/
|
||||||
@TableField("active_time")
|
@TableField("active_time")
|
||||||
private LocalDateTime activeTime;
|
private Date activeTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最后一条消息id
|
* 最后一条消息id
|
||||||
@@ -65,13 +65,13 @@ public class Contact implements Serializable {
|
|||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改时间
|
* 修改时间
|
||||||
*/
|
*/
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private LocalDateTime updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.*;
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -21,6 +20,9 @@ import java.time.LocalDateTime;
|
|||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@TableName("group_member")
|
@TableName("group_member")
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
public class GroupMember implements Serializable {
|
public class GroupMember implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@@ -32,10 +34,10 @@ public class GroupMember implements Serializable {
|
|||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 房间id
|
* 群组id
|
||||||
*/
|
*/
|
||||||
@TableField("room_id")
|
@TableField("group_id")
|
||||||
private Long roomId;
|
private Long groupId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 成员uid
|
* 成员uid
|
||||||
@@ -44,7 +46,9 @@ public class GroupMember implements Serializable {
|
|||||||
private Long uid;
|
private Long uid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 成员角色1群主 2管理员 3普通成员
|
* 成员角色1群主(可撤回,可移除,可解散) 2管理员(可撤回,可移除) 3普通成员
|
||||||
|
*
|
||||||
|
* @see com.abin.mallchat.common.chat.domain.enums.GroupRoleEnum
|
||||||
*/
|
*/
|
||||||
@TableField("role")
|
@TableField("role")
|
||||||
private Integer role;
|
private Integer role;
|
||||||
@@ -53,13 +57,13 @@ public class GroupMember implements Serializable {
|
|||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改时间
|
* 修改时间
|
||||||
*/
|
*/
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private LocalDateTime updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -32,6 +32,8 @@ public class Room implements Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 房间类型 1群聊 2单聊
|
* 房间类型 1群聊 2单聊
|
||||||
|
*
|
||||||
|
* @see com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum
|
||||||
*/
|
*/
|
||||||
@TableField("type")
|
@TableField("type")
|
||||||
private Integer type;
|
private Integer type;
|
||||||
@@ -48,7 +50,13 @@ public class Room implements Serializable {
|
|||||||
* 群最后消息的更新时间(热点群不需要写扩散,更新这里就行)
|
* 群最后消息的更新时间(热点群不需要写扩散,更新这里就行)
|
||||||
*/
|
*/
|
||||||
@TableField("active_time")
|
@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")
|
@TableField("create_time")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改时间
|
* 修改时间
|
||||||
*/
|
*/
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private LocalDateTime updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -52,8 +52,8 @@ public class RoomFriend implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 房间key由两个uid拼接,先做排序uid1_uid2
|
* 房间key由两个uid拼接,先做排序uid1_uid2
|
||||||
*/
|
*/
|
||||||
@TableField("key")
|
@TableField("room_key")
|
||||||
private String key;
|
private String roomKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 房间状态 0正常 1禁用(删好友了禁用)
|
* 房间状态 0正常 1禁用(删好友了禁用)
|
||||||
@@ -65,12 +65,12 @@ public class RoomFriend implements Serializable {
|
|||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改时间
|
* 修改时间
|
||||||
*/
|
*/
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private LocalDateTime updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -63,13 +63,13 @@ public class RoomGroup implements Serializable {
|
|||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改时间
|
* 修改时间
|
||||||
*/
|
*/
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private LocalDateTime updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.abin.mallchat.common.chat.domain.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 成员角色枚举
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-19
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum GroupRoleEnum {
|
||||||
|
LEADER(1, "群主"),
|
||||||
|
MANAGER(2, "管理"),
|
||||||
|
MEMBER(3, "普通成员"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer type;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
private static Map<Integer, GroupRoleEnum> cache;
|
||||||
|
|
||||||
|
static {
|
||||||
|
cache = Arrays.stream(GroupRoleEnum.values()).collect(Collectors.toMap(GroupRoleEnum::getType, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupRoleEnum of(Integer type) {
|
||||||
|
return cache.get(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ public enum MessageTypeEnum {
|
|||||||
SOUND(5, "语音"),
|
SOUND(5, "语音"),
|
||||||
VIDEO(6, "视频"),
|
VIDEO(6, "视频"),
|
||||||
EMOJI(7, "表情"),
|
EMOJI(7, "表情"),
|
||||||
|
SYSTEM(8, "系统消息"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final Integer type;
|
private final Integer type;
|
||||||
|
|||||||
@@ -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 io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -17,7 +17,7 @@ import java.util.Date;
|
|||||||
@Builder
|
@Builder
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class ChatMessageRespV1 {
|
public class ChatMessageResp {
|
||||||
|
|
||||||
@ApiModelProperty("发送者信息")
|
@ApiModelProperty("发送者信息")
|
||||||
private UserInfo fromUser;
|
private UserInfo fromUser;
|
||||||
@@ -42,7 +42,6 @@ public class ChatMessageRespV1 {
|
|||||||
private Object body;
|
private Object body;
|
||||||
@ApiModelProperty("消息标记")
|
@ApiModelProperty("消息标记")
|
||||||
private MessageMark messageMark;
|
private MessageMark messageMark;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -56,5 +55,4 @@ public class ChatMessageRespV1 {
|
|||||||
@ApiModelProperty("该用户是否已经举报 0否 1是")
|
@ApiModelProperty("该用户是否已经举报 0否 1是")
|
||||||
private Integer userDislike;
|
private Integer userDislike;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,10 @@ package com.abin.mallchat.common.chat.mapper;
|
|||||||
|
|
||||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -13,4 +17,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||||||
*/
|
*/
|
||||||
public interface ContactMapper extends BaseMapper<Contact> {
|
public interface ContactMapper extends BaseMapper<Contact> {
|
||||||
|
|
||||||
|
void refreshOrCreateActiveTime(@Param("roomId") Long roomId, @Param("memberUidList") List<Long> memberUidList, @Param("msgId") Long msgId, @Param("activeTime") Date activeTime);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.abin.mallchat.common.chat.service;
|
package com.abin.mallchat.common.chat.service;
|
||||||
|
|
||||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
||||||
|
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -15,4 +16,9 @@ public interface RoomService {
|
|||||||
* 创建一个单聊房间
|
* 创建一个单聊房间
|
||||||
*/
|
*/
|
||||||
RoomFriend createFriendRoom(List<Long> uidList);
|
RoomFriend createFriendRoom(List<Long> uidList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个群聊房间
|
||||||
|
*/
|
||||||
|
RoomGroup createGroupRoom(Long uid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.Contact;
|
||||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
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.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.HotFlagEnum;
|
||||||
import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum;
|
import com.abin.mallchat.common.chat.domain.enums.RoomTypeEnum;
|
||||||
import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum;
|
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.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -41,7 +43,7 @@ public class ChatAdapter {
|
|||||||
roomFriend.setRoomId(roomId);
|
roomFriend.setRoomId(roomId);
|
||||||
roomFriend.setUid1(collect.get(0));
|
roomFriend.setUid1(collect.get(0));
|
||||||
roomFriend.setUid2(collect.get(1));
|
roomFriend.setUid2(collect.get(1));
|
||||||
roomFriend.setKey(generateRoomKey(uidList));
|
roomFriend.setRoomKey(generateRoomKey(uidList));
|
||||||
roomFriend.setStatus(NormalOrNoEnum.NORMAL.getStatus());
|
roomFriend.setStatus(NormalOrNoEnum.NORMAL.getStatus());
|
||||||
return roomFriend;
|
return roomFriend;
|
||||||
}
|
}
|
||||||
@@ -65,4 +67,12 @@ public class ChatAdapter {
|
|||||||
public static Long getFriendUid(RoomFriend roomFriend, Long uid) {
|
public static Long getFriendUid(RoomFriend roomFriend, Long uid) {
|
||||||
return Objects.equals(uid, roomFriend.getUid1()) ? roomFriend.getUid2() : roomFriend.getUid1();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
44
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/GroupMemberCache.java
vendored
Normal file
44
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/GroupMemberCache.java
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package com.abin.mallchat.common.chat.service.cache;
|
||||||
|
|
||||||
|
import com.abin.mallchat.common.chat.dao.GroupMemberDao;
|
||||||
|
import com.abin.mallchat.common.chat.dao.MessageDao;
|
||||||
|
import com.abin.mallchat.common.chat.dao.RoomGroupDao;
|
||||||
|
import com.abin.mallchat.common.chat.domain.entity.RoomGroup;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 群成员相关缓存
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-27
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class GroupMemberCache {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageDao messageDao;
|
||||||
|
@Autowired
|
||||||
|
private RoomGroupDao roomGroupDao;
|
||||||
|
@Autowired
|
||||||
|
private GroupMemberDao groupMemberDao;
|
||||||
|
|
||||||
|
@Cacheable(cacheNames = "member", key = "'groupMember'+#roomId")
|
||||||
|
public List<Long> getMemberUidList(Long roomId) {
|
||||||
|
RoomGroup roomGroup = roomGroupDao.getByRoomId(roomId);
|
||||||
|
if (Objects.isNull(roomGroup)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return groupMemberDao.getMemberUidList(roomGroup.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@CacheEvict(cacheNames = "member", key = "'groupMember'+#roomId")
|
||||||
|
public List<Long> evictMemberUidList(Long roomId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
42
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/HotRoomCache.java
vendored
Normal file
42
mallchat-common/src/main/java/com/abin/mallchat/common/chat/service/cache/HotRoomCache.java
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package com.abin.mallchat.common.chat.service.cache;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Pair;
|
||||||
|
import com.abin.mallchat.common.common.constant.RedisKey;
|
||||||
|
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||||
|
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||||
|
import com.abin.mallchat.common.common.utils.CursorUtils;
|
||||||
|
import com.abin.mallchat.common.common.utils.RedisUtils;
|
||||||
|
import org.springframework.data.redis.core.ZSetOperations;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 全局房间
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-07-23
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class HotRoomCache {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取热门群聊翻页
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public CursorPageBaseResp<Pair<Long, Double>> getRoomCursorPage(CursorPageBaseReq pageBaseReq) {
|
||||||
|
return CursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.HOT_ROOM_ZET), Long::parseLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<ZSetOperations.TypedTuple<String>> getRoomRange(Double hotStart, Double hotEnd) {
|
||||||
|
return RedisUtils.zRangeByScoreWithScores(RedisKey.getKey(RedisKey.HOT_ROOM_ZET), hotStart, hotEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新热门群聊的最新时间
|
||||||
|
*/
|
||||||
|
public void refreshActiveTime(Long roomId, Date refreshTime) {
|
||||||
|
RedisUtils.zAdd(RedisKey.getKey(RedisKey.HOT_ROOM_ZET), roomId, (double) refreshTime.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.dao.MessageDao;
|
||||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
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.BlackDao;
|
||||||
import com.abin.mallchat.common.user.dao.RoleDao;
|
import com.abin.mallchat.common.user.dao.RoleDao;
|
||||||
import com.abin.mallchat.common.user.dao.UserDao;
|
import com.abin.mallchat.common.user.dao.UserDao;
|
||||||
@@ -19,8 +18,6 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public class MsgCache {
|
public class MsgCache {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private CursorUtils cursorUtils;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserDao userDao;
|
private UserDao userDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ public class RoomGroupCache extends AbstractRedisStringCache<Long, RoomGroup> {
|
|||||||
private RoomGroupDao roomGroupDao;
|
private RoomGroupDao roomGroupDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getKey(Long groupId) {
|
protected String getKey(Long roomId) {
|
||||||
return RedisKey.getKey(RedisKey.GROUP_INFO_STRING, groupId);
|
return RedisKey.getKey(RedisKey.GROUP_INFO_STRING, roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
package com.abin.mallchat.common.chat.service.impl;
|
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.RoomDao;
|
||||||
import com.abin.mallchat.common.chat.dao.RoomFriendDao;
|
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.Room;
|
||||||
import com.abin.mallchat.common.chat.domain.entity.RoomFriend;
|
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.domain.enums.RoomTypeEnum;
|
||||||
import com.abin.mallchat.common.chat.service.RoomService;
|
import com.abin.mallchat.common.chat.service.RoomService;
|
||||||
import com.abin.mallchat.common.chat.service.adapter.ChatAdapter;
|
import com.abin.mallchat.common.chat.service.adapter.ChatAdapter;
|
||||||
import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum;
|
import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum;
|
||||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -28,6 +35,12 @@ public class RoomServiceImpl implements RoomService {
|
|||||||
private RoomFriendDao roomFriendDao;
|
private RoomFriendDao roomFriendDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RoomDao roomDao;
|
private RoomDao roomDao;
|
||||||
|
@Autowired
|
||||||
|
private GroupMemberDao groupMemberDao;
|
||||||
|
@Autowired
|
||||||
|
private UserInfoCache userInfoCache;
|
||||||
|
@Autowired
|
||||||
|
private RoomGroupDao roomGroupDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@@ -40,12 +53,32 @@ public class RoomServiceImpl implements RoomService {
|
|||||||
if (Objects.nonNull(roomFriend)) { //如果存在房间就恢复,适用于恢复好友场景
|
if (Objects.nonNull(roomFriend)) { //如果存在房间就恢复,适用于恢复好友场景
|
||||||
restoreRoomIfNeed(roomFriend);
|
restoreRoomIfNeed(roomFriend);
|
||||||
} else {//新建房间
|
} else {//新建房间
|
||||||
Room room = createRoom(RoomTypeEnum.GROUP);
|
Room room = createRoom(RoomTypeEnum.FRIEND);
|
||||||
roomFriend = createFriendRoom(room.getId(), uidList);
|
roomFriend = createFriendRoom(room.getId(), uidList);
|
||||||
}
|
}
|
||||||
return roomFriend;
|
return roomFriend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public RoomGroup createGroupRoom(Long uid) {
|
||||||
|
List<GroupMember> selfGroup = groupMemberDao.getSelfGroup(uid);
|
||||||
|
AssertUtil.isEmpty(selfGroup, "每个人只能创建一个群");
|
||||||
|
User user = userInfoCache.get(uid);
|
||||||
|
Room room = createRoom(RoomTypeEnum.GROUP);
|
||||||
|
//插入群
|
||||||
|
RoomGroup roomGroup = ChatAdapter.buildGroupRoom(user, room.getId());
|
||||||
|
roomGroupDao.save(roomGroup);
|
||||||
|
//插入群主
|
||||||
|
GroupMember leader = GroupMember.builder()
|
||||||
|
.role(GroupRoleEnum.LEADER.getType())
|
||||||
|
.groupId(roomGroup.getId())
|
||||||
|
.uid(uid)
|
||||||
|
.build();
|
||||||
|
groupMemberDao.save(leader);
|
||||||
|
return roomGroup;
|
||||||
|
}
|
||||||
|
|
||||||
private RoomFriend createFriendRoom(Long roomId, List<Long> uidList) {
|
private RoomFriend createFriendRoom(Long roomId, List<Long> uidList) {
|
||||||
RoomFriend insert = ChatAdapter.buildFriendRoom(roomId, uidList);
|
RoomFriend insert = ChatAdapter.buildFriendRoom(roomId, uidList);
|
||||||
roomFriendDao.save(insert);
|
roomFriendDao.save(insert);
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ public class RedisKey {
|
|||||||
*/
|
*/
|
||||||
public static final String OFFLINE_UID_ZET = "offline";
|
public static final String OFFLINE_UID_ZET = "offline";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 热门房间列表
|
||||||
|
*/
|
||||||
|
public static final String HOT_ROOM_ZET = "hotRoom";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户信息
|
* 用户信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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<GroupMember> memberList;
|
||||||
|
private final RoomGroup roomGroup;
|
||||||
|
private final Long inviteUid;
|
||||||
|
|
||||||
|
public GroupMemberAddEvent(Object source, RoomGroup roomGroup, List<GroupMember> memberList, Long inviteUid) {
|
||||||
|
super(source);
|
||||||
|
this.memberList = memberList;
|
||||||
|
this.roomGroup = roomGroup;
|
||||||
|
this.inviteUid = inviteUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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<Long> 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<Long> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import org.springframework.data.redis.core.ZSetOperations;
|
import org.springframework.data.redis.core.ZSetOperations;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -55,10 +56,18 @@ public class CursorUtils {
|
|||||||
Page<T> page = mapper.page(request.plusPage(), wrapper);
|
Page<T> page = mapper.page(request.plusPage(), wrapper);
|
||||||
String cursor = Optional.ofNullable(CollectionUtil.getLast(page.getRecords()))
|
String cursor = Optional.ofNullable(CollectionUtil.getLast(page.getRecords()))
|
||||||
.map(cursorColumn)
|
.map(cursorColumn)
|
||||||
.map(String::valueOf)
|
.map(CursorUtils::parseCursor)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
Boolean isLast = page.getRecords().size() != request.getPageSize();
|
Boolean isLast = page.getRecords().size() != request.getPageSize();
|
||||||
return new CursorPageBaseResp<>(cursor, isLast, page.getRecords());
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -849,6 +849,10 @@ public class RedisUtils {
|
|||||||
return stringRedisTemplate.opsForZSet().range(key, start, end);
|
return stringRedisTemplate.opsForZSet().range(key, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<String> zAll(String key) {
|
||||||
|
return stringRedisTemplate.opsForZSet().range(key, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取集合元素, 并且把score值也获取
|
* 获取集合元素, 并且把score值也获取
|
||||||
*
|
*
|
||||||
@@ -882,8 +886,14 @@ public class RedisUtils {
|
|||||||
* @param max 最大值
|
* @param max 最大值
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
|
public static Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
|
||||||
double min, double max) {
|
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);
|
return stringRedisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class UserApplyDao extends ServiceImpl<UserApplyMapper, UserApply> {
|
|||||||
return lambdaQuery()
|
return lambdaQuery()
|
||||||
.eq(UserApply::getTargetId, uid)
|
.eq(UserApply::getTargetId, uid)
|
||||||
.eq(UserApply::getType, ApplyTypeEnum.ADD_FRIEND.getCode())
|
.eq(UserApply::getType, ApplyTypeEnum.ADD_FRIEND.getCode())
|
||||||
.orderByAsc(UserApply::getCreateTime)
|
.orderByDesc(UserApply::getCreateTime)
|
||||||
.page(page);
|
.page(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
package com.abin.mallchat.common.user.dao;
|
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.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.entity.User;
|
||||||
|
import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum;
|
||||||
import com.abin.mallchat.common.user.mapper.UserMapper;
|
import com.abin.mallchat.common.user.mapper.UserMapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -47,7 +53,7 @@ public class UserDao extends ServiceImpl<UserMapper, User> {
|
|||||||
public List<User> getMemberList() {
|
public List<User> getMemberList() {
|
||||||
return lambdaQuery()
|
return lambdaQuery()
|
||||||
.eq(User::getStatus, NormalOrNoEnum.NORMAL.getStatus())
|
.eq(User::getStatus, NormalOrNoEnum.NORMAL.getStatus())
|
||||||
.orderByDesc(User::getUpdateTime)//最近活跃的1000个人,可以用lastOptTime字段,但是该字段没索引,updateTime可平替
|
.orderByDesc(User::getLastOptTime)//最近活跃的1000个人,可以用lastOptTime字段,但是该字段没索引,updateTime可平替
|
||||||
.last("limit 1000")//毕竟是大群聊,人数需要做个限制
|
.last("limit 1000")//毕竟是大群聊,人数需要做个限制
|
||||||
.select(User::getId, User::getName, User::getAvatar)
|
.select(User::getId, User::getName, User::getAvatar)
|
||||||
.list();
|
.list();
|
||||||
@@ -62,4 +68,23 @@ public class UserDao extends ServiceImpl<UserMapper, User> {
|
|||||||
.list();
|
.list();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getOnlineCount() {
|
||||||
|
return getOnlineCount(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getOnlineCount(List<Long> memberUidList) {
|
||||||
|
return lambdaQuery()
|
||||||
|
.eq(User::getActiveStatus, ChatActiveStatusEnum.ONLINE.getStatus())
|
||||||
|
.in(CollectionUtil.isNotEmpty(memberUidList), User::getId, memberUidList)
|
||||||
|
.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CursorPageBaseResp<User> getCursorPage(List<Long> 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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ public class User implements Serializable {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static Long UID_SYSTEM = 1L;//系统uid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户id
|
* 用户id
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -71,13 +71,13 @@ public class UserApply implements Serializable {
|
|||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改时间
|
* 修改时间
|
||||||
*/
|
*/
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private LocalDateTime updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -47,13 +47,13 @@ public class UserFriend implements Serializable {
|
|||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改时间
|
* 修改时间
|
||||||
*/
|
*/
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private LocalDateTime updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -47,11 +47,11 @@ public class UserRole implements Serializable {
|
|||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改时间
|
* 修改时间
|
||||||
*/
|
*/
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private LocalDateTime updateTime;
|
private Date updateTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -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;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ public class WSBaseResp<T> {
|
|||||||
/**
|
/**
|
||||||
* ws推送给前端的消息
|
* ws推送给前端的消息
|
||||||
*
|
*
|
||||||
* @see com.abin.mallchat.custom.user.domain.enums.WSRespTypeEnum
|
* @see WSRespTypeEnum
|
||||||
*/
|
*/
|
||||||
private Integer type;
|
private Integer type;
|
||||||
private T data;
|
private T data;
|
||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-07-29
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum WSPushTypeEnum {
|
||||||
|
USER(1, "个人"),
|
||||||
|
ALL(2, "全部连接用户"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer type;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
private static Map<Integer, WSPushTypeEnum> cache;
|
||||||
|
|
||||||
|
static {
|
||||||
|
cache = Arrays.stream(WSPushTypeEnum.values()).collect(Collectors.toMap(WSPushTypeEnum::getType, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WSPushTypeEnum of(Integer type) {
|
||||||
|
return cache.get(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -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.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@@ -28,7 +28,6 @@ public enum WSRespTypeEnum {
|
|||||||
RECALL(9, "消息撤回", WSMsgRecall.class),
|
RECALL(9, "消息撤回", WSMsgRecall.class),
|
||||||
APPLY(10, "好友申请", WSFriendApply.class),
|
APPLY(10, "好友申请", WSFriendApply.class),
|
||||||
MEMBER_CHANGE(11, "成员变动", WSMemberChange.class),
|
MEMBER_CHANGE(11, "成员变动", WSMemberChange.class),
|
||||||
MESSAGE_READ(12, "消息已读数", WSMessageRead.class),
|
|
||||||
;
|
;
|
||||||
|
|
||||||
private final Integer type;
|
private final Integer type;
|
||||||
@@ -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.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@@ -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;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ public class WSBaseReq {
|
|||||||
/**
|
/**
|
||||||
* 请求类型 1.请求登录二维码,2心跳检测
|
* 请求类型 1.请求登录二维码,2心跳检测
|
||||||
*
|
*
|
||||||
* @see com.abin.mallchat.custom.user.domain.enums.WSReqTypeEnum
|
* @see com.abin.mallchat.common.user.domain.enums.WSReqTypeEnum
|
||||||
*/
|
*/
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
@@ -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 io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -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.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@@ -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 io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -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.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@@ -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.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@@ -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 io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -18,9 +18,11 @@ import java.util.Date;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class WSMemberChange {
|
public class WSMemberChange {
|
||||||
|
public static final Integer CHANGE_TYPE_ADD = 1;
|
||||||
|
public static final Integer CHANGE_TYPE_REMOVE = 2;
|
||||||
@ApiModelProperty("群组id")
|
@ApiModelProperty("群组id")
|
||||||
private Long roomId;
|
private Long roomId;
|
||||||
@ApiModelProperty("变动人")
|
@ApiModelProperty("变动uid集合")
|
||||||
private Long uid;
|
private Long uid;
|
||||||
@ApiModelProperty("变动类型 1加入群组 2移除群组")
|
@ApiModelProperty("变动类型 1加入群组 2移除群组")
|
||||||
private Integer changeType;
|
private Integer changeType;
|
||||||
@@ -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;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -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 io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -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 io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -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 com.abin.mallchat.common.chat.domain.dto.ChatMsgRecallDTO;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -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.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -70,6 +70,13 @@ public class UserCache {
|
|||||||
RedisUtils.zAdd(onlineKey, uid, optTime.getTime());
|
RedisUtils.zAdd(onlineKey, uid, optTime.getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//获取用户上线列表
|
||||||
|
public List<Long> getOnlineUidList() {
|
||||||
|
String onlineKey = RedisKey.getKey(RedisKey.ONLINE_UID_ZET);
|
||||||
|
Set<String> strings = RedisUtils.zAll(onlineKey);
|
||||||
|
return strings.stream().map(Long::parseLong).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isOnline(Long uid) {
|
public boolean isOnline(Long uid) {
|
||||||
String onlineKey = RedisKey.getKey(RedisKey.ONLINE_UID_ZET);
|
String onlineKey = RedisKey.getKey(RedisKey.ONLINE_UID_ZET);
|
||||||
return RedisUtils.zIsMember(onlineKey, uid);
|
return RedisUtils.zIsMember(onlineKey, uid);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ mybatis-plus:
|
|||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
#运行的环境
|
#运行的环境
|
||||||
active: test
|
active: my-prod
|
||||||
application:
|
application:
|
||||||
name: mallchat
|
name: mallchat
|
||||||
datasource:
|
datasource:
|
||||||
|
|||||||
@@ -2,4 +2,14 @@
|
|||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.abin.mallchat.common.chat.mapper.ContactMapper">
|
<mapper namespace="com.abin.mallchat.common.chat.mapper.ContactMapper">
|
||||||
|
|
||||||
|
<insert id="refreshOrCreateActiveTime">
|
||||||
|
insert into contact(`room_id`,`uid`,`last_msg_id`,`active_time`)
|
||||||
|
values
|
||||||
|
<foreach collection="memberUidList" item="uid" separator=",">
|
||||||
|
(#{roomId},#{uid},#{msgId},#{activeTime})
|
||||||
|
</foreach>
|
||||||
|
on DUPLICATE KEY UPDATE
|
||||||
|
`last_msg_id`=VALUES(last_msg_id),
|
||||||
|
`active_time`=VALUES(active_time)
|
||||||
|
</insert>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -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.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.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.ApiResult;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||||
import com.abin.mallchat.common.common.utils.RequestHolder;
|
import com.abin.mallchat.common.common.utils.RequestHolder;
|
||||||
import com.abin.mallchat.common.user.domain.enums.BlackTypeEnum;
|
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.common.user.service.cache.UserCache;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.*;
|
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.ChatService;
|
||||||
import com.abin.mallchat.custom.user.service.impl.UserServiceImpl;
|
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -43,17 +45,12 @@ public class ChatController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserCache userCache;
|
private UserCache userCache;
|
||||||
|
|
||||||
@GetMapping("/public/room/page")
|
|
||||||
@ApiOperation("会话列表")
|
|
||||||
public ApiResult<CursorPageBaseResp<ChatRoomResp>> getRoomPage(@Valid CursorPageBaseReq request) {
|
|
||||||
return ApiResult.success(chatService.getRoomPage(request, RequestHolder.get().getUid()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/public/member/page")
|
@GetMapping("/public/member/page")
|
||||||
@ApiOperation("群成员列表")
|
@ApiOperation("群成员列表")
|
||||||
|
@Deprecated
|
||||||
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
||||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid CursorPageBaseReq request) {
|
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid MemberReq request) {
|
||||||
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(request);
|
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(null, request);
|
||||||
filterBlackMember(memberPage);
|
filterBlackMember(memberPage);
|
||||||
return ApiResult.success(memberPage);
|
return ApiResult.success(memberPage);
|
||||||
}
|
}
|
||||||
@@ -81,9 +78,6 @@ public class ChatController {
|
|||||||
return ApiResult.success(chatService.getMemberStatistic());
|
return ApiResult.success(chatService.getMemberStatistic());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UserServiceImpl userService;
|
|
||||||
|
|
||||||
@GetMapping("/public/msg/page")
|
@GetMapping("/public/msg/page")
|
||||||
@ApiOperation("消息列表")
|
@ApiOperation("消息列表")
|
||||||
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
||||||
@@ -138,5 +132,13 @@ public class ChatController {
|
|||||||
Long uid = RequestHolder.get().getUid();
|
Long uid = RequestHolder.get().getUid();
|
||||||
return ApiResult.success(chatService.getMsgReadInfo(uid, request));
|
return ApiResult.success(chatService.getMsgReadInfo(uid, request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PutMapping("/msg/read")
|
||||||
|
@ApiOperation("消息阅读上报")
|
||||||
|
public ApiResult<Void> msgRead(@Valid @RequestBody ChatMessageMemberReq request) {
|
||||||
|
Long uid = RequestHolder.get().getUid();
|
||||||
|
chatService.msgRead(uid, request);
|
||||||
|
return ApiResult.success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.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.ApiResult;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||||
import com.abin.mallchat.common.common.utils.RequestHolder;
|
import com.abin.mallchat.common.common.utils.RequestHolder;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
|
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.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.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -34,7 +35,7 @@ public class ContactController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ChatService chatService;
|
private ChatService chatService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RoomService roomService;
|
private RoomAppService roomService;
|
||||||
|
|
||||||
@GetMapping("/public/contact/page")
|
@GetMapping("/public/contact/page")
|
||||||
@ApiOperation("会话列表")
|
@ApiOperation("会话列表")
|
||||||
@@ -43,6 +44,11 @@ public class ContactController {
|
|||||||
return ApiResult.success(roomService.getContactPage(request, uid));
|
return ApiResult.success(roomService.getContactPage(request, uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/public/contact/detail")
|
||||||
|
@ApiOperation("会话详情")
|
||||||
|
public ApiResult<ChatRoomResp> getRoomPage(@Valid IdReqVO request) {
|
||||||
|
Long uid = RequestHolder.get().getUid();
|
||||||
|
return ApiResult.success(roomService.getContactDetail(uid, request.getId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,16 @@
|
|||||||
package com.abin.mallchat.custom.chat.controller;
|
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.request.IdReqVO;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
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.CursorPageBaseResp;
|
||||||
|
import com.abin.mallchat.common.common.domain.vo.response.IdRespVO;
|
||||||
import com.abin.mallchat.common.common.utils.RequestHolder;
|
import com.abin.mallchat.common.common.utils.RequestHolder;
|
||||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMemberReq;
|
import com.abin.mallchat.custom.chat.domain.vo.request.*;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.MemberAddReq;
|
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.MemberDelReq;
|
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.MemberReq;
|
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberListResp;
|
import com.abin.mallchat.custom.chat.domain.vo.response.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.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.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -38,41 +34,48 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class RoomController {
|
public class RoomController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ChatService chatService;
|
private RoomAppService roomService;
|
||||||
@Autowired
|
|
||||||
private UserCache userCache;
|
|
||||||
|
|
||||||
@GetMapping("/public/group")
|
@GetMapping("/public/group")
|
||||||
@ApiOperation("群组详情")
|
@ApiOperation("群组详情")
|
||||||
public ApiResult<MemberResp> groupDetail(@Valid IdReqVO request) {
|
public ApiResult<MemberResp> 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")
|
@GetMapping("/public/group/member/page")
|
||||||
@ApiOperation("群成员列表")
|
@ApiOperation("群成员列表")
|
||||||
@FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
|
|
||||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid MemberReq request) {
|
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(@Valid MemberReq request) {
|
||||||
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(request);
|
return ApiResult.success(roomService.getMemberPage(request));
|
||||||
return ApiResult.success(memberPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/group/member/list")
|
@GetMapping("/group/member/list")
|
||||||
@ApiOperation("房间内的所有群成员列表-@专用")
|
@ApiOperation("房间内的所有群成员列表-@专用")
|
||||||
public ApiResult<List<ChatMemberListResp>> getMemberList(@Valid ChatMessageMemberReq request) {
|
public ApiResult<List<ChatMemberListResp>> getMemberList(@Valid ChatMessageMemberReq request) {
|
||||||
return ApiResult.success(chatService.getMemberList(request));
|
return ApiResult.success(roomService.getMemberList(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/group/member")
|
@DeleteMapping("/group/member")
|
||||||
@ApiOperation("移除成员")
|
@ApiOperation("移除成员")
|
||||||
public ApiResult<Void> delMember(@Valid @RequestBody MemberDelReq request) {
|
public ApiResult<Void> delMember(@Valid @RequestBody MemberDelReq request) {
|
||||||
Long uid = RequestHolder.get().getUid();
|
Long uid = RequestHolder.get().getUid();
|
||||||
|
roomService.delMember(uid, request);
|
||||||
return ApiResult.success();
|
return ApiResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/group")
|
||||||
|
@ApiOperation("新增群组")
|
||||||
|
public ApiResult<IdRespVO> addGroup(@Valid @RequestBody GroupAddReq request) {
|
||||||
|
Long uid = RequestHolder.get().getUid();
|
||||||
|
Long roomId = roomService.addGroup(uid, request);
|
||||||
|
return ApiResult.success(IdRespVO.id(roomId));
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/group/member")
|
@PostMapping("/group/member")
|
||||||
@ApiOperation("邀请好友")
|
@ApiOperation("邀请好友")
|
||||||
public ApiResult<List<ChatMemberListResp>> addMember(@Valid @RequestBody MemberAddReq request) {
|
public ApiResult<Void> addMember(@Valid @RequestBody MemberAddReq request) {
|
||||||
Long uid = RequestHolder.get().getUid();
|
Long uid = RequestHolder.get().getUid();
|
||||||
|
roomService.addMember(uid, request);
|
||||||
return ApiResult.success();
|
return ApiResult.success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-19
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum GroupRoleAPPEnum {
|
||||||
|
LEADER(1, "群主"),
|
||||||
|
MANAGER(2, "管理"),
|
||||||
|
MEMBER(3, "普通成员"),
|
||||||
|
REMOVE(4, "被移除的成员"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer type;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
private static Map<Integer, GroupRoleAPPEnum> cache;
|
||||||
|
|
||||||
|
static {
|
||||||
|
cache = Arrays.stream(GroupRoleAPPEnum.values()).collect(Collectors.toMap(GroupRoleAPPEnum::getType, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GroupRoleAPPEnum of(Integer type) {
|
||||||
|
return cache.get(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,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: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class GroupAddReq {
|
||||||
|
@NotNull
|
||||||
|
@Size(min = 1, max = 50)
|
||||||
|
@ApiModelProperty("邀请的uid")
|
||||||
|
private List<Long> uidList;
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ import java.util.List;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class MemberAddReq {
|
public class MemberAddReq {
|
||||||
@NotNull
|
@NotNull
|
||||||
@ApiModelProperty("会话id")
|
@ApiModelProperty("房间id")
|
||||||
private Long roomId;
|
private Long roomId;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description:
|
* Description:
|
||||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
@@ -20,6 +18,5 @@ import javax.validation.constraints.NotNull;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class MemberReq extends CursorPageBaseReq {
|
public class MemberReq extends CursorPageBaseReq {
|
||||||
@ApiModelProperty("房间号")
|
@ApiModelProperty("房间号")
|
||||||
@NotNull
|
private Long roomId = 1L;
|
||||||
private Long roomId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
|
||||||
* Date: 2023-03-23
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class ChatMessageResp {
|
|
||||||
|
|
||||||
@ApiModelProperty("发送者信息")
|
|
||||||
private UserInfo fromUser;
|
|
||||||
@ApiModelProperty("消息详情")
|
|
||||||
private Message message;
|
|
||||||
|
|
||||||
@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;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,7 @@ public class ChatRoomResp {
|
|||||||
@ApiModelProperty("会话头像")
|
@ApiModelProperty("会话头像")
|
||||||
private String avatar;
|
private String avatar;
|
||||||
@ApiModelProperty("房间最后活跃时间(用来排序)")
|
@ApiModelProperty("房间最后活跃时间(用来排序)")
|
||||||
private Date lastActiveTime;
|
private Date activeTime;
|
||||||
@ApiModelProperty("未读数")
|
@ApiModelProperty("未读数")
|
||||||
private Integer unreadCount;
|
private Integer unreadCount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,17 @@ import lombok.NoArgsConstructor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class MemberResp {
|
public class MemberResp {
|
||||||
@ApiModelProperty("群id")
|
@ApiModelProperty("房间id")
|
||||||
private Long id;
|
private Long roomId;
|
||||||
@ApiModelProperty("群名称")
|
@ApiModelProperty("群名称")
|
||||||
private Long groupName;
|
private String groupName;
|
||||||
|
@ApiModelProperty("群头像")
|
||||||
|
private String avatar;
|
||||||
@ApiModelProperty("在线人数")
|
@ApiModelProperty("在线人数")
|
||||||
private Long onlineNum;//在线人数
|
private Long onlineNum;//在线人数
|
||||||
@ApiModelProperty("群聊描述")
|
/**
|
||||||
private String desc;//在线人数
|
* @see com.abin.mallchat.custom.chat.domain.vo.enums.GroupRoleAPPEnum
|
||||||
|
*/
|
||||||
@ApiModelProperty("成员角色 1群主 2管理员 3普通成员 4踢出群聊")
|
@ApiModelProperty("成员角色 1群主 2管理员 3普通成员 4踢出群聊")
|
||||||
private Integer role;//在线人数
|
private Integer role;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.dto.MsgReadInfoDTO;
|
||||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
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.request.CursorPageBaseReq;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
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.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 javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -46,10 +50,11 @@ public interface ChatService {
|
|||||||
/**
|
/**
|
||||||
* 获取群成员列表
|
* 获取群成员列表
|
||||||
*
|
*
|
||||||
|
* @param memberUidList
|
||||||
* @param request
|
* @param request
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
CursorPageBaseResp<ChatMemberResp> getMemberPage(CursorPageBaseReq request);
|
CursorPageBaseResp<ChatMemberResp> getMemberPage(List<Long> memberUidList, CursorPageBaseReq request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取消息列表
|
* 获取消息列表
|
||||||
@@ -59,15 +64,6 @@ public interface ChatService {
|
|||||||
*/
|
*/
|
||||||
CursorPageBaseResp<ChatMessageResp> getMsgPage(ChatMessagePageReq request, @Nullable Long receiveUid);
|
CursorPageBaseResp<ChatMessageResp> getMsgPage(ChatMessagePageReq request, @Nullable Long receiveUid);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取会话列表
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @param uid
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
CursorPageBaseResp<ChatRoomResp> getRoomPage(CursorPageBaseReq request, Long uid);
|
|
||||||
|
|
||||||
ChatMemberStatisticResp getMemberStatistic();
|
ChatMemberStatisticResp getMemberStatistic();
|
||||||
|
|
||||||
void setMsgMark(Long uid, ChatMessageMarkReq request);
|
void setMsgMark(Long uid, ChatMessageMarkReq request);
|
||||||
@@ -79,4 +75,6 @@ public interface ChatService {
|
|||||||
Collection<MsgReadInfoDTO> getMsgReadInfo(Long uid, ChatMessageReadInfoReq request);
|
Collection<MsgReadInfoDTO> getMsgReadInfo(Long uid, ChatMessageReadInfoReq request);
|
||||||
|
|
||||||
CursorPageBaseResp<ChatMessageReadResp> getReadPage(Long uid, ChatMessageReadReq request);
|
CursorPageBaseResp<ChatMessageReadResp> getReadPage(Long uid, ChatMessageReadReq request);
|
||||||
|
|
||||||
|
void msgRead(Long uid, ChatMessageMemberReq request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-07-22
|
||||||
|
*/
|
||||||
|
public interface RoomAppService {
|
||||||
|
/**
|
||||||
|
* 获取会话列表--支持未登录态
|
||||||
|
*/
|
||||||
|
CursorPageBaseResp<ChatRoomResp> getContactPage(CursorPageBaseReq request, Long uid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群组信息
|
||||||
|
*/
|
||||||
|
MemberResp getGroupDetail(Long uid, long roomId);
|
||||||
|
|
||||||
|
CursorPageBaseResp<ChatMemberResp> getMemberPage(MemberReq request);
|
||||||
|
|
||||||
|
List<ChatMemberListResp> getMemberList(ChatMessageMemberReq request);
|
||||||
|
|
||||||
|
void delMember(Long uid, MemberDelReq request);
|
||||||
|
|
||||||
|
void addMember(Long uid, MemberAddReq request);
|
||||||
|
|
||||||
|
Long addGroup(Long uid, GroupAddReq request);
|
||||||
|
|
||||||
|
ChatRoomResp getContactDetail(Long uid, Long roomId);
|
||||||
|
}
|
||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
|
||||||
* Date: 2023-07-22
|
|
||||||
*/
|
|
||||||
public interface RoomService {
|
|
||||||
/**
|
|
||||||
* 获取会话列表--支持未登录态
|
|
||||||
*/
|
|
||||||
CursorPageBaseResp<ChatRoomResp> getContactPage(CursorPageBaseReq request, Long uid);
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,29 @@
|
|||||||
package com.abin.mallchat.custom.chat.service.adapter;
|
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.User;
|
||||||
import com.abin.mallchat.common.user.domain.entity.UserFriend;
|
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.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 lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
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: 成员适配器
|
* Description: 成员适配器
|
||||||
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
@@ -27,12 +35,12 @@ public class MemberAdapter {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserCache userCache;
|
private UserCache userCache;
|
||||||
|
|
||||||
public List<ChatMemberResp> buildMember(List<Pair<Long, Double>> list, ChatActiveStatusEnum statusEnum) {
|
public static List<ChatMemberResp> buildMember(List<User> list) {
|
||||||
return list.stream().map(a -> {
|
return list.stream().map(a -> {
|
||||||
ChatMemberResp resp = new ChatMemberResp();
|
ChatMemberResp resp = new ChatMemberResp();
|
||||||
resp.setActiveStatus(statusEnum.getStatus());
|
resp.setActiveStatus(a.getActiveStatus());
|
||||||
resp.setLastOptTime(new Date(a.getValue().longValue()));
|
resp.setLastOptTime(a.getLastOptTime());
|
||||||
resp.setUid(a.getKey());
|
resp.setUid(a.getId());
|
||||||
return resp;
|
return resp;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@@ -50,4 +58,53 @@ public class MemberAdapter {
|
|||||||
return resp;
|
return resp;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<ChatMemberListResp> buildMemberList(List<User> memberList) {
|
||||||
|
return memberList.stream()
|
||||||
|
.map(a -> {
|
||||||
|
ChatMemberListResp resp = new ChatMemberListResp();
|
||||||
|
BeanUtils.copyProperties(a, resp);
|
||||||
|
resp.setUid(a.getId());
|
||||||
|
return resp;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ChatMemberListResp> buildMemberList(Map<Long, User> batch) {
|
||||||
|
return buildMemberList(new ArrayList<>(batch.values()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<GroupMember> buildMemberAdd(Long groupId, List<Long> waitAddUidList) {
|
||||||
|
return waitAddUidList.stream().map(a -> {
|
||||||
|
GroupMember member = new GroupMember();
|
||||||
|
member.setGroupId(groupId);
|
||||||
|
member.setUid(a);
|
||||||
|
member.setRole(GroupRoleEnum.MEMBER.getType());
|
||||||
|
return member;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WSBaseResp<WSMemberChange> buildMemberAddWS(Long roomId, User user) {
|
||||||
|
WSBaseResp<WSMemberChange> wsBaseResp = new WSBaseResp<>();
|
||||||
|
wsBaseResp.setType(WSRespTypeEnum.MEMBER_CHANGE.getType());
|
||||||
|
WSMemberChange wsMemberChange = new WSMemberChange();
|
||||||
|
wsMemberChange.setActiveStatus(user.getActiveStatus());
|
||||||
|
wsMemberChange.setLastOptTime(user.getLastOptTime());
|
||||||
|
wsMemberChange.setUid(user.getId());
|
||||||
|
wsMemberChange.setRoomId(roomId);
|
||||||
|
wsMemberChange.setChangeType(CHANGE_TYPE_ADD);
|
||||||
|
wsBaseResp.setData(wsMemberChange);
|
||||||
|
return wsBaseResp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WSBaseResp<WSMemberChange> buildMemberRemoveWS(Long roomId, Long uid) {
|
||||||
|
WSBaseResp<WSMemberChange> wsBaseResp = new WSBaseResp<>();
|
||||||
|
wsBaseResp.setType(WSRespTypeEnum.MEMBER_CHANGE.getType());
|
||||||
|
WSMemberChange wsMemberChange = new WSMemberChange();
|
||||||
|
wsMemberChange.setUid(uid);
|
||||||
|
wsMemberChange.setRoomId(roomId);
|
||||||
|
wsMemberChange.setChangeType(CHANGE_TYPE_REMOVE);
|
||||||
|
wsBaseResp.setData(wsMemberChange);
|
||||||
|
return wsBaseResp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.MessageMarkTypeEnum;
|
||||||
import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum;
|
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.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.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.ChatMessageReq;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.msg.TextMsgReq;
|
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.AbstractMsgHandler;
|
||||||
import com.abin.mallchat.custom.chat.service.strategy.msg.MsgHandlerFactory;
|
import com.abin.mallchat.custom.chat.service.strategy.msg.MsgHandlerFactory;
|
||||||
|
|
||||||
@@ -79,22 +78,6 @@ public class MessageAdapter {
|
|||||||
return userInfo;
|
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) {
|
public static ChatMessageReq buildAgreeMsg(Long roomId) {
|
||||||
ChatMessageReq chatMessageReq = new ChatMessageReq();
|
ChatMessageReq chatMessageReq = new ChatMessageReq();
|
||||||
chatMessageReq.setRoomId(roomId);
|
chatMessageReq.setRoomId(roomId);
|
||||||
|
|||||||
@@ -2,11 +2,18 @@ package com.abin.mallchat.custom.chat.service.adapter;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import com.abin.mallchat.common.chat.domain.entity.Contact;
|
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.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.ChatMessageReadResp;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
|
import com.abin.mallchat.custom.chat.domain.vo.response.ChatRoomResp;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,7 +29,7 @@ public class RoomAdapter {
|
|||||||
.map(a -> {
|
.map(a -> {
|
||||||
ChatRoomResp resp = new ChatRoomResp();
|
ChatRoomResp resp = new ChatRoomResp();
|
||||||
BeanUtil.copyProperties(a, resp);
|
BeanUtil.copyProperties(a, resp);
|
||||||
resp.setLastActiveTime(a.getActiveTime());
|
resp.setActiveTime(a.getActiveTime());
|
||||||
return resp;
|
return resp;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@@ -34,4 +41,31 @@ public class RoomAdapter {
|
|||||||
return resp;
|
return resp;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<GroupMember> buildGroupMemberBatch(List<Long> uidList, Long groupId) {
|
||||||
|
return uidList.stream()
|
||||||
|
.distinct()
|
||||||
|
.map(uid -> {
|
||||||
|
GroupMember member = new GroupMember();
|
||||||
|
member.setRole(GroupRoleEnum.MEMBER.getType());
|
||||||
|
member.setUid(uid);
|
||||||
|
member.setGroupId(groupId);
|
||||||
|
return member;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChatMessageReq buildGroupAddMessage(RoomGroup groupRoom, User inviter, Map<Long, User> member) {
|
||||||
|
ChatMessageReq chatMessageReq = new ChatMessageReq();
|
||||||
|
chatMessageReq.setRoomId(groupRoom.getRoomId());
|
||||||
|
chatMessageReq.setMsgType(MessageTypeEnum.SYSTEM.getType());
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("\"")
|
||||||
|
.append(inviter.getName())
|
||||||
|
.append("\"")
|
||||||
|
.append("邀请")
|
||||||
|
.append(member.values().stream().map(u -> "\"" + u.getName() + "\"").collect(Collectors.joining(",")))
|
||||||
|
.append("加入群聊");
|
||||||
|
chatMessageReq.setBody(sb.toString());
|
||||||
|
return chatMessageReq;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.Contact;
|
||||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
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.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.MessageMarkActTypeEnum;
|
||||||
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
|
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.chat.service.ContactService;
|
||||||
import com.abin.mallchat.common.common.annotation.RedissonLock;
|
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.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.event.MessageSendEvent;
|
||||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||||
import com.abin.mallchat.common.user.dao.UserDao;
|
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.ChatActiveStatusEnum;
|
||||||
import com.abin.mallchat.common.user.domain.enums.RoleEnum;
|
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.IRoleService;
|
||||||
import com.abin.mallchat.common.user.service.cache.ItemCache;
|
import com.abin.mallchat.common.user.service.cache.ItemCache;
|
||||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
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.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.ChatService;
|
||||||
import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter;
|
import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter;
|
||||||
import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter;
|
import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter;
|
||||||
@@ -116,26 +120,26 @@ public class ChatServiceImpl implements ChatService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CursorPageBaseResp<ChatMemberResp> getMemberPage(CursorPageBaseReq request) {
|
public CursorPageBaseResp<ChatMemberResp> getMemberPage(List<Long> memberUidList, CursorPageBaseReq request) {
|
||||||
Pair<ChatActiveStatusEnum, String> pair = ChatMemberHelper.getCursorPair(request.getCursor());
|
Pair<ChatActiveStatusEnum, String> pair = ChatMemberHelper.getCursorPair(request.getCursor());
|
||||||
ChatActiveStatusEnum activeStatusEnum = pair.getKey();
|
ChatActiveStatusEnum activeStatusEnum = pair.getKey();
|
||||||
String timeCursor = pair.getValue();
|
String timeCursor = pair.getValue();
|
||||||
List<ChatMemberResp> resultList = new ArrayList<>();//最终列表
|
List<ChatMemberResp> resultList = new ArrayList<>();//最终列表
|
||||||
Boolean isLast = Boolean.FALSE;
|
Boolean isLast = Boolean.FALSE;
|
||||||
if (activeStatusEnum == ChatActiveStatusEnum.ONLINE) {//在线列表
|
if (activeStatusEnum == ChatActiveStatusEnum.ONLINE) {//在线列表
|
||||||
CursorPageBaseResp<Pair<Long, Double>> cursorPage = userCache.getOnlineCursorPage(new CursorPageBaseReq(request.getPageSize(), timeCursor));
|
CursorPageBaseResp<User> cursorPage = userDao.getCursorPage(memberUidList, request, ChatActiveStatusEnum.ONLINE);
|
||||||
resultList.addAll(memberAdapter.buildMember(cursorPage.getList(), ChatActiveStatusEnum.ONLINE));//添加在线列表
|
resultList.addAll(MemberAdapter.buildMember(cursorPage.getList()));//添加在线列表
|
||||||
if (cursorPage.getIsLast()) {//如果是最后一页,从离线列表再补点数据
|
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;
|
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();
|
timeCursor = cursorPage.getCursor();
|
||||||
isLast = cursorPage.getIsLast();
|
isLast = cursorPage.getIsLast();
|
||||||
} else if (activeStatusEnum == ChatActiveStatusEnum.OFFLINE) {//离线列表
|
} else if (activeStatusEnum == ChatActiveStatusEnum.OFFLINE) {//离线列表
|
||||||
CursorPageBaseResp<Pair<Long, Double>> cursorPage = userCache.getOfflineCursorPage(new CursorPageBaseReq(request.getPageSize(), timeCursor));
|
CursorPageBaseResp<User> cursorPage = userDao.getCursorPage(memberUidList, request, ChatActiveStatusEnum.OFFLINE);
|
||||||
resultList.addAll(memberAdapter.buildMember(cursorPage.getList(), ChatActiveStatusEnum.OFFLINE));//添加离线线列表
|
resultList.addAll(MemberAdapter.buildMember(cursorPage.getList()));//添加离线线列表
|
||||||
timeCursor = cursorPage.getCursor();
|
timeCursor = cursorPage.getCursor();
|
||||||
isLast = cursorPage.getIsLast();
|
isLast = cursorPage.getIsLast();
|
||||||
}
|
}
|
||||||
@@ -152,18 +156,6 @@ public class ChatServiceImpl implements ChatService {
|
|||||||
return CursorPageBaseResp.init(cursorPage, getMsgRespBatch(cursorPage.getList(), receiveUid));
|
return CursorPageBaseResp.init(cursorPage, getMsgRespBatch(cursorPage.getList(), receiveUid));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CursorPageBaseResp<ChatRoomResp> getRoomPage(CursorPageBaseReq request, Long uid) {
|
|
||||||
CursorPageBaseResp<Room> cursorPage = roomDao.getCursorPage(request);
|
|
||||||
ArrayList<Room> 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
|
@Override
|
||||||
public ChatMemberStatisticResp getMemberStatistic() {
|
public ChatMemberStatisticResp getMemberStatistic() {
|
||||||
System.out.println(Thread.currentThread().getName());
|
System.out.println(Thread.currentThread().getName());
|
||||||
@@ -240,6 +232,24 @@ public class ChatServiceImpl implements ChatService {
|
|||||||
return CursorPageBaseResp.init(page, RoomAdapter.buildReadResp(page.getList()));
|
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) {
|
private void checkRecall(Long uid, Message message) {
|
||||||
AssertUtil.isNotEmpty(message, "消息有误");
|
AssertUtil.isNotEmpty(message, "消息有误");
|
||||||
AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL, "消息无法撤回");
|
AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL, "消息无法撤回");
|
||||||
|
|||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-07-22
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class RoomAppServiceImpl implements RoomAppService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ContactDao contactDao;
|
||||||
|
@Autowired
|
||||||
|
private RoomCache roomCache;
|
||||||
|
@Autowired
|
||||||
|
private RoomGroupCache roomGroupCache;
|
||||||
|
@Autowired
|
||||||
|
private RoomFriendCache roomFriendCache;
|
||||||
|
@Autowired
|
||||||
|
private UserInfoCache userInfoCache;
|
||||||
|
@Autowired
|
||||||
|
private MessageDao messageDao;
|
||||||
|
@Autowired
|
||||||
|
private HotRoomCache hotRoomCache;
|
||||||
|
@Autowired
|
||||||
|
private UserCache userCache;
|
||||||
|
@Autowired
|
||||||
|
private GroupMemberDao groupMemberDao;
|
||||||
|
@Autowired
|
||||||
|
private UserDao userDao;
|
||||||
|
@Autowired
|
||||||
|
private ChatService chatService;
|
||||||
|
@Autowired
|
||||||
|
private IRoleService iRoleService;
|
||||||
|
@Autowired
|
||||||
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
@Autowired
|
||||||
|
private RoomService roomService;
|
||||||
|
@Autowired
|
||||||
|
private GroupMemberCache groupMemberCache;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CursorPageBaseResp<ChatRoomResp> getContactPage(CursorPageBaseReq request, Long uid) {
|
||||||
|
//查出用户要展示的会话列表
|
||||||
|
CursorPageBaseResp<Long> page;
|
||||||
|
if (Objects.nonNull(uid)) {
|
||||||
|
Double hotStart = getCursorOrNull(request.getCursor());
|
||||||
|
Double hotEnd;
|
||||||
|
//用户基础会话
|
||||||
|
CursorPageBaseResp<Contact> contactPage = contactDao.getContactPage(uid, request);
|
||||||
|
List<Long> baseRoomIds = contactPage.getList().stream().map(Contact::getRoomId).collect(Collectors.toList());
|
||||||
|
hotEnd = getCursorOrNull(contactPage.getCursor());
|
||||||
|
//热门房间
|
||||||
|
Set<ZSetOperations.TypedTuple<String>> typedTuples = hotRoomCache.getRoomRange(hotStart, hotEnd);
|
||||||
|
List<Long> hotRoomIds = typedTuples.stream().map(ZSetOperations.TypedTuple::getValue).filter(Objects::nonNull).map(Long::parseLong).collect(Collectors.toList());
|
||||||
|
baseRoomIds.addAll(hotRoomIds);
|
||||||
|
//基础会话和热门房间合并
|
||||||
|
page = CursorPageBaseResp.init(contactPage, baseRoomIds);
|
||||||
|
} else {//用户未登录,只查全局房间
|
||||||
|
CursorPageBaseResp<Pair<Long, Double>> roomCursorPage = hotRoomCache.getRoomCursorPage(request);
|
||||||
|
List<Long> roomIds = roomCursorPage.getList().stream().map(Pair::getKey).collect(Collectors.toList());
|
||||||
|
page = CursorPageBaseResp.init(roomCursorPage, roomIds);
|
||||||
|
}
|
||||||
|
//最后组装会话信息(名称,头像,未读数等)
|
||||||
|
List<ChatRoomResp> result = buildContactResp(uid, page.getList());
|
||||||
|
return CursorPageBaseResp.init(page, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChatRoomResp getContactDetail(Long uid, Long roomId) {
|
||||||
|
Room room = roomCache.get(roomId);
|
||||||
|
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||||
|
return buildContactResp(uid, Collections.singletonList(roomId)).get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MemberResp getGroupDetail(Long uid, long roomId) {
|
||||||
|
RoomGroup roomGroup = roomGroupCache.get(roomId);
|
||||||
|
Room room = roomCache.get(roomId);
|
||||||
|
AssertUtil.isNotEmpty(roomGroup, "roomId有误");
|
||||||
|
Long onlineNum;
|
||||||
|
if (isHotGroup(room)) {//热点群从redis取人数
|
||||||
|
onlineNum = userCache.getOnlineNum();
|
||||||
|
} else {
|
||||||
|
List<Long> memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId());
|
||||||
|
onlineNum = userDao.getOnlineCount(memberUidList).longValue();
|
||||||
|
}
|
||||||
|
GroupRoleAPPEnum groupRole = getGroupRole(uid, roomGroup, room);
|
||||||
|
return MemberResp.builder()
|
||||||
|
.avatar(roomGroup.getAvatar())
|
||||||
|
.roomId(roomId)
|
||||||
|
.groupName(roomGroup.getName())
|
||||||
|
.onlineNum(onlineNum)
|
||||||
|
.role(groupRole.getType())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CursorPageBaseResp<ChatMemberResp> getMemberPage(MemberReq request) {
|
||||||
|
Room room = roomCache.get(request.getRoomId());
|
||||||
|
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||||
|
List<Long> memberUidList = null;
|
||||||
|
if (isHotGroup(room)) {//全员群展示所有用户
|
||||||
|
memberUidList = null;
|
||||||
|
} else {//只展示房间内的群成员
|
||||||
|
RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
|
||||||
|
memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId());
|
||||||
|
}
|
||||||
|
return chatService.getMemberPage(memberUidList, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Cacheable(cacheNames = "member", key = "'memberList.'+#request.roomId")
|
||||||
|
public List<ChatMemberListResp> getMemberList(ChatMessageMemberReq request) {
|
||||||
|
Room room = roomCache.get(request.getRoomId());
|
||||||
|
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||||
|
if (isHotGroup(room)) {//全员群展示所有用户100名
|
||||||
|
List<User> memberList = userDao.getMemberList();
|
||||||
|
return MemberAdapter.buildMemberList(memberList);
|
||||||
|
} else {
|
||||||
|
RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
|
||||||
|
List<Long> memberUidList = groupMemberDao.getMemberUidList(roomGroup.getId());
|
||||||
|
Map<Long, User> batch = userInfoCache.getBatch(memberUidList);
|
||||||
|
return MemberAdapter.buildMemberList(batch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delMember(Long uid, MemberDelReq request) {
|
||||||
|
Room room = roomCache.get(request.getRoomId());
|
||||||
|
AssertUtil.isNotEmpty(room, "房间号有误");
|
||||||
|
RoomGroup roomGroup = roomGroupCache.get(request.getRoomId());
|
||||||
|
AssertUtil.isNotEmpty(roomGroup, "房间号有误");
|
||||||
|
GroupMember self = groupMemberDao.getMember(roomGroup.getId(), uid);
|
||||||
|
AssertUtil.isNotEmpty(self, "您不是群管理");
|
||||||
|
AssertUtil.isTrue(hasPower(self), "您不是群管理");
|
||||||
|
GroupMember member = groupMemberDao.getMember(roomGroup.getId(), request.getUid());
|
||||||
|
AssertUtil.isNotEmpty(self, "用户已经移除");
|
||||||
|
groupMemberDao.removeById(member.getId());
|
||||||
|
//发送移除事件告知群成员
|
||||||
|
List<Long> memberUidList = groupMemberCache.getMemberUidList(roomGroup.getRoomId());
|
||||||
|
WSBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), member.getUid());
|
||||||
|
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<Long> memberBatch = groupMemberDao.getMemberBatch(roomGroup.getId(), request.getUidList());
|
||||||
|
Set<Long> existUid = new HashSet<>(memberBatch);
|
||||||
|
List<Long> waitAddUidList = request.getUidList().stream().filter(a -> !existUid.contains(a)).collect(Collectors.toList());
|
||||||
|
if (CollectionUtils.isEmpty(waitAddUidList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<GroupMember> groupMembers = MemberAdapter.buildMemberAdd(roomGroup.getId(), waitAddUidList);
|
||||||
|
groupMemberDao.saveBatch(groupMembers);
|
||||||
|
applicationEventPublisher.publishEvent(new GroupMemberAddEvent(this, roomGroup, groupMembers, uid));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public Long addGroup(Long uid, GroupAddReq request) {
|
||||||
|
RoomGroup roomGroup = roomService.createGroupRoom(uid);
|
||||||
|
//批量保存群成员
|
||||||
|
List<GroupMember> groupMembers = RoomAdapter.buildGroupMemberBatch(request.getUidList(), roomGroup.getId());
|
||||||
|
groupMemberDao.saveBatch(groupMembers);
|
||||||
|
//发送邀请加群消息==》触发每个人的会话
|
||||||
|
applicationEventPublisher.publishEvent(new GroupMemberAddEvent(this, roomGroup, groupMembers, uid));
|
||||||
|
return roomGroup.getRoomId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasPower(GroupMember self) {
|
||||||
|
return Objects.equals(self.getRole(), GroupRoleEnum.LEADER.getType())
|
||||||
|
|| Objects.equals(self.getRole(), GroupRoleEnum.MANAGER.getType())
|
||||||
|
|| iRoleService.hasPower(self.getUid(), RoleEnum.ADMIN);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupRoleAPPEnum getGroupRole(Long uid, RoomGroup roomGroup, Room room) {
|
||||||
|
GroupMember member = Objects.isNull(uid) ? null : groupMemberDao.getMember(roomGroup.getId(), uid);
|
||||||
|
if (Objects.nonNull(member)) {
|
||||||
|
return GroupRoleAPPEnum.of(member.getRole());
|
||||||
|
} else if (isHotGroup(room)) {
|
||||||
|
return GroupRoleAPPEnum.MEMBER;
|
||||||
|
} else {
|
||||||
|
return GroupRoleAPPEnum.REMOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isHotGroup(Room room) {
|
||||||
|
return HotFlagEnum.YES.getType().equals(room.getHotFlag());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Contact> buildContact(List<Pair<Long, Double>> list, Long uid) {
|
||||||
|
List<Long> roomIds = list.stream().map(Pair::getKey).collect(Collectors.toList());
|
||||||
|
Map<Long, Room> batch = roomCache.getBatch(roomIds);
|
||||||
|
Map<Long, Contact> contactMap = new HashMap<>();
|
||||||
|
if (Objects.nonNull(uid)) {
|
||||||
|
List<Contact> byRoomIds = contactDao.getByRoomIds(roomIds, uid);
|
||||||
|
contactMap = byRoomIds.stream().collect(Collectors.toMap(Contact::getRoomId, Function.identity()));
|
||||||
|
}
|
||||||
|
Map<Long, Contact> finalContactMap = contactMap;
|
||||||
|
return list.stream().map(pair -> {
|
||||||
|
Long roomId = pair.getKey();
|
||||||
|
Contact contact = finalContactMap.get(roomId);
|
||||||
|
if (Objects.isNull(contact)) {
|
||||||
|
contact = new Contact();
|
||||||
|
contact.setRoomId(pair.getKey());
|
||||||
|
Room room = batch.get(roomId);
|
||||||
|
contact.setLastMsgId(room.getLastMsgId());
|
||||||
|
}
|
||||||
|
contact.setActiveTime(new Date(pair.getValue().longValue()));
|
||||||
|
return contact;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Double getCursorOrNull(String cursor) {
|
||||||
|
return Optional.ofNullable(cursor).map(Double::parseDouble).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private List<ChatRoomResp> buildContactResp(Long uid, List<Long> roomIds) {
|
||||||
|
//表情和头像
|
||||||
|
Map<Long, RoomBaseInfo> roomBaseInfoMap = getRoomBaseInfoMap(roomIds, uid);
|
||||||
|
//最后一条消息
|
||||||
|
List<Long> msgIds = roomBaseInfoMap.values().stream().map(RoomBaseInfo::getLastMsgId).collect(Collectors.toList());
|
||||||
|
List<Message> messages = CollectionUtil.isEmpty(msgIds) ? new ArrayList<>() : messageDao.listByIds(msgIds);
|
||||||
|
Map<Long, Message> msgMap = messages.stream().collect(Collectors.toMap(Message::getId, Function.identity()));
|
||||||
|
Map<Long, User> lastMsgUidMap = userInfoCache.getBatch(messages.stream().map(Message::getFromUid).collect(Collectors.toList()));
|
||||||
|
//消息未读数
|
||||||
|
Map<Long, Integer> unReadCountMap = getUnReadCountMap(uid, roomIds);
|
||||||
|
return roomBaseInfoMap.values().stream().map(room -> {
|
||||||
|
ChatRoomResp resp = new ChatRoomResp();
|
||||||
|
RoomBaseInfo roomBaseInfo = roomBaseInfoMap.get(room.getRoomId());
|
||||||
|
resp.setAvatar(roomBaseInfo.getAvatar());
|
||||||
|
resp.setRoomId(room.getRoomId());
|
||||||
|
resp.setActiveTime(room.getActiveTime());
|
||||||
|
resp.setHot_Flag(roomBaseInfo.getHotFlag());
|
||||||
|
resp.setType(roomBaseInfo.getType());
|
||||||
|
resp.setName(roomBaseInfo.getName());
|
||||||
|
Message message = msgMap.get(room.getLastMsgId());
|
||||||
|
if (Objects.nonNull(message)) {
|
||||||
|
AbstractMsgHandler strategyNoNull = MsgHandlerFactory.getStrategyNoNull(message.getType());
|
||||||
|
resp.setText(lastMsgUidMap.get(message.getFromUid()).getName() + ":" + strategyNoNull.showContactMsg(message));
|
||||||
|
}
|
||||||
|
resp.setUnreadCount(unReadCountMap.getOrDefault(room.getRoomId(), 0));
|
||||||
|
return resp;
|
||||||
|
}).sorted(Comparator.comparing(ChatRoomResp::getActiveTime).reversed())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取未读数
|
||||||
|
*/
|
||||||
|
private Map<Long, Integer> getUnReadCountMap(Long uid, List<Long> roomIds) {
|
||||||
|
if (Objects.isNull(uid)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
List<Contact> contacts = contactDao.getByRoomIds(roomIds, uid);
|
||||||
|
return contacts.parallelStream()
|
||||||
|
.map(contact -> Pair.of(contact.getRoomId(), messageDao.getUnReadCount(contact.getRoomId(), contact.getReadTime())))
|
||||||
|
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Long, User> getFriendRoomMap(List<Long> roomIds, Long uid) {
|
||||||
|
if (CollectionUtil.isEmpty(roomIds)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
Map<Long, RoomFriend> roomFriendMap = roomFriendCache.getBatch(roomIds);
|
||||||
|
Set<Long> friendUidSet = ChatAdapter.getFriendUidSet(roomFriendMap.values(), uid);
|
||||||
|
Map<Long, User> userBatch = userInfoCache.getBatch(new ArrayList<>(friendUidSet));
|
||||||
|
return roomFriendMap.values()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(RoomFriend::getRoomId, roomFriend -> {
|
||||||
|
Long friendUid = ChatAdapter.getFriendUid(roomFriend, uid);
|
||||||
|
return userBatch.get(friendUid);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Long, RoomBaseInfo> getRoomBaseInfoMap(List<Long> roomIds, Long uid) {
|
||||||
|
Map<Long, Room> roomMap = roomCache.getBatch(roomIds);
|
||||||
|
//房间根据好友和群组类型分组
|
||||||
|
Map<Integer, List<Long>> groupRoomIdMap = roomMap.values().stream().collect(Collectors.groupingBy(Room::getType,
|
||||||
|
Collectors.mapping(Room::getId, Collectors.toList())));
|
||||||
|
//获取群组信息
|
||||||
|
List<Long> groupRoomId = groupRoomIdMap.get(RoomTypeEnum.GROUP.getType());
|
||||||
|
Map<Long, RoomGroup> roomInfoBatch = roomGroupCache.getBatch(groupRoomId);
|
||||||
|
//获取好友信息
|
||||||
|
List<Long> friendRoomId = groupRoomIdMap.get(RoomTypeEnum.FRIEND.getType());
|
||||||
|
Map<Long, User> friendRoomMap = getFriendRoomMap(friendRoomId, uid);
|
||||||
|
|
||||||
|
return roomMap.values().stream().map(room -> {
|
||||||
|
RoomBaseInfo roomBaseInfo = new RoomBaseInfo();
|
||||||
|
roomBaseInfo.setRoomId(room.getId());
|
||||||
|
roomBaseInfo.setType(room.getType());
|
||||||
|
roomBaseInfo.setHotFlag(room.getHotFlag());
|
||||||
|
roomBaseInfo.setLastMsgId(room.getLastMsgId());
|
||||||
|
roomBaseInfo.setActiveTime(room.getActiveTime());
|
||||||
|
if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.GROUP) {
|
||||||
|
RoomGroup roomGroup = roomInfoBatch.get(room.getId());
|
||||||
|
roomBaseInfo.setName(roomGroup.getName());
|
||||||
|
roomBaseInfo.setAvatar(roomGroup.getAvatar());
|
||||||
|
} else if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.FRIEND) {
|
||||||
|
User user = friendRoomMap.get(room.getId());
|
||||||
|
roomBaseInfo.setName(user.getName());
|
||||||
|
roomBaseInfo.setAvatar(user.getAvatar());
|
||||||
|
}
|
||||||
|
return roomBaseInfo;
|
||||||
|
}).collect(Collectors.toMap(RoomBaseInfo::getRoomId, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillRoomActive(Long uid, Map<Long, Room> roomMap) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
|
||||||
* Date: 2023-07-22
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class RoomServiceImpl implements RoomService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ContactDao contactDao;
|
|
||||||
@Autowired
|
|
||||||
private RoomCache roomCache;
|
|
||||||
@Autowired
|
|
||||||
private RoomGroupCache roomGroupCache;
|
|
||||||
@Autowired
|
|
||||||
private RoomFriendCache roomFriendCache;
|
|
||||||
@Autowired
|
|
||||||
private UserInfoCache userInfoCache;
|
|
||||||
@Autowired
|
|
||||||
private MessageDao messageDao;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CursorPageBaseResp<ChatRoomResp> getContactPage(CursorPageBaseReq request, Long uid) {
|
|
||||||
|
|
||||||
if (Objects.nonNull(uid)) {
|
|
||||||
CursorPageBaseResp<Contact> contactPage = contactDao.getContactPage(uid, request);
|
|
||||||
List<Long> roomIds = contactPage.getList().stream().map(Contact::getRoomId).collect(Collectors.toList());
|
|
||||||
//表情和头像
|
|
||||||
Map<Long, RoomBaseInfo> roomBaseInfoMap = getRoomBaseInfoMap(roomIds, uid);
|
|
||||||
//最后一条消息
|
|
||||||
List<Long> msgIds = contactPage.getList().stream().map(Contact::getLastMsgId).collect(Collectors.toList());
|
|
||||||
List<Message> messages = messageDao.listByIds(msgIds);
|
|
||||||
Map<Long, Message> msgMap = messages.stream().collect(Collectors.toMap(Message::getId, Function.identity()));
|
|
||||||
List<ChatRoomResp> collect = contactPage.getList().stream().map(contact -> {
|
|
||||||
ChatRoomResp resp = new ChatRoomResp();
|
|
||||||
BeanUtil.copyProperties(contact, resp);
|
|
||||||
RoomBaseInfo roomBaseInfo = roomBaseInfoMap.get(contact.getRoomId());
|
|
||||||
resp.setAvatar(roomBaseInfo.getAvatar());
|
|
||||||
resp.setName(roomBaseInfo.getName());
|
|
||||||
Message message = msgMap.get(contact.getLastMsgId());
|
|
||||||
if (Objects.nonNull(message)) {
|
|
||||||
resp.setText();
|
|
||||||
}
|
|
||||||
return resp;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
CursorPageBaseResp.init(contactPage, collect);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<Long, User> getFriendRoomMap(List<Long> roomIds, Long uid) {
|
|
||||||
Map<Long, RoomFriend> roomFriendMap = roomFriendCache.getBatch(roomIds);
|
|
||||||
Set<Long> friendUidSet = ChatAdapter.getFriendUidSet(roomFriendMap.values(), uid);
|
|
||||||
Map<Long, User> userBatch = userInfoCache.getBatch(new ArrayList<>(friendUidSet));
|
|
||||||
return roomFriendMap.values()
|
|
||||||
.stream()
|
|
||||||
.collect(Collectors.toMap(RoomFriend::getRoomId, roomFriend -> {
|
|
||||||
Long friendUid = ChatAdapter.getFriendUid(roomFriend, uid);
|
|
||||||
return userBatch.get(friendUid);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<Long, RoomBaseInfo> getRoomBaseInfoMap(List<Long> roomIds, Long uid) {
|
|
||||||
Map<Long, Room> roomMap = roomCache.getBatch(roomIds);
|
|
||||||
Map<Integer, List<Long>> groupRoomIdMap = roomMap.values().stream().collect(Collectors.groupingBy(Room::getType,
|
|
||||||
Collectors.mapping(Room::getId, Collectors.toList())));
|
|
||||||
//获取群组信息
|
|
||||||
List<Long> groupRoomId = groupRoomIdMap.get(RoomTypeEnum.GROUP.getType());
|
|
||||||
Map<Long, RoomGroup> roomInfoBatch = roomGroupCache.getBatch(groupRoomId);
|
|
||||||
//获取好友信息
|
|
||||||
List<Long> friendRoomId = groupRoomIdMap.get(RoomTypeEnum.FRIEND.getType());
|
|
||||||
Map<Long, User> friendRoomMap = getFriendRoomMap(friendRoomId, uid);
|
|
||||||
return roomMap.values().stream().map(room -> {
|
|
||||||
RoomBaseInfo roomBaseInfo = new RoomBaseInfo();
|
|
||||||
roomBaseInfo.setRoomId(room.getId());
|
|
||||||
if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.GROUP) {
|
|
||||||
RoomGroup roomGroup = roomInfoBatch.get(room.getId());
|
|
||||||
roomBaseInfo.setName(roomGroup.getName());
|
|
||||||
roomBaseInfo.setAvatar(roomGroup.getAvatar());
|
|
||||||
} else if (RoomTypeEnum.of(room.getType()) == RoomTypeEnum.FRIEND) {
|
|
||||||
User user = friendRoomMap.get(room.getId());
|
|
||||||
roomBaseInfo.setName(user.getName());
|
|
||||||
roomBaseInfo.setAvatar(user.getAvatar());
|
|
||||||
}
|
|
||||||
return roomBaseInfo;
|
|
||||||
}).collect(Collectors.toMap(RoomBaseInfo::getRoomId, Function.identity()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -43,4 +43,9 @@ public abstract class AbstractMsgHandler {
|
|||||||
*/
|
*/
|
||||||
public abstract Object showReplyMsg(Message msg);
|
public abstract Object showReplyMsg(Message msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话列表——展示的消息
|
||||||
|
*/
|
||||||
|
public abstract String showContactMsg(Message msg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,9 @@ public class EmojisMsgHandler extends AbstractMsgHandler {
|
|||||||
public Object showReplyMsg(Message msg) {
|
public Object showReplyMsg(Message msg) {
|
||||||
return "表情";
|
return "表情";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showContactMsg(Message msg) {
|
||||||
|
return "[表情包]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,9 @@ public class FileMsgHandler extends AbstractMsgHandler {
|
|||||||
public Object showReplyMsg(Message msg) {
|
public Object showReplyMsg(Message msg) {
|
||||||
return "文件:" + msg.getExtra().getFileMsg().getFileName();
|
return "文件:" + msg.getExtra().getFileMsg().getFileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showContactMsg(Message msg) {
|
||||||
|
return "[文件]" + msg.getExtra().getFileMsg().getFileName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,9 @@ public class ImgMsgHandler extends AbstractMsgHandler {
|
|||||||
public Object showReplyMsg(Message msg) {
|
public Object showReplyMsg(Message msg) {
|
||||||
return "图片";
|
return "图片";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showContactMsg(Message msg) {
|
||||||
|
return "[图片]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,4 +76,9 @@ public class RecallMsgHandler extends AbstractMsgHandler {
|
|||||||
applicationEventPublisher.publishEvent(new MessageRecallEvent(this, new ChatMsgRecallDTO(message.getId(), message.getRoomId(), recallUid)));
|
applicationEventPublisher.publishEvent(new MessageRecallEvent(this, new ChatMsgRecallDTO(message.getId(), message.getRoomId(), recallUid)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showContactMsg(Message msg) {
|
||||||
|
return "撤回了一条消息";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,9 @@ public class SoundMsgHandler extends AbstractMsgHandler {
|
|||||||
public Object showReplyMsg(Message msg) {
|
public Object showReplyMsg(Message msg) {
|
||||||
return "语音";
|
return "语音";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showContactMsg(Message msg) {
|
||||||
|
return "[语音]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -135,4 +135,9 @@ public class TextMsgHandler extends AbstractMsgHandler {
|
|||||||
public Object showReplyMsg(Message msg) {
|
public Object showReplyMsg(Message msg) {
|
||||||
return msg.getContent();
|
return msg.getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showContactMsg(Message msg) {
|
||||||
|
return msg.getContent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,9 @@ public class VideoMsgHandler extends AbstractMsgHandler {
|
|||||||
public Object showReplyMsg(Message msg) {
|
public Object showReplyMsg(Message msg) {
|
||||||
return "视频";
|
return "视频";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showContactMsg(Message msg) {
|
||||||
|
return "[视频]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<GroupMember> memberList = event.getMemberList();
|
||||||
|
RoomGroup roomGroup = event.getRoomGroup();
|
||||||
|
Long inviteUid = event.getInviteUid();
|
||||||
|
User user = userInfoCache.get(inviteUid);
|
||||||
|
List<Long> 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<GroupMember> memberList = event.getMemberList();
|
||||||
|
RoomGroup roomGroup = event.getRoomGroup();
|
||||||
|
List<Long> memberUidList = groupMemberCache.getMemberUidList(roomGroup.getRoomId());
|
||||||
|
List<Long> uidList = memberList.stream().map(GroupMember::getUid).collect(Collectors.toList());
|
||||||
|
List<User> users = userDao.listByIds(uidList);
|
||||||
|
users.forEach(user -> {
|
||||||
|
WSBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberAddWS(roomGroup.getRoomId(), user);
|
||||||
|
applicationEventPublisher.publishEvent(new WSPushEvent(this, memberUidList, ws));
|
||||||
|
});
|
||||||
|
//移除缓存
|
||||||
|
groupMemberCache.evictMemberUidList(roomGroup.getRoomId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,22 +1,38 @@
|
|||||||
package com.abin.mallchat.custom.common.event.listener;
|
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.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.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.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.ChatService;
|
||||||
import com.abin.mallchat.custom.chat.service.WeChatMsgOperationService;
|
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.chatai.service.IChatAIService;
|
||||||
import com.abin.mallchat.custom.user.service.WebSocketService;
|
import com.abin.mallchat.custom.user.service.WebSocketService;
|
||||||
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.event.TransactionalEventListener;
|
import org.springframework.transaction.event.TransactionalEventListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,23 +51,68 @@ public class MessageSendListener {
|
|||||||
private MessageDao messageDao;
|
private MessageDao messageDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IChatAIService openAIService;
|
private IChatAIService openAIService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
WeChatMsgOperationService weChatMsgOperationService;
|
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
|
@Async
|
||||||
@TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true)
|
@TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true)
|
||||||
public void notifyAllOnline(MessageSendEvent event) {
|
public void messageRoute(MessageSendEvent event) {
|
||||||
Message message = messageDao.getById(event.getMsgId());
|
Message message = messageDao.getById(event.getMsgId());
|
||||||
|
Room room = roomCache.get(message.getRoomId());
|
||||||
ChatMessageResp msgResp = chatService.getMsgResp(message, null);
|
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<Long> memberUidList = new ArrayList<>();
|
||||||
|
if (Objects.equals(room.getType(), RoomTypeEnum.GROUP.getType())) {//普通群聊推送所有群成员
|
||||||
|
memberUidList = groupMemberCache.getMemberUidList(room.getId());
|
||||||
|
} else if (Objects.equals(room.getType(), RoomTypeEnum.FRIEND.getType())) {//单聊对象
|
||||||
|
//对单人推送
|
||||||
|
RoomFriend roomFriend = roomFriendDao.getByRoomId(room.getId());
|
||||||
|
memberUidList = Arrays.asList(roomFriend.getUid1(), roomFriend.getUid2());
|
||||||
|
}
|
||||||
|
//更新所有群成员的会话时间
|
||||||
|
contactDao.refreshOrCreateActiveTime(room.getId(), memberUidList, message.getId(), message.getCreateTime());
|
||||||
|
//推送房间成员
|
||||||
|
applicationEventPublisher.publishEvent(new WSPushEvent(this, memberUidList, WSAdapter.buildMsgSend(msgResp)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true)
|
@TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true)
|
||||||
public void handlerMsg(@NotNull MessageSendEvent event) {
|
public void handlerMsg(@NotNull MessageSendEvent event) {
|
||||||
Message message = messageDao.getById(event.getMsgId());
|
Message message = messageDao.getById(event.getMsgId());
|
||||||
|
Room room = roomCache.get(message.getRoomId());
|
||||||
|
if (isHotRoom(room)) {
|
||||||
openAIService.chat(message);
|
openAIService.chat(message);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public boolean isHotRoom(Room room) {
|
||||||
|
return Objects.equals(HotFlagEnum.YES.getType(), room.getHotFlag());
|
||||||
|
}
|
||||||
|
|
||||||
@TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true)
|
@TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true)
|
||||||
public void publishChatToWechat(@NotNull MessageSendEvent event) {
|
public void publishChatToWechat(@NotNull MessageSendEvent event) {
|
||||||
|
|||||||
@@ -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.common.event.UserApplyEvent;
|
||||||
import com.abin.mallchat.common.user.dao.UserApplyDao;
|
import com.abin.mallchat.common.user.dao.UserApplyDao;
|
||||||
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
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.WebSocketService;
|
||||||
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -30,7 +30,7 @@ public class UserApplyListener {
|
|||||||
public void notifyFriend(UserApplyEvent event) {
|
public void notifyFriend(UserApplyEvent event) {
|
||||||
UserApply userApply = event.getUserApply();
|
UserApply userApply = event.getUserApply();
|
||||||
Integer unReadCount = userApplyDao.getUnReadCount(userApply.getTargetId());
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.chat.dao.MessageDao;
|
||||||
import com.abin.mallchat.common.common.event.UserBlackEvent;
|
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.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 com.abin.mallchat.custom.user.service.WebSocketService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|||||||
@@ -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.common.event.UserOfflineEvent;
|
||||||
import com.abin.mallchat.common.user.dao.UserDao;
|
import com.abin.mallchat.common.user.dao.UserDao;
|
||||||
import com.abin.mallchat.common.user.domain.entity.User;
|
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.common.user.service.cache.UserCache;
|
||||||
import com.abin.mallchat.custom.user.service.WebSocketService;
|
import com.abin.mallchat.custom.user.service.WebSocketService;
|
||||||
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
||||||
@@ -45,6 +46,7 @@ public class UserOfflineListener {
|
|||||||
User update = new User();
|
User update = new User();
|
||||||
update.setId(user.getId());
|
update.setId(user.getId());
|
||||||
update.setLastOptTime(user.getLastOptTime());
|
update.setLastOptTime(user.getLastOptTime());
|
||||||
|
update.setActiveStatus(ChatActiveStatusEnum.OFFLINE.getStatus());
|
||||||
userDao.updateById(update);
|
userDao.updateById(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.common.event.UserOnlineEvent;
|
||||||
import com.abin.mallchat.common.user.dao.UserDao;
|
import com.abin.mallchat.common.user.dao.UserDao;
|
||||||
import com.abin.mallchat.common.user.domain.entity.User;
|
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.IpService;
|
||||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||||
import com.abin.mallchat.custom.user.service.WebSocketService;
|
import com.abin.mallchat.custom.user.service.WebSocketService;
|
||||||
@@ -49,6 +50,7 @@ public class UserOnlineListener {
|
|||||||
update.setId(user.getId());
|
update.setId(user.getId());
|
||||||
update.setLastOptTime(user.getLastOptTime());
|
update.setLastOptTime(user.getLastOptTime());
|
||||||
update.setIpInfo(user.getIpInfo());
|
update.setIpInfo(user.getIpInfo());
|
||||||
|
update.setActiveStatus(ChatActiveStatusEnum.ONLINE.getStatus());
|
||||||
userDao.updateById(update);
|
userDao.updateById(update);
|
||||||
//更新用户ip详情
|
//更新用户ip详情
|
||||||
ipService.refreshIpDetailAsync(user.getId());
|
ipService.refreshIpDetailAsync(user.getId());
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.CursorPageBaseResp;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.PageBaseResp;
|
import com.abin.mallchat.common.common.domain.vo.response.PageBaseResp;
|
||||||
import com.abin.mallchat.common.common.utils.RequestHolder;
|
import com.abin.mallchat.common.common.utils.RequestHolder;
|
||||||
import com.abin.mallchat.common.user.service.cache.UserCache;
|
import com.abin.mallchat.common.user.domain.vo.response.ws.ChatMemberResp;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp;
|
|
||||||
import com.abin.mallchat.custom.chat.service.ChatService;
|
|
||||||
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApplyReq;
|
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.FriendApproveReq;
|
||||||
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendCheckReq;
|
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.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -40,11 +37,6 @@ import javax.validation.Valid;
|
|||||||
@Api(tags = "好友相关接口")
|
@Api(tags = "好友相关接口")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FriendController {
|
public class FriendController {
|
||||||
@Autowired
|
|
||||||
private ChatService chatService;
|
|
||||||
@Autowired
|
|
||||||
private UserCache userCache;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private FriendService friendService;
|
private FriendService friendService;
|
||||||
|
|
||||||
@@ -86,13 +78,13 @@ public class FriendController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/apply")
|
@PutMapping("/apply")
|
||||||
@ApiOperation("申请审批")
|
@ApiOperation("审批申请")
|
||||||
public ApiResult<Void> applyApprove(@Valid @RequestBody FriendApproveReq request) {
|
public ApiResult<Void> applyApprove(@Valid @RequestBody FriendApproveReq request) {
|
||||||
friendService.applyApprove(RequestHolder.get().getUid(), request);
|
friendService.applyApprove(RequestHolder.get().getUid(), request);
|
||||||
return ApiResult.success();
|
return ApiResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/page")
|
@GetMapping("/page")
|
||||||
@ApiOperation("联系人列表")
|
@ApiOperation("联系人列表")
|
||||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> friendList(@Valid CursorPageBaseReq request) {
|
public ApiResult<CursorPageBaseResp<ChatMemberResp>> friendList(@Valid CursorPageBaseReq request) {
|
||||||
Long uid = RequestHolder.get().getUid();
|
Long uid = RequestHolder.get().getUid();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import lombok.Data;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,7 +25,7 @@ public class FriendApplyReq {
|
|||||||
@ApiModelProperty("申请信息")
|
@ApiModelProperty("申请信息")
|
||||||
private String msg;
|
private String msg;
|
||||||
|
|
||||||
@NotBlank
|
@NotNull
|
||||||
@ApiModelProperty("好友uid")
|
@ApiModelProperty("好友uid")
|
||||||
private Long targetUid;
|
private Long targetUid;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,7 +20,7 @@ import javax.validation.constraints.NotBlank;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class FriendDeleteReq {
|
public class FriendDeleteReq {
|
||||||
|
|
||||||
@NotBlank
|
@NotNull
|
||||||
@ApiModelProperty("好友uid")
|
@ApiModelProperty("好友uid")
|
||||||
private Long targetUid;
|
private Long targetUid;
|
||||||
|
|
||||||
|
|||||||
@@ -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.request.PageBaseReq;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
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.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.FriendApplyReq;
|
||||||
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApproveReq;
|
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendApproveReq;
|
||||||
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendCheckReq;
|
import com.abin.mallchat.custom.user.domain.vo.request.friend.FriendCheckReq;
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.abin.mallchat.custom.user.service;
|
package com.abin.mallchat.custom.user.service;
|
||||||
|
|
||||||
import com.abin.mallchat.common.user.domain.entity.User;
|
import com.abin.mallchat.common.user.domain.entity.User;
|
||||||
import com.abin.mallchat.custom.user.domain.vo.request.ws.WSAuthorize;
|
import com.abin.mallchat.common.user.domain.enums.WSBaseResp;
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSBaseResp;
|
import com.abin.mallchat.common.user.domain.vo.request.ws.WSAuthorize;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface WebSocketService {
|
public interface WebSocketService {
|
||||||
/**
|
/**
|
||||||
* 处理用户登录请求,需要返回一张带code的二维码
|
* 处理用户登录请求,需要返回一张带code的二维码
|
||||||
@@ -66,7 +68,9 @@ public interface WebSocketService {
|
|||||||
*/
|
*/
|
||||||
void sendToAllOnline(WSBaseResp<?> wsBaseResp);
|
void sendToAllOnline(WSBaseResp<?> wsBaseResp);
|
||||||
|
|
||||||
void sendToFriend(WSBaseResp<?> wsBaseResp, Long friendUid);
|
void sendToUid(WSBaseResp<?> wsBaseResp, Long uid);
|
||||||
|
|
||||||
|
void sendToUidList(WSBaseResp<?> wsBaseResp, List<Long> uidList);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class FriendAdapter {
|
|||||||
FriendApplyResp friendApplyResp = new FriendApplyResp();
|
FriendApplyResp friendApplyResp = new FriendApplyResp();
|
||||||
friendApplyResp.setUid(userApply.getUid());
|
friendApplyResp.setUid(userApply.getUid());
|
||||||
friendApplyResp.setType(userApply.getType());
|
friendApplyResp.setType(userApply.getType());
|
||||||
|
friendApplyResp.setApplyId(userApply.getId());
|
||||||
friendApplyResp.setMsg(userApply.getMsg());
|
friendApplyResp.setMsg(userApply.getMsg());
|
||||||
friendApplyResp.setStatus(userApply.getStatus());
|
friendApplyResp.setStatus(userApply.getStatus());
|
||||||
return friendApplyResp;
|
return friendApplyResp;
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package com.abin.mallchat.custom.user.service.adapter;
|
|||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import com.abin.mallchat.common.chat.domain.dto.ChatMessageMarkDTO;
|
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.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.entity.User;
|
||||||
import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum;
|
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.ChatMemberStatisticResp;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
|
|
||||||
import com.abin.mallchat.custom.chat.service.ChatService;
|
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 me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -87,7 +87,6 @@ public class WSAdapter {
|
|||||||
private void assembleNum(WSOnlineOfflineNotify onlineOfflineNotify) {
|
private void assembleNum(WSOnlineOfflineNotify onlineOfflineNotify) {
|
||||||
ChatMemberStatisticResp memberStatistic = chatService.getMemberStatistic();
|
ChatMemberStatisticResp memberStatistic = chatService.getMemberStatistic();
|
||||||
onlineOfflineNotify.setOnlineNum(memberStatistic.getOnlineNum());
|
onlineOfflineNotify.setOnlineNum(memberStatistic.getOnlineNum());
|
||||||
onlineOfflineNotify.setTotalNum(memberStatistic.getTotalNum());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ChatMemberResp buildOnlineInfo(User user) {
|
private static ChatMemberResp buildOnlineInfo(User user) {
|
||||||
|
|||||||
@@ -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.User;
|
||||||
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
import com.abin.mallchat.common.user.domain.entity.UserApply;
|
||||||
import com.abin.mallchat.common.user.domain.entity.UserFriend;
|
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.ChatService;
|
||||||
import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter;
|
import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter;
|
||||||
import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter;
|
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.context.ApplicationEventPublisher;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -43,7 +44,7 @@ import java.util.Objects;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
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
|
* @author : limeng
|
||||||
@@ -148,22 +149,22 @@ public class FriendServiceImpl implements FriendService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@RedissonLock(key = "#uid")
|
@RedissonLock(key = "#uid")
|
||||||
public void applyApprove(Long uid, FriendApproveReq request) {
|
public void applyApprove(Long uid, FriendApproveReq request) {
|
||||||
UserApply userApply = userApplyDao.getById(request.getApplyId());
|
UserApply userApply = userApplyDao.getById(request.getApplyId());
|
||||||
AssertUtil.isNotEmpty(userApply, "不存在申请记录");
|
AssertUtil.isNotEmpty(userApply, "不存在申请记录");
|
||||||
AssertUtil.equal(userApply.getTargetId(), uid, "不存在申请记录");
|
AssertUtil.equal(userApply.getTargetId(), uid, "不存在申请记录");
|
||||||
AssertUtil.equal(userApply.getStatus(), AGREE.getCode(), "已同意好友申请");
|
AssertUtil.equal(userApply.getStatus(), WAIT_APPROVAL.getCode(), "已同意好友申请");
|
||||||
//同意申请
|
//同意申请
|
||||||
userApplyDao.agree(request.getApplyId());
|
userApplyDao.agree(request.getApplyId());
|
||||||
//创建双方好友关系
|
//创建双方好友关系
|
||||||
createFriend(uid, userApply.getUid());
|
createFriend(uid, userApply.getUid());
|
||||||
//创建一个聊天房间
|
//创建一个聊天房间
|
||||||
RoomFriend roomFriend = roomService.createFriendRoom(Arrays.asList(uid, userApply.getUid()));
|
RoomFriend roomFriend = roomService.createFriendRoom(Arrays.asList(uid, userApply.getUid()));
|
||||||
//创建双方的会话
|
// //创建双方的会话
|
||||||
contactService.createContact(uid, roomFriend.getRoomId());
|
// contactService.createContact(uid, roomFriend.getRoomId());
|
||||||
contactService.createContact(userApply.getUid(), roomFriend.getRoomId());
|
// contactService.createContact(userApply.getUid(), roomFriend.getRoomId());
|
||||||
//发送一条同意消息。。我们已经是好友了,开始聊天吧
|
//发送一条同意消息。。我们已经是好友了,开始聊天吧
|
||||||
chatService.sendMsg(MessageAdapter.buildAgreeMsg(roomFriend.getRoomId()), uid);
|
chatService.sendMsg(MessageAdapter.buildAgreeMsg(roomFriend.getRoomId()), uid);
|
||||||
}
|
}
|
||||||
@@ -188,6 +189,9 @@ public class FriendServiceImpl implements FriendService {
|
|||||||
@Override
|
@Override
|
||||||
public CursorPageBaseResp<ChatMemberResp> friendList(Long uid, CursorPageBaseReq request) {
|
public CursorPageBaseResp<ChatMemberResp> friendList(Long uid, CursorPageBaseReq request) {
|
||||||
CursorPageBaseResp<UserFriend> friendPage = userFriendDao.getFriendPage(uid, request);
|
CursorPageBaseResp<UserFriend> friendPage = userFriendDao.getFriendPage(uid, request);
|
||||||
|
if (CollectionUtils.isEmpty(friendPage.getList())) {
|
||||||
|
return CursorPageBaseResp.empty();
|
||||||
|
}
|
||||||
List<Long> friendUids = friendPage.getList()
|
List<Long> friendUids = friendPage.getList()
|
||||||
.stream().map(UserFriend::getFriendUid)
|
.stream().map(UserFriend::getFriendUid)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user