fix:修复设置功能页面布尔值转为字符串的错误处理方式

This commit is contained in:
qian committed 2026-06-09 22:53:20 +08:00
1 parent 3e06f6b2f4
commit 974efb6685
10 files changed
+67 -37

No files matched your search

+35
View File
@@ -2,6 +2,7 @@ package admin
import (
"context"
"strings"
v1 "github.com/qianfree/team-api/api/admin/v1"
"github.com/qianfree/team-api/internal/logic/common"
@@ -56,12 +57,46 @@ func (s *sAdmin) UpdateSettings(ctx context.Context, req *v1.AdminSettingsUpdate
for key, val := range req.Settings {
strValues[key] = common.NormalizeSettingValue(val)
}
if err := s.validateCrossFieldSettings(ctx, req.Category, strValues); err != nil {
return nil, err
}
if err := common.Config().UpdateCategory(ctx, req.Category, strValues); err != nil {
return nil, err
}
return nil, nil
}
// validateCrossFieldSettings validates interdependent settings within a category.
func (s *sAdmin) validateCrossFieldSettings(ctx context.Context, category string, values map[string]string) error {
if category != "security" {
return nil
}
enabled, ok := values["turnstile_enabled"]
if !ok || (enabled != "true" && enabled != "1") {
return nil
}
siteKey := values["turnstile_site_key"]
secretKey := values["turnstile_secret_key"]
// If keys not in the current request, read existing values from DB
if siteKey == "" {
siteKey = common.Config().GetString(ctx, "turnstile_site_key")
}
if secretKey == "" || secretKey == "******" {
secretKey = common.Config().GetString(ctx, "turnstile_secret_key")
}
if strings.TrimSpace(siteKey) == "" || strings.TrimSpace(secretKey) == "" {
return common.NewBadRequestError("启用 Turnstile 前必须先配置 Site Key 和 Secret Key")
}
return nil
}
func isValidCategory(category string) bool {
for _, c := range common.Categories {
if c.Key == category {
@@ -12,16 +12,16 @@ const values = useFormValues()
<span class="switch-label">渠道自动探测</span>
<span class="switch-desc">定期向活跃渠道发送测试请求,检测连通性并更新健康度(会消耗少量 Token)</span>
<ASwitch
:model-value="values['channel_auto_test_enabled'] === 'true' || values['channel_auto_test_enabled'] === '1'"
@change="(v: string | number | boolean) => values['channel_auto_test_enabled'] = String(v)"
:model-value="!!values['channel_auto_test_enabled']"
@change="(v: string | number | boolean) => values['channel_auto_test_enabled'] = v"
/>
</div>
<div class="switch-row" style="margin-top: 12px">
<span class="switch-label">自动恢复探测</span>
<span class="switch-desc">定期测试已自动禁用的渠道,测试通过则恢复启用(依赖自动探测开启)</span>
<ASwitch
:model-value="values['channel_auto_test_recovery_enabled'] === 'true' || values['channel_auto_test_recovery_enabled'] === '1'"
@change="(v: string | number | boolean) => values['channel_auto_test_recovery_enabled'] = String(v)"
:model-value="!!values['channel_auto_test_recovery_enabled']"
@change="(v: string | number | boolean) => values['channel_auto_test_recovery_enabled'] = v"
/>
</div>
</div>
@@ -33,8 +33,8 @@ const values = useFormValues()
<span class="switch-label">渠道自动禁用</span>
<span class="switch-desc">连续失败达到阈值时自动禁用渠道</span>
<ASwitch
:model-value="values['channel_auto_disable_enabled'] === 'true' || values['channel_auto_disable_enabled'] === '1'"
@change="(v: string | number | boolean) => values['channel_auto_disable_enabled'] = String(v)"
:model-value="!!values['channel_auto_disable_enabled']"
@change="(v: string | number | boolean) => values['channel_auto_disable_enabled'] = v"
/>
</div>
<div class="section-grid" style="margin-top: 12px">
@@ -47,8 +47,8 @@ function set(key: string, v: number | undefined): void {
<div class="switch-row">
<span class="switch-label">启用文件保留期检查</span>
<ASwitch
:model-value="values['file_retention_enabled'] === 'true' || values['file_retention_enabled'] === '1'"
@change="(v: string | number | boolean) => values['file_retention_enabled'] = String(v)"
:model-value="!!values['file_retention_enabled']"
@change="(v: string | number | boolean) => values['file_retention_enabled'] = v"
/>
</div>
</div>
@@ -40,8 +40,8 @@ const values = useFormValues()
<span class="switch-label">启用 TLS</span>
<span class="switch-desc">587/465 端口建议开启</span>
<ASwitch
:model-value="values['email_smtp_tls'] === 'true' || values['email_smtp_tls'] === '1'"
@change="(v: string | number | boolean) => values['email_smtp_tls'] = String(v)"
:model-value="!!values['email_smtp_tls']"
@change="(v: string | number | boolean) => values['email_smtp_tls'] = v"
/>
</div>
</div>
@@ -28,16 +28,16 @@ const values = useFormValues()
<span class="switch-label">开放注册</span>
<span class="switch-desc">是否允许新用户注册</span>
<ASwitch
:model-value="values['register_enabled'] === 'true' || values['register_enabled'] === '1'"
@change="(v: string | number | boolean) => values['register_enabled'] = String(v)"
:model-value="!!values['register_enabled']"
@change="(v: string | number | boolean) => values['register_enabled'] = v"
/>
</div>
<div class="switch-row">
<span class="switch-label">注册邮箱验证</span>
<span class="switch-desc">注册时是否需要邮箱验证码,关闭时使用滑块验证</span>
<ASwitch
:model-value="values['register_email_verification'] === 'true' || values['register_email_verification'] === '1'"
@change="(v: string | number | boolean) => values['register_email_verification'] = String(v)"
:model-value="!!values['register_email_verification']"
@change="(v: string | number | boolean) => values['register_email_verification'] = v"
/>
</div>
</div>
@@ -49,8 +49,8 @@ const values = useFormValues()
<span class="switch-label">启用维护模式</span>
<span class="switch-desc">开启后控制台显示维护提示</span>
<ASwitch
:model-value="values['maintenance_mode'] === 'true' || values['maintenance_mode'] === '1'"
@change="(v: string | number | boolean) => values['maintenance_mode'] = String(v)"
:model-value="!!values['maintenance_mode']"
@change="(v: string | number | boolean) => values['maintenance_mode'] = v"
/>
</div>
<div class="section-grid" style="margin-top: 12px">
@@ -65,8 +65,8 @@ const values = useFormValues()
<span class="switch-label">全局 API 维护</span>
<span class="switch-desc">开启后 API 代理返回 503</span>
<ASwitch
:model-value="values['api_maintenance_enabled'] === 'true' || values['api_maintenance_enabled'] === '1'"
@change="(v: string | number | boolean) => values['api_maintenance_enabled'] = String(v)"
:model-value="!!values['api_maintenance_enabled']"
@change="(v: string | number | boolean) => values['api_maintenance_enabled'] = v"
/>
</div>
</div>
@@ -12,8 +12,8 @@ const values = useFormValues()
<span class="switch-label">OAuth 自动注册</span>
<span class="switch-desc">首次 OAuth 登录自动创建租户账号</span>
<ASwitch
:model-value="values['oauth_auto_register'] === 'true' || values['oauth_auto_register'] === '1'"
@change="(v: string | number | boolean) => values['oauth_auto_register'] = String(v)"
:model-value="!!values['oauth_auto_register']"
@change="(v: string | number | boolean) => values['oauth_auto_register'] = v"
/>
</div>
<div class="section-grid" style="margin-top: 12px">
@@ -30,8 +30,8 @@ const values = useFormValues()
<span class="switch-label">启用 GitHub 登录</span>
<span class="switch-desc"></span>
<ASwitch
:model-value="values['oauth_github_enabled'] === 'true' || values['oauth_github_enabled'] === '1'"
@change="(v: string | number | boolean) => values['oauth_github_enabled'] = String(v)"
:model-value="!!values['oauth_github_enabled']"
@change="(v: string | number | boolean) => values['oauth_github_enabled'] = v"
/>
</div>
<div class="section-grid" style="margin-top: 12px">
@@ -51,8 +51,8 @@ const values = useFormValues()
<span class="switch-label">启用 Google 登录</span>
<span class="switch-desc"></span>
<ASwitch
:model-value="values['oauth_google_enabled'] === 'true' || values['oauth_google_enabled'] === '1'"
@change="(v: string | number | boolean) => values['oauth_google_enabled'] = String(v)"
:model-value="!!values['oauth_google_enabled']"
@change="(v: string | number | boolean) => values['oauth_google_enabled'] = v"
/>
</div>
<div class="section-grid" style="margin-top: 12px">
@@ -65,8 +65,8 @@ function set(key: string, v: number | undefined): void {
<div class="compact-row">
<label>启用缓存</label>
<ASwitch
:model-value="values['cache_enabled'] === 'true' || values['cache_enabled'] === '1'"
@change="(v: string | number | boolean) => values['cache_enabled'] = String(v)"
:model-value="!!values['cache_enabled']"
@change="(v: string | number | boolean) => values['cache_enabled'] = v"
/>
</div>
<div class="compact-row">
@@ -107,8 +107,8 @@ function set(key: string, v: number | undefined): void {
<div class="compact-row">
<label>启用沙箱</label>
<ASwitch
:model-value="values['sandbox_enabled'] === 'true' || values['sandbox_enabled'] === '1'"
@change="(v: string | number | boolean) => values['sandbox_enabled'] = String(v)"
:model-value="!!values['sandbox_enabled']"
@change="(v: string | number | boolean) => values['sandbox_enabled'] = v"
/>
</div>
<div class="compact-row">
@@ -89,7 +89,7 @@ const values = useFormValues()
</AFormItem>
<AFormItem label="新设备登录通知">
<ASwitch
:model-value="values['new_device_notification'] !== false"
:model-value="!!values['new_device_notification']"
@change="(v: string | number | boolean) => values['new_device_notification'] = v"
/>
</AFormItem>
@@ -47,8 +47,8 @@ const values = useFormValues()
<div class="switch-row" style="margin-top: 8px">
<span class="switch-label">启用 SSL</span>
<ASwitch
:model-value="values['storage_use_ssl'] === 'true' || values['storage_use_ssl'] === '1'"
@change="(v: string | number | boolean) => values['storage_use_ssl'] = String(v)"
:model-value="!!values['storage_use_ssl']"
@change="(v: string | number | boolean) => values['storage_use_ssl'] = v"
/>
</div>
</div>
@@ -19,12 +19,7 @@ export function useSettings(category: () => string) {
const items = res.data?.data?.list || []
const vals: Record<string, any> = {}
for (const item of items) {
let val = item.value ?? item.default ?? ''
// Normalize bool values to strings for consistent switch handling
if (item.type === 'bool') {
val = String(val)
}
vals[item.key] = val
vals[item.key] = item.value ?? item.default ?? ''
}
Object.keys(formValues).forEach(k => delete formValues[k])
Object.assign(formValues, vals)