Commit ae71b7134c5545d703a940c2d00a79459efa9588
1 parent
bed0a463
✨ feat(im): 初始化群申请 v0.2:第三把 review
Showing
5 changed files
with
71 additions
and
71 deletions
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java
| ... | ... | @@ -74,6 +74,10 @@ public enum ImMessageTypeEnum implements ArrayValuable<Integer> { |
| 74 | 74 | READ(2201, "已读", false, false), |
| 75 | 75 | |
| 76 | 76 | // ========== 好友通知(1201-1210 直接复用 OpenIM 段位编号) ========== |
| 77 | + // TODO @芋艿:FRIEND_REQUEST_* 与 GROUP_REQUEST_* 都是 persistent=false 的 SysMsg,离线 pull 拉不到, | |
| 78 | + // 目前可能丢失「实时 toast 提醒」体验(业务状态不丢,前端上线 fetch{Friend,Group}RequestList 能补回来); | |
| 79 | + // 未来思考下怎么优化:候选方案 1)改 persistent=true 入私聊消息流 + 让客户端按 type 自渲染; | |
| 80 | + // 2)服务端补一个「未读通知拉取」接口给前端冷启动调用。 | |
| 77 | 81 | /** |
| 78 | 82 | * 对应 OpenIM:FriendApplicationApprovedNotification 1201 |
| 79 | 83 | * 对应自己的类:FriendRequestApprovedNotification |
| ... | ... | @@ -148,7 +152,7 @@ public enum ImMessageTypeEnum implements ArrayValuable<Integer> { |
| 148 | 152 | GROUP_INFO_UPDATE(1502, "群信息变更", true, false), |
| 149 | 153 | /** |
| 150 | 154 | * 对应 OpenIM:sdkws.JoinGroupApplicationTips(JoinGroupApplicationNotification 1503) |
| 151 | - * 对应自己的类:GroupRequestNotification | |
| 155 | + * 对应自己的类:GroupRequestReceivedNotification | |
| 152 | 156 | * 场景:用户申请加群 / 普通成员邀请待审批,定向私聊推送给群主 + 全部管理员(多端同步);不入群消息流 |
| 153 | 157 | */ |
| 154 | 158 | GROUP_REQUEST_RECEIVED(1503, "收到新的入群申请", false, false), | ... | ... |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendRequestServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.im.service.friend; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.bean.BeanUtil; | |
| 4 | -import cn.hutool.core.bean.copier.CopyOptions; | |
| 5 | 3 | import cn.hutool.core.util.ObjUtil; |
| 4 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | |
| 6 | 5 | import cn.hutool.extra.spring.SpringUtil; |
| 7 | 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 8 | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| ... | ... | @@ -89,18 +88,22 @@ public class ImFriendRequestServiceImpl implements ImFriendRequestService { |
| 89 | 88 | } |
| 90 | 89 | |
| 91 | 90 | // 2. 落库:upsert 语义;同一对 (from, to) 唯一,已有记录覆盖申请理由 / 备注 / 来源 + 重置为未处理 + 清空旧处理痕迹 |
| 91 | + // null 字段(handleContent / handleTime)走 LambdaUpdateWrapper.set 显式清空,updateById 默认会忽略 null | |
| 92 | + // TODO @AI:看看是不是在 basemapperx 里,增加一个 updateXXXX;可以根据传递的 DO,深度更新的方法?应该匹配这个场景的对哇?【主要希望 service 不要出现 mapper 相关的类】 | |
| 92 | 93 | ImFriendRequestDO request = friendRequestMapper.selectByFromUserIdAndToUserId(fromUserId, toUserId); |
| 93 | 94 | if (request != null) { |
| 94 | - // TODO @AI:相同的放在一行里;然后 null 直接这样更新是清理不掉的;看看是不是在 basemapperx 里,增加一个 updateXXXX;可以根据传递的 DO,深度更新的方法?应该匹配这个场景的对哇? | |
| 95 | - ImFriendRequestDO updateObj = new ImFriendRequestDO() | |
| 96 | - .setApplyContent(reqVO.getApplyContent()) | |
| 97 | - .setDisplayName(reqVO.getDisplayName()) | |
| 95 | + friendRequestMapper.update(null, new LambdaUpdateWrapper<ImFriendRequestDO>() | |
| 96 | + .eq(ImFriendRequestDO::getId, request.getId()) | |
| 97 | + .set(ImFriendRequestDO::getApplyContent, reqVO.getApplyContent()) | |
| 98 | + .set(ImFriendRequestDO::getDisplayName, reqVO.getDisplayName()) | |
| 99 | + .set(ImFriendRequestDO::getAddSource, reqVO.getAddSource()) | |
| 100 | + .set(ImFriendRequestDO::getHandleResult, ImFriendRequestHandleResultEnum.UNHANDLED.getResult()) | |
| 101 | + .set(ImFriendRequestDO::getHandleContent, null) | |
| 102 | + .set(ImFriendRequestDO::getHandleTime, null)); | |
| 103 | + request.setApplyContent(reqVO.getApplyContent()).setDisplayName(reqVO.getDisplayName()) | |
| 98 | 104 | .setAddSource(reqVO.getAddSource()) |
| 99 | 105 | .setHandleResult(ImFriendRequestHandleResultEnum.UNHANDLED.getResult()) |
| 100 | 106 | .setHandleContent(null).setHandleTime(null); |
| 101 | - updateObj.setId(request.getId()); | |
| 102 | - friendRequestMapper.updateById(updateObj); | |
| 103 | - BeanUtil.copyProperties(updateObj, request, CopyOptions.create().setIgnoreNullValue(true)); | |
| 104 | 107 | } else { |
| 105 | 108 | request = BeanUtils.toBean(reqVO, ImFriendRequestDO.class) |
| 106 | 109 | .setFromUserId(fromUserId).setToUserId(toUserId) | ... | ... |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.im.service.group; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.bean.BeanUtil; | |
| 4 | -import cn.hutool.core.bean.copier.CopyOptions; | |
| 5 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | |
| 6 | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 7 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | 7 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| ... | ... | @@ -21,7 +20,7 @@ import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; |
| 21 | 20 | import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; |
| 22 | 21 | import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.BaseGroupNotification; |
| 23 | 22 | import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestApprovedNotification; |
| 24 | -import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestNotification; | |
| 23 | +import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestReceivedNotification; | |
| 25 | 24 | import cn.iocoder.yudao.module.im.service.websocket.dto.notification.group.GroupRequestRejectedNotification; |
| 26 | 25 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 27 | 26 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| ... | ... | @@ -36,6 +35,7 @@ import java.time.LocalDateTime; |
| 36 | 35 | import java.util.*; |
| 37 | 36 | |
| 38 | 37 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 38 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 39 | 39 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 40 | 40 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; |
| 41 | 41 | |
| ... | ... | @@ -95,17 +95,23 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 95 | 95 | |
| 96 | 96 | // 3. 情况二:群开启了审批;upsert 一条「主动申请」记录,inviterUserId=null |
| 97 | 97 | // 已有记录(无论之前是未处理 / 已同意 / 已拒绝),覆盖申请理由 + 来源 + 重置为未处理 + 清空旧处理痕迹 |
| 98 | + // null 字段(inviterUserId / handleUserId / handleContent / handleTime)走 LambdaUpdateWrapper.set 显式清空,updateById 默认会忽略 null | |
| 99 | + // TODO @AI:看看是不是在 basemapperx 里,增加一个 updateXXXX;可以根据传递的 DO,深度更新的方法?应该匹配这个场景的对哇?【主要希望 service 不要出现 mapper 相关的类】 | |
| 98 | 100 | ImGroupRequestDO request = groupRequestMapper.selectByGroupIdAndUserId(groupId, userId); |
| 99 | 101 | if (request != null) { |
| 100 | - // TODO @AI:相同的放在一行里;然后 null 直接这样更新是清理不掉的;看看是不是在 basemapperx 里,增加一个 updateXXXX;可以根据传递的 DO,深度更新的方法?应该匹配这个场景的对哇? | |
| 101 | - ImGroupRequestDO updateObj = new ImGroupRequestDO() | |
| 102 | - .setInviterUserId(null) | |
| 103 | - .setApplyContent(reqVO.getApplyContent()).setAddSource(reqVO.getAddSource()) | |
| 102 | + groupRequestMapper.update(null, new LambdaUpdateWrapper<ImGroupRequestDO>() | |
| 103 | + .eq(ImGroupRequestDO::getId, request.getId()) | |
| 104 | + .set(ImGroupRequestDO::getApplyContent, reqVO.getApplyContent()) | |
| 105 | + .set(ImGroupRequestDO::getAddSource, reqVO.getAddSource()) | |
| 106 | + .set(ImGroupRequestDO::getHandleResult, ImGroupRequestHandleResultEnum.UNHANDLED.getResult()) | |
| 107 | + .set(ImGroupRequestDO::getInviterUserId, null) | |
| 108 | + .set(ImGroupRequestDO::getHandleUserId, null) | |
| 109 | + .set(ImGroupRequestDO::getHandleContent, null) | |
| 110 | + .set(ImGroupRequestDO::getHandleTime, null)); | |
| 111 | + request.setApplyContent(reqVO.getApplyContent()).setAddSource(reqVO.getAddSource()) | |
| 104 | 112 | .setHandleResult(ImGroupRequestHandleResultEnum.UNHANDLED.getResult()) |
| 105 | - .setHandleUserId(null).setHandleContent(null).setHandleTime(null); | |
| 106 | - updateObj.setId(request.getId()); | |
| 107 | - groupRequestMapper.updateById(updateObj); | |
| 108 | - BeanUtil.copyProperties(updateObj, request, CopyOptions.create().setIgnoreNullValue(true)); | |
| 113 | + .setInviterUserId(null).setHandleUserId(null) | |
| 114 | + .setHandleContent(null).setHandleTime(null); | |
| 109 | 115 | } else { |
| 110 | 116 | request = BeanUtils.toBean(reqVO, ImGroupRequestDO.class) |
| 111 | 117 | .setUserId(userId).setInviterUserId(null) |
| ... | ... | @@ -115,9 +121,8 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 115 | 121 | |
| 116 | 122 | // 4. 1503 私聊定向推群主 + 全部管理员(多端同步);payload 携带申请方昵称 / 头像 |
| 117 | 123 | AdminUserRespDTO applyUser = adminUserApi.getUser(userId); |
| 118 | - GroupRequestNotification payload = buildRequestNotification(group, request, applyUser); | |
| 119 | - for (Long receiverUserId : listOwnerAndAdminUserIds(group)) { | |
| 120 | - // TODO @AI:能不能发群的,只发给群管理员;就是 groupMessageService;只是不 persist 呀。 | |
| 124 | + GroupRequestReceivedNotification payload = buildRequestNotification(group, request, applyUser); | |
| 125 | + for (Long receiverUserId : getGroupMemberListByOwnerAndAdminUserIds(group)) { | |
| 121 | 126 | websocketService.sendPrivateMessageAsync(receiverUserId, ImPrivateMessageDTO.ofGroupNotification( |
| 122 | 127 | ImMessageTypeEnum.GROUP_REQUEST_RECEIVED.getType(), userId, receiverUserId, payload)); |
| 123 | 128 | } |
| ... | ... | @@ -150,13 +155,9 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 150 | 155 | ImGroupMemberRoleEnum.NORMAL.getRole(), request.getAddSource(), request.getInviterUserId()); |
| 151 | 156 | |
| 152 | 157 | // 5.1 1505 私聊推送给申请人 + 群主 + 全部管理员(每端单推) |
| 153 | - // TODO @AI:同类属性,放在一行,减少行占用;其它位置也是! | |
| 154 | - GroupRequestApprovedNotification payload = (GroupRequestApprovedNotification) | |
| 155 | - new GroupRequestApprovedNotification() | |
| 156 | - .setRequestId(request.getId()) | |
| 157 | - .setGroupId(request.getGroupId()) | |
| 158 | - .setUserId(request.getUserId()) | |
| 159 | - .setOperatorUserId(userId); | |
| 158 | + GroupRequestApprovedNotification payload = (GroupRequestApprovedNotification) new GroupRequestApprovedNotification() | |
| 159 | + .setRequestId(request.getId()).setGroupId(request.getGroupId()).setUserId(request.getUserId()) | |
| 160 | + .setOperatorUserId(userId); | |
| 160 | 161 | broadcastToOwnerAdminsAndApplicant(request.getGroupId(), request.getUserId(), payload, |
| 161 | 162 | ImMessageTypeEnum.GROUP_REQUEST_APPROVED.getType(), userId); |
| 162 | 163 | // 5.2 群事件:主动申请 → 1510 自由进群;被邀请 → 1509 成员加入 |
| ... | ... | @@ -189,13 +190,9 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 189 | 190 | } |
| 190 | 191 | |
| 191 | 192 | // 3. 1506 私聊推送给申请人 + 群主 + 全部管理员 |
| 192 | - GroupRequestRejectedNotification payload = (GroupRequestRejectedNotification) | |
| 193 | - new GroupRequestRejectedNotification() | |
| 194 | - .setRequestId(request.getId()) | |
| 195 | - .setGroupId(request.getGroupId()) | |
| 196 | - .setUserId(request.getUserId()) | |
| 197 | - .setHandleContent(handleContent) | |
| 198 | - .setOperatorUserId(userId); | |
| 193 | + GroupRequestRejectedNotification payload = (GroupRequestRejectedNotification) new GroupRequestRejectedNotification() | |
| 194 | + .setRequestId(request.getId()).setGroupId(request.getGroupId()).setUserId(request.getUserId()) | |
| 195 | + .setHandleContent(handleContent).setOperatorUserId(userId); | |
| 199 | 196 | broadcastToOwnerAdminsAndApplicant(request.getGroupId(), request.getUserId(), payload, |
| 200 | 197 | ImMessageTypeEnum.GROUP_REQUEST_REJECTED.getType(), userId); |
| 201 | 198 | } |
| ... | ... | @@ -209,17 +206,19 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 209 | 206 | ImGroupDO group = groupService.validateGroupExists(groupId); |
| 210 | 207 | |
| 211 | 208 | // 1. 每个被邀请人 upsert 一条 inviter_user_id=邀请人 的记录 |
| 212 | - // 已有记录(同一对 group_id, user_id 唯一):覆盖 inviter_user_id + 重置 handle_result + 清空处理痕迹 | |
| 209 | + // 已有记录(同一对 group_id, user_id 唯一):覆盖 inviter_user_id + 重置 handle_result + 清空旧处理痕迹(走 LambdaUpdateWrapper.set 显式置 null) | |
| 213 | 210 | List<ImGroupRequestDO> requests = new ArrayList<>(invitedUserIds.size()); |
| 211 | + // TODO @AI:看看是不是在 basemapperx 里,增加一个 updateXXXX;可以根据传递的 DO,深度更新的方法?应该匹配这个场景的对哇?【主要希望 service 不要出现 mapper 相关的类】 | |
| 214 | 212 | for (Long invitedUserId : invitedUserIds) { |
| 215 | 213 | ImGroupRequestDO existing = groupRequestMapper.selectByGroupIdAndUserId(groupId, invitedUserId); |
| 216 | 214 | if (existing != null) { |
| 217 | - ImGroupRequestDO updateObj = new ImGroupRequestDO() | |
| 218 | - .setInviterUserId(inviterUserId) | |
| 219 | - .setHandleResult(ImGroupRequestHandleResultEnum.UNHANDLED.getResult()) | |
| 220 | - .setHandleUserId(null).setHandleContent(null).setHandleTime(null); | |
| 221 | - updateObj.setId(existing.getId()); | |
| 222 | - groupRequestMapper.updateById(updateObj); | |
| 215 | + groupRequestMapper.update(null, new LambdaUpdateWrapper<ImGroupRequestDO>() | |
| 216 | + .eq(ImGroupRequestDO::getId, existing.getId()) | |
| 217 | + .set(ImGroupRequestDO::getInviterUserId, inviterUserId) | |
| 218 | + .set(ImGroupRequestDO::getHandleResult, ImGroupRequestHandleResultEnum.UNHANDLED.getResult()) | |
| 219 | + .set(ImGroupRequestDO::getHandleUserId, null) | |
| 220 | + .set(ImGroupRequestDO::getHandleContent, null) | |
| 221 | + .set(ImGroupRequestDO::getHandleTime, null)); | |
| 223 | 222 | existing.setInviterUserId(inviterUserId) |
| 224 | 223 | .setHandleResult(ImGroupRequestHandleResultEnum.UNHANDLED.getResult()) |
| 225 | 224 | .setHandleUserId(null).setHandleContent(null).setHandleTime(null); |
| ... | ... | @@ -235,11 +234,10 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 235 | 234 | |
| 236 | 235 | // 2. 推 1503 给群主 + 全部管理员;多端同步;每条申请单独推一帧 |
| 237 | 236 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(invitedUserIds); |
| 238 | - List<Long> ownerAndAdmins = listOwnerAndAdminUserIds(group); | |
| 237 | + List<Long> ownerAndAdmins = getGroupMemberListByOwnerAndAdminUserIds(group); | |
| 239 | 238 | for (ImGroupRequestDO request : requests) { |
| 240 | 239 | AdminUserRespDTO applyUser = userMap.get(request.getUserId()); |
| 241 | - // TODO @AI:GroupRequestNotification 是不是要调整下命名?因为它是 RECEIVED 的,不然显得太公用了。 | |
| 242 | - GroupRequestNotification payload = buildRequestNotification(group, request, applyUser); | |
| 240 | + GroupRequestReceivedNotification payload = buildRequestNotification(group, request, applyUser); | |
| 243 | 241 | for (Long receiverUserId : ownerAndAdmins) { |
| 244 | 242 | websocketService.sendPrivateMessageAsync(receiverUserId, ImPrivateMessageDTO.ofGroupNotification( |
| 245 | 243 | ImMessageTypeEnum.GROUP_REQUEST_RECEIVED.getType(), inviterUserId, receiverUserId, payload)); |
| ... | ... | @@ -298,18 +296,14 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 298 | 296 | /** |
| 299 | 297 | * 构建 1503 通知 payload;聚合申请方昵称 / 头像供前端直接渲染 |
| 300 | 298 | */ |
| 301 | - private GroupRequestNotification buildRequestNotification(ImGroupDO group, ImGroupRequestDO request, | |
| 302 | - AdminUserRespDTO applyUser) { | |
| 303 | - // TODO @AI:看看能不能链式调用;同类属性,相同行; | |
| 304 | - GroupRequestNotification payload = (GroupRequestNotification) new GroupRequestNotification() | |
| 305 | - .setRequestId(request.getId()) | |
| 306 | - .setGroupId(group.getId()) | |
| 307 | - .setUserId(request.getUserId()) | |
| 299 | + private GroupRequestReceivedNotification buildRequestNotification(ImGroupDO group, ImGroupRequestDO request, | |
| 300 | + AdminUserRespDTO applyUser) { | |
| 301 | + Long operatorUserId = request.getInviterUserId() != null ? request.getInviterUserId() : request.getUserId(); | |
| 302 | + GroupRequestReceivedNotification payload = (GroupRequestReceivedNotification) new GroupRequestReceivedNotification() | |
| 303 | + .setRequestId(request.getId()).setGroupId(group.getId()).setUserId(request.getUserId()) | |
| 308 | 304 | .setInviterUserId(request.getInviterUserId()) |
| 309 | - .setApplyContent(request.getApplyContent()) | |
| 310 | - .setAddSource(request.getAddSource()) | |
| 311 | - .setOperatorUserId(request.getInviterUserId() != null | |
| 312 | - ? request.getInviterUserId() : request.getUserId()); | |
| 305 | + .setApplyContent(request.getApplyContent()).setAddSource(request.getAddSource()) | |
| 306 | + .setOperatorUserId(operatorUserId); | |
| 313 | 307 | if (applyUser != null) { |
| 314 | 308 | payload.setUserNickname(applyUser.getNickname()).setUserAvatar(applyUser.getAvatar()); |
| 315 | 309 | } |
| ... | ... | @@ -325,7 +319,7 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 325 | 319 | if (group == null) { |
| 326 | 320 | return; |
| 327 | 321 | } |
| 328 | - Set<Long> receivers = new LinkedHashSet<>(listOwnerAndAdminUserIds(group)); | |
| 322 | + Set<Long> receivers = new LinkedHashSet<>(getGroupMemberListByOwnerAndAdminUserIds(group)); | |
| 329 | 323 | receivers.add(applicantUserId); |
| 330 | 324 | for (Long receiverUserId : receivers) { |
| 331 | 325 | websocketService.sendPrivateMessageAsync(receiverUserId, ImPrivateMessageDTO.ofGroupNotification( |
| ... | ... | @@ -334,16 +328,14 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { |
| 334 | 328 | } |
| 335 | 329 | |
| 336 | 330 | /** |
| 337 | - * 列出群主 + 全部管理员的用户编号;以 group.ownerUserId 兜底,避免 group_member 表里 owner 角色记录异常缺失 | |
| 331 | + * 列出群主 + 全部管理员的用户编号 | |
| 332 | + * | |
| 333 | + * @param group 群信息 | |
| 334 | + * @return 群主 + 全部管理员的用户编号列表 | |
| 338 | 335 | */ |
| 339 | - // TODO @AI:有点过度设计了,直接 convertset 群成员即可! | |
| 340 | - private List<Long> listOwnerAndAdminUserIds(ImGroupDO group) { | |
| 341 | - Set<Long> set = new LinkedHashSet<>(); | |
| 342 | - set.add(group.getOwnerUserId()); | |
| 343 | - for (ImGroupMemberDO member : groupMemberService.getGroupMemberListByOwnerAndAdmin(group.getId())) { | |
| 344 | - set.add(member.getUserId()); | |
| 345 | - } | |
| 346 | - return new ArrayList<>(set); | |
| 336 | + private List<Long> getGroupMemberListByOwnerAndAdminUserIds(ImGroupDO group) { | |
| 337 | + return convertList(groupMemberService.getGroupMemberListByOwnerAndAdmin(group.getId()), | |
| 338 | + ImGroupMemberDO::getUserId); | |
| 347 | 339 | } |
| 348 | 340 | |
| 349 | 341 | } | ... | ... |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestNotification.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/notification/group/GroupRequestReceivedNotification.java
| ... | ... | @@ -10,7 +10,7 @@ import lombok.EqualsAndHashCode; |
| 10 | 10 | */ |
| 11 | 11 | @EqualsAndHashCode(callSuper = true) |
| 12 | 12 | @Data |
| 13 | -public class GroupRequestNotification extends BaseGroupNotification { | |
| 13 | +public class GroupRequestReceivedNotification extends BaseGroupNotification { | |
| 14 | 14 | |
| 15 | 15 | /** |
| 16 | 16 | * 申请记录编号 | ... | ... |
yudao-module-im/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -194,5 +194,6 @@ CREATE TABLE IF NOT EXISTS "im_face_user_item" ( |
| 194 | 194 | "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 195 | 195 | "deleted" bit NOT NULL DEFAULT FALSE, |
| 196 | 196 | "tenant_id" bigint NOT NULL DEFAULT 0, |
| 197 | - PRIMARY KEY ("id") | |
| 197 | + PRIMARY KEY ("id"), | |
| 198 | + CONSTRAINT "uk_im_face_user_item_user_url" UNIQUE ("user_id", "url", "tenant_id") | |
| 198 | 199 | ) COMMENT 'IM 用户私有表情表'; | ... | ... |