Commit b814a87361ce5a49c3757b89c755b30f78efa220
1 parent
ea29dea4
✨ feat(group): 添加群成员管理功能
实现群成员的邀请、退出和移除功能,支持群主对成员的管理操作。新增相关提示信息和错误码,优化群成员更新逻辑,确保群主无法退出群聊。 BREAKING CHANGE: 群解散相关逻辑已调整为群删除,更新了相关消息推送类型
Showing
13 changed files
with
202 additions
and
170 deletions
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java
| @@ -35,6 +35,8 @@ public interface ErrorCodeConstants { | @@ -35,6 +35,8 @@ public interface ErrorCodeConstants { | ||
| 35 | ErrorCode GROUP_MEMBER_NOT_EXISTS = new ErrorCode(1_040_500_000, "群成员不存在"); | 35 | ErrorCode GROUP_MEMBER_NOT_EXISTS = new ErrorCode(1_040_500_000, "群成员不存在"); |
| 36 | ErrorCode GROUP_MEMBER_NOT_IN_GROUP = new ErrorCode(1_040_500_001, "您已不在该群中"); | 36 | ErrorCode GROUP_MEMBER_NOT_IN_GROUP = new ErrorCode(1_040_500_001, "您已不在该群中"); |
| 37 | ErrorCode GROUP_MEMBER_ALREADY_QUIT = new ErrorCode(1_040_500_002, "您已退出该群"); | 37 | ErrorCode GROUP_MEMBER_ALREADY_QUIT = new ErrorCode(1_040_500_002, "您已退出该群"); |
| 38 | + ErrorCode GROUP_OWNER_CANNOT_QUIT = new ErrorCode(1_040_500_003, "您是群主,不可退出群聊"); | ||
| 39 | + ErrorCode GROUP_CANNOT_REMOVE_SELF = new ErrorCode(1_040_500_004, "不能移除自己"); | ||
| 38 | 40 | ||
| 39 | // ========== 好友 (1-040-600-000) ========== | 41 | // ========== 好友 (1-040-600-000) ========== |
| 40 | ErrorCode FRIEND_NOT_EXISTS = new ErrorCode(1_040_600_000, "好友关系不存在"); | 42 | ErrorCode FRIEND_NOT_EXISTS = new ErrorCode(1_040_600_000, "好友关系不存在"); |
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ImCommonConstants.java
| @@ -51,5 +51,13 @@ public interface ImCommonConstants { | @@ -51,5 +51,13 @@ public interface ImCommonConstants { | ||
| 51 | * 群解散系统提示 | 51 | * 群解散系统提示 |
| 52 | */ | 52 | */ |
| 53 | String GROUP_DISSOLVE_TIP_MESSAGE = "'{}'解散了群聊"; | 53 | String GROUP_DISSOLVE_TIP_MESSAGE = "'{}'解散了群聊"; |
| 54 | + /** | ||
| 55 | + * 退群系统提示 | ||
| 56 | + */ | ||
| 57 | + String GROUP_QUIT_TIP_MESSAGE = "您已退出群聊"; | ||
| 58 | + /** | ||
| 59 | + * 踢出群系统提示 | ||
| 60 | + */ | ||
| 61 | + String GROUP_REMOVE_TIP_MESSAGE = "您已被移出群聊"; | ||
| 54 | 62 | ||
| 55 | } | 63 | } |
yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/message/ImMessageTypeEnum.java
| @@ -34,7 +34,7 @@ public enum ImMessageTypeEnum implements ArrayValuable<Integer> { | @@ -34,7 +34,7 @@ public enum ImMessageTypeEnum implements ArrayValuable<Integer> { | ||
| 34 | 34 | ||
| 35 | GROUP_CREATE(200, "群创建"), // 暂无 | 35 | GROUP_CREATE(200, "群创建"), // 暂无 |
| 36 | GROUP_UPDATE(201, "群信息变更"), // 暂无 | 36 | GROUP_UPDATE(201, "群信息变更"), // 暂无 |
| 37 | - GROUP_DISSOLVE(202, "群解散"); // 暂无 | 37 | + GROUP_DELETE(202, "群删除"); // 暂无(解散/退群/踢出均用此类型) |
| 38 | 38 | ||
| 39 | public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImMessageTypeEnum::getType).toArray(Integer[]::new); | 39 | public static final Integer[] ARRAYS = Arrays.stream(values()).map(ImMessageTypeEnum::getType).toArray(Integer[]::new); |
| 40 | 40 |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java
| @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupCreateReqVO; | 5 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupCreateReqVO; |
| 6 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupRespVO; | 6 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupRespVO; |
| 7 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupUpdateReqVO; | 7 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupUpdateReqVO; |
| 8 | +import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberInviteReqVO; | ||
| 8 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; | 9 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; |
| 9 | import cn.iocoder.yudao.module.im.service.group.ImGroupService; | 10 | import cn.iocoder.yudao.module.im.service.group.ImGroupService; |
| 10 | import io.swagger.v3.oas.annotations.Operation; | 11 | import io.swagger.v3.oas.annotations.Operation; |
| @@ -30,6 +31,8 @@ public class ImGroupController { | @@ -30,6 +31,8 @@ public class ImGroupController { | ||
| 30 | @Resource | 31 | @Resource |
| 31 | private ImGroupService imGroupService; | 32 | private ImGroupService imGroupService; |
| 32 | 33 | ||
| 34 | + // ==================== 群的写操作 ==================== | ||
| 35 | + | ||
| 33 | @PostMapping("/create") | 36 | @PostMapping("/create") |
| 34 | @Operation(summary = "创建群") | 37 | @Operation(summary = "创建群") |
| 35 | @PreAuthorize("@ss.hasPermission('im:group:create')") | 38 | @PreAuthorize("@ss.hasPermission('im:group:create')") |
| @@ -55,6 +58,8 @@ public class ImGroupController { | @@ -55,6 +58,8 @@ public class ImGroupController { | ||
| 55 | return success(true); | 58 | return success(true); |
| 56 | } | 59 | } |
| 57 | 60 | ||
| 61 | + // ==================== 群的读操作 ==================== | ||
| 62 | + | ||
| 58 | @GetMapping("/get") | 63 | @GetMapping("/get") |
| 59 | @Operation(summary = "获得群") | 64 | @Operation(summary = "获得群") |
| 60 | @Parameter(name = "id", description = "编号", required = true, example = "1024") | 65 | @Parameter(name = "id", description = "编号", required = true, example = "1024") |
| @@ -71,4 +76,31 @@ public class ImGroupController { | @@ -71,4 +76,31 @@ public class ImGroupController { | ||
| 71 | return success(BeanUtils.toBean(groups, ImGroupRespVO.class)); | 76 | return success(BeanUtils.toBean(groups, ImGroupRespVO.class)); |
| 72 | } | 77 | } |
| 73 | 78 | ||
| 79 | + // ==================== 群成员的写操作 ==================== | ||
| 80 | + | ||
| 81 | + @PostMapping("/invite") | ||
| 82 | + @Operation(summary = "邀请用户加入群") | ||
| 83 | + @PreAuthorize("@ss.hasPermission('im:group:update')") | ||
| 84 | + public CommonResult<Long> inviteGroupMember(@Valid @RequestBody ImGroupMemberInviteReqVO inviteReqVO) { | ||
| 85 | + return success(imGroupService.inviteGroupMember(getLoginUserId(), inviteReqVO)); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + @DeleteMapping("/quit") | ||
| 89 | + @Operation(summary = "退出群") | ||
| 90 | + @Parameter(name = "groupId", description = "群编号", required = true) | ||
| 91 | + @PreAuthorize("@ss.hasPermission('im:group:update')") | ||
| 92 | + public CommonResult<Boolean> quitGroup(@RequestParam("groupId") Long groupId) { | ||
| 93 | + imGroupService.quitGroup(groupId, getLoginUserId()); | ||
| 94 | + return success(true); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + @DeleteMapping("/kicking") | ||
| 98 | + @Operation(summary = "移除群成员") | ||
| 99 | + @PreAuthorize("@ss.hasPermission('im:group:update')") | ||
| 100 | + public CommonResult<Boolean> removeGroupMember(@RequestParam("groupId") Long groupId, | ||
| 101 | + @RequestParam("memberUserId") Long memberUserId) { | ||
| 102 | + imGroupService.removeGroupMember(groupId, memberUserId, getLoginUserId()); | ||
| 103 | + return success(true); | ||
| 104 | + } | ||
| 105 | + | ||
| 74 | } | 106 | } |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupMemberController.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.im.controller.admin.group; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.im.controller.admin.group; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | 4 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 6 | -import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberInviteReqVO; | ||
| 7 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberRespVO; | 6 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberRespVO; |
| 8 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; | 7 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; |
| 9 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; | 8 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; |
| @@ -24,6 +23,7 @@ import java.util.Map; | @@ -24,6 +23,7 @@ import java.util.Map; | ||
| 24 | 23 | ||
| 25 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 24 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 26 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 25 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 26 | +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; | ||
| 27 | 27 | ||
| 28 | @Tag(name = "管理后台 - 群成员") | 28 | @Tag(name = "管理后台 - 群成员") |
| 29 | @RestController | 29 | @RestController |
| @@ -32,32 +32,16 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | @@ -32,32 +32,16 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | ||
| 32 | public class ImGroupMemberController { | 32 | public class ImGroupMemberController { |
| 33 | 33 | ||
| 34 | @Resource | 34 | @Resource |
| 35 | - private ImGroupMemberService imGroupMemberService; | 35 | + private ImGroupMemberService groupMemberService; |
| 36 | 36 | ||
| 37 | @Resource | 37 | @Resource |
| 38 | private AdminUserApi adminUserApi; | 38 | private AdminUserApi adminUserApi; |
| 39 | 39 | ||
| 40 | - @PostMapping("/invite") | ||
| 41 | - @Operation(summary = "邀请用户加入群") | ||
| 42 | - @PreAuthorize("@ss.hasPermission('im:group-member:create')") | ||
| 43 | - public CommonResult<Long> inviteGroupMember(@Valid @RequestBody ImGroupMemberInviteReqVO inviteReqVO) { | ||
| 44 | - return success(imGroupMemberService.inviteGroupMember(inviteReqVO)); | ||
| 45 | - } | ||
| 46 | - | ||
| 47 | @PutMapping("/update") | 40 | @PutMapping("/update") |
| 48 | @Operation(summary = "更新群成员") | 41 | @Operation(summary = "更新群成员") |
| 49 | @PreAuthorize("@ss.hasPermission('im:group-member:update')") | 42 | @PreAuthorize("@ss.hasPermission('im:group-member:update')") |
| 50 | public CommonResult<Boolean> updateGroupMember(@Valid @RequestBody ImGroupMemberUpdateReqVO updateReqVO) { | 43 | public CommonResult<Boolean> updateGroupMember(@Valid @RequestBody ImGroupMemberUpdateReqVO updateReqVO) { |
| 51 | - imGroupMemberService.updateGroupMember(updateReqVO); | ||
| 52 | - return success(true); | ||
| 53 | - } | ||
| 54 | - | ||
| 55 | - @DeleteMapping("/remove") | ||
| 56 | - @Operation(summary = "移除群成员(踢人)") | ||
| 57 | - @Parameter(name = "id", description = "群成员编号", required = true) | ||
| 58 | - @PreAuthorize("@ss.hasPermission('im:group-member:delete')") | ||
| 59 | - public CommonResult<Boolean> removeGroupMember(@RequestParam("id") Long id) { | ||
| 60 | - imGroupMemberService.removeGroupMember(id); | 44 | + groupMemberService.updateGroupMember(getLoginUserId(), updateReqVO); |
| 61 | return success(true); | 45 | return success(true); |
| 62 | } | 46 | } |
| 63 | 47 | ||
| @@ -66,7 +50,7 @@ public class ImGroupMemberController { | @@ -66,7 +50,7 @@ public class ImGroupMemberController { | ||
| 66 | @Parameter(name = "id", description = "编号", required = true, example = "1024") | 50 | @Parameter(name = "id", description = "编号", required = true, example = "1024") |
| 67 | @PreAuthorize("@ss.hasPermission('im:group-member:query')") | 51 | @PreAuthorize("@ss.hasPermission('im:group-member:query')") |
| 68 | public CommonResult<ImGroupMemberRespVO> getGroupMember(@RequestParam("id") Long id) { | 52 | public CommonResult<ImGroupMemberRespVO> getGroupMember(@RequestParam("id") Long id) { |
| 69 | - ImGroupMemberDO groupMember = imGroupMemberService.getGroupMember(id); | 53 | + ImGroupMemberDO groupMember = groupMemberService.getGroupMember(id); |
| 70 | return success(BeanUtils.toBean(groupMember, ImGroupMemberRespVO.class)); | 54 | return success(BeanUtils.toBean(groupMember, ImGroupMemberRespVO.class)); |
| 71 | } | 55 | } |
| 72 | 56 | ||
| @@ -74,7 +58,7 @@ public class ImGroupMemberController { | @@ -74,7 +58,7 @@ public class ImGroupMemberController { | ||
| 74 | @Operation(summary = "获得指定群的成员列表") | 58 | @Operation(summary = "获得指定群的成员列表") |
| 75 | @Parameter(name = "groupId", description = "群编号", required = true, example = "1024") | 59 | @Parameter(name = "groupId", description = "群编号", required = true, example = "1024") |
| 76 | public CommonResult<List<ImGroupMemberRespVO>> getGroupMemberList(@RequestParam("groupId") Long groupId) { | 60 | public CommonResult<List<ImGroupMemberRespVO>> getGroupMemberList(@RequestParam("groupId") Long groupId) { |
| 77 | - List<ImGroupMemberDO> members = imGroupMemberService.getGroupMemberListByGroupId(groupId); | 61 | + List<ImGroupMemberDO> members = groupMemberService.getGroupMemberListByGroupId(groupId); |
| 78 | // 批量聚合 AdminUser 信息(昵称 / 头像) | 62 | // 批量聚合 AdminUser 信息(昵称 / 头像) |
| 79 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | 63 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( |
| 80 | convertList(members, ImGroupMemberDO::getUserId)); | 64 | convertList(members, ImGroupMemberDO::getUserId)); |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/member/ImGroupMemberPageReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.im.controller.admin.group.vo.member; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | -import lombok.Data; | ||
| 6 | -import lombok.EqualsAndHashCode; | ||
| 7 | -import lombok.ToString; | ||
| 8 | -import org.springframework.format.annotation.DateTimeFormat; | ||
| 9 | - | ||
| 10 | -import java.time.LocalDateTime; | ||
| 11 | - | ||
| 12 | -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 13 | - | ||
| 14 | -@Schema(description = "管理后台 - 群成员分页 Request VO") | ||
| 15 | -@Data | ||
| 16 | -@EqualsAndHashCode(callSuper = true) | ||
| 17 | -@ToString(callSuper = true) | ||
| 18 | -public class ImGroupMemberPageReqVO extends PageParam { | ||
| 19 | - | ||
| 20 | - @Schema(description = "群编号", example = "13279") | ||
| 21 | - private Long groupId; | ||
| 22 | - | ||
| 23 | - @Schema(description = "用户编号", example = "21730") | ||
| 24 | - private Long userId; | ||
| 25 | - | ||
| 26 | - @Schema(description = "成员状态", example = "0") | ||
| 27 | - private Integer status; | ||
| 28 | - | ||
| 29 | - @Schema(description = "创建时间") | ||
| 30 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 31 | - private LocalDateTime[] createTime; | ||
| 32 | - | ||
| 33 | -} | ||
| 34 | \ No newline at end of file | 0 | \ No newline at end of file |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/member/ImGroupMemberSaveReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.im.controller.admin.group.vo.member; | ||
| 2 | - | ||
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | -import jakarta.validation.constraints.NotNull; | ||
| 5 | -import lombok.Data; | ||
| 6 | - | ||
| 7 | -@Schema(description = "管理后台 - 群成员新增/修改 Request VO") | ||
| 8 | -@Data | ||
| 9 | -public class ImGroupMemberSaveReqVO { | ||
| 10 | - | ||
| 11 | - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17071") | ||
| 12 | - private Long id; | ||
| 13 | - | ||
| 14 | - @Schema(description = "群编号", example = "13279") | ||
| 15 | - private Long groupId; | ||
| 16 | - | ||
| 17 | - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21730") | ||
| 18 | - @NotNull(message = "用户编号不能为空") | ||
| 19 | - private Long userId; | ||
| 20 | - | ||
| 21 | - @Schema(description = "是否免打扰") | ||
| 22 | - private Boolean muted; | ||
| 23 | - | ||
| 24 | -} | ||
| 25 | \ No newline at end of file | 0 | \ No newline at end of file |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/member/ImGroupMemberUpdateReqVO.java
| @@ -3,14 +3,22 @@ package cn.iocoder.yudao.module.im.controller.admin.group.vo.member; | @@ -3,14 +3,22 @@ package cn.iocoder.yudao.module.im.controller.admin.group.vo.member; | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import jakarta.validation.constraints.NotNull; | 4 | import jakarta.validation.constraints.NotNull; |
| 5 | import lombok.Data; | 5 | import lombok.Data; |
| 6 | +import lombok.experimental.Accessors; | ||
| 6 | 7 | ||
| 7 | @Schema(description = "管理后台 - 群成员更新 Request VO") | 8 | @Schema(description = "管理后台 - 群成员更新 Request VO") |
| 8 | @Data | 9 | @Data |
| 10 | +@Accessors(chain = true) | ||
| 9 | public class ImGroupMemberUpdateReqVO { | 11 | public class ImGroupMemberUpdateReqVO { |
| 10 | 12 | ||
| 11 | - @Schema(description = "群成员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17071") | ||
| 12 | - @NotNull(message = "群成员编号不能为空") | ||
| 13 | - private Long id; | 13 | + @Schema(description = "群编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 14 | + @NotNull(message = "群编号不能为空") | ||
| 15 | + private Long groupId; | ||
| 16 | + | ||
| 17 | + @Schema(description = "群内昵称", example = "芋头") | ||
| 18 | + private String displayUserName; | ||
| 19 | + | ||
| 20 | + @Schema(description = "群名备注", example = "公司群") | ||
| 21 | + private String displayGroupName; | ||
| 14 | 22 | ||
| 15 | @Schema(description = "是否免打扰") | 23 | @Schema(description = "是否免打扰") |
| 16 | private Boolean muted; | 24 | private Boolean muted; |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java
| 1 | package cn.iocoder.yudao.module.im.service.group; | 1 | package cn.iocoder.yudao.module.im.service.group; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberInviteReqVO; | ||
| 4 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; | 3 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; |
| 5 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; | 4 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; |
| 6 | import jakarta.validation.Valid; | 5 | import jakarta.validation.Valid; |
| @@ -16,28 +15,6 @@ import java.util.List; | @@ -16,28 +15,6 @@ import java.util.List; | ||
| 16 | public interface ImGroupMemberService { | 15 | public interface ImGroupMemberService { |
| 17 | 16 | ||
| 18 | /** | 17 | /** |
| 19 | - * 邀请用户加入群 | ||
| 20 | - * | ||
| 21 | - * @param inviteReqVO 邀请信息 | ||
| 22 | - * @return 编号 | ||
| 23 | - */ | ||
| 24 | - Long inviteGroupMember(@Valid ImGroupMemberInviteReqVO inviteReqVO); | ||
| 25 | - | ||
| 26 | - /** | ||
| 27 | - * 更新群成员信息 | ||
| 28 | - * | ||
| 29 | - * @param updateReqVO 更新信息 | ||
| 30 | - */ | ||
| 31 | - void updateGroupMember(@Valid ImGroupMemberUpdateReqVO updateReqVO); | ||
| 32 | - | ||
| 33 | - /** | ||
| 34 | - * 删除群成员 | ||
| 35 | - * | ||
| 36 | - * @param id 编号 | ||
| 37 | - */ | ||
| 38 | - void removeGroupMember(Long id); | ||
| 39 | - | ||
| 40 | - /** | ||
| 41 | * 获得群成员 | 18 | * 获得群成员 |
| 42 | * | 19 | * |
| 43 | * @param id 编号 | 20 | * @param id 编号 |
| @@ -101,17 +78,24 @@ public interface ImGroupMemberService { | @@ -101,17 +78,24 @@ public interface ImGroupMemberService { | ||
| 101 | ImGroupMemberDO validateMemberInGroup(Long groupId, Long userId); | 78 | ImGroupMemberDO validateMemberInGroup(Long groupId, Long userId); |
| 102 | 79 | ||
| 103 | /** | 80 | /** |
| 104 | - * 更新群成员的展示信息(群内昵称、群名备注) | 81 | + * 更新群成员信息(群内昵称、群名备注、免打扰等) |
| 105 | * <p> | 82 | * <p> |
| 106 | * 内部会校验用户是否为群的有效成员 | 83 | * 内部会校验用户是否为群的有效成员 |
| 107 | * | 84 | * |
| 108 | - * @param groupId 群编号 | ||
| 109 | - * @param userId 用户编号 | ||
| 110 | - * @param displayUserName 群内昵称(null 则不更新) | ||
| 111 | - * @param displayGroupName 群名备注(null 则不更新) | 85 | + * @param userId 当前登录用户编号 |
| 86 | + * @param updateReqVO 更新信息 | ||
| 87 | + */ | ||
| 88 | + void updateGroupMember(Long userId, @Valid ImGroupMemberUpdateReqVO updateReqVO); | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * 移除指定群成员(设置为 DISABLE 状态) | ||
| 92 | + * <p> | ||
| 93 | + * 用于退群、踢出场景 | ||
| 94 | + * | ||
| 95 | + * @param groupId 群编号 | ||
| 96 | + * @param userId 用户编号 | ||
| 112 | */ | 97 | */ |
| 113 | - void updateGroupMember(Long groupId, Long userId, | ||
| 114 | - String displayUserName, String displayGroupName); | 98 | + void removeGroupMember(Long groupId, Long userId); |
| 115 | 99 | ||
| 116 | /** | 100 | /** |
| 117 | * 移除群的全部成员(设置为 DISABLE 状态) | 101 | * 移除群的全部成员(设置为 DISABLE 状态) |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.im.service.group; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.im.service.group; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 5 | -import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberInviteReqVO; | ||
| 6 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; | 5 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; | 6 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; |
| 8 | import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMemberMapper; | 7 | import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMemberMapper; |
| @@ -14,7 +13,6 @@ import java.time.LocalDateTime; | @@ -14,7 +13,6 @@ import java.time.LocalDateTime; | ||
| 14 | import java.util.List; | 13 | import java.util.List; |
| 15 | 14 | ||
| 16 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 15 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 17 | -import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.GROUP_MEMBER_NOT_EXISTS; | ||
| 18 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.GROUP_MEMBER_NOT_IN_GROUP; | 16 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.GROUP_MEMBER_NOT_IN_GROUP; |
| 19 | 17 | ||
| 20 | /** | 18 | /** |
| @@ -30,43 +28,6 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService { | @@ -30,43 +28,6 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService { | ||
| 30 | private ImGroupMemberMapper imGroupMemberMapper; | 28 | private ImGroupMemberMapper imGroupMemberMapper; |
| 31 | 29 | ||
| 32 | @Override | 30 | @Override |
| 33 | - public Long inviteGroupMember(ImGroupMemberInviteReqVO inviteReqVO) { | ||
| 34 | - // TODO @AI:需要群主校验下; | ||
| 35 | - // 插入 | ||
| 36 | - ImGroupMemberDO groupMember = BeanUtils.toBean(inviteReqVO, ImGroupMemberDO.class); | ||
| 37 | - // TODO @AI:默认字段的设置; | ||
| 38 | - imGroupMemberMapper.insert(groupMember); | ||
| 39 | - // TODO @AI:或者调用内部的 createGroupMember 方法,设置默认字段的值; | ||
| 40 | - // 返回 | ||
| 41 | - return groupMember.getId(); | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | - @Override | ||
| 45 | - public void updateGroupMember(ImGroupMemberUpdateReqVO updateReqVO) { | ||
| 46 | - // 校验存在 | ||
| 47 | - validateGroupMemberExists(updateReqVO.getId()); | ||
| 48 | - // 更新 | ||
| 49 | - ImGroupMemberDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupMemberDO.class); | ||
| 50 | - imGroupMemberMapper.updateById(updateObj); | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - @Override | ||
| 54 | - public void removeGroupMember(Long id) { | ||
| 55 | - // TODO @AI:需要群主校验下; | ||
| 56 | - // 校验存在 | ||
| 57 | - validateGroupMemberExists(id); | ||
| 58 | - | ||
| 59 | - // 删除 | ||
| 60 | - imGroupMemberMapper.deleteById(id); | ||
| 61 | - } | ||
| 62 | - | ||
| 63 | - private void validateGroupMemberExists(Long id) { | ||
| 64 | - if (imGroupMemberMapper.selectById(id) == null) { | ||
| 65 | - throw exception(GROUP_MEMBER_NOT_EXISTS); | ||
| 66 | - } | ||
| 67 | - } | ||
| 68 | - | ||
| 69 | - @Override | ||
| 70 | public ImGroupMemberDO getGroupMember(Long id) { | 31 | public ImGroupMemberDO getGroupMember(Long id) { |
| 71 | return imGroupMemberMapper.selectById(id); | 32 | return imGroupMemberMapper.selectById(id); |
| 72 | } | 33 | } |
| @@ -96,7 +57,6 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService { | @@ -96,7 +57,6 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService { | ||
| 96 | ImGroupMemberDO member = new ImGroupMemberDO() | 57 | ImGroupMemberDO member = new ImGroupMemberDO() |
| 97 | .setGroupId(groupId).setUserId(userId) | 58 | .setGroupId(groupId).setUserId(userId) |
| 98 | .setStatus(CommonStatusEnum.ENABLE.getStatus()).setJoinTime(LocalDateTime.now()); | 59 | .setStatus(CommonStatusEnum.ENABLE.getStatus()).setJoinTime(LocalDateTime.now()); |
| 99 | - // TODO @AI:要不要有个 initXXX 方法,设置默认字段的值; | ||
| 100 | imGroupMemberMapper.insert(member); | 60 | imGroupMemberMapper.insert(member); |
| 101 | return member; | 61 | return member; |
| 102 | } | 62 | } |
| @@ -111,15 +71,23 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService { | @@ -111,15 +71,23 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService { | ||
| 111 | } | 71 | } |
| 112 | 72 | ||
| 113 | @Override | 73 | @Override |
| 114 | - public void updateGroupMember(Long groupId, Long userId, String displayUserName, String displayGroupName) { | 74 | + public void updateGroupMember(Long userId, ImGroupMemberUpdateReqVO updateReqVO) { |
| 115 | // 1. 校验是群的有效成员 | 75 | // 1. 校验是群的有效成员 |
| 116 | - ImGroupMemberDO member = validateMemberInGroup(groupId, userId); | 76 | + ImGroupMemberDO member = validateMemberInGroup(updateReqVO.getGroupId(), userId); |
| 77 | + // 2. 更新群成员信息 | ||
| 78 | + ImGroupMemberDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupMemberDO.class) | ||
| 79 | + .setId(member.getId()); | ||
| 80 | + imGroupMemberMapper.updateById(updateObj); | ||
| 81 | + } | ||
| 117 | 82 | ||
| 118 | - // 2. 更新展示信息 | 83 | + @Override |
| 84 | + public void removeGroupMember(Long groupId, Long userId) { | ||
| 85 | + // 1. 校验是群的有效成员 | ||
| 86 | + ImGroupMemberDO member = validateMemberInGroup(groupId, userId); | ||
| 87 | + // 2. 更新为退群状态 | ||
| 119 | imGroupMemberMapper.updateById(new ImGroupMemberDO().setId(member.getId()) | 88 | imGroupMemberMapper.updateById(new ImGroupMemberDO().setId(member.getId()) |
| 120 | - .setDisplayUserName(displayUserName).setDisplayGroupName(displayGroupName)); | ||
| 121 | - | ||
| 122 | - // TODO @AI:需要分析下,是否需要 | 89 | + .setStatus(CommonStatusEnum.DISABLE.getStatus()) |
| 90 | + .setQuitTime(LocalDateTime.now())); | ||
| 123 | } | 91 | } |
| 124 | 92 | ||
| 125 | @Override | 93 | @Override |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.im.service.group; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.im.service.group; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupCreateReqVO; | 3 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupCreateReqVO; |
| 4 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupUpdateReqVO; | 4 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupUpdateReqVO; |
| 5 | +import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberInviteReqVO; | ||
| 5 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; | 6 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; |
| 6 | import jakarta.validation.Valid; | 7 | import jakarta.validation.Valid; |
| 7 | 8 | ||
| @@ -14,6 +15,8 @@ import java.util.List; | @@ -14,6 +15,8 @@ import java.util.List; | ||
| 14 | */ | 15 | */ |
| 15 | public interface ImGroupService { | 16 | public interface ImGroupService { |
| 16 | 17 | ||
| 18 | + // ==================== 群的写操作 ==================== | ||
| 19 | + | ||
| 17 | /** | 20 | /** |
| 18 | * 创建群 | 21 | * 创建群 |
| 19 | * <p> | 22 | * <p> |
| @@ -44,6 +47,8 @@ public interface ImGroupService { | @@ -44,6 +47,8 @@ public interface ImGroupService { | ||
| 44 | */ | 47 | */ |
| 45 | void dissolveGroup(Long id, Long userId); | 48 | void dissolveGroup(Long id, Long userId); |
| 46 | 49 | ||
| 50 | + // ==================== 群的读操作 ==================== | ||
| 51 | + | ||
| 47 | /** | 52 | /** |
| 48 | * 获得群 | 53 | * 获得群 |
| 49 | * | 54 | * |
| @@ -80,4 +85,40 @@ public interface ImGroupService { | @@ -80,4 +85,40 @@ public interface ImGroupService { | ||
| 80 | */ | 85 | */ |
| 81 | List<ImGroupDO> getActiveGroupList(Long userId); | 86 | List<ImGroupDO> getActiveGroupList(Long userId); |
| 82 | 87 | ||
| 88 | + // ==================== 群成员的写操作 ==================== | ||
| 89 | + // 说明:群成员的写操作统一放在 ImGroupService,而非 ImGroupMemberService, | ||
| 90 | + // 保持 ImGroupMemberService 无 WebSocket 推送等外部依赖,职责更单一。 | ||
| 91 | + | ||
| 92 | + /** | ||
| 93 | + * 邀请用户加入群 | ||
| 94 | + * <p> | ||
| 95 | + * 仅群主可执行 | ||
| 96 | + * | ||
| 97 | + * @param userId 当前登录用户编号(群主) | ||
| 98 | + * @param inviteReqVO 邀请信息 | ||
| 99 | + * @return 群成员编号 | ||
| 100 | + */ | ||
| 101 | + Long inviteGroupMember(Long userId, @Valid ImGroupMemberInviteReqVO inviteReqVO); | ||
| 102 | + | ||
| 103 | + /** | ||
| 104 | + * 退群 | ||
| 105 | + * <p> | ||
| 106 | + * 群主不可退群(只能解散) | ||
| 107 | + * | ||
| 108 | + * @param groupId 群编号 | ||
| 109 | + * @param userId 当前登录用户编号 | ||
| 110 | + */ | ||
| 111 | + void quitGroup(Long groupId, Long userId); | ||
| 112 | + | ||
| 113 | + /** | ||
| 114 | + * 移除群成员(踢人) | ||
| 115 | + * <p> | ||
| 116 | + * 仅群主可执行,且不能移除自己 | ||
| 117 | + * | ||
| 118 | + * @param groupId 群编号 | ||
| 119 | + * @param memberUserId 被移除的用户编号 | ||
| 120 | + * @param userId 当前登录用户编号(群主) | ||
| 121 | + */ | ||
| 122 | + void removeGroupMember(Long groupId, Long memberUserId, Long userId); | ||
| 123 | + | ||
| 83 | } | 124 | } |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java
| @@ -10,6 +10,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | @@ -10,6 +10,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 10 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 10 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 11 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupCreateReqVO; | 11 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupCreateReqVO; |
| 12 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupUpdateReqVO; | 12 | import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupUpdateReqVO; |
| 13 | +import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberInviteReqVO; | ||
| 14 | +import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; | ||
| 13 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; | 15 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; |
| 14 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; | 16 | import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; |
| 15 | import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper; | 17 | import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper; |
| @@ -35,7 +37,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU | @@ -35,7 +37,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU | ||
| 35 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 37 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 36 | import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.GROUP; | 38 | import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.GROUP; |
| 37 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; | 39 | import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; |
| 38 | -import static cn.iocoder.yudao.module.im.enums.ImCommonConstants.GROUP_DISSOLVE_TIP_MESSAGE; | 40 | +import static cn.iocoder.yudao.module.im.enums.ImCommonConstants.*; |
| 39 | 41 | ||
| 40 | // TODO @芋艿:群主的调整,暂时不考虑。后续在弄; | 42 | // TODO @芋艿:群主的调整,暂时不考虑。后续在弄; |
| 41 | /** | 43 | /** |
| @@ -62,6 +64,8 @@ public class ImGroupServiceImpl implements ImGroupService { | @@ -62,6 +64,8 @@ public class ImGroupServiceImpl implements ImGroupService { | ||
| 62 | @Resource | 64 | @Resource |
| 63 | private AdminUserApi adminUserApi; | 65 | private AdminUserApi adminUserApi; |
| 64 | 66 | ||
| 67 | + // ==================== 群的写操作 ==================== | ||
| 68 | + | ||
| 65 | @Override | 69 | @Override |
| 66 | @Transactional(rollbackFor = Exception.class) | 70 | @Transactional(rollbackFor = Exception.class) |
| 67 | public ImGroupDO createGroup(ImGroupCreateReqVO createReqVO, Long userId) { | 71 | public ImGroupDO createGroup(ImGroupCreateReqVO createReqVO, Long userId) { |
| @@ -107,10 +111,10 @@ public class ImGroupServiceImpl implements ImGroupService { | @@ -107,10 +111,10 @@ public class ImGroupServiceImpl implements ImGroupService { | ||
| 107 | } | 111 | } |
| 108 | 112 | ||
| 109 | // 3. 更新当前用户的群成员信息(displayUserName、displayGroupName → im_group_member 表) | 113 | // 3. 更新当前用户的群成员信息(displayUserName、displayGroupName → im_group_member 表) |
| 110 | - // TODO @AI:ObjUtil.isAllEmpty(? | ||
| 111 | - if (updateReqVO.getDisplayUserName() != null || updateReqVO.getDisplayGroupName() != null) { | ||
| 112 | - groupMemberService.updateGroupMember(updateReqVO.getId(), userId, | ||
| 113 | - updateReqVO.getDisplayUserName(), updateReqVO.getDisplayGroupName()); | 114 | + if (!ObjUtil.isAllEmpty(updateReqVO.getDisplayUserName(), updateReqVO.getDisplayGroupName())) { |
| 115 | + groupMemberService.updateGroupMember(userId, new ImGroupMemberUpdateReqVO() | ||
| 116 | + .setGroupId(updateReqVO.getId()).setDisplayUserName(updateReqVO.getDisplayUserName()) | ||
| 117 | + .setDisplayGroupName(updateReqVO.getDisplayGroupName())); | ||
| 114 | } | 118 | } |
| 115 | return group; | 119 | return group; |
| 116 | } | 120 | } |
| @@ -137,12 +141,68 @@ public class ImGroupServiceImpl implements ImGroupService { | @@ -137,12 +141,68 @@ public class ImGroupServiceImpl implements ImGroupService { | ||
| 137 | AdminUserRespDTO user = adminUserApi.getUser(userId); | 141 | AdminUserRespDTO user = adminUserApi.getUser(userId); |
| 138 | String tipContent = StrUtil.format(GROUP_DISSOLVE_TIP_MESSAGE, user.getNickname()); | 142 | String tipContent = StrUtil.format(GROUP_DISSOLVE_TIP_MESSAGE, user.getNickname()); |
| 139 | groupMessageService.sendTipGroupMessage(userId, id, memberUserIds, tipContent); | 143 | groupMessageService.sendTipGroupMessage(userId, id, memberUserIds, tipContent); |
| 140 | - // 3.2 推送群解散事件给所有原群成员 | 144 | + // 3.2 推送群删除事件给所有原群成员 |
| 141 | webSocketService.sendGroupMessageAsync(memberUserIds, | 145 | webSocketService.sendGroupMessageAsync(memberUserIds, |
| 142 | - ImGroupMessageDTO.ofGroupDissolve(userId, id)); | 146 | + ImGroupMessageDTO.ofGroupDelete(userId, id)); |
| 147 | + } | ||
| 148 | + | ||
| 149 | + // ==================== 群成员的写操作 ==================== | ||
| 150 | + | ||
| 151 | + @Override | ||
| 152 | + public Long inviteGroupMember(Long userId, ImGroupMemberInviteReqVO inviteReqVO) { | ||
| 153 | + // 1. 校验群存在 + 当前用户是群主 | ||
| 154 | + validateGroupOwner(inviteReqVO.getGroupId(), userId); | ||
| 155 | + | ||
| 156 | + // 2. 添加群成员 | ||
| 157 | + ImGroupMemberDO member = groupMemberService.addGroupMember(inviteReqVO.getGroupId(), inviteReqVO.getUserId()); | ||
| 158 | + return member.getId(); | ||
| 143 | } | 159 | } |
| 144 | 160 | ||
| 145 | @Override | 161 | @Override |
| 162 | + public void quitGroup(Long groupId, Long userId) { | ||
| 163 | + // 1. 校验群存在 | ||
| 164 | + ImGroupDO group = validateGroupExists(groupId); | ||
| 165 | + // 2. 群主不可退群 | ||
| 166 | + if (ObjUtil.equal(group.getOwnerUserId(), userId)) { | ||
| 167 | + throw exception(GROUP_OWNER_CANNOT_QUIT); | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | + // 3.1 移除群成员 | ||
| 171 | + groupMemberService.removeGroupMember(groupId, userId); | ||
| 172 | + // 3.2 清理已读缓存 | ||
| 173 | + groupMessageService.deleteReadMaxMessageId(groupId, userId); | ||
| 174 | + | ||
| 175 | + // 4.1 发送退群提示消息(TIP_TEXT) | ||
| 176 | + groupMessageService.sendTipGroupMessage(userId, groupId, Set.of(userId), GROUP_QUIT_TIP_MESSAGE); | ||
| 177 | + // 4.2 推送群删除事件 | ||
| 178 | + webSocketService.sendGroupMessageAsync(Set.of(userId), | ||
| 179 | + ImGroupMessageDTO.ofGroupDelete(userId, groupId)); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + @Override | ||
| 183 | + public void removeGroupMember(Long groupId, Long memberUserId, Long userId) { | ||
| 184 | + // 1. 校验群存在 + 当前用户是群主 | ||
| 185 | + validateGroupOwner(groupId, userId); | ||
| 186 | + // 2. 不能移除自己 | ||
| 187 | + if (ObjUtil.equal(memberUserId, userId)) { | ||
| 188 | + throw exception(GROUP_CANNOT_REMOVE_SELF); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + // 3.1 移除群成员 | ||
| 192 | + groupMemberService.removeGroupMember(groupId, memberUserId); | ||
| 193 | + // 3.2 清理已读缓存 | ||
| 194 | + groupMessageService.deleteReadMaxMessageId(groupId, memberUserId); | ||
| 195 | + | ||
| 196 | + // 4.1 发送踢出提示消息(TIP_TEXT) | ||
| 197 | + groupMessageService.sendTipGroupMessage(userId, groupId, Set.of(memberUserId), GROUP_REMOVE_TIP_MESSAGE); | ||
| 198 | + // 4.2 推送群删除事件 | ||
| 199 | + webSocketService.sendGroupMessageAsync(Set.of(memberUserId), | ||
| 200 | + ImGroupMessageDTO.ofGroupDelete(userId, groupId)); | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + // ==================== 群的读操作 ==================== | ||
| 204 | + | ||
| 205 | + @Override | ||
| 146 | public ImGroupDO validateGroupExists(Long id) { | 206 | public ImGroupDO validateGroupExists(Long id) { |
| 147 | ImGroupDO group = getSelf().getGroup(id); | 207 | ImGroupDO group = getSelf().getGroup(id); |
| 148 | if (group == null) { | 208 | if (group == null) { |
| @@ -185,7 +245,7 @@ public class ImGroupServiceImpl implements ImGroupService { | @@ -185,7 +245,7 @@ public class ImGroupServiceImpl implements ImGroupService { | ||
| 185 | } | 245 | } |
| 186 | 246 | ||
| 187 | // 2. 批量查询群信息(仅 ENABLE 状态) | 247 | // 2. 批量查询群信息(仅 ENABLE 状态) |
| 188 | - return groupMapper.selectListByIds(groupIds, CommonStatusEnum.ENABLE.getStatus(), null); | 248 | + return groupMapper.selectListByIds(groupIds, CommonStatusEnum.ENABLE.getStatus(), false); |
| 189 | } | 249 | } |
| 190 | 250 | ||
| 191 | private ImGroupServiceImpl getSelf() { | 251 | private ImGroupServiceImpl getSelf() { |
yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/ImGroupMessageDTO.java
| @@ -147,15 +147,17 @@ public class ImGroupMessageDTO { | @@ -147,15 +147,17 @@ public class ImGroupMessageDTO { | ||
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | /** | 149 | /** |
| 150 | - * 构建群解散推送 DTO(通知所有群成员"群已解散") | 150 | + * 构建群删除推送 DTO(通知群成员"群已移除") |
| 151 | + * <p> | ||
| 152 | + * 适用于群解散、退群、踢出等场景 | ||
| 151 | * | 153 | * |
| 152 | - * @param senderId 操作者(群主)用户编号 | 154 | + * @param senderId 操作者用户编号 |
| 153 | * @param groupId 群编号 | 155 | * @param groupId 群编号 |
| 154 | * @return 群聊 DTO | 156 | * @return 群聊 DTO |
| 155 | */ | 157 | */ |
| 156 | - public static ImGroupMessageDTO ofGroupDissolve(Long senderId, Long groupId) { | 158 | + public static ImGroupMessageDTO ofGroupDelete(Long senderId, Long groupId) { |
| 157 | return new ImGroupMessageDTO() | 159 | return new ImGroupMessageDTO() |
| 158 | - .setType(ImMessageTypeEnum.GROUP_DISSOLVE.getType()) | 160 | + .setType(ImMessageTypeEnum.GROUP_DELETE.getType()) |
| 159 | .setSenderId(senderId).setGroupId(groupId) | 161 | .setSenderId(senderId).setGroupId(groupId) |
| 160 | .setSendTime(LocalDateTime.now()); | 162 | .setSendTime(LocalDateTime.now()); |
| 161 | } | 163 | } |