fix: 防止开始节点重名参数被删除

- 校验开始节点参数名并保留冲突输入

- 在字段归一化前拦截重名并补充回归测试
This commit is contained in:
2026-07-30 16:23:34 +08:00
parent 5dbb46ef8f
commit 9959f95b94
3 changed files with 128 additions and 3 deletions

View File

@@ -7,6 +7,7 @@
import {useTinyflowStore} from '#store/stores.svelte';
import {getCurrentNodeId} from '#components/utils/NodeUtils';
import {
isStartFormFieldKeyAvailable,
renameStartFieldReferencesInNodes,
removeStartFormField,
START_NODE_TYPE,
@@ -47,12 +48,15 @@
}
return param.formType ? [param.formType] : [];
});
let parameterNameDraft = $state<string | null>(null);
let displayParamName = $derived.by(() => {
if (isSystemStartParam) {
return '用户问题';
}
return param.name;
return parameterNameDraft ?? param.name;
});
let parameterNameError = $state('');
let parameterNameErrorId = $derived(`parameter-name-error-${param.id || index}`);
const { updateNodeData } = useSvelteFlow();
@@ -146,7 +150,27 @@
};
const updateName = (event: Event) => {
const newValue = (event.target as any).value;
const input = event.target as HTMLInputElement;
const newValue = input.value;
if (isStartNodeInputParam) {
const normalizedValue = trimString(newValue);
if (!normalizedValue) {
parameterNameError = '参数名不能为空';
parameterNameDraft = newValue;
return;
}
if (!isStartFormFieldKeyAvailable(
node?.current?.data as Record<string, any>,
param.name || '',
normalizedValue
)) {
parameterNameError = '参数名已存在';
parameterNameDraft = newValue;
return;
}
}
parameterNameDraft = null;
parameterNameError = '';
updateParameter('name', newValue);
};
@@ -191,10 +215,17 @@
</script>
<div class="input-item">
<div class="input-item input-item-name">
<Input style="width: 100%;" value={displayParamName} placeholder="请输入参数名称"
disabled={param.nameDisabled === true}
aria-invalid={parameterNameError ? 'true' : undefined}
aria-describedby={parameterNameError ? parameterNameErrorId : undefined}
oninput={updateName} />
{#if parameterNameError}
<div id={parameterNameErrorId} class="input-error" role="alert">
{parameterNameError}
</div>
{/if}
</div>
<div class="input-item">
<Checkbox checked={param.required} disabled={param.requiredDisabled === true} onchange={updateRequired} />
@@ -276,6 +307,22 @@
align-items: center;
}
.input-item-name {
flex-direction: column;
align-items: stretch;
gap: 3px;
}
.input-error {
font-size: 12px;
line-height: 1.4;
color: var(--tf-danger-soft-text);
}
:global(.tf-input[aria-invalid='true']) {
border-color: var(--tf-danger-soft-border);
}
.input-more-setting {
display: flex;
flex-direction: column;