diff --git a/backend/internal/service/admin_service.go b/backend/internal/service/admin_service.go index 86824b6f..7dc8bfbd 100644 --- a/backend/internal/service/admin_service.go +++ b/backend/internal/service/admin_service.go @@ -832,7 +832,7 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn subscriptionType = SubscriptionTypeStandard } - // 限额字段:0 和 nil 都表示"无限制" + // 限额字段:nil/负数 表示"无限制",0 表示"不允许用量",正数表示具体限额 dailyLimit := normalizeLimit(input.DailyLimitUSD) weeklyLimit := normalizeLimit(input.WeeklyLimitUSD) monthlyLimit := normalizeLimit(input.MonthlyLimitUSD) @@ -944,9 +944,9 @@ func (s *adminServiceImpl) CreateGroup(ctx context.Context, input *CreateGroupIn return group, nil } -// normalizeLimit 将 0 或负数转换为 nil(表示无限制) +// normalizeLimit 将负数转换为 nil(表示无限制),0 保留(表示限额为零) func normalizeLimit(limit *float64) *float64 { - if limit == nil || *limit <= 0 { + if limit == nil || *limit < 0 { return nil } return limit @@ -1058,16 +1058,11 @@ func (s *adminServiceImpl) UpdateGroup(ctx context.Context, id int64, input *Upd if input.SubscriptionType != "" { group.SubscriptionType = input.SubscriptionType } - // 限额字段:0 和 nil 都表示"无限制",正数表示具体限额 - if input.DailyLimitUSD != nil { - group.DailyLimitUSD = normalizeLimit(input.DailyLimitUSD) - } - if input.WeeklyLimitUSD != nil { - group.WeeklyLimitUSD = normalizeLimit(input.WeeklyLimitUSD) - } - if input.MonthlyLimitUSD != nil { - group.MonthlyLimitUSD = normalizeLimit(input.MonthlyLimitUSD) - } + // 限额字段:nil/负数 表示"无限制",0 表示"不允许用量",正数表示具体限额 + // 前端始终发送这三个字段,无需 nil 守卫 + group.DailyLimitUSD = normalizeLimit(input.DailyLimitUSD) + group.WeeklyLimitUSD = normalizeLimit(input.WeeklyLimitUSD) + group.MonthlyLimitUSD = normalizeLimit(input.MonthlyLimitUSD) // 图片生成计费配置:负数表示清除(使用默认价格) if input.ImagePrice1K != nil { group.ImagePrice1K = normalizePrice(input.ImagePrice1K) diff --git a/frontend/src/views/admin/GroupsView.vue b/frontend/src/views/admin/GroupsView.vue index a78762d6..498342d0 100644 --- a/frontend/src/views/admin/GroupsView.vue +++ b/frontend/src/views/admin/GroupsView.vue @@ -2382,6 +2382,11 @@ const handleCreateGroup = async () => { sora_storage_quota_bytes: createQuotaGb ? Math.round(createQuotaGb * 1024 * 1024 * 1024) : 0, model_routing: convertRoutingRulesToApiFormat(createModelRoutingRules.value) } + // v-model.number 清空输入框时产生 "",转为 null 让后端设为无限制 + const emptyToNull = (v: any) => v === '' ? null : v + requestData.daily_limit_usd = emptyToNull(requestData.daily_limit_usd) + requestData.weekly_limit_usd = emptyToNull(requestData.weekly_limit_usd) + requestData.monthly_limit_usd = emptyToNull(requestData.monthly_limit_usd) await adminAPI.groups.create(requestData) appStore.showSuccess(t('admin.groups.groupCreated')) closeCreateModal() @@ -2465,6 +2470,11 @@ const handleUpdateGroup = async () => { : editForm.fallback_group_id_on_invalid_request, model_routing: convertRoutingRulesToApiFormat(editModelRoutingRules.value) } + // v-model.number 清空输入框时产生 "",转为 null 让后端设为无限制 + const emptyToNull = (v: any) => v === '' ? null : v + payload.daily_limit_usd = emptyToNull(payload.daily_limit_usd) + payload.weekly_limit_usd = emptyToNull(payload.weekly_limit_usd) + payload.monthly_limit_usd = emptyToNull(payload.monthly_limit_usd) await adminAPI.groups.update(editingGroup.value.id, payload) appStore.showSuccess(t('admin.groups.groupUpdated')) closeEditModal()