feat(web): move candidates/system nav to topbar, free mobile bottom nav

This commit is contained in:
kairee committed 2026-11-01 17:43:42 +08:00
1 parent 4253779501
commit 3cb9b92361
6 files changed
+59 -20

No files matched your search

+24 -11
View File
@@ -15,11 +15,16 @@ const NAV_ITEMS = [
{ path: "/videos", label: "视频", icon: "video" },
{ path: "/ups", label: "UP主", icon: "up" },
{ path: "/fans", label: "粉丝", icon: "fans" },
{ path: "/candidates", label: "候选", icon: "candidate", protected: true },
{ path: "/system", label: "系统", icon: "system", protected: true },
{ path: "/about", label: "说明", icon: "info" },
];
// 登录后的「候选 / 系统」入口放在顶栏右侧(未登录显示「登录」),
// 以减轻移动端底部主导航的拥挤。
const TOPBAR_ITEMS = [
{ path: "/candidates", label: "候选" },
{ path: "/system", label: "系统" },
];
const ROUTES = [
{ pattern: /^\/home$/, view: renderHome, title: "最新动态" },
{ pattern: /^\/videos$/, view: renderVideos, title: "视频" },
@@ -79,13 +84,23 @@ function icon(name) {
function renderNav() {
const nav = document.querySelector("#nav-items");
const items = NAV_ITEMS.filter(
(item) => !item.protected || canAccessProtected(),
);
nav.innerHTML = items.map((item) => `
nav.innerHTML = NAV_ITEMS.map((item) => `
<a class="nav-item" href="${item.path}" data-nav="${item.path}">
${icon(item.icon)}<span class="nav-label">${item.label}</span>
</a>`).join("");
// 未登录显示「登录」;可访问受保护页面时显示「候选 | 系统」。
const loggedIn = canAccessProtected();
document.querySelectorAll(".topbar-auth").forEach((element) => {
element.hidden = loggedIn;
});
document.querySelectorAll("[data-topbar-links]").forEach((element) => {
element.hidden = !loggedIn;
element.innerHTML = loggedIn
? TOPBAR_ITEMS.map((item) => `
<a href="${item.path}" data-topbar-nav="${item.path}">${item.label}</a>`).join("")
: "";
});
}
function activeNav(path) {
@@ -99,6 +114,9 @@ function activeNav(path) {
document.querySelectorAll("[data-nav]").forEach((item) => {
item.classList.toggle("active", item.dataset.nav === active);
});
document.querySelectorAll("[data-topbar-nav]").forEach((item) => {
item.classList.toggle("active", item.dataset.topbarNav === active);
});
}
function setTitle(route, path) {
@@ -144,11 +162,6 @@ async function boot() {
element.hidden = false;
});
}
if (authState.authEnabled && !authState.authenticated) {
document.querySelectorAll(".topbar-auth").forEach((element) => {
element.hidden = false;
});
}
} catch {
toast("无法连接看板服务", "error");
}
+10 -4
View File
@@ -20,8 +20,11 @@
<small class="brand-subtitle">最新动态</small>
</span>
</a>
<a class="topbar-hint topbar-auth" href="/login" hidden>登录</a>
<span class="topbar-hint topbar-preview" hidden>预览</span>
<div class="topbar-actions">
<a class="topbar-hint topbar-auth" href="/login" hidden>登录</a>
<span class="topbar-links" data-topbar-links hidden></span>
<span class="topbar-hint topbar-preview" hidden>预览</span>
</div>
</header>
<div class="preview-banner" id="preview-banner" hidden>预览数据 · 不影响真实数据库</div>
<main class="main-shell">
@@ -36,8 +39,11 @@
<small class="brand-subtitle">最新动态</small>
</span>
</a>
<a class="topbar-hint topbar-auth" href="/login" hidden>登录</a>
<span class="topbar-hint topbar-preview" hidden>预览</span>
<div class="topbar-actions">
<a class="topbar-hint topbar-auth" href="/login" hidden>登录</a>
<span class="topbar-links" data-topbar-links hidden></span>
<span class="topbar-hint topbar-preview" hidden>预览</span>
</div>
</div>
<div class="nav-items" id="nav-items"></div>
</nav>
+22 -2
View File
@@ -123,10 +123,30 @@ h1, h2, h3, p { margin: 0; }
color: var(--muted);
font-size: 11px;
}
.topbar-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.topbar-links { display: flex; align-items: center; gap: 6px; }
.topbar-links a {
padding: 4px 10px;
border: 1px solid var(--border);
border-radius: 999px;
color: var(--muted);
font-size: 11px;
white-space: nowrap;
}
.topbar-links a:hover {
color: var(--accent);
border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
}
.topbar-links a.active {
color: var(--accent);
background: var(--accent-soft);
border-color: transparent;
}
.sidebar-topbar {
display: none;
flex-direction: column;
align-items: flex-start;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 8px;
width: 100%;
padding: 0 4px 12px;