Files
tamabox/templates/user/question-list.html
T
2026-10-18 23:32:38 +08:00

504 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{template "base/header" .}}
<style>
.qlist-tabs {
display: flex;
justify-content: center;
gap: 4px;
padding: 4px;
margin: 6px auto 20px;
max-width: 320px;
border: 1px solid #e5e5e5;
border-radius: 9px;
background: #fafafa;
}
.qlist-tab {
flex: 1 1 0;
border: 0;
border-radius: 6px;
padding: 8px 15px;
background: transparent;
color: #666;
cursor: pointer;
font-size: 0.9rem;
transition: background 0.2s ease, color 0.2s ease;
}
.qlist-tab:hover { color: #1e87f0; }
.qlist-tab.is-active {
background: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.10);
color: #1e87f0;
font-weight: 600;
}
.qlist-panel[hidden] { display: none !important; }
.all-votes-list { display: grid; gap: 10px; }
.all-vote-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 14px 16px;
border-bottom: 1px solid #e9e9e9;
text-decoration: none;
}
.all-vote-item:first-child { border-top: 1px solid #e9e9e9; }
.all-vote-item:hover { background: #f8fbff; text-decoration: none; }
.all-vote-item .hot-vote-title { max-width: 100%; }
.hot-vote-title {
display: block;
overflow: hidden;
color: #333;
font-size: 0.98rem;
font-weight: 600;
line-height: 1.45;
text-overflow: ellipsis;
white-space: nowrap;
}
.hot-vote-title:hover { color: #1e87f0; }
.hot-vote-meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 7px;
margin-top: 8px;
}
.hot-vote-meta .uk-label { font-size: 0.72rem; line-height: 1.6; }
.hot-vote-action { flex: 0 0 auto; color: #1e87f0; font-size: 0.82rem; white-space: nowrap; }
/* 提问列表右上角:状态标签与操作按钮统一尺寸(等宽等高、垂直居中、完全对齐)。
每个元素显式带 .qlist-pill 类,选择器挂在 .qlist-pills 容器下提升优先级,
避免浏览器对 <button> 的默认样式或 UIkit .uk-label 造成差异。
移动端默认显示短文字标签(每语言短词,如 未读→新/New,宽度可控);
≥640px 显示完整文案(配合 title 悬浮提示,多语言安全)。 */
.qlist-pills .qlist-pill {
display: inline-flex;
align-items: center;
justify-content: center;
height: 24px;
min-width: 40px;
padding: 0 8px;
box-sizing: border-box;
font-size: 0.72rem;
line-height: 1;
white-space: nowrap;
border-radius: 2px;
border: 0;
vertical-align: middle;
}
.qlist-pills .tb-short { display: inline; }
.qlist-pills .tb-text { display: none; }
/* 按钮额外重置浏览器默认样式,保证与 span 标签渲染完全一致 */
.qlist-pills .qlist-pill.tb-label-btn {
cursor: pointer;
font-family: inherit;
-webkit-appearance: none;
appearance: none;
background-image: none;
outline: none;
margin: 0;
}
.qlist-pills .qlist-pill.tb-label-btn:hover { opacity: 0.85; }
@media (min-width: 640px) {
/* 桌面端纯文字:隐藏移动端短词,只显示完整文案 */
.qlist-pills .qlist-pill { min-width: 62px; padding: 0 10px; }
.qlist-pills .tb-short { display: none; }
.qlist-pills .tb-text { display: inline; }
}
html[data-theme="dark"] .qlist-tabs { border-color: var(--tb-border); background: var(--tb-surface-2); }
html[data-theme="dark"] .qlist-tab { color: var(--tb-text-muted); }
html[data-theme="dark"] .qlist-tab.is-active { background: var(--tb-surface); color: var(--tb-primary); }
html[data-theme="dark"] .all-vote-item { border-color: var(--tb-border); }
html[data-theme="dark"] .all-vote-item:hover { background: rgba(78, 168, 245, 0.10); }
html[data-theme="dark"] .hot-vote-title { color: var(--tb-text); }
/* 紧凑统计看板:替代原 UIkit 卡片网格。手机端 4 列(7 项=2 行)、桌面端 7 列 1 行,
轻量描边小格子、缩字号、去掉大卡片内边距,显著降低纵向高度,减少手机端滚动。
--4 修饰类用于项数较少的看板(如私聊 4 项),在所有断点固定 4 列,避免末尾留白过多。 */
.qlist-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
margin-bottom: 16px;
}
@media (min-width: 768px) {
.qlist-stats { grid-template-columns: repeat(7, 1fr); }
}
.qlist-stats--4 { grid-template-columns: repeat(4, 1fr); }
@media (min-width: 768px) {
.qlist-stats--4 { grid-template-columns: repeat(4, 1fr); }
}
/* --2 修饰类用于项数很少的看板(如投票 2 项),固定 2 列,避免末尾留白 */
.qlist-stats--2 { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) {
.qlist-stats--2 { grid-template-columns: repeat(2, 1fr); }
}
.qlist-stat {
background: #fff;
border: 1px solid #e5e5e5;
border-radius: 9px;
padding: 8px 6px;
text-align: center;
}
.qlist-stat .qlist-stat-num {
display: block;
font-size: 1.15rem;
font-weight: 700;
line-height: 1.15;
color: #222;
}
.qlist-stat .qlist-stat-lbl {
display: block;
margin-top: 2px;
font-size: 0.7rem;
color: #888;
line-height: 1.15;
}
html[data-theme="dark"] .qlist-stat { background: var(--tb-surface); border-color: var(--tb-border); }
html[data-theme="dark"] .qlist-stat .qlist-stat-num { color: var(--tb-text); }
html[data-theme="dark"] .qlist-stat .qlist-stat-lbl { color: var(--tb-text-muted); }
</style>
<div class="uk-container">
<div class="uk-flex uk-flex-middle uk-flex-between uk-margin-small-bottom">
<h2 class="uk-margin-remove">{{t .LangCode "qlist.title"}}</h2>
<a class="uk-button uk-button-default uk-button-small" href="/user/profile">{{t .LangCode "admin.featuresEntry"}}</a>
</div>
<!-- 居中切换:提问 / 投票 / 私聊 -->
<div class="qlist-tabs" role="tablist" aria-label="{{t .LangCode "qlist.title"}}">
<button type="button" class="qlist-tab is-active" data-qlist-tab="questions" role="tab" aria-selected="true">{{t .LangCode "qlist.questionsTab"}}</button>
<button type="button" class="qlist-tab" data-qlist-tab="votes" role="tab" aria-selected="false">{{t .LangCode "qlist.votesTab"}}</button>
<button type="button" class="qlist-tab" data-qlist-tab="chats" role="tab" aria-selected="false">{{t .LangCode "qlist.chatsTab"}}</button>
</div>
<!-- 提问面板(默认展示) -->
<div class="qlist-panel" data-qlist-panel="questions">
<!-- 统一提示区:标记已读/未读、置顶等操作的成功/错误提示沿用 base/alert 样式 -->
{{template "base/alert" .}}
{{ if .RestrictionLevel }}
<!-- 处置期常驻提示:L1 停分发 / L2 新回答不公开 / L3 禁止发布 -->
<div class="uk-alert-warning" uk-alert>
<div>{{t .LangCode "qlist.restrictionBanner" .RestrictionLevel .RestrictionExpiresAt}}</div>
</div>
{{ end }}
<!-- 提问箱统计看板(紧凑多列网格:手机4列/桌面7列,降低纵向高度) -->
<div class="qlist-stats">
<div class="qlist-stat"><span class="qlist-stat-num">{{ .Stats.total }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.statsTotal"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .Stats.answered }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.statsAnswered"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .Stats.unanswered }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.statsUnanswered"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .Stats.read }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.statsRead"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .Stats.unread }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.statsUnread"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .Stats.private }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.statsPrivate"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .Stats.pinned }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.statsPinned"}}</span></div>
</div>
<div class="uk-margin-medium-bottom uk-text-center">
<!-- 全文搜索自己提问箱 -->
<form method="get" action="" class="uk-form-stacked">
<div class="uk-flex uk-flex-center uk-flex-nowrap uk-overflow-auto">
<div class="uk-margin-small-right uk-width-expand" style="max-width: 420px;">
<input type="text" name="q" class="uk-input uk-form-small" value="{{ .Keyword }}" placeholder="{{t .LangCode "qlist.searchPlaceholder"}}" aria-label="{{t .LangCode "qlist.searchPlaceholder"}}">
</div>
<div class="uk-margin-small-right">
<button type="submit" class="uk-button uk-button-primary uk-button-small">{{t .LangCode "qlist.searchBtn"}}</button>
</div>
{{ if ne .Keyword "" }}
<div>
<a class="uk-button uk-button-default uk-button-small" href="/user/questions">{{t .LangCode "qlist.searchClear"}}</a>
</div>
{{ end }}
</div>
</form>
<form method="get" action="" class="uk-form-stacked uk-margin-small-top">
<div class="uk-flex uk-flex-center uk-flex-nowrap uk-overflow-auto">
<div class="uk-margin-small-right" style="width: 120px;">
<label class="uk-form-label uk-text-small">{{t .LangCode "qlist.sort"}}</label>
<select name="sort" class="uk-select uk-form-small" onchange="this.form.submit()" style="width: 100%;">
<option value="latest" {{if eq .SelectedSort "latest"}}selected{{end}}>{{t .LangCode "qlist.latest"}}</option>
<option value="oldest" {{if eq .SelectedSort "oldest"}}selected{{end}}>{{t .LangCode "qlist.oldest"}}</option>
</select>
</div>
<div class="uk-margin-small-right" style="width: 120px;">
<label class="uk-form-label uk-text-small">{{t .LangCode "qlist.status"}}</label>
<select name="status" class="uk-select uk-form-small" onchange="this.form.submit()" style="width: 100%;">
<option value="all" {{if eq .SelectedStatus "all"}}selected{{end}}>{{t .LangCode "qlist.all"}}</option>
<option value="answered" {{if eq .SelectedStatus "answered"}}selected{{end}}>{{t .LangCode "qlist.answered"}}</option>
<option value="unanswered" {{if eq .SelectedStatus "unanswered"}}selected{{end}}>{{t $.LangCode "qlist.unanswered"}}</option>
</select>
</div>
<div class="uk-margin-small-right" style="width: 120px;">
<label class="uk-form-label uk-text-small">{{t .LangCode "qlist.type"}}</label>
<select name="type" class="uk-select uk-form-small" onchange="this.form.submit()" style="width: 100%;">
<option value="all" {{if eq .SelectedType "all"}}selected{{end}}>{{t .LangCode "qlist.all"}}</option>
<option value="public" {{if eq .SelectedType "public"}}selected{{end}}>{{t .LangCode "qlist.public"}}</option>
<option value="private_question" {{if eq .SelectedType "private_question"}}selected{{end}}>{{t .LangCode "qlist.privateQuestion"}}</option>
</select>
</div>
<div class="uk-margin-small-right" style="width: 120px;">
<label class="uk-form-label uk-text-small">{{t .LangCode "qlist.reportFilter"}}</label>
<select name="reported" class="uk-select uk-form-small" onchange="this.form.submit()" style="width: 100%;">
<option value="all" {{if eq .SelectedReported "all"}}selected{{end}}>{{t .LangCode "qlist.all"}}</option>
<option value="reported" {{if eq .SelectedReported "reported"}}selected{{end}}>{{t .LangCode "qlist.reportedOnly"}}</option>
</select>
</div>
<div style="width: 120px;">
<label class="uk-form-label uk-text-small">{{t .LangCode "qlist.readStatus"}}</label>
<select name="read" class="uk-select uk-form-small" onchange="this.form.submit()" style="width: 100%;">
<option value="all" {{if eq .SelectedRead "all"}}selected{{end}}>{{t .LangCode "qlist.all"}}</option>
<option value="read" {{if eq .SelectedRead "read"}}selected{{end}}>{{t .LangCode "qlist.read"}}</option>
<option value="unread" {{if eq .SelectedRead "unread"}}selected{{end}}>{{t .LangCode "qlist.unread"}}</option>
</select>
</div>
</div>
</form>
</div>
<!-- 我收到的提问(标签右浮同行时间,内容下一行) -->
<h4>{{t .LangCode "qlist.received"}}</h4>
{{ if .ReceivedItems }}
{{ range .ReceivedItems }}
<div class="uk-margin-medium-bottom" id="question-{{.QuestionID}}">
<hr>
<!-- 标签在左、按钮在右:两组分开布局;移动端状态/按钮只显示 emoji 图标,保持单行紧凑 -->
<div class="uk-flex uk-flex-middle uk-flex-wrap qlist-pills" style="gap: 6px;">
<!-- 左:时间 + 状态标签 -->
<div class="uk-flex uk-flex-middle uk-flex-wrap" style="gap: 6px;">
<span class="uk-text-small uk-text-muted">{{Date .CreatedAt "Y-m-d H:i:s"}}</span>
{{ if .IsPinned }}
<span class="uk-label uk-label-warning qlist-pill" title="{{t $.LangCode "qlist.pinned"}}"><span class="tb-short">{{t $.LangCode "qlist.pinnedShort"}}</span><span class="tb-text">{{t $.LangCode "qlist.pinned"}}</span></span>
{{ end }}
{{ if eq .Type "question_private" }}
<span class="uk-label uk-label-warning qlist-pill" title="{{t $.LangCode "qlist.private"}}"><span class="tb-short">{{t $.LangCode "qlist.privateShort"}}</span><span class="tb-text">{{t $.LangCode "qlist.private"}}</span></span>
{{ end }}
{{ if not .IsAnswered }}
<span class="uk-label qlist-pill" title="{{t $.LangCode "qlist.unanswered"}}"><span class="tb-short">{{t $.LangCode "qlist.unansweredShort"}}</span><span class="tb-text">{{t $.LangCode "qlist.unanswered"}}</span></span>
{{ end }}
{{ if gt .ReportCount 0 }}
<span class="uk-label uk-label-danger qlist-pill" title="{{t $.LangCode "qlist.reported" .ReportCount}}"><span class="tb-short">{{t $.LangCode "qlist.reportedShort" .ReportCount}}</span><span class="tb-text">{{t $.LangCode "qlist.reported" .ReportCount}}</span></span>
{{ end }}
{{ if .IsRead }}
<span class="uk-label uk-label-success qlist-pill" title="{{t $.LangCode "qlist.read"}}"><span class="tb-short">{{t $.LangCode "qlist.readShort"}}</span><span class="tb-text">{{t $.LangCode "qlist.read"}}</span></span>
{{ else }}
<span class="uk-label qlist-pill" title="{{t $.LangCode "qlist.unread"}}"><span class="tb-short">{{t $.LangCode "qlist.unreadShort"}}</span><span class="tb-text">{{t $.LangCode "qlist.unread"}}</span></span>
{{ end }}
</div>
<!-- 右:操作按钮(margin-left:auto 推到最右,换行后仍保持右对齐) -->
<div class="uk-flex uk-flex-middle uk-flex-wrap" style="gap: 6px; margin-left: auto;">
{{ if not .IsRead }}
<!-- 快捷标记已读:沿用原 tb-label-btn 样式,display:contents 不破坏 flex 布局 -->
<form method="post" action="/_/{{$.LoggedUser.Domain}}/{{.QuestionID}}/read" style="margin: 0; display: contents;">
{{ $.CSRFTokenHTML }}
<button type="submit" class="uk-label tb-label-btn uk-label-success qlist-pill" title="{{t $.LangCode "qitem.markRead"}}"><span class="tb-short">{{t $.LangCode "qitem.markReadShort"}}</span><span class="tb-text">{{t $.LangCode "qitem.markRead"}}</span></button>
</form>
{{ end }}
<!-- form 用 display:contents 不产生盒子,置顶按钮直接参与 flex 对齐 -->
<form method="post" action="{{.PinLink}}" style="margin: 0; display: contents;">
{{ $.CSRFTokenHTML }}
<button type="submit" class="uk-label tb-label-btn {{ if .IsPinned }}uk-label-danger{{ else }}uk-label-primary{{ end }} qlist-pill" title="{{ if .IsPinned }}{{t $.LangCode "qlist.unpin"}}{{ else }}{{t $.LangCode "qlist.pin"}}{{ end }}"><span class="tb-short">{{ if .IsPinned }}{{t $.LangCode "qlist.unpinShort"}}{{ else }}{{t $.LangCode "qlist.pinShort"}}{{ end }}</span><span class="tb-text">{{ if .IsPinned }}{{t $.LangCode "qlist.unpin"}}{{ else }}{{t $.LangCode "qlist.pin"}}{{ end }}</span></button>
</form>
</div>
</div>
<a href="{{.Link}}">
<div class="uk-text-small uk-text-break tb-preline tb-clamp-5 uk-margin-small-top">{{MarkdownPlainText .Content}}</div>
</a>
</div>
{{ end }}
{{ if .HasMoreQuestions }}
<div class="uk-text-center uk-margin-medium-top">
<a class="uk-button uk-button-default uk-button-small" href="{{ .QuestionLoadMoreURL }}">{{t .LangCode "qlist.loadMore"}}</a>
</div>
{{ end }}
{{ else }}
<p class="uk-text-muted">{{t .LangCode "qlist.empty"}}</p>
{{ end }}
</div>
<!-- 投票面板 -->
<div class="qlist-panel" data-qlist-panel="votes" hidden>
<!-- 统一提示区:发布/结束/删除等操作的成功/错误提示沿用 base/alert 样式 -->
{{template "base/alert" .}}
<!-- 投票统计看板(与提问/私聊看板一致) -->
<div class="qlist-stats qlist-stats--2">
<div class="qlist-stat"><span class="qlist-stat-num">{{ .VoteStats.total }}</span><span class="qlist-stat-lbl">{{t .LangCode "vote.statsTotal"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .VoteStats.published }}</span><span class="qlist-stat-lbl">{{t .LangCode "vote.statsPublished"}}</span></div>
</div>
<div class="uk-card uk-card-default uk-card-small uk-card-body uk-margin-bottom uk-flex uk-flex-between uk-flex-middle">
<div>
<div class="uk-text-bold">{{t .LangCode "qlist.myVotes"}}</div>
<div class="uk-text-meta uk-text-small">{{t .LangCode "vote.manageDesc"}}</div>
</div>
<a class="uk-button uk-button-primary uk-button-small" href="/user/votes/new">{{t .LangCode "qlist.newVote"}}</a>
</div>
{{ if .MyVotes }}
{{ range .MyVotes }}
<div class="uk-margin-medium-bottom">
<hr>
<!-- 第一行:标题 + 类型 + 状态 + 元信息 -->
<div class="uk-flex uk-flex-middle uk-flex-wrap" style="gap: 8px;">
<span class="uk-text-bold">{{ if .Title }}{{ .Title }}{{ else }}{{t $.LangCode "qlist.untitledVote"}}{{ end }}</span>
{{ if eq .Type "single" }}<span class="uk-label uk-label-primary">{{t $.LangCode "vote.typeSingle"}}</span>{{ end }}
{{ if eq .Type "multiple" }}<span class="uk-label uk-label-primary">{{t $.LangCode "vote.typeMultiple"}}</span>{{ end }}
{{ if eq .Type "rating" }}<span class="uk-label uk-label-primary">{{t $.LangCode "vote.typeRating"}}</span>{{ end }}
{{ if eq .Type "rank" }}<span class="uk-label uk-label-primary">{{t $.LangCode "vote.typeRank"}}</span>{{ end }}
{{ if eq .Type "form" }}<span class="uk-label uk-label-primary">{{t $.LangCode "vote.typeForm"}}</span>{{ end }}
{{ if eq .EffectiveStatus "draft" }}<span class="uk-label">{{t $.LangCode "vote.statusDraft"}}</span>{{ end }}
{{ if eq .EffectiveStatus "published" }}<span class="uk-label uk-label-success">{{t $.LangCode "vote.statusPublished"}}</span>{{ end }}
{{ if eq .EffectiveStatus "not_started" }}<span class="uk-label uk-label-primary">{{t $.LangCode "vote.statusNotStarted"}}</span>{{ end }}
{{ if eq .EffectiveStatus "ended" }}<span class="uk-label uk-label-warning">{{t $.LangCode "vote.statusEnded"}}</span>{{ end }}
{{ if eq .EffectiveStatus "archived" }}<span class="uk-label uk-label-secondary">{{t $.LangCode "vote.statusArchived"}}</span>{{ end }}
<span class="uk-text-meta">{{t $.LangCode "vote.participants"}}: {{ .SubmissionCount }}</span>
{{ if .RemainingText }}<span class="uk-text-meta">{{ .RemainingText }}</span>{{ end }}
<span class="uk-text-meta">{{t $.LangCode "vote.createdAt"}}: {{ .CreatedAt.Format "2006-01-02 15:04" }}</span>
</div>
<!-- 第二行:操作按钮(统一右对齐,所有状态保持一致的两行布局) -->
<div class="uk-flex uk-flex-wrap uk-margin-small-top" style="gap: 6px; justify-content: flex-end;">
{{ if eq .EffectiveStatus "draft" }}
<form method="post" action="/user/votes/{{ .ID }}/publish" class="uk-display-inline">
{{ $.CSRFTokenHTML }}
<button class="uk-button uk-button-primary uk-button-small" onclick="return confirm('{{t $.LangCode "vote.confirmPublish"}}')">{{t $.LangCode "vote.publish"}}</button>
</form>
<a class="uk-button uk-button-default uk-button-small" href="/user/votes/{{ .ID }}/preview">{{t $.LangCode "vote.preview"}}</a>
{{ end }}
{{ if or (eq .EffectiveStatus "published") (eq .EffectiveStatus "not_started") }}
<form method="post" action="/user/votes/{{ .ID }}/close" class="uk-display-inline">
{{ $.CSRFTokenHTML }}
<button class="uk-button uk-button-warning uk-button-small" onclick="return confirm('{{t $.LangCode "vote.confirmClose"}}')">{{t $.LangCode "vote.close"}}</button>
</form>
{{ end }}
{{ if ne .EffectiveStatus "archived" }}
<a class="uk-button uk-button-default uk-button-small" href="/user/votes/{{ .ID }}/edit">{{t $.LangCode "vote.edit"}}</a>
{{ end }}
{{ if ne .EffectiveStatus "draft" }}
<a class="uk-button uk-button-default uk-button-small" href="/user/votes/{{ .ID }}/results">{{t $.LangCode "vote.results"}}</a>
<a class="uk-button uk-button-default uk-button-small" href="/user/votes/{{ .ID }}/export">{{t $.LangCode "vote.export"}}</a>
{{ end }}
{{ if or (eq .EffectiveStatus "published") (eq .EffectiveStatus "not_started") }}
<button class="uk-button uk-button-default uk-button-small" onclick="copyShareURL('{{ .LinkToken }}', this)">{{t $.LangCode "vote.share"}}</button>
{{ end }}
<form method="post" action="/user/votes/{{ .ID }}/delete" class="uk-display-inline">
{{ $.CSRFTokenHTML }}
<button class="uk-button uk-button-danger uk-button-small" onclick="return confirm('{{t $.LangCode "vote.confirmDelete"}}')">{{t $.LangCode "common.delete"}}</button>
</form>
</div>
</div>
{{ end }}
{{ if .HasMoreVotes }}
<div class="uk-text-center uk-margin-medium-top">
<a class="uk-button uk-button-default uk-button-small" href="{{ .VoteLoadMoreURL }}">{{t .LangCode "qlist.loadMore"}}</a>
</div>
{{ end }}
{{ else }}
<div class="uk-alert uk-alert-primary uk-margin-remove">{{t .LangCode "vote.empty"}}</div>
{{ end }}
</div>
<!-- 私聊面板 -->
<div class="qlist-panel" data-qlist-panel="chats" hidden>
<!-- 统一提示区:私聊相关操作的成功/错误提示沿用 base/alert 样式 -->
{{template "base/alert" .}}
<!-- 私聊统计看板(与提问/投票看板一致) -->
<div class="qlist-stats qlist-stats--4">
<div class="qlist-stat"><span class="qlist-stat-num">{{ .ChatStats.total }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.chatStatsTotal"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .ChatStats.received }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.chatStatsReceived"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .ChatStats.initiated }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.chatStatsInitiated"}}</span></div>
<div class="qlist-stat"><span class="qlist-stat-num">{{ .ChatStats.closed }}</span><span class="qlist-stat-lbl">{{t .LangCode "qlist.chatStatsClosed"}}</span></div>
</div>
<!-- 我收到的私聊 -->
<h4>{{t .LangCode "qlist.receivedChats"}}({{ .ChatStats.received }})</h4>
{{ if .ReceivedChats }}
{{ range .ReceivedChats }}
<div class="uk-margin-medium-bottom">
<hr>
<div class="uk-float-right uk-flex uk-flex-middle uk-flex-wrap" style="gap: 6px;">
<span class="uk-label uk-label-success">{{t $.LangCode "chat.title"}}</span>
{{ if .IsBlocked }}
<span class="uk-label uk-label-danger">{{t $.LangCode "qlist.blocked"}}</span>
{{ end }}
</div>
<a href="{{.Link}}">
<div class="uk-text-left uk-text-small uk-text-muted">{{Date .CreatedAt "Y-m-d H:i:s"}}</div>
<div class="uk-text-small uk-text-break tb-preline tb-clamp-5 uk-margin-small-top">{{.Content}}</div>
</a>
</div>
{{ end }}
{{ else }}
<p class="uk-text-muted">{{t .LangCode "qlist.chatEmpty"}}</p>
{{ end }}
{{ if .HasMoreChats }}
<div class="uk-text-center uk-margin-medium-top">
<a class="uk-button uk-button-default uk-button-small" href="{{ .ChatLoadMoreURL }}">{{t .LangCode "qlist.loadMore"}}</a>
</div>
{{ end }}
<!-- 我发起的私聊 -->
{{ if .ConversationDetails }}
<h4 class="uk-margin-top">{{t .LangCode "qlist.myChats"}}({{ .ChatStats.initiated }})</h4>
{{ range .ConversationDetails }}
<a href="/_/{{.OwnerDomain}}/chat/{{.Conversation.Token}}" class="uk-display-block uk-overflow-hidden uk-margin-medium-bottom">
<div>
<hr>
<span class="uk-label uk-label-warning uk-float-right uk-margin-small-right">{{t $.LangCode "chat.title"}}</span>
{{ if .IsBlocked }}
<span class="uk-label uk-label-danger uk-float-right uk-margin-small-right">{{t $.LangCode "qlist.blocked"}}</span>
{{ end }}
<div class="uk-text-left uk-text-small uk-text-muted">{{Date .Conversation.CreatedAt "Y-m-d H:i:s"}}</div>
<div class="uk-text-small uk-text-break tb-preline tb-clamp-5 uk-margin-small-top">{{.FirstMessage}}</div>
</div>
</a>
{{ end }}
{{ end }}
{{ if .HasMoreAskedChats }}
<div class="uk-text-center uk-margin-medium-top">
<a class="uk-button uk-button-default uk-button-small" href="{{ .AskedChatsLoadMoreURL }}">{{t .LangCode "qlist.loadMore"}}</a>
</div>
{{ end }}
</div>
</div>
<script>
function copyShareURL(token, btn) {
var url = window.location.origin + "/vote/" + token;
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(url).then(function () {
var old = btn.textContent;
btn.textContent = '{{t .LangCode "vote.copied"}}';
setTimeout(function () { btn.textContent = old; }, 1500);
});
} else {
prompt('{{t .LangCode "vote.shareURL"}}', url);
}
}
document.addEventListener('DOMContentLoaded', function() {
const tabs = document.querySelectorAll('[data-qlist-tab]');
const panels = document.querySelectorAll('[data-qlist-panel]');
function showQlistPanel(name) {
tabs.forEach(function(tab) {
const active = tab.dataset.qlistTab === name;
tab.classList.toggle('is-active', active);
tab.setAttribute('aria-selected', active ? 'true' : 'false');
});
panels.forEach(function(panel) {
panel.hidden = panel.dataset.qlistPanel !== name;
});
if (window.history && window.history.replaceState) {
const hash = name === 'votes' ? '#votes' : (name === 'chats' ? '#chats' : '');
window.history.replaceState({}, document.title, window.location.pathname + hash);
}
}
tabs.forEach(function(tab) {
tab.addEventListener('click', function() { showQlistPanel(tab.dataset.qlistTab); });
});
if (window.location.hash === '#votes') showQlistPanel('votes');
if (window.location.hash === '#chats') showQlistPanel('chats');
});
</script>
{{template "base/footer" .}}