修复bug

This commit is contained in:
2025-09-20 17:11:04 +08:00
parent cb63437e0e
commit 1f2d54d53e
9 changed files with 212 additions and 104 deletions

View File

@@ -1,15 +1,16 @@
package plan
import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
"encoding/json"
"fmt"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"gorm.io/datatypes"
)
// PlanToResponse 将Plan模型转换为PlanResponse
func PlanToResponse(plan *models.Plan) *PlanResponse {
func PlanToResponse(plan *models.Plan) (*PlanResponse, error) {
if plan == nil {
return nil
return nil, nil
}
response := &PlanResponse{
@@ -28,7 +29,11 @@ func PlanToResponse(plan *models.Plan) *PlanResponse {
if plan.ContentType == models.PlanContentTypeSubPlans {
response.SubPlans = make([]SubPlanResponse, len(plan.SubPlans))
for i, subPlan := range plan.SubPlans {
response.SubPlans[i] = SubPlanToResponse(&subPlan)
subPlanResp, err := SubPlanToResponse(&subPlan)
if err != nil {
return nil, err
}
response.SubPlans[i] = subPlanResp
}
}
@@ -36,11 +41,15 @@ func PlanToResponse(plan *models.Plan) *PlanResponse {
if plan.ContentType == models.PlanContentTypeTasks {
response.Tasks = make([]TaskResponse, len(plan.Tasks))
for i, task := range plan.Tasks {
response.Tasks[i] = TaskToResponse(&task)
taskResp, err := TaskToResponse(&task)
if err != nil {
return nil, err
}
response.Tasks[i] = taskResp
}
}
return response
return response, nil
}
// PlanFromCreateRequest 将CreatePlanRequest转换为Plan模型并进行业务规则验证
@@ -73,8 +82,11 @@ func PlanFromCreateRequest(req *CreatePlanRequest) (*models.Plan, error) {
if req.ContentType == models.PlanContentTypeTasks && req.Tasks != nil {
plan.Tasks = make([]models.Task, len(req.Tasks))
for i, taskReq := range req.Tasks {
// 使用来自请求的ExecutionOrder
plan.Tasks[i] = TaskFromRequest(&taskReq)
task, err := TaskFromRequest(&taskReq)
if err != nil {
return nil, err
}
plan.Tasks[i] = task
}
}
@@ -120,8 +132,11 @@ func PlanFromUpdateRequest(req *UpdatePlanRequest) (*models.Plan, error) {
if req.ContentType == models.PlanContentTypeTasks && req.Tasks != nil {
plan.Tasks = make([]models.Task, len(req.Tasks))
for i, taskReq := range req.Tasks {
// 使用来自请求的ExecutionOrder
plan.Tasks[i] = TaskFromRequest(&taskReq)
task, err := TaskFromRequest(&taskReq)
if err != nil {
return nil, err
}
plan.Tasks[i] = task
}
}
@@ -138,9 +153,9 @@ func PlanFromUpdateRequest(req *UpdatePlanRequest) (*models.Plan, error) {
}
// SubPlanToResponse 将SubPlan模型转换为SubPlanResponse
func SubPlanToResponse(subPlan *models.SubPlan) SubPlanResponse {
func SubPlanToResponse(subPlan *models.SubPlan) (SubPlanResponse, error) {
if subPlan == nil {
return SubPlanResponse{}
return SubPlanResponse{}, nil
}
response := SubPlanResponse{
@@ -152,16 +167,27 @@ func SubPlanToResponse(subPlan *models.SubPlan) SubPlanResponse {
// 如果有完整的子计划数据,也进行转换
if subPlan.ChildPlan != nil {
response.ChildPlan = PlanToResponse(subPlan.ChildPlan)
childPlanResp, err := PlanToResponse(subPlan.ChildPlan)
if err != nil {
return SubPlanResponse{}, err
}
response.ChildPlan = childPlanResp
}
return response
return response, nil
}
// TaskToResponse 将Task模型转换为TaskResponse
func TaskToResponse(task *models.Task) TaskResponse {
func TaskToResponse(task *models.Task) (TaskResponse, error) {
if task == nil {
return TaskResponse{}
return TaskResponse{}, nil
}
var params map[string]interface{}
if len(task.Parameters) > 0 && string(task.Parameters) != "null" {
if err := json.Unmarshal(task.Parameters, &params); err != nil {
return TaskResponse{}, fmt.Errorf("parsing task parameters failed (ID: %d): %w", task.ID, err)
}
}
return TaskResponse{
@@ -171,14 +197,19 @@ func TaskToResponse(task *models.Task) TaskResponse {
Description: task.Description,
ExecutionOrder: task.ExecutionOrder,
Type: task.Type,
Parameters: controller.Properties(task.Parameters),
}
Parameters: params,
}, nil
}
// TaskFromRequest 将TaskRequest转换为Task模型
func TaskFromRequest(req *TaskRequest) models.Task {
func TaskFromRequest(req *TaskRequest) (models.Task, error) {
if req == nil {
return models.Task{}
return models.Task{}, nil
}
paramsJSON, err := json.Marshal(req.Parameters)
if err != nil {
return models.Task{}, fmt.Errorf("serializing task parameters failed: %w", err)
}
return models.Task{
@@ -186,6 +217,6 @@ func TaskFromRequest(req *TaskRequest) models.Task {
Description: req.Description,
ExecutionOrder: req.ExecutionOrder,
Type: req.Type,
Parameters: datatypes.JSON(req.Parameters),
}
Parameters: paramsJSON,
}, nil
}

View File

@@ -71,22 +71,22 @@ type SubPlanResponse struct {
// TaskRequest 定义任务请求结构体
type TaskRequest struct {
Name string `json:"name" example:"打开风扇"`
Description string `json:"description" example:"打开1号风扇"`
ExecutionOrder int `json:"execution_order" example:"1"`
Type models.TaskType `json:"type" example:"waiting"`
Parameters controller.Properties `json:"parameters,omitempty"`
Name string `json:"name" example:"打开风扇"`
Description string `json:"description" example:"打开1号风扇"`
ExecutionOrder int `json:"execution_order" example:"1"`
Type models.TaskType `json:"type" example:"waiting"`
Parameters map[string]interface{} `json:"parameters,omitempty"`
}
// TaskResponse 定义任务响应结构体
type TaskResponse struct {
ID int `json:"id" example:"1"`
PlanID uint `json:"plan_id" example:"1"`
Name string `json:"name" example:"打开风扇"`
Description string `json:"description" example:"打开1号风扇"`
ExecutionOrder int `json:"execution_order" example:"1"`
Type models.TaskType `json:"type" example:"waiting"`
Parameters controller.Properties `json:"parameters,omitempty"`
ID int `json:"id" example:"1"`
PlanID uint `json:"plan_id" example:"1"`
Name string `json:"name" example:"打开风扇"`
Description string `json:"description" example:"打开1号风扇"`
ExecutionOrder int `json:"execution_order" example:"1"`
Type models.TaskType `json:"type" example:"waiting"`
Parameters map[string]interface{} `json:"parameters,omitempty"`
}
// --- Controller 定义 ---
@@ -145,7 +145,12 @@ func (c *Controller) CreatePlan(ctx *gin.Context) {
}
// 使用已有的转换函数将创建后的模型转换为响应对象
resp := PlanToResponse(planToCreate)
resp, err := PlanToResponse(planToCreate)
if err != nil {
c.logger.Errorf("创建计划: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "计划创建成功,但响应生成失败")
return
}
// 使用统一的成功响应函数
controller.SendResponse(ctx, controller.CodeCreated, "计划创建成功", resp)
@@ -183,7 +188,12 @@ func (c *Controller) GetPlan(ctx *gin.Context) {
}
// 3. 将模型转换为响应 DTO
resp := PlanToResponse(plan)
resp, err := PlanToResponse(plan)
if err != nil {
c.logger.Errorf("获取计划详情: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划详情失败: 内部数据格式错误")
return
}
// 4. 发送成功响应
controller.SendResponse(ctx, controller.CodeSuccess, "获取计划详情成功", resp)
@@ -208,7 +218,13 @@ func (c *Controller) ListPlans(ctx *gin.Context) {
// 2. 将模型转换为响应 DTO
planResponses := make([]PlanResponse, 0, len(plans))
for _, p := range plans {
planResponses = append(planResponses, *PlanToResponse(&p))
resp, err := PlanToResponse(&p)
if err != nil {
c.logger.Errorf("获取计划列表: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "获取计划列表失败: 内部数据格式错误")
return
}
planResponses = append(planResponses, *resp)
}
// 3. 构造并发送成功响应
@@ -286,7 +302,12 @@ func (c *Controller) UpdatePlan(ctx *gin.Context) {
}
// 7. 将模型转换为响应 DTO
resp := PlanToResponse(updatedPlan)
resp, err := PlanToResponse(updatedPlan)
if err != nil {
c.logger.Errorf("更新计划: 序列化响应失败: %v", err)
controller.SendErrorResponse(ctx, controller.CodeInternalError, "计划更新成功,但响应生成失败")
return
}
// 8. 发送成功响应
controller.SendResponse(ctx, controller.CodeSuccess, "计划更新成功", resp)