feat: 移动端底部导航可配置与工作区导航、置顶后台等前端调整

This commit is contained in:
2026-10-16 16:26:08 +08:00
parent 47f87a011c
commit 55ded2695c
10 changed files with 573 additions and 154 deletions

View File

@@ -1,14 +1,14 @@
"use client";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { usePathname, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useRef, useState, type ReactNode } from "react";
import { Bookmark, Home, LayoutGrid, Menu, ShieldCheck } from "lucide-react";
import { Bookmark, CodeXml, Home, LayoutGrid, Menu, ShieldCheck, Trophy } from "lucide-react";
import type { BoardWithCount, User } from "@/lib/api";
import { isStaff } from "@/lib/roles";
import BoardIcon, { boardColor } from "@/components/BoardIcon";
import { useUrlStyle } from "@/components/SiteBrandProvider";
import { userPath } from "@/lib/urlStyle";
import { leaderboardPath, snippetsPath, userPath } from "@/lib/urlStyle";
import { RailDrawerPanel, useDrawerChrome } from "@/components/MobileRailDrawers";
// 首页壳内板块切换:仅替换中栏帖子流,不离开工作台
@@ -26,9 +26,16 @@ export function WorkspaceNavPanel({
user?: User | null;
}) {
const params = useSearchParams();
const pathname = usePathname();
const urlStyle = useUrlStyle();
const activeBoard = Number(params.get("board")) || 0;
const showAdmin = !!user && isStaff(user.role);
const snipHref = snippetsPath(urlStyle);
const lbHref = leaderboardPath(urlStyle);
// 与 Header 高亮规则一致:覆盖标准路径与伪静态(/snippet-*.html、/rank.html 等)
const snippetsActive =
!!pathname && (pathname.startsWith("/snippets") || pathname.startsWith("/snippet-"));
const leaderboardActive = !!pathname && (pathname === lbHref || pathname.startsWith(`${lbHref}/`));
return (
<section className="j13-module flex max-h-[var(--rail-max-h)] flex-col overflow-hidden" aria-label="板块目录">
@@ -49,6 +56,37 @@ export function WorkspaceNavPanel({
<span className="j13-bcard-name flex-1 truncate">全部讨论</span>
</Link>
{/* 不进底栏的全局入口:仅移动端展示(首页 ☰ 导航抽屉是其在移动端的唯一路径),
桌面端由顶部导航承担,左栏不重复 */}
<Link
href={snipHref}
className="j13-bcard lg:hidden"
aria-current={snippetsActive ? "page" : undefined}
>
<span
className="j13-bcard-ico"
style={{ background: "var(--accent-soft)", color: "var(--accent)" }}
aria-hidden="true"
>
<CodeXml size={15} />
</span>
<span className="j13-bcard-name flex-1 truncate">代码片段</span>
</Link>
<Link
href={lbHref}
className="j13-bcard lg:hidden"
aria-current={leaderboardActive ? "page" : undefined}
>
<span
className="j13-bcard-ico"
style={{ background: "var(--accent-soft)", color: "var(--accent)" }}
aria-hidden="true"
>
<Trophy size={15} />
</span>
<span className="j13-bcard-name flex-1 truncate">排行榜</span>
</Link>
{user ? (
<Link href={`${userPath(urlStyle, user.id)}?tab=favorites`} className="j13-bcard">
<span