import { TreeSelect, TreeSelectProps } from "antd"; import React, { useEffect, useState, useCallback, useRef } from "react"; import { getUniqueItems } from "@nice/common"; import { api } from "@nice/client"; import { DefaultOptionType } from "antd/es/select"; import "./TermSelect.css"; interface TermSelectProps { defaultValue?: string | string[]; value?: string | string[]; onChange?: (value: string | string[]) => void; placeholder?: string; multiple?: boolean; // rootId?: string; // domain?: boolean; taxonomyId?: string; disabled?: boolean; className?: string; domainId?: string; } export default function TermSelect({ defaultValue, value, onChange, className, placeholder = "选择术语", multiple = false, taxonomyId, domainId, disabled = false, }: TermSelectProps) { const utils = api.useUtils(); const [listTreeData, setListTreeData] = useState< Omit[] >([]); const fetchParentTerms = useCallback( async (termIds: string | string[], taxonomyId?: string) => { const idsArray = Array.isArray(termIds) ? termIds : [termIds].filter(Boolean); try { return await utils.term.getParentSimpleTree.fetch({ termIds: idsArray, taxonomyId, domainId, }); } catch (error) { console.error( "Error fetching parent departments for deptIds", idsArray, ":", error ); throw error; } }, [utils] ); const fetchTerms = useCallback(async () => { try { const rootDepts = await utils.term.getChildSimpleTree.fetch({ taxonomyId, domainId, }); let combinedDepts = [...rootDepts]; if (defaultValue) { const defaultDepts = await fetchParentTerms( defaultValue, taxonomyId ); combinedDepts = getUniqueItems( [...listTreeData, ...combinedDepts, ...defaultDepts] as any, "id" ); } if (value) { const valueDepts = await fetchParentTerms(value, taxonomyId); combinedDepts = getUniqueItems( [...listTreeData, ...combinedDepts, ...valueDepts] as any, "id" ); } setListTreeData(combinedDepts); } catch (error) { console.error("Error fetching terms:", error); } }, [defaultValue, value, taxonomyId, utils, fetchParentTerms]); useEffect(() => { fetchTerms(); }, [defaultValue, value, taxonomyId, fetchTerms]); const handleChange = (newValue: any) => { if (onChange) { const processedValue = multiple && Array.isArray(newValue) ? newValue.map((item) => item.value) : newValue; onChange(processedValue); } }; const onLoadData: TreeSelectProps["loadData"] = async ({ id }) => { try { const result = await utils.term.getChildSimpleTree.fetch({ termIds: [id], taxonomyId, domainId, }); const newItems = getUniqueItems([...listTreeData, ...result], "id"); setListTreeData(newItems); } catch (error) { console.error( "Error loading data for node with id", id, ":", error ); } }; const handleExpand = async (keys: React.Key[]) => { // console.log(keys); try { const allKeyIds = keys.map((key) => key.toString()).filter(Boolean) || []; const expandedNodes = await utils.term.getChildSimpleTree.fetch({ termIds: allKeyIds, taxonomyId, domainId, }); const flattenedNodes = expandedNodes.flat(); const newItems = getUniqueItems( [...listTreeData, ...flattenedNodes], "id" ); setListTreeData(newItems); } catch (error) { console.error("Error expanding nodes with keys", keys, ":", error); } }; const handleDropdownVisibleChange = async (open: boolean) => { if (open) { // This will attempt to expand all nodes and fetch their children when the dropdown opens const allKeys = listTreeData.map((item) => item.id); await handleExpand(allKeys); } }; // 检测旧版本浏览器 const isLegacyBrowser = () => { const chromeMatch = navigator.userAgent.match(/Chrome\/(\d+)/); if (chromeMatch) { const version = parseInt(chromeMatch[1], 10); return version <= 87; } return false; }; // 为降级版本准备的状态 const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); // 处理点击外部关闭下拉框 useEffect(() => { if (isLegacyBrowser()) { const handleClickOutside = (event: MouseEvent) => { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setIsOpen(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); } }, []); if (isLegacyBrowser()) { return (
setIsOpen(!isOpen)}> {multiple ? (
{Array.isArray(value) && value.length > 0 ? ( value.map((v) => { const item = listTreeData.find( (i) => i.id === v ); return ( {item?.title} { e.stopPropagation(); const newValue = value.filter( (val: string) => val !== v ); handleChange(newValue); }}> × ); }) ) : ( {placeholder} )}
) : (
{value ? ( listTreeData.find((i) => i.id === value)?.title ) : ( {placeholder} )}
)}
{isOpen && (
{listTreeData.map((item) => (
{ if (multiple) { const newValue = Array.isArray(value) ? value.includes(item.id) ? value.filter( (v) => v !== item.id ) : [...value, item.id] : [item.id]; handleChange(newValue); } else { handleChange(item.id); setIsOpen(false); } }}> {multiple && ( {Array.isArray(value) && value.includes(item.id) && "✓"} )} {item.title}
))}
)}
); } return ( handleChange(multiple ? [] : undefined)} onTreeExpand={handleExpand} onDropdownVisibleChange={handleDropdownVisibleChange} // 添加以下属性来优化显示 /> ); }