diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index 595c7b5acac..180eaee7316 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -319,6 +319,10 @@ Escape 关闭;这些默认行为可以通过同名 Props 覆盖。Element Plus 调用 `resetData()`,确保所有关闭路径都在关闭动画结束后完成清理。`resetData()` 应统一重置表单、 提交状态、临时选项和表单校验,不把清理逻辑散落在 `open()`、取消按钮或提交成功回调中。 +只有登录表单支持回车提交。其他业务表单使用 `@submit.prevent` 阻止默认提交,不绑定提交函数, +也不通过 Enter 键触发保存或添加;提交操作由按钮点击触发。组件的 `emit('submit', data)` 是向 +父组件传递数据的自定义事件,不代表支持回车提交。 + ### MkComplexSearch 用于在多个字段之间切换搜索条件。`fields` 中的基础字段使用 `@/api/types` 中的 diff --git a/ui/src/styles/element-plus.scss b/ui/src/styles/element-plus.scss index fcef12ea12c..136eeda3cbf 100644 --- a/ui/src/styles/element-plus.scss +++ b/ui/src/styles/element-plus.scss @@ -983,6 +983,10 @@ padding: calc(var(--spacing) * 2) calc(var(--spacing) * 3); } } + // 需要仅增加table最外层border的样式 + &.border { + border-right: 1px solid var(--el-table-border-color); + } [class*='el-table__row--level'] .el-table__expand-icon { align-items: center; diff --git a/ui/src/workflow-canvas/WORKFLOW_README.md b/ui/src/workflow-canvas/WORKFLOW_README.md index abfbf06bd99..d711bf94631 100644 --- a/ui/src/workflow-canvas/WORKFLOW_README.md +++ b/ui/src/workflow-canvas/WORKFLOW_README.md @@ -100,7 +100,7 @@ Vue Teleport 节点继承页面上下文;画布核心不负责模型参数接 智能体页面将详情加载或保存成功返回的配置通过 `defaultModelSettings` Props 传给画布。 `WorkflowNodeModel.getDefaultModelConfig(type)` 通过画布的配置读取函数获取对应模型,不使用 默认配置的 `provide/inject`,也不写入节点持久化数据。AI 对话、意图识别、问题优化、语音、 -图片和视频相关节点在默认来源下读取保存后的对应模型 ID 和参数,使用禁用且隐藏参数按钮的 +图片、视频及参数提取相关节点在默认来源下读取保存后的对应模型 ID 和参数,使用禁用且隐藏参数按钮的 `ModelSelect` 展示;自定义来源继续编辑节点自身配置,引用来源使用 `NodeCascader`。默认配置 只用于解析当前使用的模型,不覆盖节点保存的自定义配置;各节点在本地维护模型设置,并按当前 来源检查实际模型或引用变量。 @@ -113,6 +113,21 @@ Vue Teleport 节点继承页面上下文;画布核心不负责模型参数接 中间 computed。独立弹窗、资源选择等具有完整交互边界的能力放在节点目录的 `component/` 下; 节点入口负责统一写回节点属性和执行节点级校验。 +变量拆分节点的 `VariableFieldTable` 通过 `v-model` 接收 `VariableField[]`,只负责列表增删改、 +重名检查和编辑弹窗,不接收节点模型或读写 `node_data`。节点入口在列表写回时同步输出字段并 +清理下游失效引用;字段类型由该组件目录的 `types.ts` 统一定义。 +`VariableFieldDialog` 与 `GroupFieldDialog` 使用 `submit(data, index?)` 提交,表格通过重名检查并 +写回列表后调用 `close()`;关闭动画结束时通过 `closed` 重置表单,添加与编辑共用同一提交流程。 + +参数提取节点的默认模型读取 `LLM` 配置,新节点默认选择“默认模型”,旧节点缺少来源字段时 +保留“自定义”语义。默认模型仅用于展示与校验,不覆盖节点保存的自定义模型和参数。 + +参数提取节点遵循相同边界:`component/parameters-field` 内的 `ParametersFieldTable` 通过 +`v-model` 编辑 `ParameterField[]`,弹窗只通过 `submit(data, index?)` 提交,节点入口同步输出 +字段和下游引用。模型引用与输入变量的有效性校验接入节点表单规则,调用 `NodeCascader.validate()` +保留失效引用检查;节点级 `validate()` 统一调用表单校验。所有非登录表单仅使用 `@submit.prevent`, +保存或添加由按钮触发。 + AI 对话节点的提示词、历史记录、视觉理解和输出思考表单直接在节点入口维护,统一使用全局 `MdEditorMagnify` 和节点表单样式;AI 提示词生成与思考过程配置仍使用独立弹窗。 问题优化、图片理解和视频理解节点的系统提示词与用户提示词,以及图片、文生视频和图生视频 diff --git a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldDialog.vue b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldDialog.vue deleted file mode 100644 index 63dfa36f4bb..00000000000 --- a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldDialog.vue +++ /dev/null @@ -1,100 +0,0 @@ - - diff --git a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldTable.vue b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldTable.vue deleted file mode 100644 index 28717b969ae..00000000000 --- a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/ParametersFieldTable.vue +++ /dev/null @@ -1,117 +0,0 @@ - - diff --git a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/ParametersFieldDialog.vue b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/ParametersFieldDialog.vue new file mode 100644 index 00000000000..84bc44929dc --- /dev/null +++ b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/ParametersFieldDialog.vue @@ -0,0 +1,84 @@ + + + diff --git a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/ParametersFieldTable.vue b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/ParametersFieldTable.vue new file mode 100644 index 00000000000..d2399b334ff --- /dev/null +++ b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/ParametersFieldTable.vue @@ -0,0 +1,77 @@ + + + diff --git a/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/types.ts b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/types.ts new file mode 100644 index 00000000000..56f0e3f2b73 --- /dev/null +++ b/ui/src/workflow-canvas/nodes/parameter-extraction-node/component/parameters-field/types.ts @@ -0,0 +1,6 @@ +export interface ParameterField { + field: string + label: string + parameter_type: string + desc: string +} diff --git a/ui/src/workflow-canvas/nodes/parameter-extraction-node/index.vue b/ui/src/workflow-canvas/nodes/parameter-extraction-node/index.vue index cbbab521e4b..eaa3608ad06 100644 --- a/ui/src/workflow-canvas/nodes/parameter-extraction-node/index.vue +++ b/ui/src/workflow-canvas/nodes/parameter-extraction-node/index.vue @@ -1,5 +1,5 @@ diff --git a/ui/src/workflow-canvas/nodes/variable-splitting-node/component/VariableFieldTable.vue b/ui/src/workflow-canvas/nodes/variable-splitting-node/component/VariableFieldTable.vue deleted file mode 100644 index 5d1e7dc0d90..00000000000 --- a/ui/src/workflow-canvas/nodes/variable-splitting-node/component/VariableFieldTable.vue +++ /dev/null @@ -1,112 +0,0 @@ - - diff --git a/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/VariableFieldDialog.vue b/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/VariableFieldDialog.vue new file mode 100644 index 00000000000..afbff3c3293 --- /dev/null +++ b/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/VariableFieldDialog.vue @@ -0,0 +1,95 @@ + + diff --git a/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/VariableFieldTable.vue b/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/VariableFieldTable.vue new file mode 100644 index 00000000000..8117b2195ce --- /dev/null +++ b/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/VariableFieldTable.vue @@ -0,0 +1,73 @@ + + + diff --git a/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/types.ts b/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/types.ts new file mode 100644 index 00000000000..af8d90620b0 --- /dev/null +++ b/ui/src/workflow-canvas/nodes/variable-splitting-node/component/variable-field/types.ts @@ -0,0 +1,5 @@ +export interface VariableField { + field: string + label: string + expression: string +} diff --git a/ui/src/workflow-canvas/nodes/variable-splitting-node/index.vue b/ui/src/workflow-canvas/nodes/variable-splitting-node/index.vue index c15841ee62c..78afacf21db 100644 --- a/ui/src/workflow-canvas/nodes/variable-splitting-node/index.vue +++ b/ui/src/workflow-canvas/nodes/variable-splitting-node/index.vue @@ -6,36 +6,50 @@ import type { FormInstance } from 'element-plus' import NodeCascader from '@/workflow-canvas/core/NodeCascader.vue' import NodeContainer from '@/workflow-canvas/core/node-container/index.vue' import type { WorkflowNodeModel } from '@/workflow-canvas/core/workflow-node' -import VariableFieldTable from './component/VariableFieldTable.vue' +import VariableFieldTable from './component/variable-field/VariableFieldTable.vue' +import type { VariableField } from './component/variable-field/types' defineOptions({ name: 'WorkflowVariableSplittingNode' }) const getModel = inject('getModel') as () => BaseNodeModel const model = getModel() as WorkflowNodeModel -if (!model.properties.node_data) { - model.properties.node_data = { input_variable: [], variable_list: [] } +interface VariableSplittingNodeForm { + input_variable: string[] + variable_list: VariableField[] } -const formData = computed<{ input_variable: string[]; variable_list: Array> }>({ - get: () => model.properties.node_data as { input_variable: string[]; variable_list: Array> }, - set: (value) => { - model.properties.node_data = value - }, + +const defaultForm: VariableSplittingNodeForm = { + input_variable: [], + variable_list: [], +} +const savedForm = model.properties.node_data as Partial | undefined +model.properties.node_data = { + ...defaultForm, + ...savedForm, + input_variable: Array.isArray(savedForm?.input_variable) ? savedForm.input_variable : defaultForm.input_variable, + variable_list: Array.isArray(savedForm?.variable_list) ? savedForm.variable_list : defaultForm.variable_list, +} + +const formData = computed({ + get: () => model.properties.node_data as VariableSplittingNodeForm, + set: (value) => (model.properties.node_data = value), }) const variableSplittingFormRef = useTemplateRef('variableSplittingFormRef') -const nodeCascaderRef = useTemplateRef>('nodeCascaderRef') -const variableFieldTableRef = useTemplateRef>('variableFieldTableRef') -const validate = () => { - const vList: Array> = [] - const formResult = variableSplittingFormRef.value?.validate() - if (formResult) vList.push(formResult) - const cascaderResult = nodeCascaderRef.value?.validate() - if (cascaderResult) vList.push(cascaderResult) - if (!formData.value.variable_list.length) { - vList.push(Promise.reject('请添加拆分变量')) - } - return Promise.all(vList).catch((error) => Promise.reject({ node: model, errMessage: error })) +// 表格只编辑变量列表;节点输出和下游引用由节点入口同步。 +const variableList = computed({ + get: () => formData.value.variable_list, + set: (fields: VariableField[]) => { + formData.value.variable_list = fields + model.properties.config ??= {} + model.properties.config.fields = [{ label: '结果', value: 'result' }, ...fields.map((field) => ({ label: field.label, value: field.field }))] + model.clearNextNodeField(false) + }, +}) + +async function validate() { + return variableSplittingFormRef.value?.validate().catch((error) => Promise.reject({ node: model, errMessage: error })) } onMounted(() => { @@ -45,27 +59,16 @@ onMounted(() => {