155 lines
3.8 KiB
TypeScript
155 lines
3.8 KiB
TypeScript
import {Background, BackgroundVariant, type NodeProps} from '@xyflow/react'
|
|
import {classnames} from 'amis'
|
|
import React, {useCallback, useEffect, useMemo} from 'react'
|
|
import AddNodeButton from '../component/AddNodeButton.tsx'
|
|
import {generateAllIncomerOutputVariablesFormOptions} from '../Helper.tsx'
|
|
import {useContextStore} from '../store/ContextStore.ts'
|
|
import {useDataStore} from '../store/DataStore.ts'
|
|
import {useFlowStore} from '../store/FlowStore.ts'
|
|
import {flowBackgroundColor, flowDotColor} from '../types.ts'
|
|
import AmisNode, {nodeClassName, NormalNodeHandler, outputsFormColumns} from './AmisNode.tsx'
|
|
|
|
const LoopNode = (props: NodeProps) => {
|
|
const {getNodes, getEdges} = useFlowStore()
|
|
const {getData, mergeDataById} = useDataStore()
|
|
const {getInputSchema} = useContextStore()
|
|
|
|
useEffect(() => {
|
|
mergeDataById(
|
|
props.id,
|
|
{
|
|
failFast: true,
|
|
parallel: false,
|
|
type: 'for',
|
|
count: 1,
|
|
outputs: {
|
|
output: {
|
|
type: 'array-object',
|
|
},
|
|
},
|
|
},
|
|
)
|
|
}, [props.id])
|
|
|
|
const columnsSchema = useCallback(() => [
|
|
{
|
|
type: 'switch',
|
|
name: 'failFast',
|
|
label: '快速失败',
|
|
required: true,
|
|
description: '执行过程中一旦出现错误,及时中断循环任务的执行',
|
|
},
|
|
{
|
|
disabled: true,
|
|
type: 'switch',
|
|
name: 'parallel',
|
|
label: '并行执行',
|
|
required: true,
|
|
},
|
|
{
|
|
type: 'select',
|
|
name: 'type',
|
|
label: '循环模式',
|
|
required: true,
|
|
options: [
|
|
{
|
|
label: '次数循环',
|
|
value: 'for',
|
|
},
|
|
{
|
|
label: '次数循环 (引用变量)',
|
|
value: 'for-variable',
|
|
},
|
|
{
|
|
label: '对象循环',
|
|
value: 'for-object',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
visibleOn: '${type === \'for\'}',
|
|
type: 'input-number',
|
|
name: 'count',
|
|
label: '循环次数',
|
|
required: true,
|
|
min: 1,
|
|
precision: 0,
|
|
},
|
|
{
|
|
visibleOn: '${type === \'for-variable\'}',
|
|
type: 'select',
|
|
name: 'countVariable',
|
|
label: '循环次数',
|
|
required: true,
|
|
selectMode: 'group',
|
|
options: generateAllIncomerOutputVariablesFormOptions(
|
|
props.id,
|
|
getInputSchema(),
|
|
getNodes(),
|
|
getEdges(),
|
|
getData(),
|
|
['number'],
|
|
),
|
|
},
|
|
{
|
|
visibleOn: '${type === \'for-object\'}',
|
|
type: 'select',
|
|
name: 'countObject',
|
|
label: '循环对象',
|
|
required: true,
|
|
selectMode: 'group',
|
|
options: generateAllIncomerOutputVariablesFormOptions(
|
|
props.id,
|
|
getInputSchema(),
|
|
getNodes(),
|
|
getEdges(),
|
|
getData(),
|
|
['array-text', 'array-object'],
|
|
),
|
|
},
|
|
{
|
|
type: 'divider',
|
|
},
|
|
...outputsFormColumns(false, true),
|
|
], [props.id])
|
|
|
|
const extraNodeDescription = useMemo(() => {
|
|
return (
|
|
<div className="nodrag relative w-full h-full" style={{minHeight: '211px'}}>
|
|
<Background
|
|
id={`loop-background-${props.id}`}
|
|
className="rounded-xl"
|
|
variant={BackgroundVariant.Cross}
|
|
gap={20}
|
|
size={3}
|
|
style={{
|
|
zIndex: 0,
|
|
}}
|
|
color={flowDotColor}
|
|
bgColor={flowBackgroundColor}
|
|
/>
|
|
<AddNodeButton className="mt-2 ml-2" parent={props.id} onlyIcon/>
|
|
</div>
|
|
)
|
|
}, [props.id])
|
|
|
|
return (
|
|
<AmisNode
|
|
className={classnames('w-full', 'h-full', nodeClassName('loop'))}
|
|
style={{
|
|
minWidth: '350px',
|
|
minHeight: '290px',
|
|
}}
|
|
nodeProps={props}
|
|
extraNodeDescription={extraNodeDescription}
|
|
columnSchema={columnsSchema}
|
|
handler={<NormalNodeHandler/>}
|
|
resize={{
|
|
minWidth: 350,
|
|
minHeight: 290,
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export default React.memo(LoopNode) |