完善站点运营设置:分路由管理、登录可见评论、邮件模板内联与关闭注册 SSR。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 00:17:00 +08:00
parent acde7ee288
commit 6f054a903c
98 changed files with 8239 additions and 2073 deletions

View File

@@ -27,6 +27,7 @@ type updateSettingsRequest struct {
SiteDescription *string `json:"site_description"`
AllowRegister *bool `json:"allow_register"`
AllowComments *bool `json:"allow_comments"`
CommentsRequireLogin *bool `json:"comments_require_login"`
AllowMessages *bool `json:"allow_messages"`
PostCooldownHours *int `json:"post_cooldown_hours"`
CodeBlockAutoFold *bool `json:"code_block_auto_fold"`
@@ -55,7 +56,6 @@ type updateSettingsRequest struct {
BrandLogoSize *string `json:"brand_logo_size"`
BrandLogoFit *string `json:"brand_logo_fit"`
FooterLinks *[]service.FooterLink `json:"footer_links"`
TimelineGitImport *string `json:"timeline_git_import"` // 超管专用;不进公开 settings / WS 广播
}
func settingsPayload(saved service.PublicSiteSettings) gin.H {
@@ -65,8 +65,9 @@ func settingsPayload(saved service.PublicSiteSettings) gin.H {
"site_name": saved.SiteName,
"site_description": saved.SiteDescription,
"allow_register": saved.AllowRegister,
"allow_comments": saved.AllowComments,
"allow_messages": saved.AllowMessages,
"allow_comments": saved.AllowComments,
"comments_require_login": saved.CommentsRequireLogin,
"allow_messages": saved.AllowMessages,
"post_cooldown_hours": saved.PostCooldownHours,
"code_block_auto_fold": saved.CodeBlockAutoFold,
"code_block_fold_lines": saved.CodeBlockFoldLines,
@@ -100,7 +101,7 @@ func settingsPayload(saved service.PublicSiteSettings) gin.H {
func (req *updateSettingsRequest) hasAny() bool {
return req.Accent != nil || req.TrustReviewedPublish != nil || req.SiteName != nil ||
req.SiteDescription != nil || req.AllowRegister != nil || req.AllowComments != nil ||
req.AllowMessages != nil || req.PostCooldownHours != nil || req.CodeBlockAutoFold != nil ||
req.CommentsRequireLogin != nil || req.AllowMessages != nil || req.PostCooldownHours != nil || req.CodeBlockAutoFold != nil ||
req.CodeBlockFoldLines != nil || req.UIAnimations != nil || req.AnimCodeFold != nil ||
req.AnimSmoothScroll != nil || req.AnimChrome != nil || req.PostLinkNewTab != nil ||
req.AttachmentExtLimit != nil || req.AttachmentExts != nil || req.AttachmentMaxMB != nil ||
@@ -110,24 +111,17 @@ func (req *updateSettingsRequest) hasAny() bool {
req.SiteWordmark != nil || req.SiteSlogan != nil || req.SiteKeywords != nil ||
req.LogoLightURL != nil || req.LogoDarkURL != nil || req.FaviconURL != nil ||
req.BrandMark != nil || req.BrandLogoSize != nil || req.BrandLogoFit != nil ||
req.FooterLinks != nil || req.TimelineGitImport != nil
req.FooterLinks != nil
}
// AdminGetSettings 超管读取站点设置(含 timeline_git_import,不进公开 /api/settings)
// AdminGetSettings 超管读取站点设置(与公开 payload 字段一致)
func (h *Handlers) AdminGetSettings(c *gin.Context) {
saved, err := h.Setting.Public()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取站点设置失败"})
return
}
adapter, err := h.Setting.TimelineGitAdapterJSON()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取提交导入配置失败"})
return
}
out := settingsPayload(saved)
out["timeline_git_import"] = adapter
c.JSON(http.StatusOK, out)
c.JSON(http.StatusOK, settingsPayload(saved))
}
// PUT /api/admin/settings
@@ -142,6 +136,10 @@ func (h *Handlers) UpdateSettings(c *gin.Context) {
return
}
if req.AllowRegister != nil || req.AttachmentExtLimit != nil || req.AttachmentExts != nil || req.AttachmentMaxMB != nil || req.AttachmentMaxCount != nil || req.ImageMaxMB != nil {
c.JSON(400, gin.H{"error": "请在访问与安全或文件与存储页通过版本校验保存这些设置"})
return
}
if req.Accent != nil {
if err := h.Setting.SetAccent(*req.Accent); err != nil {
if errors.Is(err, service.ErrInvalidAccent) {
@@ -190,6 +188,12 @@ func (h *Handlers) UpdateSettings(c *gin.Context) {
return
}
}
if req.CommentsRequireLogin != nil {
if err := h.Setting.SetCommentsRequireLogin(*req.CommentsRequireLogin); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存站点设置失败"})
return
}
}
if req.AllowMessages != nil {
if err := h.Setting.SetAllowMessages(*req.AllowMessages); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存站点设置失败"})
@@ -419,16 +423,6 @@ func (h *Handlers) UpdateSettings(c *gin.Context) {
}
}
var savedAdapter string
if req.TimelineGitImport != nil {
normalized, err := h.Setting.SetTimelineGitAdapterJSON(*req.TimelineGitImport)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
savedAdapter = normalized
}
saved, err := h.Setting.Public()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取站点设置失败"})
@@ -442,9 +436,6 @@ func (h *Handlers) UpdateSettings(c *gin.Context) {
})
out := settingsPayload(saved)
out["ok"] = true
if req.TimelineGitImport != nil {
out["timeline_git_import"] = savedAdapter
}
c.JSON(http.StatusOK, out)
}