feat: 完整内容 Limits 与伪静态 Admin

设置页可配字数/编辑窗/分页与伪静态后缀;公开帖/板/用户链接走规范路径并 301。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-30 04:12:43 +08:00
parent 118f967540
commit f0358e0f71
20 changed files with 277 additions and 63 deletions

View File

@@ -94,6 +94,43 @@
<button type="submit">保存限流</button>
</form>
<h2>内容限制</h2>
<p class="j13-muted">字数、编辑时间窗、分页与账号相关上限。</p>
<form method="post" action="/admin/settings/content-limits" class="j13-form j13-admin-form">
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
<label>帖标题最大字数 <input name="post_title_max" type="number" min="1" value="{{.Limits.PostTitleMax}}"/></label>
<label>标签最大字数 <input name="post_tags_max" type="number" min="0" value="{{.Limits.PostTagsMax}}"/></label>
<label>帖正文最大字数 <input name="post_content_max" type="number" min="0" value="{{.Limits.PostContentMax}}"/></label>
<label>评论最大字数 <input name="comment_max" type="number" min="1" value="{{.Limits.CommentMax}}"/></label>
<label>搜索关键词最短 <input name="search_keyword_min" type="number" min="0" value="{{.Limits.SearchKeywordMin}}"/></label>
<label>搜索关键词最长 <input name="search_keyword_max" type="number" min="1" value="{{.Limits.SearchKeywordMax}}"/></label>
<label>默认分页大小 <input name="page_size_default" type="number" min="1" value="{{.Limits.PageSizeDefault}}"/></label>
<label>发帖可编辑(小时) <input name="post_edit_window_hours" type="number" min="0" value="{{.Limits.PostEditWindowHours}}"/></label>
<label>评论可编辑(分钟) <input name="comment_edit_window_minutes" type="number" min="0" value="{{.Limits.CommentEditWindowMinutes}}"/></label>
<label>密码最短长度 <input name="password_min_len" type="number" min="4" value="{{.Limits.PasswordMinLen}}"/></label>
<label>头像最大 MB <input name="avatar_max_mb" type="number" min="1" value="{{.Limits.AvatarMaxMB}}"/></label>
<label>签名最大字数 <input name="signature_max" type="number" min="0" value="{{.Limits.SignatureMax}}"/></label>
<label>Feed 列表样式
<select name="feed_list_style">
<option value="title"{{if eq .Limits.FeedListStyle "title"}} selected{{end}}>仅标题</option>
<option value="excerpt"{{if eq .Limits.FeedListStyle "excerpt"}} selected{{end}}>摘要</option>
<option value="thumbnail"{{if eq .Limits.FeedListStyle "thumbnail"}} selected{{end}}>缩略图</option>
</select>
</label>
<label class="j13-check"><input type="checkbox" name="open_posts_in_new_tab" value="1"{{if .Limits.OpenPostsInNewTab}} checked{{end}}/> 帖子链接新标签打开</label>
<label class="j13-check"><input type="checkbox" name="open_content_links_in_new_tab" value="1"{{if .Limits.OpenContentLinksInNewTab}} checked{{end}}/> 正文外链新标签打开</label>
<button type="submit">保存内容限制</button>
</form>
<h2>伪静态</h2>
<p class="j13-muted">启用后公开路径形如 <code>/post/123.{{.Limits.PermalinkExt}}</code>;无后缀请求会 301 到规范 URL。</p>
<form method="post" action="/admin/settings/permalink" class="j13-form j13-admin-form">
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
<label class="j13-check"><input type="checkbox" name="permalink_enabled" value="1"{{if .Limits.PermalinkEnabled}} checked{{end}}/> 启用伪静态后缀</label>
<label>后缀(不含点) <input name="permalink_ext" maxlength="16" pattern="[A-Za-z0-9]{1,16}" value="{{.Limits.PermalinkExt}}" placeholder="html"/></label>
<button type="submit">保存伪静态</button>
</form>
<h2>侧栏组件</h2>
<p class="j13-muted">控制首页与帖详情右栏可选块的显示与顺序(热门帖为固定块,不在此列)。友链页「侧栏显示」与此共用同一配置。</p>
<form method="post" action="/admin/settings/aside-widgets" class="j13-form j13-admin-form">

View File

@@ -8,7 +8,7 @@
<ul class="j13-boards__grid">
{{range .Items}}
<li>
<a class="j13-boards__card" href="/board/{{.ID}}" data-color="{{.ColorIndex}}">
<a class="j13-boards__card" href="{{.Href}}" data-color="{{.ColorIndex}}">
<span class="j13-boards__dot" aria-hidden="true"></span>
<span class="j13-boards__body">
<strong>{{.Name}}</strong>

View File

@@ -9,7 +9,7 @@
<ul class="j13-post-list">
{{range .Items}}
<li class="j13-post-item">
<a class="j13-post-item__title" href="/post/{{.PostID}}">{{.Title}}</a>
<a class="j13-post-item__title" href="{{.Href}}"{{if $.OpenPostsInNewTab}} target="_blank" rel="noopener"{{end}}>{{.Title}}</a>
<div class="j13-post-item__meta">
{{if .AuthorName}}<span>{{.AuthorName}}</span>{{end}}
{{if .BoardName}}<span>{{.BoardName}}</span>{{end}}

