staff_data/apps/web/src/components/models/term/term-select.tsx

193 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { TreeSelect, TreeSelectProps } from "antd";
import React, { useEffect, useState, useCallback, useRef } from "react";
import { getUniqueItems } from "@nicestack/common";
import { api } from "@nicestack/client";
import { DefaultOptionType } from "antd/es/select";
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,
// rootId = null,
disabled = false,
// domain = undefined,
}: TermSelectProps) {
const utils = api.useUtils();
const [listTreeData, setListTreeData] = useState<
Omit<DefaultOptionType, "label">[]
>([]);
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[]) => {
// console.log(keys);
try {
const allKeyIds =
keys.map((key) => key.toString()).filter(Boolean) || [];
// const expandedNodes = await Promise.all(
// keys.map(async (key) => {
// return await utils.department.getChildSimpleTree.fetch({
// deptId: key.toString(),
// domain,
// });
// })
// );
//
//上面那样一个个拉会拉爆必须直接拉deptIds
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 (
<TreeSelect
treeDataSimpleMode
disabled={disabled}
showSearch
allowClear
// ref={selectRef}
dropdownStyle={{
width: "300px", // 固定宽度
minWidth: "200px", // 最小宽度
maxWidth: "600px", // 最大宽度
}}
defaultValue={defaultValue}
value={value}
className={className}
placeholder={placeholder}
onChange={handleChange}
loadData={onLoadData}
treeData={listTreeData}
treeCheckable={multiple}
showCheckedStrategy={TreeSelect.SHOW_ALL}
treeCheckStrictly={multiple}
onClear={() => handleChange(multiple ? [] : undefined)}
onTreeExpand={handleExpand}
onDropdownVisibleChange={handleDropdownVisibleChange}
/>
);
}