import { useEffect, useState, useRef } from "react"; import { type Employee } from "../../services/api"; // 多选用户下拉框组件 - 带 tag 显示 export function UserMultiSelect({ users, selectedUserIds, onChange, existingMemberIds, }: { users: Employee[]; selectedUserIds: string[]; onChange: (ids: string[]) => void; existingMemberIds?: string[]; }) { const [isOpen, setIsOpen] = useState(false); const containerRef = useRef(null); // 点击外部关闭下拉框 useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (containerRef.current && !containerRef.current.contains(event.target as Node)) { setIsOpen(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, []); const selectedUsers = users.filter((user) => selectedUserIds.includes(user.user_id)); const toggleUser = (userId: string) => { if (selectedUserIds.includes(userId)) { onChange(selectedUserIds.filter((id) => id !== userId)); } else { onChange([...selectedUserIds, userId]); } }; const removeUser = (userId: string, event: React.MouseEvent) => { event.stopPropagation(); onChange(selectedUserIds.filter((id) => id !== userId)); }; return (
{/* 选择框 - 显示 tag */}
setIsOpen(!isOpen)} style={{ display: "flex", alignItems: "center", flexWrap: "wrap", gap: "4px", padding: "6px 32px 6px 8px", minHeight: "36px", border: "1px solid #ddd", borderRadius: "4px", cursor: "pointer", backgroundColor: "#fff", }} > {selectedUsers.length === 0 ? ( 请选择用户 ) : ( selectedUsers.map((user) => ( {user.display_name} removeUser(user.user_id, e)} style={{ marginLeft: "4px", cursor: "pointer", fontWeight: "bold", fontSize: "14px", }} > × )) )} {isOpen ? "▲" : "▼"}
{/* 下拉列表 */} {isOpen && (
{users.length === 0 ? (
所有可选用户已在项目中
) : ( users.map((user) => { const isSelected = selectedUserIds.includes(user.user_id); const isExisting = existingMemberIds?.includes(user.user_id); const isDisabled = isExisting; return (
!isDisabled && toggleUser(user.user_id)} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "6px 12px", cursor: isDisabled ? "not-allowed" : "pointer", backgroundColor: isSelected ? "#e6f7ff" : isExisting ? "#f5f5f5" : "transparent", borderBottom: "1px solid #f0f0f0", opacity: isDisabled ? 0.6 : 1, }} > {user.display_name} ({user.username})
{isExisting && ( 已在项目中 )} {isSelected && }
); }) )}
)}
); }