import { useClickOutside } from "@web/src/hooks/useClickOutside"; import { useAuth } from "@web/src/providers/auth-provider"; import { motion, AnimatePresence } from "framer-motion"; import { useState, useRef, useCallback, useMemo } from "react"; import { Avatar } from "../../common/element/Avatar"; import { UserOutlined, SettingOutlined, QuestionCircleOutlined, LogoutOutlined, } from "@ant-design/icons"; import { Spin } from "antd"; import { useNavigate } from "react-router-dom"; import { MenuItemType } from "./types"; const menuVariants = { hidden: { opacity: 0, scale: 0.95, y: -10 }, visible: { opacity: 1, scale: 1, y: 0, transition: { type: "spring", stiffness: 300, damping: 30, }, }, exit: { opacity: 0, scale: 0.95, y: -10, transition: { duration: 0.2, }, }, }; export function UserMenu() { const [showMenu, setShowMenu] = useState(false); const menuRef = useRef(null); const { user, logout, isLoading } = useAuth(); const navigate = useNavigate(); useClickOutside(menuRef, () => setShowMenu(false)); const toggleMenu = useCallback(() => { setShowMenu((prev) => !prev); }, []); const menuItems: MenuItemType[] = useMemo( () => [ { icon: , label: "个人信息", action: () => {}, }, { icon: , label: "设置", action: () => { navigate("/admin/staff"); }, }, // { // icon: , // label: '帮助', // action: () => { }, // }, { icon: , label: "注销", action: () => logout(), }, ], [logout] ); const handleMenuItemClick = useCallback((action: () => void) => { action(); setShowMenu(false); }, []); if (isLoading) { return (
); } return (
{/* Avatar 容器,相对定位 */}
{/* 小绿点 */}
{/* 用户信息,显示在 Avatar 右侧 */}
{user?.showname || user?.username} {user?.department?.name}
{showMenu && ( {/* User Profile Section */}
{user?.showname || user?.username} 在线
{/* Menu Items */}
{menuItems.map((item, index) => ( ))}
)}
); }