@@ -131,8 +131,8 @@ HuLa-Server 是一款基于 SpringCloud、SpringBoot3、Netty、MyBatis-Plus 和
|
|||||||
8. **目标WS节点消费分发过来的主题消息**
|
8. **目标WS节点消费分发过来的主题消息**
|
||||||
9. **查找本地会话映射表**
|
9. **查找本地会话映射表**
|
||||||
10. **推送消息到具体客户端**
|
10. **推送消息到具体客户端**
|
||||||
11. **客户端返回ACK确认** 
|
11. **客户端返回ACK确认**
|
||||||
12. **更新消息状态为已送达** 
|
12. **更新消息状态为已送达**
|
||||||

|

|
||||||
|
|
||||||
## 🌐 性能对比 (WS 服务)
|
## 🌐 性能对比 (WS 服务)
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ public class DefUserServiceImpl extends SuperCacheServiceImpl<DefUserManager, Lo
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Boolean updatePassword(DefUserPasswordUpdateVO data) {
|
public Boolean updatePassword(DefUserPasswordUpdateVO data) {
|
||||||
ArgumentAssert.notEmpty(data.getOldPassword(), "请输入旧密码");
|
// ArgumentAssert.notEmpty(data.getOldPassword(), "请输入旧密码");
|
||||||
DefUser user = superManager.getUserByEmail(2, data.getEmail());
|
DefUser user = superManager.getUserByEmail(2, data.getEmail());
|
||||||
ArgumentAssert.notNull(user, "用户不存在");
|
ArgumentAssert.notNull(user, "用户不存在");
|
||||||
ArgumentAssert.equals(user.getId(), ContextUtil.getUid(), "只能修改自己的密码");
|
ArgumentAssert.equals(user.getId(), ContextUtil.getUid(), "只能修改自己的密码");
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package com.luohuo.flex.im.core.chat.service;
|
package com.luohuo.flex.im.core.chat.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.luohuo.flex.im.domain.vo.request.admin.AdminAddReq;
|
import com.luohuo.flex.im.domain.vo.request.admin.AdminSetReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.admin.AdminRevokeReq;
|
|
||||||
import com.luohuo.flex.im.domain.vo.request.contact.ContactAddReq;
|
import com.luohuo.flex.im.domain.vo.request.contact.ContactAddReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.member.MemberExitReq;
|
import com.luohuo.flex.im.domain.vo.request.member.MemberExitReq;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
@@ -189,12 +188,12 @@ public interface RoomAppService {
|
|||||||
/**
|
/**
|
||||||
* 添加管理员
|
* 添加管理员
|
||||||
*/
|
*/
|
||||||
void addAdmin(Long uid, @Valid AdminAddReq request);
|
void addAdmin(Long uid, @Valid AdminSetReq request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除管理员
|
* 移除管理员
|
||||||
*/
|
*/
|
||||||
void revokeAdmin(Long uid, @Valid AdminRevokeReq request);
|
void revokeAdmin(Long uid, @Valid AdminSetReq request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建系统好友
|
* 创建系统好友
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.luohuo.flex.im.domain.vo.response.msg.BodyDTO;
|
|||||||
import com.luohuo.flex.im.domain.vo.response.msg.VideoCallMsgDTO;
|
import com.luohuo.flex.im.domain.vo.response.msg.VideoCallMsgDTO;
|
||||||
import com.luohuo.flex.im.domain.vo.response.msg.MergeMsgDTO;
|
import com.luohuo.flex.im.domain.vo.response.msg.MergeMsgDTO;
|
||||||
import com.luohuo.flex.im.domain.vo.response.msg.NoticeMsgDTO;
|
import com.luohuo.flex.im.domain.vo.response.msg.NoticeMsgDTO;
|
||||||
|
import com.luohuo.flex.model.entity.ws.AdminChangeDTO;
|
||||||
import com.luohuo.flex.model.entity.ws.WSNotice;
|
import com.luohuo.flex.model.entity.ws.WSNotice;
|
||||||
import com.luohuo.flex.model.enums.MessageMarkTypeEnum;
|
import com.luohuo.flex.model.enums.MessageMarkTypeEnum;
|
||||||
import com.luohuo.flex.im.domain.enums.MessageStatusEnum;
|
import com.luohuo.flex.im.domain.enums.MessageStatusEnum;
|
||||||
@@ -197,6 +198,16 @@ public class MessageAdapter {
|
|||||||
return wsBaseResp;
|
return wsBaseResp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建设置管理员
|
||||||
|
*/
|
||||||
|
public static WsBaseResp<AdminChangeDTO> buildSetAdminMessage(AdminChangeDTO adminChangeDTO) {
|
||||||
|
WsBaseResp<AdminChangeDTO> wsBaseResp = new WsBaseResp<>();
|
||||||
|
wsBaseResp.setType(WSRespTypeEnum.GROUP_SET_ADMIN.getType());
|
||||||
|
wsBaseResp.setData(adminChangeDTO);
|
||||||
|
return wsBaseResp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 已读群公告
|
* 已读群公告
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ import com.luohuo.flex.im.domain.dto.SummeryInfoDTO;
|
|||||||
import com.luohuo.flex.im.domain.entity.*;
|
import com.luohuo.flex.im.domain.entity.*;
|
||||||
import com.luohuo.flex.im.domain.enums.*;
|
import com.luohuo.flex.im.domain.enums.*;
|
||||||
import com.luohuo.flex.im.domain.vo.request.ChatMessageReq;
|
import com.luohuo.flex.im.domain.vo.request.ChatMessageReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.admin.AdminAddReq;
|
import com.luohuo.flex.im.domain.vo.request.admin.AdminSetReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.admin.AdminRevokeReq;
|
|
||||||
import com.luohuo.flex.im.domain.vo.request.member.MemberExitReq;
|
import com.luohuo.flex.im.domain.vo.request.member.MemberExitReq;
|
||||||
import com.luohuo.flex.im.domain.entity.msg.TextMsgReq;
|
import com.luohuo.flex.im.domain.entity.msg.TextMsgReq;
|
||||||
|
import com.luohuo.flex.model.entity.ws.AdminChangeDTO;
|
||||||
import com.luohuo.flex.model.enums.ChatActiveStatusEnum;
|
import com.luohuo.flex.model.enums.ChatActiveStatusEnum;
|
||||||
import com.luohuo.flex.im.domain.vo.request.contact.ContactAddReq;
|
import com.luohuo.flex.im.domain.vo.request.contact.ContactAddReq;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
@@ -110,7 +110,13 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import static com.luohuo.flex.im.core.chat.constant.GroupConst.MAX_MANAGE_COUNT;
|
import static com.luohuo.flex.im.core.chat.constant.GroupConst.MAX_MANAGE_COUNT;
|
||||||
import static com.luohuo.flex.im.domain.enums.ApplyReadStatusEnum.UNREAD;
|
import static com.luohuo.flex.im.domain.enums.ApplyReadStatusEnum.UNREAD;
|
||||||
|
/**
|
||||||
|
* 聊天室应用服务实现类
|
||||||
|
* - 聊天室创建、管理和维护
|
||||||
|
* - 群组成员管理(添加、删除、管理员设置)
|
||||||
|
* - 聊天消息处理与转发
|
||||||
|
* - 用户会话管理、在线状态管理、公告发布与管理
|
||||||
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@@ -307,30 +313,25 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
|||||||
@Override
|
@Override
|
||||||
@RedissonLock(prefixKey = "addAdmin:", key = "#request.roomId")
|
@RedissonLock(prefixKey = "addAdmin:", key = "#request.roomId")
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void addAdmin(Long uid, AdminAddReq request) {
|
public void addAdmin(Long uid, AdminSetReq request) {
|
||||||
// 1. 判断群聊是否存在
|
// 1. 判断群聊是否存在
|
||||||
RoomGroup roomGroup = roomGroupCache.getByRoomId(request.getRoomId());
|
RoomGroup roomGroup = verifyGet(uid, request);
|
||||||
AssertUtil.isNotEmpty(roomGroup, GroupErrorEnum.GROUP_NOT_EXIST);
|
|
||||||
|
|
||||||
// 2. 判断该用户是否是群主
|
// 2. 判断管理员数量是否达到上限
|
||||||
Boolean isLord = groupMemberDao.isLord(roomGroup.getId(), uid);
|
// 2.1 查询现有管理员数量
|
||||||
AssertUtil.isTrue(isLord, GroupErrorEnum.NOT_ALLOWED_OPERATION);
|
|
||||||
|
|
||||||
// 3. 判断群成员是否在群中
|
|
||||||
Boolean isGroupShip = groupMemberDao.isGroupShip(roomGroup.getRoomId(), request.getUidList());
|
|
||||||
AssertUtil.isTrue(isGroupShip, GroupErrorEnum.USER_NOT_IN_GROUP);
|
|
||||||
|
|
||||||
// 4. 判断管理员数量是否达到上限
|
|
||||||
// 4.1 查询现有管理员数量
|
|
||||||
List<Long> manageUidList = groupMemberDao.getManageUidList(roomGroup.getId());
|
List<Long> manageUidList = groupMemberDao.getManageUidList(roomGroup.getId());
|
||||||
// 4.2 去重
|
// 2.2 去重
|
||||||
HashSet<Long> manageUidSet = new HashSet<>(manageUidList);
|
HashSet<Long> manageUidSet = new HashSet<>(manageUidList);
|
||||||
manageUidSet.addAll(request.getUidList());
|
manageUidSet.addAll(request.getUidList());
|
||||||
AssertUtil.isFalse(manageUidSet.size() > MAX_MANAGE_COUNT, GroupErrorEnum.MANAGE_COUNT_EXCEED);
|
AssertUtil.isFalse(manageUidSet.size() > MAX_MANAGE_COUNT, GroupErrorEnum.MANAGE_COUNT_EXCEED);
|
||||||
|
|
||||||
// 5. 增加管理员
|
// 3. 增加管理员
|
||||||
groupMemberDao.addAdmin(roomGroup.getId(), request.getUidList());
|
groupMemberDao.addAdmin(roomGroup.getId(), request.getUidList());
|
||||||
|
|
||||||
|
// 5. 发送给所有群成员
|
||||||
|
List<Long> memberUidList = groupMemberCache.getMemberUidList(roomGroup.getRoomId());
|
||||||
|
pushService.sendPushMsg(MessageAdapter.buildSetAdminMessage(new AdminChangeDTO(roomGroup.getRoomId(), request.getUidList(), true)), memberUidList, uid);
|
||||||
|
|
||||||
// 每个被邀请的人都要收到邀请进群的消息
|
// 每个被邀请的人都要收到邀请进群的消息
|
||||||
setAdminNotice(NoticeTypeEnum.GROUP_SET_ADMIN, uid, request.getUidList(), manageUidList, roomGroup.getRoomId());
|
setAdminNotice(NoticeTypeEnum.GROUP_SET_ADMIN, uid, request.getUidList(), manageUidList, roomGroup.getRoomId());
|
||||||
}
|
}
|
||||||
@@ -358,7 +359,8 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
|||||||
// uid,
|
// uid,
|
||||||
// uuid,
|
// uuid,
|
||||||
// id,
|
// id,
|
||||||
// roomId
|
// roomId,
|
||||||
|
// ""
|
||||||
// );
|
// );
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -372,7 +374,22 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
|||||||
@Override
|
@Override
|
||||||
@RedissonLock(prefixKey = "revokeAdmin:", key = "#request.roomId")
|
@RedissonLock(prefixKey = "revokeAdmin:", key = "#request.roomId")
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void revokeAdmin(Long uid, AdminRevokeReq request) {
|
public void revokeAdmin(Long uid, AdminSetReq request) {
|
||||||
|
// 1. 校验
|
||||||
|
RoomGroup roomGroup = verifyGet(uid, request);
|
||||||
|
|
||||||
|
// 2. 撤销管理员
|
||||||
|
groupMemberDao.revokeAdmin(roomGroup.getId(), request.getUidList());
|
||||||
|
List<Long> memberUidList = groupMemberCache.getMemberUidList(roomGroup.getRoomId());
|
||||||
|
pushService.sendPushMsg(MessageAdapter.buildSetAdminMessage(new AdminChangeDTO(roomGroup.getRoomId(), request.getUidList(), false)), memberUidList, uid);
|
||||||
|
|
||||||
|
setAdminNotice(NoticeTypeEnum.GROUP_RECALL_ADMIN, uid, request.getUidList(), new ArrayList<>(), roomGroup.getRoomId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验人员在群里的权限
|
||||||
|
*/
|
||||||
|
private RoomGroup verifyGet(Long uid, AdminSetReq request) {
|
||||||
// 1. 判断群聊是否存在
|
// 1. 判断群聊是否存在
|
||||||
RoomGroup roomGroup = roomGroupCache.getByRoomId(request.getRoomId());
|
RoomGroup roomGroup = roomGroupCache.getByRoomId(request.getRoomId());
|
||||||
AssertUtil.isNotEmpty(roomGroup, GroupErrorEnum.GROUP_NOT_EXIST);
|
AssertUtil.isNotEmpty(roomGroup, GroupErrorEnum.GROUP_NOT_EXIST);
|
||||||
@@ -384,10 +401,7 @@ public class RoomAppServiceImpl implements RoomAppService, InitializingBean {
|
|||||||
// 3. 判断群成员是否在群中
|
// 3. 判断群成员是否在群中
|
||||||
Boolean isGroupShip = groupMemberDao.isGroupShip(roomGroup.getRoomId(), request.getUidList());
|
Boolean isGroupShip = groupMemberDao.isGroupShip(roomGroup.getRoomId(), request.getUidList());
|
||||||
AssertUtil.isTrue(isGroupShip, GroupErrorEnum.USER_NOT_IN_GROUP);
|
AssertUtil.isTrue(isGroupShip, GroupErrorEnum.USER_NOT_IN_GROUP);
|
||||||
|
return roomGroup;
|
||||||
// 4. 撤销管理员
|
|
||||||
groupMemberDao.revokeAdmin(roomGroup.getId(), request.getUidList());
|
|
||||||
setAdminNotice(NoticeTypeEnum.GROUP_RECALL_ADMIN, uid, request.getUidList(), new ArrayList<>(), roomGroup.getRoomId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import com.luohuo.flex.im.domain.vo.res.NoticeVO;
|
|||||||
import com.luohuo.flex.im.domain.vo.res.PageBaseResp;
|
import com.luohuo.flex.im.domain.vo.res.PageBaseResp;
|
||||||
import com.luohuo.flex.model.entity.ws.WSNotice;
|
import com.luohuo.flex.model.entity.ws.WSNotice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统通知服务,群通知、好友通知
|
||||||
|
*/
|
||||||
public interface NoticeService {
|
public interface NoticeService {
|
||||||
|
|
||||||
Notice getByApplyId(Long uid, Long applyId);
|
Notice getByApplyId(Long uid, Long applyId);
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ import com.luohuo.flex.im.domain.vo.request.ChatMessageMemberReq;
|
|||||||
import com.luohuo.flex.im.domain.vo.request.GroupAddReq;
|
import com.luohuo.flex.im.domain.vo.request.GroupAddReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.RoomInfoReq;
|
import com.luohuo.flex.im.domain.vo.request.RoomInfoReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.RoomMyInfoReq;
|
import com.luohuo.flex.im.domain.vo.request.RoomMyInfoReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.admin.AdminAddReq;
|
import com.luohuo.flex.im.domain.vo.request.admin.AdminSetReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.admin.AdminRevokeReq;
|
|
||||||
import com.luohuo.flex.im.domain.vo.request.member.MemberAddReq;
|
import com.luohuo.flex.im.domain.vo.request.member.MemberAddReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.member.MemberDelReq;
|
import com.luohuo.flex.im.domain.vo.request.member.MemberDelReq;
|
||||||
import com.luohuo.flex.im.domain.vo.request.member.MemberExitReq;
|
import com.luohuo.flex.im.domain.vo.request.member.MemberExitReq;
|
||||||
@@ -128,7 +127,7 @@ public class RoomController {
|
|||||||
|
|
||||||
@PutMapping("/group/admin")
|
@PutMapping("/group/admin")
|
||||||
@Operation(summary ="添加管理员")
|
@Operation(summary ="添加管理员")
|
||||||
public R<Boolean> addAdmin(@Valid @RequestBody AdminAddReq request) {
|
public R<Boolean> addAdmin(@Valid @RequestBody AdminSetReq request) {
|
||||||
Long uid = ContextUtil.getUid();
|
Long uid = ContextUtil.getUid();
|
||||||
roomService.addAdmin(uid, request);
|
roomService.addAdmin(uid, request);
|
||||||
return R.success();
|
return R.success();
|
||||||
@@ -136,7 +135,7 @@ public class RoomController {
|
|||||||
|
|
||||||
@DeleteMapping("/group/admin")
|
@DeleteMapping("/group/admin")
|
||||||
@Operation(summary ="撤销管理员")
|
@Operation(summary ="撤销管理员")
|
||||||
public R<Boolean> revokeAdmin(@Valid @RequestBody AdminRevokeReq request) {
|
public R<Boolean> revokeAdmin(@Valid @RequestBody AdminSetReq request) {
|
||||||
Long uid = ContextUtil.getUid();
|
Long uid = ContextUtil.getUid();
|
||||||
roomService.revokeAdmin(uid, request);
|
roomService.revokeAdmin(uid, request);
|
||||||
return R.success();
|
return R.success();
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.luohuo.flex.im.domain.vo.request.admin;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import jakarta.validation.constraints.Size;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 撤销管理员请求信息
|
|
||||||
* @author nyh
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class AdminRevokeReq {
|
|
||||||
@NotNull
|
|
||||||
@Schema(description ="房间号")
|
|
||||||
private Long roomId;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Size(min = 1, max = 3)
|
|
||||||
@Schema(description ="需要撤销管理的列表")
|
|
||||||
private List<Long> uidList;
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ import java.util.List;
|
|||||||
* @author nyh
|
* @author nyh
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class AdminAddReq {
|
public class AdminSetReq {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Schema(description ="房间号")
|
@Schema(description ="房间号")
|
||||||
private Long roomId;
|
private Long roomId;
|
||||||
@@ -56,6 +56,6 @@ public interface CaptchaService {
|
|||||||
* @date 2022/7/26 8:05 PM
|
* @date 2022/7/26 8:05 PM
|
||||||
* @create [2022/7/26 8:05 PM ] [tangyh] [初始创建]
|
* @create [2022/7/26 8:05 PM ] [tangyh] [初始创建]
|
||||||
*/
|
*/
|
||||||
R<Boolean> sendEmailCode(BindEmailReq bindEmailReq);
|
R<Long> sendEmailCode(BindEmailReq bindEmailReq);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.luohuo.flex.oauth.service.impl;
|
|||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.luohuo.basic.cache.repository.CachePlusOps;
|
||||||
import com.luohuo.basic.utils.TimeUtils;
|
import com.luohuo.basic.utils.TimeUtils;
|
||||||
import com.luohuo.flex.model.vo.query.BindEmailReq;
|
import com.luohuo.flex.model.vo.query.BindEmailReq;
|
||||||
import com.luohuo.flex.service.SysConfigService;
|
import com.luohuo.flex.service.SysConfigService;
|
||||||
@@ -20,7 +21,6 @@ import org.springframework.http.HttpHeaders;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.luohuo.basic.base.R;
|
import com.luohuo.basic.base.R;
|
||||||
import com.luohuo.basic.cache.redis2.CacheResult;
|
import com.luohuo.basic.cache.redis2.CacheResult;
|
||||||
import com.luohuo.basic.cache.repository.CacheOps;
|
|
||||||
import com.luohuo.basic.model.cache.CacheKey;
|
import com.luohuo.basic.model.cache.CacheKey;
|
||||||
import com.luohuo.basic.utils.ArgumentAssert;
|
import com.luohuo.basic.utils.ArgumentAssert;
|
||||||
import com.luohuo.flex.base.service.tenant.DefUserService;
|
import com.luohuo.flex.base.service.tenant.DefUserService;
|
||||||
@@ -49,7 +49,7 @@ import com.luohuo.flex.msg.facade.MsgFacade;
|
|||||||
public class CaptchaServiceImpl implements CaptchaService {
|
public class CaptchaServiceImpl implements CaptchaService {
|
||||||
|
|
||||||
private final SysConfigService configService;
|
private final SysConfigService configService;
|
||||||
private final CacheOps cacheOps;
|
private final CachePlusOps cachePlusOps;
|
||||||
private final CaptchaProperties captchaProperties;
|
private final CaptchaProperties captchaProperties;
|
||||||
private final MsgFacade msgFacade;
|
private final MsgFacade msgFacade;
|
||||||
private final DefUserService defUserService;
|
private final DefUserService defUserService;
|
||||||
@@ -86,7 +86,7 @@ public class CaptchaServiceImpl implements CaptchaService {
|
|||||||
Captcha captcha = createCaptcha();
|
Captcha captcha = createCaptcha();
|
||||||
|
|
||||||
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(key, CaptchaTokenGranter.GRANT_TYPE);
|
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(key, CaptchaTokenGranter.GRANT_TYPE);
|
||||||
cacheOps.set(cacheKey, captcha.text().toLowerCase());
|
cachePlusOps.set(cacheKey, captcha.text().toLowerCase());
|
||||||
|
|
||||||
HashMap<String, Object> map = new HashMap<>();
|
HashMap<String, Object> map = new HashMap<>();
|
||||||
map.put("uuid", key);
|
map.put("uuid", key);
|
||||||
@@ -114,7 +114,7 @@ public class CaptchaServiceImpl implements CaptchaService {
|
|||||||
String code = RandomUtil.randomNumbers(4);
|
String code = RandomUtil.randomNumbers(4);
|
||||||
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(mobile, templateCode);
|
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(mobile, templateCode);
|
||||||
// cacheKey.setExpire(Duration.ofMinutes(15)); // 可以修改有效期
|
// cacheKey.setExpire(Duration.ofMinutes(15)); // 可以修改有效期
|
||||||
cacheOps.set(cacheKey, code);
|
cachePlusOps.set(cacheKey, code);
|
||||||
|
|
||||||
log.info("短信验证码 cacheKey={}, code={}", cacheKey, code);
|
log.info("短信验证码 cacheKey={}, code={}", cacheKey, code);
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ public class CaptchaServiceImpl implements CaptchaService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public R<Boolean> sendEmailCode(BindEmailReq bindEmailReq) {
|
public R<Long> sendEmailCode(BindEmailReq bindEmailReq) {
|
||||||
if (MsgTemplateCodeEnum.REGISTER_EMAIL.eq(bindEmailReq.getTemplateCode())) {
|
if (MsgTemplateCodeEnum.REGISTER_EMAIL.eq(bindEmailReq.getTemplateCode())) {
|
||||||
// 查user表判断重复
|
// 查user表判断重复
|
||||||
boolean flag = defUserService.checkEmail(bindEmailReq.getEmail(), null);
|
boolean flag = defUserService.checkEmail(bindEmailReq.getEmail(), null);
|
||||||
@@ -139,14 +139,16 @@ public class CaptchaServiceImpl implements CaptchaService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CacheKey imgKey = CaptchaCacheKeyBuilder.build(bindEmailReq.getClientId(), CaptchaTokenGranter.GRANT_TYPE);
|
// CacheKey imgKey = CaptchaCacheKeyBuilder.build(bindEmailReq.getClientId(), CaptchaTokenGranter.GRANT_TYPE);
|
||||||
// CacheResult<String> result = cacheOps.get(imgKey);
|
// CacheResult<String> result = cachePlusOps.get(imgKey);
|
||||||
// ArgumentAssert.isFalse(!bindEmailReq.getCode().equals(result.getValue()), "图片验证码错误");
|
// ArgumentAssert.isFalse(!bindEmailReq.getCode().equals(result.getValue()), "图片验证码错误");
|
||||||
|
|
||||||
String code = RandomUtil.randomNumbers(6);
|
String code = RandomUtil.randomNumbers(6);
|
||||||
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(bindEmailReq.getEmail(), bindEmailReq.getTemplateCode());
|
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(bindEmailReq.getEmail(), bindEmailReq.getTemplateCode());
|
||||||
ArgumentAssert.isFalse(cacheOps.exists(cacheKey), "请勿重复发送验证码");
|
if(cachePlusOps.exists(cacheKey)){
|
||||||
|
return R.success(cachePlusOps.ttl(cacheKey));
|
||||||
|
}
|
||||||
|
|
||||||
cacheOps.set(cacheKey, code);
|
cachePlusOps.set(cacheKey, code);
|
||||||
log.info("邮件验证码 cacheKey={}, code={}", cacheKey, code);
|
log.info("邮件验证码 cacheKey={}, code={}", cacheKey, code);
|
||||||
|
|
||||||
// 在「运营平台」-「消息模板」配置一个「模板标识」为 templateCode, 且「模板内容」中需要有 code 占位符
|
// 在「运营平台」-「消息模板」配置一个「模板标识」为 templateCode, 且「模板内容」中需要有 code 占位符
|
||||||
@@ -159,7 +161,8 @@ public class CaptchaServiceImpl implements CaptchaService {
|
|||||||
msgSendVO.addParam("currentTime", TimeUtils.nowToStr());
|
msgSendVO.addParam("currentTime", TimeUtils.nowToStr());
|
||||||
|
|
||||||
msgSendVO.addRecipient(bindEmailReq.getEmail());
|
msgSendVO.addRecipient(bindEmailReq.getEmail());
|
||||||
return R.success(msgFacade.sendByTemplate(msgSendVO));
|
msgFacade.sendByTemplate(msgSendVO);
|
||||||
|
return R.success(cachePlusOps.ttl(cacheKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -168,14 +171,14 @@ public class CaptchaServiceImpl implements CaptchaService {
|
|||||||
return R.fail(CAPTCHA_ERROR.build("请输入验证码"));
|
return R.fail(CAPTCHA_ERROR.build("请输入验证码"));
|
||||||
}
|
}
|
||||||
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(key, templateCode);
|
CacheKey cacheKey = CaptchaCacheKeyBuilder.build(key, templateCode);
|
||||||
CacheResult<String> code = cacheOps.get(cacheKey);
|
CacheResult<String> code = cachePlusOps.get(cacheKey);
|
||||||
if (StrUtil.isEmpty(code.getValue())) {
|
if (StrUtil.isEmpty(code.getValue())) {
|
||||||
return R.fail(CAPTCHA_ERROR.build("验证码已过期"));
|
return R.fail(CAPTCHA_ERROR.build("验证码已过期"));
|
||||||
}
|
}
|
||||||
if (!StrUtil.equalsIgnoreCase(value, code.getValue())) {
|
if (!StrUtil.equalsIgnoreCase(value, code.getValue())) {
|
||||||
return R.fail(CAPTCHA_ERROR.build("验证码不正确"));
|
return R.fail(CAPTCHA_ERROR.build("验证码不正确"));
|
||||||
}
|
}
|
||||||
cacheOps.del(cacheKey);
|
cachePlusOps.del(cacheKey);
|
||||||
return R.success(true);
|
return R.success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class CaptchaController {
|
|||||||
})
|
})
|
||||||
@Operation(summary = "发送邮箱验证码", description = "发送邮箱验证码")
|
@Operation(summary = "发送邮箱验证码", description = "发送邮箱验证码")
|
||||||
@PostMapping(value = "/sendEmailCode")
|
@PostMapping(value = "/sendEmailCode")
|
||||||
public R<Boolean> sendEmailCode(@RequestBody BindEmailReq bindEmailReq) {
|
public R<Long> sendEmailCode(@RequestBody BindEmailReq bindEmailReq) {
|
||||||
return captchaService.sendEmailCode(bindEmailReq);
|
return captchaService.sendEmailCode(bindEmailReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public enum WSRespTypeEnum {
|
|||||||
REQUEST_APPROVAL_FRIEND("requestApprovalFriend", "同意好友请求", WSFriendApproval.class),
|
REQUEST_APPROVAL_FRIEND("requestApprovalFriend", "同意好友请求", WSFriendApproval.class),
|
||||||
NEW_APPLY("newApply", "好友申请、群聊邀请", WSNotice.class),
|
NEW_APPLY("newApply", "好友申请、群聊邀请", WSNotice.class),
|
||||||
ROOM_DISSOLUTION("roomDissolution", "群解散", null),
|
ROOM_DISSOLUTION("roomDissolution", "群解散", null),
|
||||||
|
GROUP_SET_ADMIN("groupSetAdmin", "设置管理员", AdminChangeDTO.class),
|
||||||
|
|
||||||
ROOM_GROUP_NOTICE_READ_MSG("roomGroupNoticeReadMsg", "群公告已读", null),
|
ROOM_GROUP_NOTICE_READ_MSG("roomGroupNoticeReadMsg", "群公告已读", null),
|
||||||
FEED_SEND_MSG("feedSendMsg", "朋友圈发布", null),
|
FEED_SEND_MSG("feedSendMsg", "朋友圈发布", null),
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.luohuo.flex.model.entity.ws;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员变更数据传输对象
|
||||||
|
* @author 乾乾
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AdminChangeDTO implements Serializable {
|
||||||
|
/**
|
||||||
|
* 房间ID
|
||||||
|
*/
|
||||||
|
private String roomId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员ID列表
|
||||||
|
*/
|
||||||
|
private List<String> uids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true: 设置 false: 取消
|
||||||
|
*/
|
||||||
|
private Boolean status;
|
||||||
|
|
||||||
|
public AdminChangeDTO(Long roomId, List<Long> uids, Boolean status) {
|
||||||
|
this.roomId = roomId != null ? roomId.toString() : null;
|
||||||
|
this.uids = uids != null ? uids.stream().map(Object::toString).collect(Collectors.toList()) : null;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminChangeDTO() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ public class RoomMetadataService {
|
|||||||
|
|
||||||
public Boolean isRoomClosed(Long roomId) {
|
public Boolean isRoomClosed(Long roomId) {
|
||||||
CacheResult<Boolean> result = cachePlusOps.get(CloseRoomCacheKeyBuilder.builder(roomId));
|
CacheResult<Boolean> result = cachePlusOps.get(CloseRoomCacheKeyBuilder.builder(roomId));
|
||||||
return result.isNull()? true: result.getRawValue();
|
return result.isNull() || result.isNullVal()? true: result.getRawValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ public class VideoChatService {
|
|||||||
public void forwardSignal(Long senderUid, Long roomId, String signal, String signalType) {
|
public void forwardSignal(Long senderUid, Long roomId, String signal, String signalType) {
|
||||||
// 1. 获取房间内其他成员
|
// 1. 获取房间内其他成员
|
||||||
try {
|
try {
|
||||||
List<Long> uidList = getOnlineUidList(roomId);
|
List<Long> uidList = getUserList(roomId);
|
||||||
uidList.remove(senderUid);
|
uidList.remove(senderUid);
|
||||||
|
|
||||||
if (uidList.isEmpty()) return;
|
if (uidList.isEmpty()) return;
|
||||||
@@ -168,7 +168,7 @@ public class VideoChatService {
|
|||||||
* 获取房间内所有人员id
|
* 获取房间内所有人员id
|
||||||
* @param roomId 房间id
|
* @param roomId 房间id
|
||||||
*/
|
*/
|
||||||
public List<Long> getOnlineUidList(Long roomId) {
|
public List<Long> getUserList(Long roomId) {
|
||||||
return onlineService.getGroupMembers(roomId);
|
return onlineService.getGroupMembers(roomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,8 +276,8 @@ public class VideoChatService {
|
|||||||
* @param data 通知数据
|
* @param data 通知数据
|
||||||
*/
|
*/
|
||||||
private <T> List<Long> notifyRoomMembers(Long roomId, Long excludeUid, WSRespTypeEnum respType, T data) {
|
private <T> List<Long> notifyRoomMembers(Long roomId, Long excludeUid, WSRespTypeEnum respType, T data) {
|
||||||
// 1. 获取房间内在线成员
|
// 1. 获取房间内所有成员
|
||||||
List<Long> uidList = getOnlineUidList(roomId);
|
List<Long> uidList = getUserList(roomId);
|
||||||
if (uidList.isEmpty()) return new ArrayList<>();
|
if (uidList.isEmpty()) return new ArrayList<>();
|
||||||
|
|
||||||
// 2. 排除当前用户
|
// 2. 排除当前用户
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
## 本地如何跑hula
|
## 本地如何跑hula
|
||||||
|
|
||||||
注意!! 开发环境默认大家已经安装nacos(版本我用的是3.0.2,web端端口是8080,老版本是8848)、rocketMQ、mysql、redis这些组件了
|
注意!! 开发环境默认大家已经安装nacos(版本我用的是3.0.2,web端端口是8080,老版本是8848)、rocketMQ、mysql、redis这些组件了
|
||||||
如果没有的话先看一下 [reids、mysql、rocketmq、nacos一键部署.md](../docs/install/docker/reids%E3%80%81mysql%E3%80%81rocketmq%E3%80%81nacos%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B2.md) (组件部署文档)
|
如果没有的话先看一下 [redis、mysql、rocketmq、nacos一键部署.md](install/docker/reids%E3%80%81mysql%E3%80%81rocketmq%E3%80%81nacos%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B2.md) (组件部署文档)
|
||||||
|
|
||||||
下面执行顺序不能乱,因为install cloud模块的时候需要将 src/main/filters 里面的配置打到target里面去
|
下面执行顺序不能乱,因为install cloud模块的时候需要将 src/main/filters 里面的配置打到target里面去
|
||||||
|
|
||||||
1. 将 luohuo-cloud/pom.xml 导入IDEA
|
1. 将 luohuo-cloud/pom.xml 导入IDEA
|
||||||
2. 导入luohuo-util项目
|
2. 导入luohuo-util项目
|
||||||

|

|
||||||
3. 安装luohuo-util到本地
|
3. 安装luohuo-util到本地
|
||||||
4. 导入nacos环境,以我本地为例:127.0.0.1:8080
|
4. 导入nacos环境,以我本地为例:127.0.0.1:8080
|
||||||
5. 修改redis.yml、mysql.yml、rocketmq.yml、luohuo-im-server.yml的配置
|
5. 修改redis.yml、mysql.yml、rocketmq.yml、luohuo-im-server.yml的配置
|
||||||
6. 安装luohuo-cloud到本地
|
6. 安装luohuo-cloud到本地
|
||||||
7. 导入数据库 [luohuo_dev.sql](../docs/install/sql/luohuo_dev.sql)、[luohuo_im_01.sql](../docs/install/sql/luohuo_im_01.sql)
|
7. 导入数据库 [luohuo_dev.sql](install/sql/luohuo_dev.sql)、[luohuo_im_01.sql](install/sql/luohuo_im_01.sql)
|
||||||
8. 运行效果图
|
8. 运行效果图
|
||||||
9. 前端配置访问地址:
|
9. 前端配置访问地址:
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
Reference in New Issue
Block a user