diff --git a/model/subscription.go b/model/subscription.go index 6d8d21306..2d23a8b5b 100644 --- a/model/subscription.go +++ b/model/subscription.go @@ -666,6 +666,22 @@ func GetAllActiveUserSubscriptions(userId int) ([]SubscriptionSummary, error) { return buildSubscriptionSummaries(subs), nil } +// HasActiveUserSubscription returns whether the user has any active subscription. +// This is a lightweight existence check to avoid heavy pre-consume transactions. +func HasActiveUserSubscription(userId int) (bool, error) { + if userId <= 0 { + return false, errors.New("invalid userId") + } + now := common.GetTimestamp() + var count int64 + if err := DB.Model(&UserSubscription{}). + Where("user_id = ? AND status = ? AND end_time > ?", userId, "active", now). + Count(&count).Error; err != nil { + return false, err + } + return count > 0, nil +} + // GetAllUserSubscriptions returns all subscriptions (active and expired) for a user. func GetAllUserSubscriptions(userId int) ([]SubscriptionSummary, error) { if userId <= 0 { diff --git a/service/billing_session.go b/service/billing_session.go index 04fce6136..1a31316b5 100644 --- a/service/billing_session.go +++ b/service/billing_session.go @@ -323,12 +323,19 @@ func NewBillingSession(c *gin.Context, relayInfo *relaycommon.RelayInfo, preCons case "subscription_first": fallthrough default: - session, err := trySubscription() - if err != nil { - if err.GetErrorCode() == types.ErrorCodeInsufficientUserQuota { + hasSub, subCheckErr := model.HasActiveUserSubscription(relayInfo.UserId) + if subCheckErr != nil { + return nil, types.NewError(subCheckErr, types.ErrorCodeQueryDataError, types.ErrOptionWithSkipRetry()) + } + if !hasSub { + return tryWallet() + } + session, apiErr := trySubscription() + if apiErr != nil { + if apiErr.GetErrorCode() == types.ErrorCodeInsufficientUserQuota { return tryWallet() } - return nil, err + return nil, apiErr } return session, nil } diff --git a/web/src/components/topup/SubscriptionPlansCard.jsx b/web/src/components/topup/SubscriptionPlansCard.jsx index 54b4506ba..a619c7450 100644 --- a/web/src/components/topup/SubscriptionPlansCard.jsx +++ b/web/src/components/topup/SubscriptionPlansCard.jsx @@ -201,6 +201,16 @@ const SubscriptionPlansCard = ({ // 当前订阅信息 - 支持多个订阅 const hasActiveSubscription = activeSubscriptions.length > 0; const hasAnySubscription = allSubscriptions.length > 0; + const disableSubscriptionPreference = !hasActiveSubscription; + const isSubscriptionPreference = + billingPreference === 'subscription_first' || + billingPreference === 'subscription_only'; + const displayBillingPreference = + disableSubscriptionPreference && isSubscriptionPreference + ? 'wallet_first' + : billingPreference; + const subscriptionPreferenceLabel = + billingPreference === 'subscription_only' ? t('仅用订阅') : t('优先订阅'); const planPurchaseCountMap = useMemo(() => { const map = new Map(); @@ -319,13 +329,25 @@ const SubscriptionPlansCard = ({