diff --git a/docs/docs.go b/docs/docs.go index 23b6121..32dfb60 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1663,7 +1663,7 @@ const docTemplate = `{ "parameters": [ { "type": "string", - "description": "按名称模糊查询", + "description": "按营养名称模糊查询", "name": "name", "in": "query" }, @@ -1684,6 +1684,12 @@ const docTemplate = `{ "description": "每页数量", "name": "page_size", "in": "query" + }, + { + "type": "string", + "description": "按原料名称模糊查询", + "name": "raw_material_name", + "in": "query" } ], "responses": { @@ -2665,10 +2671,16 @@ const docTemplate = `{ "parameters": [ { "type": "string", - "description": "按名称模糊查询", + "description": "按原料名称模糊查询", "name": "name", "in": "query" }, + { + "type": "string", + "description": "按营养名称模糊查询", + "name": "nutrient_name", + "in": "query" + }, { "type": "string", "description": "排序字段,例如 \"id DESC\"", @@ -3074,7 +3086,6 @@ const docTemplate = `{ }, { "enum": [ - 7, -1, 0, 1, @@ -3084,12 +3095,12 @@ const docTemplate = `{ 5, -1, 5, - 6 + 6, + 7 ], "type": "integer", "format": "int32", "x-enum-varnames": [ - "_numLevels", "DebugLevel", "InfoLevel", "WarnLevel", @@ -3099,7 +3110,8 @@ const docTemplate = `{ "FatalLevel", "_minLevel", "_maxLevel", - "InvalidLevel" + "InvalidLevel", + "_numLevels" ], "name": "level", "in": "query" @@ -9646,7 +9658,6 @@ const docTemplate = `{ "type": "integer", "format": "int32", "enum": [ - 7, -1, 0, 1, @@ -9656,10 +9667,10 @@ const docTemplate = `{ 5, -1, 5, - 6 + 6, + 7 ], "x-enum-varnames": [ - "_numLevels", "DebugLevel", "InfoLevel", "WarnLevel", @@ -9669,7 +9680,8 @@ const docTemplate = `{ "FatalLevel", "_minLevel", "_maxLevel", - "InvalidLevel" + "InvalidLevel", + "_numLevels" ] } }, diff --git a/docs/swagger.json b/docs/swagger.json index cb6b09e..bf084fd 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1655,7 +1655,7 @@ "parameters": [ { "type": "string", - "description": "按名称模糊查询", + "description": "按营养名称模糊查询", "name": "name", "in": "query" }, @@ -1676,6 +1676,12 @@ "description": "每页数量", "name": "page_size", "in": "query" + }, + { + "type": "string", + "description": "按原料名称模糊查询", + "name": "raw_material_name", + "in": "query" } ], "responses": { @@ -2657,10 +2663,16 @@ "parameters": [ { "type": "string", - "description": "按名称模糊查询", + "description": "按原料名称模糊查询", "name": "name", "in": "query" }, + { + "type": "string", + "description": "按营养名称模糊查询", + "name": "nutrient_name", + "in": "query" + }, { "type": "string", "description": "排序字段,例如 \"id DESC\"", @@ -3066,7 +3078,6 @@ }, { "enum": [ - 7, -1, 0, 1, @@ -3076,12 +3087,12 @@ 5, -1, 5, - 6 + 6, + 7 ], "type": "integer", "format": "int32", "x-enum-varnames": [ - "_numLevels", "DebugLevel", "InfoLevel", "WarnLevel", @@ -3091,7 +3102,8 @@ "FatalLevel", "_minLevel", "_maxLevel", - "InvalidLevel" + "InvalidLevel", + "_numLevels" ], "name": "level", "in": "query" @@ -9638,7 +9650,6 @@ "type": "integer", "format": "int32", "enum": [ - 7, -1, 0, 1, @@ -9648,10 +9659,10 @@ 5, -1, 5, - 6 + 6, + 7 ], "x-enum-varnames": [ - "_numLevels", "DebugLevel", "InfoLevel", "WarnLevel", @@ -9661,7 +9672,8 @@ "FatalLevel", "_minLevel", "_maxLevel", - "InvalidLevel" + "InvalidLevel", + "_numLevels" ] } }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 7cd095d..e5e8ed7 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -2517,7 +2517,6 @@ definitions: - PlanTypeFilterSystem zapcore.Level: enum: - - 7 - -1 - 0 - 1 @@ -2528,10 +2527,10 @@ definitions: - -1 - 5 - 6 + - 7 format: int32 type: integer x-enum-varnames: - - _numLevels - DebugLevel - InfoLevel - WarnLevel @@ -2542,6 +2541,7 @@ definitions: - _minLevel - _maxLevel - InvalidLevel + - _numLevels info: contact: email: divano@example.com @@ -3564,7 +3564,7 @@ paths: get: description: 获取所有营养种类的列表,支持分页和过滤。 parameters: - - description: 按名称模糊查询 + - description: 按营养名称模糊查询 in: query name: name type: string @@ -3580,6 +3580,10 @@ paths: in: query name: page_size type: integer + - description: 按原料名称模糊查询 + in: query + name: raw_material_name + type: string produces: - application/json responses: @@ -4152,10 +4156,14 @@ paths: get: description: 获取所有原料的列表,支持分页和过滤。 parameters: - - description: 按名称模糊查询 + - description: 按原料名称模糊查询 in: query name: name type: string + - description: 按营养名称模糊查询 + in: query + name: nutrient_name + type: string - description: 排序字段,例如 "id DESC" in: query name: order_by @@ -4390,7 +4398,6 @@ paths: name: end_time type: string - enum: - - 7 - -1 - 0 - 1 @@ -4401,12 +4408,12 @@ paths: - -1 - 5 - 6 + - 7 format: int32 in: query name: level type: integer x-enum-varnames: - - _numLevels - DebugLevel - InfoLevel - WarnLevel @@ -4417,6 +4424,7 @@ paths: - _minLevel - _maxLevel - InvalidLevel + - _numLevels - enum: - 邮件 - 企业微信 diff --git a/internal/app/dto/feed_dto.go b/internal/app/dto/feed_dto.go index 41bc4a1..db30316 100644 --- a/internal/app/dto/feed_dto.go +++ b/internal/app/dto/feed_dto.go @@ -39,10 +39,11 @@ type NutrientResponse struct { // ListNutrientRequest 定义了获取营养种类列表的请求参数 type ListNutrientRequest struct { - Page int `json:"page" query:"page"` // 页码 - PageSize int `json:"page_size" query:"page_size"` // 每页数量 - Name *string `json:"name" query:"name"` // 按名称模糊查询 - OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC" + Page int `json:"page" query:"page"` // 页码 + PageSize int `json:"page_size" query:"page_size"` // 每页数量 + Name *string `json:"name" query:"name"` // 按营养名称模糊查询 + RawMaterialName *string `json:"raw_material_name" query:"raw_material_name"` // 按原料名称模糊查询 + OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC" } // ListNutrientResponse 是获取营养种类列表的响应结构 @@ -89,10 +90,11 @@ type RawMaterialResponse struct { // ListRawMaterialRequest 定义了获取原料列表的请求参数 type ListRawMaterialRequest struct { - Page int `json:"page" query:"page"` // 页码 - PageSize int `json:"page_size" query:"page_size"` // 每页数量 - Name *string `json:"name" query:"name"` // 按名称模糊查询 - OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC" + Page int `json:"page" query:"page"` // 页码 + PageSize int `json:"page_size" query:"page_size"` // 每页数量 + Name *string `json:"name" query:"name"` // 按原料名称模糊查询 + NutrientName *string `json:"nutrient_name" query:"nutrient_name"` // 按营养名称模糊查询 + OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC" } // ListRawMaterialResponse 是获取原料列表的响应结构 diff --git a/internal/app/service/feed_management_service.go b/internal/app/service/feed_management_service.go index 2c7fabc..f00dc46 100644 --- a/internal/app/service/feed_management_service.go +++ b/internal/app/service/feed_management_service.go @@ -143,7 +143,12 @@ func (s *feedManagementServiceImpl) GetNutrient(ctx context.Context, id uint32) func (s *feedManagementServiceImpl) ListNutrients(ctx context.Context, req *dto.ListNutrientRequest) (*dto.ListNutrientResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListNutrients") - nutrients, total, err := s.recipeSvc.ListNutrients(serviceCtx, req.Page, req.PageSize) + opts := repository.NutrientListOptions{ + Name: req.Name, + RawMaterialName: req.RawMaterialName, + OrderBy: req.OrderBy, + } + nutrients, total, err := s.recipeSvc.ListNutrients(serviceCtx, opts, req.Page, req.PageSize) if err != nil { return nil, fmt.Errorf("获取营养种类列表失败: %w", err) } @@ -218,7 +223,12 @@ func (s *feedManagementServiceImpl) GetRawMaterial(ctx context.Context, id uint3 func (s *feedManagementServiceImpl) ListRawMaterials(ctx context.Context, req *dto.ListRawMaterialRequest) (*dto.ListRawMaterialResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListRawMaterials") - rawMaterials, total, err := s.recipeSvc.ListRawMaterials(serviceCtx, req.Page, req.PageSize) + opts := repository.RawMaterialListOptions{ + Name: req.Name, + NutrientName: req.NutrientName, + OrderBy: req.OrderBy, + } + rawMaterials, total, err := s.recipeSvc.ListRawMaterials(serviceCtx, opts, req.Page, req.PageSize) if err != nil { return nil, fmt.Errorf("获取原料列表失败: %w", err) } diff --git a/internal/domain/recipe/recipe_service.go b/internal/domain/recipe/recipe_service.go index c7d6483..ff0b66f 100644 --- a/internal/domain/recipe/recipe_service.go +++ b/internal/domain/recipe/recipe_service.go @@ -32,14 +32,14 @@ type Service interface { UpdateNutrient(ctx context.Context, id uint32, name, description string) (*models.Nutrient, error) DeleteNutrient(ctx context.Context, id uint32) error GetNutrient(ctx context.Context, id uint32) (*models.Nutrient, error) - ListNutrients(ctx context.Context, page, pageSize int) ([]models.Nutrient, int64, error) + ListNutrients(ctx context.Context, opts repository.NutrientListOptions, page, pageSize int) ([]models.Nutrient, int64, error) // 原料相关接口 CreateRawMaterial(ctx context.Context, name, description string) (*models.RawMaterial, error) UpdateRawMaterial(ctx context.Context, id uint32, name, description string) (*models.RawMaterial, error) DeleteRawMaterial(ctx context.Context, id uint32) error GetRawMaterial(ctx context.Context, id uint32) (*models.RawMaterial, error) - ListRawMaterials(ctx context.Context, page, pageSize int) ([]models.RawMaterial, int64, error) + ListRawMaterials(ctx context.Context, opts repository.RawMaterialListOptions, page, pageSize int) ([]models.RawMaterial, int64, error) // 猪品种相关接口 CreatePigBreed(ctx context.Context, breed *models.PigBreed) error @@ -175,10 +175,10 @@ func (s *recipeServiceImpl) GetNutrient(ctx context.Context, id uint32) (*models } // ListNutrients 实现了列出营养种类的逻辑 -func (s *recipeServiceImpl) ListNutrients(ctx context.Context, page, pageSize int) ([]models.Nutrient, int64, error) { +func (s *recipeServiceImpl) ListNutrients(ctx context.Context, opts repository.NutrientListOptions, page, pageSize int) ([]models.Nutrient, int64, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListNutrients") - nutrients, total, err := s.nutrientRepo.ListNutrients(serviceCtx, page, pageSize) + nutrients, total, err := s.nutrientRepo.ListNutrients(serviceCtx, opts, page, pageSize) if err != nil { return nil, 0, fmt.Errorf("获取营养种类列表失败: %w", err) } @@ -279,10 +279,10 @@ func (s *recipeServiceImpl) GetRawMaterial(ctx context.Context, id uint32) (*mod } // ListRawMaterials 实现了列出原料的逻辑 -func (s *recipeServiceImpl) ListRawMaterials(ctx context.Context, page, pageSize int) ([]models.RawMaterial, int64, error) { +func (s *recipeServiceImpl) ListRawMaterials(ctx context.Context, opts repository.RawMaterialListOptions, page, pageSize int) ([]models.RawMaterial, int64, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListRawMaterials") - rawMaterials, total, err := s.rawMaterialRepo.ListRawMaterials(serviceCtx, page, pageSize) + rawMaterials, total, err := s.rawMaterialRepo.ListRawMaterials(serviceCtx, opts, page, pageSize) if err != nil { return nil, 0, fmt.Errorf("获取原料列表失败: %w", err) } diff --git a/internal/infra/repository/nutrient_repository.go b/internal/infra/repository/nutrient_repository.go index f2e89c3..57f6eac 100644 --- a/internal/infra/repository/nutrient_repository.go +++ b/internal/infra/repository/nutrient_repository.go @@ -11,12 +11,19 @@ import ( "gorm.io/gorm" ) +// NutrientListOptions 定义了查询营养种类列表时的筛选条件 +type NutrientListOptions struct { + Name *string + RawMaterialName *string + OrderBy string +} + // NutrientRepository 定义了与营养种类相关的数据库操作接口 type NutrientRepository interface { CreateNutrient(ctx context.Context, nutrient *models.Nutrient) error GetNutrientByID(ctx context.Context, id uint32) (*models.Nutrient, error) GetNutrientByName(ctx context.Context, name string) (*models.Nutrient, error) - ListNutrients(ctx context.Context, page, pageSize int) ([]models.Nutrient, int64, error) + ListNutrients(ctx context.Context, opts NutrientListOptions, page, pageSize int) ([]models.Nutrient, int64, error) UpdateNutrient(ctx context.Context, nutrient *models.Nutrient) error DeleteNutrient(ctx context.Context, id uint32) error } @@ -61,19 +68,36 @@ func (r *gormNutrientRepository) GetNutrientByName(ctx context.Context, name str } // ListNutrients 列出所有营养种类(分页),并预加载关联的原料信息 -func (r *gormNutrientRepository) ListNutrients(ctx context.Context, page, pageSize int) ([]models.Nutrient, int64, error) { +func (r *gormNutrientRepository) ListNutrients(ctx context.Context, opts NutrientListOptions, page, pageSize int) ([]models.Nutrient, int64, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "ListNutrients") var nutrients []models.Nutrient var total int64 db := r.db.WithContext(repoCtx).Model(&models.Nutrient{}) + // 应用筛选条件 + if opts.Name != nil && *opts.Name != "" { + db = db.Where("name LIKE ?", "%"+*opts.Name+"%") + } + + // 如果传入了原料名称,则使用子查询进行筛选 + if opts.RawMaterialName != nil && *opts.RawMaterialName != "" { + subQuery := r.db.Model(&models.RawMaterialNutrient{}). + Select("nutrient_id"). + Joins("JOIN raw_materials ON raw_materials.id = raw_material_nutrients.raw_material_id"). + Where("raw_materials.name LIKE ?", "%"+*opts.RawMaterialName+"%") + db = db.Where("id IN (?)", subQuery) + } + // 首先计算总数 if err := db.Count(&total).Error; err != nil { return nil, 0, err } - // 然后应用分页并获取数据 + // 然后应用排序、分页并获取数据 + if opts.OrderBy != "" { + db = db.Order(opts.OrderBy) + } offset := (page - 1) * pageSize if err := db.Preload("RawMaterialNutrients.RawMaterial").Offset(offset).Limit(pageSize).Find(&nutrients).Error; err != nil { return nil, 0, err diff --git a/internal/infra/repository/raw_material_repository.go b/internal/infra/repository/raw_material_repository.go index 3f40c43..efff010 100644 --- a/internal/infra/repository/raw_material_repository.go +++ b/internal/infra/repository/raw_material_repository.go @@ -11,12 +11,19 @@ import ( "gorm.io/gorm" ) +// RawMaterialListOptions 定义了查询原料列表时的筛选条件 +type RawMaterialListOptions struct { + Name *string + NutrientName *string + OrderBy string +} + // RawMaterialRepository 定义了与原料相关的数据库操作接口 type RawMaterialRepository interface { CreateRawMaterial(ctx context.Context, rawMaterial *models.RawMaterial) error GetRawMaterialByID(ctx context.Context, id uint32) (*models.RawMaterial, error) GetRawMaterialByName(ctx context.Context, name string) (*models.RawMaterial, error) - ListRawMaterials(ctx context.Context, page, pageSize int) ([]models.RawMaterial, int64, error) + ListRawMaterials(ctx context.Context, opts RawMaterialListOptions, page, pageSize int) ([]models.RawMaterial, int64, error) UpdateRawMaterial(ctx context.Context, rawMaterial *models.RawMaterial) error DeleteRawMaterial(ctx context.Context, id uint32) error @@ -64,20 +71,38 @@ func (r *gormRawMaterialRepository) GetRawMaterialByName(ctx context.Context, na return &rawMaterial, nil } -// ListRawMaterials 列出所有原料(分页),并预加载关联的营养素信息 -func (r *gormRawMaterialRepository) ListRawMaterials(ctx context.Context, page, pageSize int) ([]models.RawMaterial, int64, error) { +// ListRawMaterials 列出所有原料(分页),支持按名称和营养名称筛选 +func (r *gormRawMaterialRepository) ListRawMaterials(ctx context.Context, opts RawMaterialListOptions, page, pageSize int) ([]models.RawMaterial, int64, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "ListRawMaterials") var rawMaterials []models.RawMaterial var total int64 db := r.db.WithContext(repoCtx).Model(&models.RawMaterial{}) + // 应用筛选条件 + if opts.Name != nil && *opts.Name != "" { + db = db.Where("name LIKE ?", "%"+*opts.Name+"%") + } + + // 如果传入了营养名称,则使用子查询进行筛选 + if opts.NutrientName != nil && *opts.NutrientName != "" { + // 子查询:从 raw_material_nutrients 和 nutrients 表中找到所有包含该营养的 raw_material_id + subQuery := r.db.Model(&models.RawMaterialNutrient{}). + Select("raw_material_id"). + Joins("JOIN nutrients ON nutrients.id = raw_material_nutrients.nutrient_id"). + Where("nutrients.name LIKE ?", "%"+*opts.NutrientName+"%") + db = db.Where("id IN (?)", subQuery) + } + // 首先计算总数 if err := db.Count(&total).Error; err != nil { return nil, 0, err } - // 然后应用分页并获取数据 + // 然后应用排序、分页并获取数据 + if opts.OrderBy != "" { + db = db.Order(opts.OrderBy) + } offset := (page - 1) * pageSize if err := db.Preload("RawMaterialNutrients.Nutrient").Offset(offset).Limit(pageSize).Find(&rawMaterials).Error; err != nil { return nil, 0, err