|
|
|
|
@ -121,6 +121,10 @@ const renderSpecialNodeHandles = (isStartNode: boolean, isEndNode: boolean, data
|
|
|
|
|
|
|
|
|
|
// 渲染普通节点的句柄
|
|
|
|
|
const renderRegularNodeHandles = (dataIns: any[], dataOuts: any[], apiIns: any[], apiOuts: any[]) => {
|
|
|
|
|
// 计算 API 占位数量:如果没有 API 句柄,默认占位 1 个
|
|
|
|
|
const apiInsPlaceholder = Math.max(apiIns.length, 1);
|
|
|
|
|
const apiOutsPlaceholder = Math.max(apiOuts.length, 1);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{apiOuts.map((_, index) => (
|
|
|
|
|
@ -157,7 +161,7 @@ const renderRegularNodeHandles = (dataIns: any[], dataOuts: any[], apiIns: any[]
|
|
|
|
|
id={dataIns[index].name || dataIns[index].id || `input-${index}`}
|
|
|
|
|
style={{
|
|
|
|
|
...handleStyles.data,
|
|
|
|
|
top: `${65 + (apiIns.length + index) * 22}px`
|
|
|
|
|
top: `${65 + (apiInsPlaceholder + index) * 22}px`
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
@ -171,7 +175,7 @@ const renderRegularNodeHandles = (dataIns: any[], dataOuts: any[], apiIns: any[]
|
|
|
|
|
id={dataOuts[index].name || dataOuts[index].id || `output-${index}`}
|
|
|
|
|
style={{
|
|
|
|
|
...handleStyles.data,
|
|
|
|
|
top: `${65 + (apiIns.length + index) * 22}px`
|
|
|
|
|
top: `${65 + (apiOutsPlaceholder + index) * 22}px`
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
@ -235,32 +239,49 @@ const NodeContentLocal = ({ data }: { data: NodeContentData }) => {
|
|
|
|
|
const isEndNode = data.type === 'end';
|
|
|
|
|
const isSpecialNode = isStartNode || isEndNode;
|
|
|
|
|
|
|
|
|
|
// 判断是否需要显示 API 区域(即使为空也显示占位)
|
|
|
|
|
const hasApiSection = apiIns.length > 0 || apiOuts.length > 0 || dataIns.length > 0 || dataOuts.length > 0;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{/*content栏-api部分*/}
|
|
|
|
|
<div className={styles['node-api-box']}>
|
|
|
|
|
<div className={styles['node-content-api']}>
|
|
|
|
|
{apiIns.length > 0 && (
|
|
|
|
|
<div className={styles['node-inputs']}>
|
|
|
|
|
{apiIns.map((input, index) => (
|
|
|
|
|
<div key={input.id || `input-${index}`} className={styles['node-input-label']}>
|
|
|
|
|
{formatTitle(input.desc || input.id || input.name)}
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{/*content栏-api部分 - 始终显示以保持布局一致*/}
|
|
|
|
|
{hasApiSection && (
|
|
|
|
|
<div className={styles['node-api-box']}>
|
|
|
|
|
<div className={styles['node-content-api']}>
|
|
|
|
|
{(apiIns.length > 0 || dataIns.length > 0) && (
|
|
|
|
|
<div className={styles['node-inputs']}>
|
|
|
|
|
{apiIns.map((input, index) => (
|
|
|
|
|
<div key={input.id || `input-${index}`} className={styles['node-input-label']}>
|
|
|
|
|
{formatTitle(input.desc || input.id || input.name)}
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
{/* 如果没有 API 输入但有数据输入,添加占位 */}
|
|
|
|
|
{apiIns.length === 0 && dataIns.length > 0 && (
|
|
|
|
|
<div className={styles['node-input-label']} style={{ visibility: 'hidden' }}>
|
|
|
|
|
占位
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{apiOuts.length > 0 && (
|
|
|
|
|
<div className={styles['node-outputs']}>
|
|
|
|
|
{apiOuts.map((output, index) => (
|
|
|
|
|
<div key={output.id || `output-${index}`} className={styles['node-output-label']}>
|
|
|
|
|
{output.desc}
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{(apiOuts.length > 0 || dataOuts.length > 0) && (
|
|
|
|
|
<div className={styles['node-outputs']}>
|
|
|
|
|
{apiOuts.map((output, index) => (
|
|
|
|
|
<div key={output.id || `output-${index}`} className={styles['node-output-label']}>
|
|
|
|
|
{output.desc}
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
{/* 如果没有 API 输出但有数据输出,添加占位 */}
|
|
|
|
|
{apiOuts.length === 0 && dataOuts.length > 0 && (
|
|
|
|
|
<div className={styles['node-output-label']} style={{ visibility: 'hidden' }}>
|
|
|
|
|
占位
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{(dataIns.length > 0 || dataOuts.length > 0) && (
|
|
|
|
|
<>
|
|
|
|
|
{/*分割*/}
|
|
|
|
|
|