import { TreeSelect, TreeSelectProps } from "antd"; import React, { useEffect, useState, useCallback, useRef, ReactElement, JSXElementConstructor, } from "react"; import { getUniqueItems } from "@nice/common"; import { api } from "@nice/client"; import { DefaultOptionType } from "antd/es/select"; interface TermSelectProps { defaultValue?: string | string[]; value?: string | string[]; onChange?: (value: string | string[]) => void; placeholder?: string; multiple?: boolean; taxonomyId?: string; disabled?: boolean; className?: string; domainId?: string; dropdownStyle?: React.CSSProperties; style?: React.CSSProperties; open?: boolean; showSearch?: boolean; dropdownRender?: ( menu: ReactElement> ) => ReactElement>; } export default function TermSelect({ defaultValue, value, onChange, className, placeholder = "选择分类", multiple = false, taxonomyId, open = undefined, showSearch = true, domainId, dropdownStyle, style, disabled = false, dropdownRender, }: 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 departments:", 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[]) => { 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); } }; return ( handleChange(multiple ? [] : undefined)} onTreeExpand={handleExpand} onDropdownVisibleChange={handleDropdownVisibleChange} /> ); }