qiangdanxitong/backend/src/main/java/com/designhub/service/TaskProgressCheckService.java
Your Name 9b849ccb40 feat: 优化子任务进度显示为时间线样式 + 修复需求者进行中任务显示
1. 将子任务进度从标签式改为时间线流程图样式,更直观展示任务流转进度
2. 修复需求部门用户在"进行中任务"页面看不到自己发起的任务的问题
3. 添加子任务状态辅助函数(状态类名、标签、状态文本)
4. 在MyTasksParams中添加keyword参数支持搜索
2026-01-07 15:38:59 +08:00

257 lines
11 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<TaskItem> inProgressItems = taskItemMapper.selectList(
new LambdaQueryWrapper<TaskItem>()
.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<Task> inProgressTasks = taskMapper.selectList(
new LambdaQueryWrapper<Task>()
.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<TaskProgressUpdateLog>()
.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<TaskProgressUpdateLog> getProgressUpdateLogs(LocalDate date, Integer isUpdated) {
LambdaQueryWrapper<TaskProgressUpdateLog> 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<TaskProgressUpdateLog> getUserProgressUpdateLogs(Long userId, LocalDate startDate, LocalDate endDate) {
LambdaQueryWrapper<TaskProgressUpdateLog> 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);
}
}