feat: 为任务卡片添加子任务进度统计功能
新增功能: 1. Task实体新增字段: - subTaskTotal: 子任务总数 - subTaskCompleted: 已完成子任务数 - subTaskInProgress: 进行中子任务数 - subTaskPending: 待接单子任务数 - subTasks: 子任务列表(包含处理人信息) 2. TaskService新增方法: - fillSubTaskStats(): 填充流水线任务的子任务统计信息 - 自动在getMyPublishedTasks和getMyReceivedTasks中调用 - 统计各状态子任务数量 - 自动填充处理人信息 3. 同时修复流水线任务主任务状态同步问题: - 设计师接单第一个子任务时,主任务状态更新为in_progress - 确保需求方能正确看到任务进度 影响范围: - 需求方查看"我发起的"任务时,可以看到子任务进度 - 设计师查看接收的任务时,可以看到子任务详情 - 为后续前端显示提供数据支持
This commit is contained in:
parent
ef7e39cb00
commit
371cfd5b2a
@ -317,6 +317,36 @@ public class Task implements Serializable {
|
||||
@TableField(exist = false)
|
||||
private String auditorName;
|
||||
|
||||
/**
|
||||
* 子任务总数(非数据库字段,流水线任务专用)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer subTaskTotal;
|
||||
|
||||
/**
|
||||
* 已完成子任务数(非数据库字段,流水线任务专用)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer subTaskCompleted;
|
||||
|
||||
/**
|
||||
* 进行中子任务数(非数据库字段,流水线任务专用)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer subTaskInProgress;
|
||||
|
||||
/**
|
||||
* 待接单子任务数(非数据库字段,流水线任务专用)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer subTaskPending;
|
||||
|
||||
/**
|
||||
* 子任务列表(非数据库字段,流水线任务专用)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private java.util.List<TaskItem> subTasks;
|
||||
|
||||
/**
|
||||
* 当前审核人姓名(查询时返回,不映射到数据库)
|
||||
*/
|
||||
@ -513,5 +543,20 @@ public class Task implements Serializable {
|
||||
|
||||
public String getCurrentApproverName() { return currentApproverName; }
|
||||
public void setCurrentApproverName(String currentApproverName) { this.currentApproverName = currentApproverName; }
|
||||
|
||||
public Integer getSubTaskTotal() { return subTaskTotal; }
|
||||
public void setSubTaskTotal(Integer subTaskTotal) { this.subTaskTotal = subTaskTotal; }
|
||||
|
||||
public Integer getSubTaskCompleted() { return subTaskCompleted; }
|
||||
public void setSubTaskCompleted(Integer subTaskCompleted) { this.subTaskCompleted = subTaskCompleted; }
|
||||
|
||||
public Integer getSubTaskInProgress() { return subTaskInProgress; }
|
||||
public void setSubTaskInProgress(Integer subTaskInProgress) { this.subTaskInProgress = subTaskInProgress; }
|
||||
|
||||
public Integer getSubTaskPending() { return subTaskPending; }
|
||||
public void setSubTaskPending(Integer subTaskPending) { this.subTaskPending = subTaskPending; }
|
||||
|
||||
public java.util.List<TaskItem> getSubTasks() { return subTasks; }
|
||||
public void setSubTasks(java.util.List<TaskItem> subTasks) { this.subTasks = subTasks; }
|
||||
}
|
||||
|
||||
|
||||
@ -105,7 +105,7 @@ public class DepartmentService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DepartmentOverviewVO createDepartment(DepartmentCreateRequest request) {
|
||||
validateDeptType(request.getDeptType());
|
||||
|
||||
|
||||
// 验证负责人ID是否有效
|
||||
if (request.getLeaderId() != null && request.getLeaderId() > 0) {
|
||||
User leader = userMapper.selectById(request.getLeaderId());
|
||||
|
||||
@ -261,8 +261,8 @@ public class TaskApprovalService {
|
||||
// TODO: 通知指定的设计师
|
||||
log.info("任务【{}】已指定给设计师", task.getTitle());
|
||||
} else {
|
||||
// TODO: 通知任务大厅(所有接单部门成员)
|
||||
log.info("任务【{}】已发布到任务大厅", task.getTitle());
|
||||
// TODO: 通知任务大厅(所有接单部门成员)
|
||||
log.info("任务【{}】已发布到任务大厅", task.getTitle());
|
||||
}
|
||||
|
||||
log.info("接单部门负责人审核通过,任务ID:{},审核人:{},指定接收人:{}",
|
||||
|
||||
@ -131,19 +131,31 @@ public class TaskItemService {
|
||||
|
||||
log.info("设计师 {} 成功抢单子任务 {}", userId, itemId);
|
||||
|
||||
// 发送通知给任务发布者
|
||||
// 更新主任务状态
|
||||
Task mainTask = taskMapper.selectById(item.getTaskId());
|
||||
if (mainTask != null && mainTask.getPublisherId() != null) {
|
||||
Notification notification = new Notification();
|
||||
notification.setReceiverId(mainTask.getPublisherId());
|
||||
notification.setNotificationType("task");
|
||||
notification.setTitle("子任务已被接单");
|
||||
notification.setContent(user.getRealName() + " 接单了子任务:" + item.getItemNo());
|
||||
notification.setRelatedId(itemId);
|
||||
notification.setRelatedType("task_item");
|
||||
notification.setPriority(1); // 普通
|
||||
notification.setPushDingtalk(1); // 推送到钉钉
|
||||
notificationService.sendNotification(notification);
|
||||
if (mainTask != null) {
|
||||
// 如果主任务还是pending状态,更新为in_progress
|
||||
if ("pending".equals(mainTask.getStatus())) {
|
||||
mainTask.setStatus("in_progress");
|
||||
mainTask.setStartTime(LocalDateTime.now());
|
||||
mainTask.setActualStartTime(LocalDateTime.now());
|
||||
taskMapper.updateById(mainTask);
|
||||
log.info("主任务 {} 状态已更新为 in_progress", mainTask.getId());
|
||||
}
|
||||
|
||||
// 发送通知给任务发布者
|
||||
if (mainTask.getPublisherId() != null) {
|
||||
Notification notification = new Notification();
|
||||
notification.setReceiverId(mainTask.getPublisherId());
|
||||
notification.setNotificationType("task");
|
||||
notification.setTitle("子任务已被接单");
|
||||
notification.setContent(user.getRealName() + " 接单了子任务:" + item.getItemNo());
|
||||
notification.setRelatedId(itemId);
|
||||
notification.setRelatedType("task_item");
|
||||
notification.setPriority(1); // 普通
|
||||
notification.setPushDingtalk(1); // 推送到钉钉
|
||||
notificationService.sendNotification(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -618,7 +618,14 @@ public class TaskService {
|
||||
*/
|
||||
public IPage<Task> getMyPublishedTasks(Integer page, Integer pageSize, Long userId, String status) {
|
||||
Page<Task> pageParam = new Page<>(page, pageSize);
|
||||
return taskMapper.selectMyPublishedTasks(pageParam, userId, status);
|
||||
IPage<Task> taskPage = taskMapper.selectMyPublishedTasks(pageParam, userId, status);
|
||||
|
||||
// 填充子任务统计信息
|
||||
for (Task task : taskPage.getRecords()) {
|
||||
fillSubTaskStats(task);
|
||||
}
|
||||
|
||||
return taskPage;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -626,7 +633,59 @@ public class TaskService {
|
||||
*/
|
||||
public IPage<Task> getMyReceivedTasks(Integer page, Integer pageSize, Long userId, String status) {
|
||||
Page<Task> pageParam = new Page<>(page, pageSize);
|
||||
return taskMapper.selectMyReceivedTasks(pageParam, userId, status);
|
||||
IPage<Task> taskPage = taskMapper.selectMyReceivedTasks(pageParam, userId, status);
|
||||
|
||||
// 填充子任务统计信息
|
||||
for (Task task : taskPage.getRecords()) {
|
||||
fillSubTaskStats(task);
|
||||
}
|
||||
|
||||
return taskPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充流水线任务的子任务统计信息
|
||||
*/
|
||||
private void fillSubTaskStats(Task task) {
|
||||
// 只有流水线任务才需要填充子任务信息
|
||||
if (task.getIsPipeline() == null || task.getIsPipeline() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 查询所有子任务
|
||||
List<TaskItem> subTasks = taskItemMapper.selectList(
|
||||
new LambdaQueryWrapper<TaskItem>()
|
||||
.eq(TaskItem::getTaskId, task.getId())
|
||||
.orderByAsc(TaskItem::getSortOrder)
|
||||
);
|
||||
|
||||
if (subTasks != null && !subTasks.isEmpty()) {
|
||||
task.setSubTaskTotal(subTasks.size());
|
||||
|
||||
// 统计各状态子任务数量
|
||||
long completedCount = subTasks.stream().filter(item -> "completed".equals(item.getStatus())).count();
|
||||
long inProgressCount = subTasks.stream().filter(item -> "in_progress".equals(item.getStatus())).count();
|
||||
long pendingCount = subTasks.stream().filter(item -> "pending".equals(item.getStatus())).count();
|
||||
|
||||
task.setSubTaskCompleted((int) completedCount);
|
||||
task.setSubTaskInProgress((int) inProgressCount);
|
||||
task.setSubTaskPending((int) pendingCount);
|
||||
|
||||
// 设置子任务列表(包含处理人信息)
|
||||
task.setSubTasks(subTasks);
|
||||
|
||||
// 如果主任务没有receiverName,从子任务中获取第一个有接单人的
|
||||
if (task.getReceiverName() == null || task.getReceiverName().isEmpty()) {
|
||||
subTasks.stream()
|
||||
.filter(item -> item.getReceiverName() != null && !item.getReceiverName().isEmpty())
|
||||
.findFirst()
|
||||
.ifPresent(item -> task.setReceiverName(item.getReceiverName() + "等"));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("填充子任务统计信息失败:taskId={}", task.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -168,22 +168,22 @@ const getIconName = (notification: Notification) => {
|
||||
|
||||
// 匹配系统通知
|
||||
if (type === 'system') {
|
||||
return 'info'
|
||||
return 'info'
|
||||
}
|
||||
|
||||
// 匹配任务相关通知(task, task_approval, task_review, task_completed, task_rejected等)
|
||||
if (type.includes('task')) {
|
||||
return 'document'
|
||||
return 'document'
|
||||
}
|
||||
|
||||
// 匹配积分通知
|
||||
if (type.includes('score')) {
|
||||
return 'trophy'
|
||||
return 'trophy'
|
||||
}
|
||||
|
||||
// 匹配评审通知
|
||||
if (type === 'review' || type.includes('review')) {
|
||||
return 'star'
|
||||
return 'star'
|
||||
}
|
||||
|
||||
// 默认铃铛图标
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user