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