fix: 完善工作流图片参数流转
- 图片参数使用 Object 类型并过滤上游图片引用 - 试运行支持上传、URL 和素材库图片输入 - 将模型图片能力映射到运行配置
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { EasyFlowPanelModal } from '@easyflow/common-ui';
|
||||
|
||||
@@ -18,6 +18,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
resourceType: {
|
||||
type: Number,
|
||||
default: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['choose']);
|
||||
@@ -26,6 +30,12 @@ const pageDataRef = ref();
|
||||
const dialogVisible = ref(false);
|
||||
const chooseResources = ref([]);
|
||||
const currentChoose = ref<any>({});
|
||||
const pageUrl = computed(() => {
|
||||
const baseUrl = '/api/v1/resource/page';
|
||||
return props.resourceType === undefined
|
||||
? baseUrl
|
||||
: `${baseUrl}?resourceType=${props.resourceType}`;
|
||||
});
|
||||
function openDialog() {
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
@@ -54,7 +64,7 @@ watch(
|
||||
>
|
||||
<PageData
|
||||
ref="pageDataRef"
|
||||
page-url="/api/v1/resource/page"
|
||||
:page-url="pageUrl"
|
||||
:page-size="8"
|
||||
:page-sizes="[8, 12, 16, 20]"
|
||||
>
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
let isStartNodeInputParam = $derived.by(() => {
|
||||
return node?.current?.type === START_NODE_TYPE && param.refType === 'input';
|
||||
});
|
||||
let isImageStartParam = $derived.by(() => {
|
||||
return isStartNodeInputParam && param.contentType === 'image';
|
||||
});
|
||||
let availableFormTypes = $derived.by(() => {
|
||||
if (isSystemStartParam) {
|
||||
return startFormTypes.filter((item) => item.value === 'input' || item.value === 'textarea');
|
||||
@@ -117,7 +120,15 @@
|
||||
} else if (key === 'required') {
|
||||
patch = { required: Boolean(value) };
|
||||
} else if (key === 'formType') {
|
||||
patch = { type: toStartFormFieldType(value) };
|
||||
const type = toStartFormFieldType(value);
|
||||
patch = {
|
||||
type,
|
||||
...(type === 'file'
|
||||
? { contentType: 'file' }
|
||||
: param.contentType === 'file'
|
||||
? { contentType: 'text' }
|
||||
: {})
|
||||
};
|
||||
} else if (key === 'formLabel') {
|
||||
patch = { label: value };
|
||||
} else if (key === 'formDescription') {
|
||||
@@ -127,7 +138,16 @@
|
||||
} else if (key === 'enums') {
|
||||
patch = { options: Array.isArray(value) ? value : [] };
|
||||
} else if (key === 'contentType') {
|
||||
patch = { type: value === 'file' ? 'file' : 'text' };
|
||||
patch = {
|
||||
contentType: value,
|
||||
...(value === 'file'
|
||||
? { type: 'file' }
|
||||
: value === 'image'
|
||||
? { type: 'text' }
|
||||
: param.contentType === 'file' || param.formType === 'file'
|
||||
? { type: 'text' }
|
||||
: {})
|
||||
};
|
||||
}
|
||||
if (Object.keys(patch).length === 0) {
|
||||
return;
|
||||
@@ -249,17 +269,19 @@
|
||||
数据内容:
|
||||
<Select items={contentTypes} style="width: 100%" defaultValue={["text"]}
|
||||
value={param.contentType ? [param.contentType] : []}
|
||||
disabled={param.systemReserved === true || isStartNodeInputParam}
|
||||
disabled={param.systemReserved === true}
|
||||
onSelect={updateContentType}
|
||||
/>
|
||||
</div>
|
||||
<div class="input-more-item">
|
||||
输入方式:
|
||||
<Select items={availableFormTypes} style="width: 100%" defaultValue={["input"]}
|
||||
value={displayFormTypeValue}
|
||||
onSelect={updateFormType}
|
||||
/>
|
||||
</div>
|
||||
{#if !isImageStartParam}
|
||||
<div class="input-more-item">
|
||||
输入方式:
|
||||
<Select items={availableFormTypes} style="width: 100%" defaultValue={["input"]}
|
||||
value={displayFormTypeValue}
|
||||
onSelect={updateFormType}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if param.formType === "radio" || param.formType === "checkbox" || param.formType === "select" }
|
||||
<div class="input-more-item">
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
showContentType = false,
|
||||
fixedNumberMin,
|
||||
fixedNumberMax,
|
||||
acceptedContentTypes = [],
|
||||
loopOutputAggregation = false
|
||||
}: {
|
||||
parameter: Parameter,
|
||||
@@ -35,6 +36,7 @@
|
||||
showContentType?: boolean,
|
||||
fixedNumberMin?: number,
|
||||
fixedNumberMax?: number,
|
||||
acceptedContentTypes?: string[],
|
||||
loopOutputAggregation?: boolean,
|
||||
} = $props();
|
||||
|
||||
@@ -158,6 +160,7 @@
|
||||
};
|
||||
let selectItems = useRefOptions(
|
||||
() => useChildrenOnly === true,
|
||||
() => acceptedContentTypes,
|
||||
() => param.ref || ''
|
||||
);
|
||||
let sourceDataType = $derived.by(() => {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
showContentType = false,
|
||||
fixedNumberMin,
|
||||
fixedNumberMax,
|
||||
acceptedContentTypes = [],
|
||||
loopOutputAggregation = false
|
||||
}: {
|
||||
noneParameterText?: string;
|
||||
@@ -18,6 +19,7 @@
|
||||
showContentType?: boolean,
|
||||
fixedNumberMin?: number,
|
||||
fixedNumberMax?: number,
|
||||
acceptedContentTypes?: string[],
|
||||
loopOutputAggregation?: boolean,
|
||||
} = $props();
|
||||
|
||||
@@ -45,6 +47,7 @@
|
||||
{showContentType}
|
||||
{fixedNumberMin}
|
||||
{fixedNumberMax}
|
||||
{acceptedContentTypes}
|
||||
{loopOutputAggregation}
|
||||
/>
|
||||
{:else }
|
||||
|
||||
@@ -1,6 +1,53 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { filterRefOptionsByDataType } from './refOptionFilter';
|
||||
import {
|
||||
filterRefOptionsByContentType,
|
||||
filterRefOptionsByDataType,
|
||||
} from './refOptionFilter';
|
||||
|
||||
describe('filterRefOptionsByContentType', () => {
|
||||
const options = [
|
||||
{
|
||||
label: '开始节点',
|
||||
selectable: false,
|
||||
value: 'start',
|
||||
children: [
|
||||
{
|
||||
label: '图片',
|
||||
selectable: true,
|
||||
value: 'start.image',
|
||||
contentType: 'image',
|
||||
},
|
||||
{
|
||||
label: '问题',
|
||||
selectable: true,
|
||||
value: 'start.user_input',
|
||||
contentType: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
it('图片输入仅展示图片类型引用', () => {
|
||||
const filtered = filterRefOptionsByContentType(options, ['image']);
|
||||
|
||||
expect(filtered[0]?.children).toHaveLength(1);
|
||||
expect(filtered[0]?.children[0]?.value).toBe('start.image');
|
||||
});
|
||||
|
||||
it('保留当前已选择的旧版非图片引用', () => {
|
||||
const filtered = filterRefOptionsByContentType(
|
||||
options,
|
||||
['image'],
|
||||
'start.user_input',
|
||||
);
|
||||
|
||||
expect(filtered[0]?.children.map((item: any) => item.value)).toEqual([
|
||||
'start.image',
|
||||
'start.user_input',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterRefOptionsByDataType', () => {
|
||||
const options = [
|
||||
|
||||
@@ -1,3 +1,40 @@
|
||||
/**
|
||||
* 按内容类型过滤引用选项,并保留当前已选择的旧引用。
|
||||
*/
|
||||
export function filterRefOptionsByContentType(
|
||||
options: any[],
|
||||
acceptedContentTypes: string[],
|
||||
currentRef = '',
|
||||
): any[] {
|
||||
if (!acceptedContentTypes.length) {
|
||||
return options;
|
||||
}
|
||||
const accepted = new Set(acceptedContentTypes);
|
||||
return options
|
||||
.map((option) => {
|
||||
const children = Array.isArray(option.children)
|
||||
? filterRefOptionsByContentType(
|
||||
option.children,
|
||||
acceptedContentTypes,
|
||||
currentRef,
|
||||
)
|
||||
: [];
|
||||
const selectable =
|
||||
option.selectable === true &&
|
||||
(accepted.has(String(option.contentType || '')) ||
|
||||
String(option.value || '') === currentRef);
|
||||
if (!selectable && children.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
...option,
|
||||
selectable,
|
||||
children,
|
||||
};
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function isAcceptedDataType(dataType: string, acceptedDataTypes: string[]) {
|
||||
const normalized = dataType.trim().toLowerCase();
|
||||
return acceptedDataTypes.some((acceptedDataType) => {
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
isArrayDataType,
|
||||
projectParameterDataType,
|
||||
} from '../../utils/loopScope';
|
||||
import { filterRefOptionsByContentType } from './refOptionFilter';
|
||||
|
||||
const fillRefNodeIds = (
|
||||
refNodeIds: string[],
|
||||
@@ -53,6 +54,7 @@ const getChildren = (
|
||||
return {
|
||||
label: pathLabel,
|
||||
dataType,
|
||||
contentType: param.contentType,
|
||||
value: parentId + '.' + param.name,
|
||||
selectable: true,
|
||||
nodeType: nodeType,
|
||||
@@ -102,6 +104,7 @@ const nodeToOptions = (
|
||||
children.push({
|
||||
label,
|
||||
dataType: projectParameterDataType(parameter),
|
||||
contentType: parameter.contentType,
|
||||
value: node.id + '.' + parameter.name,
|
||||
selectable: true,
|
||||
nodeType: nodeType,
|
||||
@@ -153,6 +156,7 @@ const nodeToOptions = (
|
||||
|
||||
export const useRefOptions: any = (
|
||||
useChildrenOnly: boolean | (() => boolean) = false,
|
||||
acceptedContentTypes: string[] | (() => string[]) = [],
|
||||
currentRef: string | (() => string) = '',
|
||||
) => {
|
||||
const currentNodeId = getCurrentNodeId();
|
||||
@@ -162,6 +166,10 @@ export const useRefOptions: any = (
|
||||
typeof useChildrenOnly === 'function'
|
||||
? useChildrenOnly()
|
||||
: useChildrenOnly;
|
||||
const getAcceptedContentTypes = () =>
|
||||
typeof acceptedContentTypes === 'function'
|
||||
? acceptedContentTypes()
|
||||
: acceptedContentTypes;
|
||||
const getCurrentRef = () =>
|
||||
typeof currentRef === 'function' ? currentRef() : currentRef;
|
||||
|
||||
@@ -207,7 +215,11 @@ export const useRefOptions: any = (
|
||||
}
|
||||
}
|
||||
|
||||
const items = resultOptions;
|
||||
const items = filterRefOptionsByContentType(
|
||||
resultOptions,
|
||||
getAcceptedContentTypes(),
|
||||
getCurrentRef(),
|
||||
);
|
||||
const stack = [...items];
|
||||
let selected;
|
||||
const currentValue = getCurrentRef();
|
||||
|
||||
@@ -19,6 +19,7 @@ export type SelectItem = {
|
||||
icon?: string;
|
||||
nodeType?: string;
|
||||
dataType?: string;
|
||||
contentType?: string;
|
||||
displayLabel?: string;
|
||||
pathLabel?: string;
|
||||
itemTypeLabel?: string;
|
||||
|
||||
@@ -84,6 +84,7 @@ describe('workflow node fields', () => {
|
||||
key: 'file_field',
|
||||
label: '文件字段',
|
||||
type: 'file',
|
||||
contentType: 'file',
|
||||
placeholder: '请选择文件',
|
||||
});
|
||||
expect((updated.parameters as any[]).find((item) => item.name === 'file_field'))
|
||||
@@ -110,6 +111,7 @@ describe('workflow node fields', () => {
|
||||
expect(updated.startFormSchema?.find((item: any) => item.key === 'attachments'))
|
||||
.toMatchObject({
|
||||
type: 'file',
|
||||
contentType: 'file',
|
||||
placeholder: '请选择文件',
|
||||
});
|
||||
expect((updated.parameters as any[]).find((item) => item.name === 'attachments'))
|
||||
@@ -149,6 +151,99 @@ describe('workflow node fields', () => {
|
||||
expect(nextParameter?.id).toBe(previousParameter?.id);
|
||||
});
|
||||
|
||||
it('preserves resource content type independently from input type', () => {
|
||||
for (const contentType of ['image', 'video', 'audio', 'other'] as const) {
|
||||
const key = `preview_${contentType}`;
|
||||
const initial = createInitialWorkflowData();
|
||||
const appended = appendStartFormField(
|
||||
initial.nodes[0]?.data as Record<string, any>,
|
||||
{
|
||||
key,
|
||||
label: `资源-${contentType}`,
|
||||
type: 'text',
|
||||
},
|
||||
);
|
||||
|
||||
const updated = updateStartFormField(appended, key, {
|
||||
contentType,
|
||||
});
|
||||
|
||||
expect(
|
||||
updated.startFormSchema?.find((item: any) => item.key === key),
|
||||
).toMatchObject({
|
||||
type: 'text',
|
||||
contentType,
|
||||
});
|
||||
expect(
|
||||
(updated.parameters as any[]).find((item) => item.name === key),
|
||||
).toMatchObject({
|
||||
dataType: contentType === 'image' ? 'Object' : 'String',
|
||||
contentType,
|
||||
formType: 'input',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('reconciles a legacy text schema with its image parameter', () => {
|
||||
const initial = createInitialWorkflowData();
|
||||
const startData = initial.nodes[0]?.data as Record<string, any>;
|
||||
const appended = appendStartFormField(startData, {
|
||||
key: 'legacy_image',
|
||||
label: '图片',
|
||||
type: 'text',
|
||||
});
|
||||
const imageParameterData = {
|
||||
...appended,
|
||||
parameters: (appended.parameters as any[]).map((parameter) =>
|
||||
parameter.name === 'legacy_image'
|
||||
? {
|
||||
...parameter,
|
||||
contentType: 'image',
|
||||
dataType: 'Object',
|
||||
}
|
||||
: parameter,
|
||||
),
|
||||
};
|
||||
|
||||
const normalized = normalizeStartNodeData(imageParameterData);
|
||||
|
||||
expect(
|
||||
normalized.startFormSchema?.find(
|
||||
(field: any) => field.key === 'legacy_image',
|
||||
),
|
||||
).toMatchObject({
|
||||
contentType: 'image',
|
||||
type: 'text',
|
||||
});
|
||||
expect(
|
||||
(normalized.parameters as any[]).find(
|
||||
(parameter) => parameter.name === 'legacy_image',
|
||||
),
|
||||
).toMatchObject({
|
||||
contentType: 'image',
|
||||
dataType: 'Object',
|
||||
});
|
||||
|
||||
const changedToText = updateStartFormField(normalized, 'legacy_image', {
|
||||
contentType: 'text',
|
||||
});
|
||||
expect(
|
||||
changedToText.startFormSchema?.find(
|
||||
(field: any) => field.key === 'legacy_image',
|
||||
),
|
||||
).toMatchObject({
|
||||
contentType: 'text',
|
||||
});
|
||||
expect(
|
||||
(changedToText.parameters as any[]).find(
|
||||
(parameter) => parameter.name === 'legacy_image',
|
||||
),
|
||||
).toMatchObject({
|
||||
contentType: 'text',
|
||||
dataType: 'String',
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps start fields unchanged when renaming to an existing key', () => {
|
||||
const initial = createInitialWorkflowData();
|
||||
const withTopic = appendStartFormField(
|
||||
|
||||
@@ -43,6 +43,14 @@ export type StartFormFieldType =
|
||||
| 'select'
|
||||
| 'file';
|
||||
|
||||
export type StartFormContentType =
|
||||
| 'text'
|
||||
| 'image'
|
||||
| 'video'
|
||||
| 'audio'
|
||||
| 'file'
|
||||
| 'other';
|
||||
|
||||
export type StartFormMeta = {
|
||||
title: string;
|
||||
description: string;
|
||||
@@ -54,6 +62,7 @@ export type StartFormFieldSchema = {
|
||||
key: string;
|
||||
label: string;
|
||||
type: StartFormFieldType;
|
||||
contentType: StartFormContentType;
|
||||
required: boolean;
|
||||
placeholder?: string;
|
||||
description?: string;
|
||||
@@ -70,6 +79,14 @@ const START_FORM_FIELD_TYPE_SET = new Set<StartFormFieldType>([
|
||||
'select',
|
||||
'file',
|
||||
]);
|
||||
const START_FORM_CONTENT_TYPE_SET = new Set<StartFormContentType>([
|
||||
'text',
|
||||
'image',
|
||||
'video',
|
||||
'audio',
|
||||
'file',
|
||||
'other',
|
||||
]);
|
||||
const OPTION_FIELD_TYPE_SET = new Set<StartFormFieldType>([
|
||||
'radio',
|
||||
'checkbox',
|
||||
@@ -126,6 +143,14 @@ function isOptionFieldType(value: unknown): value is StartFormFieldType {
|
||||
return OPTION_FIELD_TYPE_SET.has(asString(value).trim() as StartFormFieldType);
|
||||
}
|
||||
|
||||
function normalizeStartFormContentType(
|
||||
value: unknown,
|
||||
fallback: StartFormContentType = 'text',
|
||||
): StartFormContentType {
|
||||
const normalized = trimString(value) as StartFormContentType;
|
||||
return START_FORM_CONTENT_TYPE_SET.has(normalized) ? normalized : fallback;
|
||||
}
|
||||
|
||||
function cloneParameter(parameter: Parameter): Parameter {
|
||||
return {
|
||||
...parameter,
|
||||
@@ -511,20 +536,22 @@ function parameterTypeToStartFormFieldType(parameter?: Parameter | null): StartF
|
||||
return 'text';
|
||||
}
|
||||
|
||||
function fieldTypeToDataType(type: StartFormFieldType) {
|
||||
function fieldTypeToDataType(
|
||||
type: StartFormFieldType,
|
||||
contentType: StartFormContentType,
|
||||
) {
|
||||
if (type === 'checkbox') {
|
||||
return 'Array';
|
||||
}
|
||||
if (type === 'file') {
|
||||
return 'File';
|
||||
}
|
||||
if (contentType === 'image') {
|
||||
return 'Object';
|
||||
}
|
||||
return 'String';
|
||||
}
|
||||
|
||||
function fieldTypeToContentType(type: StartFormFieldType) {
|
||||
return type === 'file' ? 'file' : 'text';
|
||||
}
|
||||
|
||||
function fieldTypeToFormType(type: StartFormFieldType) {
|
||||
if (type === 'text') {
|
||||
return 'input';
|
||||
@@ -550,11 +577,31 @@ function normalizeStartFormField(
|
||||
: fallbackType;
|
||||
const isSystemField =
|
||||
field?.systemReserved === true || key === SYSTEM_START_PARAM_NAME;
|
||||
const parameterContentType = normalizeStartFormContentType(
|
||||
existingParameter?.contentType,
|
||||
requestedType === 'file' ? 'file' : 'text',
|
||||
);
|
||||
const fieldContentType = normalizeStartFormContentType(
|
||||
field?.contentType ?? existingParameter?.contentType,
|
||||
requestedType === 'file' ? 'file' : 'text',
|
||||
);
|
||||
// 兼容旧工作流:图片参数已更新,但同名表单 Schema 仍保留为 text。
|
||||
const requestedContentType =
|
||||
parameterContentType === 'image' && fieldContentType === 'text'
|
||||
? 'image'
|
||||
: fieldContentType;
|
||||
const contentType = isSystemField
|
||||
? 'text'
|
||||
: requestedType === 'file' || requestedContentType === 'file'
|
||||
? 'file'
|
||||
: requestedContentType;
|
||||
const type = isSystemField
|
||||
? requestedType === 'text'
|
||||
? 'text'
|
||||
: 'textarea'
|
||||
: requestedType;
|
||||
: contentType === 'file'
|
||||
? 'file'
|
||||
: requestedType;
|
||||
const options = isOptionFieldType(type)
|
||||
? ensureStringArray(field?.options || existingParameter?.enums)
|
||||
: [];
|
||||
@@ -572,6 +619,7 @@ function normalizeStartFormField(
|
||||
trimString(existingParameter?.displayName) ||
|
||||
key,
|
||||
type,
|
||||
contentType,
|
||||
required: isSystemField ? true : Boolean(field?.required ?? existingParameter?.required),
|
||||
placeholder:
|
||||
trimString(field?.placeholder) || trimString(existingParameter?.formPlaceholder),
|
||||
@@ -590,6 +638,7 @@ function parameterToStartFormField(parameter?: Parameter | null) {
|
||||
key: trimString(parameter?.name),
|
||||
label: trimString(parameter?.formLabel),
|
||||
type: parameterTypeToStartFormFieldType(parameter),
|
||||
contentType: normalizeStartFormContentType(parameter?.contentType),
|
||||
required: Boolean(parameter?.required),
|
||||
placeholder: trimString(parameter?.formPlaceholder),
|
||||
description: trimString(parameter?.formDescription),
|
||||
@@ -624,10 +673,10 @@ function startFormFieldToParameter(
|
||||
...cloneParameter(existingParameter || {}),
|
||||
id: trimString(existingParameter?.id) || trimString(field.id),
|
||||
name: field.key,
|
||||
dataType: fieldTypeToDataType(field.type),
|
||||
dataType: fieldTypeToDataType(field.type, field.contentType),
|
||||
refType: 'input',
|
||||
required: Boolean(field.required),
|
||||
contentType: fieldTypeToContentType(field.type),
|
||||
contentType: field.contentType,
|
||||
formType: fieldTypeToFormType(field.type),
|
||||
formLabel,
|
||||
formDescription: asString(field.description),
|
||||
@@ -705,6 +754,7 @@ export function normalizeStartFormSchema(
|
||||
normalizeSystemStartFormType(systemParameter?.formType) === 'input'
|
||||
? 'text'
|
||||
: 'textarea',
|
||||
contentType: 'text',
|
||||
required: true,
|
||||
placeholder: trimString(systemParameter?.formPlaceholder),
|
||||
description: trimString(systemParameter?.formDescription),
|
||||
@@ -754,13 +804,19 @@ export function createCustomStartFormField(
|
||||
field?: Partial<StartFormFieldSchema> | null,
|
||||
existingKeys: string[] = [],
|
||||
): StartFormFieldSchema {
|
||||
const type = normalizeStartFormFieldUiType(field?.type, 'text');
|
||||
const requestedType = normalizeStartFormFieldUiType(field?.type, 'text');
|
||||
const contentType = normalizeStartFormContentType(
|
||||
field?.contentType,
|
||||
requestedType === 'file' ? 'file' : 'text',
|
||||
);
|
||||
const type = contentType === 'file' ? 'file' : requestedType;
|
||||
const key = trimString(field?.key) || buildUniqueStartFormFieldKey(type, existingKeys);
|
||||
return {
|
||||
id: ensureStartFormFieldId(field?.id),
|
||||
key,
|
||||
label: trimString(field?.label) || getDefaultStartFormFieldLabel(type),
|
||||
type,
|
||||
contentType,
|
||||
required: Boolean(field?.required),
|
||||
placeholder:
|
||||
trimString(field?.placeholder) ||
|
||||
@@ -841,8 +897,24 @@ export function updateStartFormField(
|
||||
type: nextType,
|
||||
};
|
||||
});
|
||||
const nextParameters = currentParameters.map((parameter) => {
|
||||
const parameterId = trimString(parameter.id);
|
||||
const parameterName = trimString(parameter.name);
|
||||
const matchedField = nextSchema.find(
|
||||
(field) =>
|
||||
(parameterId && trimString(field.id) === parameterId) ||
|
||||
field.key === parameterName,
|
||||
);
|
||||
return matchedField
|
||||
? {
|
||||
...parameter,
|
||||
contentType: matchedField.contentType,
|
||||
}
|
||||
: parameter;
|
||||
});
|
||||
return normalizeStartNodeData({
|
||||
...currentData,
|
||||
parameters: nextParameters,
|
||||
startFormSchema: nextSchema,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user