mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-03-30 04:03:18 +00:00
✨ chore: Improve subscription billing fallback and UI states
Add a lightweight active-subscription check to skip subscription pre-consume when none exist, reducing unnecessary transactions and locks. In the subscription UI, disable subscription-first options when no active plan is available, show the effective fallback to wallet with a clear notice, and distinguish “invalidated” from “expired” states. Update i18n strings across supported locales to reflect the new messages and status labels.
This commit is contained in:
@@ -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 = ({
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Select
|
||||
value={billingPreference}
|
||||
value={displayBillingPreference}
|
||||
onChange={onChangeBillingPreference}
|
||||
size='small'
|
||||
optionList={[
|
||||
{ value: 'subscription_first', label: t('优先订阅') },
|
||||
{
|
||||
value: 'subscription_first',
|
||||
label: disableSubscriptionPreference
|
||||
? `${t('优先订阅')} (${t('无生效')})`
|
||||
: t('优先订阅'),
|
||||
disabled: disableSubscriptionPreference,
|
||||
},
|
||||
{ value: 'wallet_first', label: t('优先钱包') },
|
||||
{ value: 'subscription_only', label: t('仅用订阅') },
|
||||
{
|
||||
value: 'subscription_only',
|
||||
label: disableSubscriptionPreference
|
||||
? `${t('仅用订阅')} (${t('无生效')})`
|
||||
: t('仅用订阅'),
|
||||
disabled: disableSubscriptionPreference,
|
||||
},
|
||||
{ value: 'wallet_only', label: t('仅用钱包') },
|
||||
]}
|
||||
/>
|
||||
@@ -344,6 +366,13 @@ const SubscriptionPlansCard = ({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{disableSubscriptionPreference && isSubscriptionPreference && (
|
||||
<Text type='tertiary' size='small'>
|
||||
{t('已保存偏好为')}
|
||||
{subscriptionPreferenceLabel}
|
||||
{t(',当前无生效订阅,将自动使用钱包')}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{hasAnySubscription ? (
|
||||
<>
|
||||
@@ -364,6 +393,7 @@ const SubscriptionPlansCard = ({
|
||||
const usagePercent = getUsagePercent(sub);
|
||||
const now = Date.now() / 1000;
|
||||
const isExpired = (subscription?.end_time || 0) < now;
|
||||
const isCancelled = subscription?.status === 'cancelled';
|
||||
const isActive =
|
||||
subscription?.status === 'active' && !isExpired;
|
||||
|
||||
@@ -386,6 +416,10 @@ const SubscriptionPlansCard = ({
|
||||
>
|
||||
{t('生效')}
|
||||
</Tag>
|
||||
) : isCancelled ? (
|
||||
<Tag color='white' size='small' shape='circle'>
|
||||
{t('已作废')}
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag color='white' size='small' shape='circle'>
|
||||
{t('已过期')}
|
||||
@@ -399,7 +433,11 @@ const SubscriptionPlansCard = ({
|
||||
)}
|
||||
</div>
|
||||
<div className='text-xs text-gray-500 mb-2'>
|
||||
{isActive ? t('至') : t('过期于')}{' '}
|
||||
{isActive
|
||||
? t('至')
|
||||
: isCancelled
|
||||
? t('作废于')
|
||||
: t('过期于')}{' '}
|
||||
{new Date(
|
||||
(subscription?.end_time || 0) * 1000,
|
||||
).toLocaleString()}
|
||||
@@ -471,9 +509,9 @@ const SubscriptionPlansCard = ({
|
||||
resetLabel ? { label: resetLabel } : null,
|
||||
totalAmount > 0
|
||||
? {
|
||||
label: totalLabel,
|
||||
tooltip: `${t('原生额度')}:${totalAmount}`,
|
||||
}
|
||||
label: totalLabel,
|
||||
tooltip: `${t('原生额度')}:${totalAmount}`,
|
||||
}
|
||||
: { label: totalLabel },
|
||||
limitLabel ? { label: limitLabel } : null,
|
||||
upgradeLabel ? { label: upgradeLabel } : null,
|
||||
@@ -482,8 +520,9 @@ const SubscriptionPlansCard = ({
|
||||
return (
|
||||
<Card
|
||||
key={plan?.id}
|
||||
className={`!rounded-xl transition-all hover:shadow-lg w-full h-full ${isPopular ? 'ring-2 ring-purple-500' : ''
|
||||
}`}
|
||||
className={`!rounded-xl transition-all hover:shadow-lg w-full h-full ${
|
||||
isPopular ? 'ring-2 ring-purple-500' : ''
|
||||
}`}
|
||||
bodyStyle={{ padding: 0 }}
|
||||
>
|
||||
<div className='p-4 h-full flex flex-col'>
|
||||
@@ -629,9 +668,9 @@ const SubscriptionPlansCard = ({
|
||||
purchaseLimitInfo={
|
||||
selectedPlan?.plan?.id
|
||||
? {
|
||||
limit: Number(selectedPlan?.plan?.max_purchase_per_user || 0),
|
||||
count: getPlanPurchaseCount(selectedPlan?.plan?.id),
|
||||
}
|
||||
limit: Number(selectedPlan?.plan?.max_purchase_per_user || 0),
|
||||
count: getPlanPurchaseCount(selectedPlan?.plan?.id),
|
||||
}
|
||||
: null
|
||||
}
|
||||
onPayStripe={payStripe}
|
||||
|
||||
@@ -2729,10 +2729,13 @@
|
||||
"我的订阅": "My Subscriptions",
|
||||
"个生效中": "active",
|
||||
"无生效": "No active",
|
||||
"已保存偏好为": "Saved preference: ",
|
||||
",当前无生效订阅,将自动使用钱包": ", no active subscription. Wallet will be used automatically.",
|
||||
"个已过期": "expired",
|
||||
"订阅": "Subscription",
|
||||
"至": "until",
|
||||
"过期于": "Expires at",
|
||||
"作废于": "Invalidated at",
|
||||
"购买套餐后即可享受模型权益": "Enjoy model benefits after purchasing a plan",
|
||||
"限购": "Limit",
|
||||
"推荐": "Recommended",
|
||||
|
||||
@@ -2692,10 +2692,13 @@
|
||||
"我的订阅": "Mes abonnements",
|
||||
"个生效中": "actifs",
|
||||
"无生效": "Aucun actif",
|
||||
"已保存偏好为": "Préférence enregistrée : ",
|
||||
",当前无生效订阅,将自动使用钱包": ", aucun abonnement actif, le portefeuille sera utilisé automatiquement.",
|
||||
"个已过期": "expirés",
|
||||
"订阅": "Abonnement",
|
||||
"至": "jusqu'à",
|
||||
"过期于": "Expire le",
|
||||
"作废于": "Invalidé le",
|
||||
"购买套餐后即可享受模型权益": "Profitez des avantages du modèle après l'achat d'un plan",
|
||||
"限购": "Limite",
|
||||
"推荐": "Recommandé",
|
||||
|
||||
@@ -2675,10 +2675,13 @@
|
||||
"我的订阅": "私のサブスクリプション",
|
||||
"个生效中": "件有効中",
|
||||
"无生效": "有効なし",
|
||||
"已保存偏好为": "保存された設定は",
|
||||
",当前无生效订阅,将自动使用钱包": "、有効なサブスクリプションがないため、自動的にウォレットを使用します",
|
||||
"个已过期": "件期限切れ",
|
||||
"订阅": "サブスクリプション",
|
||||
"至": "まで",
|
||||
"过期于": "有効期限",
|
||||
"作废于": "無効化日",
|
||||
"购买套餐后即可享受模型权益": "プラン購入後にモデル特典を利用できます",
|
||||
"限购": "購入制限",
|
||||
"推荐": "おすすめ",
|
||||
|
||||
@@ -2705,10 +2705,13 @@
|
||||
"我的订阅": "Мои подписки",
|
||||
"个生效中": "активных",
|
||||
"无生效": "Нет активных",
|
||||
"已保存偏好为": "Сохранённая настройка: ",
|
||||
",当前无生效订阅,将自动使用钱包": ", нет активной подписки, автоматически будет использоваться кошелек.",
|
||||
"个已过期": "истекших",
|
||||
"订阅": "Подписка",
|
||||
"至": "до",
|
||||
"过期于": "Истекает",
|
||||
"作废于": "Аннулировано",
|
||||
"购买套餐后即可享受模型权益": "После покупки плана доступны преимущества моделей",
|
||||
"限购": "Лимит",
|
||||
"推荐": "Рекомендуется",
|
||||
|
||||
@@ -3254,9 +3254,12 @@
|
||||
"我的订阅": "Đăng ký của tôi",
|
||||
"个生效中": "gói đăng ký đang hiệu lực",
|
||||
"无生效": "Không có gói đăng ký hiệu lực",
|
||||
"已保存偏好为": "Đã lưu tùy chọn: ",
|
||||
",当前无生效订阅,将自动使用钱包": ", hiện không có gói đăng ký hiệu lực, sẽ tự động dùng ví.",
|
||||
"个已过期": "gói đăng ký đã hết hạn",
|
||||
"订阅": "Đăng ký",
|
||||
"过期于": "Hết hạn vào",
|
||||
"作废于": "Vô hiệu vào",
|
||||
"购买套餐后即可享受模型权益": "Mua gói để nhận quyền lợi mô hình",
|
||||
"限购": "Giới hạn mua",
|
||||
"推荐": "Đề xuất",
|
||||
|
||||
@@ -2714,10 +2714,13 @@
|
||||
"我的订阅": "我的订阅",
|
||||
"个生效中": "个生效中",
|
||||
"无生效": "无生效",
|
||||
"已保存偏好为": "已保存偏好为",
|
||||
",当前无生效订阅,将自动使用钱包": ",当前无生效订阅,将自动使用钱包",
|
||||
"个已过期": "个已过期",
|
||||
"订阅": "订阅",
|
||||
"至": "至",
|
||||
"过期于": "过期于",
|
||||
"作废于": "作废于",
|
||||
"购买套餐后即可享受模型权益": "购买套餐后即可享受模型权益",
|
||||
"限购": "限购",
|
||||
"推荐": "推荐",
|
||||
|
||||
Reference in New Issue
Block a user