完善Web管理页面开关

This commit is contained in:
xuans 2026-08-31 00:52:40 +08:00
parent d3eb7b542f
commit c9bbb25154
4 changed files with 89 additions and 6 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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;
}
}

View File

@ -437,11 +437,21 @@ const {
<label class="field"><span>HTTPS 模式</span><select v-model="settingsForm.server.https_mode"><option value="direct">直接终止 HTTPS</option><option value="proxy">反向代理 HTTPS</option></select></label>
<label class="field"><span>证书存储路径</span><input v-model="settingsForm.paths.certificate" required /></label>
</div>
<div class="form-grid">
<label class="field"><span>管理页面域名</span><input v-model="settingsForm.web.hostname" placeholder="例如 ssl.example.com" /></label>
<label class="field"><span>管理页面公网 IP</span><input v-model="settingsForm.web.public_ip" placeholder="例如 203.0.113.10" /></label>
</div>
<h3>ACME 设置</h3>
<div class="form-grid">
<label class="field"><span>管理页面域名</span><input v-model="settingsForm.web.hostname" placeholder="例如 ssl.example.com" /></label>
<label class="field"><span>管理页面公网 IP</span><input v-model="settingsForm.web.public_ip" placeholder="例如 203.0.113.10" /></label>
</div>
<div class="settings-web-controls">
<label class="switch-field settings-switch-field">
<input v-model="settingsForm.web.enabled" type="checkbox" />
<span>
<strong>开启 Web 管理页面</strong>
<small>关闭后停止网络 Web 管理入口,桌面端本地管理功能不受影响。</small>
</span>
</label>
<p class="field-hint settings-web-hint">修改此开关后需要重启 Scert 服务,新的监听状态才会生效。</p>
</div>
<h3>ACME 设置</h3>
<div class="form-grid">
<label class="field"><span>ACME 环境</span><select v-model="settingsForm.acme.environment"><option value="staging">测试环境</option><option value="production">生产环境</option></select></label>
<label class="field"><span>自动续期阈值(天)</span><input v-model.number="settingsForm.acme.renewal_threshold_days" type="number" min="1" max="365" /></label>