mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-04-28 00:18:37 +00:00
✨ feat: Extract quota conversion helpers to shared utils
Move quota display/conversion helpers into web/src/helpers/quota.js and update the subscription plan editor to import and use the shared utilities instead of inline functions.
This commit is contained in:
@@ -27,8 +27,9 @@ import {
|
||||
Popover,
|
||||
Divider,
|
||||
Badge,
|
||||
Tooltip,
|
||||
} from '@douyinfe/semi-ui';
|
||||
import { IconEdit, IconStop, IconPlay } from '@douyinfe/semi-icons';
|
||||
import { renderQuota } from '../../../helpers';
|
||||
import { convertUSDToCurrency } from '../../../helpers/render';
|
||||
|
||||
const { Text } = Typography;
|
||||
@@ -81,7 +82,13 @@ const renderPlanTitle = (text, record, t) => {
|
||||
{convertUSDToCurrency(Number(plan?.price_amount || 0), 2)}
|
||||
</Text>
|
||||
<Text type='tertiary'>{t('总额度')}</Text>
|
||||
<Text>{plan?.total_amount > 0 ? plan.total_amount : t('不限')}</Text>
|
||||
{plan?.total_amount > 0 ? (
|
||||
<Tooltip content={`${t('原生额度')}:${plan.total_amount}`}>
|
||||
<Text>{renderQuota(plan.total_amount)}</Text>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Text>{t('不限')}</Text>
|
||||
)}
|
||||
<Text type='tertiary'>{t('升级分组')}</Text>
|
||||
<Text>{plan?.upgrade_group ? plan.upgrade_group : t('不升级')}</Text>
|
||||
<Text type='tertiary'>{t('购买上限')}</Text>
|
||||
@@ -165,7 +172,13 @@ const renderTotalAmount = (text, record, t) => {
|
||||
const total = Number(record?.plan?.total_amount || 0);
|
||||
return (
|
||||
<Text type={total > 0 ? 'secondary' : 'tertiary'}>
|
||||
{total > 0 ? total : t('不限')}
|
||||
{total > 0 ? (
|
||||
<Tooltip content={`${t('原生额度')}:${total}`}>
|
||||
<span>{renderQuota(total)}</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
t('不限')
|
||||
)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
@@ -236,30 +249,22 @@ const renderOperations = (text, record, { openEdit, setPlanEnabled, t }) => {
|
||||
return (
|
||||
<Space spacing={8}>
|
||||
<Button
|
||||
theme='borderless'
|
||||
theme='light'
|
||||
type='tertiary'
|
||||
size='small'
|
||||
icon={<IconEdit />}
|
||||
onClick={() => openEdit(record)}
|
||||
>
|
||||
{t('编辑')}
|
||||
</Button>
|
||||
{isEnabled ? (
|
||||
<Button
|
||||
theme='borderless'
|
||||
type='danger'
|
||||
size='small'
|
||||
icon={<IconStop />}
|
||||
onClick={handleToggle}
|
||||
>
|
||||
<Button theme='light' type='danger' size='small' onClick={handleToggle}>
|
||||
{t('禁用')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
theme='borderless'
|
||||
theme='light'
|
||||
type='primary'
|
||||
size='small'
|
||||
icon={<IconPlay />}
|
||||
onClick={handleToggle}
|
||||
>
|
||||
{t('启用')}
|
||||
|
||||
@@ -39,12 +39,11 @@ import {
|
||||
IconSave,
|
||||
} from '@douyinfe/semi-icons';
|
||||
import { Clock, RefreshCw } from 'lucide-react';
|
||||
import { API, showError, showSuccess } from '../../../../helpers';
|
||||
import {
|
||||
API,
|
||||
showError,
|
||||
showSuccess,
|
||||
renderQuotaWithPrompt,
|
||||
} from '../../../../helpers';
|
||||
quotaToDisplayAmount,
|
||||
displayAmountToQuota,
|
||||
} from '../../../../helpers/quota';
|
||||
import { useIsMobile } from '../../../../hooks/common/useIsMobile';
|
||||
|
||||
const { Text, Title } = Typography;
|
||||
@@ -118,7 +117,9 @@ const AddEditSubscriptionModal = ({
|
||||
enabled: p.enabled !== false,
|
||||
sort_order: Number(p.sort_order || 0),
|
||||
max_purchase_per_user: Number(p.max_purchase_per_user || 0),
|
||||
total_amount: Number(p.total_amount || 0),
|
||||
total_amount: Number(
|
||||
quotaToDisplayAmount(p.total_amount || 0).toFixed(2),
|
||||
),
|
||||
upgrade_group: p.upgrade_group || '',
|
||||
stripe_price_id: p.stripe_price_id || '',
|
||||
creem_product_id: p.creem_product_id || '',
|
||||
@@ -161,7 +162,7 @@ const AddEditSubscriptionModal = ({
|
||||
: 0,
|
||||
sort_order: Number(values.sort_order || 0),
|
||||
max_purchase_per_user: Number(values.max_purchase_per_user || 0),
|
||||
total_amount: Number(values.total_amount || 0),
|
||||
total_amount: displayAmountToQuota(values.total_amount),
|
||||
upgrade_group: values.upgrade_group || '',
|
||||
},
|
||||
};
|
||||
@@ -307,23 +308,16 @@ const AddEditSubscriptionModal = ({
|
||||
</Col>
|
||||
|
||||
<Col span={12}>
|
||||
<Form.AutoComplete
|
||||
<Form.InputNumber
|
||||
field='total_amount'
|
||||
label={t('总额度')}
|
||||
required
|
||||
type='number'
|
||||
min={0}
|
||||
precision={2}
|
||||
rules={[{ required: true, message: t('请输入总额度') }]}
|
||||
extraText={`${t('0 表示不限')} · ${renderQuotaWithPrompt(
|
||||
Number(values.total_amount || 0),
|
||||
extraText={`${t('0 表示不限')} · ${t('原生额度')}:${displayAmountToQuota(
|
||||
values.total_amount,
|
||||
)}`}
|
||||
data={[
|
||||
{ value: 500000, label: '1' },
|
||||
{ value: 5000000, label: '10' },
|
||||
{ value: 25000000, label: '50' },
|
||||
{ value: 50000000, label: '100' },
|
||||
{ value: 250000000, label: '500' },
|
||||
{ value: 500000000, label: '1000' },
|
||||
]}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
@@ -359,7 +359,8 @@ const SubscriptionPlansCard = ({
|
||||
</div>
|
||||
<Button
|
||||
size='small'
|
||||
theme='borderless'
|
||||
theme='light'
|
||||
type='tertiary'
|
||||
icon={
|
||||
<RefreshCw
|
||||
size={12}
|
||||
|
||||
@@ -115,7 +115,6 @@ const SubscriptionPurchaseModal = ({
|
||||
visible={visible}
|
||||
onCancel={onCancel}
|
||||
footer={null}
|
||||
maskClosable={false}
|
||||
size='small'
|
||||
centered
|
||||
>
|
||||
|
||||
25
web/src/helpers/quota.js
Normal file
25
web/src/helpers/quota.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { getCurrencyConfig } from './render';
|
||||
|
||||
export const getQuotaPerUnit = () => {
|
||||
const raw = parseFloat(localStorage.getItem('quota_per_unit') || '1');
|
||||
return Number.isFinite(raw) && raw > 0 ? raw : 1;
|
||||
};
|
||||
|
||||
export const quotaToDisplayAmount = (quota) => {
|
||||
const q = Number(quota || 0);
|
||||
if (!Number.isFinite(q) || q <= 0) return 0;
|
||||
const { type, rate } = getCurrencyConfig();
|
||||
if (type === 'TOKENS') return q;
|
||||
const usd = q / getQuotaPerUnit();
|
||||
if (type === 'USD') return usd;
|
||||
return usd * (rate || 1);
|
||||
};
|
||||
|
||||
export const displayAmountToQuota = (amount) => {
|
||||
const val = Number(amount || 0);
|
||||
if (!Number.isFinite(val) || val <= 0) return 0;
|
||||
const { type, rate } = getCurrencyConfig();
|
||||
if (type === 'TOKENS') return Math.round(val);
|
||||
const usd = type === 'USD' ? val : val / (rate || 1);
|
||||
return Math.round(usd * getQuotaPerUnit());
|
||||
};
|
||||
Reference in New Issue
Block a user