Commit 3d8b8792fdeff6156c37d73edf682205bf0bcae2

Authored by YunaiV
1 parent 1db02564

♻️ refactor(im): 业务策略数值从 ImCommonConstants 上移到 ImProperties(按 group / message 子模…

…块分组),常量类仅保留 AT_USER_ID_ALL 协议契约值

♻️ refactor(im): 抽出 utils/config.ts 集中数值常量,按业务域统一前缀(GROUP_ / MESSAGE_ / FRIEND_ / CONVERSATION_ / FORWARD_),constants.ts 只留协议枚举与契约值
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/ImCommonConstants.java
@@ -8,50 +8,10 @@ package cn.iocoder.yudao.module.im.enums; @@ -8,50 +8,10 @@ package cn.iocoder.yudao.module.im.enums;
8 public interface ImCommonConstants { 8 public interface ImCommonConstants {
9 9
10 /** 10 /**
11 - * pull 最大拉取数量  
12 - */  
13 - int MESSAGE_MAX_PULL_SIZE = 1000;  
14 -  
15 - /**  
16 - * 群最大成员人数  
17 - */  
18 - int MAX_GROUP_MEMBER = 500;  
19 -  
20 - /**  
21 - * 单群管理员人数上限  
22 - */  
23 - int GROUP_ADMIN_MAX_COUNT = 3;  
24 -  
25 - /**  
26 - * 单群置顶消息条数上限  
27 - */  
28 - int GROUP_PIN_MAX_COUNT = 5;  
29 -  
30 - /**  
31 * 群消息 @ 所有人的特殊用户编号 11 * 群消息 @ 所有人的特殊用户编号
32 - */  
33 - long AT_USER_ID_ALL = -1L;  
34 -  
35 - /**  
36 - * 消息撤回时间限制(分钟)  
37 - */  
38 - int MESSAGE_RECALL_TIMEOUT_MINUTES = 5;  
39 -  
40 - /**  
41 - * 私聊离线消息最大拉取天数  
42 - * <p>  
43 - * 客户端通过 pull 接口增量拉取私聊离线消息时,仅返回最近 N 天内产生的消息,  
44 - * 超过该窗口的老消息不再主动推送(可通过历史消息接口按需倒翻)。  
45 - */  
46 - int MESSAGE_PRIVATE_PULL_MAX_DAYS = 30;  
47 -  
48 - /**  
49 - * 群聊离线消息最大拉取天数  
50 * <p> 12 * <p>
51 - * 客户端通过 pull 接口增量拉取群聊离线消息时,仅返回最近 N 天内产生的消息;  
52 - * 退群前消息的补齐也以该窗口为基准(早于窗口的退群群不再扫描),避免老用户首次  
53 - * 拉取时对历史退群群做大量查询。 13 + * 前后端协议契约值;atUserIds 数组里出现该值表示 @ 全体成员
54 */ 14 */
55 - int MESSAGE_GROUP_PULL_MAX_DAYS = 30; 15 + long AT_USER_ID_ALL = -1L;
56 16
57 } 17 }
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/config/ImProperties.java
@@ -7,7 +7,7 @@ import org.springframework.stereotype.Component; @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component;
7 /** 7 /**
8 * IM 模块全局配置 8 * IM 模块全局配置
9 * <p> 9 * <p>
10 - * 各子模块用嵌套 inner class 区分(friend / 后续 group / sensitive 等), 10 + * 各子模块用嵌套 inner class 区分(friend / group / message / 后续 sensitive 等),
11 * yaml 路径保持 yudao.im.{module}.{key} 与原有部署保持兼容 11 * yaml 路径保持 yudao.im.{module}.{key} 与原有部署保持兼容
12 * 12 *
13 * @author 芋道源码 13 * @author 芋道源码
@@ -19,6 +19,10 @@ public class ImProperties { @@ -19,6 +19,10 @@ public class ImProperties {
19 19
20 private Friend friend = new Friend(); 20 private Friend friend = new Friend();
21 21
  22 + private Group group = new Group();
  23 +
  24 + private Message message = new Message();
  25 +
22 /** 26 /**
23 * 好友模块配置 27 * 好友模块配置
24 */ 28 */
@@ -35,4 +39,62 @@ public class ImProperties { @@ -35,4 +39,62 @@ public class ImProperties {
35 39
36 } 40 }
37 41
  42 + /**
  43 + * 群模块配置
  44 + */
  45 + @Data
  46 + public static class Group {
  47 +
  48 + /**
  49 + * 群最大成员人数
  50 + */
  51 + private int maxMember = 500;
  52 +
  53 + /**
  54 + * 单群管理员人数上限
  55 + */
  56 + private int adminMaxCount = 3;
  57 +
  58 + /**
  59 + * 单群置顶消息条数上限
  60 + */
  61 + private int pinMaxCount = 5;
  62 +
  63 + }
  64 +
  65 + /**
  66 + * 消息模块配置
  67 + */
  68 + @Data
  69 + public static class Message {
  70 +
  71 + /**
  72 + * pull 最大拉取数量
  73 + */
  74 + private int maxPullSize = 1000;
  75 +
  76 + /**
  77 + * 消息撤回时间限制(分钟)
  78 + */
  79 + private int recallTimeoutMinutes = 5;
  80 +
  81 + /**
  82 + * 私聊离线消息最大拉取天数
  83 + * <p>
  84 + * 客户端通过 pull 接口增量拉取私聊离线消息时,仅返回最近 N 天内产生的消息,
  85 + * 超过该窗口的老消息不再主动推送(可通过历史消息接口按需倒翻)。
  86 + */
  87 + private int privatePullMaxDays = 30;
  88 +
  89 + /**
  90 + * 群聊离线消息最大拉取天数
  91 + * <p>
  92 + * 客户端通过 pull 接口增量拉取群聊离线消息时,仅返回最近 N 天内产生的消息;
  93 + * 退群前消息的补齐也以该窗口为基准(早于窗口的退群群不再扫描),避免老用户首次
  94 + * 拉取时对历史退群群做大量查询。
  95 + */
  96 + private int groupPullMaxDays = 30;
  97 +
  98 + }
  99 +
