diff --git a/ui/src/components/ai-chat/component/inline-params/constants.ts b/ui/src/components/ai-chat/component/inline-params/constants.ts new file mode 100644 index 00000000000..d4fe24ce528 --- /dev/null +++ b/ui/src/components/ai-chat/component/inline-params/constants.ts @@ -0,0 +1,20 @@ +/** + * 用户输入参数平铺白名单 + * + * 只有这些 input_type 的字段可以被设置为外置参数(在聊天框上平铺显示)。 + * 改动这里会影响 3 个消费方,注意同步语义: + * - UserInputTitleDialog.vue —— 齿轮弹窗中 select option 的 disabled 判断 + * - inline-params/index.vue —— 渲染时兜底过滤,防止白名单被绕过 + * - base-node/UserInputFieldTable.vue —— 字段类型变更/删除时清理脏数据 + */ +export const ALLOWED_EXPOSED_TYPES = [ + 'Model', + 'Knowledge', + 'SwitchInput', + 'DatePicker', + 'TreeSelect', + 'SingleSelect', + 'MultiSelect', + 'RadioCard', + 'RadioRow', +] as const diff --git a/ui/src/workflow/nodes/base-node/component/UserInputFieldTable.vue b/ui/src/workflow/nodes/base-node/component/UserInputFieldTable.vue index 069930b6a78..f3330b87030 100644 --- a/ui/src/workflow/nodes/base-node/component/UserInputFieldTable.vue +++ b/ui/src/workflow/nodes/base-node/component/UserInputFieldTable.vue @@ -96,6 +96,7 @@ import Sortable from 'sortablejs' import UserFieldFormDialog from './UserFieldFormDialog.vue' import { MsgError } from '@/utils/message' import { t } from '@/locales' +import { ALLOWED_EXPOSED_TYPES } from '@/components/ai-chat/component/inline-params/constants' import UserInputTitleDialog from '@/workflow/nodes/base-node/component/UserInputTitleDialog.vue' import { input_type_list } from '@/components/dynamics-form/constructor/data' const props = defineProps<{ nodeModel: any }>() @@ -110,6 +111,13 @@ function openAddDialog(data?: any, index?: any) { UserFieldFormDialogRef.value.open(data, index) } +function removeFromExposed(fieldName: string) { + const setting = props.nodeModel.properties.user_input_field_list_setting + if (setting?.exposed_fields?.includes(fieldName)) { + setting.exposed_fields = setting.exposed_fields.filter((f: string) => f !== fieldName) + } +} + function openChangeTitleDialog() { UserInputTitleDialogRef.value.open( inputFieldConfig.value, @@ -120,7 +128,11 @@ function openChangeTitleDialog() { } function deleteField(index: any) { + const removed = inputFieldList.value[index] inputFieldList.value.splice(index, 1) + if (removed?.field) { + removeFromExposed(removed.field) + } props.nodeModel.graphModel.eventCenter.emit('refreshFieldList') onDragHandle() } @@ -145,6 +157,9 @@ function refreshFieldList(data: any, index: any) { } else { inputFieldList.value.push(data) } + if (!ALLOWED_EXPOSED_TYPES.includes(data.input_type)) { + removeFromExposed(data.field) + } UserFieldFormDialogRef.value.close() props.nodeModel.graphModel.eventCenter.emit('refreshFieldList') onDragHandle() diff --git a/ui/src/workflow/nodes/base-node/component/UserInputTitleDialog.vue b/ui/src/workflow/nodes/base-node/component/UserInputTitleDialog.vue index c38a00ab355..03a7964a13c 100644 --- a/ui/src/workflow/nodes/base-node/component/UserInputTitleDialog.vue +++ b/ui/src/workflow/nodes/base-node/component/UserInputTitleDialog.vue @@ -24,7 +24,7 @@ :label="getFieldLabel(item)" :value="item.field" :disabled=" - !allowedTypes.includes(item.input_type) || + !ALLOWED_EXPOSED_TYPES.includes(item.input_type) || (form.exposed_fields.length >= 3 && !form.exposed_fields.includes(item.field)) " /> @@ -53,6 +53,7 @@ import { reactive, ref } from 'vue' import type { FormInstance } from 'element-plus' import { t } from '@/locales' +import { ALLOWED_EXPOSED_TYPES } from '@/components/ai-chat/component/inline-params/constants' const emit = defineEmits(['refresh']) const fieldFormRef = ref() @@ -68,17 +69,6 @@ const rules = reactive({ menu_title: [{ required: true, message: t('common.inputPlaceholder'), trigger: 'blur' }], }) -const allowedTypes = [ - 'Model', - 'Knowledge', - 'SwitchInput', - 'DatePicker', - 'TreeSelect', - 'SingleSelect', - 'MultiSelect', - 'RadioCard', - 'RadioRow', -] const dialogVisible = ref(false) const getFieldLabel = (item: any) => {