工作流贴片布局节点输出可被下级引用(field=templates)
- getNodeOutputFields 重构为累积输出,开启贴片布局的节点额外提供「贴片布局」输出(field=templates、label=贴片布局),与模型返回参数等并列供下级引用 - upstreamNodes 的 hasOutput 放行开启贴片布局的节点(不依赖具体 nodeCode),保证可被前驱引用 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -873,19 +873,20 @@ const collectHttpOutputFields = (node: any, prefix = '', isRoot = true, suppress
|
||||
// 取节点在设计时的可引用输出字段(运行时这些字段会产出实际值)
|
||||
const getNodeOutputFields = (node: Node<NodeData, any, string>): UpstreamField[] => {
|
||||
const nodeCode = node.data?.nodeCode || '';
|
||||
const out: UpstreamField[] = [];
|
||||
// 节点库自带输出项(outputField):非空时优先作为该节点的可引用输出(脚本转写等节点)
|
||||
const ownOutput = nodeConfigMap.value.get(nodeCode)?.outputField || [];
|
||||
if (ownOutput.length > 0) {
|
||||
return ownOutput.map((o: any) => ({ field: o.field || o.label || '', label: o.label || o.field || '' }));
|
||||
}
|
||||
if (nodeCode === 'form') {
|
||||
out.push(...ownOutput.map((o: any) => ({ field: o.field || o.label || '', label: o.label || o.field || '' })));
|
||||
} else if (nodeCode === 'form') {
|
||||
// form 节点:自定义表单字段即输出
|
||||
return (node.data?.formConfig || []).map((f: any) => ({
|
||||
field: f.field || f.label || '',
|
||||
label: f.label || f.field || '',
|
||||
}));
|
||||
}
|
||||
if (nodeCode === 'http') {
|
||||
out.push(
|
||||
...(node.data?.formConfig || []).map((f: any) => ({
|
||||
field: f.field || f.label || '',
|
||||
label: f.label || f.field || '',
|
||||
})),
|
||||
);
|
||||
} else if (nodeCode === 'http') {
|
||||
// http 节点:输出 = 结果返回结构(response schema)的叶子字段 + 对象/数组容器整体。
|
||||
// 结果返回方式为主动拉取(responseType === 'pull')时,取主动拉取分支下配置的结果返回结构。
|
||||
const formConfig = node.data?.formConfig || [];
|
||||
@@ -895,32 +896,36 @@ const getNodeOutputFields = (node: Node<NodeData, any, string>): UpstreamField[]
|
||||
? (responseTypeEntry?.expand || []).find((e: any) => e.field === 'response')
|
||||
: formConfig.find((f: any) => f.field === 'response');
|
||||
const schema = parseSchema(responseField?.value);
|
||||
if (schema) return collectHttpOutputFields(schema);
|
||||
return [];
|
||||
}
|
||||
if (nodeCode === 'model') {
|
||||
if (schema) out.push(...collectHttpOutputFields(schema));
|
||||
} else if (nodeCode === 'model') {
|
||||
// 模型节点:模型的返回参数(responseBodyMapping)即可被下游引用的输出;
|
||||
// value 为保存时从模型 responseMapping 填充的中文描述,展示优先用中文,无则兜底 key
|
||||
const resp = node.data?.modelConfig?.modelResponseBodyMapping;
|
||||
// 数组结构:元素带 field/label
|
||||
if (Array.isArray(resp)) {
|
||||
return resp
|
||||
.filter((it: any) => it && typeof it === 'object' && (it.field || it.label || it.key))
|
||||
.map((it: any) => ({ field: it.field || it.label || it.key || '', label: it.label || it.field || it.key || '' }));
|
||||
out.push(
|
||||
...resp
|
||||
.filter((it: any) => it && typeof it === 'object' && (it.field || it.label || it.key))
|
||||
.map((it: any) => ({ field: it.field || it.label || it.key || '', label: it.label || it.field || it.key || '' })),
|
||||
);
|
||||
}
|
||||
// 对象结构:{ key: 中文描述 }
|
||||
if (resp && typeof resp === 'object') {
|
||||
return Object.keys(resp)
|
||||
.filter((k: any) => typeof k === 'string' && k.trim() !== '')
|
||||
.map((k: string) => ({ field: k, label: (typeof resp[k] === 'string' && resp[k]) || k }));
|
||||
else if (resp && typeof resp === 'object') {
|
||||
out.push(
|
||||
...Object.keys(resp)
|
||||
.filter((k: any) => typeof k === 'string' && k.trim() !== '')
|
||||
.map((k: string) => ({ field: k, label: (typeof resp[k] === 'string' && resp[k]) || k })),
|
||||
);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
if (nodeCode === START_NODE_CODE) {
|
||||
} else if (nodeCode === START_NODE_CODE) {
|
||||
// 开始节点:运行表单字段(被勾选的模型参数 + form 自定义字段)
|
||||
return (node.data?.runFormFields || []).map((f: any) => ({ field: f.field || f.path || '', label: f.label || f.field || f.path || '' }));
|
||||
out.push(...(node.data?.runFormFields || []).map((f: any) => ({ field: f.field || f.path || '', label: f.label || f.field || f.path || '' })));
|
||||
}
|
||||
return [];
|
||||
// 开启贴片布局的节点:额外提供「贴片布局」输出(field=templates),供下游节点引用(后端执行后产出 templates 字段)
|
||||
if (node.data?.patchLayout) {
|
||||
out.push({ field: 'templates', label: '贴片布局' });
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
// 当前选中节点的所有前驱链路节点(含各自可引用输出字段)
|
||||
@@ -944,10 +949,12 @@ const upstreamNodes = computed<UpstreamNodeInfo[]>(() => {
|
||||
visited.add(p);
|
||||
const n = nodes.value.find((x) => x.id === p);
|
||||
if (n) {
|
||||
// 可作为下游引用来源:模型/HTTP/表单节点,或节点库声明了自带输出项(outputField)的节点(如脚本转写)
|
||||
// 可作为下游引用来源:模型/HTTP/表单节点,或节点库声明了自带输出项(outputField)的节点(如脚本转写),
|
||||
// 或开启了贴片布局的节点(产出 templates 供下游引用)
|
||||
const hasOutput =
|
||||
OUTPUT_NODE_CODES.includes(n.data?.nodeCode || '') ||
|
||||
(nodeConfigMap.value.get(n.data?.nodeCode || '')?.outputField?.length ?? 0) > 0;
|
||||
(nodeConfigMap.value.get(n.data?.nodeCode || '')?.outputField?.length ?? 0) > 0 ||
|
||||
n.data?.patchLayout === true;
|
||||
if (hasOutput) {
|
||||
result.push({
|
||||
id: n.id,
|
||||
|
||||
Reference in New Issue
Block a user