Files
mce/internal/config/site_settings.go
Victor_Jay 0b948cf70f feat(admin): 站点信息 + 注册开关可后台设置,模板动态渲染
新增 4 项可配置站点设置(DB持久化+内存缓存,即时生效):
- site.brand          品牌名(页面标题/页脚/管理面板,默认 MetaLab)
- site.framework      框架名(页脚标识,默认 MetaZone)
- site.copyright_start 版权起始年(页脚,默认 2024)
- registration.enabled 注册开关(关闭后禁止新用户注册,默认 true)

实现方式:
- InjectSiteInfo 中间件:全局注入 Brand/Framework/CopyrightStart 到 gin.Context
- BuildPageData 读取 context,所有 SSR 页面自动获取站点信息
- AuthService.Register 最先检查 IsRegistrationEnabled()
- 管理后台新增「基本设置」+「注册设置」区块,文本输入手动保存 + Toggle 即时生效
2026-05-27 15:12:28 +08:00

133 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package config
import (
"strconv"
"sync"
"metazone.cc/metalab/internal/model"
"gorm.io/gorm"
)
// SiteSettings 站点设置管理器DB 持久化 + 内存缓存,不重启生效)
// 启动时从 DB 加载全量到内存,运行时读内存不查 DB写入同步写 DB 和内存
type SiteSettings struct {
mu sync.RWMutex
data map[string]string
db *gorm.DB
}
// NewSiteSettings 创建站点设置管理器并加载 DB 中已有配置
func NewSiteSettings(db *gorm.DB) (*SiteSettings, error) {
ss := &SiteSettings{
data: make(map[string]string),
db: db,
}
if err := ss.reload(); err != nil {
return nil, err
}
return ss, nil
}
// reload 从 DB 加载全量设置到内存
func (s *SiteSettings) reload() error {
var rows []model.SiteSetting
if err := s.db.Find(&rows).Error; err != nil {
return err
}
s.mu.Lock()
defer s.mu.Unlock()
for _, row := range rows {
s.data[row.Key] = row.Value
}
return nil
}
// Get 读取一个字符串值,不存在返回默认值
func (s *SiteSettings) Get(key, defaultVal string) string {
s.mu.RLock()
defer s.mu.RUnlock()
val, ok := s.data[key]
if !ok {
return defaultVal
}
return val
}
// GetBool 读取布尔值,不存在返回默认值(仅 "true" 字符串视为 true
func (s *SiteSettings) GetBool(key string, defaultVal bool) bool {
s.mu.RLock()
defer s.mu.RUnlock()
val, ok := s.data[key]
if !ok {
return defaultVal
}
b, err := strconv.ParseBool(val)
if err != nil {
return defaultVal
}
return b
}
// Set 写入设置(同步写 DB + 更新内存)
func (s *SiteSettings) Set(key, value string) error {
entry := model.SiteSetting{Key: key, Value: value}
if err := s.db.Save(&entry).Error; err != nil {
return err
}
s.mu.Lock()
s.data[key] = value
s.mu.Unlock()
return nil
}
// SetBool 写入布尔设置
func (s *SiteSettings) SetBool(key string, value bool) error {
return s.Set(key, strconv.FormatBool(value))
}
// All 返回所有设置的快照(用于前端展示)
func (s *SiteSettings) All() map[string]string {
s.mu.RLock()
defer s.mu.RUnlock()
cp := make(map[string]string, len(s.data))
for k, v := range s.data {
cp[k] = v
}
return cp
}
// IsAuditEnabled 审核总开关是否开启
// 优先查站点设置 DB若无则取 config.yaml 默认值
func (s *SiteSettings) IsAuditEnabled() bool {
return s.GetBool("audit.enabled", App.Audit.Enabled)
}
// IsAuditTypeEnabled 某类型审核是否开启
func (s *SiteSettings) IsAuditTypeEnabled(auditType string, defaultVal bool) bool {
return s.GetBool("audit."+auditType, defaultVal)
}
// --- 站点信息设置 ---
// SiteInfoDefaults 站点展示信息的默认值
type SiteInfoDefaults struct {
Brand string // 品牌名,默认 "MetaLab"
Framework string // 框架名,默认 "MetaZone"
CopyrightStart string // 版权起始年份,默认 "2024"
}
// SiteInfo 获取站点展示信息(优先 DB 设置fallback 默认值)
func (s *SiteSettings) SiteInfo() SiteInfoDefaults {
return SiteInfoDefaults{
Brand: s.Get("site.brand", "MetaLab"),
Framework: s.Get("site.framework", "MetaZone"),
CopyrightStart: s.Get("site.copyright_start", "2024"),
}
}
// IsRegistrationEnabled 是否允许新用户注册
func (s *SiteSettings) IsRegistrationEnabled() bool {
return s.GetBool("registration.enabled", true)
}