feat(default): reorganize system settings pricing UI

Refine the default system settings structure and model pricing editor so pricing configuration is easier to scan and edit.
This commit is contained in:
CaIon
2026-05-06 16:29:45 +08:00
parent 9acf5fecae
commit 0f9f094a48
62 changed files with 3655 additions and 2343 deletions
@@ -0,0 +1,102 @@
import { SettingsPage } from '../components/settings-page'
import type { BillingSettings } from '../types'
import {
BILLING_DEFAULT_SECTION,
getBillingSectionContent,
} from './section-registry.tsx'
const defaultBillingSettings: BillingSettings = {
QuotaForNewUser: 0,
PreConsumedQuota: 0,
QuotaForInviter: 0,
QuotaForInvitee: 0,
TopUpLink: '',
'general_setting.docs_link': '',
'quota_setting.enable_free_model_pre_consume': true,
QuotaPerUnit: 500000,
USDExchangeRate: 7,
'general_setting.quota_display_type': 'USD',
'general_setting.custom_currency_symbol': '¤',
'general_setting.custom_currency_exchange_rate': 1,
DisplayInCurrencyEnabled: true,
DisplayTokenStatEnabled: true,
ModelPrice: '',
ModelRatio: '',
CacheRatio: '',
CreateCacheRatio: '',
CompletionRatio: '',
ImageRatio: '',
AudioRatio: '',
AudioCompletionRatio: '',
ExposeRatioEnabled: false,
'billing_setting.billing_mode': '{}',
'billing_setting.billing_expr': '{}',
'tool_price_setting.prices': '{}',
TopupGroupRatio: '',
GroupRatio: '',
UserUsableGroups: '',
GroupGroupRatio: '',
AutoGroups: '',
DefaultUseAutoGroup: false,
'group_ratio_setting.group_special_usable_group': '{}',
PayAddress: '',
EpayId: '',
EpayKey: '',
Price: 7.3,
MinTopUp: 1,
CustomCallbackAddress: '',
PayMethods: '',
'payment_setting.amount_options': '',
'payment_setting.amount_discount': '',
StripeApiSecret: '',
StripeWebhookSecret: '',
StripePriceId: '',
StripeUnitPrice: 8.0,
StripeMinTopUp: 1,
StripePromotionCodesEnabled: false,
CreemApiKey: '',
CreemWebhookSecret: '',
CreemTestMode: false,
CreemProducts: '[]',
WaffoEnabled: false,
WaffoApiKey: '',
WaffoPrivateKey: '',
WaffoPublicCert: '',
WaffoSandboxPublicCert: '',
WaffoSandboxApiKey: '',
WaffoSandboxPrivateKey: '',
WaffoSandbox: false,
WaffoMerchantId: '',
WaffoCurrency: 'USD',
WaffoUnitPrice: 1,
WaffoMinTopUp: 1,
WaffoNotifyUrl: '',
WaffoReturnUrl: '',
WaffoPayMethods: '[]',
WaffoPancakeEnabled: false,
WaffoPancakeSandbox: false,
WaffoPancakeMerchantID: '',
WaffoPancakePrivateKey: '',
WaffoPancakeWebhookPublicKey: '',
WaffoPancakeWebhookTestKey: '',
WaffoPancakeStoreID: '',
WaffoPancakeProductID: '',
WaffoPancakeReturnURL: '',
WaffoPancakeCurrency: 'USD',
WaffoPancakeUnitPrice: 1,
WaffoPancakeMinTopUp: 1,
'checkin_setting.enabled': false,
'checkin_setting.min_quota': 1000,
'checkin_setting.max_quota': 10000,
}
export function BillingSettings() {
return (
<SettingsPage
routePath='/_authenticated/system-settings/billing/$section'
defaultSettings={defaultBillingSettings}
defaultSection={BILLING_DEFAULT_SECTION}
getSectionContent={getBillingSectionContent}
/>
)
}
@@ -0,0 +1,202 @@
import { parseCurrencyDisplayType } from '@/lib/currency'
import type { BillingSettings } from '../types'
import { createSectionRegistry } from '../utils/section-registry'
import { CheckinSettingsSection } from '../general/checkin-settings-section'
import { PricingSection } from '../general/pricing-section'
import { QuotaSettingsSection } from '../general/quota-settings-section'
import { PaymentSettingsSection } from '../integrations/payment-settings-section'
import { RatioSettingsCard } from '../models/ratio-settings-card'
const getModelDefaults = (settings: BillingSettings) => ({
ModelPrice: settings.ModelPrice,
ModelRatio: settings.ModelRatio,
CacheRatio: settings.CacheRatio,
CreateCacheRatio: settings.CreateCacheRatio,
CompletionRatio: settings.CompletionRatio,
ImageRatio: settings.ImageRatio,
AudioRatio: settings.AudioRatio,
AudioCompletionRatio: settings.AudioCompletionRatio,
ExposeRatioEnabled: settings.ExposeRatioEnabled,
BillingMode: settings['billing_setting.billing_mode'],
BillingExpr: settings['billing_setting.billing_expr'],
})
const getGroupDefaults = (settings: BillingSettings) => ({
TopupGroupRatio: settings.TopupGroupRatio,
GroupRatio: settings.GroupRatio,
UserUsableGroups: settings.UserUsableGroups,
GroupGroupRatio: settings.GroupGroupRatio,
AutoGroups: settings.AutoGroups,
DefaultUseAutoGroup: settings.DefaultUseAutoGroup,
GroupSpecialUsableGroup:
settings['group_ratio_setting.group_special_usable_group'],
})
const BILLING_SECTIONS = [
{
id: 'quota',
titleKey: 'Quota Settings',
descriptionKey: 'Configure user quota allocation and rewards',
build: (settings: BillingSettings) => (
<QuotaSettingsSection
defaultValues={{
QuotaForNewUser: settings.QuotaForNewUser,
PreConsumedQuota: settings.PreConsumedQuota,
QuotaForInviter: settings.QuotaForInviter,
QuotaForInvitee: settings.QuotaForInvitee,
TopUpLink: settings.TopUpLink,
'general_setting.docs_link': settings['general_setting.docs_link'],
'quota_setting.enable_free_model_pre_consume':
settings['quota_setting.enable_free_model_pre_consume'],
}}
/>
),
},
{
id: 'currency',
titleKey: 'Currency & Display',
descriptionKey: 'Configure currency conversion and quota display options',
build: (settings: BillingSettings) => (
<PricingSection
defaultValues={{
QuotaPerUnit: settings.QuotaPerUnit,
USDExchangeRate: settings.USDExchangeRate,
DisplayInCurrencyEnabled: settings.DisplayInCurrencyEnabled,
DisplayTokenStatEnabled: settings.DisplayTokenStatEnabled,
general_setting: {
quota_display_type: parseCurrencyDisplayType(
settings['general_setting.quota_display_type']
),
custom_currency_symbol:
settings['general_setting.custom_currency_symbol'] ?? '¤',
custom_currency_exchange_rate:
settings['general_setting.custom_currency_exchange_rate'] ?? 1,
},
}}
/>
),
},
{
id: 'model-pricing',
titleKey: 'Model Pricing',
descriptionKey: 'Configure model pricing ratios and tool prices',
build: (settings: BillingSettings) => (
<RatioSettingsCard
titleKey='Model Pricing'
descriptionKey='Configure model pricing ratios and tool prices'
modelDefaults={getModelDefaults(settings)}
groupDefaults={getGroupDefaults(settings)}
toolPricesDefault={settings['tool_price_setting.prices']}
visibleTabs={['models', 'tool-prices', 'upstream-sync']}
/>
),
},
{
id: 'group-pricing',
titleKey: 'Group Pricing',
descriptionKey: 'Configure group ratios and group-specific pricing rules',
build: (settings: BillingSettings) => (
<RatioSettingsCard
titleKey='Group Pricing'
descriptionKey='Configure group ratios and group-specific pricing rules'
modelDefaults={getModelDefaults(settings)}
groupDefaults={getGroupDefaults(settings)}
toolPricesDefault={settings['tool_price_setting.prices']}
visibleTabs={['groups']}
/>
),
},
{
id: 'payment',
titleKey: 'Payment Gateway',
descriptionKey: 'Configure payment gateway integrations',
build: (settings: BillingSettings) => (
<PaymentSettingsSection
defaultValues={{
PayAddress: settings.PayAddress,
EpayId: settings.EpayId,
EpayKey: settings.EpayKey,
Price: settings.Price,
MinTopUp: settings.MinTopUp,
CustomCallbackAddress: settings.CustomCallbackAddress,
PayMethods: settings.PayMethods,
AmountOptions: settings['payment_setting.amount_options'],
AmountDiscount: settings['payment_setting.amount_discount'],
StripeApiSecret: settings.StripeApiSecret,
StripeWebhookSecret: settings.StripeWebhookSecret,
StripePriceId: settings.StripePriceId,
StripeUnitPrice: settings.StripeUnitPrice,
StripeMinTopUp: settings.StripeMinTopUp,
StripePromotionCodesEnabled: settings.StripePromotionCodesEnabled,
CreemApiKey: settings.CreemApiKey,
CreemWebhookSecret: settings.CreemWebhookSecret,
CreemTestMode: settings.CreemTestMode,
CreemProducts: settings.CreemProducts,
}}
waffoDefaultValues={{
WaffoEnabled: settings.WaffoEnabled ?? false,
WaffoApiKey: settings.WaffoApiKey ?? '',
WaffoPrivateKey: settings.WaffoPrivateKey ?? '',
WaffoPublicCert: settings.WaffoPublicCert ?? '',
WaffoSandboxPublicCert: settings.WaffoSandboxPublicCert ?? '',
WaffoSandboxApiKey: settings.WaffoSandboxApiKey ?? '',
WaffoSandboxPrivateKey: settings.WaffoSandboxPrivateKey ?? '',
WaffoSandbox: settings.WaffoSandbox ?? false,
WaffoMerchantId: settings.WaffoMerchantId ?? '',
WaffoCurrency: settings.WaffoCurrency ?? 'USD',
WaffoUnitPrice: settings.WaffoUnitPrice ?? 1,
WaffoMinTopUp: settings.WaffoMinTopUp ?? 1,
WaffoNotifyUrl: settings.WaffoNotifyUrl ?? '',
WaffoReturnUrl: settings.WaffoReturnUrl ?? '',
WaffoPayMethods: settings.WaffoPayMethods ?? '[]',
}}
waffoPancakeDefaultValues={{
WaffoPancakeEnabled: settings.WaffoPancakeEnabled ?? false,
WaffoPancakeSandbox: settings.WaffoPancakeSandbox ?? false,
WaffoPancakeMerchantID: settings.WaffoPancakeMerchantID ?? '',
WaffoPancakePrivateKey: settings.WaffoPancakePrivateKey ?? '',
WaffoPancakeWebhookPublicKey:
settings.WaffoPancakeWebhookPublicKey ?? '',
WaffoPancakeWebhookTestKey:
settings.WaffoPancakeWebhookTestKey ?? '',
WaffoPancakeStoreID: settings.WaffoPancakeStoreID ?? '',
WaffoPancakeProductID: settings.WaffoPancakeProductID ?? '',
WaffoPancakeReturnURL: settings.WaffoPancakeReturnURL ?? '',
WaffoPancakeCurrency: settings.WaffoPancakeCurrency ?? 'USD',
WaffoPancakeUnitPrice: settings.WaffoPancakeUnitPrice ?? 1,
WaffoPancakeMinTopUp: settings.WaffoPancakeMinTopUp ?? 1,
}}
/>
),
},
{
id: 'checkin',
titleKey: 'Check-in Rewards',
descriptionKey: 'Configure daily check-in rewards for users',
build: (settings: BillingSettings) => (
<CheckinSettingsSection
defaultValues={{
enabled: settings['checkin_setting.enabled'],
minQuota: settings['checkin_setting.min_quota'],
maxQuota: settings['checkin_setting.max_quota'],
}}
/>
),
},
] as const
export type BillingSectionId = (typeof BILLING_SECTIONS)[number]['id']
const billingRegistry = createSectionRegistry<BillingSectionId, BillingSettings>(
{
sections: BILLING_SECTIONS,
defaultSection: 'quota',
basePath: '/system-settings/billing',
urlStyle: 'path',
}
)
export const BILLING_SECTION_IDS = billingRegistry.sectionIds
export const BILLING_DEFAULT_SECTION = billingRegistry.defaultSection
export const getBillingSectionNavItems = billingRegistry.getSectionNavItems
export const getBillingSectionContent = billingRegistry.getSectionContent