|
|
@@ -32,6 +32,15 @@ public class TaskReminderScheduledTask {
|
|
|
private static final String TYPE = "task_reminder";
|
|
|
private static final String REF_TYPE = "task";
|
|
|
|
|
|
+ /**
|
|
|
+ * 逾期宽限天数:只提醒"今日到期 + 近 N 天逾期"的任务。
|
|
|
+ * 不加下限时,生产库有 2026-08-18 的历史积压与报告叙述类任务会被一次性批量误发。
|
|
|
+ */
|
|
|
+ private static final int OVERDUE_GRACE_DAYS = 3;
|
|
|
+
|
|
|
+ /** 单次调度最多发送条数,避免选数异常时形成短信轰炸 */
|
|
|
+ private static final int MAX_SEND_PER_RUN = 50;
|
|
|
+
|
|
|
@Resource
|
|
|
private TaskMapper taskMapper;
|
|
|
|
|
|
@@ -63,11 +72,18 @@ public class TaskReminderScheduledTask {
|
|
|
Date dayEnd = endCal.getTime();
|
|
|
|
|
|
// 今日到期 + 已逾期,均为 pending(未打卡/未审核通过)
|
|
|
+ // 提醒下限 = 今日0点 - 宽限天数,剔除早已废弃的历史积压
|
|
|
+ Calendar floorCal = Calendar.getInstance();
|
|
|
+ floorCal.setTime(dayStart);
|
|
|
+ floorCal.add(Calendar.DAY_OF_MONTH, -OVERDUE_GRACE_DAYS);
|
|
|
+ Date remindFloor = floorCal.getTime();
|
|
|
+
|
|
|
List<Task> tasks = taskMapper.selectList(new LambdaQueryWrapper<Task>()
|
|
|
.in(Task::getStatus, "pending", "pending_review")
|
|
|
.isNotNull(Task::getDeadline)
|
|
|
.isNotNull(Task::getFamilyId)
|
|
|
- .le(Task::getDeadline, dayEnd)
|
|
|
+ .ge(Task::getDeadline, remindFloor)
|
|
|
+ .lt(Task::getDeadline, dayEnd)
|
|
|
.orderByAsc(Task::getDeadline));
|
|
|
if (tasks == null || tasks.isEmpty()) {
|
|
|
log.info("任务提醒:今日无待打卡任务");
|
|
|
@@ -76,6 +92,10 @@ public class TaskReminderScheduledTask {
|
|
|
|
|
|
int sent = 0;
|
|
|
for (Task task : tasks) {
|
|
|
+ if (sent >= MAX_SEND_PER_RUN) {
|
|
|
+ log.warn("任务提醒达到单次上限{}条,本轮剩余{}条顺延下次", MAX_SEND_PER_RUN, tasks.size() - sent);
|
|
|
+ break;
|
|
|
+ }
|
|
|
try {
|
|
|
Long userId = resolveReceiver(task);
|
|
|
if (userId == null) continue;
|