2025-09-14 14:13:40 +08:00
|
|
|
|
package plan
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-09-20 17:11:04 +08:00
|
|
|
|
"encoding/json"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
|
2025-09-14 14:13:40 +08:00
|
|
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// PlanToResponse 将Plan模型转换为PlanResponse
|
2025-09-20 17:11:04 +08:00
|
|
|
|
func PlanToResponse(plan *models.Plan) (*PlanResponse, error) {
|
2025-09-14 14:13:40 +08:00
|
|
|
|
if plan == nil {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
return nil, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response := &PlanResponse{
|
|
|
|
|
|
ID: plan.ID,
|
|
|
|
|
|
Name: plan.Name,
|
|
|
|
|
|
Description: plan.Description,
|
|
|
|
|
|
ExecutionType: plan.ExecutionType,
|
2025-09-19 13:18:05 +08:00
|
|
|
|
Status: plan.Status,
|
|
|
|
|
|
ExecuteNum: plan.ExecuteNum,
|
|
|
|
|
|
ExecuteCount: plan.ExecuteCount,
|
2025-09-14 14:13:40 +08:00
|
|
|
|
CronExpression: plan.CronExpression,
|
|
|
|
|
|
ContentType: plan.ContentType,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换子计划
|
|
|
|
|
|
if plan.ContentType == models.PlanContentTypeSubPlans {
|
|
|
|
|
|
response.SubPlans = make([]SubPlanResponse, len(plan.SubPlans))
|
|
|
|
|
|
for i, subPlan := range plan.SubPlans {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
subPlanResp, err := SubPlanToResponse(&subPlan)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
response.SubPlans[i] = subPlanResp
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转换任务
|
|
|
|
|
|
if plan.ContentType == models.PlanContentTypeTasks {
|
|
|
|
|
|
response.Tasks = make([]TaskResponse, len(plan.Tasks))
|
|
|
|
|
|
for i, task := range plan.Tasks {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
taskResp, err := TaskToResponse(&task)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
response.Tasks[i] = taskResp
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-20 17:11:04 +08:00
|
|
|
|
return response, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 15:47:08 +08:00
|
|
|
|
// PlanFromCreateRequest 将CreatePlanRequest转换为Plan模型,并进行业务规则验证
|
|
|
|
|
|
func PlanFromCreateRequest(req *CreatePlanRequest) (*models.Plan, error) {
|
2025-09-14 14:13:40 +08:00
|
|
|
|
if req == nil {
|
2025-09-14 15:47:08 +08:00
|
|
|
|
return nil, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
plan := &models.Plan{
|
|
|
|
|
|
Name: req.Name,
|
|
|
|
|
|
Description: req.Description,
|
|
|
|
|
|
ExecutionType: req.ExecutionType,
|
2025-09-19 13:35:41 +08:00
|
|
|
|
ExecuteNum: req.ExecuteNum,
|
2025-09-14 14:13:40 +08:00
|
|
|
|
CronExpression: req.CronExpression,
|
2025-09-23 19:28:43 +08:00
|
|
|
|
// ContentType 在控制器中设置,此处不再处理
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理子计划 (通过ID引用)
|
2025-09-23 19:28:43 +08:00
|
|
|
|
if req.SubPlanIDs != nil {
|
|
|
|
|
|
subPlanSlice := req.SubPlanIDs
|
|
|
|
|
|
plan.SubPlans = make([]models.SubPlan, len(subPlanSlice))
|
|
|
|
|
|
for i, childPlanID := range subPlanSlice {
|
2025-09-14 14:13:40 +08:00
|
|
|
|
plan.SubPlans[i] = models.SubPlan{
|
|
|
|
|
|
ChildPlanID: childPlanID,
|
2025-09-14 15:47:08 +08:00
|
|
|
|
ExecutionOrder: i, // 默认执行顺序, ReorderSteps会再次确认
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理任务
|
2025-09-23 19:28:43 +08:00
|
|
|
|
if req.Tasks != nil {
|
|
|
|
|
|
taskSlice := req.Tasks
|
|
|
|
|
|
plan.Tasks = make([]models.Task, len(taskSlice))
|
|
|
|
|
|
for i, taskReq := range taskSlice {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
task, err := TaskFromRequest(&taskReq)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
plan.Tasks[i] = task
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 15:47:08 +08:00
|
|
|
|
// 1. 首先,执行重复性验证
|
|
|
|
|
|
if err := plan.ValidateExecutionOrder(); err != nil {
|
|
|
|
|
|
// 如果检测到重复,立即返回错误
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 然后,调用方法来修复顺序断层
|
|
|
|
|
|
plan.ReorderSteps()
|
|
|
|
|
|
|
|
|
|
|
|
return plan, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 15:47:08 +08:00
|
|
|
|
// PlanFromUpdateRequest 将UpdatePlanRequest转换为Plan模型,并进行业务规则验证
|
|
|
|
|
|
func PlanFromUpdateRequest(req *UpdatePlanRequest) (*models.Plan, error) {
|
2025-09-14 14:13:40 +08:00
|
|
|
|
if req == nil {
|
2025-09-14 15:47:08 +08:00
|
|
|
|
return nil, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
plan := &models.Plan{
|
|
|
|
|
|
Name: req.Name,
|
|
|
|
|
|
Description: req.Description,
|
|
|
|
|
|
ExecutionType: req.ExecutionType,
|
2025-09-19 13:35:41 +08:00
|
|
|
|
ExecuteNum: req.ExecuteNum,
|
2025-09-14 14:13:40 +08:00
|
|
|
|
CronExpression: req.CronExpression,
|
2025-09-23 19:28:43 +08:00
|
|
|
|
// ContentType 在控制器中设置,此处不再处理
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理子计划 (通过ID引用)
|
2025-09-23 19:28:43 +08:00
|
|
|
|
if req.SubPlanIDs != nil {
|
|
|
|
|
|
subPlanSlice := req.SubPlanIDs
|
|
|
|
|
|
plan.SubPlans = make([]models.SubPlan, len(subPlanSlice))
|
|
|
|
|
|
for i, childPlanID := range subPlanSlice {
|
2025-09-14 14:13:40 +08:00
|
|
|
|
plan.SubPlans[i] = models.SubPlan{
|
|
|
|
|
|
ChildPlanID: childPlanID,
|
2025-09-14 15:47:08 +08:00
|
|
|
|
ExecutionOrder: i, // 默认执行顺序, ReorderSteps会再次确认
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理任务
|
2025-09-23 19:28:43 +08:00
|
|
|
|
if req.Tasks != nil {
|
|
|
|
|
|
taskSlice := req.Tasks
|
|
|
|
|
|
plan.Tasks = make([]models.Task, len(taskSlice))
|
|
|
|
|
|
for i, taskReq := range taskSlice {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
task, err := TaskFromRequest(&taskReq)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
plan.Tasks[i] = task
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-14 15:47:08 +08:00
|
|
|
|
// 1. 首先,执行重复性验证
|
|
|
|
|
|
if err := plan.ValidateExecutionOrder(); err != nil {
|
|
|
|
|
|
// 如果检测到重复,立即返回错误
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 然后,调用方法来修复顺序断层
|
|
|
|
|
|
plan.ReorderSteps()
|
|
|
|
|
|
|
|
|
|
|
|
return plan, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// SubPlanToResponse 将SubPlan模型转换为SubPlanResponse
|
2025-09-20 17:11:04 +08:00
|
|
|
|
func SubPlanToResponse(subPlan *models.SubPlan) (SubPlanResponse, error) {
|
2025-09-14 14:13:40 +08:00
|
|
|
|
if subPlan == nil {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
return SubPlanResponse{}, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response := SubPlanResponse{
|
|
|
|
|
|
ID: subPlan.ID,
|
|
|
|
|
|
ParentPlanID: subPlan.ParentPlanID,
|
|
|
|
|
|
ChildPlanID: subPlan.ChildPlanID,
|
|
|
|
|
|
ExecutionOrder: subPlan.ExecutionOrder,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有完整的子计划数据,也进行转换
|
|
|
|
|
|
if subPlan.ChildPlan != nil {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
childPlanResp, err := PlanToResponse(subPlan.ChildPlan)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return SubPlanResponse{}, err
|
|
|
|
|
|
}
|
|
|
|
|
|
response.ChildPlan = childPlanResp
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-20 17:11:04 +08:00
|
|
|
|
return response, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TaskToResponse 将Task模型转换为TaskResponse
|
2025-09-20 17:11:04 +08:00
|
|
|
|
func TaskToResponse(task *models.Task) (TaskResponse, error) {
|
2025-09-14 14:13:40 +08:00
|
|
|
|
if task == nil {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
return TaskResponse{}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var params map[string]interface{}
|
|
|
|
|
|
if len(task.Parameters) > 0 && string(task.Parameters) != "null" {
|
2025-09-27 00:58:22 +08:00
|
|
|
|
if err := task.ParseParameters(¶ms); err != nil {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
return TaskResponse{}, fmt.Errorf("parsing task parameters failed (ID: %d): %w", task.ID, err)
|
|
|
|
|
|
}
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return TaskResponse{
|
|
|
|
|
|
ID: task.ID,
|
|
|
|
|
|
PlanID: task.PlanID,
|
|
|
|
|
|
Name: task.Name,
|
|
|
|
|
|
Description: task.Description,
|
|
|
|
|
|
ExecutionOrder: task.ExecutionOrder,
|
|
|
|
|
|
Type: task.Type,
|
2025-09-20 17:11:04 +08:00
|
|
|
|
Parameters: params,
|
|
|
|
|
|
}, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TaskFromRequest 将TaskRequest转换为Task模型
|
2025-09-20 17:11:04 +08:00
|
|
|
|
func TaskFromRequest(req *TaskRequest) (models.Task, error) {
|
2025-09-14 14:13:40 +08:00
|
|
|
|
if req == nil {
|
2025-09-20 17:11:04 +08:00
|
|
|
|
return models.Task{}, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
paramsJSON, err := json.Marshal(req.Parameters)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return models.Task{}, fmt.Errorf("serializing task parameters failed: %w", err)
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return models.Task{
|
|
|
|
|
|
Name: req.Name,
|
|
|
|
|
|
Description: req.Description,
|
|
|
|
|
|
ExecutionOrder: req.ExecutionOrder,
|
|
|
|
|
|
Type: req.Type,
|
2025-09-20 17:11:04 +08:00
|
|
|
|
Parameters: paramsJSON,
|
|
|
|
|
|
}, nil
|
2025-09-14 14:13:40 +08:00
|
|
|
|
}
|