From c9bbb25154d5bed00e3ffe91261b6ddb7ec7f93a Mon Sep 17 00:00:00 2001 From: xuans Date: Mon, 31 Aug 2026 00:52:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84Web=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/httpapi/settings_api.go | 3 +- backend/internal/httpapi/settings_api_test.go | 51 +++++++++++++++++++ frontend/src/views/Dashboard/Dashboard.css | 21 ++++++++ frontend/src/views/Dashboard/Dashboard.vue | 20 ++++++-- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/backend/internal/httpapi/settings_api.go b/backend/internal/httpapi/settings_api.go index 8b171c0..24b6bd5 100644 --- a/backend/internal/httpapi/settings_api.go +++ b/backend/internal/httpapi/settings_api.go @@ -218,6 +218,7 @@ func (s *Server) updateSettings(c *gin.Context) { previous.Server.Port != updated.Server.Port || previous.Server.HTTPSMode != updated.Server.HTTPSMode configRestartRequired := listenerRestartRequired || + previous.Web.Enabled != updated.Web.Enabled || previous.Paths.Certificate != updated.Paths.Certificate || !reflect.DeepEqual(nonRenewalACMEConfig(previous.ACME), nonRenewalACMEConfig(updated.ACME)) || !reflect.DeepEqual(previous.DNS, updated.DNS) || @@ -229,7 +230,7 @@ func (s *Server) updateSettings(c *gin.Context) { if listenerRestartRequired { message = "设置已保存;服务监听地址、端口或 HTTPS 模式已变更,请重启 Scert 服务" } else if configRestartRequired { - message = "设置已保存;部分证书、DNS 或通知运行配置已变更,请重启 Scert 服务" + message = "设置已保存;Web 页面、证书、DNS 或通知运行配置已变更,请重启 Scert 服务" } s.config = updated s.configMu.Unlock() diff --git a/backend/internal/httpapi/settings_api_test.go b/backend/internal/httpapi/settings_api_test.go index e1d6e97..4738d95 100644 --- a/backend/internal/httpapi/settings_api_test.go +++ b/backend/internal/httpapi/settings_api_test.go @@ -128,6 +128,57 @@ func TestSettingsAPIWebAddressChangeDoesNotRequireRestart(t *testing.T) { } } +func TestSettingsAPIWebEnabledChangeRequiresRestart(t *testing.T) { + dir := t.TempDir() + cfg := config.Default(dir) + cfg.SetupReady = true + cfg.Web.Enabled = true + cfg.Web.Hostname = "scert.example.test" + cfg.DNS.VerificationState = "verified" + cfg.Admin.Username = "admin" + cfg.Admin.Email = "admin@example.test" + cfg.Admin.PasswordHash = mustTestPasswordHash(t, "Password123") + configPath := dir + "\\config\\scert.json" + if err := cfg.Save(configPath); err != nil { + t.Fatalf("保存测试配置失败:%v", err) + } + server := New(Dependencies{Config: cfg, ConfigPath: configPath}) + cookie := loginForSettingsTest(t, server) + + request := httptest.NewRequest(http.MethodPut, "/api/v1/settings", strings.NewReader(`{ + "web": {"enabled": false} + }`)) + request.Header.Set("Content-Type", "application/json") + request.AddCookie(cookie) + response := httptest.NewRecorder() + server.Handler().ServeHTTP(response, request) + if response.Code != http.StatusOK { + t.Fatalf("更新 Web 页面开关应成功,实际为 %d:%s", response.Code, response.Body.String()) + } + var payload struct { + Settings settingsView `json:"settings"` + RestartRequired bool `json:"restart_required"` + Message string `json:"message"` + } + if err := json.Unmarshal(response.Body.Bytes(), &payload); err != nil { + t.Fatalf("解析 Web 页面开关响应失败:%v", err) + } + if !payload.RestartRequired || payload.Settings.Web.Enabled { + t.Fatalf("关闭 Web 页面应要求重启并返回关闭状态:%+v", payload) + } + if !strings.Contains(payload.Message, "Web 页面") || !strings.Contains(payload.Message, "请重启 Scert 服务") { + t.Fatalf("Web 页面开关变更应明确提示重启服务:%s", payload.Message) + } + + saved, err := config.Load(configPath) + if err != nil { + t.Fatalf("读取 Web 页面开关配置失败:%v", err) + } + if saved.Web.Enabled { + t.Fatal("关闭 Web 页面后配置文件仍为开启状态") + } +} + func TestSettingsAPIReturnsAndUpdatesRenewalPolicy(t *testing.T) { dir := t.TempDir() cfg := config.Default(dir) diff --git a/frontend/src/views/Dashboard/Dashboard.css b/frontend/src/views/Dashboard/Dashboard.css index 0b3c9bd..1aec34e 100644 --- a/frontend/src/views/Dashboard/Dashboard.css +++ b/frontend/src/views/Dashboard/Dashboard.css @@ -460,6 +460,23 @@ code { .switch-field small { margin: 5px 0 0; } +.settings-web-controls { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(240px, 0.9fr); + align-items: center; + gap: 12px 18px; + margin: 4px 0 18px; + padding: 12px 14px; + border: 1px solid #d8e6f3; + border-radius: 11px; + background: #fbfdff; +} +.settings-switch-field { + margin: 0; +} +.settings-web-hint { + margin: 0; +} .server-picker { margin: 4px 0 20px; padding: 15px; @@ -1161,4 +1178,8 @@ code { .dns-verification-status { margin-left: 0; } + + .settings-web-controls { + grid-template-columns: 1fr; + } } diff --git a/frontend/src/views/Dashboard/Dashboard.vue b/frontend/src/views/Dashboard/Dashboard.vue index 94110e2..9ec0f59 100644 --- a/frontend/src/views/Dashboard/Dashboard.vue +++ b/frontend/src/views/Dashboard/Dashboard.vue @@ -437,11 +437,21 @@ const { -
- - -
-

ACME 设置

+
+ + +
+
+ +

修改此开关后需要重启 Scert 服务,新的监听状态才会生效。

+
+

ACME 设置