|
@@ -0,0 +1,88 @@
|
|
|
|
|
+package com.etotem.cfc.task;
|
|
|
|
|
+
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.etotem.cfc.entity.PearlInteractionReminder;
|
|
|
|
|
+import com.etotem.cfc.entity.ResourceItem;
|
|
|
|
|
+import com.etotem.cfc.enums.ConnectionType;
|
|
|
|
|
+import com.etotem.cfc.mapper.PearlInteractionReminderMapper;
|
|
|
|
|
+import com.etotem.cfc.mapper.ResourceItemMapper;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
|
+
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
|
+import java.time.Instant;
|
|
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
|
|
+import java.util.Date;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@Component
|
|
|
|
|
+public class PearlReminderScheduledTask {
|
|
|
|
|
+
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private ResourceItemMapper resourceItemMapper;
|
|
|
|
|
+
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private PearlInteractionReminderMapper reminderMapper;
|
|
|
|
|
+
|
|
|
|
|
+ /** 每日 08:00 生成珍珠图互动提醒 */
|
|
|
|
|
+ @Scheduled(cron = "0 0 8 * * ?")
|
|
|
|
|
+ public void generateReminders() {
|
|
|
|
|
+ log.info("===== PearlReminderScheduledTask 开始执行 =====");
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 遍历所有带 connection_type 的资源
|
|
|
|
|
+ List<ResourceItem> items = resourceItemMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<ResourceItem>()
|
|
|
|
|
+ .isNotNull(ResourceItem::getConnectionType)
|
|
|
|
|
+ .ne(ResourceItem::getConnectionType, "")
|
|
|
|
|
+ );
|
|
|
|
|
+ int created = 0;
|
|
|
|
|
+ for (ResourceItem item : items) {
|
|
|
|
|
+ if (!ConnectionType.isValid(item.getConnectionType())) continue;
|
|
|
|
|
+ ConnectionType ct = null;
|
|
|
|
|
+ for (ConnectionType t : ConnectionType.values()) {
|
|
|
|
|
+ if (t.name().equals(item.getConnectionType())) { ct = t; break; }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (ct == null) continue;
|
|
|
|
|
+
|
|
|
|
|
+ int intervalDays = ct.getSuggestIntervalMonth() * 30;
|
|
|
|
|
+ long daysSinceLast;
|
|
|
|
|
+ if (item.getLastInteractionAt() == null) {
|
|
|
|
|
+ // 从未互动:按创建时间起算
|
|
|
|
|
+ Date base = item.getCreatedAt() != null ? item.getCreatedAt() : new Date();
|
|
|
|
|
+ daysSinceLast = ChronoUnit.DAYS.between(base.toInstant(), Instant.now());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ daysSinceLast = ChronoUnit.DAYS.between(item.getLastInteractionAt().toInstant(), Instant.now());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (daysSinceLast < intervalDays) continue; // 未到期
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否已有 PENDING 提醒
|
|
|
|
|
+ Long pendingCount = reminderMapper.selectCount(
|
|
|
|
|
+ new LambdaQueryWrapper<PearlInteractionReminder>()
|
|
|
|
|
+ .eq(PearlInteractionReminder::getUserId, item.getUserId())
|
|
|
|
|
+ .eq(PearlInteractionReminder::getResourceItemId, item.getId())
|
|
|
|
|
+ .eq(PearlInteractionReminder::getStatus, "PENDING")
|
|
|
|
|
+ );
|
|
|
|
|
+ if (pendingCount != null && pendingCount > 0) continue;
|
|
|
|
|
+
|
|
|
|
|
+ PearlInteractionReminder r = new PearlInteractionReminder();
|
|
|
|
|
+ r.setUserId(item.getUserId());
|
|
|
|
|
+ r.setResourceItemId(item.getId());
|
|
|
|
|
+ r.setConnectionType(item.getConnectionType());
|
|
|
|
|
+ r.setSuggestIntervalMonth(ct.getSuggestIntervalMonth());
|
|
|
|
|
+ r.setLastInteractionAt(item.getLastInteractionAt());
|
|
|
|
|
+ r.setDaysSinceLast((int) Math.max(0, daysSinceLast));
|
|
|
|
|
+ r.setStatus("PENDING");
|
|
|
|
|
+ r.setCreatedAt(new Date());
|
|
|
|
|
+ r.setUpdatedAt(new Date());
|
|
|
|
|
+ reminderMapper.insert(r);
|
|
|
|
|
+ created++;
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("珍珠图提醒生成完成,新增 {} 条", created);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("珍珠图提醒生成失败", e);
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("===== PearlReminderScheduledTask 执行完成 =====");
|
|
|
|
|
+ }
|
|
|
|
|
+}
|