From a8156976beb6e438eaf6f75683d74b4b57266ed1 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Tue, 20 Jan 2026 18:35:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(puzzle):=20=E6=B7=BB=E5=8A=A0=E5=85=8D?= =?UTF-8?q?=E8=B4=B9=E6=8B=BC=E5=9B=BE=E9=80=9A=E7=9F=A5=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在MemberPuzzleMapper中新增listFreeUnpurchased方法用于查询指定时间范围内生成且未购买的免费拼图记录 - 新增FreePuzzleNotificationTask定时任务类,每天晚7点执行免费拼图通知 - 添加SQL映射配置实现免费拼图记录的查询逻辑 - 实现微信订阅通知触发机制,向符合条件的用户发送免费拼图领取通知 - 集成景区信息查询和会员信息获取功能用于通知内容构造 --- .../puzzle/mapper/MemberPuzzleMapper.java | 5 ++ .../task/FreePuzzleNotificationTask.java | 87 +++++++++++++++++++ .../resources/mapper/MemberPuzzleMapper.xml | 9 ++ 3 files changed, 101 insertions(+) create mode 100644 src/main/java/com/ycwl/basic/task/FreePuzzleNotificationTask.java diff --git a/src/main/java/com/ycwl/basic/puzzle/mapper/MemberPuzzleMapper.java b/src/main/java/com/ycwl/basic/puzzle/mapper/MemberPuzzleMapper.java index b5322cb2..57a30458 100644 --- a/src/main/java/com/ycwl/basic/puzzle/mapper/MemberPuzzleMapper.java +++ b/src/main/java/com/ycwl/basic/puzzle/mapper/MemberPuzzleMapper.java @@ -46,4 +46,9 @@ public interface MemberPuzzleMapper { * 根据人脸ID和记录ID查询 */ MemberPuzzleEntity getByFaceAndRecord(@Param("faceId") Long faceId, @Param("recordId") Long recordId); + + /** + * 查询指定时间范围内生成且未购买的免费拼图记录 + */ + List listFreeUnpurchased(@Param("startTime") java.util.Date startTime, @Param("endTime") java.util.Date endTime); } diff --git a/src/main/java/com/ycwl/basic/task/FreePuzzleNotificationTask.java b/src/main/java/com/ycwl/basic/task/FreePuzzleNotificationTask.java new file mode 100644 index 00000000..8ceaf752 --- /dev/null +++ b/src/main/java/com/ycwl/basic/task/FreePuzzleNotificationTask.java @@ -0,0 +1,87 @@ +package com.ycwl.basic.task; + +import cn.hutool.core.date.DateUtil; +import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; +import com.ycwl.basic.mapper.MemberMapper; +import com.ycwl.basic.model.pc.member.resp.MemberRespVO; +import com.ycwl.basic.model.pc.notify.req.WechatSubscribeNotifyTriggerRequest; +import com.ycwl.basic.puzzle.mapper.MemberPuzzleMapper; +import com.ycwl.basic.repository.ScenicRepository; +import com.ycwl.basic.service.notify.WechatSubscribeNotifyTriggerService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.HashMap; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 免费拼图通知任务 + */ +@Component +@Slf4j +public class FreePuzzleNotificationTask { + + @Autowired + private MemberPuzzleMapper memberPuzzleMapper; + @Autowired + private MemberMapper memberMapper; + @Autowired + private ScenicRepository scenicRepository; + @Autowired + private WechatSubscribeNotifyTriggerService notifyTriggerService; + + /** + * 每天晚7点执行 + * 查找昨天生成的,未购买的且is_free字段等于1的member,触发“FREE_PUZZLE”通知 + */ + @Scheduled(cron = "0 0 19 * * ?") + public void sendFreePuzzleNotification() { + log.info("开始执行免费拼图通知任务"); + // 昨天开始时间 + Date startTime = DateUtil.beginOfDay(DateUtil.yesterday()); + // 昨天结束时间 + Date endTime = DateUtil.endOfDay(DateUtil.yesterday()); + + // 查询符合条件的记录 + var list = memberPuzzleMapper.listFreeUnpurchased(startTime, endTime); + log.info("查询到需发送免费拼图通知记录数: {}", list.size()); + + Set sentMemberIds = ConcurrentHashMap.newKeySet(); + + list.parallelStream().forEach(item -> { + if (!sentMemberIds.add(item.getMemberId())) { + return; + } + + try { + MemberRespVO member = memberMapper.getById(item.getMemberId()); + if (member == null || member.getOpenId() == null) { + return; + } + + // 构造参数 + HashMap variables = new HashMap<>(); + ScenicV2DTO scenic = scenicRepository.getScenicBasic(item.getScenicId()); + variables.put("activityName", "免费领取三拼图"); + variables.put("scenicName", scenic.getName()); + + WechatSubscribeNotifyTriggerRequest request = WechatSubscribeNotifyTriggerRequest.builder() + .scenicId(item.getScenicId()) + .memberId(item.getMemberId()) + .openId(member.getOpenId()) + .bizId(String.valueOf(item.getId())) + .variables(variables) + .build(); + + notifyTriggerService.trigger("FREE_PUZZLE", request); + } catch (Exception e) { + log.error("发送免费拼图通知失败: memberId={}", item.getMemberId(), e); + } + }); + log.info("免费拼图通知任务执行结束"); + } +} diff --git a/src/main/resources/mapper/MemberPuzzleMapper.xml b/src/main/resources/mapper/MemberPuzzleMapper.xml index b016ac57..0b526d9e 100644 --- a/src/main/resources/mapper/MemberPuzzleMapper.xml +++ b/src/main/resources/mapper/MemberPuzzleMapper.xml @@ -67,4 +67,13 @@ LIMIT 1 + +