这是基于vue-vben-admin 模板适用于abp vNext的前端管理项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

73 lines
1.7 KiB

import type React from "react";
import { useEffect, useState } from "react";
import { TreeSelect, type TreeSelectProps, Spin } from "antd";
function getNestedValue(obj: any, path: string) {
if (!path) return undefined;
return path.split(".").reduce((acc, part) => acc?.[part], obj);
}
export interface ApiTreeSelectProps extends Omit<TreeSelectProps, "treeData"> {
api?: (params?: any) => Promise<any>;
params?: any;
resultField?: string;
immediate?: boolean;
fieldNames?: { label: string; value: string; children: string };
}
const ApiTreeSelect: React.FC<ApiTreeSelectProps> = ({
api,
params,
resultField,
immediate = true,
fieldNames = { label: "label", value: "value", children: "children" },
...props
}) => {
const [treeData, setTreeData] = useState<any[]>([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (immediate && api) {
fetchData();
}
}, [JSON.stringify(params)]);
const fetchData = async () => {
if (!api) return;
setLoading(true);
try {
const res = await api(params);
let list = res;
if (resultField) {
list = getNestedValue(res, resultField);
}
if (Array.isArray(list)) {
setTreeData(list);
}
} catch (error) {
console.error("ApiTreeSelect fetch error:", error);
} finally {
setLoading(false);
}
};
return (
<TreeSelect
loading={loading}
treeData={treeData}
fieldNames={fieldNames}
dropdownStyle={{ maxHeight: 400, overflow: "auto" }}
notFoundContent={loading ? <Spin size="small" /> : null}
onDropdownVisibleChange={(open) => {
if (open && treeData.length === 0 && !loading) {
fetchData();
}
}}
{...props}
/>
);
};
export default ApiTreeSelect;