import React, { useState, useRef, useEffect } from 'react'; import { Category } from '../../types'; import { useApp } from '../../contexts/AppContext'; import CategoryBadge from './CategoryBadge'; import ReactDOM from 'react-dom'; interface CategorySelectorProps { selectedCategory: string | Category; onChange: (categoryId: string) => void; className?: string; } const CategorySelector: React.FC = ({ selectedCategory, onChange, className = '' }) => { const { categories } = useApp(); const [showDropdown, setShowDropdown] = useState(false); const triggerRef = useRef(null); // 查找选中的分类对象 const selectedCategoryObj = categories.find(c => typeof selectedCategory === 'string' ? c._id === selectedCategory : c._id === selectedCategory._id ); // 切换下拉菜单显示状态 const toggleDropdown = () => { setShowDropdown(!showDropdown); }; // 这是关键函数 - 处理分类选择 const handleCategorySelect = (categoryId: string) => { console.log('选择分类:', categoryId); // 直接调用传入的onChange函数 onChange(categoryId); // 关闭下拉菜单 setShowDropdown(false); }; // 点击外部关闭下拉菜单 useEffect(() => { const handleClickOutside = (e: MouseEvent) => { // 只在下拉菜单打开时处理点击外部事件 if (!showDropdown) return; // 获取下拉菜单元素 const menuElement = document.getElementById('category-dropdown-menu'); // 检查点击是否在触发器或下拉菜单内 const isClickInsideTrigger = triggerRef.current && triggerRef.current.contains(e.target as Node); const isClickInsideMenu = menuElement && menuElement.contains(e.target as Node); // 如果点击在两者之外,关闭菜单 if (!isClickInsideTrigger && !isClickInsideMenu) { setShowDropdown(false); } }; // 添加全局点击事件监听 document.addEventListener('mousedown', handleClickOutside); // 组件卸载时移除监听 return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [showDropdown]); // 创建下拉菜单Portal const createMenu = () => { if (!showDropdown || !triggerRef.current) return null; // 获取触发元素位置 const rect = triggerRef.current.getBoundingClientRect(); // 使用Portal将菜单附加到body return ReactDOM.createPortal(
{categories.map((category) => { const isSelected = typeof selectedCategory === 'string' ? selectedCategory === category._id : selectedCategory._id === category._id; // 为每个选项创建一个按钮 return ( ); })}
, document.body ); }; return (
{selectedCategoryObj ? ( ) : (
选择分类
)}
{createMenu()}
); }; export default CategorySelector;