diff --git a/backend/internal/service/billing_service.go b/backend/internal/service/billing_service.go index c3e2149a..2fe13686 100644 --- a/backend/internal/service/billing_service.go +++ b/backend/internal/service/billing_service.go @@ -422,6 +422,7 @@ type CostInput struct { RateMultiplier float64 ServiceTier string // "priority","flex","" 等 Resolver *ModelPricingResolver // 定价解析器 + Resolved *ResolvedPricing // 可选:预解析的定价结果(避免重复 Resolve 调用) } // CalculateCostUnified 统一计费入口,支持三种计费模式。 @@ -432,10 +433,14 @@ func (s *BillingService) CalculateCostUnified(input CostInput) (*CostBreakdown, return s.calculateCostInternal(input.Model, input.Tokens, input.RateMultiplier, input.ServiceTier, nil) } - resolved := input.Resolver.Resolve(input.Ctx, PricingInput{ - Model: input.Model, - GroupID: input.GroupID, - }) + // 优先使用预解析结果,避免重复 Resolve 调用 + resolved := input.Resolved + if resolved == nil { + resolved = input.Resolver.Resolve(input.Ctx, PricingInput{ + Model: input.Model, + GroupID: input.GroupID, + }) + } if input.RateMultiplier <= 0 { input.RateMultiplier = 1.0 diff --git a/backend/internal/service/gateway_service.go b/backend/internal/service/gateway_service.go index 6d2b04ee..a95b62b1 100644 --- a/backend/internal/service/gateway_service.go +++ b/backend/internal/service/gateway_service.go @@ -8007,7 +8007,7 @@ func (s *GatewayService) calculateImageCost( billingModel string, multiplier float64, ) *CostBreakdown { - if s.resolveChannelPricing(ctx, billingModel, apiKey) != nil { + if resolved := s.resolveChannelPricing(ctx, billingModel, apiKey); resolved != nil { tokens := UsageTokens{ InputTokens: result.Usage.InputTokens, OutputTokens: result.Usage.OutputTokens, @@ -8022,6 +8022,7 @@ func (s *GatewayService) calculateImageCost( RequestCount: 1, RateMultiplier: multiplier, Resolver: s.resolver, + Resolved: resolved, }) if err != nil { logger.LegacyPrintf("service.gateway", "Calculate image token cost failed: %v", err) @@ -8064,7 +8065,7 @@ func (s *GatewayService) calculateTokenCost( var err error // 优先尝试渠道定价 → CalculateCostUnified - if s.resolveChannelPricing(ctx, billingModel, apiKey) != nil { + if resolved := s.resolveChannelPricing(ctx, billingModel, apiKey); resolved != nil { gid := apiKey.Group.ID cost, err = s.billingService.CalculateCostUnified(CostInput{ Ctx: ctx, @@ -8074,6 +8075,7 @@ func (s *GatewayService) calculateTokenCost( RequestCount: 1, RateMultiplier: multiplier, Resolver: s.resolver, + Resolved: resolved, }) } else if opts.LongContextThreshold > 0 { // 长上下文双倍计费(如 Gemini 200K 阈值) diff --git a/backend/internal/service/model_pricing_resolver.go b/backend/internal/service/model_pricing_resolver.go index ad31008f..b7ca4cb7 100644 --- a/backend/internal/service/model_pricing_resolver.go +++ b/backend/internal/service/model_pricing_resolver.go @@ -151,7 +151,7 @@ func (r *ModelPricingResolver) applyTokenOverrides(chPricing *ChannelModelPricin // applyRequestTierOverrides 应用按次/图片模式的渠道覆盖 func (r *ModelPricingResolver) applyRequestTierOverrides(chPricing *ChannelModelPricing, resolved *ResolvedPricing) { - resolved.RequestTiers = chPricing.Intervals + resolved.RequestTiers = filterValidIntervals(chPricing.Intervals) if chPricing.PerRequestPrice != nil { resolved.DefaultPerRequestPrice = *chPricing.PerRequestPrice }