feat(settings): 后台可配置 Markdown 代码块自动折叠与阈值行数

支持开关与 0–100 行阈值(0 为无预览),经站点设置与 WS 热更新;短代码在视口内收起时不再回滚浏览位置。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-16 06:43:37 +08:00
parent b6e9966ba8
commit 809d8f1df7
8 changed files with 349 additions and 23 deletions

View File

@@ -20,16 +20,23 @@ const (
SettingKeySiteName = "site_name"
SettingKeySiteDescription = "site_description"
SettingKeyAllowRegister = "allow_register"
SettingKeyPostCooldownHours = "post_cooldown_hours"
SettingKeyPostCooldownHours = "post_cooldown_hours"
// SettingKeyCodeBlockAutoFold 代码块自动折叠;缺行视为开启
SettingKeyCodeBlockAutoFold = "code_block_auto_fold"
// SettingKeyCodeBlockFoldLines 超过该行数则折叠;0=无预览;缺行=5
SettingKeyCodeBlockFoldLines = "code_block_fold_lines"
)
const (
DefaultSiteName = "姜十三论坛"
DefaultSiteDescription = "姜十三论坛 - 技术分享与讨论社区"
DefaultCooldownHours = 24
DefaultCodeFoldLines = 5
MaxSiteNameRunes = 32
MaxSiteDescRunes = 160
MaxCooldownHours = 168
MinCodeFoldLines = 0
MaxCodeFoldLines = 100
)
// ErrInvalidAccent 主题色格式非法
@@ -48,6 +55,8 @@ type PublicSiteSettings struct {
SiteDescription string `json:"site_description"`
AllowRegister bool `json:"allow_register"`
PostCooldownHours int `json:"post_cooldown_hours"`
CodeBlockAutoFold bool `json:"code_block_auto_fold"`
CodeBlockFoldLines int `json:"code_block_fold_lines"`
}
// SettingService 站点级键值设置
@@ -108,6 +117,8 @@ func (s *SettingService) Public() (PublicSiteSettings, error) {
TrustReviewedPublish: true,
AllowRegister: true,
PostCooldownHours: DefaultCooldownHours,
CodeBlockAutoFold: true,
CodeBlockFoldLines: DefaultCodeFoldLines,
}
accent, err := s.AccentColor()
if err != nil {
@@ -151,6 +162,18 @@ func (s *SettingService) Public() (PublicSiteSettings, error) {
return out, err
}
out.PostCooldownHours = hours
fold, err := s.CodeBlockAutoFold()
if err != nil {
return out, err
}
out.CodeBlockAutoFold = fold
foldLines, err := s.CodeBlockFoldLines()
if err != nil {
return out, err
}
out.CodeBlockFoldLines = foldLines
return out, nil
}
@@ -223,6 +246,7 @@ func (s *SettingService) SetAllowRegister(on bool) error {
return s.setBoolDefaultTrue(SettingKeyAllowRegister, on)
}
// PostCooldownHours 新用户发帖冷静期(小时)。缺行=24;0 表示关闭。
func (s *SettingService) PostCooldownHours() (int, error) {
v, found, err := s.getValue(SettingKeyPostCooldownHours)
@@ -251,3 +275,46 @@ func (s *SettingService) SetPostCooldownHours(hours int) error {
}
return s.putValue(SettingKeyPostCooldownHours, strconv.Itoa(hours))
}
// CodeBlockAutoFold 是否对超过阈值行数的 Markdown 代码块默认折叠。缺行视为开启。
func (s *SettingService) CodeBlockAutoFold() (bool, error) {
v, found, err := s.getValue(SettingKeyCodeBlockAutoFold)
if err != nil {
return true, err
}
return parseBoolDefaultTrue(v, found), nil
}
// SetCodeBlockAutoFold 持久化代码折叠开关;开启时删键保持「缺行=默认开」。
func (s *SettingService) SetCodeBlockAutoFold(on bool) error {
return s.setBoolDefaultTrue(SettingKeyCodeBlockAutoFold, on)
}
// CodeBlockFoldLines 超过该行数则折叠(折叠预览约同高;0=无预览)。缺行=5。
func (s *SettingService) CodeBlockFoldLines() (int, error) {
v, found, err := s.getValue(SettingKeyCodeBlockFoldLines)
if err != nil {
return DefaultCodeFoldLines, err
}
if !found {
return DefaultCodeFoldLines, nil
}
n, convErr := strconv.Atoi(strings.TrimSpace(v))
if convErr != nil || n < MinCodeFoldLines {
return DefaultCodeFoldLines, nil
}
if n > MaxCodeFoldLines {
return MaxCodeFoldLines, nil
}
return n, nil
}
func (s *SettingService) SetCodeBlockFoldLines(lines int) error {
if lines < MinCodeFoldLines || lines > MaxCodeFoldLines {
return ErrInvalidSiteSetting
}
if lines == DefaultCodeFoldLines {
return s.deleteKey(SettingKeyCodeBlockFoldLines)
}
return s.putValue(SettingKeyCodeBlockFoldLines, strconv.Itoa(lines))
}