309 lines
15 KiB
HTML
309 lines
15 KiB
HTML
{{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://r2.337845818.best/tamabox/cdn/lib/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"
|
||
};
|
||
new QRCode(document.getElementById("boxqrimg"), 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" .}} |