package com.designhub.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.designhub.entity.Task; import com.designhub.entity.TaskItem; import com.designhub.entity.TaskProgressUpdateLog; import com.designhub.entity.User; import com.designhub.mapper.TaskMapper; import com.designhub.mapper.TaskItemMapper; import com.designhub.mapper.TaskProgressUpdateLogMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.List; /** * 任务进度检查服务 * 每日17:30检查任务进度是否更新,并发送钉钉通知提醒设计师 */ @Service @RequiredArgsConstructor @Slf4j public class TaskProgressCheckService { private final TaskMapper taskMapper; private final TaskItemMapper taskItemMapper; private final TaskProgressUpdateLogMapper progressUpdateLogMapper; private final NotificationService notificationService; private final UserService userService; private final DingTalkService dingTalkService; /** * 每日17:30提醒设计师更新子任务进度 * cron: 秒 分 时 日 月 周 */ @Scheduled(cron = "0 30 17 * * ?") @Transactional public void remindDesignersToUpdateProgress() { log.info("=== 开始执行每日进度更新提醒任务(17:30) ==="); // 查询所有进行中的子任务 List inProgressItems = taskItemMapper.selectList( new LambdaQueryWrapper() .eq(TaskItem::getStatus, "in_progress") .isNotNull(TaskItem::getReceiverId) ); log.info("当前进行中的子任务数量: {}", inProgressItems.size()); int reminderSentCount = 0; for (TaskItem item : inProgressItems) { try { if (item.getReceiverId() == null) continue; // 获取主任务信息 Task mainTask = taskMapper.selectById(item.getTaskId()); if (mainTask == null) continue; // 获取设计师信息 User designer = userService.getUserById(item.getReceiverId()); if (designer == null) continue; String designerName = designer.getRealName() != null ? designer.getRealName() : designer.getUsername(); // 构建提醒消息内容 StringBuilder content = new StringBuilder(); content.append("### 进度更新提醒\n\n"); content.append("**设计师**:").append(designerName).append(" \n"); content.append("**任务名称**:").append(mainTask.getTitle()).append(" \n"); content.append("**子任务编号**:").append(item.getItemNo()).append(" \n"); content.append("**当前进度**:").append(item.getProgress() != null ? item.getProgress() : 0).append("% \n\n"); content.append("请及时更新您的任务进度,以便项目负责人了解任务进展情况。"); // 发送钉钉个人通知 notificationService.sendNotification( item.getReceiverId(), "请更新任务进度", content.toString(), "PROGRESS_REMINDER", "task_item", item.getId() ); reminderSentCount++; log.debug("已向设计师 {} 发送进度更新提醒,子任务: {}", designerName, item.getItemNo()); } catch (Exception e) { log.error("发送进度更新提醒失败: itemId={}, receiverId={}", item.getId(), item.getReceiverId(), e); } } log.info("=== 每日进度更新提醒完成 === 发送提醒数: {}", reminderSentCount); } /** * 每日18:00执行进度更新检查(记录未更新的任务) * cron: 秒 分 时 日 月 周 */ @Scheduled(cron = "0 0 18 * * ?") @Transactional public void checkDailyProgressUpdate() { log.info("=== 开始执行每日进度更新检查任务 ==="); LocalDate today = LocalDate.now(); LocalDateTime todayStart = LocalDateTime.of(today, LocalTime.MIN); LocalDateTime now = LocalDateTime.now(); // 查询所有进行中的任务 List inProgressTasks = taskMapper.selectList( new LambdaQueryWrapper() .eq(Task::getStatus, "in_progress") .isNotNull(Task::getReceiverId) ); log.info("当前进行中的任务数量: {}", inProgressTasks.size()); int notUpdatedCount = 0; int updatedCount = 0; int notificationSentCount = 0; for (Task task : inProgressTasks) { try { // 检查今天是否已经有记录 TaskProgressUpdateLog existingLog = progressUpdateLogMapper.selectOne( new LambdaQueryWrapper() .eq(TaskProgressUpdateLog::getTaskId, task.getId()) .eq(TaskProgressUpdateLog::getCheckDate, today) ); if (existingLog != null) { log.debug("任务 {} 今天已检查过,跳过", task.getTaskNo()); continue; } // 检查任务进度是否在今天更新过 boolean updatedToday = task.getUpdateTime() != null && task.getUpdateTime().isAfter(todayStart); // 创建检查记录 // 获取接单人姓名 String receiverName = null; if (task.getReceiverId() != null) { try { var receiver = userService.getUserById(task.getReceiverId()); if (receiver != null) { receiverName = receiver.getRealName() != null ? receiver.getRealName() : receiver.getUsername(); } } catch (Exception e) { log.warn("获取接单人姓名失败: receiverId={}", task.getReceiverId()); } } TaskProgressUpdateLog log = new TaskProgressUpdateLog(); log.setTaskId(task.getId()); log.setTaskNo(task.getTaskNo()); log.setTaskTitle(task.getTitle()); log.setReceiverId(task.getReceiverId()); log.setReceiverName(receiverName); log.setCheckDate(today); log.setIsUpdated(updatedToday ? 1 : 0); log.setLastUpdateTime(task.getUpdateTime()); log.setProgressBefore(task.getProgress()); log.setTaskStatus(task.getStatus()); log.setCreateTime(now); if (updatedToday) { updatedCount++; log.setProgressAfter(task.getProgress()); log.setRemark("今日已更新进度"); log.setNotificationSent(0); // 已更新,不需要发送通知 } else { notUpdatedCount++; log.setRemark("今日未更新进度,已发送提醒通知"); // 发送通知给接单人 if (task.getReceiverId() != null) { try { notificationService.sendTaskNotification( task.getReceiverId(), task.getId(), String.format("任务【%s】需要更新进度", task.getTitle()), String.format("您接收的任务【%s】(编号:%s)今天还未更新进度,请及时更新任务进展情况。", task.getTitle(), task.getTaskNo()) ); log.setNotificationSent(1); log.setNotificationTime(LocalDateTime.now()); notificationSentCount++; this.log.debug("已向用户 {} 发送进度更新提醒", task.getReceiverId()); } catch (Exception e) { this.log.error("发送进度更新通知失败: taskId={}, receiverId={}", task.getId(), task.getReceiverId(), e); log.setNotificationSent(0); log.setRemark("今日未更新进度,通知发送失败: " + e.getMessage()); } } } // 保存检查记录 progressUpdateLogMapper.insert(log); } catch (Exception e) { this.log.error("检查任务进度失败: taskId={}, taskNo={}", task.getId(), task.getTaskNo(), e); } } log.info("=== 每日进度更新检查完成 ==="); log.info("总任务数: {}, 已更新: {}, 未更新: {}, 通知已发送: {}", inProgressTasks.size(), updatedCount, notUpdatedCount, notificationSentCount); } /** * 手动触发进度检查(用于测试或管理员手动触发) */ public void manualCheckProgressUpdate() { log.info("手动触发进度更新检查"); checkDailyProgressUpdate(); } /** * 获取指定日期的进度更新记录 */ public List getProgressUpdateLogs(LocalDate date, Integer isUpdated) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(TaskProgressUpdateLog::getCheckDate, date); if (isUpdated != null) { wrapper.eq(TaskProgressUpdateLog::getIsUpdated, isUpdated); } wrapper.orderByDesc(TaskProgressUpdateLog::getCreateTime); return progressUpdateLogMapper.selectList(wrapper); } /** * 获取某个用户的进度更新记录 */ public List getUserProgressUpdateLogs(Long userId, LocalDate startDate, LocalDate endDate) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(TaskProgressUpdateLog::getReceiverId, userId); if (startDate != null) { wrapper.ge(TaskProgressUpdateLog::getCheckDate, startDate); } if (endDate != null) { wrapper.le(TaskProgressUpdateLog::getCheckDate, endDate); } wrapper.orderByDesc(TaskProgressUpdateLog::getCheckDate); return progressUpdateLogMapper.selectList(wrapper); } }