From c826ac28ef61c96421f0807dbe72919743764f75 Mon Sep 17 00:00:00 2001 From: erio Date: Thu, 5 Mar 2026 22:13:56 +0800 Subject: [PATCH] refactor: extract QuotaLimitCard component for reuse in create and edit modals - Extract quota limit card/toggle UI into QuotaLimitCard.vue component - Use v-model pattern for clean parent-child data flow - Integrate into both EditAccountModal and CreateAccountModal - All apikey accounts (all platforms) now support quota limit on creation - Bump version to 0.1.90.6 --- .../components/account/CreateAccountModal.vue | 13 ++- .../components/account/EditAccountModal.vue | 69 +------------- .../src/components/account/QuotaLimitCard.vue | 92 +++++++++++++++++++ 3 files changed, 107 insertions(+), 67 deletions(-) create mode 100644 frontend/src/components/account/QuotaLimitCard.vue diff --git a/frontend/src/components/account/CreateAccountModal.vue b/frontend/src/components/account/CreateAccountModal.vue index 225b91f5..d58addb9 100644 --- a/frontend/src/components/account/CreateAccountModal.vue +++ b/frontend/src/components/account/CreateAccountModal.vue @@ -1227,6 +1227,9 @@ + + +
@@ -2337,6 +2340,7 @@ import Icon from '@/components/icons/Icon.vue' import ProxySelector from '@/components/common/ProxySelector.vue' import GroupSelector from '@/components/common/GroupSelector.vue' import ModelWhitelistSelector from '@/components/account/ModelWhitelistSelector.vue' +import QuotaLimitCard from '@/components/account/QuotaLimitCard.vue' import { applyInterceptWarmup } from '@/components/account/credentialsBuilder' import { formatDateTimeLocalInput, parseDateTimeLocalInput } from '@/utils/format' import { createStableObjectKeyResolver } from '@/utils/stableObjectKey' @@ -2460,6 +2464,7 @@ const accountCategory = ref<'oauth-based' | 'apikey'>('oauth-based') // UI selec const addMethod = ref('oauth') // For oauth-based: 'oauth' or 'setup-token' const apiKeyBaseUrl = ref('https://api.anthropic.com') const apiKeyValue = ref('') +const editQuotaLimit = ref(null) const modelMappings = ref([]) const modelRestrictionMode = ref<'whitelist' | 'mapping'>('whitelist') const allowedModels = ref([]) @@ -3120,6 +3125,7 @@ const resetForm = () => { addMethod.value = 'oauth' apiKeyBaseUrl.value = 'https://api.anthropic.com' apiKeyValue.value = '' + editQuotaLimit.value = null modelMappings.value = [] modelRestrictionMode.value = 'whitelist' allowedModels.value = [...claudeModels] // Default fill related models @@ -3533,13 +3539,18 @@ const createAccountAndFinish = async ( if (!applyTempUnschedConfig(credentials)) { return } + // Inject quota_limit for apikey accounts + let finalExtra = extra + if (type === 'apikey' && editQuotaLimit.value != null && editQuotaLimit.value > 0) { + finalExtra = { ...(extra || {}), quota_limit: editQuotaLimit.value } + } await doCreateAccount({ name: form.name, notes: form.notes, platform, type, credentials, - extra, + extra: finalExtra, proxy_id: form.proxy_id, concurrency: form.concurrency, priority: form.priority, diff --git a/frontend/src/components/account/EditAccountModal.vue b/frontend/src/components/account/EditAccountModal.vue index ebdfb3b4..6617bc33 100644 --- a/frontend/src/components/account/EditAccountModal.vue +++ b/frontend/src/components/account/EditAccountModal.vue @@ -760,61 +760,7 @@
-
-
-

{{ t('admin.accounts.quotaLimit') }}

-

- {{ t('admin.accounts.quotaLimitHint') }} -

-
- -
-
-
- -

- {{ t('admin.accounts.quotaLimitToggleHint') }} -

-
- -
- -
-
- -
- $ - -
-

{{ t('admin.accounts.quotaLimitAmountHint') }}

-
-
-
-
+
(OPENAI_WS_MODE_OF const codexCLIOnlyEnabled = ref(false) const anthropicPassthroughEnabled = ref(false) const editQuotaLimit = ref(null) -const quotaLimitEnabled = ref(false) const openAIWSModeOptions = computed(() => [ { value: OPENAI_WS_MODE_OFF, label: t('admin.accounts.openai.wsModeOff') }, // TODO: ctx_pool 选项暂时隐藏,待测试完成后恢复 @@ -1473,13 +1419,6 @@ const isOpenAIModelRestrictionDisabled = computed(() => props.account?.platform === 'openai' && openaiPassthroughEnabled.value ) -// When quota limit toggle is turned off, clear the value -watch(quotaLimitEnabled, (enabled) => { - if (!enabled) { - editQuotaLimit.value = null - } -}) - // Computed: current preset mappings based on platform const presetMappings = computed(() => getPresetMappingsByPlatform(props.account?.platform || 'anthropic')) const tempUnschedPresets = computed(() => [ @@ -1610,10 +1549,8 @@ watch( // Load quota limit for apikey accounts if (newAccount.type === 'apikey') { const quotaVal = extra?.quota_limit as number | undefined - quotaLimitEnabled.value = !!(quotaVal && quotaVal > 0) editQuotaLimit.value = (quotaVal && quotaVal > 0) ? quotaVal : null } else { - quotaLimitEnabled.value = false editQuotaLimit.value = null } @@ -2364,7 +2301,7 @@ const handleSubmit = async () => { const currentExtra = (updatePayload.extra as Record) || (props.account.extra as Record) || {} const newExtra: Record = { ...currentExtra } - if (quotaLimitEnabled.value && editQuotaLimit.value != null && editQuotaLimit.value > 0) { + if (editQuotaLimit.value != null && editQuotaLimit.value > 0) { newExtra.quota_limit = editQuotaLimit.value } else { delete newExtra.quota_limit diff --git a/frontend/src/components/account/QuotaLimitCard.vue b/frontend/src/components/account/QuotaLimitCard.vue new file mode 100644 index 00000000..1be73a25 --- /dev/null +++ b/frontend/src/components/account/QuotaLimitCard.vue @@ -0,0 +1,92 @@ + + +