From 9cee1b3ceb53906f64da446493a975fb81a20c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sat, 16 Mar 2024 15:43:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E7=BE=A4=E8=81=8A?= =?UTF-8?q?=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/im/enums/ErrorCodeConstants.java | 6 + .../admin/group/ImGroupController.java | 94 +++++++++++ .../admin/group/vo/ImGroupPageReqVO.java | 39 +++++ .../admin/group/vo/ImGroupRespVO.java | 46 ++++++ .../admin/group/vo/ImGroupSaveReqVO.java | 33 ++++ .../groupmember/ImGroupMemberController.java | 93 +++++++++++ .../vo/ImGroupMemberPageReqVO.java | 42 +++++ .../groupmember/vo/ImGroupMemberRespVO.java | 47 ++++++ .../vo/ImGroupMemberSaveReqVO.java | 33 ++++ .../im/dal/dataobject/group/ImGroupDO.java | 52 +++++++ .../dataobject/groupmember/GroupMemberDO.java | 55 +++++++ ...nMapper.java => ImConversationMapper.java} | 7 +- .../im/dal/mysql/group/ImGroupMapper.java | 30 ++++ .../groupmember/ImGroupMemberMapper.java | 35 +++++ .../{InboxMapper.java => ImInboxMapper.java} | 2 +- .../ImConversationServiceImpl.java | 24 ++- .../im/service/group/ImGroupService.java | 53 +++++++ .../im/service/group/ImGroupServiceImpl.java | 71 +++++++++ .../groupmember/ImGroupMemberService.java | 63 ++++++++ .../groupmember/ImGroupMemberServiceImpl.java | 78 ++++++++++ .../im/service/inbox/ImInboxServiceImpl.java | 16 +- .../im/service/message/ImMessageService.java | 8 + .../service/message/ImMessageServiceImpl.java | 17 +- .../websocket/ImWebSocketMessageListener.java | 72 +++++++-- ...ionMapper.xml => ImConversationMapper.xml} | 2 +- .../ImGroupMapper.xml} | 2 +- .../groupmember/ImGroupMemberMapper.xml | 12 ++ .../resources/mapper/inbox/ImInboxMapper.xml | 12 ++ .../ImConversationServiceImplTest.java | 30 ++-- .../service/group/ImGroupServiceImplTest.java | 147 ++++++++++++++++++ .../ImGroupMemberServiceImplTest.java | 147 ++++++++++++++++++ .../service/inbox/ImInboxServiceImplTest.java | 24 +-- 32 files changed, 1322 insertions(+), 70 deletions(-) create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupPageReqVO.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupRespVO.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupSaveReqVO.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberPageReqVO.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberRespVO.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberSaveReqVO.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/ImGroupDO.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/groupmember/GroupMemberDO.java rename yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/{ConversationMapper.java => ImConversationMapper.java} (83%) create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java rename yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/{InboxMapper.java => ImInboxMapper.java} (93%) create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberService.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImpl.java rename yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/conversation/{ConversationMapper.xml => ImConversationMapper.xml} (94%) rename yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/{inbox/InboxMapper.xml => group/ImGroupMapper.xml} (85%) mode change 100755 => 100644 create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/groupmember/ImGroupMemberMapper.xml create mode 100755 yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/inbox/ImInboxMapper.xml create mode 100644 yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java create mode 100644 yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImplTest.java diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java index ca674552f9..9e7d3b0114 100644 --- a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java +++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/ErrorCodeConstants.java @@ -17,4 +17,10 @@ public interface ErrorCodeConstants { // ========== 消息 (1-040-300-000) ========== ErrorCode MESSAGE_NOT_EXISTS = new ErrorCode(1_040_300_000, "消息不存在"); + + // ========== 群 (1-040-400-000) ========== + ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1_040_400_000, "群不存在"); + + // ========== 群成员 (1-040-500-000) ========== + ErrorCode GROUP_MEMBER_NOT_EXISTS = new ErrorCode(1_040_500_000, "群成员不存在"); } diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java new file mode 100644 index 0000000000..a1afcc9112 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupController.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.im.controller.admin.group; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.im.controller.admin.group.vo.*; +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; +import cn.iocoder.yudao.module.im.service.group.ImGroupService; + +@Tag(name = "管理后台 - 群") +@RestController +@RequestMapping("/im/group") +@Validated +public class ImGroupController { + + @Resource + private ImGroupService imGroupService; + + @PostMapping("/create") + @Operation(summary = "创建群") + @PreAuthorize("@ss.hasPermission('im:group:create')") + public CommonResult createGroup(@Valid @RequestBody ImGroupSaveReqVO createReqVO) { + return success(imGroupService.createGroup(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新群") + @PreAuthorize("@ss.hasPermission('im:group:update')") + public CommonResult updateGroup(@Valid @RequestBody ImGroupSaveReqVO updateReqVO) { + imGroupService.updateGroup(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除群") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('im:group:delete')") + public CommonResult deleteGroup(@RequestParam("id") Long id) { + imGroupService.deleteGroup(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得群") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('im:group:query')") + public CommonResult getGroup(@RequestParam("id") Long id) { + ImGroupDO group = imGroupService.getGroup(id); + return success(BeanUtils.toBean(group, ImGroupRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得群分页") + @PreAuthorize("@ss.hasPermission('im:group:query')") + public CommonResult> getGroupPage(@Valid ImGroupPageReqVO pageReqVO) { + PageResult pageResult = imGroupService.getGroupPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ImGroupRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出群 Excel") + @PreAuthorize("@ss.hasPermission('im:group:export')") + @OperateLog(type = EXPORT) + public void exportGroupExcel(@Valid ImGroupPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = imGroupService.getGroupPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "群.xls", "数据", ImGroupRespVO.class, + BeanUtils.toBean(list, ImGroupRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupPageReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupPageReqVO.java new file mode 100644 index 0000000000..543a0b1676 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupPageReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.im.controller.admin.group.vo; + +import lombok.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 群分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ImGroupPageReqVO extends PageParam { + + @Schema(description = "群名字", example = "芋艿") + private String groupName; + + @Schema(description = "群主id", example = "31460") + private Long ownerId; + + @Schema(description = "群头像") + private String headImage; + + @Schema(description = "群头像缩略图") + private String headImageThumb; + + @Schema(description = "群公告") + private String notice; + + @Schema(description = "群备注", example = "你说的对") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupRespVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupRespVO.java new file mode 100644 index 0000000000..e9806863f5 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupRespVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.im.controller.admin.group.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 群 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ImGroupRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1003") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "群名字", example = "芋艿") + @ExcelProperty("群名字") + private String groupName; + + @Schema(description = "群主id", requiredMode = Schema.RequiredMode.REQUIRED, example = "31460") + @ExcelProperty("群主id") + private Long ownerId; + + @Schema(description = "群头像") + @ExcelProperty("群头像") + private String headImage; + + @Schema(description = "群头像缩略图") + @ExcelProperty("群头像缩略图") + private String headImageThumb; + + @Schema(description = "群公告") + @ExcelProperty("群公告") + private String notice; + + @Schema(description = "群备注", example = "你说的对") + @ExcelProperty("群备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupSaveReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupSaveReqVO.java new file mode 100644 index 0000000000..69678b5f67 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/vo/ImGroupSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.im.controller.admin.group.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - 群新增/修改 Request VO") +@Data +public class ImGroupSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1003") + private Long id; + + @Schema(description = "群名字", example = "芋艿") + private String groupName; + + @Schema(description = "群主id", requiredMode = Schema.RequiredMode.REQUIRED, example = "31460") + @NotNull(message = "群主id不能为空") + private Long ownerId; + + @Schema(description = "群头像") + private String headImage; + + @Schema(description = "群头像缩略图") + private String headImageThumb; + + @Schema(description = "群公告") + private String notice; + + @Schema(description = "群备注", example = "你说的对") + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java new file mode 100644 index 0000000000..c715b633a1 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/ImGroupMemberController.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.im.controller.admin.groupmember; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO; +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberRespVO; +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberSaveReqVO; +import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO; +import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - 群成员") +@RestController +@RequestMapping("/im/group-member") +@Validated +public class ImGroupMemberController { + + @Resource + private ImGroupMemberService imGroupMemberService; + + @PostMapping("/create") + @Operation(summary = "创建群成员") + @PreAuthorize("@ss.hasPermission('im:group-member:create')") + public CommonResult createGroupMember(@Valid @RequestBody ImGroupMemberSaveReqVO createReqVO) { + return success(imGroupMemberService.createGroupMember(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新群成员") + @PreAuthorize("@ss.hasPermission('im:group-member:update')") + public CommonResult updateGroupMember(@Valid @RequestBody ImGroupMemberSaveReqVO updateReqVO) { + imGroupMemberService.updateGroupMember(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除群成员") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('im:group-member:delete')") + public CommonResult deleteGroupMember(@RequestParam("id") Long id) { + imGroupMemberService.deleteGroupMember(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得群成员") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('im:group-member:query')") + public CommonResult getGroupMember(@RequestParam("id") Long id) { + GroupMemberDO groupMember = imGroupMemberService.getGroupMember(id); + return success(BeanUtils.toBean(groupMember, ImGroupMemberRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得群成员分页") + @PreAuthorize("@ss.hasPermission('im:group-member:query')") + public CommonResult> getGroupMemberPage(@Valid ImGroupMemberPageReqVO pageReqVO) { + PageResult pageResult = imGroupMemberService.getGroupMemberPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ImGroupMemberRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出群成员 Excel") + @PreAuthorize("@ss.hasPermission('im:group-member:export')") + @OperateLog(type = EXPORT) + public void exportGroupMemberExcel(@Valid ImGroupMemberPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = imGroupMemberService.getGroupMemberPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "群成员.xls", "数据", ImGroupMemberRespVO.class, + BeanUtils.toBean(list, ImGroupMemberRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberPageReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberPageReqVO.java new file mode 100644 index 0000000000..7fffdd9a29 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberPageReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.im.controller.admin.groupmember.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 群成员分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ImGroupMemberPageReqVO extends PageParam { + + @Schema(description = "群 id", example = "13279") + private Long groupId; + + @Schema(description = "用户id", example = "21730") + private Long userId; + + @Schema(description = "昵称", example = "芋艿") + private String nickname; + + @Schema(description = "头像") + private String avatar; + + @Schema(description = "组内显示名称", example = "芋艿") + private String aliasName; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberRespVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberRespVO.java new file mode 100644 index 0000000000..9fe83db976 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberRespVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.im.controller.admin.groupmember.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 群成员 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ImGroupMemberRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17071") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "群 id", example = "13279") + @ExcelProperty("群 id") + private Long groupId; + + @Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "21730") + @ExcelProperty("用户id") + private Long userId; + + @Schema(description = "昵称", example = "芋艿") + @ExcelProperty("昵称") + private String nickname; + + @Schema(description = "头像") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "组内显示名称", example = "芋艿") + @ExcelProperty("组内显示名称") + private String aliasName; + + @Schema(description = "备注", example = "你说的对") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberSaveReqVO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberSaveReqVO.java new file mode 100644 index 0000000000..ccec984e8b --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/controller/admin/groupmember/vo/ImGroupMemberSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.im.controller.admin.groupmember.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - 群成员新增/修改 Request VO") +@Data +public class ImGroupMemberSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17071") + private Long id; + + @Schema(description = "群 id", example = "13279") + private Long groupId; + + @Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "21730") + @NotNull(message = "用户id不能为空") + private Long userId; + + @Schema(description = "昵称", example = "芋艿") + private String nickname; + + @Schema(description = "头像") + private String avatar; + + @Schema(description = "组内显示名称", example = "芋艿") + private String aliasName; + + @Schema(description = "备注", example = "你说的对") + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/ImGroupDO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/ImGroupDO.java new file mode 100644 index 0000000000..654709e801 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/group/ImGroupDO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.group; + +import lombok.*; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 群 DO + * + * @author 芋道源码 + */ +@TableName("im_group") +@KeySequence("im_group_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ImGroupDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 群名字 + */ + private String groupName; + /** + * 群主id + */ + private Long ownerId; + /** + * 群头像 + */ + private String headImage; + /** + * 群头像缩略图 + */ + private String headImageThumb; + /** + * 群公告 + */ + private String notice; + /** + * 群备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/groupmember/GroupMemberDO.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/groupmember/GroupMemberDO.java new file mode 100644 index 0000000000..8bc7b13d6f --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/dataobject/groupmember/GroupMemberDO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.im.dal.dataobject.groupmember; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 群成员 DO + * + * @author 芋道源码 + */ +@TableName("im_group_member") +@KeySequence("im_group_member_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class GroupMemberDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 群 id + */ + private Long groupId; + /** + * 用户id + */ + private Long userId; + /** + * 昵称 + */ + private String nickname; + /** + * 头像 + */ + private String avatar; + /** + * 组内显示名称 + */ + private String aliasName; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ConversationMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ImConversationMapper.java similarity index 83% rename from yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ConversationMapper.java rename to yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ImConversationMapper.java index a93257f32c..1b24c861f9 100755 --- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ConversationMapper.java +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/conversation/ImConversationMapper.java @@ -7,13 +7,15 @@ import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversatio import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; import org.apache.ibatis.annotations.Mapper; +import java.util.Optional; + /** * 会话 Mapper * * @author 芋道源码 */ @Mapper -public interface ConversationMapper extends BaseMapperX { +public interface ImConversationMapper extends BaseMapperX { default PageResult selectPage(ImConversationPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() @@ -27,4 +29,7 @@ public interface ConversationMapper extends BaseMapperX { .orderByDesc(ImConversationDO::getId)); } + default ImConversationDO selectByNo(String no){ + return selectOne(new LambdaQueryWrapperX().eq(ImConversationDO::getNo, no)); + } } \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java new file mode 100644 index 0000000000..ac301ee125 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.im.dal.mysql.group; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.im.controller.admin.group.vo.*; + +/** + * 群 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ImGroupMapper extends BaseMapperX { + + default PageResult selectPage(ImGroupPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ImGroupDO::getGroupName, reqVO.getGroupName()) + .eqIfPresent(ImGroupDO::getOwnerId, reqVO.getOwnerId()) + .eqIfPresent(ImGroupDO::getHeadImage, reqVO.getHeadImage()) + .eqIfPresent(ImGroupDO::getHeadImageThumb, reqVO.getHeadImageThumb()) + .eqIfPresent(ImGroupDO::getNotice, reqVO.getNotice()) + .eqIfPresent(ImGroupDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(ImGroupDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ImGroupDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java new file mode 100644 index 0000000000..d42d1f962b --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/groupmember/ImGroupMemberMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.im.dal.mysql.groupmember; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO; +import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 群成员 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ImGroupMemberMapper extends BaseMapperX { + + default PageResult selectPage(ImGroupMemberPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(GroupMemberDO::getGroupId, reqVO.getGroupId()) + .eqIfPresent(GroupMemberDO::getUserId, reqVO.getUserId()) + .likeIfPresent(GroupMemberDO::getNickname, reqVO.getNickname()) + .eqIfPresent(GroupMemberDO::getAvatar, reqVO.getAvatar()) + .likeIfPresent(GroupMemberDO::getAliasName, reqVO.getAliasName()) + .eqIfPresent(GroupMemberDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(GroupMemberDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(GroupMemberDO::getId)); + } + + default List selectListByGroupId(Long groupId) { + return selectList(new LambdaQueryWrapperX().eq(GroupMemberDO::getGroupId, groupId)); + } +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/InboxMapper.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/ImInboxMapper.java similarity index 93% rename from yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/InboxMapper.java rename to yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/ImInboxMapper.java index 90426d09ad..05bf95593e 100755 --- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/InboxMapper.java +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/inbox/ImInboxMapper.java @@ -13,7 +13,7 @@ import org.apache.ibatis.annotations.Mapper; * @author 芋道源码 */ @Mapper -public interface InboxMapper extends BaseMapperX { +public interface ImInboxMapper extends BaseMapperX { default PageResult selectPage(ImInboxPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java index 3f7634220e..5c35ac29a9 100755 --- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImpl.java @@ -5,9 +5,8 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationPageReqVO; import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.ImConversationSaveReqVO; import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; -import cn.iocoder.yudao.module.im.dal.mysql.conversation.ConversationMapper; +import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper; import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -25,13 +24,13 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.CONVERSATION_N public class ImConversationServiceImpl implements ImConversationService { @Resource - private ConversationMapper conversationMapper; + private ImConversationMapper imConversationMapper; @Override public Long createConversation(ImConversationSaveReqVO createReqVO) { // 插入 ImConversationDO conversation = BeanUtils.toBean(createReqVO, ImConversationDO.class); - conversationMapper.insert(conversation); + imConversationMapper.insert(conversation); // 返回 return conversation.getId(); } @@ -42,7 +41,7 @@ public class ImConversationServiceImpl implements ImConversationService { validateConversationExists(updateReqVO.getId()); // 更新 ImConversationDO updateObj = BeanUtils.toBean(updateReqVO, ImConversationDO.class); - conversationMapper.updateById(updateObj); + imConversationMapper.updateById(updateObj); } @Override @@ -50,23 +49,23 @@ public class ImConversationServiceImpl implements ImConversationService { // 校验存在 validateConversationExists(id); // 删除 - conversationMapper.deleteById(id); + imConversationMapper.deleteById(id); } private void validateConversationExists(Long id) { - if (conversationMapper.selectById(id) == null) { + if (imConversationMapper.selectById(id) == null) { throw exception(CONVERSATION_NOT_EXISTS); } } @Override public ImConversationDO getConversation(Long id) { - return conversationMapper.selectById(id); + return imConversationMapper.selectById(id); } @Override public PageResult getConversationPage(ImConversationPageReqVO pageReqVO) { - return conversationMapper.selectPage(pageReqVO); + return imConversationMapper.selectPage(pageReqVO); } @Override @@ -86,10 +85,9 @@ public class ImConversationServiceImpl implements ImConversationService { conversation.setPinned(false); // 根据 no 查询是否存在,不存在则新增 - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("no", conversation.getNo()); - if (conversationMapper.selectOne(queryWrapper) == null) { - conversationMapper.insert(conversation); + ImConversationDO imConversationDO = imConversationMapper.selectByNo(conversation.getNo()); + if (imConversationDO == null) { + imConversationMapper.insert(conversation); } } diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java new file mode 100644 index 0000000000..4ebc373fc9 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.im.service.group; + +import jakarta.validation.*; +import cn.iocoder.yudao.module.im.controller.admin.group.vo.*; +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * 群 Service 接口 + * + * @author 芋道源码 + */ +public interface ImGroupService { + + /** + * 创建群 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createGroup(@Valid ImGroupSaveReqVO createReqVO); + + /** + * 更新群 + * + * @param updateReqVO 更新信息 + */ + void updateGroup(@Valid ImGroupSaveReqVO updateReqVO); + + /** + * 删除群 + * + * @param id 编号 + */ + void deleteGroup(Long id); + + /** + * 获得群 + * + * @param id 编号 + * @return 群 + */ + ImGroupDO getGroup(Long id); + + /** + * 获得群分页 + * + * @param pageReqVO 分页查询 + * @return 群分页 + */ + PageResult getGroupPage(ImGroupPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java new file mode 100644 index 0000000000..e7e20e990b --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.im.service.group; + +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; + +import cn.iocoder.yudao.module.im.controller.admin.group.vo.*; +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; + +/** + * 群 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ImGroupServiceImpl implements ImGroupService { + + @Resource + private ImGroupMapper imGroupMapper; + + @Override + public Long createGroup(ImGroupSaveReqVO createReqVO) { + // 插入 + ImGroupDO group = BeanUtils.toBean(createReqVO, ImGroupDO.class); + imGroupMapper.insert(group); + // 返回 + return group.getId(); + } + + @Override + public void updateGroup(ImGroupSaveReqVO updateReqVO) { + // 校验存在 + validateGroupExists(updateReqVO.getId()); + // 更新 + ImGroupDO updateObj = BeanUtils.toBean(updateReqVO, ImGroupDO.class); + imGroupMapper.updateById(updateObj); + } + + @Override + public void deleteGroup(Long id) { + // 校验存在 + validateGroupExists(id); + // 删除 + imGroupMapper.deleteById(id); + } + + private void validateGroupExists(Long id) { + if (imGroupMapper.selectById(id) == null) { + throw exception(GROUP_NOT_EXISTS); + } + } + + @Override + public ImGroupDO getGroup(Long id) { + return imGroupMapper.selectById(id); + } + + @Override + public PageResult getGroupPage(ImGroupPageReqVO pageReqVO) { + return imGroupMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberService.java new file mode 100644 index 0000000000..4ee73aed88 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberService.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.im.service.groupmember; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberPageReqVO; +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.ImGroupMemberSaveReqVO; +import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * 群成员 Service 接口 + * + * @author 芋道源码 + */ +public interface ImGroupMemberService { + + /** + * 创建群成员 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createGroupMember(@Valid ImGroupMemberSaveReqVO createReqVO); + + /** + * 更新群成员 + * + * @param updateReqVO 更新信息 + */ + void updateGroupMember(@Valid ImGroupMemberSaveReqVO updateReqVO); + + /** + * 删除群成员 + * + * @param id 编号 + */ + void deleteGroupMember(Long id); + + /** + * 获得群成员 + * + * @param id 编号 + * @return 群成员 + */ + GroupMemberDO getGroupMember(Long id); + + /** + * 获得群成员分页 + * + * @param pageReqVO 分页查询 + * @return 群成员分页 + */ + PageResult getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO); + + /** + * 根据群组id查询群成员 + * + * @param groupId 群组id + * @return 群成员列表 + */ + List selectByGroupId(Long groupId); +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImpl.java new file mode 100644 index 0000000000..3152f043df --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImpl.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.im.service.groupmember; + +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; + +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.*; +import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; + +/** + * 群成员 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ImGroupMemberServiceImpl implements ImGroupMemberService { + + @Resource + private ImGroupMemberMapper imGroupMemberMapper; + + @Override + public Long createGroupMember(ImGroupMemberSaveReqVO createReqVO) { + // 插入 + GroupMemberDO groupMember = BeanUtils.toBean(createReqVO, GroupMemberDO.class); + imGroupMemberMapper.insert(groupMember); + // 返回 + return groupMember.getId(); + } + + @Override + public void updateGroupMember(ImGroupMemberSaveReqVO updateReqVO) { + // 校验存在 + validateGroupMemberExists(updateReqVO.getId()); + // 更新 + GroupMemberDO updateObj = BeanUtils.toBean(updateReqVO, GroupMemberDO.class); + imGroupMemberMapper.updateById(updateObj); + } + + @Override + public void deleteGroupMember(Long id) { + // 校验存在 + validateGroupMemberExists(id); + // 删除 + imGroupMemberMapper.deleteById(id); + } + + private void validateGroupMemberExists(Long id) { + if (imGroupMemberMapper.selectById(id) == null) { + throw exception(GROUP_MEMBER_NOT_EXISTS); + } + } + + @Override + public GroupMemberDO getGroupMember(Long id) { + return imGroupMemberMapper.selectById(id); + } + + @Override + public PageResult getGroupMemberPage(ImGroupMemberPageReqVO pageReqVO) { + return imGroupMemberMapper.selectPage(pageReqVO); + } + + @Override + public List selectByGroupId(Long groupId) { + return imGroupMemberMapper.selectListByGroupId(groupId); + } + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java index eabaaa9d62..dd5f67531c 100755 --- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImpl.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxPageReqVO; import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO; import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO; -import cn.iocoder.yudao.module.im.dal.mysql.inbox.InboxMapper; +import cn.iocoder.yudao.module.im.dal.mysql.inbox.ImInboxMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -23,13 +23,13 @@ import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.INBOX_NOT_EXIS public class ImInboxServiceImpl implements ImInboxService { @Resource - private InboxMapper inboxMapper; + private ImInboxMapper imInboxMapper; @Override public Long createInbox(ImInboxSaveReqVO createReqVO) { // 插入 ImInboxDO inbox = BeanUtils.toBean(createReqVO, ImInboxDO.class); - inboxMapper.insert(inbox); + imInboxMapper.insert(inbox); // 返回 return inbox.getId(); } @@ -40,7 +40,7 @@ public class ImInboxServiceImpl implements ImInboxService { validateInboxExists(updateReqVO.getId()); // 更新 ImInboxDO updateObj = BeanUtils.toBean(updateReqVO, ImInboxDO.class); - inboxMapper.updateById(updateObj); + imInboxMapper.updateById(updateObj); } @Override @@ -48,23 +48,23 @@ public class ImInboxServiceImpl implements ImInboxService { // 校验存在 validateInboxExists(id); // 删除 - inboxMapper.deleteById(id); + imInboxMapper.deleteById(id); } private void validateInboxExists(Long id) { - if (inboxMapper.selectById(id) == null) { + if (imInboxMapper.selectById(id) == null) { throw exception(INBOX_NOT_EXISTS); } } @Override public ImInboxDO getInbox(Long id) { - return inboxMapper.selectById(id); + return imInboxMapper.selectById(id); } @Override public PageResult getInboxPage(ImInboxPageReqVO pageReqVO) { - return inboxMapper.selectPage(pageReqVO); + return imInboxMapper.selectPage(pageReqVO); } } \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java index e1a3e87983..3b211d7874 100755 --- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageService.java @@ -69,4 +69,12 @@ public interface ImMessageService { * @param messageStatus 消息状态 */ void updateMessageStatus(Long messageId, Integer messageStatus); + + /** + * 保存群聊消息 + * @param message 消息 + * @param fromUserId 发送者用户ID + * @return id + */ + ImMessageDO saveGroupMessage(ImSendMessage message, Long fromUserId); } \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java index d946ddc1f7..c3a33ec089 100755 --- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/ImMessageServiceImpl.java @@ -76,18 +76,22 @@ public class ImMessageServiceImpl implements ImMessageService { @Override - public ImMessageDO savePrivateMessage(ImSendMessage message, Long senderId) { + public ImMessageDO savePrivateMessage(ImSendMessage message, Long fromUserId) { + return saveImMessageDO(message, fromUserId); + } + + private ImMessageDO saveImMessageDO(ImSendMessage message, Long fromUserId) { ImMessageDO imMessageDO = new ImMessageDO(); imMessageDO.setClientMessageId(message.getClientMessageId()); - imMessageDO.setSenderId(senderId); + imMessageDO.setSenderId(fromUserId); imMessageDO.setReceiverId(message.getReceiverId()); //查询发送人昵称和发送人头像 - AdminUserRespDTO user = adminUserApi.getUser(senderId); + AdminUserRespDTO user = adminUserApi.getUser(fromUserId); imMessageDO.setSenderNickname(user.getNickname()); imMessageDO.setSenderAvatar(user.getAvatar()); imMessageDO.setConversationType(message.getConversationType()); imMessageDO.setContentType(message.getContentType()); - imMessageDO.setConversationNo(senderId + "_" + message.getReceiverId()); + imMessageDO.setConversationNo(fromUserId + "_" + message.getReceiverId()); imMessageDO.setContent(message.getContent()); //消息来源 100-用户发送;200-系统发送(一般是通知);不能为空 imMessageDO.setSendFrom(100); @@ -108,4 +112,9 @@ public class ImMessageServiceImpl implements ImMessageService { imMessageMapper.updateById(imMessageDO); } + @Override + public ImMessageDO saveGroupMessage(ImSendMessage message, Long fromUserId) { + return saveImMessageDO(message, fromUserId); + } + } \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java index 42dd059cb5..7e39e61c02 100644 --- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java +++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java @@ -5,11 +5,13 @@ import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListen import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.ImInboxSaveReqVO; +import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImMessageDO; import cn.iocoder.yudao.module.im.dal.redis.inbox.SequenceGeneratorRedisDao; import cn.iocoder.yudao.module.im.enums.conversation.ImConversationTypeEnum; import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum; import cn.iocoder.yudao.module.im.service.conversation.ImConversationService; +import cn.iocoder.yudao.module.im.service.groupmember.ImGroupMemberService; import cn.iocoder.yudao.module.im.service.inbox.ImInboxService; import cn.iocoder.yudao.module.im.service.message.ImMessageService; import cn.iocoder.yudao.module.im.websocket.message.ImReceiveMessage; @@ -19,6 +21,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.socket.WebSocketSession; +import java.util.List; + /** * WebSocket im * @@ -28,6 +32,7 @@ import org.springframework.web.socket.WebSocketSession; @Slf4j public class ImWebSocketMessageListener implements WebSocketMessageListener { + public static final String IM_MESSAGE_RECEIVE = "im-message-receive"; @Resource private WebSocketMessageSender webSocketMessageSender; // WebSocket消息发送器 @Resource @@ -37,6 +42,8 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener groupMemberDOList = imGroupMemberService.selectByGroupId(groupId); + groupMemberDOList.forEach(groupMemberDO -> { + //过滤掉自己 + if (groupMemberDO.getUserId().equals(fromUserId)) { + return; + } + Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(groupMemberDO.getUserId()); // 生成接收者序列 + Long receiverInboxId = createAndSaveInbox(groupMemberDO.getUserId(), imMessageDO.getId(), receiverSequence); // 创建并保存接收者收件箱 + sendMessage(groupMemberDO.getUserId(), receiverInboxId, imMessageDO, message, receiverSequence); + }); + + Long fromUserSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成发送者序列 + Long fromUserInboxId = createAndSaveInbox(fromUserId, imMessageDO.getId(), fromUserSequence); // 创建并保存发送者收件箱 + + // 发送消息给发送者 + sendMessage(fromUserId, fromUserInboxId, imMessageDO, message, fromUserSequence); + + // 更新消息状态为成功 + imMessageService.updateMessageStatus(imMessageDO.getId(), ImMessageStatusEnum.SUCCESS.getStatus()); + } + /** * 处理私人消息 * - * @param fromUserId 发送者用户ID - * @param imMessageDO IM消息数据对象 - * @param message 发送的IM消息 + * @param fromUserId 发送者用户ID + * @param message 发送的IM消息 */ - private void handlePrivateMessage(Long fromUserId, ImMessageDO imMessageDO, ImSendMessage message) { + private void handlePrivateMessage(Long fromUserId, ImSendMessage message) { + ImMessageDO imMessageDO = imMessageService.savePrivateMessage(message, fromUserId); // 保存私人消息 + Long receiverId = message.getReceiverId(); + Long fromUserSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成发送者序列 Long fromUserInboxId = createAndSaveInbox(fromUserId, imMessageDO.getId(), fromUserSequence); // 创建并保存发送者收件箱 - Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(fromUserId); // 生成接收者序列 + Long receiverSequence = sequenceGeneratorRedisDao.generateSequence(message.getReceiverId()); // 生成接收者序列 Long receiverInboxId = createAndSaveInbox(message.getReceiverId(), imMessageDO.getId(), receiverSequence); // 创建并保存接收者收件箱 // 发送消息给接收者和发送者 - sendMessage(fromUserId, receiverInboxId, imMessageDO, message, "im-message-receive", fromUserSequence); - sendMessage(fromUserId, fromUserInboxId, imMessageDO, message, "im-message-receive", receiverSequence); + sendMessage(fromUserId, fromUserInboxId, imMessageDO, message, fromUserSequence); + sendMessage(receiverId, receiverInboxId, imMessageDO, message, receiverSequence); // 更新消息状态为成功 imMessageService.updateMessageStatus(imMessageDO.getId(), ImMessageStatusEnum.SUCCESS.getStatus()); // 保存私人会话,只有在 client 操作会话(已读、置顶)时,才会延迟创建 - //imConversationService.savePrivateConversation(fromUserId, message.getReceiverId()); + //imConversationService.savePrivateConversation(fromUserId, receiverId); } /** @@ -99,20 +144,19 @@ public class ImWebSocketMessageListener implements WebSocketMessageListener - + + + \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/inbox/ImInboxMapper.xml b/yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/inbox/ImInboxMapper.xml new file mode 100755 index 0000000000..f78d7a77a5 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/main/resources/mapper/inbox/ImInboxMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImplTest.java b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImplTest.java index 9b5de48dae..482a4d4ee0 100755 --- a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImplTest.java +++ b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/conversation/ImConversationServiceImplTest.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.im.controller.admin.conversation.vo.*; import cn.iocoder.yudao.module.im.dal.dataobject.conversation.ImConversationDO; -import cn.iocoder.yudao.module.im.dal.mysql.conversation.ConversationMapper; +import cn.iocoder.yudao.module.im.dal.mysql.conversation.ImConversationMapper; import cn.iocoder.yudao.framework.common.pojo.PageResult; import org.springframework.context.annotation.Import; @@ -33,7 +33,7 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest { private ImConversationServiceImpl conversationService; @Resource - private ConversationMapper conversationMapper; + private ImConversationMapper imConversationMapper; @Test public void testCreateConversation_success() { @@ -45,7 +45,7 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest { // 断言 assertNotNull(conversationId); // 校验记录的属性是否正确 - ImConversationDO conversation = conversationMapper.selectById(conversationId); + ImConversationDO conversation = imConversationMapper.selectById(conversationId); assertPojoEquals(createReqVO, conversation, "id"); } @@ -53,7 +53,7 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest { public void testUpdateConversation_success() { // mock 数据 ImConversationDO dbConversation = randomPojo(ImConversationDO.class); - conversationMapper.insert(dbConversation);// @Sql: 先插入出一条存在的数据 + imConversationMapper.insert(dbConversation);// @Sql: 先插入出一条存在的数据 // 准备参数 ImConversationSaveReqVO updateReqVO = randomPojo(ImConversationSaveReqVO.class, o -> { o.setId(dbConversation.getId()); // 设置更新的 ID @@ -62,7 +62,7 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest { // 调用 conversationService.updateConversation(updateReqVO); // 校验是否更新正确 - ImConversationDO conversation = conversationMapper.selectById(updateReqVO.getId()); // 获取最新的 + ImConversationDO conversation = imConversationMapper.selectById(updateReqVO.getId()); // 获取最新的 assertPojoEquals(updateReqVO, conversation); } @@ -79,14 +79,14 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest { public void testDeleteConversation_success() { // mock 数据 ImConversationDO dbConversation = randomPojo(ImConversationDO.class); - conversationMapper.insert(dbConversation);// @Sql: 先插入出一条存在的数据 + imConversationMapper.insert(dbConversation);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbConversation.getId(); // 调用 conversationService.deleteConversation(id); // 校验数据不存在了 - assertNull(conversationMapper.selectById(id)); + assertNull(imConversationMapper.selectById(id)); } @Test @@ -111,21 +111,21 @@ public class ImConversationServiceImplTest extends BaseDbUnitTest { o.setLastReadTime(null); o.setCreateTime(null); }); - conversationMapper.insert(dbConversation); + imConversationMapper.insert(dbConversation); // 测试 userId 不匹配 - conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setUserId(null))); + imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setUserId(null))); // 测试 conversationType 不匹配 - conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setConversationType(null))); + imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setConversationType(null))); // 测试 targetId 不匹配 - conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setTargetId(null))); + imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setTargetId(null))); // 测试 no 不匹配 - conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setNo(null))); + imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setNo(null))); // 测试 pinned 不匹配 - conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setPinned(null))); + imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setPinned(null))); // 测试 lastReadTime 不匹配 - conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setLastReadTime(null))); + imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setLastReadTime(null))); // 测试 createTime 不匹配 - conversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setCreateTime(null))); + imConversationMapper.insert(cloneIgnoreId(dbConversation, o -> o.setCreateTime(null))); // 准备参数 ImConversationPageReqVO reqVO = new ImConversationPageReqVO(); reqVO.setUserId(null); diff --git a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java new file mode 100644 index 0000000000..4876a524a1 --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.im.service.group; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.im.controller.admin.group.vo.*; +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; +import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.springframework.context.annotation.Import; + +import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link ImGroupServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ImGroupServiceImpl.class) +public class ImGroupServiceImplTest extends BaseDbUnitTest { + + @Resource + private ImGroupServiceImpl groupService; + + @Resource + private ImGroupMapper imGroupMapper; + + @Test + public void testCreateGroup_success() { + // 准备参数 + ImGroupSaveReqVO createReqVO = randomPojo(ImGroupSaveReqVO.class).setId(null); + + // 调用 + Long groupId = groupService.createGroup(createReqVO); + // 断言 + assertNotNull(groupId); + // 校验记录的属性是否正确 + ImGroupDO group = imGroupMapper.selectById(groupId); + assertPojoEquals(createReqVO, group, "id"); + } + + @Test + public void testUpdateGroup_success() { + // mock 数据 + ImGroupDO dbGroup = randomPojo(ImGroupDO.class); + imGroupMapper.insert(dbGroup);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ImGroupSaveReqVO updateReqVO = randomPojo(ImGroupSaveReqVO.class, o -> { + o.setId(dbGroup.getId()); // 设置更新的 ID + }); + + // 调用 + groupService.updateGroup(updateReqVO); + // 校验是否更新正确 + ImGroupDO group = imGroupMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, group); + } + + @Test + public void testUpdateGroup_notExists() { + // 准备参数 + ImGroupSaveReqVO updateReqVO = randomPojo(ImGroupSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> groupService.updateGroup(updateReqVO), GROUP_NOT_EXISTS); + } + + @Test + public void testDeleteGroup_success() { + // mock 数据 + ImGroupDO dbGroup = randomPojo(ImGroupDO.class); + imGroupMapper.insert(dbGroup);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbGroup.getId(); + + // 调用 + groupService.deleteGroup(id); + // 校验数据不存在了 + assertNull(imGroupMapper.selectById(id)); + } + + @Test + public void testDeleteGroup_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> groupService.deleteGroup(id), GROUP_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetGroupPage() { + // mock 数据 + ImGroupDO dbGroup = randomPojo(ImGroupDO.class, o -> { // 等会查询到 + o.setGroupName(null); + o.setOwnerId(null); + o.setHeadImage(null); + o.setHeadImageThumb(null); + o.setNotice(null); + o.setRemark(null); + o.setCreateTime(null); + }); + imGroupMapper.insert(dbGroup); + // 测试 groupName 不匹配 + imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setGroupName(null))); + // 测试 ownerId 不匹配 + imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setOwnerId(null))); + // 测试 headImage 不匹配 + imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setHeadImage(null))); + // 测试 headImageThumb 不匹配 + imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setHeadImageThumb(null))); + // 测试 notice 不匹配 + imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setNotice(null))); + // 测试 remark 不匹配 + imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setRemark(null))); + // 测试 createTime 不匹配 + imGroupMapper.insert(cloneIgnoreId(dbGroup, o -> o.setCreateTime(null))); + // 准备参数 + ImGroupPageReqVO reqVO = new ImGroupPageReqVO(); + reqVO.setGroupName(null); + reqVO.setOwnerId(null); + reqVO.setHeadImage(null); + reqVO.setHeadImageThumb(null); + reqVO.setNotice(null); + reqVO.setRemark(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = groupService.getGroupPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbGroup, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImplTest.java b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImplTest.java new file mode 100644 index 0000000000..394807ce0a --- /dev/null +++ b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/groupmember/ImGroupMemberServiceImplTest.java @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.im.service.groupmember; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.im.controller.admin.groupmember.vo.*; +import cn.iocoder.yudao.module.im.dal.dataobject.groupmember.GroupMemberDO; +import cn.iocoder.yudao.module.im.dal.mysql.groupmember.ImGroupMemberMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.springframework.context.annotation.Import; + +import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link ImGroupMemberServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ImGroupMemberServiceImpl.class) +public class ImGroupMemberServiceImplTest extends BaseDbUnitTest { + + @Resource + private ImGroupMemberServiceImpl groupMemberService; + + @Resource + private ImGroupMemberMapper imGroupMemberMapper; + + @Test + public void testCreateGroupMember_success() { + // 准备参数 + ImGroupMemberSaveReqVO createReqVO = randomPojo(ImGroupMemberSaveReqVO.class).setId(null); + + // 调用 + Long groupMemberId = groupMemberService.createGroupMember(createReqVO); + // 断言 + assertNotNull(groupMemberId); + // 校验记录的属性是否正确 + GroupMemberDO groupMember = imGroupMemberMapper.selectById(groupMemberId); + assertPojoEquals(createReqVO, groupMember, "id"); + } + + @Test + public void testUpdateGroupMember_success() { + // mock 数据 + GroupMemberDO dbGroupMember = randomPojo(GroupMemberDO.class); + imGroupMemberMapper.insert(dbGroupMember);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ImGroupMemberSaveReqVO updateReqVO = randomPojo(ImGroupMemberSaveReqVO.class, o -> { + o.setId(dbGroupMember.getId()); // 设置更新的 ID + }); + + // 调用 + groupMemberService.updateGroupMember(updateReqVO); + // 校验是否更新正确 + GroupMemberDO groupMember = imGroupMemberMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, groupMember); + } + + @Test + public void testUpdateGroupMember_notExists() { + // 准备参数 + ImGroupMemberSaveReqVO updateReqVO = randomPojo(ImGroupMemberSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> groupMemberService.updateGroupMember(updateReqVO), GROUP_MEMBER_NOT_EXISTS); + } + + @Test + public void testDeleteGroupMember_success() { + // mock 数据 + GroupMemberDO dbGroupMember = randomPojo(GroupMemberDO.class); + imGroupMemberMapper.insert(dbGroupMember);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbGroupMember.getId(); + + // 调用 + groupMemberService.deleteGroupMember(id); + // 校验数据不存在了 + assertNull(imGroupMemberMapper.selectById(id)); + } + + @Test + public void testDeleteGroupMember_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> groupMemberService.deleteGroupMember(id), GROUP_MEMBER_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetGroupMemberPage() { + // mock 数据 + GroupMemberDO dbGroupMember = randomPojo(GroupMemberDO.class, o -> { // 等会查询到 + o.setGroupId(null); + o.setUserId(null); + o.setNickname(null); + o.setAvatar(null); + o.setAliasName(null); + o.setRemark(null); + o.setCreateTime(null); + }); + imGroupMemberMapper.insert(dbGroupMember); + // 测试 groupId 不匹配 + imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setGroupId(null))); + // 测试 userId 不匹配 + imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setUserId(null))); + // 测试 nickname 不匹配 + imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setNickname(null))); + // 测试 avatar 不匹配 + imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setAvatar(null))); + // 测试 aliasName 不匹配 + imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setAliasName(null))); + // 测试 remark 不匹配 + imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setRemark(null))); + // 测试 createTime 不匹配 + imGroupMemberMapper.insert(cloneIgnoreId(dbGroupMember, o -> o.setCreateTime(null))); + // 准备参数 + ImGroupMemberPageReqVO reqVO = new ImGroupMemberPageReqVO(); + reqVO.setGroupId(null); + reqVO.setUserId(null); + reqVO.setNickname(null); + reqVO.setAvatar(null); + reqVO.setAliasName(null); + reqVO.setRemark(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = groupMemberService.getGroupMemberPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbGroupMember, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImplTest.java b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImplTest.java index 815926e2b2..82244294f5 100755 --- a/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImplTest.java +++ b/yudao-module-im/yudao-module-im-biz/src/test/java/cn/iocoder/yudao/module/im/service/inbox/ImInboxServiceImplTest.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.im.controller.admin.inbox.vo.*; import cn.iocoder.yudao.module.im.dal.dataobject.inbox.ImInboxDO; -import cn.iocoder.yudao.module.im.dal.mysql.inbox.InboxMapper; +import cn.iocoder.yudao.module.im.dal.mysql.inbox.ImInboxMapper; import cn.iocoder.yudao.framework.common.pojo.PageResult; import org.springframework.context.annotation.Import; @@ -33,7 +33,7 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest { private ImInboxServiceImpl inboxService; @Resource - private InboxMapper inboxMapper; + private ImInboxMapper imInboxMapper; @Test public void testCreateInbox_success() { @@ -45,7 +45,7 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest { // 断言 assertNotNull(inboxId); // 校验记录的属性是否正确 - ImInboxDO inbox = inboxMapper.selectById(inboxId); + ImInboxDO inbox = imInboxMapper.selectById(inboxId); assertPojoEquals(createReqVO, inbox, "id"); } @@ -53,7 +53,7 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest { public void testUpdateInbox_success() { // mock 数据 ImInboxDO dbInbox = randomPojo(ImInboxDO.class); - inboxMapper.insert(dbInbox);// @Sql: 先插入出一条存在的数据 + imInboxMapper.insert(dbInbox);// @Sql: 先插入出一条存在的数据 // 准备参数 ImInboxSaveReqVO updateReqVO = randomPojo(ImInboxSaveReqVO.class, o -> { o.setId(dbInbox.getId()); // 设置更新的 ID @@ -62,7 +62,7 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest { // 调用 inboxService.updateInbox(updateReqVO); // 校验是否更新正确 - ImInboxDO inbox = inboxMapper.selectById(updateReqVO.getId()); // 获取最新的 + ImInboxDO inbox = imInboxMapper.selectById(updateReqVO.getId()); // 获取最新的 assertPojoEquals(updateReqVO, inbox); } @@ -79,14 +79,14 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest { public void testDeleteInbox_success() { // mock 数据 ImInboxDO dbInbox = randomPojo(ImInboxDO.class); - inboxMapper.insert(dbInbox);// @Sql: 先插入出一条存在的数据 + imInboxMapper.insert(dbInbox);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbInbox.getId(); // 调用 inboxService.deleteInbox(id); // 校验数据不存在了 - assertNull(inboxMapper.selectById(id)); + assertNull(imInboxMapper.selectById(id)); } @Test @@ -108,15 +108,15 @@ public class ImInboxServiceImplTest extends BaseDbUnitTest { o.setSequence(null); o.setCreateTime(null); }); - inboxMapper.insert(dbInbox); + imInboxMapper.insert(dbInbox); // 测试 userId 不匹配 - inboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setUserId(null))); + imInboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setUserId(null))); // 测试 messageId 不匹配 - inboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setMessageId(null))); + imInboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setMessageId(null))); // 测试 sequence 不匹配 - inboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setSequence(null))); + imInboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setSequence(null))); // 测试 createTime 不匹配 - inboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setCreateTime(null))); + imInboxMapper.insert(cloneIgnoreId(dbInbox, o -> o.setCreateTime(null))); // 准备参数 ImInboxPageReqVO reqVO = new ImInboxPageReqVO(); reqVO.setUserId(null);