@@ -0,0 +1,355 @@
## 任务清单: Gin 到 Echo 迁移
- [x] **1. 配置文件 (无代码依赖)**
- [x] 修改 `config.yml` 中 `mode` 配置项的注释,将 "Gin 运行模式" 改为 "服务运行模式"。
- [x] 修改 `config.example.yml` 中 `mode` 配置项的注释,保持与 `config.yml` 一致。
- [x] **2. 控制器辅助函数 (最基础的依赖)**
- [x] ** `internal/infra/models/execution.go` **
- [x] 添加 `ContextAuditStatus` 和 `ContextAuditResultDetails` 常量。
- [x] ** `internal/app/controller/response.go` **
- [x] 将 `*gin.Context` 参数全部替换为 `echo.Context` 。
- [x] 修改响应函数,使其返回 `error` 。
- [x] **新增 `SendErrorWithStatus` 函数** , 用于在中间件等场景下发送带有特定HTTP状态码的错误响应。
- [x] **重构 `setAuditDetails` 函数** ,使其成为统一设置所有审计信息(包括操作状态和失败详情)的唯一入口。
- [x] 更新 `SendSuccessWithAudit` 和 `SendErrorWithAudit` 以调用重构后的 `setAuditDetails` 。
- [x] ** `internal/app/controller/auth_utils.go` **
- [x] 将 `*gin.Context` 参数全部替换为 `echo.Context` 。
- [x] 适配 `Get...FromContext` 系列函数,使用 `c.Get("key")` 提取数据。
- [x] **3. 中间件 (`internal/app/middleware`)**
- [x] ** `auth.go` **
- [x] 迁移到 Echo 中间件格式。
- [x] **使用 `controller.SendErrorWithStatus`** 在认证失败时返回 `401` 或 `500` HTTP状态码。
- [x] ** `audit.go` **
- [x] **极大简化并迁移到 Echo 中间件格式** 。
- [x] **移除所有响应体捕获和解析的逻辑** (`bodyLogWriter` , `auditResponse` 等)。
- [x] 在 `next(c)` 调用后,**直接从 `echo.Context` 中获取**由 `response.go` 设置好的最终审计状态和结果详情。
- [x] **4. 控制器 (`internal/app/controller/...`)**
- [x] **通用修改** :对所有控制器文件执行以下操作:
- [x] 将 `import "github.com/gin-gonic/gin"` 替换为 `import "github.com/labstack/echo/v4"` 。
- [x] 将所有处理函数签名从 `func(c *gin.Context)` 修改为 `func(c echo.Context) error` 。
- [x] 将 `c.ShouldBindJSON(&req)` 或 `c.ShouldBindQuery(&req)` 替换为
`if err := c.Bind(&req); err != nil { ... }` 。
- [x] 将 `c.Param("id")` 替换为 `c.Param("id")` (用法相同,检查返回值即可)。
- [x] 将 `controller.SendResponse(c, ...)` 和 `controller.SendErrorResponse(c, ...)` 调用修改为
`return controller.SendResponse(c, ...)` 和 `return controller.SendErrorResponse(c, ...)` 。
- [x] **文件清单** (按依赖顺序建议):
- [x] `internal/app/controller/management/controller_helpers.go` (注意:其中的泛型辅助函数也需要修改为返回
`error` )
- [x] `internal/app/controller/device/device_controller.go`
- [x] `internal/app/controller/management/pig_farm_controller.go`
- [x] `internal/app/controller/management/pig_batch_controller.go`
- [x] `internal/app/controller/management/pig_batch_health_controller.go`
- [x] `internal/app/controller/management/pig_batch_trade_controller.go`
- [x] `internal/app/controller/management/pig_batch_transfer_controller.go`
- [x] `internal/app/controller/monitor/monitor_controller.go`
- [x] `internal/app/controller/plan/plan_controller.go`
- [x] `internal/app/controller/user/user_controller.go`
- [x] **5. DTO 结构体注解**
- [x] **通用修改规则** :
- [x] `json:"..."` 标签保持不变。
- [x] `example:"..."` 标签保持不变。
- [x] 将 `binding:"required"` 替换为 `validate:"required"` 。
- [x] 将 `form:"field,default=value"` 替换为 `query:"field"` 。`default` 行为需在代码中手动实现(如在 DTO 构造函数中设置默认值),标签中不再需要。
- [x] 将 `form:"field"` 替换为 `query:"field"` 。
- [x] 对于 `json:"...,omitempty"` 的字段,在 `validate` 标签中也添加 `omitempty` 。
- [x] 对于结构体切片或数组字段,在 `validate` 标签中添加 `dive` 以递归验证切片元素。
- [x] 根据字段的业务含义,添加更具体的 `validate` 规则(例如 `min=0` , `cron` 等)。
- [x] **文件清单** (按 `internal/app/dto` 目录下的文件顺序):
- [x] `internal/app/dto/plan_dto.go`
- [x] `ListPlansQuery.PlanType` : `form:"planType,default=自定义任务"` -> `query:"planType"`
- [x] `ListPlansQuery.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListPlansQuery.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `CreatePlanRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `CreatePlanRequest.ExecutionType` : `binding:"required"` -> `validate:"required"`
- [x] `CreatePlanRequest.ExecuteNum` : 添加 `validate:"omitempty,min=0"`
- [x] `CreatePlanRequest.CronExpression` : 添加 `validate:"omitempty,cron"`
- [x] `CreatePlanRequest.SubPlanIDs` : 添加 `validate:"omitempty,dive"`
- [x] `CreatePlanRequest.Tasks` : 添加 `validate:"omitempty,dive"`
- [x] `UpdatePlanRequest.ExecutionType` : `binding:"required"` -> `validate:"required"`
- [x] `UpdatePlanRequest.ExecuteNum` : 添加 `validate:"omitempty,min=0"`
- [x] `UpdatePlanRequest.CronExpression` : 添加 `validate:"omitempty,cron"`
- [x] `UpdatePlanRequest.SubPlanIDs` : 添加 `validate:"omitempty,dive"`
- [x] `UpdatePlanRequest.Tasks` : 添加 `validate:"omitempty,dive"`
- [x] `internal/app/dto/user_dto.go`
- [x] `CreateUserRequest.Username` : `binding:"required"` -> `validate:"required"`
- [x] `CreateUserRequest.Password` : `binding:"required"` -> `validate:"required"`
- [x] `LoginRequest.Identifier` : `binding:"required"` -> `validate:"required"`
- [x] `LoginRequest.Password` : `binding:"required"` -> `validate:"required"`
- [x] `internal/app/dto/device_dto.go`
- [x] `CreateDeviceRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `CreateDeviceRequest.DeviceTemplateID` : `binding:"required"` -> `validate:"required"`
- [x] `CreateDeviceRequest.AreaControllerID` : `binding:"required"` -> `validate:"required"`
- [x] `CreateDeviceRequest.Location` : `json:"location,omitempty"` -> `validate:"omitempty"`
- [x] `CreateDeviceRequest.Properties` : `json:"properties,omitempty"` -> `validate:"omitempty"`
- [x] `UpdateDeviceRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `UpdateDeviceRequest.DeviceTemplateID` : `binding:"required"` -> `validate:"required"`
- [x] `UpdateDeviceRequest.AreaControllerID` : `binding:"required"` -> `validate:"required"`
- [x] `UpdateDeviceRequest.Location` : `json:"location,omitempty"` -> `validate:"omitempty"`
- [x] `UpdateDeviceRequest.Properties` : `json:"properties,omitempty"` -> `validate:"omitempty"`
- [x] `CreateAreaControllerRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `CreateAreaControllerRequest.NetworkID` : `binding:"required"` -> `validate:"required"`
- [x] `CreateAreaControllerRequest.Location` : `json:"location,omitempty"` -> `validate:"omitempty"`
- [x] `CreateAreaControllerRequest.Properties` : `json:"properties,omitempty"` -> `validate:"omitempty"`
- [x] `UpdateAreaControllerRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `UpdateAreaControllerRequest.NetworkID` : `binding:"required"` -> `validate:"required"`
- [x] `UpdateAreaControllerRequest.Location` : `json:"location,omitempty"` -> `validate:"omitempty"`
- [x] `UpdateAreaControllerRequest.Properties` : `json:"properties,omitempty"` -> `validate:"omitempty"`
- [x] `CreateDeviceTemplateRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `CreateDeviceTemplateRequest.Manufacturer` : `json:"manufacturer,omitempty"` -> `validate:"omitempty"`
- [x] `CreateDeviceTemplateRequest.Description` : `json:"description,omitempty"` -> `validate:"omitempty"`
- [x] `CreateDeviceTemplateRequest.Category` : `binding:"required"` -> `validate:"required"`
- [x] `CreateDeviceTemplateRequest.Commands` : `binding:"required"` -> `validate:"required"`
- [x] `CreateDeviceTemplateRequest.Values` : `json:"values,omitempty"` -> `validate:"omitempty,dive"`
- [x] `UpdateDeviceTemplateRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `UpdateDeviceTemplateRequest.Manufacturer` : `json:"manufacturer,omitempty"` -> `validate:"omitempty"`
- [x] `UpdateDeviceTemplateRequest.Description` : `json:"description,omitempty"` -> `validate:"omitempty"`
- [x] `UpdateDeviceTemplateRequest.Category` : `binding:"required"` -> `validate:"required"`
- [x] `UpdateDeviceTemplateRequest.Commands` : `binding:"required"` -> `validate:"required"`
- [x] `UpdateDeviceTemplateRequest.Values` : `json:"values,omitempty"` -> `validate:"omitempty,dive"`
- [x] `internal/app/dto/monitor_dto.go`
- [x] `ListSensorDataRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListSensorDataRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListSensorDataRequest.DeviceID` : `form:"device_id"` -> `query:"device_id"`
- [x] `ListSensorDataRequest.SensorType` : `form:"sensor_type"` -> `query:"sensor_type"`
- [x] `ListSensorDataRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListSensorDataRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListSensorDataRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListDeviceCommandLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListDeviceCommandLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListDeviceCommandLogRequest.DeviceID` : `form:"device_id"` -> `query:"device_id"`
- [x] `ListDeviceCommandLogRequest.ReceivedSuccess` : `form:"received_success"` -> `query:"received_success"`
- [x] `ListDeviceCommandLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListDeviceCommandLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListDeviceCommandLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListPlanExecutionLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListPlanExecutionLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListPlanExecutionLogRequest.PlanID` : `form:"plan_id"` -> `query:"plan_id"`
- [x] `ListPlanExecutionLogRequest.Status` : `form:"status"` -> `query:"status"`
- [x] `ListPlanExecutionLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListPlanExecutionLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListPlanExecutionLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListTaskExecutionLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListTaskExecutionLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListTaskExecutionLogRequest.PlanExecutionLogID` : `form:"plan_execution_log_id"` -> `query:"plan_execution_log_id"`
- [x] `ListTaskExecutionLogRequest.TaskID` : `form:"task_id"` -> `query:"task_id"`
- [x] `ListTaskExecutionLogRequest.Status` : `form:"status"` -> `query:"status"`
- [x] `ListTaskExecutionLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListTaskExecutionLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListTaskExecutionLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListPendingCollectionRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListPendingCollectionRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListPendingCollectionRequest.DeviceID` : `form:"device_id"` -> `query:"device_id"`
- [x] `ListPendingCollectionRequest.Status` : `form:"status"` -> `query:"status"`
- [x] `ListPendingCollectionRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListPendingCollectionRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListPendingCollectionRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListUserActionLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListUserActionLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListUserActionLogRequest.UserID` : `form:"user_id"` -> `query:"user_id"`
- [x] `ListUserActionLogRequest.Username` : `form:"username"` -> `query:"username"`
- [x] `ListUserActionLogRequest.ActionType` : `form:"action_type"` -> `query:"action_type"`
- [x] `ListUserActionLogRequest.Status` : `form:"status"` -> `query:"status"`
- [x] `ListUserActionLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListUserActionLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListUserActionLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListRawMaterialPurchaseRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListRawMaterialPurchaseRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListRawMaterialPurchaseRequest.RawMaterialID` : `form:"raw_material_id"` -> `query:"raw_material_id"`
- [x] `ListRawMaterialPurchaseRequest.Supplier` : `form:"supplier"` -> `query:"supplier"`
- [x] `ListRawMaterialPurchaseRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListRawMaterialPurchaseRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListRawMaterialPurchaseRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListRawMaterialStockLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListRawMaterialStockLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListRawMaterialStockLogRequest.RawMaterialID` : `form:"raw_material_id"` -> `query:"raw_material_id"`
- [x] `ListRawMaterialStockLogRequest.SourceType` : `form:"source_type"` -> `query:"source_type"`
- [x] `ListRawMaterialStockLogRequest.SourceID` : `form:"source_id"` -> `query:"source_id"`
- [x] `ListRawMaterialStockLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListRawMaterialStockLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListRawMaterialStockLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListFeedUsageRecordRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListFeedUsageRecordRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListFeedUsageRecordRequest.PenID` : `form:"pen_id"` -> `query:"pen_id"`
- [x] `ListFeedUsageRecordRequest.FeedFormulaID` : `form:"feed_formula_id"` -> `query:"feed_formula_id"`
- [x] `ListFeedUsageRecordRequest.OperatorID` : `form:"operator_id"` -> `query:"operator_id"`
- [x] `ListFeedUsageRecordRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListFeedUsageRecordRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListFeedUsageRecordRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListMedicationLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListMedicationLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListMedicationLogRequest.PigBatchID` : `form:"pig_batch_id"` -> `query:"pig_batch_id"`
- [x] `ListMedicationLogRequest.MedicationID` : `form:"medication_id"` -> `query:"medication_id"`
- [x] `ListMedicationLogRequest.Reason` : `form:"reason"` -> `query:"reason"`
- [x] `ListMedicationLogRequest.OperatorID` : `form:"operator_id"` -> `query:"operator_id"`
- [x] `ListMedicationLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListMedicationLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListMedicationLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListPigBatchLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListPigBatchLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListPigBatchLogRequest.PigBatchID` : `form:"pig_batch_id"` -> `query:"pig_batch_id"`
- [x] `ListPigBatchLogRequest.ChangeType` : `form:"change_type"` -> `query:"change_type"`
- [x] `ListPigBatchLogRequest.OperatorID` : `form:"operator_id"` -> `query:"operator_id"`
- [x] `ListPigBatchLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListPigBatchLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListPigBatchLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListWeighingBatchRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListWeighingBatchRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListWeighingBatchRequest.PigBatchID` : `form:"pig_batch_id"` -> `query:"pig_batch_id"`
- [x] `ListWeighingBatchRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListWeighingBatchRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListWeighingBatchRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListWeighingRecordRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListWeighingRecordRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListWeighingRecordRequest.WeighingBatchID` : `form:"weighing_batch_id"` -> `query:"weighing_batch_id"`
- [x] `ListWeighingRecordRequest.PenID` : `form:"pen_id"` -> `query:"pen_id"`
- [x] `ListWeighingRecordRequest.OperatorID` : `form:"operator_id"` -> `query:"operator_id"`
- [x] `ListWeighingRecordRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListWeighingRecordRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListWeighingRecordRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListPigTransferLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListPigTransferLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListPigTransferLogRequest.PigBatchID` : `form:"pig_batch_id"` -> `query:"pig_batch_id"`
- [x] `ListPigTransferLogRequest.PenID` : `form:"pen_id"` -> `query:"pen_id"`
- [x] `ListPigTransferLogRequest.TransferType` : `form:"transfer_type"` -> `query:"transfer_type"`
- [x] `ListPigTransferLogRequest.OperatorID` : `form:"operator_id"` -> `query:"operator_id"`
- [x] `ListPigTransferLogRequest.CorrelationID` : `form:"correlation_id"` -> `query:"correlation_id"`
- [x] `ListPigTransferLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListPigTransferLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListPigTransferLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListPigSickLogRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListPigSickLogRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListPigSickLogRequest.PigBatchID` : `form:"pig_batch_id"` -> `query:"pig_batch_id"`
- [x] `ListPigSickLogRequest.PenID` : `form:"pen_id"` -> `query:"pen_id"`
- [x] `ListPigSickLogRequest.Reason` : `form:"reason"` -> `query:"reason"`
- [x] `ListPigSickLogRequest.TreatmentLocation` : `form:"treatment_location"` -> `query:"treatment_location"`
- [x] `ListPigSickLogRequest.OperatorID` : `form:"operator_id"` -> `query:"operator_id"`
- [x] `ListPigSickLogRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListPigSickLogRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListPigSickLogRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListPigPurchaseRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListPigPurchaseRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListPigPurchaseRequest.PigBatchID` : `form:"pig_batch_id"` -> `query:"pig_batch_id"`
- [x] `ListPigPurchaseRequest.Supplier` : `form:"supplier"` -> `query:"supplier"`
- [x] `ListPigPurchaseRequest.OperatorID` : `form:"operator_id"` -> `query:"operator_id"`
- [x] `ListPigPurchaseRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListPigPurchaseRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListPigPurchaseRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `ListPigSaleRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListPigSaleRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListPigSaleRequest.PigBatchID` : `form:"pig_batch_id"` -> `query:"pig_batch_id"`
- [x] `ListPigSaleRequest.Buyer` : `form:"buyer"` -> `query:"buyer"`
- [x] `ListPigSaleRequest.OperatorID` : `form:"operator_id"` -> `query:"operator_id"`
- [x] `ListPigSaleRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListPigSaleRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListPigSaleRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `internal/app/dto/pig_farm_dto.go`
- [x] `CreatePigHouseRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `UpdatePigHouseRequest.Name` : `binding:"required"` -> `validate:"required"`
- [x] `CreatePenRequest.PenNumber` : `binding:"required"` -> `validate:"required"`
- [x] `CreatePenRequest.HouseID` : `binding:"required"` -> `validate:"required"`
- [x] `CreatePenRequest.Capacity` : `binding:"required"` -> `validate:"required"`
- [x] `UpdatePenRequest.PenNumber` : `binding:"required"` -> `validate:"required"`
- [x] `UpdatePenRequest.HouseID` : `binding:"required"` -> `validate:"required"`
- [x] `UpdatePenRequest.Capacity` : `binding:"required"` -> `validate:"required"`
- [x] `UpdatePenRequest.Status` : `binding:"required,oneof=空闲 使用中 病猪栏 康复栏 清洗消毒 维修中"` -> `validate:"required,oneof=空闲 使用中 病猪栏 康复栏 清洗消毒 维修中"`
- [x] `UpdatePenStatusRequest.Status` : `binding:"required,oneof=空闲 使用中 病猪栏 康复栏 清洗消毒 维修中"` -> `validate:"required,oneof=空闲 使用中 病猪栏 康复栏 清洗消毒 维修中"`
- [x] `internal/app/dto/pig_batch_dto.go`
- [x] `PigBatchCreateDTO.BatchNumber` : `binding:"required"` -> `validate:"required"`
- [x] `PigBatchCreateDTO.OriginType` : `binding:"required"` -> `validate:"required"`
- [x] `PigBatchCreateDTO.StartDate` : `binding:"required"` -> `validate:"required"`
- [x] `PigBatchCreateDTO.InitialCount` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `PigBatchCreateDTO.Status` : `binding:"required"` -> `validate:"required"`
- [x] `PigBatchQueryDTO.IsActive` : `form:"is_active"` -> `query:"is_active"`
- [x] `AssignEmptyPensToBatchRequest.PenIDs` : `binding:"required,min=1"` -> `validate:"required,min=1,dive"`
- [x] `ReclassifyPenToNewBatchRequest.ToBatchID` : `binding:"required"` -> `validate:"required"`
- [x] `ReclassifyPenToNewBatchRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `RemoveEmptyPenFromBatchRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `MovePigsIntoPenRequest.ToPenID` : `binding:"required"` -> `validate:"required"`
- [x] `MovePigsIntoPenRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `SellPigsRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `SellPigsRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `SellPigsRequest.UnitPrice` : `binding:"required,min=0"` -> `validate:"required,min=0"`
- [x] `SellPigsRequest.TotalPrice` : `binding:"required,min=0"` -> `validate:"required,min=0"`
- [x] `SellPigsRequest.TraderName` : `binding:"required"` -> `validate:"required"`
- [x] `SellPigsRequest.TradeDate` : `binding:"required"` -> `validate:"required"`
- [x] `BuyPigsRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `BuyPigsRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `BuyPigsRequest.UnitPrice` : `binding:"required,min=0"` -> `validate:"required,min=0"`
- [x] `BuyPigsRequest.TotalPrice` : `binding:"required,min=0"` -> `validate:"required,min=0"`
- [x] `BuyPigsRequest.TraderName` : `binding:"required"` -> `validate:"required"`
- [x] `BuyPigsRequest.TradeDate` : `binding:"required"` -> `validate:"required"`
- [x] `TransferPigsAcrossBatchesRequest.DestBatchID` : `binding:"required"` -> `validate:"required"`
- [x] `TransferPigsAcrossBatchesRequest.FromPenID` : `binding:"required"` -> `validate:"required"`
- [x] `TransferPigsAcrossBatchesRequest.ToPenID` : `binding:"required"` -> `validate:"required"`
- [x] `TransferPigsAcrossBatchesRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `TransferPigsWithinBatchRequest.FromPenID` : `binding:"required"` -> `validate:"required"`
- [x] `TransferPigsWithinBatchRequest.ToPenID` : `binding:"required"` -> `validate:"required"`
- [x] `TransferPigsWithinBatchRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `RecordSickPigsRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigsRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `RecordSickPigsRequest.TreatmentLocation` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigsRequest.HappenedAt` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigRecoveryRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigRecoveryRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `RecordSickPigRecoveryRequest.TreatmentLocation` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigRecoveryRequest.HappenedAt` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigDeathRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigDeathRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `RecordSickPigDeathRequest.TreatmentLocation` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigDeathRequest.HappenedAt` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigCullRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigCullRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `RecordSickPigCullRequest.TreatmentLocation` : `binding:"required"` -> `validate:"required"`
- [x] `RecordSickPigCullRequest.HappenedAt` : `binding:"required"` -> `validate:"required"`
- [x] `RecordDeathRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `RecordDeathRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `RecordDeathRequest.HappenedAt` : `binding:"required"` -> `validate:"required"`
- [x] `RecordCullRequest.PenID` : `binding:"required"` -> `validate:"required"`
- [x] `RecordCullRequest.Quantity` : `binding:"required,min=1"` -> `validate:"required,min=1"`
- [x] `RecordCullRequest.HappenedAt` : `binding:"required"` -> `validate:"required"`
- [x] `internal/app/dto/notification_dto.go`
- [x] `SendTestNotificationRequest.Type` : `binding:"required"` -> `validate:"required"`
- [x] `ListNotificationRequest.Page` : `form:"page,default=1"` -> `query:"page"`
- [x] `ListNotificationRequest.PageSize` : `form:"pageSize,default=10"` -> `query:"pageSize"`
- [x] `ListNotificationRequest.UserID` : `form:"user_id"` -> `query:"user_id"`
- [x] `ListNotificationRequest.NotifierType` : `form:"notifier_type"` -> `query:"notifier_type"`
- [x] `ListNotificationRequest.Status` : `form:"status"` -> `query:"status"`
- [x] `ListNotificationRequest.Level` : `form:"level"` -> `query:"level"`
- [x] `ListNotificationRequest.StartTime` : `form:"start_time"` -> `query:"start_time"`
- [x] `ListNotificationRequest.EndTime` : `form:"end_time"` -> `query:"end_time"`
- [x] `ListNotificationRequest.OrderBy` : `form:"order_by"` -> `query:"order_by"`
- [x] `internal/app/dto/plan_converter.go` (跳过,非 DTO 结构体)
- [x] `internal/app/dto/device_converter.go` (跳过,非 DTO 结构体)
- [x] `internal/app/dto/monitor_converter.go` (跳过,非 DTO 结构体)
- [x] `internal/app/dto/notification_converter.go` (跳过,非 DTO 结构体)
- [x] **6. 核心 API 层 (`internal/app/api`)**
- [x] ** `router.go` **
- [x] 将所有 `router.GET` , `router.POST` 等 Gin 路由注册方法替换为 Echo 的 `e.GET` , `e.POST` 等方法。
- [x] 将 Swagger 路由 `router.GET("/swagger/*", ginSwagger.WrapHandler(swaggerFiles.Handler))` 替换为
`e.GET("/swagger/*", echoSwagger.WrapHandler)` 。
- [x] 将 pprof 路由的 `gin.WrapH` 和 `gin.WrapF` 调用替换为 `echo.WrapHandler` 和 `echo.WrapFunc` 。
- [x] ** `api.go` **
- [x] 将 `engine *gin.Engine` 替换为 `engine *echo.Echo` 。
- [x] 更新 `NewAPI` 函数:
- [x] 将 `gin.SetMode(cfg.Mode)` 替换为 `e.Debug = (cfg.Mode == "debug")` 。
- [x] 将 `gin.New()` 替换为 `echo.New()` 。
- [x] 将 `engine.Use(middleware.Recover())` 替换为 `e.Use(middleware.Recover())` 。
- [x] **7. 依赖管理**
- [x] 在 `go.mod` 中移除 `github.com/gin-gonic/gin` 。
- [x] 在 `go.mod` 中移除 `github.com/swaggo/gin-swagger` 。
- [x] 在 `go.mod` 中添加 `github.com/labstack/echo/v4` 。
- [x] 在 `go.mod` 中添加 `github.com/swaggo/echo-swagger` 。
- [x] 执行 `go mod tidy` 清理依赖项。
- [x] **8. 验证**
- [x] 运行 `go build ./...` 确保项目能够成功编译。
- [x] 启动服务,手动测试所有 API 端点,验证功能是否与迁移前一致。
- [x] 访问 `/swagger/index.html` ,确认 Swagger UI 是否正常工作。
- [x] (可选) 访问 `/debug/pprof/` ,确认 pprof 路由是否正常。