feat: 新增维护模式 + 修复注册关闭页面标题显示问题

- 修复注册关闭时标题“创建账号”和副标题仍显示的问题,三态互斥(维护中 > 关闭注册 > 正常)
- 新增 maintenance.enabled 站点设置,默认关闭,仅 Owner 可见可调节
- 维护中间件:全局拦截,维护期间仅站长可访问,白名单放行登录相关路径
- 登录服务:维护期间仅 Owner 角色可登录,Register 优先检查维护状态
- Nav 模板新增维护通知条(黄色横幅)
- 管理后台站点设置新增“启用维护模式”开关
- BuildPageData 自动注入 IsMaintenance 到所有页面模板
This commit is contained in:
2026-05-30 20:54:23 +08:00
parent fb2eff5f23
commit 6229c81f6e
16 changed files with 186 additions and 8 deletions

View File

@ -1,7 +1,7 @@
{{template "admin/layout/base.html" .}}
<div class="page-header">
<h1>站点设置</h1>
<p class="page-desc">管理站点基本配置、审核开关与注册策略</p>
<p class="page-desc">管理站点基本配置、维护开关、审核开关与注册策略</p>
</div>
<!-- 基本设置 -->
@ -31,6 +31,23 @@
</div>
</div>
<!-- 维护设置 -->
<div class="settings-section">
<div class="section-title">维护设置</div>
<div class="section-body">
<div class="setting-item">
<div class="setting-info">
<span class="setting-label">启用维护模式</span>
<span class="setting-desc">开启后仅站长可登录和访问,其他用户将看到维护提示</span>
</div>
<label class="toggle-switch">
<input type="checkbox" id="maintenance-enabled" data-key="maintenance.enabled">
<span class="toggle-slider"></span>
</label>
</div>
</div>
</div>
<!-- 注册设置 -->
<div class="settings-section">
<div class="section-title">注册设置</div>

View File

@ -7,6 +7,7 @@
'use strict';
const TOGGLE_KEYS = [
{ id: 'maintenance-enabled', key: 'maintenance.enabled' },
{ id: 'registration-enabled', key: 'registration.enabled' },
{ id: 'audit-enabled', key: 'audit.enabled' },
{ id: 'audit-username', key: 'audit.username_audit' },
@ -17,6 +18,7 @@
// 已有专属 UI 的设置 key不在"其他设置"中重复显示
var DEDICATED_KEYS = {
'site.framework': true, 'site.copyright_start': true,
'maintenance.enabled': true,
'registration.enabled': true,
'audit.enabled': true, 'audit.username_audit': true, 'audit.avatar_audit': true, 'audit.bio_audit': true
};
@ -34,8 +36,8 @@
var el = document.getElementById(t.id);
if (!el) return;
if (t.id === 'registration-enabled') {
el.checked = allSettings['registration.enabled'] !== 'false';
if (t.id === 'maintenance-enabled' || t.id === 'registration-enabled') {
el.checked = allSettings[t.key] !== 'false';
} else {
el.checked = audit[t.key.split('.')[1]] === true;
}