From 0dd1f97f7d7b8e1a9ba27bad7179e227cb178537 Mon Sep 17 00:00:00 2001 From: tbphp Date: Thu, 3 Jul 2025 19:26:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BA=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E7=BB=93=E6=9E=84=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/config/system_settings.go | 28 ++++++++++++++-------------- internal/handler/settings_handler.go | 22 ++++++++++++++++++---- internal/models/setting_info.go | 24 ++++++++++++++---------- web/vite.config.ts | 2 +- 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/internal/config/system_settings.go b/internal/config/system_settings.go index 00d5a16..02db9c5 100644 --- a/internal/config/system_settings.go +++ b/internal/config/system_settings.go @@ -18,25 +18,22 @@ import ( // 使用结构体标签作为唯一事实来源 type SystemSettings struct { // 负载均衡和重试配置 - BlacklistThreshold int `json:"blacklist_threshold" default:"1" desc:"Error count before blacklisting a key" validate:"min=0"` - MaxRetries int `json:"max_retries" default:"3" desc:"Maximum retry attempts with different keys" validate:"min=0"` + BlacklistThreshold int `json:"blacklist_threshold" default:"1" name:"黑名单阈值" category:"失败重试" desc:"一个 Key 连续失败多少次后进入黑名单" validate:"min=0"` + MaxRetries int `json:"max_retries" default:"3" name:"最大重试次数" category:"失败重试" desc:"单个请求使用不同 Key 的最大重试次数" validate:"min=0"` // 服务器超时配置 (秒) - ServerReadTimeout int `json:"server_read_timeout" default:"120" desc:"HTTP server read timeout in seconds" validate:"min=1"` - ServerWriteTimeout int `json:"server_write_timeout" default:"1800" desc:"HTTP server write timeout in seconds" validate:"min=1"` - ServerIdleTimeout int `json:"server_idle_timeout" default:"120" desc:"HTTP server idle timeout in seconds" validate:"min=1"` - ServerGracefulShutdownTimeout int `json:"server_graceful_shutdown_timeout" default:"60" desc:"Graceful shutdown timeout in seconds" validate:"min=1"` + ServerReadTimeout int `json:"server_read_timeout" default:"120" name:"读取超时" category:"服务器配置" desc:"HTTP 服务器读取超时时间(秒)" validate:"min=1"` + ServerWriteTimeout int `json:"server_write_timeout" default:"1800" name:"写入超时" category:"服务器配置" desc:"HTTP 服务器写入超时时间(秒)" validate:"min=1"` + ServerIdleTimeout int `json:"server_idle_timeout" default:"120" name:"空闲超时" category:"服务器配置" desc:"HTTP 服务器空闲超时时间(秒)" validate:"min=1"` + ServerGracefulShutdownTimeout int `json:"server_graceful_shutdown_timeout" default:"60" name:"优雅关闭超时" category:"服务器配置" desc:"服务优雅关闭的等待超时时间(秒)" validate:"min=1"` // 请求超时配置 (秒) - RequestTimeout int `json:"request_timeout" default:"30" desc:"Request timeout in seconds" validate:"min=1"` - ResponseTimeout int `json:"response_timeout" default:"30" desc:"Response timeout in seconds (TLS handshake & response header)" validate:"min=1"` - IdleConnTimeout int `json:"idle_conn_timeout" default:"120" desc:"Idle connection timeout in seconds" validate:"min=1"` - - // 性能配置 - // MaxConcurrentRequests int `json:"max_concurrent_requests" default:"100" desc:"Maximum number of concurrent requests" validate:"min=1"` + RequestTimeout int `json:"request_timeout" default:"30" name:"请求超时" category:"请求配置" desc:"请求处理的总体超时时间(秒)" validate:"min=1"` + ResponseTimeout int `json:"response_timeout" default:"30" name:"响应超时" category:"请求配置" desc:"TLS 握手和响应头的超时时间(秒)" validate:"min=1"` + IdleConnTimeout int `json:"idle_conn_timeout" default:"120" name:"空闲连接超时" category:"请求配置" desc:"空闲连接的超时时间(秒)" validate:"min=1"` // 请求日志配置(数据库日志) - RequestLogRetentionDays int `json:"request_log_retention_days" default:"30" desc:"Number of days to retain request logs in database" validate:"min=1"` + RequestLogRetentionDays int `json:"request_log_retention_days" default:"30" name:"日志保留天数" category:"日志配置" desc:"请求日志在数据库中的保留天数" validate:"min=1"` } // GenerateSettingsMetadata 使用反射从 SystemSettings 结构体动态生成元数据 @@ -54,9 +51,11 @@ func GenerateSettingsMetadata(s *SystemSettings) []models.SystemSettingInfo { continue } + nameTag := field.Tag.Get("name") descTag := field.Tag.Get("desc") defaultTag := field.Tag.Get("default") validateTag := field.Tag.Get("validate") + categoryTag := field.Tag.Get("category") var minValue *int if strings.HasPrefix(validateTag, "min=") { @@ -68,10 +67,12 @@ func GenerateSettingsMetadata(s *SystemSettings) []models.SystemSettingInfo { info := models.SystemSettingInfo{ Key: jsonTag, + Name: nameTag, Value: fieldValue.Interface(), Type: field.Type.String(), DefaultValue: defaultTag, Description: descTag, + Category: categoryTag, MinValue: minValue, } settingsInfo = append(settingsInfo, info) @@ -325,7 +326,6 @@ func (sm *SystemSettingsManager) DisplayCurrentSettings() { sm.settings.ServerIdleTimeout, sm.settings.ServerGracefulShutdownTimeout) logrus.Infof(" Request timeouts: request=%ds, response=%ds, idle_conn=%ds", sm.settings.RequestTimeout, sm.settings.ResponseTimeout, sm.settings.IdleConnTimeout) - // logrus.Infof(" Performance: max_concurrent=%d", sm.settings.MaxConcurrentRequests) logrus.Infof(" Request log retention: %d days", sm.settings.RequestLogRetentionDays) } diff --git a/internal/handler/settings_handler.go b/internal/handler/settings_handler.go index 8986447..71249da 100644 --- a/internal/handler/settings_handler.go +++ b/internal/handler/settings_handler.go @@ -2,6 +2,7 @@ package handler import ( "gpt-load/internal/config" + "gpt-load/internal/models" "gpt-load/internal/response" "github.com/gin-gonic/gin" @@ -9,15 +10,28 @@ import ( ) // GetSettings handles the GET /api/settings request. -// It retrieves all system settings and returns them with detailed information. +// It retrieves all system settings, groups them by category, and returns them. func GetSettings(c *gin.Context) { settingsManager := config.GetSystemSettingsManager() currentSettings := settingsManager.GetSettings() - - // 使用新的动态元数据生成器 settingsInfo := config.GenerateSettingsMetadata(¤tSettings) - response.Success(c, settingsInfo) + // Group settings by category + categorized := make(map[string][]models.SystemSettingInfo) + for _, s := range settingsInfo { + categorized[s.Category] = append(categorized[s.Category], s) + } + + // Create the response structure + var responseData []models.CategorizedSettings + for categoryName, settings := range categorized { + responseData = append(responseData, models.CategorizedSettings{ + CategoryName: categoryName, + Settings: settings, + }) + } + + response.Success(c, responseData) } // UpdateSettings handles the PUT /api/settings request. diff --git a/internal/models/setting_info.go b/internal/models/setting_info.go index 07e0b4b..28938ca 100644 --- a/internal/models/setting_info.go +++ b/internal/models/setting_info.go @@ -2,14 +2,18 @@ package models // SystemSettingInfo 表示系统配置的详细信息(用于API返回) type SystemSettingInfo struct { - Key string `json:"key"` - Value interface{} `json:"value"` - Type string `json:"type"` // "int", "bool", "string" - DefaultValue interface{} `json:"default_value"` - Description string `json:"description"` - Category string `json:"category"` // "timeout", "performance", "logging", etc. - Required bool `json:"required"` - MinValue *int `json:"min_value,omitempty"` - MaxValue *int `json:"max_value,omitempty"` - ValidOptions []string `json:"valid_options,omitempty"` + Key string `json:"key"` + Name string `json:"name"` + Value any `json:"value"` + Type string `json:"type"` // "int", "bool", "string" + DefaultValue any `json:"default_value"` + Description string `json:"description"` + Category string `json:"category"` + MinValue *int `json:"min_value,omitempty"` +} + +// CategorizedSettings a list of settings grouped by category +type CategorizedSettings struct { + CategoryName string `json:"category_name"` + Settings []SystemSettingInfo `json:"settings"` } diff --git a/web/vite.config.ts b/web/vite.config.ts index 5a199c3..2f88b7a 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -21,7 +21,7 @@ export default defineConfig(({ mode }) => { // 代理配置示例 proxy: { "/api": { - target: env.VITE_API_BASE_URL, + target: env.VITE_API_BASE_URL || "http://127.0.0.1:3000", changeOrigin: true, }, },