From 9dad194130e9c2ee4a19223540a39d70135a146c Mon Sep 17 00:00:00 2001 From: fawney19 Date: Wed, 24 Dec 2025 22:35:30 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20API=20Key=20?= =?UTF-8?q?=E8=AE=BF=E9=97=AE=E9=99=90=E5=88=B6=E5=AD=97=E6=AE=B5=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=B8=85=E9=99=A4=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 统一前端创建和更新 API Key 时的空数组处理逻辑 - 后端创建和更新接口都支持空数组转 NULL(表示不限制) - 开启自动刷新时立即刷新一次数据 --- frontend/src/views/admin/ApiKeys.vue | 14 ++++++++------ frontend/src/views/shared/Usage.vue | 1 + src/services/user/apikey.py | 19 +++++++++++++++---- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/frontend/src/views/admin/ApiKeys.vue b/frontend/src/views/admin/ApiKeys.vue index 5127899..bf07f03 100644 --- a/frontend/src/views/admin/ApiKeys.vue +++ b/frontend/src/views/admin/ApiKeys.vue @@ -1046,9 +1046,10 @@ async function handleKeyFormSubmit(data: StandaloneKeyFormData) { rate_limit: data.rate_limit, expire_days: data.never_expire ? null : (data.expire_days || null), auto_delete_on_expiry: data.auto_delete_on_expiry, - allowed_providers: data.allowed_providers.length > 0 ? data.allowed_providers : undefined, - allowed_api_formats: data.allowed_api_formats.length > 0 ? data.allowed_api_formats : undefined, - allowed_models: data.allowed_models.length > 0 ? data.allowed_models : undefined + // 空数组表示清除限制(允许全部),后端会将空数组存为 NULL + allowed_providers: data.allowed_providers, + allowed_api_formats: data.allowed_api_formats, + allowed_models: data.allowed_models } await adminApi.updateApiKey(data.id, updateData) success('API Key 更新成功') @@ -1064,9 +1065,10 @@ async function handleKeyFormSubmit(data: StandaloneKeyFormData) { rate_limit: data.rate_limit, expire_days: data.never_expire ? null : (data.expire_days || null), auto_delete_on_expiry: data.auto_delete_on_expiry, - allowed_providers: data.allowed_providers.length > 0 ? data.allowed_providers : undefined, - allowed_api_formats: data.allowed_api_formats.length > 0 ? data.allowed_api_formats : undefined, - allowed_models: data.allowed_models.length > 0 ? data.allowed_models : undefined + // 空数组表示不设置限制(允许全部),后端会将空数组存为 NULL + allowed_providers: data.allowed_providers, + allowed_api_formats: data.allowed_api_formats, + allowed_models: data.allowed_models } const response = await adminApi.createStandaloneApiKey(createData) newKeyValue.value = response.key diff --git a/frontend/src/views/shared/Usage.vue b/frontend/src/views/shared/Usage.vue index 8156743..c212d34 100644 --- a/frontend/src/views/shared/Usage.vue +++ b/frontend/src/views/shared/Usage.vue @@ -301,6 +301,7 @@ function stopGlobalAutoRefresh() { function handleAutoRefreshChange(value: boolean) { globalAutoRefresh.value = value if (value) { + refreshData() // 立即刷新一次 startGlobalAutoRefresh() } else { stopGlobalAutoRefresh() diff --git a/src/services/user/apikey.py b/src/services/user/apikey.py index 87fabc2..b03e453 100644 --- a/src/services/user/apikey.py +++ b/src/services/user/apikey.py @@ -59,14 +59,15 @@ class ApiKeyService: if expire_days: expires_at = datetime.now(timezone.utc) + timedelta(days=expire_days) + # 空数组转为 None(表示不限制) api_key = ApiKey( user_id=user_id, key_hash=key_hash, key_encrypted=key_encrypted, name=name or f"API Key {datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}", - allowed_providers=allowed_providers, - allowed_api_formats=allowed_api_formats, - allowed_models=allowed_models, + allowed_providers=allowed_providers or None, + allowed_api_formats=allowed_api_formats or None, + allowed_models=allowed_models or None, rate_limit=rate_limit, concurrent_limit=concurrent_limit, expires_at=expires_at, @@ -141,8 +142,18 @@ class ApiKeyService: "auto_delete_on_expiry", ] + # 允许显式设置为空数组/None 的字段(空数组会转为 None,表示"全部") + nullable_list_fields = {"allowed_providers", "allowed_api_formats", "allowed_models"} + for field, value in kwargs.items(): - if field in updatable_fields and value is not None: + if field not in updatable_fields: + continue + # 对于 nullable_list_fields,空数组应该转为 None(表示不限制) + if field in nullable_list_fields: + if value is not None: + # 空数组转为 None(表示允许全部) + setattr(api_key, field, value if value else None) + elif value is not None: setattr(api_key, field, value) api_key.updated_at = datetime.now(timezone.utc)