fix(ui): 话题过多时首页话题栏收起为单行,不再堆满页面顶部
4 个文件变更
+96
-5
fangqihang1717@163.com
| •web/static/app.css | +25 -1 |
| •web/static/app.js | +60 -0 |
| •web/templates/admin.html | +1 -1 |
| •web/templates/front.html | +10 -3 |
变更内容
diff --git a/web/static/app.css b/web/static/app.css
index 5702d8e..1652474 100644
--- a/web/static/app.css
+++ b/web/static/app.css
@@ -111,7 +111,31 @@ button { font-family: inherit; }
/* ---------------- 话题 ---------------- */
.page-head { margin-bottom: 12px; }
-.topic-chips { display: flex; flex-wrap: wrap; gap: 8px; }
+.topic-bar { display: flex; align-items: center; gap: 10px; }
+.topic-chips { display: flex; flex-wrap: wrap; gap: 8px; flex: 1; min-width: 0; }
+/* 话题较多时收起为单行横向滚动,避免话题墙占满页面顶部(由 app.js 按需添加) */
+.topic-chips.collapsed {
+ flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
+ scrollbar-width: none; -ms-overflow-style: none;
+ -webkit-overflow-scrolling: touch;
+ /* 左右渐隐,暗示可以横向滑动 */
+ -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
+ mask-image: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
+}
+.topic-chips.collapsed::-webkit-scrollbar { display: none; }
+.topic-chips.collapsed .chip { flex: 0 0 auto; }
+/* 展开后限制高度,超出部分内部滚动 */
+.topic-chips.expanded { max-height: 34vh; overflow-y: auto; padding-right: 4px; }
+.chip-toggle {
+ flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
+ padding: 4px 10px; border-radius: 999px; font-size: 12px; cursor: pointer;
+ background: var(--clv-card); border: 1px solid var(--clv-border); color: var(--clv-muted);
+}
+.chip-toggle:hover { color: var(--clv-text); border-color: var(--clv-accent); }
+.chip-toggle svg { transition: transform .2s; }
+.chip-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
+/* 后台话题管理:话题过多时限制高度,内部滚动 */
+.topic-manage { max-height: 220px; overflow-y: auto; padding-right: 4px; }
.chip {
display: inline-flex; align-items: center; gap: 4px;
padding: 4px 12px; border-radius: 999px; font-size: 13px;
diff --git a/web/static/app.js b/web/static/app.js
index 99253e0..867d5a3 100644
--- a/web/static/app.js
+++ b/web/static/app.js
@@ -900,6 +900,65 @@
}
}
+ /* ---------------- 首页话题栏:话题过多时收起为单行 ---------------- */
+ function initTopicBar() {
+ var chips = document.getElementById('topic-chips');
+ var toggle = document.getElementById('topic-toggle');
+ if (!chips || !toggle) return;
+ var first = chips.firstElementChild;
+ if (!first) return;
+
+ // 先按默认样式渲染,若换行超过一行说明话题较多
+ var wrapped = false;
+ for (var i = 1; i < chips.children.length; i++) {
+ if (chips.children[i].offsetTop !== first.offsetTop) { wrapped = true; break; }
+ }
+ if (!wrapped) return; // 话题不多,保持原有的自动换行
+
+ chips.classList.add('collapsed');
+ toggle.hidden = false;
+ var label = toggle.querySelector('span');
+
+ // 选中的话题可能被滚出可视区,居中显示它
+ function revealActive() {
+ var act = chips.querySelector('.chip.active');
+ if (!act) return;
+ chips.scrollLeft = act.offsetLeft - (chips.clientWidth - act.offsetWidth) / 2;
+ }
+ revealActive();
+
+ var rt = null;
+ window.addEventListener('resize', function () {
+ if (!chips.classList.contains('collapsed')) return;
+ clearTimeout(rt);
+ rt = setTimeout(revealActive, 150);
+ });
+
+ // PC 端:竖向滚轮转横向滚动
+ chips.addEventListener('wheel', function (e) {
+ if (!chips.classList.contains('collapsed')) return;
+ if (Math.abs(e.deltaY) <= Math.abs(e.deltaX)) return;
+ e.preventDefault();
+ chips.scrollLeft += e.deltaY;
+ }, { passive: false });
+
+ toggle.addEventListener('click', function () {
+ if (chips.classList.contains('expanded')) {
+ chips.classList.remove('expanded');
+ chips.classList.add('collapsed');
+ toggle.setAttribute('aria-expanded', 'false');
+ if (label) label.textContent = '展开';
+ chips.scrollTop = 0;
+ revealActive();
+ } else {
+ chips.classList.remove('collapsed');
+ chips.classList.add('expanded');
+ toggle.setAttribute('aria-expanded', 'true');
+ if (label) label.textContent = '收起';
+ }
+ });
+ }
+
/* ---------------- 旧版数据迁移(后台) ---------------- */
function initMigrate() {
var form = document.getElementById('migrate-form');
@@ -1017,5 +1076,6 @@
initPatrol();
initAdmin();
initMigrate();
+ initTopicBar();
});
})();
diff --git a/web/templates/admin.html b/web/templates/admin.html
index 23ab7f6..0a6430a 100644
--- a/web/templates/admin.html
+++ b/web/templates/admin.html
@@ -419,7 +419,7 @@
<div class="grid2-cards">
<div class="card">
<h3>话题管理</h3>
- <div class="topic-chips">
+ <div class="topic-chips topic-manage">
{{range .topics}}
<span class="chip"># {{.name}}
<form method="post" action="/admin/notices" class="inline-form" data-confirm="确定删除该话题吗?">
diff --git a/web/templates/front.html b/web/templates/front.html
index 8f81901..f7dfc61 100644
--- a/web/templates/front.html
+++ b/web/templates/front.html
@@ -1,9 +1,16 @@
{{/* ============ 首页:瀑布流 + 无限滚动 ============ */}}
{{define "pg_index"}}
<div class="page-head">
- {{if .topics}}<div class="topic-chips">
- <a class="chip {{if not .topic}}active{{end}}" href="/">全部</a>
- {{range .topics}}<a class="chip {{if eq $.topic .name}}active{{end}}" href="/?topic={{.name}}"># {{.name}}</a>{{end}}
+ {{if .topics}}<div class="topic-bar">
+ <div class="topic-chips" id="topic-chips">
+ <a class="chip {{if not .topic}}active{{end}}" href="/">全部</a>
+ {{range .topics}}<a class="chip {{if eq $.topic .name}}active{{end}}" href="/?topic={{.name}}"># {{.name}}</a>{{end}}
+ </div>
+ {{/* 话题较多时由脚本收起为单行,此处按钮用于展开全部 */}}
+ <button type="button" class="chip-toggle" id="topic-toggle" hidden aria-expanded="false" aria-controls="topic-chips">
+ <span>展开</span>
+ <svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
+ </button>
</div>{{end}}
</div>
<div class="masonry" id="masonry" data-topic="{{.topic}}" aria-live="polite"></div>