fix templates v1
This commit is contained in:
@@ -187,6 +187,7 @@
|
||||
<details class="uk-card uk-card-default uk-card-body tb-changelog">
|
||||
<summary>近期更新</summary>
|
||||
<ul class="tb-list">
|
||||
<li><strong>2026.10</strong> 优化前端显示,增加主题编辑器功能,预置3套主题,并添加了问题页面“进入下一条未读提问”的功能,优化可用性。</li>
|
||||
<li><strong>2026.9</strong> 新增审核严格度选项,增加提问、投票、私聊的总开关,可设置定时收集、定量收集或关闭功能,前后端显示也更易用了。</li>
|
||||
<li><strong>2026.8</strong> 新增<a href="https://box.shiroko.one/vote/sANyLkiBNUGN">投票功能</a>、追加提问、多语言、<a href="https://box.shiroko.one/_/tamakyi/2894">Markdown 显示</a>、置顶显示等,详情见<a href="https://blog.shiroko.one/record/tamabox_changelog_20260813">这里</a>。</li>
|
||||
<li><strong>2026.8</strong> 放弃使用 recaptcha 等对国内用户不友好的验证方式,更新密码加密方式,修复图片上传等一系列问题。</li>
|
||||
|
||||
@@ -14,6 +14,37 @@
|
||||
height: 40px;
|
||||
line-height: 38px;
|
||||
}
|
||||
/* 页脚次级操作之间的分隔:返回提问箱 / 下一条未读 靠在一起会连成一片 */
|
||||
.tb-foot-sep {
|
||||
margin: 0 4px;
|
||||
color: #b0b6bd;
|
||||
}
|
||||
html[data-theme="dark"] .tb-foot-sep {
|
||||
color: #5c6674;
|
||||
}
|
||||
/* 手机端三个按钮在 300px 内放不下一行(实测需 416px):
|
||||
保留原来的「回答 / 标记为已读」一行不动,让「回答并下一条未读」独占下一行整行宽度。
|
||||
display:contents 把两个提交按钮提升为该行的直接子项,才能用 order 把它排到状态按钮之后。 */
|
||||
@media (max-width: 640px) {
|
||||
.tb-ans-actions {
|
||||
display: contents;
|
||||
}
|
||||
.tb-ans-actions .uk-button {
|
||||
order: 1;
|
||||
}
|
||||
.tb-ans-state {
|
||||
order: 2;
|
||||
margin-left: auto;
|
||||
}
|
||||
.tb-ans-next {
|
||||
order: 3;
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
/* 上面 .tb-ans-actions .uk-button 的 order:1 特异性更高,这里必须同级别盖回去 */
|
||||
.tb-ans-actions .uk-button.tb-ans-next {
|
||||
order: 3;
|
||||
}
|
||||
}
|
||||
.tb-followup-card {
|
||||
border: 1px solid #e7e9ec;
|
||||
border-left: 3px solid #b0b6bd;
|
||||
@@ -245,7 +276,7 @@
|
||||
<div class="uk-card-body uk-padding-remove-top">
|
||||
<hr>
|
||||
<h5 class="uk-text-center">{{t .LangCode "qitem.answerTitle"}}</h5>
|
||||
<form id="tb-answer-form" method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/answer" enctype="multipart/form-data">
|
||||
<form id="tb-answer-form" method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/answer{{ if .NextQuery }}?{{ .NextQuery }}{{ end }}" enctype="multipart/form-data">
|
||||
{{ .CSRFTokenHTML }}
|
||||
<div class="uk-margin uk-text-center">
|
||||
<textarea name="answer" class="uk-textarea" rows="5" maxlength="{{ .Limits.AnswerContentLen }}"
|
||||
@@ -268,8 +299,13 @@
|
||||
</form>
|
||||
<!-- 回答(左)+ 阅读状态(右)同一行,压缩空间;tb-ans-row 保证左右按钮等高 -->
|
||||
<div class="uk-flex uk-flex-middle uk-flex-wrap uk-margin-small-top tb-ans-row" style="gap: 12px; justify-content: space-between;">
|
||||
<button type="submit" form="tb-answer-form" class="uk-button uk-button-primary">{{t .LangCode "qitem.submitAnswer"}}</button>
|
||||
<div class="uk-flex uk-flex-middle uk-flex-wrap" style="gap: 8px;">
|
||||
<div class="uk-flex uk-flex-middle uk-flex-wrap tb-ans-actions" style="gap: 8px;">
|
||||
<button type="submit" form="tb-answer-form" class="uk-button uk-button-primary">{{t .LangCode "qitem.submitAnswer"}}</button>
|
||||
{{ if .NextUnreadID }}
|
||||
<button type="submit" form="tb-answer-form" name="next" value="1" class="uk-button uk-button-default tb-ans-next">{{t .LangCode "qitem.submitAndNext"}}</button>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="uk-flex uk-flex-middle uk-flex-wrap tb-ans-state" style="gap: 8px;">
|
||||
{{ if .Question.IsRead }}
|
||||
<span class="uk-text-small uk-text-muted">✓ {{t .LangCode "qlist.read"}}</span>
|
||||
<form class="uk-display-inline" method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/unread">
|
||||
@@ -397,6 +433,14 @@
|
||||
{{ $backTo := printf "/_/%s" .PageUser.Domain }}
|
||||
{{ if eq .BackFrom "admin" }}{{ $backTo = .BackTo }}{{ end }}
|
||||
<a class="uk-button uk-button-link" href="{{ $backTo }}">{{t .LangCode "qitem.backToBox" .PageUser.Name}}</a>
|
||||
{{ if and .CanDelete .NextUnreadID }}
|
||||
<!-- 下一条未读:标记本条已读并跳转,会改状态,故用 POST 表单而非链接 -->
|
||||
<span class="tb-foot-sep" aria-hidden="true">·</span>
|
||||
<form class="uk-display-inline" method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/next-unread{{ if .NextQuery }}?{{ .NextQuery }}{{ end }}">
|
||||
{{ .CSRFTokenHTML }}
|
||||
<button type="submit" class="uk-button uk-button-link" title="{{t .LangCode "qitem.nextUnreadTitle"}}">{{t .LangCode "qitem.nextUnread"}} ›</button>
|
||||
</form>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<!-- Box owner can't create new question here. -->
|
||||
|
||||
@@ -178,6 +178,7 @@ func TestGenPreview(t *testing.T) {
|
||||
// 每个页面作用域(data-page-scope)各一份。新增页面时要同步 dev/theme-builder/index.html
|
||||
// 的 SCOPES 列表,否则生成器里选不到。
|
||||
writeQuestionItemPreviews(t, outDir)
|
||||
writeQuestionOwnerPreviews(t, outDir)
|
||||
writeAdminListPreviews(t, outDir)
|
||||
writeVotePreviews(t, outDir)
|
||||
}
|
||||
@@ -213,6 +214,44 @@ func writeQuestionItemPreviews(t *testing.T, outDir string) {
|
||||
}
|
||||
}
|
||||
|
||||
// writeQuestionOwnerPreviews 单题页的箱主视角:回答行有「回答并下一条」、页脚有「下一条未读」,
|
||||
// 未回答 / 已回答两种状态都要能肉眼核对排版。
|
||||
func writeQuestionOwnerPreviews(t *testing.T, outDir string) {
|
||||
t.Helper()
|
||||
for _, state := range []struct {
|
||||
name string
|
||||
answer string
|
||||
}{
|
||||
{"unanswered", ""},
|
||||
{"answered", "沿着河堤一直往西,到海边的旧仓库就掉头。"},
|
||||
} {
|
||||
for _, theme := range []string{"light", "dark"} {
|
||||
data := publicBaseData()
|
||||
data["VConsole"] = false
|
||||
data["CanDelete"] = true
|
||||
data["IsOwnPage"] = true
|
||||
data["NextUnreadID"] = uint(2)
|
||||
data["Question"] = map[string]interface{}{
|
||||
"ID": 1, "Content": "你平时一个人骑车会去哪里?", "Answer": state.answer,
|
||||
"CreatedAt": time.Now(), "UpdatedAt": time.Now(),
|
||||
"IsPrivate": false, "IsPinned": false, "IsRead": state.answer != "",
|
||||
"Token": "abc123", "ReceiveReplyEmail": "",
|
||||
}
|
||||
data["QuestionToken"] = "abc123"
|
||||
data["AskUploadImages"] = []interface{}{}
|
||||
data["AnswerUploadImages"] = []interface{}{}
|
||||
data["FollowUps"] = []interface{}{}
|
||||
data["CanFollowUp"] = false
|
||||
data["IsQuestioner"] = false
|
||||
page, err := renderToString(t, "question/item", data)
|
||||
if err != nil {
|
||||
t.Fatalf("render question/item owner: %v", err)
|
||||
}
|
||||
writePreview(t, outDir, "preview-question-owner-"+state.name+"-"+theme+".html", page, theme, "../static")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// writeAdminListPreviews 箱主后台的问题列表(/user/questions)。
|
||||
func writeAdminListPreviews(t *testing.T, outDir string) {
|
||||
t.Helper()
|
||||
|
||||
Reference in New Issue
Block a user