View File

@@ -37,7 +37,7 @@
<ul class="j13-post-list">
{{range .Posts}}
<li class="j13-post-item">
<a class="j13-post-item__title" href="{{postURL .ID}}">{{.Title}}</a>
<a class="j13-post-item__title" href="{{.Href}}"{{if $.OpenPostsInNewTab}} target="_blank" rel="noopener"{{end}}>{{.Title}}</a>
<div class="j13-post-item__meta">
{{if .Pinned}}<span class="j13-tag j13-tag--pin">置顶</span>{{end}}
{{if .Featured}}<span class="j13-tag j13-tag--feat">精华</span>{{end}}

View File

@@ -17,8 +17,8 @@
{{if .IsQuestion}}
{{if .QuestionResolved}}<span class="j13-tag j13-tag--resolved">已解决</span>{{else}}<span class="j13-tag j13-tag--unresolved">未解决</span>{{end}}
{{end}}
{{if .BoardName}}<a class="j13-tag" href="/board/{{.BoardID}}">{{.BoardName}}</a>{{end}}
{{if .AuthorID}}<a href="/user/{{.AuthorID}}">{{.AuthorName}}</a>{{else}}<span>{{.AuthorName}}</span>{{end}}
{{if .BoardName}}<a class="j13-tag" href="{{.BoardHref}}">{{.BoardName}}</a>{{end}}
{{if .AuthorID}}<a href="{{.AuthorHref}}">{{.AuthorName}}</a>{{else}}<span>{{.AuthorName}}</span>{{end}}
<span>{{.CreatedLabel}}</span>
<span>{{.ViewCount}} 阅读</span>
</div>
@@ -44,8 +44,8 @@
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
<button type="submit">{{if .Favorited}}取消收藏{{else}}收藏{{end}}</button>
</form>
{{if .CanEdit}}<a class="j13-linkbtn" href="/post/{{.PostID}}/edit">编辑</a>{{end}}
{{if .CanViewRevisions}}<a class="j13-linkbtn" href="/post/{{.PostID}}/revisions">修订历史</a>{{end}}
{{if .CanEdit}}<a class="j13-linkbtn" href="{{.PostHref}}/edit">编辑</a>{{end}}
{{if .CanViewRevisions}}<a class="j13-linkbtn" href="{{.PostHref}}/revisions">修订历史</a>{{end}}
{{if .CanReportPost}}
<details class="j13-report">
<summary class="j13-linkbtn">举报</summary>

View File

@@ -3,7 +3,7 @@
<a class="j13-aside__link{{if eq .Path "/boards"}} is-active{{end}}" href="/boards">全部板块</a>
<a class="j13-aside__link{{if and (eq .ActiveBoard 0) (ne .Path "/boards")}} is-active{{end}}" href="/">全部帖子</a>
{{range .Boards}}
<a class="j13-aside__link{{if eq $.ActiveBoard .ID}} is-active{{end}}" href="/board/{{.ID}}">{{.Name}}</a>
<a class="j13-aside__link{{if eq $.ActiveBoard .ID}} is-active{{end}}" href="{{.Href}}">{{.Name}}</a>
{{end}}
</aside>
{{end}}

View File

@@ -33,7 +33,7 @@
{{if .RightAside.HotPosts}}
<ul class="j13-widget__list">
{{range .RightAside.HotPosts}}
<li><a href="{{postURL .ID}}">{{.Title}}</a></li>
<li><a href="{{.Href}}">{{.Title}}</a></li>
{{end}}
</ul>
{{else}}
@@ -59,7 +59,7 @@
<ul class="j13-widget__list">
{{range .Comments}}
<li>
<a href="{{postURL .PostID}}">{{.Excerpt}}</a>
<a href="{{.PostHref}}">{{.Excerpt}}</a>
<span class="j13-widget__meta">{{.Author}} · {{.PostTitle}}</span>
</li>
{{end}}
@@ -72,7 +72,7 @@
{{if .Users}}
<ul class="j13-widget__list">
{{range .Users}}
<li><a href="/user/{{.ID}}">{{.Nickname}}</a></li>
<li><a href="{{.Href}}">{{.Nickname}}</a></li>
{{end}}
</ul>
{{else}}

View File

@@ -36,7 +36,7 @@
<ul class="j13-post-list">
{{range .Posts}}
<li class="j13-post-item">
<a class="j13-post-item__title" href="/post/{{.ID}}">{{.Title}}</a>
<a class="j13-post-item__title" href="{{.Href}}"{{if $.OpenPostsInNewTab}} target="_blank" rel="noopener"{{end}}>{{.Title}}</a>
<div class="j13-post-item__meta">
{{if .BoardName}}<span>{{.BoardName}}</span>{{end}}
<span>{{.CreatedLabel}}</span>