diff --git a/docs/dev-ops/pgsql/sql/weform_run.sql b/docs/dev-ops/pgsql/sql/weform_run.sql index d7612e6..7ca9fc4 100644 --- a/docs/dev-ops/pgsql/sql/weform_run.sql +++ b/docs/dev-ops/pgsql/sql/weform_run.sql @@ -405,7 +405,6 @@ CREATE TABLE task ( task_code VARCHAR(50), project_id BIGINT NOT NULL, milestone_id BIGINT, - parent_id BIGINT, task_name VARCHAR(200) NOT NULL, description TEXT, task_type VARCHAR(50), @@ -431,13 +430,11 @@ CREATE TABLE task ( CONSTRAINT fk_task_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE, CONSTRAINT fk_task_milestone FOREIGN KEY (milestone_id) REFERENCES project_milestone(id) ON DELETE SET NULL, - CONSTRAINT fk_task_parent FOREIGN KEY (parent_id) REFERENCES task(id) ON DELETE SET NULL, CONSTRAINT fk_task_assignee FOREIGN KEY (assignee_id) REFERENCES sys_user(id) ON DELETE SET NULL ); CREATE INDEX idx_task_project ON task(project_id); CREATE INDEX idx_task_milestone ON task(milestone_id); -CREATE INDEX idx_task_parent ON task(parent_id); CREATE INDEX idx_task_assignee ON task(assignee_id); CREATE INDEX idx_task_status ON task(status); @@ -445,7 +442,6 @@ COMMENT ON TABLE task IS '任务表'; COMMENT ON COLUMN task.task_code IS '任务编号'; COMMENT ON COLUMN task.project_id IS '项目ID'; COMMENT ON COLUMN task.milestone_id IS '所属里程碑ID'; -COMMENT ON COLUMN task.parent_id IS '父任务ID'; COMMENT ON COLUMN task.task_name IS '任务名称'; COMMENT ON COLUMN task.description IS '任务描述'; COMMENT ON COLUMN task.task_type IS '任务类型'; @@ -475,8 +471,10 @@ CREATE TABLE task_dependency ( create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(task_id, depends_on_task_id), + + -- 修正了下面的 fk_td_depends 约束 CONSTRAINT fk_td_task FOREIGN KEY (task_id) REFERENCES task(id) ON DELETE CASCADE, - CONSTRAINT fk_td_depends ON DELETE CASCADE + CONSTRAINT fk_td_depends FOREIGN KEY (depends_on_task_id) REFERENCES task(id) ON DELETE CASCADE ); CREATE INDEX idx_td_depends ON task_dependency(depends_on_task_id); diff --git a/src/main/java/cn/yinlihupo/domain/entity/Task.java b/src/main/java/cn/yinlihupo/domain/entity/Task.java index ad6d830..874d0ce 100644 --- a/src/main/java/cn/yinlihupo/domain/entity/Task.java +++ b/src/main/java/cn/yinlihupo/domain/entity/Task.java @@ -35,11 +35,6 @@ public class Task { */ private Long milestoneId; - /** - * 父任务ID - */ - private Long parentId; - /** * 任务名称 */ diff --git a/src/main/java/cn/yinlihupo/domain/entity/TaskDependency.java b/src/main/java/cn/yinlihupo/domain/entity/TaskDependency.java new file mode 100644 index 0000000..3c00c3b --- /dev/null +++ b/src/main/java/cn/yinlihupo/domain/entity/TaskDependency.java @@ -0,0 +1,44 @@ +package cn.yinlihupo.domain.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 任务依赖关系实体类 + * 对应数据库表: task_dependency + */ +@Data +@TableName("task_dependency") +public class TaskDependency { + + @TableId(type = IdType.ASSIGN_ID) + private Long id; + + /** + * 任务ID + */ + private Long taskId; + + /** + * 依赖的任务ID + */ + private Long dependsOnTaskId; + + /** + * 依赖类型: finish_to_start-完成-开始, start_to_start-开始-开始, finish_to_finish-完成-完成, start_to_finish-开始-完成 + */ + private String dependencyType; + + /** + * 滞后天数 + */ + private Integer lagDays; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; +} diff --git a/src/main/java/cn/yinlihupo/domain/vo/ProjectInitResult.java b/src/main/java/cn/yinlihupo/domain/vo/ProjectInitResult.java index 1f447fd..ceed5e8 100644 --- a/src/main/java/cn/yinlihupo/domain/vo/ProjectInitResult.java +++ b/src/main/java/cn/yinlihupo/domain/vo/ProjectInitResult.java @@ -111,6 +111,9 @@ public class ProjectInitResult { @Data public static class TaskInfo { + @JsonProperty("task_id") + private String taskId; + @JsonProperty("task_name") private String taskName; diff --git a/src/main/java/cn/yinlihupo/mapper/TaskDependencyMapper.java b/src/main/java/cn/yinlihupo/mapper/TaskDependencyMapper.java new file mode 100644 index 0000000..a888839 --- /dev/null +++ b/src/main/java/cn/yinlihupo/mapper/TaskDependencyMapper.java @@ -0,0 +1,12 @@ +package cn.yinlihupo.mapper; + +import cn.yinlihupo.domain.entity.TaskDependency; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 任务依赖关系Mapper接口 + */ +@Mapper +public interface TaskDependencyMapper extends BaseMapper { +} diff --git a/src/main/java/cn/yinlihupo/service/project/impl/ProjectServiceImpl.java b/src/main/java/cn/yinlihupo/service/project/impl/ProjectServiceImpl.java index 3d1d5d5..6d5b7b3 100644 --- a/src/main/java/cn/yinlihupo/service/project/impl/ProjectServiceImpl.java +++ b/src/main/java/cn/yinlihupo/service/project/impl/ProjectServiceImpl.java @@ -40,6 +40,7 @@ public class ProjectServiceImpl implements ProjectService { private final ProjectMapper projectMapper; private final ProjectMilestoneMapper projectMilestoneMapper; private final TaskMapper taskMapper; + private final TaskDependencyMapper taskDependencyMapper; private final ProjectMemberMapper projectMemberMapper; private final ResourceMapper resourceMapper; private final RiskMapper riskMapper; @@ -93,6 +94,7 @@ public class ProjectServiceImpl implements ProjectService { ], "tasks": [ { + "task_id": "T001", "task_name": "任务名称", "parent_task_id": null, "description": "任务描述", @@ -101,7 +103,7 @@ public class ProjectServiceImpl implements ProjectService { "estimated_hours": 80, "priority": "high", "assignee_role": "执行者角色", - "dependencies": ["前置任务ID"], + "dependencies": ["T001"], "deliverables": "交付物" } ], @@ -313,26 +315,57 @@ public class ProjectServiceImpl implements ProjectService { task.setSortOrder(i); taskMapper.insert(task); - // 使用任务名称作为临时ID进行映射 - String tempId = taskInfo.getTaskName(); - taskTempIdToId.put(tempId, task.getId()); + // 使用task_id作为临时ID进行映射 + String tempId = taskInfo.getTaskId(); + if (tempId != null && !tempId.isEmpty()) { + taskTempIdToId.put(tempId, task.getId()); + } else { + // 兼容旧格式:如果没有task_id,使用task_name + taskTempIdToId.put(taskInfo.getTaskName(), task.getId()); + } } - // 第二轮:更新任务依赖关系 + // 第二轮:保存任务层级关系(parent_task_id)到 task_dependency 表 + int hierarchyCount = 0; for (int i = 0; i < result.getTasks().size(); i++) { ProjectInitResult.TaskInfo taskInfo = result.getTasks().get(i); if (taskInfo.getParentTaskId() != null && !taskInfo.getParentTaskId().isEmpty()) { - Task task = new Task(); - task.setId(taskTempIdToId.get(taskInfo.getTaskName())); - // 查找父任务ID + Long taskId = taskTempIdToId.get(taskInfo.getTaskId()); Long parentId = taskTempIdToId.get(taskInfo.getParentTaskId()); - if (parentId != null) { - task.setParentId(parentId); - taskMapper.updateById(task); + if (taskId != null && parentId != null) { + TaskDependency dependency = new TaskDependency(); + dependency.setTaskId(taskId); + dependency.setDependsOnTaskId(parentId); + dependency.setDependencyType("hierarchy"); // 层级关系 + dependency.setLagDays(0); + taskDependencyMapper.insert(dependency); + hierarchyCount++; } } } - log.info("保存了 {} 个任务", result.getTasks().size()); + + // 第三轮:保存任务执行依赖关系(dependencies)到 task_dependency 表 + int dependencyCount = 0; + for (int i = 0; i < result.getTasks().size(); i++) { + ProjectInitResult.TaskInfo taskInfo = result.getTasks().get(i); + if (taskInfo.getDependencies() != null && !taskInfo.getDependencies().isEmpty()) { + Long taskId = taskTempIdToId.get(taskInfo.getTaskId()); + for (String dependsOnTaskId : taskInfo.getDependencies()) { + Long dependsOnId = taskTempIdToId.get(dependsOnTaskId); + if (dependsOnId != null && taskId != null) { + TaskDependency dependency = new TaskDependency(); + dependency.setTaskId(taskId); + dependency.setDependsOnTaskId(dependsOnId); + dependency.setDependencyType("finish_to_start"); // 默认依赖类型 + dependency.setLagDays(0); + taskDependencyMapper.insert(dependency); + dependencyCount++; + } + } + } + } + log.info("保存了 {} 个任务, {} 个层级关系, {} 个执行依赖关系", + result.getTasks().size(), hierarchyCount, dependencyCount); } // 4. 保存项目成员