import { Select, Spin, Input, Tooltip } from 'antd'; import { QuestionCircleOutlined } from '@ant-design/icons'; import { useState, useEffect, useCallback } from 'react'; import { listPluginData, getPluginEntityRegistry } from '../api/pluginData'; interface EntitySelectProps { pluginId: string; entity: string; labelField: string; searchFields?: string[]; /** 跨插件引用的目标插件 manifest ID(如 "erp-crm") */ refPlugin?: string; /** 目标插件未安装时的降级显示文本 */ fallbackLabel?: string; value?: string; onChange?: (value: string, label: string) => void; cascadeFrom?: string; cascadeFilter?: string; cascadeValue?: string; placeholder?: string; } export default function EntitySelect({ pluginId, entity, labelField, searchFields: _searchFields, refPlugin, fallbackLabel, value, onChange, cascadeFrom, cascadeFilter, cascadeValue, placeholder, }: EntitySelectProps) { const [options, setOptions] = useState<{ value: string; label: string }[]>([]); const [loading, setLoading] = useState(false); const [targetUnavailable, setTargetUnavailable] = useState(false); const [resolvedPluginId, setResolvedPluginId] = useState(null); // 跨插件时:先解析 manifest_id → plugin UUID useEffect(() => { if (!refPlugin) { setResolvedPluginId(pluginId); return; } let cancelled = false; (async () => { try { const registry = await getPluginEntityRegistry(); const match = registry.find((e) => e.manifest_id === refPlugin && e.entity_name === entity); if (!cancelled) { setResolvedPluginId(match ? match.plugin_id : null); if (!match) setTargetUnavailable(true); } } catch { if (!cancelled) { setTargetUnavailable(true); setResolvedPluginId(null); } } })(); return () => { cancelled = true; }; }, [refPlugin, pluginId, entity]); const effectivePluginId = resolvedPluginId || pluginId; const fetchData = useCallback( async (keyword?: string) => { if (!resolvedPluginId && refPlugin) return; setLoading(true); try { const filter: Record | undefined = cascadeFrom && cascadeFilter && cascadeValue ? { [cascadeFilter]: cascadeValue } : undefined; const result = await listPluginData(effectivePluginId, entity, 1, 20, { search: keyword, filter, }); const items = (result.data || []).map((item) => ({ value: item.id, label: String(item.data?.[labelField] ?? item.id), })); setOptions(items); setTargetUnavailable(false); } catch { if (refPlugin) { setTargetUnavailable(true); setOptions([]); } } finally { setLoading(false); } }, [effectivePluginId, entity, labelField, cascadeFrom, cascadeFilter, cascadeValue, refPlugin, resolvedPluginId], ); useEffect(() => { if (resolvedPluginId || !refPlugin) { fetchData(); } }, [fetchData, resolvedPluginId, refPlugin]); // 目标插件未安装 → 降级显示 if (targetUnavailable) { return ( } /> ); } return (