feat(settings): 站点界面动画总开关与子开关

管理后台可关全站动画,并细调代码折叠、平滑滚动、装饰入场;统一 lib/motion,尊重系统减少动态效果。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-16 06:59:26 +08:00
parent c6df1b3b7e
commit 2b27703e6c
14 changed files with 511 additions and 46 deletions

View File

@@ -29,6 +29,27 @@ type updateSettingsRequest struct {
PostCooldownHours *int `json:"post_cooldown_hours"`
CodeBlockAutoFold *bool `json:"code_block_auto_fold"`
CodeBlockFoldLines *int `json:"code_block_fold_lines"`
UIAnimations *bool `json:"ui_animations"`
AnimCodeFold *bool `json:"anim_code_fold"`
AnimSmoothScroll *bool `json:"anim_smooth_scroll"`
AnimChrome *bool `json:"anim_chrome"`
}
func settingsPayload(saved service.PublicSiteSettings) gin.H {
return gin.H{
"accent": saved.Accent,
"trust_reviewed_publish": saved.TrustReviewedPublish,
"site_name": saved.SiteName,
"site_description": saved.SiteDescription,
"allow_register": saved.AllowRegister,
"post_cooldown_hours": saved.PostCooldownHours,
"code_block_auto_fold": saved.CodeBlockAutoFold,
"code_block_fold_lines": saved.CodeBlockFoldLines,
"ui_animations": saved.UIAnimations,
"anim_code_fold": saved.AnimCodeFold,
"anim_smooth_scroll": saved.AnimSmoothScroll,
"anim_chrome": saved.AnimChrome,
}
}
// PUT /api/admin/settings
@@ -40,7 +61,9 @@ func (h *Handlers) UpdateSettings(c *gin.Context) {
}
if req.Accent == nil && req.TrustReviewedPublish == nil && req.SiteName == nil &&
req.SiteDescription == nil && req.AllowRegister == nil &&
req.PostCooldownHours == nil && req.CodeBlockAutoFold == nil && req.CodeBlockFoldLines == nil {
req.PostCooldownHours == nil && req.CodeBlockAutoFold == nil && req.CodeBlockFoldLines == nil &&
req.UIAnimations == nil && req.AnimCodeFold == nil && req.AnimSmoothScroll == nil &&
req.AnimChrome == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "未提供任何可更新的设置项"})
return
}
@@ -113,6 +136,30 @@ func (h *Handlers) UpdateSettings(c *gin.Context) {
return
}
}
if req.UIAnimations != nil {
if err := h.Setting.SetUIAnimations(*req.UIAnimations); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存站点设置失败"})
return
}
}
if req.AnimCodeFold != nil {
if err := h.Setting.SetAnimCodeFold(*req.AnimCodeFold); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存站点设置失败"})
return
}
}
if req.AnimSmoothScroll != nil {
if err := h.Setting.SetAnimSmoothScroll(*req.AnimSmoothScroll); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存站点设置失败"})
return
}
}
if req.AnimChrome != nil {
if err := h.Setting.SetAnimChrome(*req.AnimChrome); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存站点设置失败"})
return
}
}
saved, err := h.Setting.Public()
if err != nil {
@@ -120,29 +167,12 @@ func (h *Handlers) UpdateSettings(c *gin.Context) {
return
}
payload := gin.H{
"accent": saved.Accent,
"trust_reviewed_publish": saved.TrustReviewedPublish,
"site_name": saved.SiteName,
"site_description": saved.SiteDescription,
"allow_register": saved.AllowRegister,
"post_cooldown_hours": saved.PostCooldownHours,
"code_block_auto_fold": saved.CodeBlockAutoFold,
"code_block_fold_lines": saved.CodeBlockFoldLines,
}
payload := settingsPayload(saved)
h.Hub.BroadcastAll(realtime.Envelope{
Type: realtime.EventSettingsChanged,
Data: payload,
})
c.JSON(http.StatusOK, gin.H{
"ok": true,
"accent": saved.Accent,
"trust_reviewed_publish": saved.TrustReviewedPublish,
"site_name": saved.SiteName,
"site_description": saved.SiteDescription,
"allow_register": saved.AllowRegister,
"post_cooldown_hours": saved.PostCooldownHours,
"code_block_auto_fold": saved.CodeBlockAutoFold,
"code_block_fold_lines": saved.CodeBlockFoldLines,
})
out := settingsPayload(saved)
out["ok"] = true
c.JSON(http.StatusOK, out)
}