设置页可配字数/编辑窗/分页与伪静态后缀;公开帖/板/用户链接走规范路径并 301。 Co-authored-by: Cursor <cursoragent@cursor.com>
200 lines
12 KiB
Cheetah
200 lines
12 KiB
Cheetah
{{define "admin/settings"}}
|
||
{{template "base/head" .}}
|
||
{{template "base/navbar" .}}
|
||
<main class="j13-main j13-admin">
|
||
<h1>站点设置</h1>
|
||
{{template "admin/nav" .}}
|
||
{{template "base/alert" .}}
|
||
|
||
<h2>品牌</h2>
|
||
<form method="post" action="/admin/settings/brand" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<label>站点名称 <input name="name" required value="{{.Brand.Name}}"/></label>
|
||
<label>标语 <input name="slogan" value="{{.Brand.Slogan}}"/></label>
|
||
<label>简介 <textarea name="description" rows="3">{{.Brand.Description}}</textarea></label>
|
||
<label>关键词 <input name="keywords" value="{{.Brand.Keywords}}"/></label>
|
||
<label>Logo 字标(单字) <input name="logo_mark" maxlength="4" value="{{.Brand.LogoMark}}"/></label>
|
||
<label>ICP 备案号 <input name="icp_beian" value="{{.Brand.ICPBeian}}"/></label>
|
||
<label>ICP 链接 <input name="icp_beian_url" value="{{.Brand.ICPBeianURL}}"/></label>
|
||
<button type="submit">保存品牌</button>
|
||
</form>
|
||
|
||
<h3>品牌图片</h3>
|
||
<p class="j13-muted">Logo / Favicon / 默认 Open Graph 图;单文件不超过 2MB。</p>
|
||
<div class="j13-admin-brand-assets">
|
||
<div class="j13-admin-brand-asset">
|
||
<strong>Logo</strong>
|
||
{{if .Brand.Logo}}
|
||
<p><img class="j13-admin-brand-preview" src="{{.Brand.Logo}}" alt="Logo"/></p>
|
||
<p class="j13-muted"><code>{{.Brand.Logo}}</code></p>
|
||
<form method="post" action="/admin/settings/brand/clear" class="j13-inline-form" onsubmit="return confirm('清除 Logo?');">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<input type="hidden" name="kind" value="logo"/>
|
||
<button type="submit" class="j13-linkbtn">清除</button>
|
||
</form>
|
||
{{else}}
|
||
<p class="j13-muted">未设置(导航使用字标)</p>
|
||
{{end}}
|
||
<form method="post" action="/admin/settings/brand/upload" enctype="multipart/form-data" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<input type="hidden" name="kind" value="logo"/>
|
||
<label>上传 <input type="file" name="file" accept="image/*" required/></label>
|
||
<button type="submit">上传 Logo</button>
|
||
</form>
|
||
</div>
|
||
<div class="j13-admin-brand-asset">
|
||
<strong>Favicon</strong>
|
||
{{if .Brand.Favicon}}
|
||
<p><img class="j13-admin-brand-preview j13-admin-brand-preview--sm" src="{{.Brand.Favicon}}" alt="Favicon"/></p>
|
||
<form method="post" action="/admin/settings/brand/clear" class="j13-inline-form" onsubmit="return confirm('清除 Favicon?');">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<input type="hidden" name="kind" value="favicon"/>
|
||
<button type="submit" class="j13-linkbtn">清除</button>
|
||
</form>
|
||
{{else}}
|
||
<p class="j13-muted">未设置</p>
|
||
{{end}}
|
||
<form method="post" action="/admin/settings/brand/upload" enctype="multipart/form-data" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<input type="hidden" name="kind" value="favicon"/>
|
||
<label>上传 <input type="file" name="file" accept="image/*" required/></label>
|
||
<button type="submit">上传 Favicon</button>
|
||
</form>
|
||
</div>
|
||
<div class="j13-admin-brand-asset">
|
||
<strong>默认 OG 图</strong>
|
||
{{if .Brand.OGImage}}
|
||
<p><img class="j13-admin-brand-preview" src="{{.Brand.OGImage}}" alt="OG"/></p>
|
||
<form method="post" action="/admin/settings/brand/clear" class="j13-inline-form" onsubmit="return confirm('清除 OG 图?');">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<input type="hidden" name="kind" value="og_image"/>
|
||
<button type="submit" class="j13-linkbtn">清除</button>
|
||
</form>
|
||
{{else}}
|
||
<p class="j13-muted">未设置(回落 Logo / Favicon)</p>
|
||
{{end}}
|
||
<form method="post" action="/admin/settings/brand/upload" enctype="multipart/form-data" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<input type="hidden" name="kind" value="og_image"/>
|
||
<label>上传 <input type="file" name="file" accept="image/*" required/></label>
|
||
<button type="submit">上传 OG 图</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<h2>基础限流</h2>
|
||
<p class="j13-muted">窗口内允许的操作次数(秒)。</p>
|
||
<form method="post" action="/admin/settings/limits" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<label>发帖 <input name="rate_limit_post" type="number" min="1" value="{{.RatePost}}"/></label>
|
||
<label>评论 <input name="rate_limit_comment" type="number" min="1" value="{{.RateComment}}"/></label>
|
||
<label>注册 <input name="rate_limit_register" type="number" min="1" value="{{.RateReg}}"/></label>
|
||
<label>登录 <input name="rate_limit_login" type="number" min="1" value="{{.RateLogin}}"/></label>
|
||
<label>窗口秒数 <input name="rate_limit_window_sec" type="number" min="10" value="{{.RateWindow}}"/></label>
|
||
<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">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<ul class="j13-admin-aside-widgets">
|
||
{{range .AsideWidgets}}
|
||
<li>
|
||
<input type="hidden" name="order" value="{{.ID}}"/>
|
||
<label class="j13-check"><input type="checkbox" name="enabled" value="{{.ID}}"{{if .Enabled}} checked{{end}}/> {{.Label}}</label>
|
||
<span class="j13-admin-aside-move">
|
||
{{if .CanMoveUp}}<button type="submit" name="move" value="up:{{.ID}}" class="j13-btn-secondary">上移</button>{{end}}
|
||
{{if .CanMoveDown}}<button type="submit" name="move" value="down:{{.ID}}" class="j13-btn-secondary">下移</button>{{end}}
|
||
</span>
|
||
</li>
|
||
{{end}}
|
||
</ul>
|
||
<button type="submit">保存侧栏</button>
|
||
</form>
|
||
|
||
<h2>敏感词(有效 {{.FilterCount}} 个)</h2>
|
||
<p class="j13-muted">每行一个词,# 开头为注释。保存后立即热更新。</p>
|
||
<form method="post" action="/admin/settings/filter-words" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<label>词表 <textarea name="filter_words" rows="12">{{.FilterWords}}</textarea></label>
|
||
<button type="submit">保存敏感词</button>
|
||
</form>
|
||
|
||
<h2>邮件 SMTP</h2>
|
||
<p class="j13-muted">启用后可用于注册验证码、忘记密码重置与通知。{{if .MailReady}}当前:已就绪。{{else}}当前:未就绪。{{end}}{{if .Mail.HasPassword}} 已保存密码。{{end}}</p>
|
||
<form method="post" action="/admin/settings/mail" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<label class="j13-check"><input type="checkbox" name="enabled" value="1"{{if .Mail.Enabled}} checked{{end}}/> 启用邮件</label>
|
||
<label>SMTP Host <input name="host" value="{{.Mail.Host}}" placeholder="smtp.example.com"/></label>
|
||
<label>端口 <input name="port" type="number" min="1" value="{{.Mail.Port}}"/></label>
|
||
<label>加密
|
||
<select name="encryption">
|
||
<option value="ssl"{{if eq .Mail.Encryption "ssl"}} selected{{end}}>SSL</option>
|
||
<option value="starttls"{{if eq .Mail.Encryption "starttls"}} selected{{end}}>STARTTLS</option>
|
||
<option value="none"{{if eq .Mail.Encryption "none"}} selected{{end}}>无</option>
|
||
</select>
|
||
</label>
|
||
<label>用户名 <input name="username" value="{{.Mail.Username}}" autocomplete="off"/></label>
|
||
<label>密码 <input name="password" type="password" value="" autocomplete="new-password" placeholder="留空表示不修改"/></label>
|
||
<label>发件人 From <input name="from" type="email" value="{{.Mail.From}}"/></label>
|
||
<label>发件人显示名 <input name="from_name" value="{{.Mail.FromName}}"/></label>
|
||
<button type="submit">保存邮件设置</button>
|
||
</form>
|
||
<form method="post" action="/admin/settings/mail/test" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<label>测试收件邮箱 <input name="test_to" type="email" required placeholder="you@example.com"/></label>
|
||
<button type="submit" class="j13-btn-secondary">发送测试信</button>
|
||
</form>
|
||
|
||
<h2>SQLite 备份</h2>
|
||
<p class="j13-muted">将当前数据库文件复制到 data 目录并下载。备份含用户哈希、私信等全库数据,请妥善保管。仅支持 SQLite;其它引擎请使用库方工具。</p>
|
||
{{if .CanBackup}}
|
||
<form method="post" action="/admin/settings/backup" class="j13-form j13-admin-form">
|
||
<input type="hidden" name="_csrf" value="{{.CSRF}}"/>
|
||
<button type="submit">立即备份并下载</button>
|
||
</form>
|
||
{{else}}
|
||
<p class="j13-muted">当前不是 SQLite,一键文件备份不可用。</p>
|
||
{{end}}
|
||
</main>
|
||
{{template "base/footer" .}}
|
||
{{end}}
|