feat: 优化工作流字段化参数配置

- 开始节点固定 user_input 并区分系统入口与自定义参数

- LLM 与知识库节点切换为字段值加上游引用配置

- 单节点调试改为字段预览与上游引用输入模式
This commit is contained in:
2026-04-12 20:31:02 +08:00
parent 47655a728b
commit 8cfe5400fe
24 changed files with 2785 additions and 792 deletions

View File

@@ -10,7 +10,7 @@ export const genUuid = () => {
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c: any) =>
(
c ^
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
((crypto.getRandomValues(new Uint8Array(1))[0] ?? 0) & (15 >> (c / 4)))
).toString(16),
);
};

View File

@@ -63,14 +63,20 @@ describe('paramToken utils', () => {
expect(result).toEqual([
{
dataType: undefined,
displayName: 'input',
name: 'input',
resolved: false,
},
{
dataType: undefined,
displayName: 'docs',
name: 'docs',
resolved: true,
},
{
dataType: undefined,
displayName: 'runtimeInput',
name: 'runtimeInput',
resolved: true,
},

View File

@@ -2,6 +2,11 @@ export interface ParameterLike {
name?: string;
ref?: string;
refType?: string;
resolved?: boolean;
disconnected?: boolean;
displayName?: string;
formLabel?: string;
dataType?: string;
children?: ParameterLike[];
}
@@ -27,6 +32,9 @@ export type TokenPart =
export interface ParameterCandidate {
name: string;
resolved: boolean;
disconnected?: boolean;
displayName?: string;
dataType?: string;
}
const TOKEN_PATTERN = /\{\{\s*([^{}]+?)\s*}}/g;
@@ -46,6 +54,10 @@ function isParameterResolved(parameter?: ParameterLike): boolean {
return false;
}
if (typeof parameter.resolved === 'boolean') {
return parameter.resolved;
}
const refType = (parameter.refType || '').trim();
if (refType === 'fixed' || refType === 'input') {
return true;
@@ -65,7 +77,13 @@ export function flattenParameterCandidates(
const candidates: ParameterCandidate[] = [];
const indexMap = new Map<string, number>();
const addCandidate = (name: string, resolved: boolean) => {
const addCandidate = (
name: string,
resolved: boolean,
disconnected: boolean,
displayName?: string,
dataType?: string,
) => {
const normalized = name.trim();
if (!normalized) {
return;
@@ -76,13 +94,26 @@ export function flattenParameterCandidates(
candidates.push({
name: normalized,
resolved,
disconnected,
displayName: displayName?.trim() || normalized,
dataType,
});
return;
}
// 同名参数只要有一个可解析,就视为可解析
const existingCandidate = candidates[exists]!;
if (resolved) {
candidates[exists].resolved = true;
existingCandidate.resolved = true;
existingCandidate.disconnected = false;
} else if (disconnected && !existingCandidate.resolved) {
existingCandidate.disconnected = true;
}
if (!existingCandidate.displayName && displayName?.trim()) {
existingCandidate.displayName = displayName.trim();
}
if (!existingCandidate.dataType && dataType) {
existingCandidate.dataType = dataType;
}
};
@@ -99,7 +130,18 @@ export function flattenParameterCandidates(
const currentPath = parentPath ? `${parentPath}.${rawName}` : rawName;
const currentResolved = inheritedResolved && isParameterResolved(item);
addCandidate(currentPath, currentResolved);
const currentDisconnected = item?.disconnected === true;
const displayName =
item?.displayName?.trim() ||
item?.formLabel?.trim() ||
currentPath;
addCandidate(
currentPath,
currentResolved,
currentDisconnected,
displayName,
item?.dataType,
);
if (item.children && item.children.length > 0) {
walk(item.children, currentPath, currentResolved);

View File

@@ -27,8 +27,9 @@ const getChildren = (
const dataType = nodeIsChildren
? `Array<${param.dataType || 'String'}>`
: param.dataType || 'String';
const label = param.formLabel || param.displayName || param.name;
return {
label: param.name,
label,
dataType: dataType,
value: parentId + '.' + param.name,
selectable: true,
@@ -71,8 +72,10 @@ const nodeToOptions = (
const dataType = nodeIsChildren
? `Array<${parameter.dataType || 'String'}>`
: parameter.dataType || 'String';
const label =
parameter.formLabel || parameter.displayName || parameter.name;
children.push({
label: parameter.name,
label,
dataType: dataType,
value: node.id + '.' + parameter.name,
selectable: true,