refractor(web): 修复入参解析

This commit is contained in:
v-zhangjc9
2025-07-15 16:27:00 +08:00
parent df8270676a
commit a7b245a670
3 changed files with 55 additions and 72 deletions

View File

@@ -1,10 +1,10 @@
import {type Edge, getIncomers, type Node} from '@xyflow/react' import {type Edge, getIncomers, type Node} from '@xyflow/react'
import type {Option} from 'amis/lib/Schema' import type {Option} from 'amis/lib/Schema'
import {find, has, isEmpty, isEqual, max, min, unique} from 'licia' import {find, has, isEqual, max, min, unique} from 'licia'
import {type DependencyList, type MouseEvent as ReactMouseEvent, useCallback, useRef} from 'react' import {type DependencyList, type MouseEvent as ReactMouseEvent, useCallback, useRef} from 'react'
import Queue from 'yocto-queue' import Queue from 'yocto-queue'
import {useFlowStore} from './store/FlowStore.ts' import {useFlowStore} from './store/FlowStore.ts'
import type {InputFormOptions, InputFormOptionsGroup} from './types.ts' import type {OutputVariable} from './types.ts'
export const getAllIncomerNodeById: (id: string, nodes: Node[], edges: Edge[]) => string[] = (id, nodes, edges) => { export const getAllIncomerNodeById: (id: string, nodes: Node[], edges: Edge[]) => string[] = (id, nodes, edges) => {
let queue = new Queue<Node>() let queue = new Queue<Node>()
@@ -20,36 +20,16 @@ export const getAllIncomerNodeById: (id: string, nodes: Node[], edges: Edge[]) =
return unique(result, (a, b) => isEqual(a, b)) return unique(result, (a, b) => isEqual(a, b))
} }
export const getAllIncomerNodeOutputVariables: (id: string, nodes: Node[], edges: Edge[], data: any) => { export const getAllIncomerNodeOutputVariables: (id: string, inputSchema: Record<string, Record<string, any>>, nodes: Node[], edges: Edge[], data: any) => OutputVariable[] = (id, inputSchema, nodes, edges, data) => {
id: string, let inputSchemaVariables: OutputVariable[] = Object.keys(inputSchema).map(key => ({
variable: string group: '流程入参',
}[] = (id, nodes, edges, data) => { name: `${key}${inputSchema[key]?.label ? ` (${inputSchema[key].label})` : ''}`,
let incomerIds = getAllIncomerNodeById(id, nodes, edges) variable: key,
let incomerVariables: { id: string, variable: string }[] = []
for (const incomerId of incomerIds) {
let nodeData = data[incomerId] ?? {}
if (has(nodeData, 'outputs')) {
let outputs = nodeData?.outputs ?? []
for (const output of Object.keys(outputs)) {
incomerVariables.push({
id: incomerId,
variable: output,
})
}
}
}
return incomerVariables
}
export const generateAllIncomerOutputVariablesFormOptions: (id: string, inputSchema: Record<string, Record<string, any>>, nodes: Node[], edges: Edge[], data: any) => Option[] = (id, inputSchema, nodes, edges, data) => {
let inputSchemaVariables: InputFormOptions[] = Object.keys(inputSchema).map(key => ({
label: `${key} (${inputSchema[key]?.label ?? ''})`,
value: key,
})) }))
let currentNode = find(nodes, n => isEqual(id, n.id)) let currentNode = find(nodes, n => isEqual(id, n.id))
if (!currentNode) { if (!currentNode) {
return [] return inputSchemaVariables
} }
let incomerIds = getAllIncomerNodeById(id, nodes, edges) let incomerIds = getAllIncomerNodeById(id, nodes, edges)
@@ -60,7 +40,7 @@ export const generateAllIncomerOutputVariablesFormOptions: (id: string, inputSch
] ]
} }
let incomerVariables: InputFormOptionsGroup[] = [] let incomerVariables: OutputVariable[] = []
for (const incomerId of incomerIds) { for (const incomerId of incomerIds) {
let nodeData = data[incomerId] ?? {} let nodeData = data[incomerId] ?? {}
let group = incomerId let group = incomerId
@@ -68,48 +48,51 @@ export const generateAllIncomerOutputVariablesFormOptions: (id: string, inputSch
group = `${nodeData.node.name} ${incomerId}` group = `${nodeData.node.name} ${incomerId}`
} }
if (has(nodeData, 'outputs')) { if (has(nodeData, 'outputs')) {
let outputs = nodeData?.outputs ?? [] let outputs = nodeData?.outputs ?? {}
incomerVariables.push({ for (const key of Object.keys(outputs)) {
group: group, incomerVariables.push({
variables: Object.keys(outputs).map(key => ({ group: group,
value: `${incomerId}.${key}`, name: key,
label: key, variable: `${incomerId}.${key}`,
})), })
}) }
} }
} }
let inputVariables = [ return [
...(isEmpty(inputSchemaVariables) ? [] : [ ...inputSchemaVariables,
{
group: '流程入参',
variables: inputSchemaVariables,
},
]),
...(currentNode.parentId ? [ ...(currentNode.parentId ? [
{ {
group: '循环入参', group: '循环入参',
variables: [ name: 'loopIndex (当前迭代索引)',
{ variable: 'loopIndex',
label: 'loopIndex (当前迭代索引)', },
value: 'loopIndex', {
}, group: '循环入参',
{ name: 'loopItem (当前迭代对象)',
label: 'loopItem (当前迭代对象)', variable: 'loopItem',
value: 'loopItem', },
}
]
}
] : []), ] : []),
...incomerVariables, ...incomerVariables,
] ]
}
return [ export const generateAllIncomerOutputVariablesFormOptions: (id: string, inputSchema: Record<string, Record<string, any>>, nodes: Node[], edges: Edge[], data: any) => Option[] = (id, inputSchema, nodes, edges, data) => {
...inputVariables.map(item => ({ let optionMap: Record<string, Option[]> = {}
label: item.group, for (const item of getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data)) {
children: item.variables, if (!optionMap[item.group]) {
})), optionMap[item.group] = []
] }
optionMap[item.group].push({
label: item.name,
value: item.variable,
})
}
return Object.keys(optionMap)
.map(key => ({
label: key,
children: optionMap[key],
}))
} }
// 处理循环节点的边界问题 // 处理循环节点的边界问题

