fix: 进群、移出群成员更新在线人员总数,优化负载均衡
This commit is contained in:
@@ -18,9 +18,6 @@ services:
|
||||
mysql:
|
||||
container_name: mysql
|
||||
restart: always
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./mysql/Dockerfile
|
||||
image: mysql:8.0.30
|
||||
env_file:
|
||||
- ./env/mysql.env
|
||||
|
||||
@@ -13,14 +13,19 @@ public class GroupMemberAddEvent extends ApplicationEvent {
|
||||
// 变动的成员
|
||||
private final List<Long> memberList;
|
||||
private final Long roomId;
|
||||
|
||||
// 群里有多少人
|
||||
private final Integer totalNum;
|
||||
// 在线有多少人
|
||||
private final Integer onlineNum;
|
||||
// 消息接收人
|
||||
private final Long uid;
|
||||
|
||||
public GroupMemberAddEvent(Object source, Long roomId, List<Long> memberList, Long uid) {
|
||||
public GroupMemberAddEvent(Object source, Long roomId, Integer totalNum, Integer onlineNum, List<Long> memberList, Long uid) {
|
||||
super(source);
|
||||
this.memberList = memberList;
|
||||
this.roomId = roomId;
|
||||
this.totalNum = totalNum;
|
||||
this.onlineNum = onlineNum;
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.luohuo.flex.im.common.event.listener;
|
||||
|
||||
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||
import com.luohuo.flex.im.api.PresenceApi;
|
||||
import com.luohuo.flex.im.common.event.GroupMemberAddEvent;
|
||||
import com.luohuo.flex.im.core.chat.dao.GroupMemberDao;
|
||||
@@ -33,6 +34,7 @@ import static com.luohuo.flex.im.common.config.ThreadPoolConfig.LUOHUO_EXECUTOR;
|
||||
@AllArgsConstructor
|
||||
public class GroupMemberAddListener {
|
||||
|
||||
private CachePlusOps cachePlusOps;
|
||||
private ChatService chatService;
|
||||
private UserInfoCache userInfoCache;
|
||||
private GroupMemberDao groupMemberDao;
|
||||
@@ -69,7 +71,7 @@ public class GroupMemberAddListener {
|
||||
Map<Long, User> map = userInfoCache.getBatch(event.getMemberList());
|
||||
|
||||
List<ChatMember> memberResps = groupMemberDao.getMemberListByUid(event.getMemberList());
|
||||
pushService.sendPushMsg(MemberAdapter.buildMemberAddWS(roomId, onlineUids, memberResps, map), memberUidList, event.getUid());
|
||||
pushService.sendPushMsg(MemberAdapter.buildMemberAddWS(roomId, event.getTotalNum(), onlineUids, memberResps, map), memberUidList, event.getUid());
|
||||
|
||||
// 移除缓存
|
||||
groupMemberCache.evictMemberList(roomId);
|
||||
|
||||
@@ -6,10 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||
import com.luohuo.basic.tenant.core.aop.TenantIgnore;
|
||||
import com.luohuo.flex.im.core.chat.cache.UserContactCacheKeyBuilder;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.luohuo.flex.im.domain.vo.req.CursorPageBaseReq;
|
||||
@@ -34,9 +31,6 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
public class ContactDao extends ServiceImpl<ContactMapper, Contact> {
|
||||
|
||||
@Resource
|
||||
private CachePlusOps cachePlusOps;
|
||||
|
||||
public Contact get(Long uid, Long roomId) {
|
||||
return lambdaQuery()
|
||||
.eq(Contact::getUid, uid)
|
||||
@@ -93,14 +87,6 @@ public class ContactDao extends ServiceImpl<ContactMapper, Contact> {
|
||||
return CursorUtils.getCursorPageByMysql(this, request, wrapper -> wrapper.eq(Contact::getUid, uid).eq(Contact::getHide, false), Contact::getActiveTime);
|
||||
}
|
||||
|
||||
public List<Contact> getByRoomIds(List<Long> roomIds, Long uid) {
|
||||
return lambdaQuery()
|
||||
.in(Contact::getRoomId, roomIds)
|
||||
.eq(Contact::getHide, false)
|
||||
.eq(Contact::getUid, uid)
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新所有人的会话时间,没有就直接插入
|
||||
*/
|
||||
@@ -110,6 +96,10 @@ public class ContactDao extends ServiceImpl<ContactMapper, Contact> {
|
||||
baseMapper.refreshOrCreateActiveTime(roomId, memberUidList, msgId, activeTime);
|
||||
}
|
||||
|
||||
public void refreshOrCreate(Long roomId, Long uid) {
|
||||
baseMapper.refreshOrCreate(roomId, uid);
|
||||
}
|
||||
|
||||
public HashMap<String, Contact> getContactMapByUid(Long uid) {
|
||||
// 1. 查出用户要展示的会话列表
|
||||
List<Contact> contacts = getAllContactsByUid(uid);
|
||||
|
||||
@@ -20,4 +20,5 @@ public interface ContactMapper extends BaseMapper<Contact> {
|
||||
|
||||
void refreshOrCreateActiveTime(@Param("roomId") Long roomId, @Param("memberUidList") List<Long> memberUidList, @Param("msgId") Long msgId, @Param("activeTime") LocalDateTime activeTime);
|
||||
|
||||
void refreshOrCreate(@Param("roomId") Long roomId, @Param("uid") Long uid);
|
||||
}
|
||||
|
||||
@@ -78,4 +78,11 @@ public interface ChatService {
|
||||
void msgRead(Long uid, ChatMessageMemberReq request);
|
||||
|
||||
List<Message> getMsgByIds(List<Long> messageIds);
|
||||
|
||||
/**
|
||||
* 创建用户与房间的会话
|
||||
* @param uid 需要创建会话的uid
|
||||
* @param roomId 创建的房间
|
||||
*/
|
||||
void createContact(Long uid, Long roomId);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public interface ContactService {
|
||||
/**
|
||||
* 创建会话
|
||||
*/
|
||||
Contact createContact(Long uid, Long roomId);
|
||||
void createContact(Long uid, Long roomId);
|
||||
|
||||
Integer getMsgReadCount(Message message);
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.luohuo.flex.im.domain.vo.response.ChatRoomResp;
|
||||
import com.luohuo.flex.im.domain.vo.response.MemberResp;
|
||||
import com.luohuo.flex.im.domain.vo.req.MergeMessageReq;
|
||||
import com.luohuo.flex.model.entity.ws.ChatMemberResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -184,4 +183,12 @@ public interface RoomAppService {
|
||||
* 移除管理员
|
||||
*/
|
||||
void revokeAdmin(Long uid, @Valid AdminRevokeReq request);
|
||||
|
||||
/**
|
||||
* 创建系统好友
|
||||
* @param defRoomId 房间id
|
||||
* @param defGroupId 群聊id
|
||||
* @param id 当前人员id
|
||||
*/
|
||||
void createSystemFriend(Long defRoomId, Long defGroupId, Long id);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.luohuo.flex.im.core.chat.service.adapter;
|
||||
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.luohuo.flex.im.domain.entity.Contact;
|
||||
import com.luohuo.flex.im.domain.entity.Room;
|
||||
import com.luohuo.flex.im.domain.entity.RoomFriend;
|
||||
import com.luohuo.flex.im.domain.entity.RoomGroup;
|
||||
@@ -34,6 +32,7 @@ public class ChatAdapter {
|
||||
Room room = new Room();
|
||||
room.setType(typeEnum.getType());
|
||||
room.setHotFlag(HotFlagEnum.NOT.getType());
|
||||
room.setCreateBy(1L);
|
||||
return room;
|
||||
}
|
||||
|
||||
@@ -46,16 +45,10 @@ public class ChatAdapter {
|
||||
roomFriend.setRoomKey(generateRoomKey(uidList));
|
||||
roomFriend.setDeFriend1(false);
|
||||
roomFriend.setDeFriend2(false);
|
||||
roomFriend.setCreateBy(1L);
|
||||
return roomFriend;
|
||||
}
|
||||
|
||||
public static Contact buildContact(Long uid, Long roomId) {
|
||||
Contact contact = new Contact();
|
||||
contact.setRoomId(roomId);
|
||||
contact.setUid(uid);
|
||||
return contact;
|
||||
}
|
||||
|
||||
public static Set<Long> getFriendUidSet(Collection<RoomFriend> values, Long uid) {
|
||||
return values.stream()
|
||||
.map(a -> getFriendUid(a, uid))
|
||||
|
||||
@@ -88,7 +88,7 @@ public class MemberAdapter {
|
||||
* @param map 用户的基础信息
|
||||
* @return
|
||||
*/
|
||||
public static WsBaseResp<WSMemberChange> buildMemberAddWS(Long roomId, List<Long> onlineUids, List<ChatMember> memberResps, Map<Long, User> map) {
|
||||
public static WsBaseResp<WSMemberChange> buildMemberAddWS(Long roomId, Integer totalNum, List<Long> onlineUids, List<ChatMember> memberResps, Map<Long, User> map) {
|
||||
WsBaseResp<WSMemberChange> wsBaseResp = new WsBaseResp<>();
|
||||
wsBaseResp.setType(WSRespTypeEnum.memberChange.getType());
|
||||
WSMemberChange wsMemberChange = new WSMemberChange();
|
||||
@@ -107,14 +107,16 @@ public class MemberAdapter {
|
||||
}
|
||||
});
|
||||
|
||||
wsMemberChange.setTotalNum(totalNum);
|
||||
wsMemberChange.setChangeType(CHANGE_TYPE_ADD);
|
||||
wsMemberChange.setUserList(memberResps);
|
||||
wsMemberChange.setOnlineNum(memberResps.size());
|
||||
wsMemberChange.setRoomId(roomId+"");
|
||||
wsBaseResp.setData(wsMemberChange);
|
||||
return wsBaseResp;
|
||||
}
|
||||
|
||||
public static WsBaseResp<WSMemberChange> buildMemberRemoveWS(Long roomId, List<Long> uidList, Integer type) {
|
||||
public static WsBaseResp<WSMemberChange> buildMemberRemoveWS(Long roomId, Integer totalNun, List<Long> uidList, Integer type) {
|
||||
WsBaseResp<WSMemberChange> wsBaseResp = new WsBaseResp<>();
|
||||
wsBaseResp.setType(WSRespTypeEnum.memberChange.getType());
|
||||
WSMemberChange wsMemberChange = new WSMemberChange();
|
||||
@@ -125,6 +127,7 @@ public class MemberAdapter {
|
||||
return chatMember;
|
||||
}).collect(Collectors.toList());
|
||||
wsMemberChange.setUserList(states);
|
||||
wsMemberChange.setTotalNum(totalNun);
|
||||
wsMemberChange.setRoomId(roomId+"");
|
||||
wsMemberChange.setChangeType(type);
|
||||
wsBaseResp.setData(wsMemberChange);
|
||||
|
||||
@@ -94,10 +94,10 @@ public class RoomAdapter {
|
||||
/**
|
||||
* 群聊被群主解散
|
||||
*/
|
||||
public static WsBaseResp<String> buildGroupDissolution(String name) {
|
||||
public static WsBaseResp<String> buildGroupDissolution(Long roomId) {
|
||||
WsBaseResp<String> WsBaseResp = new WsBaseResp<>();
|
||||
WsBaseResp.setType(WSRespTypeEnum.ROOM_DISSOLUTION.getType());
|
||||
WsBaseResp.setData(StrUtil.format("{}已解散", name));
|
||||
WsBaseResp.setData(roomId+"");
|
||||
return WsBaseResp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,6 +404,11 @@ public class ChatServiceImpl implements ChatService {
|
||||
return messageDao.listByIds(msgIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createContact(Long uid, Long roomId) {
|
||||
contactService.createContact(uid, roomId);
|
||||
}
|
||||
|
||||
private void checkRecall(Long uid, Message message) {
|
||||
AssertUtil.isNotEmpty(message, "消息有误");
|
||||
AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL.getType(), "消息无法撤回");
|
||||
|
||||
@@ -5,15 +5,11 @@ import org.springframework.stereotype.Service;
|
||||
import com.luohuo.basic.validator.utils.AssertUtil;
|
||||
import com.luohuo.flex.im.core.chat.dao.ContactDao;
|
||||
import com.luohuo.flex.im.domain.dto.MsgReadInfoDTO;
|
||||
import com.luohuo.flex.im.domain.entity.Contact;
|
||||
import com.luohuo.flex.im.domain.entity.Message;
|
||||
import com.luohuo.flex.im.core.chat.service.ContactService;
|
||||
import com.luohuo.flex.im.core.chat.service.adapter.ChatAdapter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -25,15 +21,8 @@ public class ContactServiceImpl implements ContactService {
|
||||
private ContactDao contactDao;
|
||||
|
||||
@Override
|
||||
public Contact createContact(Long uid, Long roomId) {
|
||||
Contact contact = contactDao.get(uid, roomId);
|
||||
if (Objects.isNull(contact)) {
|
||||
contact = ChatAdapter.buildContact(uid, roomId);
|
||||
contact.setCreateBy(uid);
|
||||
contact.setCreateTime(LocalDateTime.now());
|
||||
contactDao.save(contact);
|
||||
}
|
||||
return contact;
|
||||
public void createContact(Long uid, Long roomId) {
|
||||
contactDao.refreshOrCreate(roomId, uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,9 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||
import com.luohuo.basic.exception.code.ResponseEnum;
|
||||
import com.luohuo.basic.model.cache.CacheKey;
|
||||
@@ -356,6 +358,21 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
groupMemberDao.revokeAdmin(roomGroup.getId(), request.getUidList());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param roomId 房间id
|
||||
* @param groupId 群聊id
|
||||
* @param uid 当前人员id
|
||||
*/
|
||||
@Override
|
||||
public void createSystemFriend(Long roomId, Long groupId, Long uid) {
|
||||
// 创建会话
|
||||
chatService.createContact(uid, roomId);
|
||||
// 创建群成员
|
||||
roomService.createGroupMember(groupId, uid);
|
||||
// 创建系统消息
|
||||
friendService.createSystemFriend(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询加群申请记录
|
||||
* @param uid 登录用户id
|
||||
@@ -392,7 +409,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
* @param roomId 在某个房间处理
|
||||
* @return
|
||||
*/
|
||||
@Async(LUOHUO_EXECUTOR)
|
||||
// @Async(LUOHUO_EXECUTOR)
|
||||
public void asyncOnline(List<Long> uidList, Long roomId, boolean online) {
|
||||
Set<Long> onlineList = presenceApi.getOnlineUsersList(uidList).getData();
|
||||
if(CollUtil.isEmpty(onlineList)){
|
||||
@@ -471,10 +488,11 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
|
||||
// 2.修改我的信息
|
||||
boolean equals = member.getMyName().equals(StrUtil.isEmpty(request.getMyName())? "": request.getMyName());
|
||||
boolean success = groupMemberDao.update(null, Wrappers.<GroupMember>lambdaUpdate()
|
||||
.set(GroupMember::getRemark, request.getRemark())
|
||||
.set(GroupMember::getMyName, request.getMyName())
|
||||
.eq(GroupMember::getId, member.getId()));
|
||||
|
||||
member.setRemark(request.getRemark());
|
||||
member.setMyName(request.getMyName());
|
||||
boolean success = groupMemberDao.updateById(member);
|
||||
groupMemberCache.evictMemberDetail(roomGroup.getRoomId(), uid);
|
||||
|
||||
// 3.通知群里所有人我的信息改变了
|
||||
@@ -816,8 +834,8 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
|
||||
// 如果房间人员小于3人 那么直接解散群聊
|
||||
CacheKey membersKey = PresenceCacheKeyBuilder.groupMembersKey(request.getRoomId());
|
||||
Long count = cachePlusOps.sCard(membersKey);
|
||||
if(count < 3 && self.getRoleId().equals(GroupRoleEnum.LEADER.getType())) {
|
||||
Long memberNum = cachePlusOps.sCard(membersKey);
|
||||
if(memberNum <= 3 && self.getRoleId().equals(GroupRoleEnum.LEADER.getType())) {
|
||||
MemberExitReq exitReq = new MemberExitReq();
|
||||
exitReq.setRoomId(request.getRoomId());
|
||||
exitReq.setAccount(roomGroup.getAccount());
|
||||
@@ -846,21 +864,22 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
contactDao.removeByRoomId(room.getId(), Collections.singletonList(request.getUid()));
|
||||
return true;
|
||||
})){
|
||||
List<Long> memberUidList = groupMemberCache.getMemberExceptUidList(roomGroup.getRoomId());
|
||||
if(!memberUidList.contains(request.getUid())){
|
||||
memberUidList.add(request.getUid());
|
||||
}
|
||||
WsBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), Arrays.asList(member.getUid()), WSMemberChange.CHANGE_TYPE_REMOVE);
|
||||
pushService.sendPushMsg(ws, memberUidList, uid);
|
||||
groupMemberCache.evictMemberList(room.getId());
|
||||
groupMemberCache.evictExceptMemberList(room.getId());
|
||||
groupMemberCache.evictMemberDetail(room.getId(), removedUid);
|
||||
|
||||
// 移除群聊缓存
|
||||
CacheKey uKey = PresenceCacheKeyBuilder.userGroupsKey(request.getUid());
|
||||
cachePlusOps.sRem(membersKey, request.getUid());
|
||||
cachePlusOps.sRem(uKey, room.getId());
|
||||
asyncOnline(Arrays.asList(request.getUid()), room.getId(), false);
|
||||
|
||||
// 推送状态到前端
|
||||
List<Long> memberUidList = groupMemberCache.getMemberExceptUidList(roomGroup.getRoomId());
|
||||
if(!memberUidList.contains(request.getUid())){
|
||||
memberUidList.add(request.getUid());
|
||||
}
|
||||
WsBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), (int) (memberNum - 1), Arrays.asList(member.getUid()), WSMemberChange.CHANGE_TYPE_REMOVE);
|
||||
pushService.sendPushMsg(ws, memberUidList, uid);
|
||||
groupMemberCache.evictMemberList(room.getId());
|
||||
groupMemberCache.evictExceptMemberList(room.getId());
|
||||
groupMemberCache.evictMemberDetail(room.getId(), removedUid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,7 +983,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
CacheKey gKey = PresenceCacheKeyBuilder.groupMembersKey(room.getId());
|
||||
cachePlusOps.del(uKey, gKey);
|
||||
asyncOnline(memberUidList, room.getId(), false);
|
||||
pushService.sendPushMsg(RoomAdapter.buildGroupDissolution(roomGroup.getName()), memberUidList, uid);
|
||||
pushService.sendPushMsg(RoomAdapter.buildGroupDissolution(roomGroup.getRoomId()), memberUidList, uid);
|
||||
} else {
|
||||
if(transactionTemplate.execute(e -> {
|
||||
// 4.6 删除会话
|
||||
@@ -975,19 +994,19 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
AssertUtil.isTrue(isDelGroupMember, "群成员移除失败");
|
||||
return true;
|
||||
})){
|
||||
// 4.8 发送移除事件告知群成员
|
||||
WsBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), Arrays.asList(uid), WSMemberChange.CHANGE_TYPE_QUIT);
|
||||
pushService.sendPushMsg(ws, memberUidList, uid);
|
||||
groupMemberCache.evictMemberList(room.getId());
|
||||
groupMemberCache.evictExceptMemberList(room.getId());
|
||||
groupMemberCache.evictMemberDetail(room.getId(), uid);
|
||||
|
||||
// 新版退出群聊
|
||||
CacheKey uKey = PresenceCacheKeyBuilder.userGroupsKey(uid);
|
||||
CacheKey gKey = PresenceCacheKeyBuilder.groupMembersKey(room.getId());
|
||||
cachePlusOps.sRem(gKey, uid);
|
||||
cachePlusOps.sRem(uKey, room.getId());
|
||||
asyncOnline(Arrays.asList(uid), room.getId(), false);
|
||||
|
||||
// 4.8 发送移除事件告知群成员
|
||||
WsBaseResp<WSMemberChange> ws = MemberAdapter.buildMemberRemoveWS(roomGroup.getRoomId(), Math.toIntExact(cachePlusOps.sCard(gKey)), Arrays.asList(uid), WSMemberChange.CHANGE_TYPE_QUIT);
|
||||
pushService.sendPushMsg(ws, memberUidList, uid);
|
||||
groupMemberCache.evictMemberList(room.getId());
|
||||
groupMemberCache.evictExceptMemberList(room.getId());
|
||||
groupMemberCache.evictMemberDetail(room.getId(), uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1018,13 +1037,14 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
groupMemberCache.evictExceptMemberList(roomIdAtomic.get());
|
||||
|
||||
// 更新在线缓存
|
||||
CacheKey onlineGroupMembersKey = PresenceCacheKeyBuilder.onlineGroupMembersKey(roomIdAtomic.get());
|
||||
CacheKey gKey = PresenceCacheKeyBuilder.groupMembersKey(roomIdAtomic.get());
|
||||
uidList.forEach(id -> {
|
||||
cachePlusOps.sAdd(gKey, id);
|
||||
cachePlusOps.sAdd(PresenceCacheKeyBuilder.userGroupsKey(id), roomIdAtomic.get());
|
||||
});
|
||||
SpringUtils.publishEvent(new GroupMemberAddEvent(this, roomIdAtomic.get(), request.getUidList(), uid));
|
||||
asyncOnline(uidList, roomIdAtomic.get(), true);
|
||||
SpringUtils.publishEvent(new GroupMemberAddEvent(this, roomIdAtomic.get(), Math.toIntExact(cachePlusOps.sCard(gKey)), Math.toIntExact(cachePlusOps.sCard(onlineGroupMembersKey)), request.getUidList(), uid));
|
||||
}
|
||||
return roomIdAtomic.get();
|
||||
}
|
||||
@@ -1190,13 +1210,10 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
||||
if (ObjectUtil.isNotNull(member)) {
|
||||
roomBaseInfo.setMyName(member.getMyName());
|
||||
roomBaseInfo.setRemark(member.getRemark());
|
||||
if(StrUtil.isNotEmpty(member.getRemark())){
|
||||
roomBaseInfo.setName(member.getRemark());
|
||||
} else {
|
||||
roomBaseInfo.setName(roomGroup.getName());
|
||||
}
|
||||
roomBaseInfo.setName(roomGroup.getName());
|
||||
roomBaseInfo.setRoleId(member.getRoleId());
|
||||
}else {
|
||||
roomBaseInfo.setName("会话异常");
|
||||
roomBaseInfo.setMyName("会话异常");
|
||||
roomBaseInfo.setRemark("会话异常");
|
||||
roomBaseInfo.setRoleId(0);
|
||||
|
||||
@@ -90,7 +90,7 @@ public class RoomServiceImpl implements RoomService {
|
||||
Room room = createRoom(RoomTypeEnum.GROUP);
|
||||
// 插入群
|
||||
RoomGroup roomGroup = ChatAdapter.buildGroupRoom(user, room.getId(), groupAddReq.getGroupName());
|
||||
roomGroup.setAccount(Base62Encoder.createAccount(uidGenerator.getUid()));
|
||||
roomGroup.setAccount(Base62Encoder.createGroup(uidGenerator.getUid()));
|
||||
roomGroupDao.save(roomGroup);
|
||||
// 插入群主
|
||||
GroupMember leader = GroupMember.builder()
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.luohuo.flex.im.core.frequencyControl.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -10,7 +9,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author nyh
|
||||
*/
|
||||
@Data
|
||||
public class FrequencyControlDTO extends BaseEntity {
|
||||
public class FrequencyControlDTO implements Serializable {
|
||||
/**
|
||||
* 代表频控的Key 如果target为Key的话 这里要传值用于构建redis的Key target为Ip或者UID的话会从上下文取值 Key字段无需传值
|
||||
*/
|
||||
|
||||
@@ -56,7 +56,6 @@ import com.luohuo.flex.model.redis.annotation.RedissonLock;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -233,10 +232,8 @@ public class ApplyServiceImpl implements ApplyService {
|
||||
transactionTemplate.execute(e -> {
|
||||
groupMemberDao.save(MemberAdapter.buildMemberAdd(roomGroup.getId(), invite.getTargetId()));
|
||||
|
||||
// 3.2 系统下发加群信息
|
||||
if(room.isHotRoom()){
|
||||
friendService.createSystemFriend(request.getApplyId());
|
||||
}
|
||||
// 创建进群后的会话
|
||||
chatService.createContact(uid, roomGroup.getRoomId());
|
||||
|
||||
// 更新邀请状态
|
||||
userApplyDao.updateById(invite);
|
||||
@@ -248,11 +245,12 @@ public class ApplyServiceImpl implements ApplyService {
|
||||
groupMemberCache.evictExceptMemberList(invite.getRoomId());
|
||||
CacheKey uKey = PresenceCacheKeyBuilder.userGroupsKey(invite.getTargetId());
|
||||
CacheKey gKey = PresenceCacheKeyBuilder.groupMembersKey(room.getId());
|
||||
CacheKey onlineGroupMembersKey = PresenceCacheKeyBuilder.onlineGroupMembersKey(room.getId());
|
||||
cachePlusOps.sAdd(uKey, room.getId());
|
||||
cachePlusOps.sAdd(gKey, invite.getTargetId());
|
||||
roomAppService.asyncOnline(Arrays.asList(invite.getTargetId()), room.getId(), true);
|
||||
|
||||
SpringUtils.publishEvent(new GroupMemberAddEvent(this, room.getId(), Arrays.asList(invite.getTargetId()), invite.getUid()));
|
||||
SpringUtils.publishEvent(new GroupMemberAddEvent(this, room.getId(), Math.toIntExact(cachePlusOps.sCard(gKey)), Math.toIntExact(cachePlusOps.sCard(onlineGroupMembersKey)), Arrays.asList(invite.getTargetId()), invite.getUid()));
|
||||
}
|
||||
}
|
||||
case 3 -> {
|
||||
@@ -269,7 +267,6 @@ public class ApplyServiceImpl implements ApplyService {
|
||||
*/
|
||||
@Override
|
||||
@RedissonLock(key = "#request.applyId")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void handleApply(Long uid, GroupApplyHandleReq req) {
|
||||
// 1. 校验申请记录
|
||||
UserApply apply = userApplyDao.getById(req.getApplyId());
|
||||
@@ -292,15 +289,13 @@ public class ApplyServiceImpl implements ApplyService {
|
||||
transactionTemplate.execute(e -> {
|
||||
userApplyDao.updateById(apply);
|
||||
|
||||
// 5. 同意则加群
|
||||
if (req.getStatus().equals(2)) {
|
||||
// 5.1 加入群聊
|
||||
groupMemberDao.save(MemberAdapter.buildMemberAdd(group.getId(), apply.getTargetId()));
|
||||
// 5.0 创建申请人与房间的会话
|
||||
chatService.createContact(uid, apply.getRoomId());
|
||||
|
||||
// 5.2 处理热点群机器人好友
|
||||
if (room.isHotRoom()) {
|
||||
friendService.createSystemFriend(apply.getUid());
|
||||
}
|
||||
// 5.1 同意则加群
|
||||
if (req.getStatus().equals(2)) {
|
||||
// 5.2 加入群聊
|
||||
groupMemberDao.save(MemberAdapter.buildMemberAdd(group.getId(), apply.getTargetId()));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@@ -312,12 +307,13 @@ public class ApplyServiceImpl implements ApplyService {
|
||||
|
||||
CacheKey uKey = PresenceCacheKeyBuilder.userGroupsKey(apply.getUid());
|
||||
CacheKey gKey = PresenceCacheKeyBuilder.groupMembersKey(room.getId());
|
||||
CacheKey onlineGroupMembersKey = PresenceCacheKeyBuilder.onlineGroupMembersKey(room.getId());
|
||||
cachePlusOps.sAdd(uKey, room.getId());
|
||||
cachePlusOps.sAdd(gKey, apply.getUid());
|
||||
roomAppService.asyncOnline(Arrays.asList(apply.getUid()), room.getId(), true);
|
||||
|
||||
// 5.5 发布成员增加事件
|
||||
SpringUtils.publishEvent(new GroupMemberAddEvent(this, room.getId(), Collections.singletonList(apply.getUid()), apply.getUid()));
|
||||
SpringUtils.publishEvent(new GroupMemberAddEvent(this, room.getId(), Math.toIntExact(cachePlusOps.sCard(gKey)), Math.toIntExact(cachePlusOps.sCard(onlineGroupMembersKey)), Collections.singletonList(apply.getUid()), apply.getUid()));
|
||||
}
|
||||
|
||||
// 6. 通知申请人 [这条消息需要覆盖前端]
|
||||
|
||||
@@ -3,10 +3,12 @@ package com.luohuo.flex.im.core.user.service.impl;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.luohuo.basic.cache.redis.BaseRedis;
|
||||
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||
import com.luohuo.basic.model.cache.CacheKey;
|
||||
import com.luohuo.flex.common.cache.FriendCacheKeyBuilder;
|
||||
import com.luohuo.flex.common.cache.PresenceCacheKeyBuilder;
|
||||
import com.luohuo.flex.common.constant.DefValConstants;
|
||||
import com.luohuo.flex.im.api.PresenceApi;
|
||||
import com.luohuo.flex.im.domain.enums.ApplyReadStatusEnum;
|
||||
import com.luohuo.flex.im.domain.enums.ApplyStatusEnum;
|
||||
@@ -44,7 +46,6 @@ import com.luohuo.flex.im.core.user.service.cache.UserCache;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -63,6 +64,7 @@ public class FriendServiceImpl implements FriendService, InitializingBean {
|
||||
private ChatService chatService;
|
||||
private UserDao userDao;
|
||||
private UserCache userCache;
|
||||
private BaseRedis baseRedis;
|
||||
private CachePlusOps cachePlusOps;
|
||||
private PresenceApi presenceApi;
|
||||
|
||||
@@ -96,7 +98,8 @@ public class FriendServiceImpl implements FriendService, InitializingBean {
|
||||
@PostConstruct
|
||||
public void initUserCount() {
|
||||
Long dbCount = userDao.count();
|
||||
cachePlusOps.set(new CacheKey("luohuo:user:total_count"), dbCount);
|
||||
// cachePlusOps.set(new CacheKey("luohuo:user:total_count"), dbCount);
|
||||
baseRedis.set("luohuo:user:total_count", dbCount);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,18 +171,17 @@ public class FriendServiceImpl implements FriendService, InitializingBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void createSystemFriend(Long uid){
|
||||
// 创建一个聊天房间
|
||||
RoomFriend roomFriend = roomService.createFriendRoom(Arrays.asList(uid, 1L));
|
||||
RoomFriend roomFriend = roomService.createFriendRoom(Arrays.asList(uid, DefValConstants.DEF_BOT_ID));
|
||||
// 创建双方好友关系
|
||||
createFriend(roomFriend.getRoomId(), uid, 1L);
|
||||
createFriend(roomFriend.getRoomId(), uid, DefValConstants.DEF_BOT_ID);
|
||||
// 发送一条同意消息。。我们已经是好友了,开始聊天吧
|
||||
chatService.sendMsg(MessageAdapter.buildAgreeMsg(roomFriend.getRoomId(), true), uid);
|
||||
// 系统账号在群内发送一条欢迎消息
|
||||
User user = userCache.getUserInfo(uid);
|
||||
Long total = cachePlusOps.inc("luohuo:user:total_count", 0, TimeUnit.DAYS); // 查询系统总注册人员
|
||||
chatService.sendMsg(MessageAdapter.buildAgreeMsg4Group(1L, total, user.getName()), 1L);
|
||||
chatService.sendMsg(MessageAdapter.buildAgreeMsg4Group(DefValConstants.DEF_ROOM_ID, total, user.getName()), DefValConstants.DEF_BOT_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,6 +229,10 @@ public class FriendServiceImpl implements FriendService, InitializingBean {
|
||||
userFriend2.setRoomId(roomId);
|
||||
userFriendDao.saveBatch(Lists.newArrayList(userFriend1, userFriend2));
|
||||
updateFriendCache(uid, targetUid);
|
||||
|
||||
// 创建好友会话
|
||||
chatService.createContact(uid, roomId);
|
||||
chatService.createContact(targetUid, roomId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.luohuo.flex.common.constant.DefValConstants;
|
||||
import com.luohuo.flex.im.api.vo.UserRegisterVo;
|
||||
import com.luohuo.flex.im.common.event.UserRegisterEvent;
|
||||
import com.luohuo.flex.im.core.chat.service.ContactService;
|
||||
import com.luohuo.flex.im.core.chat.service.RoomAppService;
|
||||
import com.luohuo.flex.im.core.chat.service.RoomService;
|
||||
import com.luohuo.flex.im.core.user.service.cache.DefUserCache;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -72,6 +73,7 @@ public class UserServiceImpl implements UserService {
|
||||
public static final LocalDateTime MAX_DATE = LocalDateTime.of(2099, 12, 31, 00, 00, 00);
|
||||
private final ContactService contactService;
|
||||
private final RoomService roomService;
|
||||
private final RoomAppService roomAppService;
|
||||
private UserCache userCache;
|
||||
private DefUserCache defUserCache;
|
||||
private UserBackpackDao userBackpackDao;
|
||||
@@ -312,6 +314,7 @@ public class UserServiceImpl implements UserService {
|
||||
@Transactional
|
||||
public Boolean register(UserRegisterVo userRegisterVo) {
|
||||
// 1. 检查邮箱是否已被其他用户绑定
|
||||
ContextUtil.setUid(DefValConstants.DEF_BOT_ID);
|
||||
ContextUtil.setTenantId(userRegisterVo.getTenantId());
|
||||
if (userDao.existsByEmailAndIdNot(null, userRegisterVo.getEmail())) {
|
||||
return false;
|
||||
@@ -336,10 +339,8 @@ public class UserServiceImpl implements UserService {
|
||||
// 保存用户
|
||||
newUser.setCreateBy(1L);
|
||||
userDao.save(newUser);
|
||||
// 创建会话
|
||||
contactService.createContact(newUser.getId(), DefValConstants.DEF_ROOM_ID);
|
||||
// 创建群成员
|
||||
roomService.createGroupMember(DefValConstants.DEF_GROUP_ID, newUser.getId());
|
||||
// 加上系统机器人好友
|
||||
roomAppService.createSystemFriend(DefValConstants.DEF_ROOM_ID, DefValConstants.DEF_GROUP_ID, newUser.getId());
|
||||
|
||||
// 注入群组信息
|
||||
cachePlusOps.sAdd(PresenceCacheKeyBuilder.groupMembersKey(DefValConstants.DEF_ROOM_ID), newUser.getId());
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
is_del = 0,
|
||||
hide = 0,
|
||||
last_msg_id = VALUES(last_msg_id),
|
||||
active_time = VALUES(active_time);
|
||||
active_time = VALUES(active_time)
|
||||
</insert>
|
||||
|
||||
<insert id="refreshOrCreate">
|
||||
INSERT INTO im_contact (room_id, uid, is_del) VALUES (#{roomId},#{uid},0)
|
||||
ON DUPLICATE KEY UPDATE is_del = 0, hide = 0
|
||||
</insert>
|
||||
</mapper>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.luohuo.flex.im.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RoomChatInfoPO {
|
||||
private Long roomId;
|
||||
private Long uid;
|
||||
private Long friendId;
|
||||
}
|
||||
@@ -9,7 +9,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -20,7 +21,7 @@ import com.luohuo.basic.base.entity.BaseEntity;
|
||||
@Schema(description = "游标翻页请求")
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class CursorPageBaseReq extends BaseEntity {
|
||||
public class CursorPageBaseReq implements Serializable {
|
||||
|
||||
@Schema(description = "页面大小")
|
||||
@Min(0)
|
||||
|
||||
@@ -6,7 +6,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author nyh
|
||||
@@ -14,7 +14,7 @@ import com.luohuo.basic.base.entity.BaseEntity;
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IdReqVO extends BaseEntity {
|
||||
public class IdReqVO implements Serializable {
|
||||
@Schema(description = "id")
|
||||
@NotNull
|
||||
private long id;
|
||||
|
||||
@@ -5,7 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import lombok.Data;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@ import com.luohuo.basic.base.entity.BaseEntity;
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "基础翻页请求")
|
||||
public class PageBaseReq extends BaseEntity {
|
||||
public class PageBaseReq implements Serializable {
|
||||
|
||||
@Schema(description = "页面大小")
|
||||
@Min(0)
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.config;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 配置查询参数
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class ConfigParam implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotBlank(message = "参数名称不能为空")
|
||||
@Size(max = 100, message = "参数名称不能超过100个字符")
|
||||
private String configName;
|
||||
|
||||
private String type;
|
||||
|
||||
@NotBlank(message = "参数键名长度不能为空")
|
||||
@Size(max = 100, message = "参数键名长度不能超过100个字符")
|
||||
private String configKey;
|
||||
|
||||
@NotBlank(message = "参数键值不能为空")
|
||||
@Size(max = 500, message = "参数键值长度不能超过500个字符")
|
||||
private String configValue;
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -18,7 +18,7 @@ import com.luohuo.basic.base.entity.BaseEntity;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class FriendApplyReq extends BaseEntity {
|
||||
public class FriendApplyReq implements Serializable {
|
||||
|
||||
@NotBlank
|
||||
@Schema(description ="申请信息")
|
||||
|
||||
@@ -7,8 +7,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -20,7 +19,7 @@ import java.util.List;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class FriendCheckReq extends BaseEntity {
|
||||
public class FriendCheckReq implements Serializable {
|
||||
|
||||
@NotEmpty
|
||||
@Size(max = 50)
|
||||
|
||||
@@ -6,7 +6,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -17,7 +17,7 @@ import com.luohuo.basic.base.entity.BaseEntity;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class FriendDeleteReq extends BaseEntity {
|
||||
public class FriendDeleteReq implements Serializable {
|
||||
|
||||
@NotNull
|
||||
@Schema(description ="好友uid")
|
||||
|
||||
@@ -7,8 +7,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 上传url请求入参
|
||||
@@ -18,7 +18,7 @@ import com.luohuo.basic.base.entity.BaseEntity;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UploadUrlReq extends BaseEntity {
|
||||
public class UploadUrlReq implements Serializable {
|
||||
@Schema(description = "文件名(带后缀)")
|
||||
@NotBlank
|
||||
private String fileName;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.room;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PendingInviteResp implements Serializable {
|
||||
@Schema(description ="邀请人id")
|
||||
private Long inviteId;
|
||||
@Schema(description ="群id")
|
||||
private Long groupId;
|
||||
@Schema(description ="被邀请人id")
|
||||
private Long inviterUid;
|
||||
@Schema(description ="邀请时间")
|
||||
private LocalDateTime inviteTime;
|
||||
}
|
||||
@@ -3,13 +3,13 @@ package com.luohuo.flex.im.domain.vo.req.user;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author nyh
|
||||
*/
|
||||
@Data
|
||||
public class BlackReq extends BaseEntity {
|
||||
public class BlackReq implements Serializable {
|
||||
|
||||
@NotNull(message = "请选择拉黑用户")
|
||||
@Schema(description = "拉黑用户的uid")
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author 乾乾
|
||||
*/
|
||||
@Data
|
||||
public class ForgotPasswordReq implements Serializable {
|
||||
|
||||
@NotEmpty(message = "请填写邮箱")
|
||||
@Schema(description = "邮箱")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$", message = "请输入有效的邮箱地址")
|
||||
private String email;
|
||||
|
||||
@NotEmpty(message = "邮箱验证码不能为空")
|
||||
@Schema(description = "邮箱验证码")
|
||||
private String code;
|
||||
|
||||
@NotEmpty(message = "修改码非法!")
|
||||
@Schema(description = "uuid")
|
||||
private String uuid;
|
||||
|
||||
@NotEmpty(message = "请输入密码")
|
||||
private String password;
|
||||
}
|
||||
@@ -6,11 +6,9 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 批量查询徽章详情
|
||||
* @author nyh
|
||||
@@ -19,7 +17,7 @@ import java.util.List;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ItemInfoReq extends BaseEntity {
|
||||
public class ItemInfoReq implements Serializable {
|
||||
@Schema(description = "徽章信息入参")
|
||||
@Size(max = 50)
|
||||
private List<infoReq> reqList;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* TODO 要删除
|
||||
* @author nyh
|
||||
*/
|
||||
@Data
|
||||
public class LoginReq implements Serializable {
|
||||
|
||||
@NotEmpty(message = "请输入账号")
|
||||
private String account;
|
||||
|
||||
@NotEmpty(message = "请输入密码")
|
||||
private String password;
|
||||
|
||||
@NotEmpty(message = "请选择登录方式")
|
||||
private String source;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author 乾乾
|
||||
*/
|
||||
@Data
|
||||
public class LogoutReq implements Serializable {
|
||||
|
||||
@NotNull(message = "是否自动登录")
|
||||
private Boolean autoLogin;
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -8,6 +7,8 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 修改用户名
|
||||
* @author nyh
|
||||
@@ -16,7 +17,7 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ModifyAvatarReq extends BaseEntity {
|
||||
public class ModifyAvatarReq implements Serializable {
|
||||
|
||||
@NotEmpty
|
||||
@Schema(description = "头像url")
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author 乾乾
|
||||
*/
|
||||
@Data
|
||||
public class RefreshTokenReq extends BaseEntity {
|
||||
public class RefreshTokenReq implements Serializable {
|
||||
|
||||
@NotEmpty(message = "refreshToken不能为空")
|
||||
private String refreshToken;
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* TODO 待删除
|
||||
* @author ZOL
|
||||
*/
|
||||
@Data
|
||||
public class RegisterReq extends BaseEntity {
|
||||
|
||||
@NotEmpty(message = "请输入昵称")
|
||||
private String name;
|
||||
|
||||
@NotNull
|
||||
@Pattern(regexp = "00[1-9]|01[0-9]|021", message = "默认头像只能是001到021之间的字符串")
|
||||
private String avatar;
|
||||
|
||||
@NotEmpty(message = "请填写邮箱")
|
||||
@Schema(description = "邮箱")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$", message = "请输入有效的邮箱地址")
|
||||
private String email;
|
||||
|
||||
@NotEmpty(message = "邮箱验证码不能为空")
|
||||
@Schema(description = "邮箱验证码")
|
||||
private String code;
|
||||
|
||||
@NotEmpty(message = "注册码非法!")
|
||||
@Schema(description = "uuid")
|
||||
private String uuid;
|
||||
|
||||
@NotEmpty(message = "请输入密码")
|
||||
private String password;
|
||||
|
||||
private String openId;
|
||||
|
||||
public RegisterReq() {
|
||||
}
|
||||
|
||||
public RegisterReq(String name, String avatar, String email, String password, String openId) {
|
||||
this.name = name;
|
||||
this.avatar = avatar;
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.openId = openId;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.List;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SummeryInfoReq extends BaseEntity {
|
||||
public class SummeryInfoReq implements Serializable {
|
||||
@Schema(description = "用户信息入参")
|
||||
@Size(max = 50, message = "一次最多查询50个用户数据")
|
||||
private List<infoReq> reqList;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 表情包反参
|
||||
@@ -16,7 +17,7 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserEmojiReq extends BaseEntity {
|
||||
public class UserEmojiReq implements Serializable {
|
||||
/**
|
||||
* 表情地址
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.luohuo.flex.im.domain.vo.req.user;
|
||||
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -8,6 +7,8 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 佩戴徽章
|
||||
* @author nyh
|
||||
@@ -16,7 +17,7 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class WearingBadgeReq extends BaseEntity {
|
||||
public class WearingBadgeReq implements Serializable {
|
||||
|
||||
@NotNull
|
||||
@Schema(description ="徽章id")
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.luohuo.flex.im.domain.vo.resp.friend;
|
||||
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.List;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class FriendCheckResp extends BaseEntity {
|
||||
public class FriendCheckResp implements Serializable {
|
||||
|
||||
@Schema(description ="校验结果")
|
||||
private List<FriendCheck> checkedList;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.luohuo.flex.im.domain.vo.resp.user;
|
||||
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* 徽章信息
|
||||
@@ -11,7 +12,7 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
@Schema(description ="徽章信息")
|
||||
public class BadgeResp extends BaseEntity {
|
||||
public class BadgeResp implements Serializable {
|
||||
|
||||
@Schema(description ="徽章id")
|
||||
private Long id;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.luohuo.flex.im.domain.vo.resp.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 表情包反参
|
||||
* @author nyh
|
||||
@@ -15,7 +16,7 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserEmojiResp extends BaseEntity {
|
||||
public class UserEmojiResp implements Serializable {
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package com.luohuo.flex.im.domain.vo.resp.user;
|
||||
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author nyh
|
||||
*/
|
||||
@Data
|
||||
public class UserInfoResp extends BaseEntity {
|
||||
public class UserInfoResp implements Serializable {
|
||||
|
||||
@Schema(description = "用户id")
|
||||
private Long uid;
|
||||
|
||||
@@ -119,7 +119,7 @@ public class UserInfoServiceImpl implements UserInfoService {
|
||||
if(!imUserApi.register(userRegisterVo).getData()){
|
||||
throw new BizException("该邮箱已被其他账号绑定");
|
||||
}
|
||||
yield defUser.getEmail();
|
||||
yield defUser.getEmail();
|
||||
}
|
||||
case ACCOUNT -> {
|
||||
// 2.1 注册后台管理员、RAM账号
|
||||
|
||||
@@ -11,6 +11,8 @@ import com.luohuo.basic.utils.TreeUtil;
|
||||
public interface DefValConstants {
|
||||
/** 内置的租户 */
|
||||
Long DEF_TENANT_ID = 1L;
|
||||
/** 机器人id */
|
||||
Long DEF_BOT_ID = 1L;
|
||||
/** 内置的房间id */
|
||||
Long DEF_ROOM_ID = 1L;
|
||||
/** 内置的群组id */
|
||||
|
||||
@@ -3,9 +3,8 @@ package com.luohuo.flex.model.entity.dto;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 将扫码登录返回信息推送给所有横向扩展的服务
|
||||
@@ -14,7 +13,7 @@ import java.io.Serial;
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LoginMessageDTO extends BaseEntity {
|
||||
public class LoginMessageDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.luohuo.flex.model.entity.dto;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.luohuo.basic.base.entity.BaseEntity;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 扫码成功对象,推送给用户的消息对象
|
||||
@@ -12,7 +12,7 @@ import com.luohuo.basic.base.entity.BaseEntity;
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ScanSuccessMessageDTO extends BaseEntity {
|
||||
public class ScanSuccessMessageDTO implements Serializable {
|
||||
/**
|
||||
* 推送的code
|
||||
*/
|
||||
|
||||
@@ -26,4 +26,8 @@ public class WSMemberChange implements Serializable {
|
||||
private Integer changeType;
|
||||
@Schema(description ="变动uid集合")
|
||||
private List<ChatMember> userList;
|
||||
@Schema(description ="群内总人数")
|
||||
private Integer totalNum;
|
||||
@Schema(description ="在线总人数")
|
||||
private Integer onlineNum;
|
||||
}
|
||||
|
||||
@@ -5,14 +5,16 @@ import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.luohuo.basic.utils.JsonUtils;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.core.*;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.data.redis.core.script.RedisScript;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import com.luohuo.basic.cache.redis2.CacheResult;
|
||||
@@ -531,6 +533,10 @@ public abstract class BaseRedis {
|
||||
valueOps.set(key, value == null ? newNullVal() : value);
|
||||
}
|
||||
|
||||
public void set(@NonNull String key, Object value) {
|
||||
stringRedisTemplate.opsForValue().set(key, JsonUtils.toStr(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置缓存
|
||||
*
|
||||
@@ -817,6 +823,20 @@ public abstract class BaseRedis {
|
||||
return increment;
|
||||
}
|
||||
|
||||
private static final String LUA_INCR_EXPIRE =
|
||||
"local key,ttl=KEYS[1],ARGV[1] \n" +
|
||||
" \n" +
|
||||
"if redis.call('EXISTS',key)==0 then \n" +
|
||||
" redis.call('SETEX',key,ttl,1) \n" +
|
||||
" return 1 \n" +
|
||||
"else \n" +
|
||||
" return tonumber(redis.call('INCR',key)) \n" +
|
||||
"end ";
|
||||
|
||||
public Long inc(String key, int time, TimeUnit unit) {
|
||||
RedisScript<Long> redisScript = new DefaultRedisScript<>(LUA_INCR_EXPIRE, Long.class);
|
||||
return stringRedisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(unit.toSeconds(time)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 为键 key 储存的数字值加上增量 increment 。
|
||||
|
||||
@@ -316,7 +316,7 @@ public class RedisOpsImpl implements CacheOps, CachePlusOps {
|
||||
|
||||
@Override
|
||||
public Long inc(String k, Integer time, TimeUnit unit) {
|
||||
return 0L;
|
||||
return redisOps.inc(k, time, unit);
|
||||
}
|
||||
|
||||
public static <T> List<T> toBeanOrNull(List<Object> list, Class<T> tClass) {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.luohuo.basic.base.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class BaseEntity implements Serializable {
|
||||
|
||||
private Long createBy;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
private Long updateBy;
|
||||
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -12,6 +12,11 @@ public class Base62Encoder {
|
||||
public static String createAccount(long id){
|
||||
return "ID_" + encode(id, 19);
|
||||
}
|
||||
|
||||
public static String createGroup(long id){
|
||||
return "hula_" + encode(id, 19);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Long型ID编码为定长Base62字符串(可配置12-19位)
|
||||
*/
|
||||
|
||||
BIN
preview/wx.png
BIN
preview/wx.png
Binary file not shown.
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 502 KiB |
Reference in New Issue
Block a user