feat(wallet): 钱包系统替代配额系统,新增支付与退款机制

- 新增钱包余额管理、充值、扣费、退款完整流程
- 新增支付网关抽象层(支持手动/支付宝/微信)
- 用量计费从配额系统迁移到钱包余额扣费
- 新增管理员钱包管理与支付订单管理页面
- 新增用户钱包中心页面
- 移除独立 Key 锁定机制,统一由钱包余额控制
- 新增相关 API 路由、序列化器与数据库迁移
- 新增钱包、支付、退款相关测试
This commit is contained in:
LewisPen
2026-03-08 00:05:48 +08:00
committed by fawney19
parent 9cdcce1b5f
commit 783f654953
108 changed files with 13152 additions and 3372 deletions
@@ -18,19 +18,19 @@
for="default-quota"
class="block text-sm font-medium"
>
默认用户配额(美元)
默认用户初始赠款(美元)
</Label>
<Input
id="default-quota"
:model-value="defaultUserQuotaUsd"
:model-value="defaultUserInitialGiftUsd"
type="number"
step="0.01"
placeholder="10.00"
class="mt-1"
@update:model-value="$emit('update:defaultUserQuotaUsd', Number($event))"
@update:model-value="$emit('update:defaultUserInitialGiftUsd', Number($event))"
/>
<p class="mt-1 text-xs text-muted-foreground">
新用户注册时的默认配额
新用户注册时的默认初始赠款
</p>
</div>
@@ -128,7 +128,7 @@ import Checkbox from '@/components/ui/checkbox.vue'
import { CardSection } from '@/components/layout'
defineProps<{
defaultUserQuotaUsd: number
defaultUserInitialGiftUsd: number
rateLimitPerMinute: number
enableRegistration: boolean
autoDeleteExpiredKeys: boolean
@@ -139,7 +139,7 @@ defineProps<{
defineEmits<{
save: []
'update:defaultUserQuotaUsd': [value: number]
'update:defaultUserInitialGiftUsd': [value: number]
'update:rateLimitPerMinute': [value: number]
'update:enableRegistration': [value: boolean]
'update:autoDeleteExpiredKeys': [value: boolean]
@@ -14,9 +14,7 @@
? 'border-primary/30 bg-primary/[0.02] shadow-sm shadow-primary/5'
: 'border-border bg-card hover:border-border/80'"
>
<!-- 主行 -->
<div class="flex items-center gap-4 p-4">
<!-- 左侧:开关 -->
<div class="shrink-0">
<Switch
:id="`enable-${task.id}`"
@@ -25,7 +23,6 @@
/>
</div>
<!-- 中间:图标、标题、描述 -->
<div class="flex items-center gap-3 flex-1 min-w-0">
<div
class="w-9 h-9 rounded-lg flex items-center justify-center shrink-0 transition-colors duration-300"
@@ -48,7 +45,6 @@
</div>
</div>
<!-- 右侧:时间选择器 + 保存按钮 -->
<div
v-if="task.enabled && task.hasTimeConfig"
class="flex items-center gap-2 shrink-0"
@@ -118,123 +114,6 @@
</template>
</div>
</div>
<!-- 额外配置区域(仅用户配额重置任务有) -->
<div
v-if="task.id === 'user-quota-reset' && task.enabled"
class="px-4 pb-4 pt-0"
>
<div class="flex items-center gap-3 p-3 rounded-lg bg-muted/30 border border-border/50">
<div class="flex items-center gap-2 text-sm">
<span class="text-muted-foreground">重置周期</span>
<div class="flex items-center gap-1.5">
<span class="text-muted-foreground">每</span>
<Input
:model-value="quotaResetIntervalDays"
type="number"
min="1"
step="1"
class="w-14 h-7 text-xs text-center px-2"
@update:model-value="$emit('update:quotaResetIntervalDays', Number($event))"
/>
<span class="text-muted-foreground">天</span>
</div>
</div>
</div>
<p class="text-[11px] text-muted-foreground mt-2 ml-1">
滚动计算:距离上次成功执行满 N 天后再次执行
</p>
</div>
<!-- 独立密钥额度重置额外配置 -->
<div
v-if="task.id === 'standalone-key-quota-reset' && task.enabled"
class="px-4 pb-4 pt-0 space-y-3"
>
<!-- 重置周期 -->
<div class="flex items-center gap-3 p-3 rounded-lg bg-muted/30 border border-border/50">
<div class="flex items-center gap-2 text-sm">
<span class="text-muted-foreground">重置周期</span>
<div class="flex items-center gap-1.5">
<span class="text-muted-foreground">每</span>
<Input
:model-value="standaloneKeyResetIntervalDays"
type="number"
min="1"
step="1"
class="w-14 h-7 text-xs text-center px-2"
@update:model-value="$emit('update:standaloneKeyResetIntervalDays', Number($event))"
/>
<span class="text-muted-foreground">天</span>
</div>
</div>
</div>
<!-- 重置范围 -->
<div class="p-3 rounded-lg bg-muted/30 border border-border/50 space-y-3">
<div class="flex items-center gap-2 text-sm">
<span class="text-muted-foreground">重置范围</span>
<Select
:model-value="standaloneKeyResetMode"
@update:model-value="$emit('update:standaloneKeyResetMode', $event)"
>
<SelectTrigger class="w-32 h-7 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">
全部独立密钥
</SelectItem>
<SelectItem value="selected">
指定密钥
</SelectItem>
</SelectContent>
</Select>
</div>
<!-- 密钥多选列表 -->
<div
v-if="standaloneKeyResetMode === 'selected'"
class="space-y-2"
>
<div class="text-xs text-muted-foreground">
选择需要重置的密钥:
</div>
<div
v-if="standaloneKeys.length === 0"
class="text-xs text-muted-foreground/60 py-2"
>
暂无独立密钥
</div>
<div
v-else
class="max-h-48 overflow-y-auto space-y-1"
>
<label
v-for="key in standaloneKeys"
:key="key.id"
class="flex items-center gap-2 p-2 rounded hover:bg-muted/50 cursor-pointer text-xs"
>
<Checkbox
:model-value="standaloneKeyResetKeyIds.includes(key.id)"
@update:model-value="$emit('toggleStandaloneKeyResetKeyId', key.id)"
/>
<span class="truncate">{{ key.name || key.key_display || 'sk-****' }}</span>
<span
v-if="key.current_balance_usd != null"
class="text-muted-foreground ml-auto shrink-0"
>
${{ key.current_balance_usd.toFixed(2) }}
</span>
</label>
</div>
</div>
</div>
<p class="text-[11px] text-muted-foreground ml-1">
滚动计算:距离上次成功执行满 N 天后再次执行
</p>
</div>
</div>
</template>
</div>
@@ -244,9 +123,7 @@
<script setup lang="ts">
import { Clock, Check, Loader2, X } from 'lucide-vue-next'
import Button from '@/components/ui/button.vue'
import Input from '@/components/ui/input.vue'
import Switch from '@/components/ui/switch.vue'
import Checkbox from '@/components/ui/checkbox.vue'
import Select from '@/components/ui/select.vue'
import SelectTrigger from '@/components/ui/select-trigger.vue'
import SelectValue from '@/components/ui/select-value.vue'
@@ -272,26 +149,7 @@ interface ScheduledTask {
onCancel: () => void
}
interface StandaloneKeyOption {
id: string
name?: string
key_display?: string
current_balance_usd?: number | null
}
defineProps<{
scheduledTasks: ScheduledTask[]
quotaResetIntervalDays: number
standaloneKeyResetIntervalDays: number
standaloneKeyResetMode: string
standaloneKeyResetKeyIds: string[]
standaloneKeys: StandaloneKeyOption[]
}>()
defineEmits<{
'update:quotaResetIntervalDays': [value: number]
'update:standaloneKeyResetIntervalDays': [value: number]
'update:standaloneKeyResetMode': [value: string]
'toggleStandaloneKeyResetKeyId': [keyId: string]
}>()
</script>
@@ -1,5 +1,5 @@
import { ref, computed, type Ref } from 'vue'
import { CalendarCheck, RotateCcw, RefreshCw, KeyRound } from 'lucide-vue-next'
import { CalendarCheck, RefreshCw } from 'lucide-vue-next'
import { useToast } from '@/composables/useToast'
import { adminApi } from '@/api/admin'
import { log } from '@/utils/logger'
@@ -9,25 +9,13 @@ export function useScheduledTasks(systemConfig: Ref<SystemConfig>) {
const { success, error } = useToast()
const checkinConfigLoading = ref(false)
const quotaResetConfigLoading = ref(false)
const standaloneKeyResetConfigLoading = ref(false)
// 签到时间的原始值(用于回滚)
const previousCheckinTime = ref('')
// 用户配额重置时间的原始值
const previousUserQuotaResetTime = ref('')
const previousUserQuotaResetIntervalDays = ref(1)
// 独立密钥额度重置的原始值
const previousStandaloneKeyResetTime = ref('')
const previousStandaloneKeyResetIntervalDays = ref(1)
// 初始化原始值(在配置加载完成后调用)
function initPreviousValues() {
previousCheckinTime.value = systemConfig.value.provider_checkin_time
previousUserQuotaResetTime.value = systemConfig.value.user_quota_reset_time
previousUserQuotaResetIntervalDays.value = systemConfig.value.user_quota_reset_interval_days
previousStandaloneKeyResetTime.value = systemConfig.value.standalone_key_quota_reset_time
previousStandaloneKeyResetIntervalDays.value = systemConfig.value.standalone_key_quota_reset_interval_days
}
// 签到时间
@@ -51,70 +39,6 @@ export function useScheduledTasks(systemConfig: Ref<SystemConfig>) {
return systemConfig.value.provider_checkin_time !== previousCheckinTime.value
})
// 用户配额重置时间
const userQuotaResetHour = computed(() => {
const time = systemConfig.value.user_quota_reset_time
if (!time || !time.includes(':')) return '05'
return time.split(':')[0]
})
const userQuotaResetMinute = computed(() => {
const time = systemConfig.value.user_quota_reset_time
if (!time || !time.includes(':')) return '00'
return time.split(':')[1]
})
function updateUserQuotaResetTime(hour: string, minute: string) {
systemConfig.value.user_quota_reset_time = `${hour}:${minute}`
}
const hasUserQuotaResetTimeChanged = computed(() => {
return systemConfig.value.user_quota_reset_time !== previousUserQuotaResetTime.value
})
const hasUserQuotaResetIntervalChanged = computed(() => {
return (
systemConfig.value.user_quota_reset_interval_days !==
previousUserQuotaResetIntervalDays.value
)
})
const hasQuotaResetConfigChanged = computed(() => {
return hasUserQuotaResetTimeChanged.value || hasUserQuotaResetIntervalChanged.value
})
// 独立密钥额度重置时间
const standaloneKeyResetHour = computed(() => {
const time = systemConfig.value.standalone_key_quota_reset_time
if (!time || !time.includes(':')) return '05'
return time.split(':')[0]
})
const standaloneKeyResetMinute = computed(() => {
const time = systemConfig.value.standalone_key_quota_reset_time
if (!time || !time.includes(':')) return '00'
return time.split(':')[1]
})
function updateStandaloneKeyResetTime(hour: string, minute: string) {
systemConfig.value.standalone_key_quota_reset_time = `${hour}:${minute}`
}
const hasStandaloneKeyResetTimeChanged = computed(() => {
return systemConfig.value.standalone_key_quota_reset_time !== previousStandaloneKeyResetTime.value
})
const hasStandaloneKeyResetIntervalChanged = computed(() => {
return (
systemConfig.value.standalone_key_quota_reset_interval_days !==
previousStandaloneKeyResetIntervalDays.value
)
})
const hasStandaloneKeyResetConfigChanged = computed(() => {
return hasStandaloneKeyResetTimeChanged.value || hasStandaloneKeyResetIntervalChanged.value
})
// Toggle handlers
async function handleProviderCheckinToggle(enabled: boolean) {
const previousValue = systemConfig.value.enable_provider_checkin
@@ -133,23 +57,6 @@ export function useScheduledTasks(systemConfig: Ref<SystemConfig>) {
}
}
async function handleUserQuotaResetToggle(enabled: boolean) {
const previousValue = systemConfig.value.enable_user_quota_reset
systemConfig.value.enable_user_quota_reset = enabled
try {
await adminApi.updateSystemConfig(
'enable_user_quota_reset',
enabled,
'是否启用用户配额自动重置任务'
)
success(enabled ? '已启用用户配额自动重置' : '已禁用用户配额自动重置')
} catch (err) {
error('保存配置失败')
log.error('保存用户配额自动重置配置失败:', err)
systemConfig.value.enable_user_quota_reset = previousValue
}
}
async function handleOAuthTokenRefreshToggle(enabled: boolean) {
const previousValue = systemConfig.value.enable_oauth_token_refresh
systemConfig.value.enable_oauth_token_refresh = enabled
@@ -167,38 +74,11 @@ export function useScheduledTasks(systemConfig: Ref<SystemConfig>) {
}
}
async function handleStandaloneKeyResetToggle(enabled: boolean) {
const previousValue = systemConfig.value.enable_standalone_key_quota_reset
systemConfig.value.enable_standalone_key_quota_reset = enabled
try {
await adminApi.updateSystemConfig(
'enable_standalone_key_quota_reset',
enabled,
'是否启用独立密钥额度自动重置任务'
)
success(enabled ? '已启用独立密钥额度自动重置' : '已禁用独立密钥额度自动重置')
} catch (err) {
error('保存配置失败')
log.error('保存独立密钥额度自动重置配置失败:', err)
systemConfig.value.enable_standalone_key_quota_reset = previousValue
}
}
// Cancel handlers
function handleCheckinTimeCancel() {
systemConfig.value.provider_checkin_time = previousCheckinTime.value
}
function handleQuotaResetConfigCancel() {
systemConfig.value.user_quota_reset_time = previousUserQuotaResetTime.value
systemConfig.value.user_quota_reset_interval_days = previousUserQuotaResetIntervalDays.value
}
function handleStandaloneKeyResetConfigCancel() {
systemConfig.value.standalone_key_quota_reset_time = previousStandaloneKeyResetTime.value
systemConfig.value.standalone_key_quota_reset_interval_days = previousStandaloneKeyResetIntervalDays.value
}
// Save handlers
async function handleCheckinTimeSave() {
const newTime = systemConfig.value.provider_checkin_time
@@ -224,171 +104,6 @@ export function useScheduledTasks(systemConfig: Ref<SystemConfig>) {
}
}
async function handleQuotaResetConfigSave() {
const configItems: Array<{
key: string
value: unknown
description: string
onSuccess: () => void
}> = []
if (hasUserQuotaResetTimeChanged.value) {
const newTime = systemConfig.value.user_quota_reset_time
if (!newTime || !/^\d{2}:\d{2}$/.test(newTime)) {
error('请输入有效的时间格式 (HH:MM)')
return
}
configItems.push({
key: 'user_quota_reset_time',
value: newTime,
description: '用户配额自动重置执行时间(HH:MM 格式)',
onSuccess: () => {
previousUserQuotaResetTime.value = newTime
},
})
}
if (hasUserQuotaResetIntervalChanged.value) {
let intervalDays = Number(systemConfig.value.user_quota_reset_interval_days)
if (!Number.isFinite(intervalDays) || intervalDays < 1) intervalDays = 1
intervalDays = Math.trunc(intervalDays)
systemConfig.value.user_quota_reset_interval_days = intervalDays
configItems.push({
key: 'user_quota_reset_interval_days',
value: intervalDays,
description: '用户配额重置周期(天数),滚动计算',
onSuccess: () => {
previousUserQuotaResetIntervalDays.value = intervalDays
},
})
}
if (configItems.length === 0) return
quotaResetConfigLoading.value = true
const failedKeys: string[] = []
try {
for (const item of configItems) {
try {
await adminApi.updateSystemConfig(item.key, item.value, item.description)
item.onSuccess()
} catch (err) {
failedKeys.push(item.key)
log.error(`保存配额重置配置失败: ${item.key}`, err)
}
}
if (failedKeys.length > 0) {
error(`部分配置保存失败: ${failedKeys.join(', ')}`)
return
}
success('配额重置配置已保存')
} finally {
quotaResetConfigLoading.value = false
}
}
async function handleStandaloneKeyResetConfigSave() {
const configItems: Array<{
key: string
value: unknown
description: string
onSuccess: () => void
}> = []
if (hasStandaloneKeyResetTimeChanged.value) {
const newTime = systemConfig.value.standalone_key_quota_reset_time
if (!newTime || !/^\d{2}:\d{2}$/.test(newTime)) {
error('请输入有效的时间格式 (HH:MM)')
return
}
configItems.push({
key: 'standalone_key_quota_reset_time',
value: newTime,
description: '独立密钥额度自动重置执行时间(HH:MM 格式)',
onSuccess: () => {
previousStandaloneKeyResetTime.value = newTime
},
})
}
if (hasStandaloneKeyResetIntervalChanged.value) {
let intervalDays = Number(systemConfig.value.standalone_key_quota_reset_interval_days)
if (!Number.isFinite(intervalDays) || intervalDays < 1) intervalDays = 1
intervalDays = Math.trunc(intervalDays)
systemConfig.value.standalone_key_quota_reset_interval_days = intervalDays
configItems.push({
key: 'standalone_key_quota_reset_interval_days',
value: intervalDays,
description: '独立密钥额度重置周期(天数),滚动计算',
onSuccess: () => {
previousStandaloneKeyResetIntervalDays.value = intervalDays
},
})
}
if (configItems.length === 0) return
standaloneKeyResetConfigLoading.value = true
const failedKeys: string[] = []
try {
for (const item of configItems) {
try {
await adminApi.updateSystemConfig(item.key, item.value, item.description)
item.onSuccess()
} catch (err) {
failedKeys.push(item.key)
log.error(`保存独立密钥额度重置配置失败: ${item.key}`, err)
}
}
if (failedKeys.length > 0) {
error(`部分配置保存失败: ${failedKeys.join(', ')}`)
return
}
success('独立密钥额度重置配置已保存')
} finally {
standaloneKeyResetConfigLoading.value = false
}
}
// 保存独立密钥额度重置模式和选中密钥
async function saveStandaloneKeyResetMode(mode: string) {
try {
await adminApi.updateSystemConfig(
'standalone_key_quota_reset_mode',
mode,
'独立密钥额度重置模式'
)
success('重置模式已保存')
} catch (err) {
error('保存重置模式失败')
log.error('保存独立密钥额度重置模式失败:', err)
}
}
async function saveStandaloneKeyResetKeyIds(keyIds: string[]) {
try {
await adminApi.updateSystemConfig(
'standalone_key_quota_reset_key_ids',
keyIds,
'独立密钥额度重置指定的密钥 ID 列表'
)
success('已保存选中密钥')
} catch (err) {
error('保存选中密钥失败')
log.error('保存独立密钥额度重置密钥列表失败:', err)
}
}
// 定时任务配置列表
const scheduledTasks = computed(() => [
{
@@ -407,22 +122,6 @@ export function useScheduledTasks(systemConfig: Ref<SystemConfig>) {
onSave: handleCheckinTimeSave,
onCancel: handleCheckinTimeCancel,
},
{
id: 'user-quota-reset',
icon: RotateCcw,
title: '用户配额自动重置',
description: '定时将用户已使用配额重置为零',
enabled: systemConfig.value.enable_user_quota_reset,
hasTimeConfig: true,
hour: userQuotaResetHour.value,
minute: userQuotaResetMinute.value,
updateTime: updateUserQuotaResetTime,
hasChanges: hasQuotaResetConfigChanged.value,
loading: quotaResetConfigLoading.value,
onToggle: handleUserQuotaResetToggle,
onSave: handleQuotaResetConfigSave,
onCancel: handleQuotaResetConfigCancel,
},
{
id: 'oauth-token-refresh',
icon: RefreshCw,
@@ -439,31 +138,11 @@ export function useScheduledTasks(systemConfig: Ref<SystemConfig>) {
onSave: () => {},
onCancel: () => {},
},
{
id: 'standalone-key-quota-reset',
icon: KeyRound,
title: '独立密钥额度自动重置',
description: '定时将独立密钥已使用额度重置为零',
enabled: systemConfig.value.enable_standalone_key_quota_reset,
hasTimeConfig: true,
hour: standaloneKeyResetHour.value,
minute: standaloneKeyResetMinute.value,
updateTime: updateStandaloneKeyResetTime,
hasChanges: hasStandaloneKeyResetConfigChanged.value,
loading: standaloneKeyResetConfigLoading.value,
onToggle: handleStandaloneKeyResetToggle,
onSave: handleStandaloneKeyResetConfigSave,
onCancel: handleStandaloneKeyResetConfigCancel,
},
])
return {
checkinConfigLoading,
quotaResetConfigLoading,
standaloneKeyResetConfigLoading,
scheduledTasks,
initPreviousValues,
saveStandaloneKeyResetMode,
saveStandaloneKeyResetKeyIds,
}
}
@@ -11,7 +11,7 @@ export interface SystemConfig {
// 网络代理
system_proxy_node_id: string | null
// 基础配置
default_user_quota_usd: number
default_user_initial_gift_usd: number
rate_limit_per_minute: number
enable_registration: boolean
// 独立余额 Key 过期管理
@@ -34,16 +34,7 @@ export interface SystemConfig {
// 定时任务
enable_provider_checkin: boolean
provider_checkin_time: string
enable_user_quota_reset: boolean
user_quota_reset_time: string
user_quota_reset_interval_days: number
enable_oauth_token_refresh: boolean
// 独立密钥额度重置
enable_standalone_key_quota_reset: boolean
standalone_key_quota_reset_time: string
standalone_key_quota_reset_interval_days: number
standalone_key_quota_reset_mode: string
standalone_key_quota_reset_key_ids: string[]
}
const CONFIG_KEYS = [
@@ -53,7 +44,7 @@ const CONFIG_KEYS = [
// 网络代理
'system_proxy_node_id',
// 基础配置
'default_user_quota_usd',
'default_user_initial_gift_usd',
'rate_limit_per_minute',
'enable_registration',
// 独立余额 Key 过期管理
@@ -76,16 +67,7 @@ const CONFIG_KEYS = [
// 定时任务
'enable_provider_checkin',
'provider_checkin_time',
'enable_user_quota_reset',
'user_quota_reset_time',
'user_quota_reset_interval_days',
'enable_oauth_token_refresh',
// 独立密钥额度重置
'enable_standalone_key_quota_reset',
'standalone_key_quota_reset_time',
'standalone_key_quota_reset_interval_days',
'standalone_key_quota_reset_mode',
'standalone_key_quota_reset_key_ids',
]
function createDefaultConfig(): SystemConfig {
@@ -96,7 +78,7 @@ function createDefaultConfig(): SystemConfig {
// 网络代理
system_proxy_node_id: null,
// 基础配置
default_user_quota_usd: 10.0,
default_user_initial_gift_usd: 10.0,
rate_limit_per_minute: 0,
enable_registration: false,
// 独立余额 Key 过期管理
@@ -119,16 +101,7 @@ function createDefaultConfig(): SystemConfig {
// 定时任务
enable_provider_checkin: true,
provider_checkin_time: '01:05',
enable_user_quota_reset: false,
user_quota_reset_time: '05:00',
user_quota_reset_interval_days: 1,
enable_oauth_token_refresh: true,
// 独立密钥额度重置
enable_standalone_key_quota_reset: false,
standalone_key_quota_reset_time: '05:00',
standalone_key_quota_reset_interval_days: 1,
standalone_key_quota_reset_mode: 'all',
standalone_key_quota_reset_key_ids: [],
}
}
@@ -164,7 +137,7 @@ export function useSystemConfig() {
const hasBasicConfigChanges = computed(() => {
if (!originalConfig.value) return false
return (
systemConfig.value.default_user_quota_usd !== originalConfig.value.default_user_quota_usd ||
systemConfig.value.default_user_initial_gift_usd !== originalConfig.value.default_user_initial_gift_usd ||
systemConfig.value.rate_limit_per_minute !== originalConfig.value.rate_limit_per_minute ||
systemConfig.value.enable_registration !== originalConfig.value.enable_registration ||
systemConfig.value.auto_delete_expired_keys !== originalConfig.value.auto_delete_expired_keys ||
@@ -234,7 +207,7 @@ export function useSystemConfig() {
; (systemConfig.value as Record<string, unknown>)[key] = response.value
}
} catch {
// 配置不存在时使用默认值,无需处理
// 单个配置项加载失败时忽略,使用默认值
}
}
originalConfig.value = JSON.parse(JSON.stringify(systemConfig.value))
@@ -309,9 +282,9 @@ export function useSystemConfig() {
try {
const configItems = [
{
key: 'default_user_quota_usd',
value: systemConfig.value.default_user_quota_usd,
description: '默认用户配额(美元)',
key: 'default_user_initial_gift_usd',
value: systemConfig.value.default_user_initial_gift_usd,
description: '默认用户初始赠款(美元)',
},
{
key: 'rate_limit_per_minute',
@@ -341,7 +314,7 @@ export function useSystemConfig() {
)
)
if (originalConfig.value) {
originalConfig.value.default_user_quota_usd = systemConfig.value.default_user_quota_usd
originalConfig.value.default_user_initial_gift_usd = systemConfig.value.default_user_initial_gift_usd
originalConfig.value.rate_limit_per_minute = systemConfig.value.rate_limit_per_minute
originalConfig.value.enable_registration = systemConfig.value.enable_registration
originalConfig.value.auto_delete_expired_keys =