This commit is contained in:
tamakyi
2026-09-08 10:10:44 +08:00
commit 2ed27dd55e
288 changed files with 67061 additions and 0 deletions
+425
View File
@@ -0,0 +1,425 @@
{{template "base/header" .}}
<link rel="shortcut icon"
href="{{.PageUser.Avatar}}?x-oss-process=image/auto-orient,1/quality,q_70/sharpen,200/resize,limit_0,m_fill,w_200,h_200"/>
<link rel="apple-touch-icon"
href="{{.PageUser.Avatar}}?x-oss-process=image/auto-orient,1/quality,q_70/sharpen,200/resize,limit_0,m_fill,w_200,h_200"/>
<link rel="icon" sizes="192x192"
href="{{.PageUser.Avatar}}?x-oss-process=image/auto-orient,1/quality,q_70/sharpen,200/resize,limit_0,m_fill,w_200,h_200">
<style>
a.uk-button.uk-button-link {
text-transform: none;
}
/* 回答行:左侧「回答」与右侧「标记为已读/标记为未读」按钮等高 */
.tb-ans-row .uk-button {
height: 40px;
line-height: 38px;
}
.tb-followup-card {
border: 1px solid #e7e9ec;
border-left: 3px solid #b0b6bd;
border-radius: 8px;
padding: 12px 14px;
background: #fbfbfc;
}
html[data-theme="dark"] .tb-followup-card {
background: #1b1e23;
border-color: #2c2f36;
border-left-color: #3a4250;
}
html[data-theme="dark"] .tb-followup-card .uk-button-default {
background-color: #2c2f36;
color: #e5e9ec;
border-color: #3a4250;
}
html[data-theme="dark"] .tb-followup-card .uk-button-default:hover {
background-color: #353941;
color: #ffffff;
}
.tb-img-uploader {
width: 100%;
background-color: #f8f8f8;
display: flex;
padding-top: 5px;
padding-bottom: 5px;
align-items: center;
justify-content: flex-start;
gap: 5px;
}
html[data-theme="dark"] .tb-img-uploader {
background-color: #1b1e23;
}
</style>
<div>
<div class="uk-card uk-card-default">
<div class="uk-card-header">
<div class="uk-text-left uk-text-small uk-text-muted">{{Date .Question.CreatedAt "Y-m-d H:i:s"}}</div>
<div class="md-body uk-text-break uk-margin-top uk-margin-bottom">{{MarkdownFormat .Question.Content}}</div>
{{ if .AskUploadImages }}
<ul class="uk-thumbnav" uk-margin>
{{ range $index, $elem := .AskUploadImages }}
<div uk-lightbox>
<a href="https://{{ ImageBucketCDNHost }}/{{ $elem.Key }}">
<img class="uk-border-rounded uk-object-fill" src="https://{{ ImageBucketCDNHost }}/{{ $elem.Key }}" width="100" height="100" alt="">
</a>
</div>
{{ end }}
</ul>
{{ end }}
</div>
{{if ne .Question.Answer ""}}
<div class="uk-card-body">
<!--<div class="uk-text-left uk-text-small uk-text-muted">{{Date .Question.UpdatedAt "Y-m-d H:i:s"}}</div>-->
<div id="answer-display">
<div class="md-body uk-text-break">{{MarkdownFormat .Question.Answer}}</div>
{{ if .AnswerUploadImages }}
<ul class="uk-thumbnav" uk-margin>
{{ range $index, $elem := .AnswerUploadImages }}
<div uk-lightbox>
<a href="https://{{ ImageBucketCDNHost }}/{{ $elem.Key }}">
<img class="uk-border-rounded uk-object-fill" src="https://{{ ImageBucketCDNHost }}/{{ $elem.Key }}" width="100" height="100" alt="">
</a>
</div>
{{ end }}
</ul>
{{ end }}
</div>
<p class="uk-text-small uk-text-right uk-text-muted">{{t .LangCode "qitem.answeredBy" .PageUser.Name (Date .Question.UpdatedAt "Y-m-d H:i:s")}}</p>
<!-- 分享此提问(左)与 更新回答(右)一左一右分开;箱主未登录(无更新回答按钮)时分享按钮居中;编辑区在下方由 tbToggleAnswerEditor 控制 -->
<div class="uk-flex uk-flex-middle uk-flex-wrap uk-margin-small-top {{ if not .CanDelete }}uk-flex-center{{ end }}" style="gap: 8px;">
{{ if and (not .Question.IsPrivate) (ne .Question.Answer "") }}
<a class="uk-button uk-button-default uk-button-small" href="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/share-card" target="_blank">📤 {{t .LangCode "qitem.shareCard"}}</a>
{{ end }}
{{ if .CanDelete }}
<div id="answer-edit-trigger" style="margin-left: auto;">
<button type="button" class="uk-button uk-button-default uk-button-small" onclick="tbToggleAnswerEditor()">{{t .LangCode "qitem.updateAnswer"}}</button>
</div>
{{ end }}
</div>
{{ if not .CanDelete }}
<div id="waline"></div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const waline = Waline.init({
el: '#waline',
//后端服务器地址
serverURL: 'https://waline.337845818.best/',
path: window.location.href,
// 中文默认
locale: {
nick: '昵称',
nickError: '昵称不能少于3个字符',
mail: '邮箱',
mailError: '请填写正确的邮件地址',
link: '网址',
optional: '可选',
placeholder: '欢迎评论(需要手工审核,不会立即展现)',
sofa: '来发评论吧~',
submit: '提交',
like: '喜欢',
cancelLike: '取消喜欢',
reply: '回复',
cancelReply: '取消回复',
comment: '评论',
refresh: '刷新',
more: '加载更多...',
preview: '预览',
emoji: '表情',
uploadImage: '上传图片',
seconds: '秒前',
minutes: '分钟前',
hours: '小时前',
days: '天前',
now: '刚刚',
uploading: '正在上传',
login: '登录',
logout: '退出',
admin: '博主',
sticky: '置顶',
word: '字',
wordHint: '评论字数应在 $0 到 $1 字之间!\n当前字数:$2',
anonymous: '无名小狼',
level0: '潜水',
level1: '冒泡',
level2: '吐槽',
level3: '活跃',
level4: '话痨',
level5: '传说',
gif: '表情包',
gifSearchPlaceholder: '搜索表情包',
profile: '个人资料',
approved: '通过',
waiting: '待审核',
spam: '垃圾',
unsticky: '取消置顶',
oldest: '按倒序',
latest: '按正序',
hottest: '按热度',
reactionTitle: '',
reaction0: '哇哦',
reaction1: 'prpr',
reaction2: '流汗',
reaction3: '生气',
reaction4: '流鼻血',
reaction5: 'あべ',
},
reaction: [
'https://ali-imgs.acfun.cn/kimg/bs2/zt-image-host/ChYwOGQ3OTRhYzRjMTBkZmZhZDVmZTA1EIjM1y8.gif',
'https://ali-imgs.acfun.cn/kimg/bs2/zt-image-host/ChQwOGEyOTlhYzRjMTBmOWFkZjAwYRCIzNcv.gif',
'https://ali-imgs.acfun.cn/kimg/bs2/zt-image-host/ChYwOGRhOTVhYzRjMTBkNmViYTVlNTA2EIjM1y8.gif',
'https://ali-imgs.acfun.cn/kimg/bs2/zt-image-host/ChYwOGU1OTJhYzRjMTBmMzk3ZmVmNTAyEIjM1y8.gif',
'https://ali-imgs.acfun.cn/kimg/bs2/zt-image-host/ChYwOGNkODdhYzRjMTBjYmEwOTFjNjAxEIjM1y8.gif',
'https://ali-imgs.acfun.cn/kimg/bs2/zt-image-host/ChQwODliOGVhYzRjMTBmOGM0ZWY1ZRCIzNcv.gif',
],
meta: ['nick','mail'],
requiredMeta: ['mail'],
pageview: true,
search: false,
comment: false,
login: 'disable',
wordLimit: 50,
pageSize: 5,
avatar: 'monsterid',
emoji: [
'https://gcore.jsdelivr.net/gh/tamakyi/emoji-collection@main/acfun-color/60x60',
],
//禁止图片上传按钮
imageUploader: false,
//不显示版权标志
copyright: false,
});
});
</script>
{{ end }}
{{ if .CanDelete }}
<div id="answer-editor" style="display:none;">
<hr>
<form method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/answer" enctype="multipart/form-data">
{{ .CSRFTokenHTML }}
<div class="uk-margin uk-text-center">
<textarea name="answer" class="uk-textarea" rows="5" maxlength="{{ .Limits.AnswerContentLen }}"
placeholder="{{t .LangCode "qitem.answerPlaceholder"}}">{{ .Question.Answer }}</textarea>
<div x-data="{ files: null }" class="tb-img-uploader">
<div uk-form-custom>
<a href="#" class="uk-icon-link" uk-icon="image" style="margin-left: 10px"></a>
<span style="font-size: 12px" x-text="files ? files[0].name : '{{t .LangCode "ask.addImage"}}'"></span>
<input id="uploader" name="images" type="file" accept="image/*" x-on:change="files = Object.values($event.target.files)">
</div>
<button x-show="files" type="button" class="uk-icon-link" uk-icon="close" style="margin-left: 10px;"
@click="files = null"></button>
</div>
</div>
{{ if ne .Question.ReceiveReplyEmail "" }}
<div class="uk-alert-warning uk-text-small" uk-alert>
<p>{{t .LangCode "qitem.emailNotifyHint"}}</p>
</div>
{{ end }}
<div class="uk-margin uk-text-center">
<button type="submit" class="uk-button uk-button-primary uk-button-small">{{t .LangCode "qitem.updateAnswer"}}</button>
<button type="button" class="uk-button uk-button-default uk-button-small uk-margin-small-left" onclick="tbToggleAnswerEditor()">{{t .LangCode "common.cancel"}}</button>
</div>
</form>
</div>
{{ end }}
</div>
{{ else if .CanDelete }}
<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">
{{ .CSRFTokenHTML }}
<div class="uk-margin uk-text-center">
<textarea name="answer" class="uk-textarea" rows="5" maxlength="{{ .Limits.AnswerContentLen }}"
placeholder="{{t .LangCode "qitem.answerPlaceholder"}}">{{ .answer }}</textarea>
<div x-data="{ files: null }" style="width: 100%; background-color: #f8f8f8; display: flex; padding-top: 5px; padding-bottom: 5px; align-items: center; justify-content: start;gap: 5px">
<div uk-form-custom>
<a href="#" class="uk-icon-link" uk-icon="image" style="margin-left: 10px"></a>
<span style="font-size: 12px" x-text="files ? files[0].name : '{{t .LangCode "ask.addImage"}}'"></span>
<input id="uploader" name="images" type="file" accept="image/*" x-on:change="files = Object.values($event.target.files)">
</div>
<button x-show="files" type="button" class="uk-icon-link" uk-icon="close" style="margin-left: 10px;"
@click="files = null"></button>
</div>
</div>
{{ if ne .Question.ReceiveReplyEmail "" }}
<div class="uk-alert-warning uk-text-small" uk-alert>
<p>{{t .LangCode "qitem.emailNotifyHint"}}</p>
</div>
{{ end }}
</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;">
{{ 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">
{{ .CSRFTokenHTML }}
<button type="submit" class="uk-button uk-button-default">{{t .LangCode "qitem.markUnread"}}</button>
</form>
{{ else }}
<form method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/read">
{{ .CSRFTokenHTML }}
<button type="submit" class="uk-button uk-button-default">{{t .LangCode "qitem.markRead"}}</button>
</form>
{{ end }}
</div>
</div>
</div>
{{ end }}
<!-- 已回答的阅读状态(箱主):该行仅此一个元素,居中显示 -->
{{ if and .CanDelete (ne .Question.Answer "") }}
<div class="uk-card-body uk-padding-remove-top">
<div class="uk-text-center">
<span class="uk-label uk-label-success">✓ {{t .LangCode "qlist.read"}}</span>
<span class="uk-text-small uk-text-muted">{{t .LangCode "qitem.readLocked"}}</span>
</div>
</div>
{{ end }}
{{ if .FollowUps }}
<div class="uk-card-body uk-padding-remove-top">
{{ range $index, $elem := .FollowUps }}
<div class="tb-followup-card uk-margin-small-bottom">
<p class="uk-text-small uk-text-break uk-margin-remove-bottom"><strong>{{t $.LangCode "followup.content"}}</strong>{{ $elem.Content }}</p>
{{ if ne $elem.Answer "" }}
{{ if $.CanDelete }}
<div id="fu-display-{{ $index }}" class="uk-text-small uk-text-muted uk-text-break uk-margin-small-top">@{{ $.PageUser.Name }}:{{ MarkdownFormat $elem.Answer }}</div>
<div class="uk-margin-small-top uk-text-right">
<button type="button" class="uk-button uk-button-default uk-button-small" onclick="tbToggleFollowUpEditor({{ $index }})">{{t $.LangCode "qitem.updateAnswer"}}</button>
</div>
<div id="fu-editor-{{ $index }}" style="display:none;">
<hr>
<form method="post" action="/_/{{ $.PageUser.Domain }}/{{ $.Question.ID }}/follow-up/{{ $elem.ID }}/answer" class="uk-margin-small-top">
{{ $.CSRFTokenHTML }}
<textarea name="answer" class="uk-textarea" rows="3" maxlength="{{ $.Limits.AnswerContentLen }}" placeholder="{{t $.LangCode "followup.answerPlaceholder"}}">{{ $elem.Answer }}</textarea>
<div class="uk-margin-small-top uk-text-right">
<button type="submit" class="uk-button uk-button-primary uk-button-small">{{t $.LangCode "qitem.updateAnswer"}}</button>
<button type="button" class="uk-button uk-button-default uk-button-small uk-margin-small-left" onclick="tbToggleFollowUpEditor({{ $index }})">{{t $.LangCode "common.cancel"}}</button>
</div>
</form>
</div>
{{ else }}
<div class="uk-text-small uk-text-muted uk-text-break uk-margin-small-top">@{{ $.PageUser.Name }}:{{ MarkdownFormat $elem.Answer }}</div>
{{ end }}
{{ else if $.CanDelete }}
<form method="post" action="/_/{{ $.PageUser.Domain }}/{{ $.Question.ID }}/follow-up/{{ $elem.ID }}/answer" class="uk-margin-small-top">
{{ $.CSRFTokenHTML }}
<textarea name="answer" class="uk-textarea" rows="3" maxlength="{{ $.Limits.AnswerContentLen }}" placeholder="{{t $.LangCode "followup.answerPlaceholder"}}"></textarea>
<div class="uk-margin-small-top uk-text-right">
<button type="submit" class="uk-button uk-button-primary uk-button-small">{{t $.LangCode "followup.answerBtn"}}</button>
</div>
</form>
{{ else }}
<p class="uk-text-small uk-text-muted uk-margin-small-top">{{t $.LangCode "followup.waiting"}}</p>
{{ end }}
</div>
{{ end }}
</div>
{{ end }}
{{ if and .CanFollowUp (not .CanDelete) }}
<div class="uk-card-body uk-padding-remove-top">
<div class="tb-followup-card">
<h5 class="uk-margin-remove-bottom">{{t .LangCode "followup.askMore"}}</h5>
<p class="uk-text-small uk-text-muted">{{t .LangCode "followup.remaining" .FollowUpRemaining .FollowUpLimit}}</p>
<form method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/follow-up">
{{ .CSRFTokenHTML }}
<input type="hidden" name="token" value="{{ .QuestionToken }}">
<textarea name="content" class="uk-textarea" rows="3" maxlength="{{ .Limits.FollowUpContentLen }}" placeholder="{{t .LangCode "followup.contentPlaceholder"}}"></textarea>
<div class="uk-margin uk-text-center">
<button type="submit" class="uk-button uk-button-primary">{{t .LangCode "followup.submit"}}</button>
</div>
</form>
</div>
</div>
{{ end }}
{{ if and .WaitingFollowUpReply (not .CanDelete) }}
<div class="uk-card-body uk-padding-remove-top">
<div class="tb-followup-card uk-text-small uk-text-muted uk-text-center">{{t .LangCode "followup.waitingReply"}}</div>
</div>
{{ end }}
<div class="uk-card-footer">
{{template "base/alert" .}}
{{ if .CanDelete }}
{{ if .Question.IsPrivate }}
<form class="uk-float-right" method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/set-public">
{{ .CSRFTokenHTML }}
<button type="submit" class="uk-button uk-button-default uk-button-small">{{t .LangCode "qitem.public"}}</button>
</form>
{{ else }}
<form class="uk-float-right" method="post" action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/set-private">
{{ .CSRFTokenHTML }}
<button type="submit" class="uk-button uk-button-default uk-button-small">{{t .LangCode "qitem.private"}}</button>
</form>
{{ end }}
<a class="uk-button uk-button-danger uk-button-small" href="#">{{t .LangCode "qitem.delete"}}</a>
<div class="uk-dropbar uk-dropbar-top" uk-drop="stretch: x; mode: click">
<div class="uk-card uk-card-default uk-card-body">
<h3 class="uk-card-title">{{t .LangCode "qitem.danger"}}</h3>
<p>{{t .LangCode "qitem.deleteConfirm"}}</p>
<form class="uk-float-right"
method="post"
action="/_/{{ .PageUser.Domain }}/{{ .Question.ID }}/delete">
{{ .CSRFTokenHTML }}
<button class="uk-button uk-button-danger">{{t .LangCode "qitem.deleteConfirmBtn"}}</button>
</form>
</div>
</div>
{{ end }}
<div class="uk-margin uk-text-center">
{{ $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>
</div>
<!-- Box owner can't create new question here. -->
{{if not .IsOwnPage }}
<h5 class="uk-text-center">{{t .LangCode "qitem.askMore"}}</h5>
{{template "question/new-question-template" .}}
{{ end }}
<hr class="uk-divider-icon">
<p class="uk-text-left uk-text-muted uk-text-small">{{t .LangCode "ask.history" .PageUser.Name}} ({{ .AnsweredCount }})</p>
{{ template "question/history-template" . }}
</div>
</div>
</div>
<script>
function tbToggleAnswerEditor() {
var disp = document.getElementById('answer-display');
var trig = document.getElementById('answer-edit-trigger');
var ed = document.getElementById('answer-editor');
if (!ed) return;
if (ed.style.display === 'none') {
ed.style.display = 'block';
if (disp) disp.style.display = 'none';
if (trig) trig.style.display = 'none';
} else {
ed.style.display = 'none';
if (disp) disp.style.display = 'block';
if (trig) trig.style.display = 'block';
}
}
function tbToggleFollowUpEditor(idx) {
var disp = document.getElementById('fu-display-' + idx);
var ed = document.getElementById('fu-editor-' + idx);
if (!ed) return;
if (ed.style.display === 'none') {
ed.style.display = 'block';
if (disp) disp.style.display = 'none';
} else {
ed.style.display = 'none';
if (disp) disp.style.display = 'block';
}
}
</script>
{{template "base/footer" .}}