package service import ( "context" "errors" "fmt" "git.huangwc.com/pig/pig-farm-controller/internal/app/dto" "git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe" "git.huangwc.com/pig/pig-farm-controller/internal/infra/logs" "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" "git.huangwc.com/pig/pig-farm-controller/internal/infra/repository" ) // 定义服务层特定的错误 var ( ErrNutrientNameConflict = errors.New("营养种类名称已存在") ErrNutrientNotFound = errors.New("营养种类不存在") ErrRawMaterialNameConflict = errors.New("原料名称已存在") ErrRawMaterialNotFound = errors.New("原料不存在") ErrPigBreedInUse = errors.New("猪品种正在被猪类型使用,无法删除") ErrPigBreedNotFound = errors.New("猪品种不存在") ErrPigAgeStageInUse = errors.New("猪年龄阶段正在被猪类型使用,无法删除") ErrPigAgeStageNotFound = errors.New("猪年龄阶段不存在") ErrPigTypeNotFound = errors.New("猪类型不存在") ) // FeedManagementService 定义了饲料管理的应用服务接口 type FeedManagementService interface { // 营养种类相关 CreateNutrient(ctx context.Context, req *dto.CreateNutrientRequest) (*dto.NutrientResponse, error) UpdateNutrient(ctx context.Context, id uint32, req *dto.UpdateNutrientRequest) (*dto.NutrientResponse, error) DeleteNutrient(ctx context.Context, id uint32) error GetNutrient(ctx context.Context, id uint32) (*dto.NutrientResponse, error) ListNutrients(ctx context.Context, req *dto.ListNutrientRequest) (*dto.ListNutrientResponse, error) // 原料相关 CreateRawMaterial(ctx context.Context, req *dto.CreateRawMaterialRequest) (*dto.RawMaterialResponse, error) UpdateRawMaterial(ctx context.Context, id uint32, req *dto.UpdateRawMaterialRequest) (*dto.RawMaterialResponse, error) DeleteRawMaterial(ctx context.Context, id uint32) error GetRawMaterial(ctx context.Context, id uint32) (*dto.RawMaterialResponse, error) ListRawMaterials(ctx context.Context, req *dto.ListRawMaterialRequest) (*dto.ListRawMaterialResponse, error) UpdateRawMaterialNutrients(ctx context.Context, id uint32, req *dto.UpdateRawMaterialNutrientsRequest) (*dto.RawMaterialResponse, error) // 新增 // 猪品种相关 CreatePigBreed(ctx context.Context, req *dto.CreatePigBreedRequest) (*dto.PigBreedResponse, error) UpdatePigBreed(ctx context.Context, id uint32, req *dto.UpdatePigBreedRequest) (*dto.PigBreedResponse, error) DeletePigBreed(ctx context.Context, id uint32) error GetPigBreed(ctx context.Context, id uint32) (*dto.PigBreedResponse, error) ListPigBreeds(ctx context.Context, req *dto.ListPigBreedRequest) (*dto.ListPigBreedResponse, error) // 猪年龄阶段相关 CreatePigAgeStage(ctx context.Context, req *dto.CreatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) UpdatePigAgeStage(ctx context.Context, id uint32, req *dto.UpdatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) DeletePigAgeStage(ctx context.Context, id uint32) error GetPigAgeStage(ctx context.Context, id uint32) (*dto.PigAgeStageResponse, error) ListPigAgeStages(ctx context.Context, req *dto.ListPigAgeStageRequest) (*dto.ListPigAgeStageResponse, error) // 猪类型相关 CreatePigType(ctx context.Context, req *dto.CreatePigTypeRequest) (*dto.PigTypeResponse, error) UpdatePigType(ctx context.Context, id uint32, req *dto.UpdatePigTypeRequest) (*dto.PigTypeResponse, error) DeletePigType(ctx context.Context, id uint32) error GetPigType(ctx context.Context, id uint32) (*dto.PigTypeResponse, error) ListPigTypes(ctx context.Context, req *dto.ListPigTypeRequest) (*dto.ListPigTypeResponse, error) } // feedManagementServiceImpl 是 FeedManagementService 接口的实现 type feedManagementServiceImpl struct { ctx context.Context recipeSvc recipe.Service } // NewFeedManagementService 创建一个新的 FeedManagementService 实例 func NewFeedManagementService(ctx context.Context, recipeSvc recipe.Service) FeedManagementService { return &feedManagementServiceImpl{ ctx: ctx, recipeSvc: recipeSvc, } } // ===================================================================================================================== // 营养种类 (Nutrient) 实现 // ===================================================================================================================== // CreateNutrient 创建营养种类 func (s *feedManagementServiceImpl) CreateNutrient(ctx context.Context, req *dto.CreateNutrientRequest) (*dto.NutrientResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateNutrient") nutrient, err := s.recipeSvc.CreateNutrient(serviceCtx, req.Name, req.Description) if err != nil { if errors.Is(err, recipe.ErrNutrientNameConflict) { return nil, ErrNutrientNameConflict } return nil, fmt.Errorf("创建营养种类失败: %w", err) } return dto.ConvertNutrientToDTO(nutrient), nil } // UpdateNutrient 更新营养种类 func (s *feedManagementServiceImpl) UpdateNutrient(ctx context.Context, id uint32, req *dto.UpdateNutrientRequest) (*dto.NutrientResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateNutrient") nutrient, err := s.recipeSvc.UpdateNutrient(serviceCtx, id, req.Name, req.Description) if err != nil { if errors.Is(err, recipe.ErrNutrientNotFound) { return nil, ErrNutrientNotFound } if errors.Is(err, recipe.ErrNutrientNameConflict) { return nil, ErrNutrientNameConflict } return nil, fmt.Errorf("更新营养种类失败: %w", err) } return dto.ConvertNutrientToDTO(nutrient), nil } // DeleteNutrient 删除营养种类 func (s *feedManagementServiceImpl) DeleteNutrient(ctx context.Context, id uint32) error { serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteNutrient") err := s.recipeSvc.DeleteNutrient(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrNutrientNotFound) { return ErrNutrientNotFound } return fmt.Errorf("删除营养种类失败: %w", err) } return nil } // GetNutrient 获取单个营养种类 func (s *feedManagementServiceImpl) GetNutrient(ctx context.Context, id uint32) (*dto.NutrientResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetNutrient") nutrient, err := s.recipeSvc.GetNutrient(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrNutrientNotFound) { return nil, ErrNutrientNotFound } return nil, fmt.Errorf("获取营养种类失败: %w", err) } return dto.ConvertNutrientToDTO(nutrient), nil } // ListNutrients 列出营养种类 func (s *feedManagementServiceImpl) ListNutrients(ctx context.Context, req *dto.ListNutrientRequest) (*dto.ListNutrientResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListNutrients") 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) } return dto.ConvertNutrientListToDTO(nutrients, total, req.Page, req.PageSize), nil } // ===================================================================================================================== // 原料 (RawMaterial) 实现 // ===================================================================================================================== // CreateRawMaterial 创建原料 func (s *feedManagementServiceImpl) CreateRawMaterial(ctx context.Context, req *dto.CreateRawMaterialRequest) (*dto.RawMaterialResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateRawMaterial") rawMaterial, err := s.recipeSvc.CreateRawMaterial(serviceCtx, req.Name, req.Description) if err != nil { if errors.Is(err, recipe.ErrRawMaterialNameConflict) { return nil, ErrRawMaterialNameConflict } return nil, fmt.Errorf("创建原料失败: %w", err) } return dto.ConvertRawMaterialToDTO(rawMaterial), nil } // UpdateRawMaterial 更新原料 func (s *feedManagementServiceImpl) UpdateRawMaterial(ctx context.Context, id uint32, req *dto.UpdateRawMaterialRequest) (*dto.RawMaterialResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateRawMaterial") rawMaterial, err := s.recipeSvc.UpdateRawMaterial(serviceCtx, id, req.Name, req.Description) if err != nil { if errors.Is(err, recipe.ErrRawMaterialNotFound) { return nil, ErrRawMaterialNotFound } if errors.Is(err, recipe.ErrRawMaterialNameConflict) { return nil, ErrRawMaterialNameConflict } return nil, fmt.Errorf("更新原料失败: %w", err) } return dto.ConvertRawMaterialToDTO(rawMaterial), nil } // DeleteRawMaterial 删除原料 func (s *feedManagementServiceImpl) DeleteRawMaterial(ctx context.Context, id uint32) error { serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteRawMaterial") err := s.recipeSvc.DeleteRawMaterial(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrRawMaterialNotFound) { return ErrRawMaterialNotFound } return fmt.Errorf("删除原料失败: %w", err) } return nil } // GetRawMaterial 获取单个原料 func (s *feedManagementServiceImpl) GetRawMaterial(ctx context.Context, id uint32) (*dto.RawMaterialResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetRawMaterial") rawMaterial, err := s.recipeSvc.GetRawMaterial(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrRawMaterialNotFound) { return nil, ErrRawMaterialNotFound } return nil, fmt.Errorf("获取原料失败: %w", err) } return dto.ConvertRawMaterialToDTO(rawMaterial), nil } // ListRawMaterials 列出原料 func (s *feedManagementServiceImpl) ListRawMaterials(ctx context.Context, req *dto.ListRawMaterialRequest) (*dto.ListRawMaterialResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListRawMaterials") 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) } return dto.ConvertRawMaterialListToDTO(rawMaterials, total, req.Page, req.PageSize), nil } // UpdateRawMaterialNutrients 全量更新原料的营养成分 func (s *feedManagementServiceImpl) UpdateRawMaterialNutrients(ctx context.Context, id uint32, req *dto.UpdateRawMaterialNutrientsRequest) (*dto.RawMaterialResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateRawMaterialNutrients") // 1. 将 DTO 转换为领域模型 nutrients := make([]models.RawMaterialNutrient, len(req.Nutrients)) for i, item := range req.Nutrients { nutrients[i] = models.RawMaterialNutrient{ NutrientID: item.NutrientID, Value: item.Value, } } // 2. 调用领域服务执行更新命令 err := s.recipeSvc.UpdateRawMaterialNutrients(serviceCtx, id, nutrients) if err != nil { if errors.Is(err, recipe.ErrRawMaterialNotFound) { return nil, ErrRawMaterialNotFound } // 此处可以根据领域层可能返回的其他特定错误进行转换 return nil, fmt.Errorf("更新原料营养成分失败: %w", err) } // 3. 更新成功后,调用查询服务获取最新的原料信息 updatedRawMaterial, err := s.recipeSvc.GetRawMaterial(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrRawMaterialNotFound) { // 理论上不应该发生,因为刚更新成功 return nil, ErrRawMaterialNotFound } return nil, fmt.Errorf("更新后获取原料信息失败: %w", err) } // 4. 将领域模型转换为 DTO 并返回 return dto.ConvertRawMaterialToDTO(updatedRawMaterial), nil } // ===================================================================================================================== // 猪品种 (PigBreed) 实现 // ===================================================================================================================== // CreatePigBreed 创建猪品种 func (s *feedManagementServiceImpl) CreatePigBreed(ctx context.Context, req *dto.CreatePigBreedRequest) (*dto.PigBreedResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigBreed") breed := &models.PigBreed{ Name: req.Name, Description: req.Description, ParentInfo: req.ParentInfo, AppearanceFeatures: req.AppearanceFeatures, BreedAdvantages: req.BreedAdvantages, BreedDisadvantages: req.BreedDisadvantages, } if err := s.recipeSvc.CreatePigBreed(serviceCtx, breed); err != nil { return nil, fmt.Errorf("创建猪品种失败: %w", err) } return dto.ConvertPigBreedToDTO(breed), nil } // UpdatePigBreed 更新猪品种 func (s *feedManagementServiceImpl) UpdatePigBreed(ctx context.Context, id uint32, req *dto.UpdatePigBreedRequest) (*dto.PigBreedResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigBreed") breed := &models.PigBreed{ Model: models.Model{ID: id}, Name: req.Name, Description: req.Description, ParentInfo: req.ParentInfo, AppearanceFeatures: req.AppearanceFeatures, BreedAdvantages: req.BreedAdvantages, BreedDisadvantages: req.BreedDisadvantages, } if err := s.recipeSvc.UpdatePigBreed(serviceCtx, breed); err != nil { if errors.Is(err, recipe.ErrPigBreedNotFound) { return nil, ErrPigBreedNotFound } return nil, fmt.Errorf("更新猪品种失败: %w", err) } return dto.ConvertPigBreedToDTO(breed), nil } // DeletePigBreed 删除猪品种 func (s *feedManagementServiceImpl) DeletePigBreed(ctx context.Context, id uint32) error { serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigBreed") err := s.recipeSvc.DeletePigBreed(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrPigBreedNotFound) { return ErrPigBreedNotFound } if errors.Is(err, recipe.ErrPigBreedInUse) { return ErrPigBreedInUse } return fmt.Errorf("删除猪品种失败: %w", err) } return nil } // GetPigBreed 获取单个猪品种 func (s *feedManagementServiceImpl) GetPigBreed(ctx context.Context, id uint32) (*dto.PigBreedResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigBreed") breed, err := s.recipeSvc.GetPigBreedByID(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrPigBreedNotFound) { return nil, ErrPigBreedNotFound } return nil, fmt.Errorf("获取猪品种失败: %w", err) } return dto.ConvertPigBreedToDTO(breed), nil } // ListPigBreeds 列出猪品种 func (s *feedManagementServiceImpl) ListPigBreeds(ctx context.Context, req *dto.ListPigBreedRequest) (*dto.ListPigBreedResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigBreeds") opts := repository.PigBreedListOptions{ Name: req.Name, OrderBy: req.OrderBy, } breeds, total, err := s.recipeSvc.ListPigBreeds(serviceCtx, opts, req.Page, req.PageSize) if err != nil { return nil, fmt.Errorf("获取猪品种列表失败: %w", err) } return dto.ConvertPigBreedListToDTO(breeds, total, req.Page, req.PageSize), nil } // ===================================================================================================================== // 猪年龄阶段 (PigAgeStage) 实现 // ===================================================================================================================== // CreatePigAgeStage 创建猪年龄阶段 func (s *feedManagementServiceImpl) CreatePigAgeStage(ctx context.Context, req *dto.CreatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigAgeStage") ageStage := &models.PigAgeStage{ Name: req.Name, Description: req.Description, } if err := s.recipeSvc.CreatePigAgeStage(serviceCtx, ageStage); err != nil { return nil, fmt.Errorf("创建猪年龄阶段失败: %w", err) } return dto.ConvertPigAgeStageToDTO(ageStage), nil } // UpdatePigAgeStage 更新猪年龄阶段 func (s *feedManagementServiceImpl) UpdatePigAgeStage(ctx context.Context, id uint32, req *dto.UpdatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigAgeStage") ageStage := &models.PigAgeStage{ Model: models.Model{ID: id}, Name: req.Name, Description: req.Description, } if err := s.recipeSvc.UpdatePigAgeStage(serviceCtx, ageStage); err != nil { if errors.Is(err, recipe.ErrPigAgeStageNotFound) { return nil, ErrPigAgeStageNotFound } return nil, fmt.Errorf("更新猪年龄阶段失败: %w", err) } return dto.ConvertPigAgeStageToDTO(ageStage), nil } // DeletePigAgeStage 删除猪年龄阶段 func (s *feedManagementServiceImpl) DeletePigAgeStage(ctx context.Context, id uint32) error { serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigAgeStage") err := s.recipeSvc.DeletePigAgeStage(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrPigAgeStageNotFound) { return ErrPigAgeStageNotFound } if errors.Is(err, recipe.ErrPigAgeStageInUse) { return ErrPigAgeStageInUse } return fmt.Errorf("删除猪年龄阶段失败: %w", err) } return nil } // GetPigAgeStage 获取单个猪年龄阶段 func (s *feedManagementServiceImpl) GetPigAgeStage(ctx context.Context, id uint32) (*dto.PigAgeStageResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigAgeStage") ageStage, err := s.recipeSvc.GetPigAgeStageByID(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrPigAgeStageNotFound) { return nil, ErrPigAgeStageNotFound } return nil, fmt.Errorf("获取猪年龄阶段失败: %w", err) } return dto.ConvertPigAgeStageToDTO(ageStage), nil } // ListPigAgeStages 列出猪年龄阶段 func (s *feedManagementServiceImpl) ListPigAgeStages(ctx context.Context, req *dto.ListPigAgeStageRequest) (*dto.ListPigAgeStageResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigAgeStages") opts := repository.PigAgeStageListOptions{ Name: req.Name, OrderBy: req.OrderBy, } ageStages, total, err := s.recipeSvc.ListPigAgeStages(serviceCtx, opts, req.Page, req.PageSize) if err != nil { return nil, fmt.Errorf("获取猪年龄阶段列表失败: %w", err) } return dto.ConvertPigAgeStageListToDTO(ageStages, total, req.Page, req.PageSize), nil } // ===================================================================================================================== // 猪类型 (PigType) 实现 // ===================================================================================================================== // CreatePigType 创建猪类型 func (s *feedManagementServiceImpl) CreatePigType(ctx context.Context, req *dto.CreatePigTypeRequest) (*dto.PigTypeResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigType") pigType := &models.PigType{ BreedID: req.BreedID, AgeStageID: req.AgeStageID, Description: req.Description, DailyFeedIntake: req.DailyFeedIntake, DailyGainWeight: req.DailyGainWeight, MinDays: req.MinDays, MaxDays: req.MaxDays, MinWeight: req.MinWeight, MaxWeight: req.MaxWeight, } if err := s.recipeSvc.CreatePigType(serviceCtx, pigType); err != nil { if errors.Is(err, recipe.ErrPigBreedNotFound) { return nil, ErrPigBreedNotFound } if errors.Is(err, recipe.ErrPigAgeStageNotFound) { return nil, ErrPigAgeStageNotFound } return nil, fmt.Errorf("创建猪类型失败: %w", err) } // 创建后需要重新获取,以包含关联数据 createdPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, pigType.ID) if err != nil { if errors.Is(err, recipe.ErrPigTypeNotFound) { // 理论上不应该发生,因为刚创建 return nil, ErrPigTypeNotFound } return nil, fmt.Errorf("创建猪类型后获取详情失败: %w", err) } return dto.ConvertPigTypeToDTO(createdPigType), nil } // UpdatePigType 更新猪类型 func (s *feedManagementServiceImpl) UpdatePigType(ctx context.Context, id uint32, req *dto.UpdatePigTypeRequest) (*dto.PigTypeResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigType") pigType := &models.PigType{ Model: models.Model{ID: id}, BreedID: req.BreedID, AgeStageID: req.AgeStageID, Description: req.Description, DailyFeedIntake: req.DailyFeedIntake, DailyGainWeight: req.DailyGainWeight, MinDays: req.MinDays, MaxDays: req.MaxDays, MinWeight: req.MinWeight, MaxWeight: req.MaxWeight, } if err := s.recipeSvc.UpdatePigType(serviceCtx, pigType); err != nil { if errors.Is(err, recipe.ErrPigTypeNotFound) { return nil, ErrPigTypeNotFound } if errors.Is(err, recipe.ErrPigBreedNotFound) { return nil, ErrPigBreedNotFound } if errors.Is(err, recipe.ErrPigAgeStageNotFound) { return nil, ErrPigAgeStageNotFound } return nil, fmt.Errorf("更新猪类型失败: %w", err) } // 更新后需要重新获取,以包含关联数据 updatedPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrPigTypeNotFound) { // 理论上不应该发生,因为刚更新成功 return nil, ErrPigTypeNotFound } return nil, fmt.Errorf("更新猪类型后获取详情失败: %w", err) } return dto.ConvertPigTypeToDTO(updatedPigType), nil } // DeletePigType 删除猪类型 func (s *feedManagementServiceImpl) DeletePigType(ctx context.Context, id uint32) error { serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigType") err := s.recipeSvc.DeletePigType(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrPigTypeNotFound) { return ErrPigTypeNotFound } return fmt.Errorf("删除猪类型失败: %w", err) } return nil } // GetPigType 获取单个猪类型 func (s *feedManagementServiceImpl) GetPigType(ctx context.Context, id uint32) (*dto.PigTypeResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigType") pigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id) if err != nil { if errors.Is(err, recipe.ErrPigTypeNotFound) { return nil, ErrPigTypeNotFound } return nil, fmt.Errorf("获取猪类型失败: %w", err) } return dto.ConvertPigTypeToDTO(pigType), nil } // ListPigTypes 列出猪类型 func (s *feedManagementServiceImpl) ListPigTypes(ctx context.Context, req *dto.ListPigTypeRequest) (*dto.ListPigTypeResponse, error) { serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigTypes") opts := repository.PigTypeListOptions{ BreedID: req.BreedID, AgeStageID: req.AgeStageID, BreedName: req.BreedName, AgeStageName: req.AgeStageName, OrderBy: req.OrderBy, } pigTypes, total, err := s.recipeSvc.ListPigTypes(serviceCtx, opts, req.Page, req.PageSize) if err != nil { return nil, fmt.Errorf("获取猪类型列表失败: %w", err) } return dto.ConvertPigTypeListToDTO(pigTypes, total, req.Page, req.PageSize), nil }