fix: 进群、移出群成员更新在线人员总数,优化负载均衡

This commit is contained in:
乾乾
2025-09-03 17:54:09 +08:00
parent 69b475ce64
commit b941aa2790
55 changed files with 213 additions and 362 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -18,7 +18,7 @@ public interface ContactService {
/**
* 创建会话
*/
Contact createContact(Long uid, Long roomId);
void createContact(Long uid, Long roomId);
Integer getMsgReadCount(Message message);

View File

@@ -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);
}

View File

@@ -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))

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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(), "消息无法撤回");

View File

@@ -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

View File

@@ -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);

View File

@@ -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()

View File

@@ -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字段无需传值
*/

View File

@@ -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. 通知申请人 [这条消息需要覆盖前端]

View File

@@ -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);
}
/**

View File

@@ -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());

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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 ="申请信息")

View File

@@ -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)

View File

@@ -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")

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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")

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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")

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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 {
/**
* 表情地址
*/

View File

@@ -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")

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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账号

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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
*/

View File

@@ -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;
}

View File

@@ -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 。

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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位
*/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 502 KiB