package service import ( "strings" "nex/backend/pkg/modelid" "nex/backend/internal/domain" "nex/backend/internal/repository" appErrors "nex/backend/pkg/errors" ) type providerService struct { providerRepo repository.ProviderRepository modelRepo repository.ModelRepository } func NewProviderService(providerRepo repository.ProviderRepository, modelRepo repository.ModelRepository) ProviderService { return &providerService{providerRepo: providerRepo, modelRepo: modelRepo} } func (s *providerService) Create(provider *domain.Provider) error { // 校验 provider_id 字符集 if err := modelid.ValidateProviderID(provider.ID); err != nil { return appErrors.ErrInvalidProviderID } provider.Enabled = true err := s.providerRepo.Create(provider) if err != nil && isUniqueConstraintError(err) { return appErrors.ErrConflict } return err } func (s *providerService) Get(id string, maskKey bool) (*domain.Provider, error) { provider, err := s.providerRepo.GetByID(id) if err != nil { return nil, err } if maskKey { provider.MaskAPIKey() } return provider, nil } func (s *providerService) List() ([]domain.Provider, error) { providers, err := s.providerRepo.List() if err != nil { return nil, err } for i := range providers { providers[i].MaskAPIKey() } return providers, nil } func (s *providerService) Update(id string, updates map[string]interface{}) error { if _, ok := updates["id"]; ok { return appErrors.ErrImmutableField } return s.providerRepo.Update(id, updates) } func (s *providerService) Delete(id string) error { return s.providerRepo.Delete(id) } // ListEnabledModels 返回所有启用的模型(用于 Models 接口本地聚合) func (s *providerService) ListEnabledModels() ([]domain.Model, error) { return s.modelRepo.ListEnabled() } // GetModelByProviderAndName 按 provider_id 和 model_name 查询模型(用于 ModelInfo 接口本地查询) func (s *providerService) GetModelByProviderAndName(providerID, modelName string) (*domain.Model, error) { return s.modelRepo.FindByProviderAndModelName(providerID, modelName) } // isUniqueConstraintError 判断是否为数据库唯一约束冲突错误 func isUniqueConstraintError(err error) bool { if err == nil { return false } msg := strings.ToLower(err.Error()) return strings.Contains(msg, "unique constraint") || strings.Contains(msg, "duplicate") }