From fc90635abbf739518f18204ceeae90f3f00e748e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 30 Apr 2026 14:07:39 +0800 Subject: [PATCH] ✨ feat(im): 新增 friend、group 等管理后台接口 --- yudao-dependencies/pom.xml | 7 +++++++ yudao-module-im/pom.xml | 4 +--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/friend/ImFriendManagerController.java | 30 +++++++++++++++++++++++++++++- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupManagerController.java | 30 +++++++++++++++++++++++++++++- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupMemberManagerController.java | 25 ++++++++++++++++++++++++- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/vo/ImGroupManagerPageReqVO.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImGroupMessageManagerController.java | 34 ++++++++++++++++++++++++++++++++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImPrivateMessageManagerController.java | 29 +++++++++++++++++++++++++++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java | 9 ++++----- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java | 8 ++++---- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordPageReqVO.java | 4 ++-- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordSaveReqVO.java | 5 ++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMemberMapper.java | 1 - yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/sensitiveword/ImSensitiveWordMapper.java | 6 ++++++ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordConfiguration.java | 32 -------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordDeny.java | 36 ------------------------------------ yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendService.java | 5 ++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java | 31 +++++-------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java | 11 ----------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java | 28 ---------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java | 5 +---- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java | 23 ++--------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageService.java | 5 ++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java | 29 ++--------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageService.java | 5 ++--- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java | 34 +++------------------------------- yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/sensitiveword/ImSensitiveWordServiceImpl.java | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- 27 files changed, 282 insertions(+), 278 deletions(-) delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordConfiguration.java delete mode 100644 yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordDeny.java diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index fa180b4..07be435 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -50,6 +50,7 @@ 1.4.0 1.21.2 + 0.29.5 1.18.42 1.6.3 5.8.42 @@ -558,6 +559,12 @@ ${jsoup.version} + + com.github.houbb + sensitive-word + ${sensitive-word.version} + + io.vertx diff --git a/yudao-module-im/pom.xml b/yudao-module-im/pom.xml index 8f2f096..18354f6 100644 --- a/yudao-module-im/pom.xml +++ b/yudao-module-im/pom.xml @@ -62,12 +62,10 @@ yudao-spring-boot-starter-excel - - + com.github.houbb sensitive-word - 0.29.5 diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/friend/ImFriendManagerController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/friend/ImFriendManagerController.java index d5f07ea..b2f6ae7 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/friend/ImFriendManagerController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/friend/ImFriendManagerController.java @@ -1,10 +1,16 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.friend; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.manager.friend.vo.ImFriendManagerPageReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.friend.vo.ImFriendManagerRespVO; +import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendDO; import cn.iocoder.yudao.module.im.service.friend.ImFriendService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -15,7 +21,12 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; @Tag(name = "管理后台 - IM 好友管理") @RestController @@ -25,13 +36,30 @@ public class ImFriendManagerController { @Resource private ImFriendService friendService; + @Resource + private AdminUserApi adminUserApi; @GetMapping("/page") @Operation(summary = "获得好友关系分页") @PreAuthorize("@ss.hasPermission('im:manager:friend:query')") public CommonResult> getFriendPage( @Valid ImFriendManagerPageReqVO pageReqVO) { - return success(friendService.getFriendPage(pageReqVO)); + // 1. 分页查询 + PageResult pageResult = friendService.getFriendPage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + // 2.1 一次性批量查询用户 + 好友的昵称 + Set userIds = convertSetByFlatMap(pageResult.getList(), + f -> Stream.of(f.getUserId(), f.getFriendUserId())); + Map userMap = adminUserApi.getUserMap(userIds); + // 2.2 转换为 VO,填充昵称 + return success(BeanUtils.toBean(pageResult, ImFriendManagerRespVO.class, vo -> { + MapUtils.findAndThen(userMap, vo.getUserId(), + user -> vo.setUserNickname(user.getNickname())); + MapUtils.findAndThen(userMap, vo.getFriendUserId(), + user -> vo.setFriendNickname(user.getNickname())); + })); } } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupManagerController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupManagerController.java index 2779d5b..1da326d 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupManagerController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupManagerController.java @@ -1,13 +1,18 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.group; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerBanReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerPageReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerRespVO; import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; +import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService; import cn.iocoder.yudao.module.im.service.group.ImGroupService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -17,7 +22,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.Map; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - IM 群聊管理") @RestController @@ -27,12 +35,32 @@ public class ImGroupManagerController { @Resource private ImGroupService groupService; + @Resource + private ImGroupMemberService groupMemberService; + + @Resource + private AdminUserApi adminUserApi; @GetMapping("/page") @Operation(summary = "获得群分页") @PreAuthorize("@ss.hasPermission('im:manager:group:query')") public CommonResult> getGroupPage(@Valid ImGroupManagerPageReqVO pageReqVO) { - return success(groupService.getGroupPage(pageReqVO)); + // 1. 分页查询群 + PageResult pageResult = groupService.getGroupPage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + // 2.1 批量查询相关数据 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), ImGroupDO::getOwnerUserId)); + Map memberCountMap = groupMemberService.getActiveMemberCountMap( + convertSet(pageResult.getList(), ImGroupDO::getId)); + // 2.2 转换为 VO,填充群主昵称、群成员数量 + return success(BeanUtils.toBean(pageResult, ImGroupManagerRespVO.class, vo -> { + MapUtils.findAndThen(userMap, vo.getOwnerUserId(), + user -> vo.setOwnerNickname(user.getNickname())); + vo.setMemberCount(memberCountMap.getOrDefault(vo.getId(), 0L).intValue()); + })); } @GetMapping("/get") diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupMemberManagerController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupMemberManagerController.java index 88192b6..e08c78d 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupMemberManagerController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/ImGroupMemberManagerController.java @@ -1,8 +1,14 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.group; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.member.ImGroupMemberManagerRespVO; +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; import cn.iocoder.yudao.module.im.service.group.ImGroupMemberService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -14,9 +20,13 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - IM 群成员管理") @RestController @@ -26,13 +36,26 @@ public class ImGroupMemberManagerController { @Resource private ImGroupMemberService groupMemberService; + @Resource + private AdminUserApi adminUserApi; @GetMapping("/list") @Operation(summary = "获得群成员列表") @Parameter(name = "groupId", description = "群编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('im:manager:group:query')") public CommonResult> getGroupMemberList(@RequestParam("groupId") Long groupId) { - return success(groupMemberService.getGroupMemberList(groupId)); + // 1. 查询有效群成员 + List members = groupMemberService.getActiveGroupMemberListByGroupId(groupId); + if (CollUtil.isEmpty(members)) { + return success(Collections.emptyList()); + } + // 2.1 批量查询用户信息 + Map userMap = adminUserApi.getUserMap( + convertSet(members, ImGroupMemberDO::getUserId)); + // 2.2 转换为 VO,填充昵称、头像 + return success(BeanUtils.toBean(members, ImGroupMemberManagerRespVO.class, vo -> + MapUtils.findAndThen(userMap, vo.getUserId(), user -> + vo.setNickname(user.getNickname()).setAvatar(user.getAvatar())))); } } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/vo/ImGroupManagerPageReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/vo/ImGroupManagerPageReqVO.java index 1efdc15..6abb081 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/vo/ImGroupManagerPageReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/group/vo/ImGroupManagerPageReqVO.java @@ -21,8 +21,8 @@ public class ImGroupManagerPageReqVO extends PageParam { @Schema(description = "群主用户编号", example = "1024") private Long ownerUserId; - @Schema(description = "群状态,参见 CommonStatusEnum 枚举类(0 正常 / 1 已解散)", example = "0") - private Integer status; + @Schema(description = "群状态", example = "0") + private Integer status; // 参见 CommonStatusEnum 枚举类(0 正常 / 1 已解散) @Schema(description = "是否封禁", example = "false") private Boolean banned; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImGroupMessageManagerController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImGroupMessageManagerController.java index 6e1f9c2..03b4a16 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImGroupMessageManagerController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImGroupMessageManagerController.java @@ -1,12 +1,18 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.message; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.group.ImGroupMessageManagerPageReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.group.ImGroupMessageManagerRespVO; +import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO; +import cn.iocoder.yudao.module.im.service.group.ImGroupService; import cn.iocoder.yudao.module.im.service.message.ImGroupMessageService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -14,9 +20,15 @@ import jakarta.annotation.Resource; import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - IM 群聊消息") @RestController @@ -26,13 +38,31 @@ public class ImGroupMessageManagerController { @Resource private ImGroupMessageService groupMessageService; + @Resource + private ImGroupService groupService; + @Resource + private AdminUserApi adminUserApi; @GetMapping("/page") @Operation(summary = "获得群聊消息分页") @PreAuthorize("@ss.hasPermission('im:manager:message:query')") public CommonResult> getGroupMessagePage( @Valid ImGroupMessageManagerPageReqVO pageReqVO) { - return success(groupMessageService.getGroupMessagePage(pageReqVO)); + // 1. 分页查询 + PageResult pageResult = groupMessageService.getGroupMessagePage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + // 2.1 批量查询群名称、发送人昵称 + Map groupMap = groupService.getGroupMap( + convertSet(pageResult.getList(), ImGroupMessageDO::getGroupId)); + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), ImGroupMessageDO::getSenderId)); + // 2.2 转换为 VO,填充群名 / 发送人昵称 + return success(BeanUtils.toBean(pageResult, ImGroupMessageManagerRespVO.class, vo -> { + MapUtils.findAndThen(groupMap, vo.getGroupId(), group -> vo.setGroupName(group.getName())); + MapUtils.findAndThen(userMap, vo.getSenderId(), user -> vo.setSenderNickname(user.getNickname())); + })); } @GetMapping("/get") diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImPrivateMessageManagerController.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImPrivateMessageManagerController.java index 67fb34c..8db5b69 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImPrivateMessageManagerController.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/ImPrivateMessageManagerController.java @@ -1,12 +1,16 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.message; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.privates.ImPrivateMessageManagerPageReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.privates.ImPrivateMessageManagerRespVO; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO; import cn.iocoder.yudao.module.im.service.message.ImPrivateMessageService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -14,9 +18,16 @@ import jakarta.annotation.Resource; import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; +import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; @Tag(name = "管理后台 - IM 私聊消息") @RestController @@ -26,13 +37,27 @@ public class ImPrivateMessageManagerController { @Resource private ImPrivateMessageService privateMessageService; + @Resource + private AdminUserApi adminUserApi; @GetMapping("/page") @Operation(summary = "获得私聊消息分页") @PreAuthorize("@ss.hasPermission('im:manager:message:query')") public CommonResult> getPrivateMessagePage( @Valid ImPrivateMessageManagerPageReqVO pageReqVO) { - return success(privateMessageService.getPrivateMessagePage(pageReqVO)); + // 1. 分页查询 + PageResult pageResult = privateMessageService.getPrivateMessagePage(pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + // 2.1 一次性批量查询发送人 + 接收人昵称 + Map userMap = adminUserApi.getUserMap(convertSetByFlatMap(pageResult.getList(), + m -> Stream.of(m.getSenderId(), m.getReceiverId()))); + // 2.2 转换为 VO,填充昵称 + return success(BeanUtils.toBean(pageResult, ImPrivateMessageManagerRespVO.class, vo -> { + MapUtils.findAndThen(userMap, vo.getSenderId(), user -> vo.setSenderNickname(user.getNickname())); + MapUtils.findAndThen(userMap, vo.getReceiverId(), user -> vo.setReceiverNickname(user.getNickname())); + })); } @GetMapping("/get") diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java index 1ce4a7c..af3ea38 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/group/ImGroupMessageManagerPageReqVO.java @@ -21,12 +21,11 @@ public class ImGroupMessageManagerPageReqVO extends PageParam { @Schema(description = "发送人编号", example = "1024") private Long senderId; - // TODO @AI:参见 ImMessageTypeEnum 枚举类,都放到 // 注释后面。注意加到我的 memory 里。其它类似也处理下。im 的。 - @Schema(description = "消息类型,参见 ImMessageTypeEnum 枚举类", example = "1") - private Integer type; + @Schema(description = "消息类型", example = "1") + private Integer type; // 参见 ImMessageTypeEnum 枚举类 - @Schema(description = "消息状态,参见 ImMessageStatusEnum 枚举类", example = "0") - private Integer status; + @Schema(description = "消息状态", example = "0") + private Integer status; // 参见 ImMessageStatusEnum 枚举类 @Schema(description = "发送时间", example = "[2026-04-01 00:00:00, 2026-04-30 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java index 95b19d2..36c6feb 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/message/vo/privates/ImPrivateMessageManagerPageReqVO.java @@ -21,11 +21,11 @@ public class ImPrivateMessageManagerPageReqVO extends PageParam { @Schema(description = "接收人编号", example = "2048") private Long receiverId; - @Schema(description = "消息类型,参见 ImMessageTypeEnum 枚举类", example = "1") - private Integer type; + @Schema(description = "消息类型", example = "1") + private Integer type; // 参见 ImMessageTypeEnum 枚举类 - @Schema(description = "消息状态,参见 ImMessageStatusEnum 枚举类", example = "0") - private Integer status; + @Schema(description = "消息状态", example = "0") + private Integer status; // 参见 ImMessageStatusEnum 枚举类 @Schema(description = "发送时间", example = "[2026-04-01 00:00:00, 2026-04-30 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordPageReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordPageReqVO.java index 36c25e9..302e002 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordPageReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordPageReqVO.java @@ -18,8 +18,8 @@ public class ImSensitiveWordPageReqVO extends PageParam { @Schema(description = "敏感词,模糊匹配", example = "敏感") private String word; - @Schema(description = "状态,参见 CommonStatusEnum 枚举类(0 启用 / 1 禁用)", example = "0") - private Integer status; + @Schema(description = "状态", example = "0") + private Integer status; // 参见 CommonStatusEnum 枚举类(0 启用 / 1 禁用) @Schema(description = "创建时间", example = "[2026-04-01 00:00:00, 2026-04-30 23:59:59]") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordSaveReqVO.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordSaveReqVO.java index c7c57a9..d88d826 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordSaveReqVO.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/sensitiveword/vo/ImSensitiveWordSaveReqVO.java @@ -18,9 +18,8 @@ public class ImSensitiveWordSaveReqVO { @Size(max = 64, message = "敏感词长度不能超过 64") private String word; - @Schema(description = "状态,参见 CommonStatusEnum 枚举类(0 启用 / 1 禁用)", - requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @NotNull(message = "状态不能为空") - private Integer status; + private Integer status; // 参见 CommonStatusEnum 枚举类(0 启用 / 1 禁用) } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMemberMapper.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMemberMapper.java index b69a09b..afffef6 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMemberMapper.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupMemberMapper.java @@ -90,7 +90,6 @@ public interface ImGroupMemberMapper extends BaseMapperX { if (CollUtil.isEmpty(groupIds)) { return Collections.emptyMap(); } - // TODO @AI:使用 mybatis plus join,可以简化这个操作么? List> rows = selectMaps(Wrappers.query() .select("group_id AS groupId", "COUNT(*) AS cnt") .in("group_id", groupIds) diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/sensitiveword/ImSensitiveWordMapper.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/sensitiveword/ImSensitiveWordMapper.java index 2b33b78..ccf3f2b 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/sensitiveword/ImSensitiveWordMapper.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/sensitiveword/ImSensitiveWordMapper.java @@ -6,7 +6,10 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.im.controller.admin.manager.sensitiveword.vo.ImSensitiveWordPageReqVO; import cn.iocoder.yudao.module.im.dal.dataobject.sensitiveword.ImSensitiveWordDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import java.time.LocalDateTime; import java.util.List; /** @@ -35,4 +38,7 @@ public interface ImSensitiveWordMapper extends BaseMapperX { .orderByDesc(ImSensitiveWordDO::getId)); } + @Select("SELECT MAX(update_time) FROM im_sensitive_word") + LocalDateTime selectMaxUpdateTime(@Param("tenantId") Long tenantId); + } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordConfiguration.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordConfiguration.java deleted file mode 100644 index 44c51c7..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordConfiguration.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.im.framework.sensitiveword; - -import com.github.houbb.sensitive.word.bs.SensitiveWordBs; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * IM 敏感词检测配置 - * - * @author 芋道源码 - */ -@Configuration -public class ImSensitiveWordConfiguration { - - // TODO @AI:可能需要按需创建;因为多租户。 - /** - * 装配 {@link SensitiveWordBs}: - * 词库来源 = {@link ImSensitiveWordDeny}(DB 里启用的敏感词),并开启常用规范化能力。 - */ - @Bean - public SensitiveWordBs sensitiveWordBs(ImSensitiveWordDeny imSensitiveWordDeny) { - return SensitiveWordBs.newInstance() - .wordDeny(imSensitiveWordDeny) - .ignoreCase(true) - .ignoreWidth(true) // 忽略全/半角 - .ignoreNumStyle(true) // 忽略数字风格(中文/阿拉伯) - .ignoreChineseStyle(true) // 忽略繁简体 - .enableWordCheck(true) - .init(); - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordDeny.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordDeny.java deleted file mode 100644 index 34e8b7c..0000000 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/framework/sensitiveword/ImSensitiveWordDeny.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.im.framework.sensitiveword; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.module.im.dal.dataobject.sensitiveword.ImSensitiveWordDO; -import cn.iocoder.yudao.module.im.dal.mysql.sensitiveword.ImSensitiveWordMapper; -import com.github.houbb.sensitive.word.api.IWordDeny; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Component; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -// TODO @AI:是不是可以,直接塞入一个数组。而不是这里查询??? -/** - * 自定义敏感词数据来源:从 im_sensitive_word 表加载启用状态的敏感词 - *

- * 由 {@link com.github.houbb.sensitive.word.bs.SensitiveWordBs} 在 init() 时回调, - * 因此 CRUD 完成后调用 sensitiveWordBs.init() 即可实现热更新。 - * - * @author 芋道源码 - */ -@Component -public class ImSensitiveWordDeny implements IWordDeny { - - @Resource - private ImSensitiveWordMapper sensitiveWordMapper; - - @Override - public List deny() { - return convertList( - sensitiveWordMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()), - ImSensitiveWordDO::getWord); - } - -} diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendService.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendService.java index a14fe0d..bdedc73 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendService.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendService.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.im.service.friend; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.im.controller.admin.friend.vo.ImFriendUpdateReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.friend.vo.ImFriendManagerPageReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.friend.vo.ImFriendManagerRespVO; import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendDO; import java.util.Collection; @@ -90,8 +89,8 @@ public interface ImFriendService { // ==================== 管理后台 ==================== /** - * 【管理后台】分页查询好友关系(已填充用户 / 好友昵称) + * 【管理后台】分页查询好友关系 */ - PageResult getFriendPage(ImFriendManagerPageReqVO reqVO); + PageResult getFriendPage(ImFriendManagerPageReqVO reqVO); } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java index 14e2091..1e503cd 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImpl.java @@ -1,21 +1,16 @@ package cn.iocoder.yudao.module.im.service.friend; -import cn.hutool.core.collection.CollUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.friend.vo.ImFriendUpdateReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.friend.vo.ImFriendManagerPageReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.friend.vo.ImFriendManagerRespVO; import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendDO; import cn.iocoder.yudao.module.im.dal.mysql.friend.ImFriendMapper; import cn.iocoder.yudao.module.im.service.message.ImPrivateMessageService; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; @@ -27,10 +22,11 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.im.dal.redis.RedisKeyConstants.FRIEND; import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FRIEND_ADD_SELF; import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FRIEND_NOT_FRIEND; @@ -189,26 +185,9 @@ public class ImFriendServiceImpl implements ImFriendService { // ==================== 管理后台 ==================== - // TODO @AI:拿到 controller 拼接数据,简化 service; @Override - public PageResult getFriendPage(ImFriendManagerPageReqVO reqVO) { - // 1. 分页查询 - PageResult pageResult = imFriendMapper.selectPage(reqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return PageResult.empty(pageResult.getTotal()); - } - - // 2. 一次性批量查询用户 + 好友的昵称 - Set userIds = new HashSet<>(); - userIds.addAll(convertSet(pageResult.getList(), ImFriendDO::getUserId)); - userIds.addAll(convertSet(pageResult.getList(), ImFriendDO::getFriendUserId)); - Map userMap = adminUserApi.getUserMap(userIds); - - // 3. 转换为 VO,填充昵称 - return BeanUtils.toBean(pageResult, ImFriendManagerRespVO.class, vo -> { - MapUtils.findAndThen(userMap, vo.getUserId(), user -> vo.setUserNickname(user.getNickname())); - MapUtils.findAndThen(userMap, vo.getFriendUserId(), user -> vo.setFriendNickname(user.getNickname())); - }); + public PageResult getFriendPage(ImFriendManagerPageReqVO reqVO) { + return imFriendMapper.selectPage(reqVO); } } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java index 21d46ed..cfb0a4d 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberService.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.im.service.group; import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.member.ImGroupMemberManagerRespVO; import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; import jakarta.validation.Valid; @@ -156,14 +155,4 @@ public interface ImGroupMemberService { */ Map getActiveMemberCountMap(Collection groupIds); - // ==================== 管理后台 ==================== - - /** - * 【管理后台】获取群成员列表 - * - * @param groupId 群编号 - * @return 群成员列表 - */ - List getGroupMemberList(Long groupId); - } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java index b172ebb..b4697e6 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupMemberServiceImpl.java @@ -2,16 +2,12 @@ package cn.iocoder.yudao.module.im.service.group; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberUpdateReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.member.ImGroupMemberManagerRespVO; import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; import cn.iocoder.yudao.module.im.dal.mysql.group.ImGroupMemberMapper; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; @@ -44,9 +40,6 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService { @Resource private ImWebSocketService webSocketService; - @Resource - private AdminUserApi adminUserApi; - @Override public ImGroupMemberDO getGroupMember(Long id) { return groupMemberMapper.selectById(id); @@ -222,25 +215,4 @@ public class ImGroupMemberServiceImpl implements ImGroupMemberService { return groupMemberMapper.selectCountMapByGroupIdsAndStatus(groupIds, CommonStatusEnum.ENABLE.getStatus()); } - // ==================== 管理后台 ==================== - - // TODO @AI:这个拼接的逻辑,拿到 controller,这里只返回 list do; - @Override - public List getGroupMemberList(Long groupId) { - // 1. 查询有效群成员 - List members = getActiveGroupMemberListByGroupId(groupId); - if (CollUtil.isEmpty(members)) { - return Collections.emptyList(); - } - - // 2. 批量查询用户信息 - Set userIds = convertSet(members, ImGroupMemberDO::getUserId); - Map userMap = adminUserApi.getUserMap(userIds); - - // 3. 转换为 VO,填充昵称、头像 - return BeanUtils.toBean(members, ImGroupMemberManagerRespVO.class, vo -> - MapUtils.findAndThen(userMap, vo.getUserId(), user -> - vo.setNickname(user.getNickname()).setAvatar(user.getAvatar()))); - } - } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java index b40768b..281cb64 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupService.java @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMember import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberRemoveReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerBanReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerPageReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerRespVO; import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; import jakarta.validation.Valid; @@ -138,15 +137,13 @@ public interface ImGroupService { // ==================== 管理后台 ==================== - // TODO DONE @AI:是不是 controller 拆分哈;(getGroupPage 留在 ImGroupService;getGroupMemberList 已拆到 ImGroupMemberService + ImGroupMemberManagerController) - // TODO @AI:不对;应该 VO 放在 controller 拼接 /** * 【管理后台】分页查询群列表 * * @param pageReqVO 分页查询条件 * @return 群分页列表 */ - PageResult getGroupPage(ImGroupManagerPageReqVO pageReqVO); + PageResult getGroupPage(ImGroupManagerPageReqVO pageReqVO); /** * 【管理后台】封禁群 diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java index 57c9496..ea8e0e1 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java @@ -8,7 +8,6 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupCreateReqVO; import cn.iocoder.yudao.module.im.controller.admin.group.vo.ImGroupUpdateReqVO; @@ -16,7 +15,6 @@ import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMember import cn.iocoder.yudao.module.im.controller.admin.group.vo.member.ImGroupMemberRemoveReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerBanReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerPageReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.group.vo.ImGroupManagerRespVO; import cn.iocoder.yudao.module.im.dal.dataobject.friend.ImFriendDO; import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; @@ -288,24 +286,8 @@ public class ImGroupServiceImpl implements ImGroupService { // ==================== 管理后台 ==================== @Override - public PageResult getGroupPage(ImGroupManagerPageReqVO pageReqVO) { - // 1. 分页查询群 - PageResult pageResult = groupMapper.selectPage(pageReqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return PageResult.empty(pageResult.getTotal()); - } - - // 2.1 批量查询群主昵称 - Set ownerUserIds = convertSet(pageResult.getList(), ImGroupDO::getOwnerUserId); - Map userMap = adminUserApi.getUserMap(ownerUserIds); - // 2.2 一次 GROUP BY 查出本页所有群的活跃成员数,避免按行 N+1 - Set groupIds = convertSet(pageResult.getList(), ImGroupDO::getId); - Map memberCountMap = groupMemberService.getActiveMemberCountMap(groupIds); - // 2.3 转换为 VO,填充群主昵称、群成员数量 - return BeanUtils.toBean(pageResult, ImGroupManagerRespVO.class, vo -> { - MapUtils.findAndThen(userMap, vo.getOwnerUserId(), user -> vo.setOwnerNickname(user.getNickname())); - vo.setMemberCount(memberCountMap.getOrDefault(vo.getId(), 0L).intValue()); - }); + public PageResult getGroupPage(ImGroupManagerPageReqVO pageReqVO) { + return groupMapper.selectPage(pageReqVO); } @Override @@ -328,7 +310,6 @@ public class ImGroupServiceImpl implements ImGroupService { throw exception(GROUP_NOT_EXISTS); } // 2. 解封(保留 bannedReason / bannedTime 作为历史记录) - // TODO DONE @AI:不要使用 mybatis plus 的方法,直接操作。另外,感觉封禁时间、封禁原因,没必要置空,留着问题不大。 groupMapper.updateById(new ImGroupDO().setId(id).setBanned(false)); } diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageService.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageService.java index ae89515..3551018 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageService.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageService.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.im.service.message; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.group.ImGroupMessageManagerPageReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.group.ImGroupMessageManagerRespVO; import cn.iocoder.yudao.module.im.controller.admin.message.vo.group.ImGroupMessageListReqVO; import cn.iocoder.yudao.module.im.controller.admin.message.vo.group.ImGroupMessageSendReqVO; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO; @@ -118,9 +117,9 @@ public interface ImGroupMessageService { // ==================== 管理后台 ==================== /** - * 【管理后台】分页查询群聊消息(已填充群名称、发送人昵称) + * 【管理后台】分页查询群聊消息 */ - PageResult getGroupMessagePage(ImGroupMessageManagerPageReqVO reqVO); + PageResult getGroupMessagePage(ImGroupMessageManagerPageReqVO reqVO); /** * 【管理后台】获取群聊消息详情 diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java index 145f018..0590ce4 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImGroupMessageServiceImpl.java @@ -7,14 +7,11 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.group.ImGroupMessageManagerPageReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.group.ImGroupMessageManagerRespVO; import cn.iocoder.yudao.module.im.controller.admin.message.vo.group.ImGroupMessageListReqVO; import cn.iocoder.yudao.module.im.controller.admin.message.vo.group.ImGroupMessageSendReqVO; -import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupDO; import cn.iocoder.yudao.module.im.dal.dataobject.group.ImGroupMemberDO; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImGroupMessageDO; import cn.iocoder.yudao.module.im.dal.mysql.message.ImGroupMessageMapper; @@ -28,8 +25,6 @@ import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; import cn.iocoder.yudao.module.im.service.websocket.dto.ImGroupMessageDTO; import cn.iocoder.yudao.module.im.service.websocket.dto.message.RecallMessage; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; @@ -77,9 +72,6 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService { @Resource private ImWebSocketService imWebSocketService; - @Resource - private AdminUserApi adminUserApi; - @Override public ImGroupMessageDO sendGroupMessage(Long senderId, ImGroupMessageSendReqVO reqVO) { // 1.1 幂等校验:根据 senderId + clientMessageId 查重 @@ -554,26 +546,9 @@ public class ImGroupMessageServiceImpl implements ImGroupMessageService { // ==================== 管理后台 ==================== - // TODO @AI:这些挪到 controller 拼接 VO @Override - public PageResult getGroupMessagePage(ImGroupMessageManagerPageReqVO reqVO) { - // 1. 分页查询 - PageResult pageResult = groupMessageMapper.selectPage(reqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return PageResult.empty(pageResult.getTotal()); - } - - // 2. 批量查询群名称、发送人昵称 - Set groupIds = convertSet(pageResult.getList(), ImGroupMessageDO::getGroupId); - Set senderIds = convertSet(pageResult.getList(), ImGroupMessageDO::getSenderId); - Map groupMap = groupService.getGroupMap(groupIds); - Map userMap = adminUserApi.getUserMap(senderIds); - - // 3. 转换为 VO,填充群名 / 发送人昵称 - return BeanUtils.toBean(pageResult, ImGroupMessageManagerRespVO.class, vo -> { - MapUtils.findAndThen(groupMap, vo.getGroupId(), group -> vo.setGroupName(group.getName())); - MapUtils.findAndThen(userMap, vo.getSenderId(), user -> vo.setSenderNickname(user.getNickname())); - }); + public PageResult getGroupMessagePage(ImGroupMessageManagerPageReqVO reqVO) { + return groupMessageMapper.selectPage(reqVO); } @Override diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageService.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageService.java index 407eda0..1dfd668 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageService.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageService.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.im.service.message; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.privates.ImPrivateMessageManagerPageReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.privates.ImPrivateMessageManagerRespVO; import cn.iocoder.yudao.module.im.controller.admin.message.vo.privates.ImPrivateMessageListReqVO; import cn.iocoder.yudao.module.im.controller.admin.message.vo.privates.ImPrivateMessageSendReqVO; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO; @@ -91,9 +90,9 @@ public interface ImPrivateMessageService { // ==================== 管理后台 ==================== /** - * 【管理后台】分页查询私聊消息(已填充发送人 / 接收人昵称) + * 【管理后台】分页查询私聊消息 */ - PageResult getPrivateMessagePage(ImPrivateMessageManagerPageReqVO reqVO); + PageResult getPrivateMessagePage(ImPrivateMessageManagerPageReqVO reqVO); /** * 【管理后台】获取私聊消息详情 diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java index 49ac482..a9b8fd6 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImpl.java @@ -1,15 +1,12 @@ package cn.iocoder.yudao.module.im.service.message; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.privates.ImPrivateMessageManagerPageReqVO; -import cn.iocoder.yudao.module.im.controller.admin.manager.message.vo.privates.ImPrivateMessageManagerRespVO; import cn.iocoder.yudao.module.im.controller.admin.message.vo.privates.ImPrivateMessageListReqVO; import cn.iocoder.yudao.module.im.controller.admin.message.vo.privates.ImPrivateMessageSendReqVO; import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO; @@ -21,8 +18,6 @@ import cn.iocoder.yudao.module.im.service.sensitiveword.ImSensitiveWordService; import cn.iocoder.yudao.module.im.service.websocket.ImWebSocketService; import cn.iocoder.yudao.module.im.service.websocket.dto.ImPrivateMessageDTO; import cn.iocoder.yudao.module.im.service.websocket.dto.message.RecallMessage; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -30,13 +25,9 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.im.enums.ImCommonConstants.*; @@ -61,9 +52,6 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService { @Resource private ImWebSocketService imWebSocketService; - @Resource - private AdminUserApi adminUserApi; - @Override public ImPrivateMessageDO sendPrivateMessage(Long senderId, ImPrivateMessageSendReqVO reqVO) { // 1.1 幂等校验:根据 senderId + clientMessageId 查重 @@ -183,26 +171,10 @@ public class ImPrivateMessageServiceImpl implements ImPrivateMessageService { // ==================== 管理后台 ==================== - // TODO @AI:这些挪到 controller 拼接 VO + // DONE @AI:这些挪到 controller 拼接 VO @Override - public PageResult getPrivateMessagePage(ImPrivateMessageManagerPageReqVO reqVO) { - // 1. 分页查询 - PageResult pageResult = privateMessageMapper.selectPage(reqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return PageResult.empty(pageResult.getTotal()); - } - - // 2. 一次性批量查询发送人 + 接收人昵称 - Set userIds = new HashSet<>(); - userIds.addAll(convertSet(pageResult.getList(), ImPrivateMessageDO::getSenderId)); - userIds.addAll(convertSet(pageResult.getList(), ImPrivateMessageDO::getReceiverId)); - Map userMap = adminUserApi.getUserMap(userIds); - - // 3. 转换为 VO,填充昵称 - return BeanUtils.toBean(pageResult, ImPrivateMessageManagerRespVO.class, vo -> { - MapUtils.findAndThen(userMap, vo.getSenderId(), user -> vo.setSenderNickname(user.getNickname())); - MapUtils.findAndThen(userMap, vo.getReceiverId(), user -> vo.setReceiverNickname(user.getNickname())); - }); + public PageResult getPrivateMessagePage(ImPrivateMessageManagerPageReqVO reqVO) { + return privateMessageMapper.selectPage(reqVO); } @Override diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/sensitiveword/ImSensitiveWordServiceImpl.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/sensitiveword/ImSensitiveWordServiceImpl.java index 1620b9e..3483526 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/sensitiveword/ImSensitiveWordServiceImpl.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/sensitiveword/ImSensitiveWordServiceImpl.java @@ -3,21 +3,35 @@ package cn.iocoder.yudao.module.im.service.sensitiveword; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.cache.CacheUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.im.controller.admin.manager.sensitiveword.vo.ImSensitiveWordPageReqVO; import cn.iocoder.yudao.module.im.controller.admin.manager.sensitiveword.vo.ImSensitiveWordSaveReqVO; import cn.iocoder.yudao.module.im.dal.dataobject.sensitiveword.ImSensitiveWordDO; import cn.iocoder.yudao.module.im.dal.mysql.sensitiveword.ImSensitiveWordMapper; import com.github.houbb.sensitive.word.bs.SensitiveWordBs; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import jakarta.annotation.Resource; +import lombok.AllArgsConstructor; +import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.List; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.MESSAGE_SENSITIVE_WORD_BLOCKED; import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.SENSITIVE_WORD_DUPLICATED; import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.SENSITIVE_WORD_NOT_EXISTS; @@ -37,34 +51,92 @@ public class ImSensitiveWordServiceImpl implements ImSensitiveWordService { @Resource private ImSensitiveWordMapper sensitiveWordMapper; - // TODO @AI:当前节点,立即刷新。其他节点,通过 job 扫描最后更新时间(只要有不同于目前最后一条记录的最大更新时间,就重新构建对应的树)。 /** - * houbb 敏感词检测器,词库由 ImSensitiveWordDeny 在 init 时回调加载 + * 缓存条目 */ - @Resource - private SensitiveWordBs sensitiveWordBs; + @Data + @AllArgsConstructor + private static class SensitiveWordBsCache { + + /** + * 敏感词检测器 + */ + private SensitiveWordBs bs; + /** + * 构建本实例时数据库里的 max(update_time),作为下次刷新比对的基线 + */ + private LocalDateTime maxUpdateTime; + + } - // TODO @AI:你看看现有仓库里,是否有类似这种的。按照最后更新判断,是否需要刷新本地缓存。 /** - * 触发 houbb 词库重新加载(重建 trie) + * 租户 → SensitiveWordBs 实例的本地缓存 *

- * 加 synchronized 是因为 SensitiveWordBs.init() 内部对 wordData 做就地写入, - * 若与并发的 contains() 重叠会读到半构建的 trie。互斥后短暂阻塞 contains 即可保证可见性。 + * 每分钟触发一次异步 reload,先读 max(update_time),没变就复用旧实例(避免 trie 重建),变了才重新读词库 + 重建。 + * 单实例 CRUD 后另外通过 {@link #invalidateSensitiveWordBsCaches()} 立即让本机失效,多实例靠定时刷新最长 1 分钟内收敛。 + */ + @SuppressWarnings({"Convert2Diamond", "NullableProblems"}) + private final LoadingCache sensitiveWordBsCaches = CacheUtils.buildAsyncReloadingCache( + Duration.ofMinutes(1L), // 1 分钟过期 + new CacheLoader() { + + @Override + public SensitiveWordBsCache load(Long tenantId) { + return loadFresh(tenantId); + } + + @Override + public ListenableFuture reload(Long tenantId, SensitiveWordBsCache oldValue) { + // 先比对 max(update_time);没变 → 复用旧实例,避免无谓地重建 trie + LocalDateTime currentMax = sensitiveWordMapper.selectMaxUpdateTime(tenantId); + if (Objects.equals(oldValue.getMaxUpdateTime(), currentMax)) { + return Futures.immediateFuture(oldValue); + } + // 变了 → 重新读词库并重建 trie + return Futures.immediateFuture(loadFresh(tenantId)); + } + + }); + + private SensitiveWordBsCache loadFresh(Long tenantId) { + return TenantUtils.execute(tenantId, () -> { + // 先取基线时间再读词库:反过来在两次查询之间出现的新插入会被漏感知 + LocalDateTime maxUpdateTime = sensitiveWordMapper.selectMaxUpdateTime(tenantId); + List words = sensitiveWordMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); + // 构建敏感词检测器 + SensitiveWordBs bs = SensitiveWordBs.newInstance() + .wordDeny(() -> convertList(words, ImSensitiveWordDO::getWord)) + .ignoreCase(true) + .ignoreWidth(true) // 忽略全/半角 + .ignoreNumStyle(true) // 忽略数字风格(中文/阿拉伯) + .ignoreChineseStyle(true) // 忽略繁简体 + .enableWordCheck(true) + .init(); + return new SensitiveWordBsCache(bs, maxUpdateTime); + }); + } + + /** + * 强制让敏感词缓存失效,下次访问按最新 DB 重建 *

- * init() 本身幂等,单实例可以直接调;多实例部署时需配合 Redis pub/sub 广播让各实例 init。 + * 有租户上下文:仅失效该租户。无租户上下文(如系统级 / 跨租户清理):兜底失效所有租户。 */ - private synchronized void reloadSensitiveWords() { - sensitiveWordBs.init(); - log.info("[reloadSensitiveWords][敏感词库已 reload]"); + private void invalidateSensitiveWordBsCaches() { + Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId != null) { + sensitiveWordBsCaches.invalidate(tenantId); + return; + } + sensitiveWordBsCaches.invalidateAll(); } - // TODO @AI:需要按照租户来。 @Override public void validateText(String text) { if (StrUtil.isBlank(text)) { return; } - if (sensitiveWordBs.contains(text)) { + SensitiveWordBs bs = sensitiveWordBsCaches.getUnchecked(TenantContextHolder.getRequiredTenantId()).getBs(); + if (bs.contains(text)) { throw exception(MESSAGE_SENSITIVE_WORD_BLOCKED); } } @@ -89,9 +161,8 @@ public class ImSensitiveWordServiceImpl implements ImSensitiveWordService { // 2.1 入库 ImSensitiveWordDO word = BeanUtils.toBean(reqVO, ImSensitiveWordDO.class); sensitiveWordMapper.insert(word); - // TODO @AI:houbb 这个注释有点奇怪! - // 2.2 触发 houbb 词库 reload - reloadSensitiveWords(); + // 2.2 强制失效本机缓存(多实例靠定时刷新收敛) + invalidateSensitiveWordBsCaches(); return word.getId(); } @@ -105,9 +176,8 @@ public class ImSensitiveWordServiceImpl implements ImSensitiveWordService { // 2.1 更新 ImSensitiveWordDO updateObj = BeanUtils.toBean(reqVO, ImSensitiveWordDO.class); sensitiveWordMapper.updateById(updateObj); - // 2.2 TODO @AI:houbb 这个注释有点奇怪! - // 2.2 触发 houbb 词库 reload - reloadSensitiveWords(); + // 2.2 强制失效本机缓存 + invalidateSensitiveWordBsCaches(); } @Override @@ -117,8 +187,8 @@ public class ImSensitiveWordServiceImpl implements ImSensitiveWordService { // 2.1 删除 sensitiveWordMapper.deleteById(id); - // 2.2 触发 houbb 词库 reload - reloadSensitiveWords(); + // 2.2 强制失效本机缓存 + invalidateSensitiveWordBsCaches(); } @@ -127,11 +197,10 @@ public class ImSensitiveWordServiceImpl implements ImSensitiveWordService { if (CollUtil.isEmpty(ids)) { return; } - // 1. 删除 sensitiveWordMapper.deleteByIds(ids); - // 触发 houbb 词库 reload - reloadSensitiveWords(); + // 2. 强制失效本机缓存 + invalidateSensitiveWordBsCaches(); } private void validateSensitiveWordExists(Long id) { @@ -148,7 +217,6 @@ public class ImSensitiveWordServiceImpl implements ImSensitiveWordService { if (exist == null) { return; } - // TODO @AI:是不是 id 不用判断 if (id == null || ObjUtil.notEqual(exist.getId(), id)) { throw exception(SENSITIVE_WORD_DUPLICATED, word); } -- libgit2 0.21.4