package models import ( "sync" "gorm.io/gorm" ) // configCache 保存平台配置的进程级缓存,使每次请求的渲染与上传校验 // 都不必访问数据库。缓存启动时填充一次,每当管理员保存设置页面时刷新 // (参见 RefreshConfigCache / 各管理处理器)。 var configCache = struct { mu sync.RWMutex site *SiteSetting upload *UploadConfig comment *CommentConfig types []UploadFileType baseURLs []DownloadBaseURL navLinks []NavLink }{ site: &SiteSetting{}, upload: &UploadConfig{Enabled: true, DefaultMaxSize: DefaultUploadMaxSize, StorageDir: "attachments"}, } // LoadConfigCache 将所有平台配置从数据库读入进程缓存。 // 在 InitDB 之后于启动时调用一次。 func LoadConfigCache(db *gorm.DB) { configCache.mu.Lock() defer configCache.mu.Unlock() var s SiteSetting if err := db.First(&s, 1).Error; err == nil { configCache.site = &s } else { configCache.site = &SiteSetting{ID: 1} } var u UploadConfig if err := db.First(&u, 1).Error; err == nil { configCache.upload = &u } else { configCache.upload = &UploadConfig{ID: 1, Enabled: true, DefaultMaxSize: DefaultUploadMaxSize, StorageDir: "attachments"} } var cc CommentConfig if err := db.First(&cc, 1).Error; err == nil { configCache.comment = &cc } else { configCache.comment = defaultCommentConfig() } var t []UploadFileType if err := db.Order("sort asc, id asc").Find(&t).Error; err == nil { configCache.types = t } var b []DownloadBaseURL if err := db.Order("is_default desc, priority asc, id asc").Find(&b).Error; err == nil { configCache.baseURLs = b } var n []NavLink if err := db.Where("enabled = ?", true).Order("sort asc, id asc").Find(&n).Error; err == nil { configCache.navLinks = n } } // RefreshConfigCache 重新加载所有缓存中的平台配置。管理处理器在写入变更后 // 调用此方法,以便下一次请求能看到更新。 func RefreshConfigCache(db *gorm.DB) { LoadConfigCache(db) } // GetSiteSetting 返回缓存的站点设置指针(只读副本语义:调用方不得修改)。 func GetSiteSetting() *SiteSetting { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.site } // GetUploadConfig 返回缓存的上传策略。 func GetUploadConfig() *UploadConfig { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.upload } // GetCommentConfig 返回缓存的评论策略。 func GetCommentConfig() *CommentConfig { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.comment } // GetUploadFileTypes 返回缓存的允许文件类型列表。 func GetUploadFileTypes() []UploadFileType { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.types } // GetDownloadBaseURLs 返回缓存的下载基础 URL 列表。 func GetDownloadBaseURLs() []DownloadBaseURL { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.baseURLs } // DefaultDownloadBaseURL 返回用于构建附件下载链接的基础 URL: // 首选标记为 IsDefault 且启用的行,否则选择优先级最高的启用行。 // 若未配置任何项则返回空字符串。 func DefaultDownloadBaseURL() string { configCache.mu.RLock() defer configCache.mu.RUnlock() // 行按 is_default desc、priority asc 排序,因此第一个启用行即为正确选择。 for _, b := range configCache.baseURLs { if b.Enabled { return b.BaseURL } } return "" } // GetNavLinks 返回缓存的启用导航链接列表,按排序顺序排列。 func GetNavLinks() []NavLink { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.navLinks }