package com.tcm.training.admin.system.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.tcm.training.admin.app.notice.service.AppSystemNoticeDispatchCommand; import com.tcm.training.admin.app.notice.service.AppSystemNoticeDispatchService; import com.tcm.training.admin.app.notice.service.AppSystemNoticeType; import com.tcm.training.admin.app.notice.entity.AppUserActivityNotice; import com.tcm.training.admin.app.notice.mapper.AppUserActivityNoticeMapper; import com.tcm.training.admin.member.entity.AppUser; import com.tcm.training.admin.member.mapper.UserMapper; import com.tcm.training.admin.system.event.ActivityNoticeCreatedEvent; import com.tcm.training.admin.system.entity.ActivityNotice; import com.tcm.training.admin.system.mapper.ActivityNoticeMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.event.TransactionalEventListener; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * 活动通知分发服务。 */ @Service public class ActivityNoticeDispatchService { private static final Logger log = LoggerFactory.getLogger(ActivityNoticeDispatchService.class); private static final int USER_STATUS_ENABLED = 1; private static final int USER_DELETED_NO = 0; private static final int RECORD_DELETED_NO = 0; private static final int RECORD_DELETED_YES = 1; private static final long PAGE_SIZE = 500L; private final UserMapper userMapper; private final AppUserActivityNoticeMapper appUserActivityNoticeMapper; private final ActivityNoticeMapper activityNoticeMapper; private final AppSystemNoticeDispatchService appSystemNoticeDispatchService; /** * 注入活动通知分发所需依赖。 */ public ActivityNoticeDispatchService(UserMapper userMapper, AppUserActivityNoticeMapper appUserActivityNoticeMapper, ActivityNoticeMapper activityNoticeMapper, AppSystemNoticeDispatchService appSystemNoticeDispatchService) { this.userMapper = userMapper; this.appUserActivityNoticeMapper = appUserActivityNoticeMapper; this.activityNoticeMapper = activityNoticeMapper; this.appSystemNoticeDispatchService = appSystemNoticeDispatchService; } /** * 在活动通知创建提交成功后异步为用户分发通知记录。 */ @Async("activityNoticeTaskExecutor") @TransactionalEventListener public void handleActivityNoticeCreated(ActivityNoticeCreatedEvent event) { if (event == null || event.getActivityNoticeId() == null) { return; } ActivityNotice activityNotice = activityNoticeMapper.selectOne(new LambdaQueryWrapper() .eq(ActivityNotice::getId, event.getActivityNoticeId()) .eq(ActivityNotice::getDeleted, RECORD_DELETED_NO) .last("limit 1")); if (activityNotice == null) { return; } long currentPage = 1L; while (true) { Page page = userMapper.selectPage( new Page(currentPage, PAGE_SIZE), new LambdaQueryWrapper() .eq(AppUser::getDeleted, USER_DELETED_NO) .eq(AppUser::getStatus, USER_STATUS_ENABLED) .orderByAsc(AppUser::getId) ); List users = page.getRecords(); if (users == null || users.isEmpty()) { break; } for (AppUser user : users) { distributeToUser(user, activityNotice); } if (page.getCurrent() >= page.getPages()) { break; } currentPage++; } } /** * 为单个 APP 用户分发活动通知,单用户失败不影响整批分发。 */ private void distributeToUser(AppUser user, ActivityNotice activityNotice) { if (user == null || user.getId() == null || activityNotice == null || activityNotice.getId() == null) { return; } try { boolean exists = appUserActivityNoticeMapper.selectCount(new LambdaQueryWrapper() .eq(AppUserActivityNotice::getAppUserId, user.getId()) .eq(AppUserActivityNotice::getActivityNoticeId, activityNotice.getId()) .eq(AppUserActivityNotice::getDeleted, RECORD_DELETED_NO)) > 0; if (!exists) { AppUserActivityNotice record = new AppUserActivityNotice(); record.setAppUserId(user.getId()); record.setActivityNoticeId(activityNotice.getId()); record.setDeleted(RECORD_DELETED_NO); appUserActivityNoticeMapper.insert(record); } // 活动通知发布后同时写入统一系统通知表,并按双开关规则尝试极光推送。 appSystemNoticeDispatchService.createAndPush(buildActivityNoticeCommand(user.getId(), activityNotice)); } catch (Exception ex) { log.error("activity notice distribute failed, activityNoticeId={}, appUserId={}", activityNotice.getId(), user.getId(), ex); } } /** * 构建活动通知统一发放命令。 */ private AppSystemNoticeDispatchCommand buildActivityNoticeCommand(Long appUserId, ActivityNotice activityNotice) { AppSystemNoticeDispatchCommand command = new AppSystemNoticeDispatchCommand(); command.setAppUserId(appUserId); command.setNoticeTypeCode(AppSystemNoticeType.ACTIVITY_NOTICE); command.setTitle(activityNotice.getTitle()); command.setContent(activityNotice.getTitle()); command.setReferenceType("ACTIVITY_NOTICE"); command.setReferenceId(activityNotice.getId()); command.setRequireUserSetting(Boolean.TRUE); Map payload = new LinkedHashMap(); payload.put("activityNoticeId", String.valueOf(activityNotice.getId())); payload.put("title", activityNotice.getTitle()); command.setPayload(payload); return command; } /** * 在后台删除活动通知时同步隐藏用户侧对应记录。 */ public void hideDistributedRecords(Long activityNoticeId) { if (activityNoticeId == null) { return; } appUserActivityNoticeMapper.update( null, new LambdaUpdateWrapper() .eq(AppUserActivityNotice::getActivityNoticeId, activityNoticeId) .eq(AppUserActivityNotice::getDeleted, RECORD_DELETED_NO) .set(AppUserActivityNotice::getDeleted, RECORD_DELETED_YES) ); } }