全局美化 v1
This commit is contained in:
+181
-11
@@ -7,6 +7,52 @@
|
||||
<meta name="msvalidate.01" content="2F185E8E63C93635F50B3574F3B31E42" />
|
||||
<meta name="description" content="{{ if .MetaDescription }}{{ .MetaDescription }}{{ else }}{{ t .LangCode "site.description" }}{{ end }}">
|
||||
<meta name="keywords" content="{{ t .LangCode "site.keywords" }}">
|
||||
<!-- 主题初始化:必须在任何样式生效前执行,否则深色模式用户会先渲染出一帧亮色(顶栏白闪)。
|
||||
只读 cookie 并打属性,切换逻辑仍在页面底部(#theme-toggle / #theme-toggle-mobile)。 -->
|
||||
<script>
|
||||
(function () {
|
||||
var m = document.cookie.match(/(?:^|;\s*)theme=([^;]*)/);
|
||||
if (m && m[1] === 'dark') document.documentElement.setAttribute('data-theme', 'dark');
|
||||
})();
|
||||
</script>
|
||||
<!-- 设计令牌:亮色为默认(:root),深色在 html[data-theme="dark"] 覆盖。
|
||||
页面与组件样式一律引用 var(--tb-*),不再写死色值/圆角/阴影;
|
||||
var() 的第二个参数仅作兜底(旧缓存页、邮件模板等不引入本文件的场景)。
|
||||
改配色只动这一块,亮暗两套自动保持一致。 -->
|
||||
<style>
|
||||
:root {
|
||||
--tb-bg: #f7f8fa;
|
||||
--tb-surface: #ffffff;
|
||||
--tb-surface-2: #f4f6f8;
|
||||
--tb-surface-hover: #f3f7ff;
|
||||
--tb-border: #e8eaee;
|
||||
--tb-text: #1f2329;
|
||||
--tb-text-secondary: #5c6370;
|
||||
--tb-text-muted: #8a919c;
|
||||
--tb-primary: #1e87f0;
|
||||
--tb-primary-weak: rgba(30, 135, 240, 0.10);
|
||||
--tb-radius: 12px;
|
||||
--tb-radius-sm: 8px;
|
||||
--tb-radius-xs: 6px;
|
||||
--tb-shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 12px 28px -18px rgba(16, 24, 40, 0.20);
|
||||
--tb-shadow-hover: 0 1px 2px rgba(16, 24, 40, 0.05), 0 18px 40px -20px rgba(16, 24, 40, 0.28);
|
||||
--tb-font: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
html[data-theme="dark"] {
|
||||
--tb-bg: #1a1d23;
|
||||
--tb-surface: #242830;
|
||||
--tb-surface-2: #2d323c;
|
||||
--tb-surface-hover: rgba(92, 141, 255, 0.12);
|
||||
--tb-border: #3a404c;
|
||||
--tb-text: #d8dce4;
|
||||
--tb-text-secondary: #a8b0bd;
|
||||
--tb-text-muted: #8b93a1;
|
||||
--tb-primary: #5c8dff;
|
||||
--tb-primary-weak: rgba(92, 141, 255, 0.14);
|
||||
--tb-shadow: 0 1px 2px rgba(0, 0, 0, 0.30), 0 12px 28px -18px rgba(0, 0, 0, 0.55);
|
||||
--tb-shadow-hover: 0 1px 2px rgba(0, 0, 0, 0.35), 0 18px 40px -20px rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
</style>
|
||||
<!-- 预连接:UIkit 走公共 CDN(cdnjs.snrat.com),其余自托管库仍在本站 R2,均需预连接 -->
|
||||
<link rel="preconnect" href="https://r2.337845818.best" crossorigin>
|
||||
<link rel="preconnect" href="https://cdnjs.snrat.com" crossorigin>
|
||||
@@ -185,15 +231,7 @@
|
||||
|
||||
<!-- 深色模式:html[data-theme="dark"] 时覆盖 UIkit 3.3.3 编译主题的关键颜色 -->
|
||||
<style>
|
||||
html[data-theme="dark"] {
|
||||
--tb-bg: #1a1d23;
|
||||
--tb-surface: #242830;
|
||||
--tb-surface-2: #2d323c;
|
||||
--tb-border: #3a404c;
|
||||
--tb-text: #d8dce4;
|
||||
--tb-text-muted: #8b93a1;
|
||||
--tb-primary: #5c8dff;
|
||||
}
|
||||
/* 变量(--tb-*)已上移到 head 顶部的令牌块,亮暗两套同名常量在那里定义。 */
|
||||
/* 根元素与 body 一起覆盖,确保整个视口(含内容不足一屏时的空白区)都是深色背景 */
|
||||
html[data-theme="dark"],
|
||||
html[data-theme="dark"] body {
|
||||
@@ -331,6 +369,139 @@
|
||||
html[data-theme="dark"] #theme-toggle-mobile .tb-icon-dark { display: inline; }
|
||||
</style>
|
||||
|
||||
<!-- 基础质感层:只调整外观(圆角/投影/字体/数字对齐),不改任何结构与布局。
|
||||
颜色一律取自头部令牌,亮暗两套自动生效,因此这里不需要再写 html[data-theme="dark"] 分支。 -->
|
||||
<style>
|
||||
/* 根元素与 body 同时上色:内容不足一屏时,body 之外的视口区域也要是同一底色 */
|
||||
html,
|
||||
body {
|
||||
font-family: var(--tb-font);
|
||||
background-color: var(--tb-bg);
|
||||
color: var(--tb-text);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
/* 卡片:12px 圆角 + 一层极淡接触影 + 一层大扩散影(UIkit 默认的 0 5px 15px 偏硬) */
|
||||
.uk-card {
|
||||
border-radius: var(--tb-radius);
|
||||
}
|
||||
.uk-card-default {
|
||||
background-color: var(--tb-surface);
|
||||
box-shadow: var(--tb-shadow);
|
||||
}
|
||||
.uk-card-default.uk-card-hover:hover {
|
||||
box-shadow: var(--tb-shadow-hover);
|
||||
}
|
||||
.uk-card-header {
|
||||
border-radius: var(--tb-radius) var(--tb-radius) 0 0;
|
||||
}
|
||||
.uk-card-footer {
|
||||
border-radius: 0 0 var(--tb-radius) var(--tb-radius);
|
||||
}
|
||||
.uk-card,
|
||||
.uk-button,
|
||||
.uk-alert,
|
||||
.uk-label {
|
||||
transition: box-shadow 0.18s ease, background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
|
||||
}
|
||||
/* 交互元素:统一 8px 圆角,标签 6px */
|
||||
.uk-button {
|
||||
border-radius: var(--tb-radius-sm);
|
||||
}
|
||||
.uk-input,
|
||||
.uk-select,
|
||||
.uk-textarea,
|
||||
.uk-form-small,
|
||||
.uk-search-input {
|
||||
border-radius: var(--tb-radius-sm);
|
||||
}
|
||||
.uk-label {
|
||||
border-radius: var(--tb-radius-xs);
|
||||
}
|
||||
.uk-alert {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.uk-modal-dialog {
|
||||
border-radius: 14px;
|
||||
}
|
||||
.uk-dropdown,
|
||||
.uk-navbar-dropdown {
|
||||
border-radius: 10px;
|
||||
box-shadow: var(--tb-shadow);
|
||||
}
|
||||
.uk-navbar-container:not(.uk-navbar-transparent) {
|
||||
background-color: var(--tb-surface);
|
||||
}
|
||||
/* 键盘可达性:仅在键盘聚焦时出现描边,鼠标点击不出现 */
|
||||
.uk-button:focus-visible,
|
||||
.uk-navbar-nav > li > a:focus-visible {
|
||||
outline: 2px solid var(--tb-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
/* 次要文字统一走令牌,避免 #999 / #8a919c 混用 */
|
||||
.uk-text-muted,
|
||||
.uk-text-meta {
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
/* 统计/日期等数字列等宽对齐,避免刷新时左右跳动 */
|
||||
.uk-table,
|
||||
.tb-num {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
/* 图片上传条:原为 item/new-question 两处各写一份内联 style(写死 #f8f8f8,深色下露白),
|
||||
收敛到一处并走令牌,亮暗自动适配 */
|
||||
.tb-img-uploader {
|
||||
width: 100%;
|
||||
background-color: var(--tb-surface-2);
|
||||
display: flex;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 5px;
|
||||
}
|
||||
/* 背景图封面(提问箱主页):渐变遮罩,保证用户自选文字色叠加后仍可读。
|
||||
默认浅色遮罩(页面 .uk-light 补丁把文字兜底成深色);若箱主选了浅色文字,
|
||||
question/list.html 会按亮度加上 .tb-cover-dark 换成深色遮罩。 */
|
||||
.tb-cover {
|
||||
position: relative;
|
||||
border-radius: var(--tb-radius) var(--tb-radius) 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tb-cover::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.58) 55%, rgba(255, 255, 255, 0.84) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.tb-cover.tb-cover-dark::after {
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.16) 45%, rgba(0, 0, 0, 0.46) 100%);
|
||||
}
|
||||
.tb-cover > * {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.tb-cover h3,
|
||||
.tb-cover p {
|
||||
text-shadow: 0 1px 10px rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
.tb-cover.tb-cover-dark h3,
|
||||
.tb-cover.tb-cover-dark p {
|
||||
text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
/* 尊重系统的减少动效设置 */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.uk-card,
|
||||
.uk-button,
|
||||
.emoji-placeholder {
|
||||
transition: none;
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 顶栏自适应:导航全部直接显示,窄屏时分级缩小字号/间距,保证英文/日文等长文字不溢出 -->
|
||||
<style>
|
||||
.uk-navbar-nav a {
|
||||
@@ -830,8 +1001,7 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||
var expires = new Date(Date.now() + 365 * 24 * 3600 * 1000).toUTCString();
|
||||
document.cookie = THEME_COOKIE + '=' + next + '; path=/; max-age=' + (365 * 24 * 3600) + '; SameSite=Lax';
|
||||
}
|
||||
// 首屏前应用,避免闪烁
|
||||
applyTheme(getTheme());
|
||||
// 首屏主题已由 <head> 顶部的内联脚本打过属性(避免白闪),这里只负责点击切换。
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// 桌面顶栏按钮与移动端底部按钮都绑定
|
||||
var buttons = document.querySelectorAll('#theme-toggle, #theme-toggle-mobile');
|
||||
|
||||
+320
-109
@@ -1,123 +1,334 @@
|
||||
{{template "base/header" .}}
|
||||
<div class="uk-card uk-card-default uk-card-body">
|
||||
<h1 class="uk-heading-small">{{t .LangCode "site.title"}}</h1>
|
||||
<p style="color: red;">重大消息!本站已切换到<a href="https://box.shiroko.one/">box.shiroko.one</a>,原域名将在2026年12月24日到期,期间将通过301转发指向新域名,到期后旧域名将彻底不在使用。<br>
|
||||
现已切换内容审核服务到阿里云,审核速度提升且误伤变少了。另外允许用户调整审核严格度,在不碰底线的前提下允许用户设置不接受辱骂、广告等信息(即不听坏话模式)。 </p><hr>
|
||||
<p><br>⭐一个无需注册即可提问的匿名提问箱。你不需要下载App,不需要绑定社交账号,甚至连邮箱都不需要是真的。<br>⭐本站在原版的基础上新增了问题页面的二维码、私聊、投票、追加提问等功能以及更多自定义内容。各位用户可自行修改二维码背景图、颜色等个性化配置。<br>⭐可以到站长唯一提问提问箱链接<a href="//box.shiroko.one/_/tamakyi">小狼的提问箱</a>尝试相关功能或给我提意见。<br>⭐本站提倡友好、友善的发炎,请遵守:<a href="https://box.shiroko.one/rules">社区规则</a>,无论匿名与否,我都会看着你,你要对你的发言负责。<br></p>
|
||||
<hr><p style="color: red; font-weight: bold;">近期更新:<br>⭐2026.9 新增审核严格度选项,增加了提问、投票、私聊的总开关,可以设置定时收集、定量收集或关闭功能,顺便调整了前后端显示,看起来更易用了一些。<br>⭐2026.8 新增了<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>。<br>⭐2026.8 放弃使用recaptcha等对国内用户非常不友好的验证方式,更新了密码加密方式,修复了图片上传等一系列问题。<br>⭐2026.5 增加了私聊功能,可进行连续性对话,详见<a href="https://blog.shiroko.one/record/tamabox-update-20260513">介绍</a>;另有增加提问箱的卡片分享,更直观和美观。<br>⭐2026.2 新增了用户展示和标签功能,如果你希望陌生人给你提问,可以在设置页面给自己贴上5个标签并选择是否展示在探索页面:<a href="https://box.shiroko.one/explore">点我访问</a>,详情见<a href="https://blog.shiroko.one/record/tamabox-tags">狼的公告板</a><br></p>
|
||||
<hr><p>一点提醒:<br>⭐本站唯一指定认证站长:<a href="//box.shiroko.one/_/tamakyi">小狼</a>,注意不要被骗。
|
||||
<br>⭐本站不允许垃圾信息、广告、辱骂、涉政、暴恐、色情、违禁、无意义、灌水提问的出现,如有涉证或不良言论将直接删除。</p>
|
||||
<style>
|
||||
/* 首页:hero + 功能卡 + 统计条。仅首页使用的排版,颜色全部走令牌,亮暗自动适配。
|
||||
正文文案沿用本站既有的中文(首页一直是中文直写,不随语言切换)。 */
|
||||
.tb-hero {
|
||||
padding: 36px 24px 32px;
|
||||
text-align: center;
|
||||
background-image: linear-gradient(180deg, var(--tb-primary-weak), rgba(255, 255, 255, 0));
|
||||
}
|
||||
.tb-hero-title {
|
||||
margin: 0;
|
||||
font-size: 1.75rem;
|
||||
line-height: 1.35;
|
||||
font-weight: 600;
|
||||
color: var(--tb-text);
|
||||
}
|
||||
.tb-hero-lead {
|
||||
margin: 12px auto 0;
|
||||
max-width: 30rem;
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.8;
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
.tb-hero-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-top: 22px;
|
||||
}
|
||||
.tb-hero-actions .uk-button {
|
||||
min-width: 112px;
|
||||
}
|
||||
.tb-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
|
||||
gap: 12px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.tb-grid .uk-card {
|
||||
padding: 18px 18px 20px;
|
||||
text-align: left;
|
||||
}
|
||||
.tb-card-title {
|
||||
margin: 0 0 6px;
|
||||
font-size: 0.98rem;
|
||||
font-weight: 600;
|
||||
color: var(--tb-text);
|
||||
}
|
||||
.tb-card-text {
|
||||
margin: 0;
|
||||
font-size: 0.86rem;
|
||||
line-height: 1.7;
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
.tb-card-text + .tb-card-text {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.tb-card-text.tb-lead {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.tb-changelog summary + ul {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.tb-section-title {
|
||||
margin: 0 0 10px;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: var(--tb-text);
|
||||
}
|
||||
.tb-notice-tag {
|
||||
display: inline-block;
|
||||
margin: 0 0 8px;
|
||||
padding: 2px 8px;
|
||||
border-radius: var(--tb-radius-xs);
|
||||
background: var(--tb-primary-weak);
|
||||
color: var(--tb-primary);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
.tb-list {
|
||||
margin: 0;
|
||||
padding-left: 1.15em;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.9;
|
||||
color: var(--tb-text);
|
||||
}
|
||||
.tb-changelog summary {
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
color: var(--tb-text);
|
||||
list-style: none;
|
||||
}
|
||||
.tb-changelog summary::-webkit-details-marker { display: none; }
|
||||
.tb-changelog summary::before {
|
||||
content: "▸";
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
color: var(--tb-text-muted);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.tb-changelog[open] summary::before { transform: rotate(90deg); }
|
||||
.tb-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
.tb-stat-num {
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
color: var(--tb-text);
|
||||
}
|
||||
.tb-stat-label {
|
||||
display: block;
|
||||
margin-top: 2px;
|
||||
font-size: 0.78rem;
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
.tb-stats-meta {
|
||||
margin: 14px 0 0;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.8;
|
||||
color: var(--tb-text-muted);
|
||||
text-align: center;
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.tb-hero { padding: 28px 16px 24px; }
|
||||
.tb-hero-title { font-size: 1.4rem; }
|
||||
.tb-stat-num { font-size: 1.25rem; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="uk-card uk-card-default tb-hero">
|
||||
<h1 class="tb-hero-title">{{t .LangCode "site.title"}}</h1>
|
||||
<p class="tb-hero-lead">
|
||||
一个无需注册即可提问的匿名提问箱。不用下载 App,不用绑定社交账号,连邮箱都不必是真的。
|
||||
</p>
|
||||
<div class="tb-hero-actions">
|
||||
<a href="/explore" class="uk-button uk-button-primary">{{t .LangCode "nav.explore"}}</a>
|
||||
<a href="/rules" class="uk-button uk-button-default">{{t .LangCode "site.footer.rules"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tb-grid">
|
||||
<div class="uk-card uk-card-default">
|
||||
<p class="tb-card-title">匿名也能问</p>
|
||||
<p class="tb-card-text">不需要账号、不需要真实邮箱,打开就能写。想收到回复再留邮箱即可。</p>
|
||||
</div>
|
||||
<div class="uk-card uk-card-default">
|
||||
<p class="tb-card-title">不止一问一答</p>
|
||||
<p class="tb-card-text">问题二维码、私聊、投票、追加提问、Markdown 排版,原版没有的这里都有。</p>
|
||||
</div>
|
||||
<div class="uk-card uk-card-default">
|
||||
<p class="tb-card-title">箱子归你</p>
|
||||
<p class="tb-card-text">头像、背景、二维码配色都能自己调,还能设置审核严格度和收集时段。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-card uk-card-default uk-card-body">
|
||||
<p class="tb-notice-tag">域名迁移</p>
|
||||
<p class="tb-card-text">
|
||||
本站已切换到 <a href="https://box.shiroko.one/">box.shiroko.one</a>,原域名将在 2026 年 12 月 24 日到期,
|
||||
期间通过 301 转发指向新域名,到期后旧域名将彻底不再使用。
|
||||
</p>
|
||||
<p class="tb-card-text">
|
||||
审核服务已切换到阿里云,审核速度提升且误伤更少;同时允许用户调整审核严格度,在不碰底线的前提下
|
||||
可以设置不接受辱骂、广告等信息(即「不听坏话模式」)。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="uk-card uk-card-default uk-card-body">
|
||||
<h2 class="tb-section-title">一点提醒</h2>
|
||||
<ul class="tb-list">
|
||||
<li>本站唯一指定认证站长:<a href="https://box.shiroko.one/_/tamakyi">小狼</a>,注意不要被骗。</li>
|
||||
<li>本站提倡友好、友善的发言,请遵守<a href="/rules">社区规则</a>。无论匿名与否,都要为自己的发言负责。</li>
|
||||
<li>不允许垃圾信息、广告、辱骂、涉政、暴恐、色情、违禁、无意义、灌水提问,涉政或不良言论将直接删除。</li>
|
||||
</ul>
|
||||
<p class="tb-card-text tb-lead">
|
||||
想先试试功能,可以到站长的提问箱
|
||||
<a href="//box.shiroko.one/_/tamakyi">小狼的提问箱</a> 提问或提意见。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<details class="uk-card uk-card-default uk-card-body tb-changelog">
|
||||
<summary>近期更新</summary>
|
||||
<ul class="tb-list">
|
||||
<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>
|
||||
<li><strong>2026.5</strong> 增加私聊功能,可连续对话,详见<a href="https://blog.shiroko.one/record/tamabox-update-20260513">介绍</a>;另有提问箱卡片分享。</li>
|
||||
<li><strong>2026.2</strong> 新增用户展示和标签功能,可给自己贴 5 个标签并选择是否在<a href="https://box.shiroko.one/explore">探索页</a>展示,详情见<a href="https://blog.shiroko.one/record/tamabox-tags">狼的公告板</a>。</li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<div class="uk-card uk-card-default uk-card-body">
|
||||
<h2 class="tb-section-title">{{t .LangCode "site.stats"}}</h2>
|
||||
<div class="tb-stats">
|
||||
<div>
|
||||
<span class="tb-stat-num tb-num" data-stat="registered_users">{{if .SiteStats}}{{.SiteStats.RegisteredUsers}}{{else}}-{{end}}</span>
|
||||
<span class="tb-stat-label">注册用户</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="tb-stat-num tb-num" data-stat="total_questions">{{if .SiteStats}}{{.SiteStats.TotalQuestions}}{{else}}-{{end}}</span>
|
||||
<span class="tb-stat-label">累计提问</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="tb-stat-num tb-num" data-stat="answered_questions">{{if .SiteStats}}{{.SiteStats.AnsweredQuestions}}{{else}}-{{end}}</span>
|
||||
<span class="tb-stat-label">已获回答</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="tb-stats-meta">
|
||||
最后提问:<span data-stat="last_question_at">{{if .SiteStats}}{{.SiteStats.LastQuestionAt}}{{else}}-{{end}}</span><br>
|
||||
最后回答:<span data-stat="last_answer_at">{{if .SiteStats}}{{.SiteStats.LastAnswerAt}}{{else}}-{{end}}</span><br>
|
||||
数据更新于:<span data-stat="updated_at">{{if .SiteStats}}{{.SiteStats.UpdatedAt}}{{else}}-{{end}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<p>{{t .LangCode "site.stats"}}:<pre style="overflow: hidden;" id="site-stats-text">{{if .SiteStats}}{{.SiteStats.Text}}{{end}}</pre></p>
|
||||
<script type="text/javascript">
|
||||
// 首页统计已改为程序内直接计算(服务端 30 分钟缓存),这里每 30 分钟定时拉取最新值刷新,
|
||||
// 与原来 crontab 生成 question.count.txt 的节奏一致,且不再依赖外部静态文件。
|
||||
// 统计数字保持服务端 30 分钟缓存,页面每 30 分钟拉一次最新值就地更新(不整页刷新)。
|
||||
// 与原来写 textContent 整块文本的做法等价,只是改为按字段更新三张数字卡。
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
setInterval(function () {
|
||||
fetch("/api/v1/site-stats")
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (resp) {
|
||||
var d = resp.data;
|
||||
if (!d || !d.text) return;
|
||||
var el = document.getElementById("site-stats-text");
|
||||
if (el) el.textContent = d.text;
|
||||
if (!d) return;
|
||||
["registered_users", "total_questions", "answered_questions",
|
||||
"last_question_at", "last_answer_at", "updated_at"].forEach(function (k) {
|
||||
var v = d[k];
|
||||
if (v === undefined || v === null || v === "") return;
|
||||
var el = document.querySelector('[data-stat="' + k + '"]');
|
||||
if (el) el.textContent = v;
|
||||
});
|
||||
})
|
||||
.catch(function () {});
|
||||
}, 30 * 60 * 1000);
|
||||
});
|
||||
</script>
|
||||
<!--<script src="https://r2.337845818.best/oss-to-r2/nekobox/cdn/waline/client/v2/waline.js"></script>
|
||||
<link href='https://r2.337845818.best/oss-to-r2/nekobox/cdn/waline/client/v2/waline-no-commits.css' rel='stylesheet' />-->
|
||||
<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,
|
||||
login: 'enable',
|
||||
wordLimit: 50,
|
||||
pageSize: 5,
|
||||
avatar: 'identicon',
|
||||
emoji: [
|
||||
'https://gcore.jsdelivr.net/gh/tamakyi/emoji-collection@main/acfun-color/60x60',
|
||||
],
|
||||
//禁止图片上传按钮
|
||||
imageUploader: false,
|
||||
//不显示版权标志
|
||||
copyright: false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{{template "base/footer" .}}
|
||||
<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,
|
||||
login: 'enable',
|
||||
wordLimit: 50,
|
||||
pageSize: 5,
|
||||
avatar: 'identicon',
|
||||
emoji: [
|
||||
'https://gcore.jsdelivr.net/gh/tamakyi/emoji-collection@main/acfun-color/60x60',
|
||||
],
|
||||
//禁止图片上传按钮
|
||||
imageUploader: false,
|
||||
//不显示版权标志
|
||||
copyright: false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{{template "base/footer" .}}
|
||||
@@ -35,20 +35,8 @@
|
||||
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">
|
||||
@@ -262,7 +250,7 @@
|
||||
<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 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>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<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>
|
||||
/* 封面高度(原内联 style,改到类里便于和遮罩一起维护) */
|
||||
.tb-profile-cover { min-height: 260px; }
|
||||
/* 投票列表:与探索页"全部投票"一致的列表行样式 */
|
||||
.profile-votes-list { display: grid; gap: 0; }
|
||||
.profile-vote-item {
|
||||
@@ -14,16 +16,16 @@
|
||||
gap: 16px;
|
||||
min-width: 0;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid var(--tb-border, #e9e9e9);
|
||||
border-bottom: 1px solid var(--tb-border);
|
||||
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-item:first-child { border-top: 1px solid var(--tb-border); }
|
||||
.profile-vote-item:hover { background: var(--tb-surface-hover); text-decoration: none; }
|
||||
.profile-vote-content { min-width: 0; }
|
||||
.profile-vote-title {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
color: var(--tb-text, #333);
|
||||
color: var(--tb-text);
|
||||
font-size: 0.98rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.45;
|
||||
@@ -40,7 +42,7 @@
|
||||
.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);
|
||||
color: var(--tb-primary);
|
||||
font-size: 0.82rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -55,9 +57,9 @@
|
||||
padding: 4px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid var(--tb-border, #e5e5e5);
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 9px;
|
||||
background: var(--tb-surface-2, #fafafa);
|
||||
background: var(--tb-surface-2);
|
||||
}
|
||||
.profile-tab {
|
||||
flex: 1;
|
||||
@@ -65,26 +67,26 @@
|
||||
border-radius: 6px;
|
||||
padding: 9px 15px;
|
||||
background: transparent;
|
||||
color: var(--tb-text-muted, #666);
|
||||
color: var(--tb-text-muted);
|
||||
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:hover { color: var(--tb-primary); }
|
||||
.profile-tab.is-active {
|
||||
background: var(--tb-surface, #fff);
|
||||
background: var(--tb-surface);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.10);
|
||||
color: var(--tb-primary, #1e87f0);
|
||||
color: var(--tb-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
/* 功能关闭时置灰禁用的 Tab(如投票功能关闭) */
|
||||
.profile-tab.is-disabled,
|
||||
.profile-tab:disabled {
|
||||
cursor: not-allowed;
|
||||
color: var(--tb-text-muted, #999);
|
||||
color: var(--tb-text-muted);
|
||||
opacity: 0.7;
|
||||
}
|
||||
.profile-tab.is-disabled:hover { color: var(--tb-text-muted, #999); }
|
||||
.profile-tab.is-disabled:hover { color: var(--tb-text-muted); }
|
||||
.profile-panel[hidden] { display: none !important; }
|
||||
html[data-theme="dark"] .profile-tabs {
|
||||
border-color: var(--tb-border);
|
||||
@@ -95,7 +97,7 @@
|
||||
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="tb-profile-cover uk-flex uk-flex-center uk-flex-middle uk-background-cover uk-light{{ if .PageUser.Background }} tb-cover{{ end }}" 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>
|
||||
@@ -133,6 +135,18 @@
|
||||
<script>
|
||||
document.getElementById("usernamecolor").style.color = "{{.PageUser.Usernamecolor}}";
|
||||
document.getElementById("introcolor").style.color = "{{.PageUser.Introcolor}}";
|
||||
// 封面上的文字颜色由箱主自选,深浅不定:按用户名颜色的亮度决定遮罩方向
|
||||
// (深字上面压浅色遮罩、浅字上面压深色遮罩),保证任何配色都能读。
|
||||
// 无背景图时页面没有 .tb-cover,这里什么都不做,保持原样。
|
||||
(function () {
|
||||
var cover = document.querySelector('.tb-cover');
|
||||
var el = document.getElementById('usernamecolor');
|
||||
if (!cover || !el) return;
|
||||
var m = window.getComputedStyle(el).color.match(/\d+/g);
|
||||
if (!m || m.length < 3) return;
|
||||
var lum = (0.299 * m[0] + 0.587 * m[1] + 0.114 * m[2]) / 255;
|
||||
if (lum > 0.62) cover.classList.add('tb-cover-dark');
|
||||
})();
|
||||
</script>
|
||||
<div>
|
||||
<div class="uk-card uk-card-default uk-card-small uk-card-body">
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
<div class="uk-margin uk-text-center">
|
||||
<textarea name="content" class="uk-textarea" rows="5" placeholder="{{t .LangCode "ask.placeholder"}}"
|
||||
maxlength="{{ .Limits.QuestionContentLen }}">{{.content}}</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 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>
|
||||
|
||||
+24
-24
@@ -30,13 +30,13 @@
|
||||
}
|
||||
.explore-name a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
color: var(--tb-text);
|
||||
}
|
||||
.explore-name a:hover {
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
}
|
||||
.explore-intro {
|
||||
color: #666;
|
||||
color: var(--tb-text-secondary);
|
||||
margin-bottom: 10px;
|
||||
font-size: 0.9rem;
|
||||
display: -webkit-box;
|
||||
@@ -60,7 +60,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background: #f8f8f8;
|
||||
background: var(--tb-surface-2);
|
||||
border-radius: 8px;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
@@ -83,7 +83,7 @@
|
||||
}
|
||||
.recommend-name a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
color: var(--tb-text);
|
||||
}
|
||||
.recommend-tags {
|
||||
display: flex;
|
||||
@@ -108,14 +108,14 @@
|
||||
gap: 16px;
|
||||
min-width: 0;
|
||||
padding: 16px 18px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 8px;
|
||||
background: #fafafa;
|
||||
background: var(--tb-surface-2);
|
||||
text-decoration: none;
|
||||
transition: border-color 0.2s ease, background 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
.hot-vote-item:hover {
|
||||
border-color: #1e87f0;
|
||||
border-color: var(--tb-primary);
|
||||
background: #f5faff;
|
||||
text-decoration: none;
|
||||
transform: translateY(-1px);
|
||||
@@ -126,7 +126,7 @@
|
||||
.hot-vote-title {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
color: #333;
|
||||
color: var(--tb-text);
|
||||
font-size: 0.98rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.45;
|
||||
@@ -146,7 +146,7 @@
|
||||
}
|
||||
.hot-vote-action {
|
||||
flex: 0 0 auto;
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
font-size: 0.82rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -176,25 +176,25 @@
|
||||
padding: 4px;
|
||||
margin: 2px auto 20px;
|
||||
max-width: 320px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 9px;
|
||||
background: #fafafa;
|
||||
background: var(--tb-surface-2);
|
||||
}
|
||||
.explore-tab {
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
padding: 8px 15px;
|
||||
background: transparent;
|
||||
color: #666;
|
||||
color: var(--tb-text-secondary);
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
transition: background 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
.explore-tab:hover { color: #1e87f0; }
|
||||
.explore-tab:hover { color: var(--tb-primary); }
|
||||
.explore-tab.is-active {
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.10);
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.explore-panel[hidden] { display: none !important; }
|
||||
@@ -211,12 +211,12 @@
|
||||
border: 1px solid #dce9ff;
|
||||
border-radius: 7px;
|
||||
padding: 7px 11px;
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
background: #f5faff;
|
||||
cursor: pointer;
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
.vote-random-btn:hover { border-color: #1e87f0; background: #edf6ff; }
|
||||
.vote-random-btn:hover { border-color: var(--tb-primary); background: #edf6ff; }
|
||||
.all-votes-list { display: grid; gap: 10px; }
|
||||
.all-vote-item {
|
||||
display: flex;
|
||||
@@ -224,10 +224,10 @@
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
border-bottom: 1px solid var(--tb-border);
|
||||
text-decoration: none;
|
||||
}
|
||||
.all-vote-item:first-child { border-top: 1px solid #e9e9e9; }
|
||||
.all-vote-item:first-child { border-top: 1px solid var(--tb-border); }
|
||||
.all-vote-item:hover { background: #f8fbff; text-decoration: none; }
|
||||
.all-vote-item .hot-vote-title { max-width: 100%; }
|
||||
html[data-theme="dark"] .explore-tabs {
|
||||
@@ -241,16 +241,16 @@
|
||||
html[data-theme="dark"] .all-vote-item:hover { background: rgba(78, 168, 245, 0.10); }
|
||||
.explore-notice {
|
||||
background: #f0f7ff;
|
||||
border-left: 4px solid #1e87f0;
|
||||
border-left: 4px solid var(--tb-primary);
|
||||
padding: 15px 20px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
color: #333;
|
||||
color: var(--tb-text);
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.explore-notice strong {
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
}
|
||||
/* 极简「换一批」按钮:描边胶囊 + 悬停浅蓝底色 + 点击旋转反馈 */
|
||||
.tb-shuffle-btn {
|
||||
@@ -260,7 +260,7 @@
|
||||
padding: 5px 14px;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.4;
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
background: transparent;
|
||||
border: 1px solid #e3e3e3;
|
||||
border-radius: 999px;
|
||||
@@ -269,7 +269,7 @@
|
||||
}
|
||||
.tb-shuffle-btn:hover {
|
||||
background: #f0f7ff;
|
||||
border-color: #1e87f0;
|
||||
border-color: var(--tb-primary);
|
||||
}
|
||||
.tb-shuffle-btn:active {
|
||||
transform: scale(0.96);
|
||||
|
||||
+29
-29
@@ -35,7 +35,7 @@
|
||||
.preview-card {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -76,9 +76,9 @@
|
||||
gap: 4px;
|
||||
padding: 4px;
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid var(--tb-border, #e5e5e5);
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 9px;
|
||||
background: var(--tb-surface-2, #fafafa);
|
||||
background: var(--tb-surface-2);
|
||||
}
|
||||
.profile-tab {
|
||||
flex: 1;
|
||||
@@ -86,17 +86,17 @@
|
||||
border-radius: 6px;
|
||||
padding: 9px 8px;
|
||||
background: transparent;
|
||||
color: var(--tb-text-muted, #666);
|
||||
color: var(--tb-text-muted);
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
white-space: nowrap;
|
||||
transition: background 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
.profile-tab:hover { color: var(--tb-primary, #1e87f0); }
|
||||
.profile-tab:hover { color: var(--tb-primary); }
|
||||
.profile-tab.is-active {
|
||||
background: var(--tb-surface, #fff);
|
||||
background: var(--tb-surface);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.10);
|
||||
color: var(--tb-primary, #1e87f0);
|
||||
color: var(--tb-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.profile-panel[hidden] { display: none !important; }
|
||||
@@ -113,7 +113,7 @@
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
@@ -137,7 +137,7 @@
|
||||
display: block;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.5;
|
||||
color: #999;
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
.feat-field { display: block; }
|
||||
.feat-field > label > span {
|
||||
@@ -172,18 +172,18 @@
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
padding: 3px 8px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 999px;
|
||||
font-size: 0.78rem;
|
||||
color: #666;
|
||||
color: var(--tb-text-secondary);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.feat-day input { margin: 0; }
|
||||
.feat-day.is-on {
|
||||
border-color: #1e87f0;
|
||||
border-color: var(--tb-primary);
|
||||
background: rgba(30, 135, 240, 0.08);
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
}
|
||||
.feat-schedule-times {
|
||||
display: flex;
|
||||
@@ -195,12 +195,12 @@
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 0.82rem;
|
||||
color: #666;
|
||||
color: var(--tb-text-secondary);
|
||||
}
|
||||
.feat-schedule-times input[type="time"] {
|
||||
width: 130px;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
html[data-theme="dark"] .feat-day {
|
||||
@@ -208,9 +208,9 @@
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
html[data-theme="dark"] .feat-day.is-on {
|
||||
border-color: #1e87f0;
|
||||
border-color: var(--tb-primary);
|
||||
background: rgba(30, 135, 240, 0.14);
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
}
|
||||
html[data-theme="dark"] .feat-schedule-times input[type="time"] {
|
||||
border-color: var(--tb-border);
|
||||
@@ -219,7 +219,7 @@
|
||||
}
|
||||
.feat-quota-line {
|
||||
font-size: 0.82rem;
|
||||
color: #666;
|
||||
color: var(--tb-text-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
.feat-actions {
|
||||
@@ -259,19 +259,19 @@
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 8px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
cursor: text;
|
||||
}
|
||||
.tb-tag-box:focus-within { border-color: #1e87f0; }
|
||||
.tb-tag-box:focus-within { border-color: var(--tb-primary); }
|
||||
.tb-tag-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 3px;
|
||||
background: #1e87f0;
|
||||
background: var(--tb-primary);
|
||||
color: #fff;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.8;
|
||||
@@ -302,7 +302,7 @@
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
font-size: 0.75rem;
|
||||
color: #999;
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
.tb-tag-error { color: #f0506e; }
|
||||
html[data-theme="dark"] .tb-tag-box {
|
||||
@@ -316,7 +316,7 @@
|
||||
/* ===== profile account 面板卡片化(复用 UIkit 变量体系,暗色自动跟随) ===== */
|
||||
.tb-pcard {
|
||||
background: #fff;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 10px;
|
||||
padding: 13px 14px 8px;
|
||||
margin-bottom: 12px;
|
||||
@@ -332,7 +332,7 @@
|
||||
float: right;
|
||||
font-size: 0.76rem;
|
||||
font-weight: 400;
|
||||
color: #999;
|
||||
color: var(--tb-text-muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
/* 头像与背景预览:两项同行、整体居中;头像框与背景框“显示高度”一致(150px) */
|
||||
@@ -355,7 +355,7 @@
|
||||
.tb-media-frame {
|
||||
display: block;
|
||||
flex: none;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
background: #f7f7f7;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -382,9 +382,9 @@
|
||||
margin: 8px 0 0;
|
||||
font-size: 0.72rem;
|
||||
line-height: 1;
|
||||
color: #666;
|
||||
color: var(--tb-text-secondary);
|
||||
background: #f4f4f4;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 999px;
|
||||
padding: 4px 9px;
|
||||
}
|
||||
@@ -392,7 +392,7 @@
|
||||
display: block;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.5;
|
||||
color: #999;
|
||||
color: var(--tb-text-muted);
|
||||
margin-top: 6px;
|
||||
}
|
||||
.tb-media-actions { margin-top: 10px; }
|
||||
@@ -421,7 +421,7 @@
|
||||
text-align: center;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.6;
|
||||
color: #999;
|
||||
color: var(--tb-text-muted);
|
||||
}
|
||||
.tb-account-note:last-child { margin-bottom: 0; }
|
||||
/* 裁剪弹窗:图片区域限制在视口内,移动端可用 */
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
padding: 4px;
|
||||
margin: 6px auto 20px;
|
||||
max-width: 320px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 9px;
|
||||
background: #fafafa;
|
||||
background: var(--tb-surface-2);
|
||||
}
|
||||
.qlist-tab {
|
||||
flex: 1 1 0;
|
||||
@@ -18,16 +18,16 @@
|
||||
border-radius: 6px;
|
||||
padding: 8px 15px;
|
||||
background: transparent;
|
||||
color: #666;
|
||||
color: var(--tb-text-secondary);
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
transition: background 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
.qlist-tab:hover { color: #1e87f0; }
|
||||
.qlist-tab:hover { color: var(--tb-primary); }
|
||||
.qlist-tab.is-active {
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.10);
|
||||
color: #1e87f0;
|
||||
color: var(--tb-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.qlist-panel[hidden] { display: none !important; }
|
||||
@@ -38,23 +38,23 @@
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
border-bottom: 1px solid var(--tb-border);
|
||||
text-decoration: none;
|
||||
}
|
||||
.all-vote-item:first-child { border-top: 1px solid #e9e9e9; }
|
||||
.all-vote-item:first-child { border-top: 1px solid var(--tb-border); }
|
||||
.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;
|
||||
color: var(--tb-text);
|
||||
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-title:hover { color: var(--tb-primary); }
|
||||
.hot-vote-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -63,7 +63,7 @@
|
||||
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; }
|
||||
.hot-vote-action { flex: 0 0 auto; color: var(--tb-primary); font-size: 0.82rem; white-space: nowrap; }
|
||||
/* 提问列表右上角:状态标签与操作按钮统一尺寸(等宽等高、垂直居中、完全对齐)。
|
||||
每个元素显式带 .qlist-pill 类,选择器挂在 .qlist-pills 容器下提升优先级,
|
||||
避免浏览器对 <button> 的默认样式或 UIkit .uk-label 造成差异。
|
||||
@@ -132,7 +132,7 @@
|
||||
}
|
||||
.qlist-stat {
|
||||
background: #fff;
|
||||
border: 1px solid #e5e5e5;
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 9px;
|
||||
padding: 8px 6px;
|
||||
text-align: center;
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
gap: 10px;
|
||||
padding: 12px 14px;
|
||||
margin-bottom: 8px;
|
||||
border: 1px solid var(--tb-border, #e5e5e5);
|
||||
border: 1px solid var(--tb-border);
|
||||
border-radius: 8px;
|
||||
background: var(--tb-surface, #fff);
|
||||
background: var(--tb-surface);
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
@@ -41,12 +41,12 @@
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.tb-choice:hover {
|
||||
border-color: var(--tb-primary, #1e87f0);
|
||||
background: var(--tb-surface-hover, #f5faff);
|
||||
border-color: var(--tb-primary);
|
||||
background: var(--tb-surface-hover);
|
||||
}
|
||||
.tb-choice:has(input:checked) {
|
||||
border-color: var(--tb-primary, #1e87f0);
|
||||
background: var(--tb-surface-active, #edf6ff);
|
||||
border-color: var(--tb-primary);
|
||||
background: var(--tb-surface-active);
|
||||
}
|
||||
html[data-theme="dark"] .tb-choice {
|
||||
border-color: var(--tb-border);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tamakyi/TamaBox/internal/conf"
|
||||
"github.com/tamakyi/TamaBox/internal/stats"
|
||||
)
|
||||
|
||||
// TestGenPreview 仅用于本地肉眼核对样式改动,产出 outputs/preview-*.html。
|
||||
// 不在 CI 里跑:需要 TEST_PREVIEW=1 才执行。
|
||||
func TestGenPreview(t *testing.T) {
|
||||
if os.Getenv("TEST_PREVIEW") != "1" {
|
||||
t.Skip("set TEST_PREVIEW=1 to generate preview files")
|
||||
}
|
||||
outDir := filepath.Join("..", "outputs")
|
||||
if err := os.MkdirAll(outDir, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
base := map[string]interface{}{
|
||||
"LangCode": "zh-CN",
|
||||
"SupportedLangs": []map[string]string{{"Code": "zh-CN", "Name": "简体中文"}, {"Code": "ja", "Name": "日本語"}, {"Code": "en", "Name": "English"}},
|
||||
"IsLogged": false,
|
||||
"IsUserPage": false,
|
||||
"IsPixel": false,
|
||||
"VConsole": false,
|
||||
"CurrentURI": "/",
|
||||
"ExternalURL": "https://box.shiroko.one",
|
||||
"CaptchaType": "math",
|
||||
"Limits": conf.Limits,
|
||||
"Title": "TamaBox",
|
||||
"SiteStats": &stats.View{
|
||||
RegisteredUsers: 1284, TotalQuestions: 56321, AnsweredQuestions: 31208,
|
||||
LastQuestionAt: "2026-10-19 10:12:44",
|
||||
LastAnswerAt: "2026-10-19 09:58:02",
|
||||
UpdatedAt: "2026-10-19 10:00:00",
|
||||
},
|
||||
}
|
||||
|
||||
for _, theme := range []string{"light", "dark"} {
|
||||
home, err := renderToString(t, "home", base)
|
||||
if err != nil {
|
||||
t.Fatalf("render home: %v", err)
|
||||
}
|
||||
writePreview(t, outDir, "preview-home-"+theme+".html", home, theme, "../static")
|
||||
}
|
||||
|
||||
// 提问箱主页:带背景图(渐变占位)+ 浅色文字,验证遮罩方向
|
||||
boxData := publicBaseData()
|
||||
boxData["VConsole"] = false
|
||||
boxData["Background"] = "data:image/svg+xml;utf8," +
|
||||
strings.NewReplacer("#", "%23").Replace(
|
||||
`<svg xmlns='http://www.w3.org/2000/svg' width='900' height='500'><defs><linearGradient id='g' x1='0' y1='0' x2='1' y2='1'><stop offset='0' stop-color='#3b6ea5'/><stop offset='1' stop-color='#d98b6a'/></linearGradient></defs><rect width='900' height='500' fill='url(#g)'/></svg>`)
|
||||
boxData["PageUser"].(map[string]interface{})["Usernamecolor"] = "#ffffff"
|
||||
boxData["PageUser"].(map[string]interface{})["Introcolor"] = "#ffffff"
|
||||
// 无头 Chrome 里 uk-img 的懒加载不一定触发,这里直接把背景图写进 CSS 便于核对遮罩
|
||||
coverCSS := `<style>.tb-profile-cover{background-image:url("` + boxData["Background"].(string) +
|
||||
`");background-size:cover;background-position:center;}</style>`
|
||||
for _, theme := range []string{"light", "dark"} {
|
||||
box, err := renderToString(t, "question/list", boxData)
|
||||
if err != nil {
|
||||
t.Fatalf("render list: %v", err)
|
||||
}
|
||||
box = strings.Replace(box, "</head>", coverCSS+"</head>", 1)
|
||||
writePreview(t, outDir, "preview-box-"+theme+".html", box, theme, "../static")
|
||||
}
|
||||
|
||||
// 探索页:核对令牌替换后的卡片/列表配色
|
||||
explore := voteBaseData()
|
||||
explore["LangCode"] = "zh-CN"
|
||||
explore["IsUserPage"] = false
|
||||
explore["Keyword"] = ""
|
||||
explore["Sort"] = "latest"
|
||||
explore["Page"] = 1
|
||||
explore["TotalPages"] = 1
|
||||
explore["PrevPage"] = 0
|
||||
explore["NextPage"] = 2
|
||||
explore["HotTags"] = []string{"杂谈", "学习", "音乐"}
|
||||
explore["HotVotes"] = nil
|
||||
explore["AllVotes"] = nil
|
||||
explore["RecommendUsers"] = []interface{}{}
|
||||
explore["Users"] = []map[string]interface{}{
|
||||
{"Name": "小狼", "Domain": "tamakyi", "Avatar": "", "Intro": "随便问,友善一点,看到都会回。", "Tags": "杂谈,日常"},
|
||||
{"Name": "Kitsune", "Domain": "kitsune", "Avatar": "", "Intro": "摄影 / 音乐 / 一点点代码", "Tags": "摄影"},
|
||||
{"Name": "残响", "Domain": "echo", "Avatar": "", "Intro": "长期潜水,偶尔冒泡。", "Tags": "杂谈"},
|
||||
{"Name": "Mika", "Domain": "mika", "Avatar": "", "Intro": "想认识更多有趣的人。", "Tags": "学习,音乐"},
|
||||
}
|
||||
for _, theme := range []string{"light", "dark"} {
|
||||
page, err := renderToString(t, "user/explore", explore)
|
||||
if err != nil {
|
||||
t.Fatalf("render explore: %v", err)
|
||||
}
|
||||
writePreview(t, outDir, "preview-explore-"+theme+".html", page, theme, "../static")
|
||||
}
|
||||
}
|
||||
|
||||
// writePreview 把 CDN 换成可直连的镜像、钉死主题,仅用于本地预览。
|
||||
func writePreview(t *testing.T, dir, name, html, theme, staticPrefix string) {
|
||||
t.Helper()
|
||||
html = strings.ReplaceAll(html, "https://cdnjs.snrat.com/", "https://cdnjs.cloudflare.com/")
|
||||
if theme == "dark" {
|
||||
html = strings.Replace(html, `<html lang="zh-CN">`, `<html lang="zh-CN" data-theme="dark">`, 1)
|
||||
}
|
||||
html = strings.ReplaceAll(html, `href="/favicon.ico"`, `href="`+staticPrefix+`/favicon.ico"`)
|
||||
html = strings.Replace(html, `<title>`, `<title>预览 `+time.Now().Format("15:04")+` · `, 1)
|
||||
if err := os.WriteFile(filepath.Join(dir, name), []byte(html), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user