refactor: CSP nonce替代unsafe-inline, HSTS始终启用, router/api拆分, 管理后台+用户设置页拆分, DB健康降级, 时区配置, UID统一解析, CI接入
Some checks failed
CI / Lint + Build (push) Has been cancelled
Some checks failed
CI / Lint + Build (push) Has been cancelled
审计修复: - CSP: unsafe-inline移除, nonce替代; unsafe-eval保留供Vditor使用 - HSTS: 始终启用(不再依赖release模式) - Controller Exp: common.GetGinExp包装, 不再直接读context - UID解析: common.ParseUIDParam统一, follow/admin controller改用 重构: - router/api.go(198行)拆为7个域文件: auth/settings/posts/comments/reactions/social/studio - 管理后台站点设置: 单页拆为4个子页(brand/security/registration/content)+子菜单 - 前台用户设置页: 1201行拆为6个独立模板+6个独立JS文件 新增: - DB健康检测中间件(middleware/db_health.go): 5s ping+降级页面 - 时区配置: config.yaml server.timezone→time.Local初始化 - .gitea/workflows/ci.yml: strict模式CI流水线
This commit is contained in:
@ -68,7 +68,7 @@
|
||||
评论管理
|
||||
</a>
|
||||
{{if .CanManageSettings}}
|
||||
<a href="/admin/site-settings" class="sidebar-item {{if eq .CurrentPath "/admin/site-settings"}}active{{end}}">
|
||||
<a href="/admin/settings/brand" class="sidebar-item {{if or (eq .CurrentPath "/admin/site-settings") (eq .CurrentPath "/admin/settings/brand") (eq .CurrentPath "/admin/settings/security") (eq .CurrentPath "/admin/settings/registration") (eq .CurrentPath "/admin/settings/content")}}active{{end}}">
|
||||
<span class="sidebar-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span>
|
||||
站点设置
|
||||
</a>
|
||||
|
||||
6
templates/admin/html/site-settings/_menu.html
Normal file
6
templates/admin/html/site-settings/_menu.html
Normal file
@ -0,0 +1,6 @@
|
||||
<div class="settings-subnav">
|
||||
<a href="/admin/settings/brand" class="subnav-item {{if eq .ActiveSetting "brand"}}active{{end}}">品牌与合规</a>
|
||||
<a href="/admin/settings/security" class="subnav-item {{if eq .ActiveSetting "security"}}active{{end}}">安全与维护</a>
|
||||
<a href="/admin/settings/registration" class="subnav-item {{if eq .ActiveSetting "registration"}}active{{end}}">注册策略</a>
|
||||
<a href="/admin/settings/content" class="subnav-item {{if eq .ActiveSetting "content"}}active{{end}}">审核与内容</a>
|
||||
</div>
|
||||
152
templates/admin/html/site-settings/brand.html
Normal file
152
templates/admin/html/site-settings/brand.html
Normal file
@ -0,0 +1,152 @@
|
||||
{{template "admin/layout/base.html" .}}
|
||||
<div class="page-header">
|
||||
<h1>站点设置</h1>
|
||||
<p class="page-desc">管理站点基本配置和合规信息</p>
|
||||
</div>
|
||||
|
||||
{{template "admin/site-settings/_menu.html" .}}
|
||||
|
||||
<!-- 基本设置 -->
|
||||
<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>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-name" class="setting-input" placeholder="MetaLab" value="{{.SiteName}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.name" data-input="setting-site-name">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">站点标语</span>
|
||||
<span class="setting-desc">首页 Hero 区域的副标题</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-tagline" class="setting-input" placeholder="下一代开发者社区" value="{{.SiteTagline}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.tagline" data-input="setting-site-tagline">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">联系邮箱</span>
|
||||
<span class="setting-desc">申诉/联系邮箱,显示在社区准则等页面</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-email" class="setting-input" placeholder="metazone@foxmail.com" value="{{.ContactEmail}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.contact_email" data-input="setting-site-email">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">附加信息</span>
|
||||
<span class="setting-desc">页脚附加信息,留空则隐藏(如 "Framework: MetaGenesis")</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-framework" class="setting-input" placeholder="留空则不显示" value="{{.Framework}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.framework" data-input="setting-site-framework">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">版权起始年份</span>
|
||||
<span class="setting-desc">页脚版权标起始年(如 2024 → © 2024-当前年)</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-copyright" class="setting-input" placeholder="2024" value="{{.CopyrightStart}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.copyright_start" data-input="setting-site-copyright">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-operator" class="setting-input" placeholder="留空则不显示" value="{{.OperatorName}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.operator_name" data-input="setting-site-operator">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">隐私政策</span>
|
||||
<span class="setting-desc">纯手写 HTML,如 <a href="/privacy">隐私政策</a></span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-privacy" class="setting-input" placeholder="留空则不显示" value="{{.PrivacyURL}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.privacy_url" data-input="setting-site-privacy">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">服务条款</span>
|
||||
<span class="setting-desc">纯手写 HTML,如 <a href="/terms">服务条款</a></span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-terms" class="setting-input" placeholder="留空则不显示" value="{{.TermsURL}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.terms_url" data-input="setting-site-terms">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">ICP 备案</span>
|
||||
<span class="setting-desc">纯手写 HTML,如 <a href="https://beian.miit.gov.cn">京ICP备XXXX号</a></span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-icp" class="setting-input" placeholder="留空则不显示" value="{{.ICPNumber}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.icp_number" data-input="setting-site-icp">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">ICP 经营许可证</span>
|
||||
<span class="setting-desc">纯手写 HTML,留空则不显示</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-icp-license" class="setting-input" placeholder="留空则不显示" value="{{.ICPLicense}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.icp_license" data-input="setting-site-icp-license">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">公安备案</span>
|
||||
<span class="setting-desc">纯手写 HTML,留空则不显示</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-police" class="setting-input" placeholder="留空则不显示" value="{{.PoliceNumber}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.police_number" data-input="setting-site-police">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">文网文</span>
|
||||
<span class="setting-desc">纯手写 HTML,留空则不显示</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-wenwangwen" class="setting-input" placeholder="留空则不显示" value="{{.WenWangWen}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.wenwangwen" data-input="setting-site-wenwangwen">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">算法备案</span>
|
||||
<span class="setting-desc">纯手写 HTML,留空则不显示</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="text" id="setting-site-algorithm-filing" class="setting-input" placeholder="留空则不显示" value="{{.AlgorithmFiling}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="site.algorithm_filing" data-input="setting-site-algorithm-filing">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "admin/layout/footer.html" .}}
|
||||
83
templates/admin/html/site-settings/content.html
Normal file
83
templates/admin/html/site-settings/content.html
Normal file
@ -0,0 +1,83 @@
|
||||
{{template "admin/layout/base.html" .}}
|
||||
<div class="page-header">
|
||||
<h1>站点设置</h1>
|
||||
<p class="page-desc">审核配置与内容管理</p>
|
||||
</div>
|
||||
|
||||
{{template "admin/site-settings/_menu.html" .}}
|
||||
|
||||
<!-- 审核设置 -->
|
||||
<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="audit-enabled" data-key="audit.enabled">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<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="audit-username" data-key="audit.username_audit">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<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="audit-avatar" data-key="audit.avatar_audit">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<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="audit-bio" data-key="audit.bio_audit">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容管理 -->
|
||||
<div class="settings-section">
|
||||
<div class="section-title">内容管理</div>
|
||||
<div class="section-body">
|
||||
<div class="setting-item setting-item-vertical">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">社区准则</span>
|
||||
<span class="setting-desc">注册时需用户阅读并同意,支持 HTML 格式</span>
|
||||
</div>
|
||||
<div class="setting-input-block">
|
||||
<textarea id="setting-site-guidelines" class="setting-textarea" rows="12" placeholder="留空则使用默认准则文件"></textarea>
|
||||
<button class="btn btn-sm btn-primary btn-save-block" data-key="site.guidelines" data-input="setting-site-guidelines">保存准则</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 通用设置 -->
|
||||
<div class="settings-section">
|
||||
<div class="section-title">其他设置</div>
|
||||
<div class="section-body" id="general-settings">
|
||||
<div class="settings-empty" id="settings-empty">加载中...</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "admin/layout/footer.html" .}}
|
||||
55
templates/admin/html/site-settings/registration.html
Normal file
55
templates/admin/html/site-settings/registration.html
Normal file
@ -0,0 +1,55 @@
|
||||
{{template "admin/layout/base.html" .}}
|
||||
<div class="page-header">
|
||||
<h1>站点设置</h1>
|
||||
<p class="page-desc">注册策略与准则配置</p>
|
||||
</div>
|
||||
|
||||
{{template "admin/site-settings/_menu.html" .}}
|
||||
|
||||
<!-- 注册设置 -->
|
||||
<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="registration-enabled" data-key="registration.enabled">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<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="registration-show-guidelines" data-key="registration.show_guidelines">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<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="registration-force-guidelines" data-key="registration.force_guidelines">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">阅读倒计时</span>
|
||||
<span class="setting-desc">强制阅读时的倒计时秒数</span>
|
||||
</div>
|
||||
<div class="setting-input-wrap">
|
||||
<input type="number" id="setting-guidelines-timer" class="setting-input" placeholder="60" min="1" style="width:100px" value="{{.GuidelinesTimer}}">
|
||||
<button class="btn btn-sm btn-primary btn-save" data-key="registration.guidelines_timer" data-input="setting-guidelines-timer">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "admin/layout/footer.html" .}}
|
||||
47
templates/admin/html/site-settings/security.html
Normal file
47
templates/admin/html/site-settings/security.html
Normal file
@ -0,0 +1,47 @@
|
||||
{{template "admin/layout/base.html" .}}
|
||||
<div class="page-header">
|
||||
<h1>站点设置</h1>
|
||||
<p class="page-desc">安全策略与维护模式</p>
|
||||
</div>
|
||||
|
||||
{{template "admin/site-settings/_menu.html" .}}
|
||||
|
||||
<!-- 安全设置 -->
|
||||
<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>
|
||||
<div class="setting-input-wrap">
|
||||
<select id="setting-password-strength" class="setting-select" data-key="password.strength">
|
||||
<option value="low">低 — 仅要求 8 位</option>
|
||||
<option value="medium" selected>中 — 字母+数字/符号(两类)</option>
|
||||
<option value="high">高 — 大小写+数字+符号(至少三类)+ 禁止连续字符</option>
|
||||
<option value="very_high">极高 — 四类全有 + 禁止连续字符</option>
|
||||
</select>
|
||||
<button class="btn btn-sm btn-primary btn-save-select" data-key="password.strength" data-input="setting-password-strength">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
{{template "admin/layout/footer.html" .}}
|
||||
Reference in New Issue
Block a user