From d747a0fdaeb4f343ab472a89037c595680fadaf5 Mon Sep 17 00:00:00 2001 From: Timi Date: Tue, 25 Aug 2026 22:55:18 +0800 Subject: [PATCH] add gao user notify --- .../common/controller/NotifyController.java | 91 +++++++++--- .../common/mapper/NotifyDetailMapper.java | 16 +- .../modules/common/mapper/NotifyMapper.java | 25 ++++ .../modules/common/service/NotifyService.java | 29 ++++ .../NotifyDetailServiceImplement.java | 7 +- .../implement/NotifyServiceImplement.java | 58 +++++++- .../common/vo/NotifyManagementItem.java | 57 +++++++ .../gao/controller/GaoNotifyController.java | 140 ++++++++++++++++++ .../api/modules/gao/mapper/GaoUserMapper.java | 5 + .../modules/gao/service/GaoUserService.java | 9 ++ .../implement/GaoUserServiceImplement.java | 14 ++ .../V43__add_notify_management_indexes.sql | 6 + .../timi-server/common/NotifyMapper.xml | 82 ++++++++++ .../mapper/timi-server/gao/GaoUserMapper.xml | 15 ++ 14 files changed, 520 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/imyeyu/api/modules/common/vo/NotifyManagementItem.java create mode 100644 src/main/java/com/imyeyu/api/modules/gao/controller/GaoNotifyController.java create mode 100644 src/main/resources/db/migration/timiserver/V43__add_notify_management_indexes.sql create mode 100644 src/main/resources/mapper/timi-server/common/NotifyMapper.xml create mode 100644 src/main/resources/mapper/timi-server/gao/GaoUserMapper.xml diff --git a/src/main/java/com/imyeyu/api/modules/common/controller/NotifyController.java b/src/main/java/com/imyeyu/api/modules/common/controller/NotifyController.java index 8621182..8e11c24 100644 --- a/src/main/java/com/imyeyu/api/modules/common/controller/NotifyController.java +++ b/src/main/java/com/imyeyu/api/modules/common/controller/NotifyController.java @@ -8,6 +8,7 @@ import com.imyeyu.api.modules.common.entity.NotifyDetail; import com.imyeyu.api.modules.common.service.NotifyDetailService; import com.imyeyu.api.modules.common.service.NotifyService; import com.imyeyu.api.modules.common.service.SmsService; +import com.imyeyu.api.modules.common.vo.NotifyManagementItem; import com.imyeyu.api.modules.user.entity.User; import com.imyeyu.api.modules.user.service.UserLoginService; import com.imyeyu.api.modules.user.service.UserService; @@ -70,25 +71,31 @@ public class NotifyController { @RequiredToken @RequestMapping("/detail") public Notify detail(@RequestParam String id) { - Notify notify = service.get(id); - { - List detailList = detailService.listByNotifyId(id); - Set userIdSet = detailList.stream() - .filter(item -> item.getMsgType() == NotifyDetail.MsgType.INTERNAL) - .flatMap(item -> Stream.of(item.getSendFrom(), item.getSendTo())) - .collect(Collectors.toSet()); - Map userMap = userService.mapByIdList(userIdSet); - for (NotifyDetail detail : detailList) { - if (TimiJava.isNotEmpty(detail.getSendFrom())) { - detail.setFromUser(userMap.get(detail.getSendFrom())); - } - if (TimiJava.isNotEmpty(detail.getSendTo())) { - detail.setToUser(userMap.get(detail.getSendTo())); - } - } - notify.setDetailList(detailList); - } - return notify; + return fillDetailList(service.get(id)); + } + + /// 查询管理端通知列表 + /// + /// @param page 分页参数 + /// @return 管理端通知列表 + @JsonView(ResponseView.Admin.class) + @RequireCorePermission(CorePermissionCode.NOTIFY_READ) + @RequiredToken + @PostMapping("/management/list") + public PageResult managementList(@RequestBody(required = false) Page page) { + return service.pageManagement(page, userLoginService.getRequireLoginUserId()); + } + + /// 查询管理端通知详情及收件人 + /// + /// @param id 通知 ID + /// @return 通知详情及收件人 + @JsonView(ResponseView.Admin.class) + @RequireCorePermission(CorePermissionCode.NOTIFY_READ) + @RequiredToken + @PostMapping("/management/detail") + public Notify managementDetail(@RequestParam String id) { + return fillDetailList(service.getManagement(id, userLoginService.getRequireLoginUserId())); } /// 删除通知及其通知详情 @@ -111,6 +118,26 @@ public class NotifyController { service.cancel(id); } + /// 删除管理端通知及其通知详情 + /// + /// @param id 通知 ID + @RequireCorePermission(CorePermissionCode.NOTIFY_DELETE) + @RequiredToken + @PostMapping("/management/delete") + public void managementDelete(@RequestParam String id) { + service.deleteManagement(id, userLoginService.getRequireLoginUserId()); + } + + /// 取消管理端尚未成功发送的通知 + /// + /// @param id 通知 ID + @RequireCorePermission(CorePermissionCode.NOTIFY_CANCEL) + @RequiredToken + @PostMapping("/management/cancel") + public void managementCancel(@RequestParam String id) { + service.cancelManagement(id, userLoginService.getRequireLoginUserId()); + } + @AOPLog @CaptchaValid @RequestRateLimit(value = 1, inSeconds = 59) @@ -186,4 +213,30 @@ public class NotifyController { public void markAllSiteRead() { detailService.markAllSiteRead(userLoginService.getRequireLoginUserId()); } + + /// 回填通知详情中的用户信息 + /// + /// @param notify 通知 + /// @return 已回填用户信息的通知 + private Notify fillDetailList(Notify notify) { + if (notify == null) { + return null; + } + List detailList = detailService.listByNotifyId(notify.getId()); + Set userIdSet = detailList.stream() + .filter(item -> item.getMsgType() == NotifyDetail.MsgType.INTERNAL) + .flatMap(item -> Stream.of(item.getSendFrom(), item.getSendTo())) + .collect(Collectors.toSet()); + Map userMap = userService.mapByIdList(userIdSet); + for (NotifyDetail detail : detailList) { + if (TimiJava.isNotEmpty(detail.getSendFrom())) { + detail.setFromUser(userMap.get(detail.getSendFrom())); + } + if (TimiJava.isNotEmpty(detail.getSendTo())) { + detail.setToUser(userMap.get(detail.getSendTo())); + } + } + notify.setDetailList(detailList); + return notify; + } } diff --git a/src/main/java/com/imyeyu/api/modules/common/mapper/NotifyDetailMapper.java b/src/main/java/com/imyeyu/api/modules/common/mapper/NotifyDetailMapper.java index d17daf5..c7d4103 100644 --- a/src/main/java/com/imyeyu/api/modules/common/mapper/NotifyDetailMapper.java +++ b/src/main/java/com/imyeyu/api/modules/common/mapper/NotifyDetailMapper.java @@ -17,34 +17,34 @@ import java.util.List; public interface NotifyDetailMapper extends BaseMapper { /** 查询用户的站内通知 */ - @Select("SELECT * FROM `notify_detail` WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} " + NOT_DELETE + " ORDER BY `created_at` DESC LIMIT #{offset}, #{limit}") + @Select("SELECT * FROM `notify_detail` WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `send_at` < " + UNIX_TIME + NOT_DELETE + " ORDER BY `created_at` DESC LIMIT #{offset}, #{limit}") List selectSiteByUserId(@Param("userId") String userId, @Param("offset") long offset, @Param("limit") long limit); /** 查询用户的未读站内通知 */ - @Select("SELECT * FROM `notify_detail` WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `read_at` IS NULL " + NOT_DELETE + " ORDER BY `created_at` DESC LIMIT #{offset}, #{limit}") + @Select("SELECT * FROM `notify_detail` WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `send_at` < " + UNIX_TIME + " AND `read_at` IS NULL " + NOT_DELETE + " ORDER BY `created_at` DESC LIMIT #{offset}, #{limit}") List selectUnreadSiteByUserId(@Param("userId") String userId, @Param("offset") long offset, @Param("limit") long limit); /** 统计用户的站内通知数量 */ - @Select("SELECT COUNT(*) FROM `notify_detail` WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} " + NOT_DELETE) + @Select("SELECT COUNT(*) FROM `notify_detail` WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `send_at` < " + UNIX_TIME + NOT_DELETE) long countSiteByUserId(@Param("userId") String userId); /** 统计用户的未读站内通知数量 */ - @Select("SELECT COUNT(*) FROM `notify_detail` WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `read_at` IS NULL " + NOT_DELETE) + @Select("SELECT COUNT(*) FROM `notify_detail` WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `send_at` < " + UNIX_TIME + " AND `read_at` IS NULL " + NOT_DELETE) long countUnreadSiteByUserId(@Param("userId") String userId); /** 查询用户拥有的站内通知 */ - @Select("SELECT * FROM `notify_detail` WHERE `id` = #{detailId} AND `msg_type` = 'INTERNAL' AND `send_to` = #{userId} " + NOT_DELETE + " LIMIT 1") + @Select("SELECT * FROM `notify_detail` WHERE `id` = #{detailId} AND `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `send_at` < " + UNIX_TIME + NOT_DELETE + " LIMIT 1") NotifyDetail selectSiteByIdAndUserId(@Param("detailId") String detailId, @Param("userId") String userId); /** 删除用户的站内通知 */ - @Update("UPDATE `notify_detail` SET `deleted_at` = " + UNIX_TIME + ", `updated_at` = " + UNIX_TIME + " WHERE `id` = #{detailId} AND `msg_type` = 'INTERNAL' AND `send_to` = #{userId} " + NOT_DELETE) + @Update("UPDATE `notify_detail` SET `deleted_at` = " + UNIX_TIME + ", `updated_at` = " + UNIX_TIME + " WHERE `id` = #{detailId} AND `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `send_at` < " + UNIX_TIME + NOT_DELETE) int deleteSiteByIdAndUserId(@Param("detailId") String detailId, @Param("userId") String userId); /** 标记站内通知已读 */ - @Update("UPDATE `notify_detail` SET `read_at` = #{readAt}, `updated_at` = " + UNIX_TIME + " WHERE `id` = #{detailId} AND `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `read_at` IS NULL " + NOT_DELETE) + @Update("UPDATE `notify_detail` SET `read_at` = #{readAt}, `updated_at` = " + UNIX_TIME + " WHERE `id` = #{detailId} AND `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `send_at` < " + UNIX_TIME + " AND `read_at` IS NULL " + NOT_DELETE) int markSiteRead(@Param("detailId") String detailId, @Param("userId") String userId, @Param("readAt") long readAt); /** 标记用户全部站内通知已读 */ - @Update("UPDATE `notify_detail` SET `read_at` = #{readAt}, `updated_at` = " + UNIX_TIME + " WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `read_at` IS NULL " + NOT_DELETE) + @Update("UPDATE `notify_detail` SET `read_at` = #{readAt}, `updated_at` = " + UNIX_TIME + " WHERE `msg_type` = 'INTERNAL' AND `send_to` = #{userId} AND `send_at` < " + UNIX_TIME + " AND `read_at` IS NULL " + NOT_DELETE) int markAllSiteRead(@Param("userId") String userId, @Param("readAt") long readAt); } diff --git a/src/main/java/com/imyeyu/api/modules/common/mapper/NotifyMapper.java b/src/main/java/com/imyeyu/api/modules/common/mapper/NotifyMapper.java index 6126211..10ff654 100644 --- a/src/main/java/com/imyeyu/api/modules/common/mapper/NotifyMapper.java +++ b/src/main/java/com/imyeyu/api/modules/common/mapper/NotifyMapper.java @@ -1,8 +1,12 @@ package com.imyeyu.api.modules.common.mapper; import com.imyeyu.api.modules.common.entity.Notify; +import com.imyeyu.api.modules.common.vo.NotifyManagementItem; +import org.apache.ibatis.annotations.Param; import com.imyeyu.spring.mapper.BaseMapper; +import java.util.List; + /** * 通知 Mapper * @@ -10,4 +14,25 @@ import com.imyeyu.spring.mapper.BaseMapper; * @since 2026-05-13 14:46 */ public interface NotifyMapper extends BaseMapper { + + /// 分页查询管理端通知 + /// + /// @param userId 管理员用户 ID + /// @param offset 分页偏移量 + /// @param limit 分页大小 + /// @return 通知列表 + List selectManagementPage(@Param("userId") String userId, @Param("offset") long offset, @Param("limit") long limit); + + /// 统计管理端通知数量 + /// + /// @param userId 管理员用户 ID + /// @return 通知数量 + long countManagement(@Param("userId") String userId); + + /// 查询管理员可管理的通知 + /// + /// @param notifyId 通知 ID + /// @param userId 管理员用户 ID + /// @return 通知 + Notify selectManagement(@Param("notifyId") String notifyId, @Param("userId") String userId); } diff --git a/src/main/java/com/imyeyu/api/modules/common/service/NotifyService.java b/src/main/java/com/imyeyu/api/modules/common/service/NotifyService.java index 5f4da6a..4b41082 100644 --- a/src/main/java/com/imyeyu/api/modules/common/service/NotifyService.java +++ b/src/main/java/com/imyeyu/api/modules/common/service/NotifyService.java @@ -1,6 +1,9 @@ package com.imyeyu.api.modules.common.service; import com.imyeyu.api.modules.common.entity.Notify; +import com.imyeyu.api.modules.common.vo.NotifyManagementItem; +import com.imyeyu.spring.bean.Page; +import com.imyeyu.spring.bean.PageResult; import com.imyeyu.spring.service.BaseService; /** @@ -11,6 +14,32 @@ import com.imyeyu.spring.service.BaseService; */ public interface NotifyService extends BaseService { + /// 分页查询当前用户创建的通知 + /// + /// @param page 分页参数 + /// @param userId 用户 ID + /// @return 管理端通知列表 + PageResult pageManagement(Page page, String userId); + + /// 查询当前用户可管理的通知 + /// + /// @param notifyId 通知 ID + /// @param userId 用户 ID + /// @return 通知 + Notify getManagement(String notifyId, String userId); + + /// 删除当前用户创建的通知 + /// + /// @param notifyId 通知 ID + /// @param userId 用户 ID + void deleteManagement(String notifyId, String userId); + + /// 取消当前用户创建的通知 + /// + /// @param notifyId 通知 ID + /// @param userId 用户 ID + void cancelManagement(String notifyId, String userId); + /// 取消通知中尚未成功发送的通知详情 /// /// @param notifyId 通知 ID diff --git a/src/main/java/com/imyeyu/api/modules/common/service/implement/NotifyDetailServiceImplement.java b/src/main/java/com/imyeyu/api/modules/common/service/implement/NotifyDetailServiceImplement.java index c3dc2ee..8fc55c9 100644 --- a/src/main/java/com/imyeyu/api/modules/common/service/implement/NotifyDetailServiceImplement.java +++ b/src/main/java/com/imyeyu/api/modules/common/service/implement/NotifyDetailServiceImplement.java @@ -64,9 +64,10 @@ public class NotifyDetailServiceImplement extends AbstractEntityService pageManagement(Page page, String userId) { + TimiException.required(userId, "未找到用户 ID"); + Page validPage = TimiJava.defaultIfNull(page, new Page<>()); + PageResult result = new PageResult<>(); + result.setTotal(mapper.countManagement(userId)); + result.setList(mapper.selectManagementPage(userId, validPage.getOffset(), validPage.getLimit())); + return result; + } + + /// 查询当前用户可管理的通知 + /// + /// @param notifyId 通知 ID + /// @param userId 用户 ID + /// @return 通知 + @Override + public Notify getManagement(String notifyId, String userId) { + TimiException.required(notifyId, "未找到通知 ID"); + TimiException.required(userId, "未找到用户 ID"); + Notify notify = mapper.selectManagement(notifyId, userId); + TimiException.required(notify, "未找到可管理的通知"); + return notify; + } + + /// 删除当前用户创建的通知 + /// + /// @param notifyId 通知 ID + /// @param userId 用户 ID + @Override + public void deleteManagement(String notifyId, String userId) { + getManagement(notifyId, userId); + delete(notifyId); + } + + /// 取消当前用户创建的通知 + /// + /// @param notifyId 通知 ID + /// @param userId 用户 ID + @Override + public void cancelManagement(String notifyId, String userId) { + getManagement(notifyId, userId); + cancel(notifyId); + } + /// 删除通知并级联软删除通知详情 /// /// @param notifyId 通知 ID diff --git a/src/main/java/com/imyeyu/api/modules/common/vo/NotifyManagementItem.java b/src/main/java/com/imyeyu/api/modules/common/vo/NotifyManagementItem.java new file mode 100644 index 0000000..6bebf4a --- /dev/null +++ b/src/main/java/com/imyeyu/api/modules/common/vo/NotifyManagementItem.java @@ -0,0 +1,57 @@ +package com.imyeyu.api.modules.common.vo; + +import com.imyeyu.api.modules.common.entity.NotifyDetail; +import lombok.Data; + +/// 管理端通知列表项 +/// +/// @author 夜雨 +/// @since 2026-08-25 +@Data +public class NotifyManagementItem { + + /// 通知 ID + private String id; + + /// 创建者用户 ID + private String createdBy; + + /// 创建时间 + private Long createdAt; + + /// 更新时间 + private Long updatedAt; + + /// 通知标题 + private String subject; + + /// 通知内容 + private String content; + + /// 内容类型 + private NotifyDetail.ContentType contentType; + + /// 发送时间 + private Long sendAt; + + /// 接收用户数量 + private Long recipientCount; + + /// 已读用户数量 + private Long readCount; + + /// 等待发送数量 + private Long waitingCount; + + /// 已发送数量 + private Long remindedCount; + + /// 超时数量 + private Long timeoutCount; + + /// 已取消数量 + private Long cancelCount; + + /// 失败数量 + private Long failCount; +} diff --git a/src/main/java/com/imyeyu/api/modules/gao/controller/GaoNotifyController.java b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoNotifyController.java new file mode 100644 index 0000000..cf1ccae --- /dev/null +++ b/src/main/java/com/imyeyu/api/modules/gao/controller/GaoNotifyController.java @@ -0,0 +1,140 @@ +package com.imyeyu.api.modules.gao.controller; + +import com.fasterxml.jackson.annotation.JsonView; +import com.imyeyu.api.annotation.RequireCorePermission; +import com.imyeyu.api.bean.CorePermissionCode; +import com.imyeyu.api.bean.PermissionMatchMode; +import com.imyeyu.api.modules.common.entity.Notify; +import com.imyeyu.api.modules.common.entity.NotifyDetail; +import com.imyeyu.api.modules.common.service.NotifyService; +import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission; +import com.imyeyu.api.modules.gao.bean.GaoPermissionCode; +import com.imyeyu.api.modules.gao.entity.GaoUser; +import com.imyeyu.api.modules.gao.service.GaoStoreScopeService; +import com.imyeyu.api.modules.gao.service.GaoUserService; +import com.imyeyu.api.modules.user.entity.User; +import com.imyeyu.api.modules.user.service.UserService; +import com.imyeyu.java.TimiJava; +import com.imyeyu.java.bean.timi.TimiException; +import com.imyeyu.spring.annotation.RequestRateLimit; +import com.imyeyu.spring.annotation.RequiredToken; +import com.imyeyu.spring.bean.Page; +import com.imyeyu.spring.bean.PageResult; +import com.imyeyu.spring.util.ResponseView; +import com.imyeyu.utils.Time; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/// GAO 通知接口 +/// +/// 这里的通知接收用户必须属于当前操作人的 GAO 用户范围,不能直接复用通用通知创建接口。 +/// +/// @author Codex +/// @since 2026-08-25 +@RestController +@RequiredArgsConstructor +@RequestMapping("/gao/notify") +public class GaoNotifyController { + + private final GaoUserService gaoUserService; + private final GaoStoreScopeService storeScopeService; + private final NotifyService notifyService; + private final UserService userService; + + /// 查询可作为通知接收人的 GAO 用户 + /// + /// 门店管理范围可以查询全部门店或指定门店,店长只能查询当前门店。 + /// + /// @param page 分页参数 + /// @return 可发送用户分页结果 + @JsonView(ResponseView.Public.class) + @RequiredToken + @RequestRateLimit + @RequireCorePermission(CorePermissionCode.NOTIFY_CREATE) + @RequireGaoPermission(value = {GaoPermissionCode.USER_READ, GaoPermissionCode.STORE_READ}, mode = PermissionMatchMode.ANY) + @PostMapping("/recipient/list") + public PageResult recipientList(@RequestBody Page page) { + TimiException.required(page, "未找到分页参数"); + GaoUser example = TimiJava.defaultIfNull(page.getEqualsExample(), new GaoUser()); + example.setEnabled(true); + if (storeScopeService.hasGlobalScope()) { + if (TimiJava.isNotEmpty(example.getStoreId())) { + storeScopeService.checkStoreId(example.getStoreId()); + } + } else { + example.setStoreId(storeScopeService.resolveStoreId(example.getStoreId())); + } + page.setEqualsExample(example); + + PageResult result = gaoUserService.page(page); + fillUser(result.getList()); + return result; + } + + /// 创建 GAO 站内通知 + /// + /// 只允许发送站内通知,并逐个校验接收用户是否属于当前操作人的门店范围。 + /// + /// @param notify 通知及通知详情 + /// @return 创建后的通知 + @RequiredToken + @RequestRateLimit + @RequireCorePermission(CorePermissionCode.NOTIFY_CREATE) + @RequireGaoPermission(value = {GaoPermissionCode.USER_READ, GaoPermissionCode.STORE_READ}, mode = PermissionMatchMode.ANY) + @PostMapping("/create") + public Notify create(@RequestBody Notify notify) { + checkRecipientBoundary(notify); + notifyService.create(notify); + return notify; + } + + /// 校验通知接收用户边界 + /// + /// @param notify 通知 + private void checkRecipientBoundary(Notify notify) { + TimiException.required(notify, "未找到通知"); + List detailList = notify.getDetailList(); + TimiException.required(detailList, "未找到通知详情列表"); + TimiException.requiredTrue(!detailList.isEmpty(), "通知详情列表不能为空"); + + Set recipientIdSet = detailList.stream().map(detail -> { + TimiException.required(detail, "未找到通知详情"); + TimiException.requiredTrue(detail.getMsgType() == NotifyDetail.MsgType.INTERNAL, "GAO 通知仅支持站内通知"); + TimiException.required(detail.getSendTo(), "未找到通知接收用户 ID"); + if (detail.getSendAt() != null) { + TimiException.requiredTrue(Time.now() < detail.getSendAt(), "定时发送时间必须晚于当前时间"); + } + return detail.getSendTo(); + }).collect(Collectors.toSet()); + TimiException.requiredTrue(recipientIdSet.size() == detailList.size(), "通知接收用户不能重复"); + + Map gaoUserMap = gaoUserService.mapByUserIdList(recipientIdSet); + TimiException.requiredTrue(gaoUserMap.size() == recipientIdSet.size(), "包含无效的通知接收用户"); + for (GaoUser gaoUser : gaoUserMap.values()) { + TimiException.requiredTrue(Boolean.TRUE.equals(gaoUser.getEnabled()), "通知接收用户已停用"); + storeScopeService.checkStoreId(gaoUser.getStoreId()); + } + } + + /// 回填 GAO 用户的核心用户资料 + /// + /// @param gaoUserList GAO 用户列表 + private void fillUser(List gaoUserList) { + if (TimiJava.isEmpty(gaoUserList)) { + return; + } + List userIdList = gaoUserList.stream().map(GaoUser::getUserId).toList(); + Map userMap = userService.mapByIdList(userIdList); + for (GaoUser gaoUser : gaoUserList) { + gaoUser.setUser(userMap.get(gaoUser.getUserId())); + } + } +} diff --git a/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoUserMapper.java b/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoUserMapper.java index dc94f6e..21e4662 100644 --- a/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoUserMapper.java +++ b/src/main/java/com/imyeyu/api/modules/gao/mapper/GaoUserMapper.java @@ -3,10 +3,15 @@ package com.imyeyu.api.modules.gao.mapper; import com.imyeyu.api.modules.gao.entity.GaoUser; import com.imyeyu.spring.mapper.BaseMapper; +import java.util.Collection; +import java.util.List; + /// /// GAO 用户 Mapper /// /// @author Codex /// @since 2026-07-30 public interface GaoUserMapper extends BaseMapper { + + List selectByUserIdList(Collection userIdList); } diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/GaoUserService.java b/src/main/java/com/imyeyu/api/modules/gao/service/GaoUserService.java index 61a7da2..327c004 100644 --- a/src/main/java/com/imyeyu/api/modules/gao/service/GaoUserService.java +++ b/src/main/java/com/imyeyu/api/modules/gao/service/GaoUserService.java @@ -3,6 +3,9 @@ package com.imyeyu.api.modules.gao.service; import com.imyeyu.api.modules.gao.entity.GaoUser; import com.imyeyu.spring.service.BaseService; +import java.util.Collection; +import java.util.Map; + /// /// GAO 用户服务 /// @@ -19,4 +22,10 @@ public interface GaoUserService extends BaseService { /// /// @param gaoUser GAO 用户,必须包含 ID 和目标门店 ID void transferStore(GaoUser gaoUser); + + /// 根据核心用户 ID 映射 GAO 用户 + /// + /// @param userIdList 核心用户 ID 列表 + /// @return GAO 用户映射 + Map mapByUserIdList(Collection userIdList); } diff --git a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoUserServiceImplement.java b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoUserServiceImplement.java index 6ce98b7..4affc95 100644 --- a/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoUserServiceImplement.java +++ b/src/main/java/com/imyeyu/api/modules/gao/service/implement/GaoUserServiceImplement.java @@ -19,6 +19,11 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Collection; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + /// /// GAO 用户服务实现 /// @@ -160,4 +165,13 @@ public class GaoUserServiceImplement extends AbstractEntityService mapByUserIdList(Collection userIdList) { + if (TimiJava.isEmpty(userIdList)) { + return Map.of(); + } + return mapper.selectByUserIdList(userIdList).stream() + .collect(Collectors.toMap(GaoUser::getUserId, Function.identity())); + } } diff --git a/src/main/resources/db/migration/timiserver/V43__add_notify_management_indexes.sql b/src/main/resources/db/migration/timiserver/V43__add_notify_management_indexes.sql new file mode 100644 index 0000000..4c922e0 --- /dev/null +++ b/src/main/resources/db/migration/timiserver/V43__add_notify_management_indexes.sql @@ -0,0 +1,6 @@ +ALTER TABLE `notify` + ADD INDEX `idx_created_by_created`(`created_by` ASC, `created_at` DESC) USING BTREE; + +ALTER TABLE `notify_detail` + ADD INDEX `idx_notify_send_from_deleted`(`notify_id` ASC, `send_from` ASC, `deleted_at` ASC) USING BTREE, + ADD INDEX `idx_internal_user_send_at`(`msg_type` ASC, `send_to` ASC, `send_at` ASC, `deleted_at` ASC) USING BTREE; diff --git a/src/main/resources/mapper/timi-server/common/NotifyMapper.xml b/src/main/resources/mapper/timi-server/common/NotifyMapper.xml new file mode 100644 index 0000000..0e518c9 --- /dev/null +++ b/src/main/resources/mapper/timi-server/common/NotifyMapper.xml @@ -0,0 +1,82 @@ + + + + + + + + + diff --git a/src/main/resources/mapper/timi-server/gao/GaoUserMapper.xml b/src/main/resources/mapper/timi-server/gao/GaoUserMapper.xml new file mode 100644 index 0000000..8d24732 --- /dev/null +++ b/src/main/resources/mapper/timi-server/gao/GaoUserMapper.xml @@ -0,0 +1,15 @@ + + + + +