chore: baseline snapshot before moderation-strictness feature

Repo .git was damaged (refs/ missing, index truncated, object store near-empty).
Repaired via git init (rebuilt refs), stale index preserved as .git/index.corrupt-20260910.bak,
then full worktree committed as a rollback baseline.
This commit is contained in:
tamakyi
2026-09-10 10:56:27 +08:00
commit e3e59e7c69
296 changed files with 67458 additions and 0 deletions
+310
View File
@@ -0,0 +1,310 @@
{{template "base/header" .}}
<!-- 头像直连 R2:crossorigin 让 favicon 也以 CORS 模式请求,确保浏览器缓存的响应都带 ACAO;
?v=2 击穿历史上被「无 ACAO 响应」污染的缓存条目(R2 对无 Origin 请求的响应无 Vary,可缓存 31 天) -->
<link rel="shortcut icon" href="{{.PageUser.Avatar}}?v=2" crossorigin="anonymous"/>
<link rel="apple-touch-icon" href="{{.PageUser.Avatar}}?v=2" crossorigin="anonymous"/>
<link rel="icon" sizes="192x192" href="{{.PageUser.Avatar}}?v=2" crossorigin="anonymous">
<style>
/* 投票列表:与探索页"全部投票"一致的列表行样式 */
.profile-votes-list { display: grid; gap: 0; }
.profile-vote-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
min-width: 0;
padding: 14px 16px;
border-bottom: 1px solid var(--tb-border, #e9e9e9);
text-decoration: none;
}
.profile-vote-item:first-child { border-top: 1px solid var(--tb-border, #e9e9e9); }
.profile-vote-item:hover { background: var(--tb-surface-hover, #f8fbff); text-decoration: none; }
.profile-vote-content { min-width: 0; }
.profile-vote-title {
display: block;
overflow: hidden;
color: var(--tb-text, #333);
font-size: 0.98rem;
font-weight: 600;
line-height: 1.45;
text-overflow: ellipsis;
white-space: nowrap;
}
.profile-vote-meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 7px;
margin-top: 8px;
}
.profile-vote-meta .uk-label { font-size: 0.72rem; line-height: 1.6; }
.profile-vote-action {
flex: 0 0 auto;
color: var(--tb-primary, #1e87f0);
font-size: 0.82rem;
white-space: nowrap;
}
html[data-theme="dark"] .profile-vote-item { border-color: var(--tb-border); }
html[data-theme="dark"] .profile-vote-title { color: var(--tb-text); }
html[data-theme="dark"] .profile-vote-item:hover { background: rgba(78, 168, 245, 0.10); }
/* 个人主页 Tab:与探索页一致的胶囊切换样式 */
/* 个人主页 Tab:全宽等分,置于主体顶部,作为一级导航(移动端整行可点) */
.profile-tabs {
display: flex;
gap: 4px;
padding: 4px;
margin-top: 20px;
margin-bottom: 18px;
border: 1px solid var(--tb-border, #e5e5e5);
border-radius: 9px;
background: var(--tb-surface-2, #fafafa);
}
.profile-tab {
flex: 1;
border: 0;
border-radius: 6px;
padding: 9px 15px;
background: transparent;
color: var(--tb-text-muted, #666);
cursor: pointer;
font-size: 0.9rem;
transition: background 0.2s ease, color 0.2s ease;
}
.profile-tab:hover { color: var(--tb-primary, #1e87f0); }
.profile-tab.is-active {
background: var(--tb-surface, #fff);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.10);
color: var(--tb-primary, #1e87f0);
font-weight: 600;
}
/* 功能关闭时置灰禁用的 Tab(如投票功能关闭) */
.profile-tab.is-disabled,
.profile-tab:disabled {
cursor: not-allowed;
color: var(--tb-text-muted, #999);
opacity: 0.7;
}
.profile-tab.is-disabled:hover { color: var(--tb-text-muted, #999); }
.profile-panel[hidden] { display: none !important; }
html[data-theme="dark"] .profile-tabs {
border-color: var(--tb-border);
background: var(--tb-surface-2);
}
html[data-theme="dark"] .profile-tab { color: var(--tb-text-muted); }
html[data-theme="dark"] .profile-tab.is-active { background: var(--tb-surface); color: var(--tb-primary); }
html[data-theme="dark"] .profile-tab.is-disabled { color: var(--tb-text-muted); opacity: 0.55; }
</style>
<div class="uk-card uk-card-default uk-text-center">
<div class="uk-flex uk-flex-center uk-flex-middle uk-background-cover uk-light" style="min-height: 260px;" data-src="{{ .PageUser.Background }}" uk-img>
<div class="uk-card-body">
<img class="uk-border-circle uk-box-shadow-large" src="{{ if .PageUser.Avatar }}{{ .PageUser.Avatar }}?v=2{{ else }}{{ .DefaultAvatar }}{{ end }}" crossorigin="anonymous" style="width: 100px; height: 100px; max-width: 100%; max-height: 100%;">
<h3 id="usernamecolor">{{ .PageUser.Name }}</h3>
<p id="introcolor">{{ .PageUser.Intro }}</p>
<div class="icon-container">
{{ if and .PageUser.Acfunlink (ne .PageUser.Acfunlink "none") }}
<a href="https://{{.PageUser.Acfunlink}}" target="_blank">
<img src="https://r2.337845818.best/tamabox/icon/social/ailicili.png" alt="acfunlink" class="icon">
</a>
{{ end }}
{{ if and .PageUser.Bililink (ne .PageUser.Bililink "none") }}
<a href="https://{{.PageUser.Bililink}}" target="_blank">
<img src="https://r2.337845818.best/tamabox/icon/social/bili.png" alt="bililink" class="icon">
</a>
{{ end }}
{{ if and .PageUser.Weibolink (ne .PageUser.Weibolink "none") }}
<a href="https://{{.PageUser.Weibolink}}" target="_blank">
<img src="https://r2.337845818.best/tamabox/icon/social/weibo.png" alt="weibolink" class="icon">
</a>
{{ end }}
{{ if and .PageUser.Xiaohongshulink (ne .PageUser.Xiaohongshulink "none") }}
<a href="https://{{.PageUser.Xiaohongshulink}}" target="_blank">
<img src="https://r2.337845818.best/tamabox/icon/social/xiaohongshu.png" alt="xiaohongshulink" class="icon">
</a>
{{ end }}
{{ if and .PageUser.Bloglink (ne .PageUser.Bloglink "none") }}
<a href="https://{{.PageUser.Bloglink}}" target="_blank">
<img src="https://r2.337845818.best/tamabox/icon/social/blog.png" alt="bloglink" class="icon">
</a>
{{ end }}
</div>
</div>
</div>
</div>
<script>
document.getElementById("usernamecolor").style.color = "{{.PageUser.Usernamecolor}}";
document.getElementById("introcolor").style.color = "{{.PageUser.Introcolor}}";
</script>
<div>
<div class="uk-card uk-card-default uk-card-small uk-card-body">
{{ if .CanAsk }}
<!-- jQuery 已改为按需加载:defer 按文档顺序先于 easy.qrcode 执行,保证就绪 -->
<script defer src="https://cdnjs.snrat.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script defer src='https://r2.337845818.best/tamabox/cdn/js/remake/easy.qrcode.min.js' type="text/javascript" charset="utf-8"></script>
<center><div id="boxqrimg"></div></center>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
var options = {
text: window.location.href,
width: 200,
height: 200,
// 与 Profile 编辑器保持一致:仅当启用自定义前景色时,才把 Qrcodebackcolor 作为前景色;
// 否则强制黑色 #000000,避免未勾选却显示自定义前景色、与 Profile 预览不一致。
colorDark: ({{.PageUser.UseCustomQRColor}} ? "{{.PageUser.Qrcodebackcolor}}" : "#000000") || "#000000",
colorLight: "{{.PageUser.Qrcodecolor}}" || "#FFFFFF",
dotScale: parseFloat("{{.PageUser.Dotscale}}") || 0.4,
dotScaleTiming: parseFloat("{{.PageUser.Dotscale}}") || 0.4,
dotScaleA: parseFloat("{{.PageUser.Dotscale}}") || 0.4,
correctLevel: QRCode.CorrectLevel.H,
logo: (function () {
// ?v=2:击穿曾被无 ACAO 响应污染的浏览器缓存条目;仅对 http(s) 绝对地址追加
var a = "{{.PageUser.Avatar}}" || "{{.DefaultAvatar}}";
return a ? (a.indexOf("http") === 0 ? a + "?v=2" : a) : undefined;
})(),
logoWidth: 60,
logoHeight: 60,
logoBackgroundTransparent: true,
// 直连 R2 等跨域图片须以 CORS 模式加载,canvas 才不被污染、可正常导出
crossOrigin: 'anonymous',
backgroundImage: ("{{.PageUser.BackgroundImage}}" ? "{{.PageUser.BackgroundImage}}" : undefined),
backgroundImageAlpha: parseFloat("{{.PageUser.Backgroundimagealpha}}") || 0.8,
autoColor: false,
PO: "{{.PageUser.Qrcodepdpcolor}}" || "#000000",
PI: "{{.PageUser.Qrcodepdpcolor}}" || "#000000",
AO: '',
AI: '',
timing: "{{.PageUser.Qrcodepdpcolor}}" || "#000000"
};
// 降级渲染:头像(logo)/ 背景图加载慢/失败时先出基础码,探针成功后再升级带 logo 版
window.tbRenderQR(document.getElementById("boxqrimg"), function () { return options; });
});
</script>
<p class="uk-text-center uk-text-small">{{t .LangCode "ask.scan" .PageUser.Name}}<br>{{ if .RegisterOnlyAsk }}{{t .LangCode "ask.registerOnly"}}{{ else }}{{t .LangCode "ask.anonymous"}}{{ end }}</p>
<div class="uk-text-center uk-margin-small-top">
<a id="share-btn" href="/_/{{ .PageUser.Domain }}/share-card" download class="uk-button uk-button-default uk-button-small">
📤 {{t .LangCode "ask.share"}}
</a>
</div>
<div id="share-loading-overlay" style="display:none; position: fixed; top:0; left:0; width:100%; height:100%; background: rgba(255,255,255,0.85); z-index:9999;">
<div style="display:flex; flex-direction:column; align-items:center; justify-content:center; height:100%;">
<div uk-spinner="ratio: 2" class="uk-margin-bottom"></div>
<p class="uk-text-large uk-text-muted">{{t .LangCode "ask.generating"}}</p>
</div>
</div>
<script>
(function() {
var btn = document.getElementById('share-btn');
var overlay = document.getElementById('share-loading-overlay');
if (!btn || !overlay) return;
btn.addEventListener('click', function(e) {
e.preventDefault();
overlay.style.display = 'block';
btn.style.pointerEvents = 'none';
fetch(btn.href)
.then(function(response) {
if (!response.ok) throw new Error('{{t .LangCode "ask.networkError"}}');
return response.blob();
})
.then(function(blob) {
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = '{{t .LangCode "ask.shareFilename"}}';
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
URL.revokeObjectURL(url);
}, 100);
})
.catch(function(err) {
alert('{{t .LangCode "ask.genFailed"}}');
console.error(err);
})
.finally(function() {
overlay.style.display = 'none';
btn.style.pointerEvents = 'auto';
});
});
})();
</script>
{{ end }}
{{template "base/alert" .}}
<!-- 提问 / 投票 切换:默认显示提问,支持 ?tab=votes 直达(服务端初始态)与 #votes hash 覆盖 -->
<div class="profile-tabs" role="tablist">
<button type="button" class="profile-tab{{ if eq .ActiveProfileTab "questions" }} is-active{{ end }}" data-profile-tab="questions" role="tab" aria-selected="{{ if eq .ActiveProfileTab "questions" }}true{{ else }}false{{ end }}">{{t .LangCode "explore.questionsTab"}}</button>
{{ if .VoteEnabled }}
<button type="button" class="profile-tab{{ if eq .ActiveProfileTab "votes" }} is-active{{ end }}" data-profile-tab="votes" role="tab" aria-selected="{{ if eq .ActiveProfileTab "votes" }}true{{ else }}false{{ end }}">{{t .LangCode "explore.votesTab"}}</button>
{{ else }}
<!-- 投票功能关闭:保留 Tab 展示但置灰禁用,hover 提示原因 -->
<button type="button" class="profile-tab is-disabled" disabled aria-disabled="true" uk-tooltip="{{ .VoteClosedMessage }}">{{t .LangCode "explore.votesTab"}} <span uk-icon="icon: lock; ratio: 0.8"></span></button>
{{ end }}
</div>
<div class="profile-panel" data-profile-panel="questions"{{ if eq .ActiveProfileTab "votes" }} hidden{{ end }}>
{{template "question/new-question-template" .}}
{{ if ne (len .PageQuestions) 0 }}
<p class="uk-text-left uk-text-muted uk-text-small">{{t .LangCode "ask.history" .PageUser.Name}} ({{ .AnsweredCount }})</p>
{{ template "question/history-template" . }}
{{ end }}
</div>
<div class="profile-panel" data-profile-panel="votes"{{ if ne .ActiveProfileTab "votes" }} hidden{{ end }}>
{{ if .PageVotes }}
<!-- 匿名投票板块:箱主"进行中"的公开投票(列表行样式,与探索页"全部投票"一致) -->
<div class="profile-votes-list">
{{ range .PageVotes }}
<a href="/vote/{{ .LinkToken }}" class="profile-vote-item">
<div class="profile-vote-content">
<span class="profile-vote-title" title="{{ .Title }}">{{ .Title }}</span>
<span class="profile-vote-meta">
{{ 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 }}
<span class="uk-text-meta">{{ .CreatedAt.Format "2006-01-02" }}</span>
</span>
</div>
<span class="profile-vote-action">{{t $.LangCode "vote.page.goVote"}} <span uk-icon="icon: arrow-right; ratio: .8"></span></span>
</a>
{{ end }}
</div>
{{ else }}
<div class="uk-alert uk-alert-primary uk-margin-remove-top">{{t .LangCode "explore.noVotes"}}</div>
{{ end }}
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var tabs = document.querySelectorAll('[data-profile-tab]');
var panels = document.querySelectorAll('[data-profile-panel]');
function showPanel(name) {
tabs.forEach(function(tab) {
var active = tab.dataset.profileTab === name;
tab.classList.toggle('is-active', active);
tab.setAttribute('aria-selected', active ? 'true' : 'false');
});
panels.forEach(function(panel) {
panel.hidden = panel.dataset.profilePanel !== name;
});
if (window.history && window.history.replaceState) {
window.history.replaceState({}, document.title, window.location.pathname + window.location.search + (name === 'votes' ? '#votes' : ''));
}
}
tabs.forEach(function(tab) {
tab.addEventListener('click', function() { showPanel(tab.dataset.profileTab); });
});
// 仅当投票 Tab 可点击(功能开启)时才响应 #votes hash,避免投票关闭时切到空面板
if (window.location.hash === '#votes' && document.querySelector('[data-profile-tab="votes"]')) {
showPanel('votes');
}
});
</script>
{{template "base/footer" .}}