fix(ui): remove sidebar collapse footer and unify header control heights
Build and Deploy / build-and-push (push) Successful in 52s
Build and Deploy / build-and-push (push) Successful in 52s
This commit is contained in:
@@ -33,7 +33,7 @@ import { SystemNotice } from '@/components/business/SystemNotice'
|
|||||||
import { ToastHost } from '@/components/business/ToastHost'
|
import { ToastHost } from '@/components/business/ToastHost'
|
||||||
import { resetAuthCache } from '@/lib/auth'
|
import { resetAuthCache } from '@/lib/auth'
|
||||||
import { eventBus } from '@/lib/event-bus'
|
import { eventBus } from '@/lib/event-bus'
|
||||||
import { Button, cn } from '@/components/ui'
|
import { cn } from '@/components/ui'
|
||||||
|
|
||||||
const NAV_ITEMS = [
|
const NAV_ITEMS = [
|
||||||
{ path: '/', icon: LayoutDashboard, label: '数据仪表', exact: true },
|
{ path: '/', icon: LayoutDashboard, label: '数据仪表', exact: true },
|
||||||
@@ -213,23 +213,6 @@ export default function Layout() {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{/* 桌面端:侧栏底部放一个次要折叠入口,主入口在顶栏 */}
|
|
||||||
{!isMobile && (
|
|
||||||
<div className="border-t border-[var(--border)] p-2">
|
|
||||||
<button
|
|
||||||
onClick={() => setCollapsed((v) => !v)}
|
|
||||||
title={collapsed ? '展开侧边栏' : '收起侧边栏'}
|
|
||||||
className={cn(
|
|
||||||
'flex h-9 w-full items-center rounded-md text-[12px] text-[var(--text-muted)] transition-colors hover:bg-[var(--bg-hover)] hover:text-[var(--text-primary)]',
|
|
||||||
sidebarCollapsed ? 'justify-center' : 'gap-2 px-2.5',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{collapsed ? <ChevronRight size={15} strokeWidth={1.5} /> : <ChevronLeft size={15} strokeWidth={1.5} />}
|
|
||||||
{!sidebarCollapsed && <span>收起导航</span>}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main className="flex min-w-0 flex-1 flex-col">
|
<main className="flex min-w-0 flex-1 flex-col">
|
||||||
@@ -237,19 +220,19 @@ export default function Layout() {
|
|||||||
<div className="flex min-w-0 flex-1 items-center gap-2">
|
<div className="flex min-w-0 flex-1 items-center gap-2">
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
<button
|
<button
|
||||||
className="rounded-md p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)]"
|
className="inline-flex h-8 w-8 items-center justify-center rounded-md text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-primary)]"
|
||||||
onClick={() => setMenuOpen(true)}
|
onClick={() => setMenuOpen(true)}
|
||||||
title="打开菜单"
|
title="打开菜单"
|
||||||
>
|
>
|
||||||
<Menu size={18} strokeWidth={1.5} />
|
<Menu size={16} strokeWidth={1.5} />
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
className="rounded-md p-2 text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-primary)]"
|
className="inline-flex h-8 w-8 items-center justify-center rounded-md text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-primary)]"
|
||||||
onClick={() => setCollapsed((v) => !v)}
|
onClick={() => setCollapsed((v) => !v)}
|
||||||
title={collapsed ? '展开侧边栏' : '收起侧边栏'}
|
title={collapsed ? '展开侧边栏' : '收起侧边栏'}
|
||||||
>
|
>
|
||||||
{collapsed ? <PanelLeftOpen size={17} strokeWidth={1.5} /> : <PanelLeftClose size={17} strokeWidth={1.5} />}
|
{collapsed ? <PanelLeftOpen size={16} strokeWidth={1.5} /> : <PanelLeftClose size={16} strokeWidth={1.5} />}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<p className="truncate text-[13px] text-[var(--text-muted)]" title={sentence}>
|
<p className="truncate text-[13px] text-[var(--text-muted)]" title={sentence}>
|
||||||
@@ -257,30 +240,30 @@ export default function Layout() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-1.5">
|
{/* 顶栏工具统一 h-8,避免通知/主题/用户高度不一致 */}
|
||||||
|
<div className="flex h-8 items-center gap-1.5">
|
||||||
<NodeSwitcher />
|
<NodeSwitcher />
|
||||||
<SystemNotice />
|
<SystemNotice />
|
||||||
<Button
|
<button
|
||||||
variant="secondary"
|
type="button"
|
||||||
size="icon"
|
|
||||||
onClick={toggleTheme}
|
onClick={toggleTheme}
|
||||||
title={theme === 'light' ? '深色模式' : '浅色模式'}
|
title={theme === 'light' ? '深色模式' : '浅色模式'}
|
||||||
className="h-8 w-8"
|
className="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-[var(--border)] bg-[var(--bg-primary)] text-[var(--text-secondary)] transition-colors hover:border-[var(--border-hover)] hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-primary)]"
|
||||||
>
|
>
|
||||||
{theme === 'light' ? <Moon size={15} strokeWidth={1.5} /> : <Sun size={15} strokeWidth={1.5} />}
|
{theme === 'light' ? <Moon size={15} strokeWidth={1.5} /> : <Sun size={15} strokeWidth={1.5} />}
|
||||||
</Button>
|
</button>
|
||||||
|
|
||||||
{/* 用户菜单:退出登录放这里,比左下角更干净 */}
|
|
||||||
<div className="relative" ref={userMenuRef}>
|
<div className="relative" ref={userMenuRef}>
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
onClick={() => setUserMenuOpen((v) => !v)}
|
onClick={() => setUserMenuOpen((v) => !v)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex h-8 items-center gap-1.5 rounded-md border border-[var(--border)] bg-[var(--bg-primary)] px-2 text-[12px] text-[var(--text-secondary)] transition-colors hover:border-[var(--border-hover)] hover:text-[var(--text-primary)]',
|
'inline-flex h-8 items-center gap-1.5 rounded-md border border-[var(--border)] bg-[var(--bg-primary)] px-2 text-[12px] leading-none text-[var(--text-secondary)] transition-colors hover:border-[var(--border-hover)] hover:text-[var(--text-primary)]',
|
||||||
userMenuOpen && 'border-[var(--border-hover)] text-[var(--text-primary)]',
|
userMenuOpen && 'border-[var(--border-hover)] text-[var(--text-primary)]',
|
||||||
)}
|
)}
|
||||||
title="账户"
|
title="账户"
|
||||||
>
|
>
|
||||||
<span className="flex h-5 w-5 items-center justify-center rounded-full bg-[var(--bg-tertiary)] text-[var(--text-muted)]">
|
<span className="inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-[var(--bg-tertiary)] text-[var(--text-muted)]">
|
||||||
<UserRound size={12} strokeWidth={1.75} />
|
<UserRound size={12} strokeWidth={1.75} />
|
||||||
</span>
|
</span>
|
||||||
<span className="hidden max-w-[96px] truncate sm:inline">{username}</span>
|
<span className="hidden max-w-[96px] truncate sm:inline">{username}</span>
|
||||||
@@ -293,6 +276,7 @@ export default function Layout() {
|
|||||||
<div className="truncate text-[11px] text-[var(--text-muted)]">已登录</div>
|
<div className="truncate text-[11px] text-[var(--text-muted)]">已登录</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setUserMenuOpen(false)
|
setUserMenuOpen(false)
|
||||||
void logout()
|
void logout()
|
||||||
|
|||||||
@@ -76,10 +76,10 @@ export function NodeSwitcher() {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex h-8 max-w-[150px] items-center gap-1 rounded-md border px-2 text-[11px]',
|
'inline-flex h-8 max-w-[150px] shrink-0 items-center gap-1 rounded-md border px-2 text-[11px] leading-none',
|
||||||
selected !== 'local'
|
selected !== 'local'
|
||||||
? 'border-amber-500/30 bg-amber-500/10 text-amber-600 dark:text-amber-400'
|
? 'border-amber-500/30 bg-amber-500/10 text-amber-600 dark:text-amber-400'
|
||||||
: 'border-[var(--border)] bg-[var(--bg-secondary)] text-[var(--text-secondary)]',
|
: 'border-[var(--border)] bg-[var(--bg-primary)] text-[var(--text-secondary)]',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<MonitorDot size={12} className="shrink-0" />
|
<MonitorDot size={12} className="shrink-0" />
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Bell, Check } from 'lucide-react'
|
|||||||
import { api, LOG_CATEGORY, LOG_STATUS, type AppLog } from '@/api'
|
import { api, LOG_CATEGORY, LOG_STATUS, type AppLog } from '@/api'
|
||||||
import { LOG_EVENTS } from '@/constants'
|
import { LOG_EVENTS } from '@/constants'
|
||||||
import { useEventBus } from '@/hooks/useEventBus'
|
import { useEventBus } from '@/hooks/useEventBus'
|
||||||
import { Button } from '@/components/ui'
|
|
||||||
import { formatDateTime } from '@/lib/format'
|
import { formatDateTime } from '@/lib/format'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
@@ -63,18 +62,17 @@ export function SystemNotice() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Button
|
<button
|
||||||
variant="secondary"
|
type="button"
|
||||||
size="icon"
|
className="relative inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md border border-[var(--border)] bg-[var(--bg-primary)] text-[var(--text-secondary)] transition-colors hover:border-[var(--border-hover)] hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-primary)]"
|
||||||
className="relative h-8 w-8"
|
|
||||||
title="系统通知"
|
title="系统通知"
|
||||||
onClick={() => setOpen((v) => !v)}
|
onClick={() => setOpen((v) => !v)}
|
||||||
>
|
>
|
||||||
<Bell size={15} strokeWidth={1.5} />
|
<Bell size={15} strokeWidth={1.5} />
|
||||||
{unread > 0 ? (
|
{unread > 0 ? (
|
||||||
<span className="absolute right-1 top-1 h-2 w-2 animate-pulse rounded-full bg-red-500" />
|
<span className="absolute right-1.5 top-1.5 h-1.5 w-1.5 animate-pulse rounded-full bg-red-500" />
|
||||||
) : null}
|
) : null}
|
||||||
</Button>
|
</button>
|
||||||
|
|
||||||
{open ? (
|
{open ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user