38 } 100 }
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java
@@ -99,8 +99,8 @@ public interface ImGroupService { @@ -99,8 +99,8 @@ public interface ImGroupService {
99 /** 99 /**
100 * 获取指定用户的群列表 100 * 获取指定用户的群列表
101 * <p> 101 * <p>
102 - * 返回用户当前仍有效的群,以及最近 {@link cn.iocoder.yudao.module.im.enums.ImCommonConstants#MESSAGE_GROUP_PULL_MAX_DAYS}  
103 - * 天内退群的群 —— 退群前可能还有离线消息需要展示,前端需要把这些群信息作为缓存。 102 + * 返回用户当前仍有效的群,以及最近 yudao.im.message.group-pull-max-days 天内退群的群
  103 + * —— 退群前可能还有离线消息需要展示,前端需要把这些群信息作为缓存。
104 * 104 *
105 * @param userId 用户编号 105 * @param userId 用户编号
106 * @return 群列表 106 * @return 群列表
@@ -171,7 +171,7 @@ public interface ImGroupService { @@ -171,7 +171,7 @@ public interface ImGroupService {
171 /** 171 /**
172 * 置顶群消息(仅群主或管理员可执行) 172 * 置顶群消息(仅群主或管理员可执行)
173 * <p> 173 * <p>
174 - * 上限 {@link cn.iocoder.yudao.module.im.enums.ImCommonConstants#GROUP_PIN_MAX_COUNT};幂等失败时抛业务异常 174 + * 上限由 yudao.im.group.pin-max-count 控制;幂等失败时抛业务异常
175 * 175 *
176 * @param userId 当前登录用户编号 176 * @param userId 当前登录用户编号
177 * @param groupId 群编号 177 * @param groupId 群编号
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java
@@ -28,6 +28,7 @@ import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; @@ -28,6 +28,7 @@ import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO;
28 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO; 28 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO;
29 import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper; 29 import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper;
30 import cn.iocoder.yudao.module.im.enums.group.ImGroupAddSourceEnum; 30 import cn.iocoder.yudao.module.im.enums.group.ImGroupAddSourceEnum;
  31 +import cn.iocoder.yudao.module.im.framework.config.ImProperties;
31 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum; 32 import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
32 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; 33 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
33 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; 34 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
@@ -53,7 +54,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @@ -53,7 +54,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
53 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 54 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
54 import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.GROUP; 55 import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.GROUP;
55 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; 56 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
56 -import static cn.iocoder.yudao.module.im.enums.ImCommonConstants.*;  
57 57
58 /** 58 /**
59 * 用户群 Service 实现类 59 * 用户群 Service 实现类
@@ -83,6 +83,9 @@ public class ImGroupServiceImpl implements ImGroupService { @@ -83,6 +83,9 @@ public class ImGroupServiceImpl implements ImGroupService {
83 @Resource 83 @Resource
84 private AdminUserApi adminUserApi; 84 private AdminUserApi adminUserApi;
85 85
  86 + @Resource
  87 + private ImProperties imProperties;
  88 +
86 // ==================== 群的写操作 ==================== 89 // ==================== 群的写操作 ====================
87 90
88 @Override 91 @Override
@@ -101,9 +104,10 @@ public class ImGroupServiceImpl implements ImGroupService { @@ -101,9 +104,10 @@ public class ImGroupServiceImpl implements ImGroupService {
101 throw exception(GROUP_INVITE_NOT_FRIEND, getUserNicknames(notFriendUserIds)); 104 throw exception(GROUP_INVITE_NOT_FRIEND, getUserNicknames(notFriendUserIds));
102 } 105 }
103 } 106 }
104 - // 1.3 校验群人数上限(创建者 + 初始成员 ≤ MAX_GROUP_MEMBER)  
105 - if (initialMemberUserIds.size() + 1 > MAX_GROUP_MEMBER) {  
106 - throw exception(GROUP_MEMBER_EXCEED, MAX_GROUP_MEMBER); 107 + // 1.3 校验群人数上限(创建者 + 初始成员 ≤ 群成员上限)
  108 + int maxMember = imProperties.getGroup().getMaxMember();
  109 + if (initialMemberUserIds.size() + 1 > maxMember) {
  110 + throw exception(GROUP_MEMBER_EXCEED, maxMember);
107 } 111 }
108 112
109 // 2.1 插入群记录 113 // 2.1 插入群记录
@@ -210,8 +214,9 @@ public class ImGroupServiceImpl implements ImGroupService { @@ -210,8 +214,9 @@ public class ImGroupServiceImpl implements ImGroupService {
210 throw exception(GROUP_INVITE_NOT_FRIEND, getUserNicknames(notFriendUserIds)); 214 throw exception(GROUP_INVITE_NOT_FRIEND, getUserNicknames(notFriendUserIds));
211 } 215 }
212 // 1.4 校验群人数上限 216 // 1.4 校验群人数上限
213 - if (activeMembers.size() + memberUserIds.size() > MAX_GROUP_MEMBER) {  
214 - throw exception(GROUP_MEMBER_EXCEED, MAX_GROUP_MEMBER); 217 + int maxMember = imProperties.getGroup().getMaxMember();
  218 + if (activeMembers.size() + memberUserIds.size() > maxMember) {
  219 + throw exception(GROUP_MEMBER_EXCEED, maxMember);
215 } 220 }
216 221
217 // 2. 情况一:群开启审批 + 邀请人是普通成员,落 group_request 等群主 / 管理员处理 222 // 2. 情况一:群开启审批 + 邀请人是普通成员,落 group_request 等群主 / 管理员处理
@@ -304,8 +309,9 @@ public class ImGroupServiceImpl implements ImGroupService { @@ -304,8 +309,9 @@ public class ImGroupServiceImpl implements ImGroupService {
304 // 1.4 校验上限 309 // 1.4 校验上限
305 Long existAdminCount = groupMemberService.getGroupMemberCountByRole( 310 Long existAdminCount = groupMemberService.getGroupMemberCountByRole(
306 groupId, ImGroupMemberRoleEnum.ADMIN.getRole()); 311 groupId, ImGroupMemberRoleEnum.ADMIN.getRole());
307 - if (existAdminCount + changedUserIds.size() > GROUP_ADMIN_MAX_COUNT) {  
308 - throw exception(GROUP_ADMIN_MAX_LIMIT, GROUP_ADMIN_MAX_COUNT); 312 + int adminMaxCount = imProperties.getGroup().getAdminMaxCount();
  313 + if (existAdminCount + changedUserIds.size() > adminMaxCount) {
  314 + throw exception(GROUP_ADMIN_MAX_LIMIT, adminMaxCount);
309 } 315 }
310 316
311 // 2. 批量更新角色 317 // 2. 批量更新角色
@@ -404,8 +410,9 @@ public class ImGroupServiceImpl implements ImGroupService { @@ -404,8 +410,9 @@ public class ImGroupServiceImpl implements ImGroupService {
404 if (pinned.contains(messageId)) { 410 if (pinned.contains(messageId)) {
405 throw exception(GROUP_MESSAGE_ALREADY_PINNED); 411 throw exception(GROUP_MESSAGE_ALREADY_PINNED);
406 } 412 }
407 - if (pinned.size() >= GROUP_PIN_MAX_COUNT) {  
408 - throw exception(GROUP_MESSAGE_PIN_MAX_LIMIT, GROUP_PIN_MAX_COUNT); 413 + int pinMaxCount = imProperties.getGroup().getPinMaxCount();
  414 + if (pinned.size() >= pinMaxCount) {
  415 + throw exception(GROUP_MESSAGE_PIN_MAX_LIMIT, pinMaxCount);
409 } 416 }
410 pinned.add(messageId); 417 pinned.add(messageId);
411 groupMapper.updateById(new ImGroupDO().setId(groupId).setPinnedMessageIds(pinned)); 418 groupMapper.updateById(new ImGroupDO().setId(groupId).setPinnedMessageIds(pinned));
@@ -465,8 +472,9 @@ public class ImGroupServiceImpl implements ImGroupService { @@ -465,8 +472,9 @@ public class ImGroupServiceImpl implements ImGroupService {
465 @Override 472 @Override
466 public void validateMemberCountLimit(Long groupId, int addCount) { 473 public void validateMemberCountLimit(Long groupId, int addCount) {
467 int activeCount = groupMemberService.getActiveGroupMemberUserIdsByGroupId(groupId).size(); 474 int activeCount = groupMemberService.getActiveGroupMemberUserIdsByGroupId(groupId).size();
468 - if (activeCount + addCount > MAX_GROUP_MEMBER) {  
469 - throw exception(GROUP_MEMBER_EXCEED, MAX_GROUP_MEMBER); 475 + int maxMember = imProperties.getGroup().getMaxMember();
  476 + if (activeCount + addCount > maxMember) {
  477 + throw exception(GROUP_MEMBER_EXCEED, maxMember);
470 } 478 }
471 } 479 }
472 480
@@ -512,8 +520,8 @@ public class ImGroupServiceImpl implements ImGroupService { @@ -512,8 +520,8 @@ public class ImGroupServiceImpl implements ImGroupService {
512 public List<ImGroupDO> getMyGroupList(Long userId) { 520 public List<ImGroupDO> getMyGroupList(Long userId) {
513 // 1.1 查用户所在的、仍有效的群成员记录(仅 ENABLE 状态) 521 // 1.1 查用户所在的、仍有效的群成员记录(仅 ENABLE 状态)
514 List<ImGroupMemberDO> members = groupMemberService.getActiveGroupMemberListByUserId(userId); 522 List<ImGroupMemberDO> members = groupMemberService.getActiveGroupMemberListByUserId(userId);
515 - // 1.2 再查最近 MESSAGE_GROUP_PULL_MAX_DAYS 天内退群的成员记录(退群前可能有离线消息需要展示,一并返回作为前端缓存)  
516 - LocalDateTime minQuitTime = LocalDateTime.now().minusDays(MESSAGE_GROUP_PULL_MAX_DAYS); 523 + // 1.2 再查最近 N 天(与群消息离线拉取窗口一致)内退群的成员记录(退群前可能有离线消息需要展示,一并返回作为前端缓存)
  524 + LocalDateTime minQuitTime = LocalDateTime.now().minusDays(imProperties.getMessage().getGroupPullMaxDays());
517 members.addAll(groupMemberService.getQuitGroupMemberListByUserId(userId, minQuitTime)); 525 members.addAll(groupMemberService.getQuitGroupMemberListByUserId(userId, minQuitTime));
518 if (CollUtil.isEmpty(members)) { 526 if (CollUtil.isEmpty(members)) {
519 return Collections.emptyList(); 527 return Collections.emptyList();
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java
@@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum; @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.im.enums.group.ImGroupMemberRoleEnum;
21 import cn.iocoder.yudao.module.im.enums.message.ImGroupMessageReceiptStatusEnum; 21 import cn.iocoder.yudao.module.im.enums.message.ImGroupMessageReceiptStatusEnum;
22 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; 22 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
23 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; 23 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
  24 +import cn.iocoder.yudao.module.im.framework.config.ImProperties;
24 import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService; 25 import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService;
25 import cn.iocoder.yudao.module.im.service.group.ImGroupService; 26 import cn.iocoder.yudao.module.im.service.group.ImGroupService;
26 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO; 27 import cn.iocoder.yudao.module.im.service.message.dto.ImGroupMessageSendDTO;
@@ -43,7 +44,6 @@ import java.util.*; @@ -43,7 +44,6 @@ import java.util.*;
43 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 44 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
44 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 45 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
45 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; 46 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
46 -import static cn.iocoder.yudao.module.im.enums.ImCommonConstants.*;  
47 47
48 /** 48 /**
49 * IM 群聊消息 Service 实现类 49 * IM 群聊消息 Service 实现类
@@ -77,6 +77,9 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService { @@ -77,6 +77,9 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
77 @Resource 77 @Resource
78 private ImWebSocketService imWebSocketService; 78 private ImWebSocketService imWebSocketService;
79 79
  80 + @Resource
  81 + private ImProperties imProperties;
  82 +
80 @Override 83 @Override
81 public ImGroupMessageDO sendGroupMessage(Long senderId, ImGroupMessageSendReqVO reqVO) { 84 public ImGroupMessageDO sendGroupMessage(Long senderId, ImGroupMessageSendReqVO reqVO) {
82 // 1.1 幂等校验:根据 senderId + clientMessageId 查重 85 // 1.1 幂等校验:根据 senderId + clientMessageId 查重
@@ -161,8 +164,9 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService { @@ -161,8 +164,9 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
161 throw exception(MESSAGE_ALREADY_RECALLED); 164 throw exception(MESSAGE_ALREADY_RECALLED);
162 } 165 }
163 // 1.4 只允许撤回限定时间内的消息 166 // 1.4 只允许撤回限定时间内的消息
164 - if (message.getSendTime().plusMinutes(MESSAGE_RECALL_TIMEOUT_MINUTES).isBefore(LocalDateTime.now())) {  
165 - throw exception(MESSAGE_RECALL_TIMEOUT, MESSAGE_RECALL_TIMEOUT_MINUTES); 167 + int recallTimeoutMinutes = imProperties.getMessage().getRecallTimeoutMinutes();
  168 + if (message.getSendTime().plusMinutes(recallTimeoutMinutes).isBefore(LocalDateTime.now())) {
  169 + throw exception(MESSAGE_RECALL_TIMEOUT, recallTimeoutMinutes);
166 } 170 }
167 // 1.5 校验撤回人仍在群中 171 // 1.5 校验撤回人仍在群中
168 groupMemberService.validateMemberInGroup(message.getGroupId(), userId); 172 groupMemberService.validateMemberInGroup(message.getGroupId(), userId);
@@ -178,12 +182,13 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService { @@ -178,12 +182,13 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService {
178 182
179 @Override 183 @Override
180 public List<ImGroupMessageDO> pullGroupMessageList(Long userId, Long minId, Integer size) { 184 public List<ImGroupMessageDO> pullGroupMessageList(Long userId, Long minId, Integer size) {
181 - if (size > MESSAGE_MAX_PULL_SIZE) {  
182 - throw exception(MESSAGE_PULL_SIZE_EXCEEDED, MESSAGE_MAX_PULL_SIZE); 185 + int maxPullSize = imProperties.getMessage().getMaxPullSize();
  186 + if (size > maxPullSize) {
  187 + throw exception(MESSAGE_PULL_SIZE_EXCEEDED, maxPullSize);
183 } 188 }
184 189
185 - // 0. 拉取时间窗:超过窗口的老消息不再通过离线通道推送  
186 - LocalDateTime minSendTime = LocalDateTime.now().minusDays(MESSAGE_GROUP_PULL_MAX_DAYS); 190 + // 0. 拉取时间窗;超过窗口的老消息不再通过离线通道推送
  191 + LocalDateTime minSendTime = LocalDateTime.now().minusDays(imProperties.getMessage().getGroupPullMaxDays());
187 192
188 // 1.1 主查询:仅用"当前仍在群"的成员记录驱动;若首批消息过滤后为空,则允许内部重试 193 // 1.1 主查询:仅用"当前仍在群"的成员记录驱动;若首批消息过滤后为空,则允许内部重试
189 List<ImGroupMemberDO> activeMembers = groupMemberService.getActiveGroupMemberListByUserId(userId); 194 List<ImGroupMemberDO> activeMembers = groupMemberService.getActiveGroupMemberListByUserId(userId);
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java
@@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper; @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
14 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; 14 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
15 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum; 15 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
16 import cn.iocoder.yudao.module.im.enums.friend.ImFriendStateEnum; 16 import cn.iocoder.yudao.module.im.enums.friend.ImFriendStateEnum;
  17 +import cn.iocoder.yudao.module.im.framework.config.ImProperties;
17 import cn.iocoder.yudao.module.im.service.friend.ImFriendService; 18 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
18 import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO; 19 import cn.iocoder.yudao.module.im.service.message.dto.ImPrivateMessageSendDTO;
19 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService; 20 import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService;
@@ -33,7 +34,6 @@ import java.util.List; @@ -33,7 +34,6 @@ import java.util.List;
33 34
34 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
35 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; 36 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*;
36 -import static cn.iocoder.yudao.module.im.enums.ImCommonConstants.*;  
37 37
38 /** 38 /**
39 * IM 私聊消息 Service 实现类 39 * IM 私聊消息 Service 实现类
@@ -56,6 +56,9 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService { @@ -56,6 +56,9 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
56 @Resource 56 @Resource
57 private ImWebSocketService imWebSocketService; 57 private ImWebSocketService imWebSocketService;
58 58
  59 + @Resource
  60 + private ImProperties imProperties;
  61 +
59 @Override 62 @Override
60 public ImPrivateMessageDO sendPrivateMessage(Long senderId, ImPrivateMessageSendReqVO reqVO) { 63 public ImPrivateMessageDO sendPrivateMessage(Long senderId, ImPrivateMessageSendReqVO reqVO) {
61 // 1.1 幂等校验:根据 senderId + clientMessageId 查重 64 // 1.1 幂等校验:根据 senderId + clientMessageId 查重
@@ -139,8 +142,9 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService { @@ -139,8 +142,9 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
139 throw exception(MESSAGE_ALREADY_RECALLED); 142 throw exception(MESSAGE_ALREADY_RECALLED);
140 } 143 }
141 // 1.4 只允许撤回限定时间内的消息 144 // 1.4 只允许撤回限定时间内的消息
142 - if (message.getSendTime().plusMinutes(MESSAGE_RECALL_TIMEOUT_MINUTES).isBefore(LocalDateTime.now())) {  
143 - throw exception(MESSAGE_RECALL_TIMEOUT, MESSAGE_RECALL_TIMEOUT_MINUTES); 145 + int recallTimeoutMinutes = imProperties.getMessage().getRecallTimeoutMinutes();
  146 + if (message.getSendTime().plusMinutes(recallTimeoutMinutes).isBefore(LocalDateTime.now())) {
  147 + throw exception(MESSAGE_RECALL_TIMEOUT, recallTimeoutMinutes);
144 } 148 }
145 149
146 // 2. 更新原消息状态为撤回 150 // 2. 更新原消息状态为撤回
@@ -190,11 +194,12 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService { @@ -190,11 +194,12 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService {
190 194
191 @Override 195 @Override
192 public List<ImPrivateMessageDO> pullPrivateMessageList(Long userId, Long minId, Integer size) { 196 public List<ImPrivateMessageDO> pullPrivateMessageList(Long userId, Long minId, Integer size) {
193 - if (size > MESSAGE_MAX_PULL_SIZE) {  
194 - throw exception(MESSAGE_PULL_SIZE_EXCEEDED, MESSAGE_MAX_PULL_SIZE); 197 + int maxPullSize = imProperties.getMessage().getMaxPullSize();
  198 + if (size > maxPullSize) {
  199 + throw exception(MESSAGE_PULL_SIZE_EXCEEDED, maxPullSize);
195 } 200 }
196 - // 0. 拉取时间窗:超过窗口的老消息不再通过离线通道推送  
197 - LocalDateTime minSendTime = LocalDateTime.now().minusDays(MESSAGE_PRIVATE_PULL_MAX_DAYS); 201 + // 0. 拉取时间窗;超过窗口的老消息不再通过离线通道推送
  202 + LocalDateTime minSendTime = LocalDateTime.now().minusDays(imProperties.getMessage().getPrivatePullMaxDays());
198 203
199 // 根据 minId 和 minSendTime 拉取消息,避免 minId 恰好被发出后才拉取,导致漏消息 204 // 根据 minId 和 minSendTime 拉取消息,避免 minId 恰好被发出后才拉取,导致漏消息
200 List<ImPrivateMessageDO> messages = privateMessageMapper.selectListByMinId(userId, minId, minSendTime, size); 205 List<ImPrivateMessageDO> messages = privateMessageMapper.selectListByMinId(userId, minId, minSendTime, size);