View File

@@ -15,10 +15,7 @@ const inputSingleVariableChecker: (field: string) => NodeChecker = field => {
if (has(nodeData, field)) { if (has(nodeData, field)) {
let expression = nodeData?.[field] ?? '' let expression = nodeData?.[field] ?? ''
if (!isEmpty(expression)) { if (!isEmpty(expression)) {
let outputVariables = new Set([ let outputVariables = new Set(getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data).map(i => i.variable))
...getAllIncomerNodeOutputVariables(id, nodes, edges, data).map(i => `${i.id}.${i.variable}`),
...Object.keys(inputSchema),
])
if (!outputVariables.has(expression)) { if (!outputVariables.has(expression)) {
return { return {
error: true, error: true,
@@ -36,10 +33,7 @@ const inputMultiVariableChecker: NodeChecker = (id, inputSchema, nodes, edges, d
if (has(nodeData, 'inputs')) { if (has(nodeData, 'inputs')) {
let inputs = nodeData?.inputs ?? {} let inputs = nodeData?.inputs ?? {}
if (!isEmpty(inputs)) { if (!isEmpty(inputs)) {
let outputVariables = new Set([ let outputVariables = new Set(getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data).map(i => i.variable))
...getAllIncomerNodeOutputVariables(id, nodes, edges, data).map(i => `${i.id}.${i.variable}`),
...Object.keys(inputSchema),
])
for (const key of Object.keys(inputs)) { for (const key of Object.keys(inputs)) {
let variable = inputs[key]?.variable ?? '' let variable = inputs[key]?.variable ?? ''
if (!outputVariables.has(variable)) { if (!outputVariables.has(variable)) {

View File

@@ -1,8 +1,8 @@
import type {Edge, Node} from '@xyflow/react' import type {Edge, Node} from '@xyflow/react'
import type {JSX} from 'react' import type {JSX} from 'react'
export const flowBackgroundColor = "#fafafa" export const flowBackgroundColor = '#fafafa'
export const flowDotColor = "#dedede" export const flowDotColor = '#dedede'
export type InputFormOptions = { export type InputFormOptions = {
label: string label: string
@@ -37,4 +37,10 @@ export type NodeDefine = {
description: string, description: string,
component: any, component: any,
checkers: NodeChecker[], checkers: NodeChecker[],
} }
export type OutputVariable = {
group: string,
name: string | undefined,
variable: string,
}