From 4d078a885412e0807a4d6013ff55ac4a38e19dc3 Mon Sep 17 00:00:00 2001 From: shaw Date: Mon, 5 Jan 2026 20:53:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(admin):=20=E4=BF=AE=E5=A4=8D=E9=9B=B6?= =?UTF-8?q?=E5=80=BC=E5=AD=97=E6=AE=B5=E6=97=A0=E6=B3=95=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 用户允许分组:前端发送空数组而非 null 表示"允许全部" - 账户代理:前端发送 0 而非 null 表示"无代理" - 后端 UpdateAccount/BulkUpdate 正确处理 ProxyID=0 为清除代理 --- backend/internal/repository/account_repo.go | 11 ++++++++--- backend/internal/service/admin_service.go | 7 ++++++- .../components/admin/user/UserAllowedGroupsModal.vue | 2 +- frontend/src/components/common/ProxySelector.vue | 9 +++++---- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/backend/internal/repository/account_repo.go b/backend/internal/repository/account_repo.go index 927349bf..1073ae0d 100644 --- a/backend/internal/repository/account_repo.go +++ b/backend/internal/repository/account_repo.go @@ -773,9 +773,14 @@ func (r *accountRepository) BulkUpdate(ctx context.Context, ids []int64, updates idx++ } if updates.ProxyID != nil { - setClauses = append(setClauses, "proxy_id = $"+itoa(idx)) - args = append(args, *updates.ProxyID) - idx++ + // 0 表示清除代理(前端发送 0 而不是 null 来表达清除意图) + if *updates.ProxyID == 0 { + setClauses = append(setClauses, "proxy_id = NULL") + } else { + setClauses = append(setClauses, "proxy_id = $"+itoa(idx)) + args = append(args, *updates.ProxyID) + idx++ + } } if updates.Concurrency != nil { setClauses = append(setClauses, "concurrency = $"+itoa(idx)) diff --git a/backend/internal/service/admin_service.go b/backend/internal/service/admin_service.go index f3626733..44660d62 100644 --- a/backend/internal/service/admin_service.go +++ b/backend/internal/service/admin_service.go @@ -702,7 +702,12 @@ func (s *adminServiceImpl) UpdateAccount(ctx context.Context, id int64, input *U account.Extra = input.Extra } if input.ProxyID != nil { - account.ProxyID = input.ProxyID + // 0 表示清除代理(前端发送 0 而不是 null 来表达清除意图) + if *input.ProxyID == 0 { + account.ProxyID = nil + } else { + account.ProxyID = input.ProxyID + } account.Proxy = nil // 清除关联对象,防止 GORM Save 时根据 Proxy.ID 覆盖 ProxyID } // 只在指针非 nil 时更新 Concurrency(支持设置为 0) diff --git a/frontend/src/components/admin/user/UserAllowedGroupsModal.vue b/frontend/src/components/admin/user/UserAllowedGroupsModal.vue index 669772e3..409fd835 100644 --- a/frontend/src/components/admin/user/UserAllowedGroupsModal.vue +++ b/frontend/src/components/admin/user/UserAllowedGroupsModal.vue @@ -52,7 +52,7 @@ const load = async () => { loading.value = true; try { const res = await adminAP const handleSave = async () => { if (!props.user) return; submitting.value = true try { - await adminAPI.users.update(props.user.id, { allowed_groups: selectedIds.value.length > 0 ? selectedIds.value : null }) + await adminAPI.users.update(props.user.id, { allowed_groups: selectedIds.value }) appStore.showSuccess(t('admin.users.allowedGroupsUpdated')); emit('success'); emit('close') } catch {} finally { submitting.value = false } } diff --git a/frontend/src/components/common/ProxySelector.vue b/frontend/src/components/common/ProxySelector.vue index 8a3c0c94..4616de56 100644 --- a/frontend/src/components/common/ProxySelector.vue +++ b/frontend/src/components/common/ProxySelector.vue @@ -98,11 +98,11 @@
{{ t('admin.accounts.noProxy') }} ()) const batchTesting = ref(false) const selectedProxy = computed(() => { - if (props.modelValue === null) return null + if (props.modelValue === null || props.modelValue === 0) return null return props.proxies.find((p) => p.id === props.modelValue) || null }) @@ -300,7 +300,8 @@ const toggle = () => { } const selectOption = (value: number | null) => { - emit('update:modelValue', value) + // 使用 0 表示"无代理",以便后端能正确识别清除意图 + emit('update:modelValue', value === null ? 0 : value) isOpen.value = false searchQuery.value = '' }