import { ChevronDown, KeyRound, LogOut, Menu as MenuIcon } from "lucide-react"; import { useEffect, useRef, useState, type KeyboardEvent, type Ref } from "react"; import { Avatar, Button, Dropdown, Layout, Space, Tooltip, type DropdownOption } from "tdesign-react"; export interface AppHeaderProps { adminName?: string; adminUsername?: string; onToggleMenu?: () => void; menuButtonRef?: Ref; menuOpen?: boolean; menuControls?: string; onLogout?: () => void; onOpenPassword?: () => void; } export default function AppHeader({ adminName, adminUsername, onToggleMenu, menuButtonRef, menuOpen = false, menuControls, onLogout, onOpenPassword }: AppHeaderProps) { const displayName = adminName?.trim() || "管理员"; const avatarText = [...displayName][0]?.toUpperCase() || "管"; const [userMenuOpen, setUserMenuOpen] = useState(false); const userMenuButtonRef = useRef(null); const menuItem = (label: string) => ; const userOptions: DropdownOption[] = [ ...(onOpenPassword ? [{ value: "password", content: menuItem("修改密码"), prefixIcon: }] : []), ...(onLogout ? [{ value: "logout", content: menuItem("退出登录"), theme: "error" as const, prefixIcon: }] : []), ]; useEffect(() => { if (!userMenuOpen) return; let disposed = false; const focusMenu = () => { if (disposed) return; const menu = document.querySelector(".tn-user-dropdown"); if (!menu) return; menu.setAttribute("role", "menu"); menu.setAttribute("aria-label", "账号操作"); menu.querySelector("[role='menuitem']")?.focus(); }; const frame = window.requestAnimationFrame(focusMenu); const timer = window.setTimeout(focusMenu, 80); return () => { disposed = true; window.cancelAnimationFrame(frame); window.clearTimeout(timer); }; }, [userMenuOpen]); function handleMenuKeyDown(event: KeyboardEvent) { const items = Array.from(document.querySelectorAll(".tn-user-dropdown [role='menuitem']")); const index = items.indexOf(event.currentTarget); if (event.key === "Escape") { event.preventDefault(); userMenuButtonRef.current?.click(); userMenuButtonRef.current?.focus(); return; } if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key) || !items.length) return; event.preventDefault(); const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowDown" ? (index + 1) % items.length : (index - 1 + items.length) % items.length; items[nextIndex]?.focus(); } const handleUserAction = (item: DropdownOption) => { if (item.value === "password") onOpenPassword?.(); if (item.value === "logout") onLogout?.(); }; return ( } ); }