From 5b064b40151bc752a33e95cc5ada936f9d227de4 Mon Sep 17 00:00:00 2001 From: huang <1724659546@qq.com> Date: Thu, 30 Oct 2025 17:34:25 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4openspace=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../refactor-migrate-gin-to-echo/design.md | 15 +- .../refactor-migrate-gin-to-echo/tasks.md | 282 +++++++++++++++++- 2 files changed, 291 insertions(+), 6 deletions(-) diff --git a/openspec/changes/refactor-migrate-gin-to-echo/design.md b/openspec/changes/refactor-migrate-gin-to-echo/design.md index 374a91e..127bc7c 100644 --- a/openspec/changes/refactor-migrate-gin-to-echo/design.md +++ b/openspec/changes/refactor-migrate-gin-to-echo/design.md @@ -60,9 +60,18 @@ - **Rationale**: 这种重构使得审计逻辑更加清晰和内聚,避免了在中间件中进行复杂的响应体捕获。 7. **DTO 注解 (Annotations)**: - - **From**: `json:"field" binding:"required"` - - **To**: `json:"field" validate:"required"` - - **Rationale**: Gin 使用 `binding` 标签进行请求参数绑定和验证。Echo 框架通常结合 `go-playground/validator` 库进行验证,其对应的标签为 `validate`。因此,所有 DTO 结构体中的 `binding` 标签需要替换为 `validate`。`json` 标签保持不变。 + - **From**: Gin 相关的注解,主要包括 `binding:"..."` 和 `form:"..."`。 + - **To**: Echo 兼容的注解,主要包括 `validate:"..."` 和 `query:"..."`。 + - **Rationale**: Gin 使用 `binding` 标签进行请求参数绑定和验证,`form` 标签用于表单或查询参数绑定。Echo 框架通常结合 `go-playground/validator` 库进行验证,其对应的标签为 `validate`。对于查询参数,Echo 默认使用 `query` 标签。 + - **通用修改规则**: + - `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` 等)。 ## Risks / Trade-offs diff --git a/openspec/changes/refactor-migrate-gin-to-echo/tasks.md b/openspec/changes/refactor-migrate-gin-to-echo/tasks.md index 80cebf2..6d1db09 100644 --- a/openspec/changes/refactor-migrate-gin-to-echo/tasks.md +++ b/openspec/changes/refactor-migrate-gin-to-echo/tasks.md @@ -11,7 +11,7 @@ - [x] 将 `*gin.Context` 参数全部替换为 `echo.Context`。 - [x] 修改响应函数,使其返回 `error`。 - [x] **新增 `SendErrorWithStatus` 函数**,用于在中间件等场景下发送带有特定HTTP状态码的错误响应。 - - [x] **重构 `setAuditDetails` 函数**,使其成为统一设置所有审计信息(包括操作状态和结果详情)的唯一入口。 + - [x] **重构 `setAuditDetails` 函数**,使其成为统一设置所有审计信息(包括操作状态和失败详情)的唯一入口。 - [x] 更新 `SendSuccessWithAudit` 和 `SendErrorWithAudit` 以调用重构后的 `setAuditDetails`。 - [x] **`internal/app/controller/auth_utils.go`** - [x] 将 `*gin.Context` 参数全部替换为 `echo.Context`。 @@ -49,8 +49,284 @@ - [x] `internal/app/controller/user/user_controller.go` - [ ] **5. DTO 结构体注解** - - [ ] 检查并修改 `internal/app/dto` 包下所有结构体的注解。将所有 Gin 相关的注解(例如 `binding:"..."`)替换为 Echo - 兼容的注解(例如 `validate:"..."`)。`json:"..."` 标签通常保持不变。 + - [ ] **通用修改规则**: + - [ ] `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`**