diff --git a/backend/internal/service/admin_service.go b/backend/internal/service/admin_service.go index 8992e2505d..5d96db45f2 100644 --- a/backend/internal/service/admin_service.go +++ b/backend/internal/service/admin_service.go @@ -84,7 +84,6 @@ type AdminService interface { DeleteRedeemCode(ctx context.Context, id int64) error BatchDeleteRedeemCodes(ctx context.Context, ids []int64) (int64, error) ExpireRedeemCode(ctx context.Context, id int64) (*RedeemCode, error) - ResetAccountQuota(ctx context.Context, id int64) error } // CreateUserInput represents input for creating a new user via admin operations. @@ -138,10 +137,9 @@ type CreateGroupInput struct { // 无效请求兜底分组 ID(仅 anthropic 平台使用) FallbackGroupIDOnInvalidRequest *int64 // 模型路由配置(仅 anthropic 平台使用) - ModelRouting map[string][]int64 - ModelRoutingEnabled bool // 是否启用模型路由 - MCPXMLInject *bool - SimulateClaudeMaxEnabled *bool + ModelRouting map[string][]int64 + ModelRoutingEnabled bool // 是否启用模型路由 + MCPXMLInject *bool // 支持的模型系列(仅 antigravity 平台使用) SupportedModelScopes []string // Sora 存储配额 @@ -175,10 +173,9 @@ type UpdateGroupInput struct { // 无效请求兜底分组 ID(仅 anthropic 平台使用) FallbackGroupIDOnInvalidRequest *int64 // 模型路由配置(仅 anthropic 平台使用) - ModelRouting map[string][]int64 - ModelRoutingEnabled *bool // 是否启用模型路由 - MCPXMLInject *bool - SimulateClaudeMaxEnabled *bool + ModelRouting map[string][]int64 + ModelRoutingEnabled *bool // 是否启用模型路由 + MCPXMLInject *bool // 支持的模型系列(仅 antigravity 平台使用) SupportedModelScopes *[]string // Sora 存储配额 @@ -359,10 +356,6 @@ type ProxyExitInfoProber interface { ProbeProxy(ctx context.Context, proxyURL string) (*ProxyExitInfo, int64, error) } -type groupExistenceBatchReader interface { - ExistsByIDs(ctx context.Context, ids []int64) (map[int64]bool, error) -} - type proxyQualityTarget struct { Target string URL string @@ -438,6 +431,10 @@ type userGroupRateBatchReader interface { GetByUserIDs(ctx context.Context, userIDs []int64) (map[int64]map[int64]float64, error) } +type groupExistenceBatchReader interface { + ExistsByIDs(ctx context.Context, ids []int64) (map[int64]bool, error) +} + // NewAdminService creates a new AdminService func NewAdminService( userRepo UserRepository, @@ -853,13 +850,6 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn if input.MCPXMLInject != nil { mcpXMLInject = *input.MCPXMLInject } - simulateClaudeMaxEnabled := false - if input.SimulateClaudeMaxEnabled != nil { - if platform != PlatformAnthropic && *input.SimulateClaudeMaxEnabled { - return nil, fmt.Errorf("simulate_claude_max_enabled only supported for anthropic groups") - } - simulateClaudeMaxEnabled = *input.SimulateClaudeMaxEnabled - } // 如果指定了复制账号的源分组,先获取账号 ID 列表 var accountIDsToCopy []int64 @@ -916,7 +906,6 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn FallbackGroupIDOnInvalidRequest: fallbackOnInvalidRequest, ModelRouting: input.ModelRouting, MCPXMLInject: mcpXMLInject, - SimulateClaudeMaxEnabled: simulateClaudeMaxEnabled, SupportedModelScopes: input.SupportedModelScopes, SoraStorageQuotaBytes: input.SoraStorageQuotaBytes, } @@ -1126,15 +1115,6 @@ func (s *adminServiceImpl) UpdateGroup(ctx context.Context, id int64, input *Upd if input.MCPXMLInject != nil { group.MCPXMLInject = *input.MCPXMLInject } - if input.SimulateClaudeMaxEnabled != nil { - if group.Platform != PlatformAnthropic && *input.SimulateClaudeMaxEnabled { - return nil, fmt.Errorf("simulate_claude_max_enabled only supported for anthropic groups") - } - group.SimulateClaudeMaxEnabled = *input.SimulateClaudeMaxEnabled - } - if group.Platform != PlatformAnthropic { - group.SimulateClaudeMaxEnabled = false - } // 支持的模型系列(仅 antigravity 平台使用) if input.SupportedModelScopes != nil { @@ -1487,10 +1467,6 @@ func (s *adminServiceImpl) UpdateAccount(ctx context.Context, id int64, input *U account.Credentials = input.Credentials } if len(input.Extra) > 0 { - // 保留 quota_used,防止编辑账号时意外重置配额用量 - if oldQuotaUsed, ok := account.Extra["quota_used"]; ok { - input.Extra["quota_used"] = oldQuotaUsed - } account.Extra = input.Extra } if input.ProxyID != nil { @@ -1659,7 +1635,13 @@ func (s *adminServiceImpl) BulkUpdateAccounts(ctx context.Context, input *BulkUp repoUpdates.RateMultiplier = input.RateMultiplier } if input.LoadFactor != nil { - repoUpdates.LoadFactor = input.LoadFactor + if *input.LoadFactor <= 0 { + repoUpdates.LoadFactor = nil // 0 或负数表示清除 + } else if *input.LoadFactor > 10000 { + return nil, errors.New("load_factor must be <= 10000") + } else { + repoUpdates.LoadFactor = input.LoadFactor + } } if input.Status != "" { repoUpdates.Status = &input.Status @@ -2484,7 +2466,3 @@ func (e *MixedChannelError) Error() string { return fmt.Sprintf("mixed_channel_warning: Group '%s' contains both %s and %s accounts. Using mixed channels in the same context may cause thinking block signature validation issues, which will fallback to non-thinking mode for historical messages.", e.GroupName, e.CurrentPlatform, e.OtherPlatform) } - -func (s *adminServiceImpl) ResetAccountQuota(ctx context.Context, id int64) error { - return s.accountRepo.ResetQuotaUsed(ctx, id) -} diff --git a/backend/internal/service/ops_concurrency.go b/backend/internal/service/ops_concurrency.go index c03108c4b9..a571dd4df4 100644 --- a/backend/internal/service/ops_concurrency.go +++ b/backend/internal/service/ops_concurrency.go @@ -64,9 +64,12 @@ func (s *OpsService) getAccountsLoadMapBestEffort(ctx context.Context, accounts if acc.ID <= 0 { continue } - lf := acc.EffectiveLoadFactor() - if prev, ok := unique[acc.ID]; !ok || lf > prev { - unique[acc.ID] = lf + c := acc.Concurrency + if c <= 0 { + c = 1 + } + if prev, ok := unique[acc.ID]; !ok || c > prev { + unique[acc.ID] = c } } diff --git a/backend/internal/service/ops_metrics_collector.go b/backend/internal/service/ops_metrics_collector.go index 6c33707138..f93481e7ff 100644 --- a/backend/internal/service/ops_metrics_collector.go +++ b/backend/internal/service/ops_metrics_collector.go @@ -391,7 +391,7 @@ func (c *OpsMetricsCollector) collectConcurrencyQueueDepth(parentCtx context.Con } batch = append(batch, AccountWithConcurrency{ ID: acc.ID, - MaxConcurrency: acc.EffectiveLoadFactor(), + MaxConcurrency: acc.Concurrency, }) } if len(batch) == 0 {