feat: 品牌CMS配置化 + cookie_secure配置

- config.yaml 新增 server.cookie_secure 配置项
- site_settings 新增 site_name/site_tagline/contact_email 站点信息
- SiteInfo 结构体扩展,支持运行时从 DB 读取站点品牌信息
- cookie.go 使用 cfg.Server.CookieSecure 替代 Mode!=debug 判断
- SetSessionCookie/ClearSessionCookie 支持 siteSettings 运行时覆盖
- 模板替换硬编码 MetaLab → {{.SiteName}}(nav/header/footer/home/login/register/guidelines/admin,12+处)
- 管理后台站点设置页新增站点名称/标语/联系邮箱输入项
- 页脚版权年份改为动态 CurrentYear
- 注册成功消息 CMS 化(后端+前端)
This commit is contained in:
2026-06-21 23:12:18 +08:00
parent 7b5856e0ba
commit 0014bdb9ff
21 changed files with 106 additions and 35 deletions

View File

@ -5,7 +5,7 @@
<main class="auth-page">
<div class="auth-card">
<h2>登录 MetaLab</h2>
<h2>登录 {{.SiteName}}</h2>
<p class="auth-subtitle">回到开发者社区</p>
<form id="loginForm" novalidate>
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">

View File

@ -13,7 +13,7 @@
</div>
{{else if .RegistrationEnabled}}
<h2>创建账号</h2>
<p class="auth-subtitle">加入 MetaLab 开发者社区</p>
<p class="auth-subtitle">加入 {{.SiteName}} 开发者社区</p>
<form id="registerForm" novalidate>
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<div class="form-group">
@ -38,7 +38,7 @@
</label>
<span class="remember-hint">非共享设备推荐</span>
</div>
<p class="guidelines-link">点击注册即表示同意 <a href="#" id="openGuidelines">MetaLab 社区用户准则》</a></p>
<p class="guidelines-link">点击注册即表示同意 <a href="#" id="openGuidelines">{{.SiteName}} 社区用户准则》</a></p>
<button type="submit" class="submit-btn" id="submitBtn">注 册</button>
</form>
{{else}}
@ -59,7 +59,7 @@
<div class="modal-overlay" id="modalOverlay">
<div class="modal">
<div class="modal-header">
<h3>MetaLab 社区用户准则</h3>
<h3>{{.SiteName}} 社区用户准则</h3>
<button class="modal-close" id="modalClose">&times;</button>
</div>
<div class="modal-body" id="modalBody">

View File

@ -7,8 +7,8 @@
<section class="hero-banner">
<div class="hero-bg"></div>
<div class="hero-content">
<h1 class="hero-title">Meta<span class="hero-accent">Lab</span></h1>
<p class="hero-tagline">下一代开发者社区</p>
<h1 class="hero-title">{{.SiteName}}</h1>
<p class="hero-tagline">{{.SiteTagline}}</p>
{{if .IsLoggedIn}}
<p class="hero-welcome">欢迎回来,{{.Username}} 👋</p>
{{else}}
@ -69,7 +69,7 @@
<div class="user-avatar-fallback"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg></div>
{{end}}
<h3 class="user-card-name">{{.Username}}</h3>
<p class="user-card-desc">欢迎加入 MetaLab</p>
<p class="user-card-desc">欢迎加入 {{.SiteName}}</p>
<a href="/space" class="user-card-link">我的空间</a>
{{else}}
<div class="user-avatar-fallback guest-avatar">

View File

@ -1,6 +1,6 @@
<footer>
<div class="container footer-content">
<p class="copyright">&copy; {{.CopyrightStart}}-2026 MetaLab{{if .Framework}} | {{.Framework}}{{end}}{{if .CanAccessAdmin}} | <a href="/admin">管理面板</a>{{end}}</p>
<p class="copyright">&copy; {{.CopyrightStart}}-{{.CurrentYear}} {{.SiteName}}{{if .Framework}} | {{.Framework}}{{end}}{{if .CanAccessAdmin}} | <a href="/admin">管理面板</a>{{end}}</p>
</div>
</footer>
<script src="/static/js/common.js?v={{assetV "/static/js/common.js"}}" nonce="{{.CSPNonce}}"></script>

View File

@ -7,12 +7,12 @@
{{if .OgTitle}}
<meta property="og:title" content="{{.OgTitle}}">
<meta property="og:type" content="article">
<meta property="og:site_name" content="MetaLab">
<meta property="og:site_name" content="{{.SiteName}}">
{{if .OgDescription}}<meta property="og:description" content="{{.OgDescription}}">{{end}}
{{if .OgImage}}<meta property="og:image" content="{{.OgImage}}">{{end}}
{{if .OgURL}}<meta property="og:url" content="{{.OgURL}}">{{end}}
{{end}}
<title>{{.Title}} - MetaLab</title>
<title>{{.Title}} - {{.SiteName}}</title>
<link rel="stylesheet" href="/static/css/common.css?v={{assetV "/static/css/common.css"}}">
{{if .ExtraCSS}}
<link rel="stylesheet" href="{{.ExtraCSS}}?v={{assetV .ExtraCSS}}">

View File

@ -1,6 +1,6 @@
<header>
<div class="container nav-container">
<a href="/" class="logo">Meta<span>Lab</span></a>
<a href="/" class="logo">{{.SiteName}}</a>
<button class="mobile-menu-btn" id="mobileMenuBtn">
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
</button>

View File

@ -290,7 +290,7 @@
try { resp = JSON.parse(xhr.responseText); } catch (err) { resp = null; }
if (xhr.status === 200 && resp && resp.success) {
window.MetaLab.toast(toast, '🎉 注册成功!欢迎加入 MetaLab', false);
window.MetaLab.toast(toast, resp.message || '🎉 注册成功!', false);
// Token 已通过 HttpOnly Cookie 自动设置JS 无需处理
// 注册即登录,跳转首页
setTimeout(function () {

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{if .CSRFToken}}<meta name="csrf-token" content="{{.CSRFToken}}">{{end}}
<title>{{.Title}} - MetaLab 管理面板</title>
<title>{{.Title}} - {{.SiteName}} 管理面板</title>
<link rel="stylesheet" href="/admin/static/css/common.css?v={{assetV "/admin/static/css/common.css"}}">
{{if .ExtraCSS}}
<link rel="stylesheet" href="{{.ExtraCSS}}">
@ -13,7 +13,7 @@
<body>
<header class="admin-header">
<div class="admin-header-inner">
<a href="/admin" class="admin-logo">MetaLab <span>管理面板</span></a>
<a href="/admin" class="admin-logo">{{.SiteName}} <span>管理面板</span></a>
<div class="admin-header-right">
<span class="admin-user">{{.Username}}</span>
<a href="/" class="admin-back-btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>返回前台</a>

View File

@ -10,8 +10,38 @@
<div class="section-body">
<div class="setting-item">
<div class="setting-info">
<span class="setting-label">版权信息</span>
<span class="setting-desc">页脚附加信息,留空则隐藏(如 "Framework: MetaZone"</span>
<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}}">