feat(web): move candidates/system nav to topbar, free mobile bottom nav
This commit is contained in:
1 parent
4253779501
commit
3cb9b92361
6 files changed
+59
-20
No files matched your search
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user