diff --git a/src/components/VariableRichTextEditor.vue b/src/components/VariableRichTextEditor.vue index 10b6ba5c2d22c24c191263b245dfbbe707aee817..c53ca8490e53ba2f8990fec850782aa66a147be7 100644 --- a/src/components/VariableRichTextEditor.vue +++ b/src/components/VariableRichTextEditor.vue @@ -7,44 +7,53 @@ 回复
-
- + + > {x} - - - - -
+ + + +
- + />
-
+
- @@ -53,10 +62,10 @@
- +
-
- +
- - @@ -2268,11 +2402,11 @@ onUnmounted(() => { user-select: none !important; vertical-align: middle !important; pointer-events: auto !important; // 确保可以响应hover事件 - + &:hover { opacity: 0.8 !important; } - + // 无效变量的警告样式 &.variable-tag-invalid { background: linear-gradient(135deg, #f56565 0%, #e53e3e 100%) !important; @@ -2280,17 +2414,17 @@ onUnmounted(() => { cursor: help !important; // 使用help光标提示有tooltip pointer-events: all !important; // 强制允许所有指针事件 user-select: auto !important; // 允许选择以支持tooltip - + &:hover { opacity: 0.9 !important; } - + // 添加警告图标 &::after { - content: " ⚠️"; + content: ' ⚠️'; font-size: 10px; margin-left: 2px; } } } - \ No newline at end of file + diff --git a/src/i18n/lang/en.ts b/src/i18n/lang/en.ts index 5b6e518af81551e6dc6910a194962e2a4e414d77..87ac5a4adcc25f484a9197116058a3a968d7cc6a 100644 --- a/src/i18n/lang/en.ts +++ b/src/i18n/lang/en.ts @@ -91,6 +91,12 @@ export default { baseMessage: 'Base Message', copyFailed: 'Copy failed', checkFormat: 'Please check the format', + component_name: 'component name', + component_introduction: 'component introduction', + selectedModel: 'select model', + key: 'key', + value: 'value', + rag_query_variables: 'query' }, plugin_center: { plugin_name: 'Plugin Name', @@ -426,24 +432,6 @@ export default { output: 'Output', params: 'Parameters', supplementaryParameters: 'Supplementary Parameters', - add_description: 'Add description...', - settings: 'Settings', - input_params: 'Input Fields', - param_name: 'Parameter Name', - param_label: 'Parameter Label', - select_type: 'Select Type', - required: 'Required', - default_value: 'Default Value', - no_input_params: 'No input parameters', - add_first_param: 'Add first parameter', - duplicate_param_key: 'Parameter name cannot be duplicate', - save_failed: 'Save failed', - add_param: 'Add Parameter', - edit_param: 'Edit Parameter', - param_type: 'Parameter Type', - param_settings: 'Parameter Settings', - param_name_required: 'Parameter name is required', - invalid_param_name: 'Invalid parameter name format', }, pagination: { prev: 'Previous', diff --git a/src/i18n/lang/zh-cn.ts b/src/i18n/lang/zh-cn.ts index 2af288735256caff488a7fe4fdd71158be682131..8d0d8b1f4be3db4ea441965b4552448f8dfc6856 100644 --- a/src/i18n/lang/zh-cn.ts +++ b/src/i18n/lang/zh-cn.ts @@ -90,6 +90,12 @@ export default { publish: '发布', copyFailed: '复制失败', checkFormat: '请检查格式', + component_name: '组件名称', + component_introduction: '组件描述', + selectedModel: '选择模型', + key: '键', + value: '值', + rag_query_variables: '问题' }, plugin_center: { plugin_name: '插件名称', diff --git a/src/views/createapp/components/types.ts b/src/views/createapp/components/types.ts index 425721a8ad21b148acf31764a13c9b6fe050fedc..6cdb5cff9b871824de3b45b9ab05f7454e398ca5 100644 --- a/src/views/createapp/components/types.ts +++ b/src/views/createapp/components/types.ts @@ -148,3 +148,14 @@ export interface ListItem { id: string; value: string | null; } + +export const NodeType = { + RAG: 'rag', + API: 'api', + LLM: 'llm', + MCP: 'mcp', + CHOICE: 'choice', + CODE: 'code', + DIRECTREPLY: 'directreply', + PLUGIN: 'api', +}; diff --git a/src/views/createapp/components/workFlow.vue b/src/views/createapp/components/workFlow.vue index f4a9d9cbad1ef40fd442cedffe7c7333fe4b8c5f..3b97cd64c4f007593c1266c533571741628bf11f 100644 --- a/src/views/createapp/components/workFlow.vue +++ b/src/views/createapp/components/workFlow.vue @@ -25,6 +25,10 @@ import { IconPlusCircle, } from '@computing/opendesign-icons'; +import ApiCallDrawer from './workFlowConfig/ApiCallDrawer.vue'; +import LLMDrawer from './workFlowConfig/LLMDrawer.vue'; +import MCPDrawer from './workFlowConfig/MCPDrawer.vue'; +import RAGDrawer from './workFlowConfig/RAGDrawer.vue'; import EditYamlDrawer from './workFlowConfig/yamlEditDrawer.vue'; import VariableBasedStartNodeDrawer from './workFlowConfig/VariableBasedStartNodeDrawer.vue'; import CodeNodeDrawer from './workFlowConfig/CodeNodeDrawer.vue'; @@ -42,7 +46,7 @@ import CustomLoading from '../../customLoading/index.vue'; import EditFlowName from './workFlowConfig/editFlowName.vue'; import NodeListPanel from './workFlowConfig/NodeListPanel.vue'; import EnvironmentVariableDrawer from './workFlowConfig/EnvironmentVariableDrawer.vue'; - +import { NodeType } from './types'; const { t } = useI18n(); const copilotAside = ref(); const isCopilotAsideVisible = ref(false); @@ -54,6 +58,10 @@ const editFlowNameId = ref(); const editData = ref(); const dialogType = ref(''); const isEditYaml = ref(false); +const isEditApiCall = ref(false); +const isEditLLM = ref(false); +const isEditRAG = ref(false); +const isEditMCP = ref(false); const isEditStartNode = ref(false); const isEditCodeNode = ref(false); const isEditDirectReplyNode = ref(false); @@ -74,7 +82,13 @@ const emits = defineEmits(['updateFlowsDebug']); const route = useRoute(); const workFlowList = ref([]); const props = defineProps(['flowList']); -const flowObj = ref<{flowId?: string, debug?: boolean, name?: string, nodes?: any[], edges?: any[]}>({}); +const flowObj = ref<{ + flowId?: string; + debug?: boolean; + name?: string; + nodes?: any[]; + edges?: any[]; +}>({}); const nodes = ref([]); const debugStatus = ref(''); const debugTime = ref(''); @@ -101,7 +115,7 @@ const insertMenuData = ref({ visible: false, position: { x: 0, y: 0 }, edgeInfo: null, - direction: 'right' as 'left' | 'right' + direction: 'right' as 'left' | 'right', }); const hanleAsideVisible = () => { @@ -170,7 +184,6 @@ onConnect((e) => { }); }); - // 打开新增工作流弹窗 const addWorkFlow = () => { // 待增加新增弹窗 @@ -183,7 +196,9 @@ const handleClose = (flowId?: string) => { api.querySingleAppData({ id: route.query.appId as string }).then((res) => { //workflowList 数据更新 workFlowList.value = res[1]?.result.workflows; - const foundFlow = workFlowList.value.find((item: any) => item.id === flowId); + const foundFlow = workFlowList.value.find( + (item: any) => item.id === flowId, + ); if (foundFlow) { choiceFlowId(foundFlow); } @@ -201,7 +216,7 @@ const delNode = (id) => { }; // 处理变量更新事件 - 仅重新加载对话变量用于开始节点展示 -const handleVariablesUpdated = async () => { +const handleVariablesUpdated = async () => { // 延迟加载,确保后端数据已经同步 setTimeout(async () => { await loadConversationVariablesForDisplay(); @@ -214,16 +229,16 @@ const loadConversationVariablesForDisplay = async () => { console.warn('没有flowId,跳过变量加载'); return; } - + variablesLoading.value = true; - - try { + + try { // 只加载对话变量(不带current_step_id,因为是给开始节点展示用的) - const convVars: any = await listVariables({ - scope: 'conversation', - flow_id: flowObj.value.flowId + const convVars: any = await listVariables({ + scope: 'conversation', + flow_id: flowObj.value.flowId, }); - + // 修复:支持多种API响应结构 let variables: any[] = []; if (convVars?.result?.variables) { @@ -236,13 +251,12 @@ const loadConversationVariablesForDisplay = async () => { // 结构3: 直接返回数组 variables = convVars; } - + if (variables && Array.isArray(variables)) { conversationVariablesForDisplay.value = variables; } else { conversationVariablesForDisplay.value = []; } - } catch (error) { console.error('❌ 加载对话变量失败:', error); ElMessage.error('加载对话变量失败'); @@ -251,8 +265,6 @@ const loadConversationVariablesForDisplay = async () => { } }; - - // 验证节点是否都连接 const nodeAndLineConnection = () => { // 获取当前所有节点和边 @@ -290,83 +302,120 @@ const nodeAndLineConnection = () => { }; // 编辑yaml const editYamlDrawer = (name, desc, yamlCode, nodeId) => { - // 查找当前节点 const currentNode = findNode(nodeId); - - // 检查是否为Code类型节点 - if (currentNode && currentNode.data.callId === 'Code') { - // 打开代码节点编辑器 - currentCodeNodeData.value = { - name: currentNode.data.name, - description: currentNode.data.description, - callId: currentNode.data.callId, - - // 代码节点自身属性 - code: currentNode.data.code || '', - codeType: currentNode.data.codeType || 'python', - securityLevel: currentNode.data.securityLevel || 'low', - timeoutSeconds: currentNode.data.timeoutSeconds || 30, - memoryLimitMb: currentNode.data.memoryLimitMb || 128, - cpuLimit: currentNode.data.cpuLimit || 0.5, - - // 用户定义的输入输出参数 - input_parameters: currentNode.data.parameters?.input_parameters || {}, - output_parameters: currentNode.data.parameters?.output_parameters || {}, - }; - nodeYamlId.value = nodeId; - selectedNodeId.value = nodeId; - isEditCodeNode.value = true; - } else if (currentNode && currentNode.data.callId === 'DirectReply') { - // 打开直接回复节点编辑器 - currentDirectReplyNodeData.value = { - name: currentNode.data.name, - description: currentNode.data.description, - callId: currentNode.data.callId, - parameters: { - input_parameters: { - answer: currentNode.data.parameters?.input_parameters?.answer || '' + console.log(currentNode?.data.callId); + switch (currentNode?.data.callId) { + case 'Code': + // 打开代码节点编辑器 + currentCodeNodeData.value = { + name: currentNode.data.name, + description: currentNode.data.description, + callId: currentNode.data.callId, + + // 代码节点自身属性 + code: currentNode.data.code || '', + codeType: currentNode.data.codeType || 'python', + securityLevel: currentNode.data.securityLevel || 'low', + timeoutSeconds: currentNode.data.timeoutSeconds || 30, + memoryLimitMb: currentNode.data.memoryLimitMb || 128, + cpuLimit: currentNode.data.cpuLimit || 0.5, + + // 用户定义的输入输出参数 + input_parameters: currentNode.data.parameters?.input_parameters || {}, + output_parameters: currentNode.data.parameters?.output_parameters || {}, + }; + isEditCodeNode.value = true; + break; + case 'DirectReply': + // 打开直接回复节点编辑器 + currentDirectReplyNodeData.value = { + name: currentNode.data.name, + description: currentNode.data.description, + callId: currentNode.data.callId, + parameters: { + input_parameters: { + answer: currentNode.data.parameters?.input_parameters?.answer || '', + }, + output_parameters: + currentNode.data.parameters?.output_parameters || {}, }, - output_parameters: currentNode.data.parameters?.output_parameters || {} - } - }; - nodeYamlId.value = nodeId; - selectedNodeId.value = nodeId; - isEditDirectReplyNode.value = true; - } else if (currentNode && currentNode.data.callId === 'Choice') { - // 打开条件分支节点编辑器 - currentChoiceBranchNodeData.value = { - name: currentNode.data.name, - description: currentNode.data.description, - callId: currentNode.data.callId, - parameters: currentNode.data.parameters || { - input_parameters: { choices: [] }, - output_parameters: { - branch_id: { - type: 'string', - description: '选中的分支ID' - } -} - } - }; - nodeYamlId.value = nodeId; - selectedNodeId.value = nodeId; - isEditChoiceBranchNode.value = true; - } else { - // 打开YAML编辑器(其他节点类型) - yamlContent.value = yamlCode; - nodeName.value = name; - nodeDesc.value = desc; - isEditYaml.value = true; - nodeYamlId.value = nodeId; - selectedNodeId.value = nodeId; + }; + isEditDirectReplyNode.value = true; + break; + case 'Choice': + // 打开条件分支节点编辑器 + currentChoiceBranchNodeData.value = { + name: currentNode.data.name, + description: currentNode.data.description, + callId: currentNode.data.callId, + parameters: currentNode.data.parameters || { + input_parameters: { choices: [] }, + output_parameters: { + branch_id: { + type: 'string', + description: '选中的分支ID', + }, + }, + }, + }; + isEditChoiceBranchNode.value = true; + break; + case 'API': + isEditApiCall.value = true; + break; + case 'LLM': + isEditLLM.value = true; + break; + case 'RAG': + isEditRAG.value = true; + break; + case 'MCP': + isEditMCP.value = true; + break; + default: + isEditYaml.value = true; + break; } - - // 编辑时,需要debug 后才可发布 + + yamlContent.value = yamlCode; + nodeName.value = name; + nodeDesc.value = desc; + nodeYamlId.value = nodeId; + selectedNodeId.value = nodeId; + // ↓ 调用节点需要debug 后才可发布 emits('updateFlowsDebug', false); }; // 关闭抽屉 -const closeDrawer = () => { - isEditYaml.value = false; +const closeDrawer = (node_type) => { + switch (node_type) { + case NodeType.API: + isEditApiCall.value = false; + break; + case NodeType.LLM: + isEditLLM.value = false; + break; + case NodeType.RAG: + isEditRAG.value = false; + break; + case NodeType.MCP: + isEditMCP.value = false; + break; + case NodeType.CODE: + isEditCodeNode.value = false; + currentCodeNodeData.value = {}; + break; + case NodeType.DIRECTREPLY: + isEditDirectReplyNode.value = false; + currentDirectReplyNodeData.value = {}; + break; + case NodeType.CHOICE: + isEditChoiceBranchNode.value = false; + currentChoiceBranchNodeData.value = {}; + break; + default: + isEditYaml.value = false; + } + // 清除选中状态 selectedNodeId.value = ''; }; @@ -385,13 +434,13 @@ const saveCodeNode = (nodeData, nodeId) => { id: nodeId, ...nodeData, }; - + // 调用保存接口 saveFlow(updateNodeParameter); - + // 关闭抽屉 closeCodeNodeDrawer(); - + ElMessage.success('代码节点保存成功'); }; @@ -409,13 +458,13 @@ const saveDirectReplyNode = (nodeData, nodeId) => { id: nodeId, ...nodeData, }; - + // 调用保存接口 saveFlow(updateNodeParameter); - + // 关闭抽屉 closeDirectReplyDrawer(); - + ElMessage.success('直接回复节点保存成功'); }; @@ -433,13 +482,13 @@ const saveChoiceBranchNode = (nodeData, nodeId) => { id: nodeId, ...nodeData, }; - + // 调用保存接口 saveFlow(updateNodeParameter); - + // 关闭抽屉 closeChoiceBranchDrawer(); - + ElMessage.success('条件分支节点保存成功'); }; @@ -468,7 +517,7 @@ const editStartNodeDrawer = async (name, desc, yamlCode, nodeId) => { nodeYamlId.value = nodeId; // 设置选中的节点 selectedNodeId.value = nodeId; - + isEditStartNode.value = true; // 编辑 yaml 时,需要debug 后才可发布 emits('updateFlowsDebug', false); @@ -534,7 +583,7 @@ onMounted(() => { }) .then((res) => { const services = res[1]?.result.services || []; - + apiServiceList.value = services; allApiServiceList.value = services; apiLoading.value = false; @@ -548,8 +597,6 @@ onUnmounted(() => { sessionStorage.setItem('workflowViewPortY', ''); }); - - // 处理节点拖拽开始事件 const handleNodeDragStart = (event: DragEvent, node: any) => { onDragStart(event, node.type, { @@ -621,7 +668,7 @@ const getCreatedFlow = async (createdFlowObj) => { workFlowItemName.value = createdFlowObj.name; // 回显工作流节点和边 redrageFlow(createdFlowObj?.nodes, createdFlowObj?.edges); - + // 重新加载对话变量,确保显示当前flow的正确变量状态 await loadConversationVariablesForDisplay(); } @@ -672,11 +719,11 @@ const editFlow = async (item) => { appId: route.query?.appId, flowId: item.id, }); - + if (res[1]?.result?.flow) { flowObj.value = res[1].result.flow; redrageFlow(flowObj.value.nodes || [], flowObj.value.edges || []); - + // 加载对话变量用于开始节点展示 await loadConversationVariablesForDisplay(); } @@ -758,13 +805,15 @@ const redrageFlow = (nodesList, edgesList) => { newNode.deletable = false; } else if (node.callId === 'Choice') { newNode.type = 'Choice'; - + // 处理Choice节点的参数,确保包含ELSE分支 const choices = node.parameters?.input_parameters?.choices || []; - + // 检查是否已有默认分支 - const hasDefaultBranch = choices.some(choice => choice.is_default === true); - + const hasDefaultBranch = choices.some( + (choice) => choice.is_default === true, + ); + // 如果没有默认分支,添加一个ELSE分支 if (!hasDefaultBranch) { choices.push({ @@ -772,30 +821,30 @@ const redrageFlow = (nodesList, edgesList) => { name: 'ELSE', is_default: true, conditions: [], - logic: 'and' + logic: 'and', }); } - + newNode.data = { ...newNode.data, parameters: { - input_parameters: { - choices: choices + input_parameters: { + choices: choices, }, - output_parameters: node.parameters?.output_parameters || { + output_parameters: node.parameters?.output_parameters || { branch_id: { type: 'string', - description: '选中的分支ID' - } - } - } + description: '选中的分支ID', + }, + }, + }, }; } else if (node.callId === 'Code') { // Code节点特殊处理:从parameters中提取特有属性并添加到data中 newNode.type = 'custom'; newNode.data = { ...newNode.data, - nodeId: 'Code', // 设置正确的nodeId + nodeId: 'Code', // 设置正确的nodeId // 从parameters中提取Code节点特有的配置属性 code: node.parameters?.code || '', codeType: node.parameters?.codeType || 'python', @@ -840,43 +889,43 @@ const handleInsertNode = (edgeInfo) => { if (debugDialogVisible.value) { return; // 调试模式下不允许插入节点 } - + // 获取Vue Flow画布的viewport信息 const viewport = getViewport(); - + // 获取Vue Flow容器的位置信息 const vueFlowElement = document.querySelector('.vue-flow__viewport'); const containerRect = vueFlowElement?.getBoundingClientRect(); - + if (!containerRect) { console.error('无法获取Vue Flow容器位置'); return; } - + // 将画布坐标转换为相对于Vue Flow容器的坐标 const containerX = edgeInfo.midX * viewport.zoom + viewport.x; const containerY = edgeInfo.midY * viewport.zoom + viewport.y; - + // 计算建议的菜单方向(不做位置调整,只做方向建议) const menuWidth = 400; let direction: 'left' | 'right' = 'right'; - + // 简单的方向建议:如果右侧空间不足,建议左侧显示 if (containerX + menuWidth + 20 > containerRect.width) { direction = 'left'; } else { direction = 'right'; } - + // 更新插入菜单数据(直接传递容器坐标,让子组件处理边界) insertMenuData.value = { visible: true, position: { x: containerX, - y: containerY + y: containerY, }, edgeInfo, - direction + direction, }; }; @@ -894,26 +943,28 @@ const executeInsertNode = (nodeMetaData) => { console.error('没有边信息,无法插入节点'); return; } - + const edgeInfo = insertMenuData.value.edgeInfo; - + // 生成新节点ID const newNodeId = `node_${Date.now()}`; - + // 找到源边 - const sourceEdge = getEdges.value.find(edge => edge.id === edgeInfo.edgeId); + const sourceEdge = getEdges.value.find( + (edge) => edge.id === edgeInfo.edgeId, + ); if (!sourceEdge) { console.error('找不到要插入的边'); return; } - + // 创建新节点 const newNode = { id: newNodeId, type: nodeMetaData.callId === 'Choice' ? 'Choice' : 'custom', position: { x: edgeInfo.midX - 100, // 节点宽度的一半 - y: edgeInfo.midY - 40 // 节点高度的一半 + y: edgeInfo.midY - 40, // 节点高度的一半 }, data: { name: nodeMetaData.name, @@ -921,44 +972,51 @@ const executeInsertNode = (nodeMetaData) => { nodeId: nodeMetaData.nodeId, callId: nodeMetaData.callId, serviceId: nodeMetaData.serviceId || 'default', - parameters: nodeMetaData.callId === 'Choice' ? { - input_parameters: { - choices: [ - { - branch_id: `else_${newNodeId}`, - name: 'ELSE', - is_default: true, - conditions: [], - logic: 'and' + parameters: + nodeMetaData.callId === 'Choice' + ? { + input_parameters: { + choices: [ + { + branch_id: `else_${newNodeId}`, + name: 'ELSE', + is_default: true, + conditions: [], + logic: 'and', + }, + ], + }, + output_parameters: { + branch_id: { + type: 'string', + description: '选中的分支ID', + }, + }, } - ] - }, - output_parameters: { - branch_id: { - type: 'string', - description: '选中的分支ID' - } - } - } : nodeMetaData.callId === 'DirectReply' ? { - input_parameters: { - answer: '' // 确保新建的DirectReply节点内容为空 - }, - output_parameters: {} - } : { - input_parameters: {}, - output_parameters: {} - } + : nodeMetaData.callId === 'DirectReply' + ? { + input_parameters: { + answer: '', // 确保新建的DirectReply节点内容为空 + }, + output_parameters: {}, + } + : { + input_parameters: {}, + output_parameters: {}, + }, }, - deletable: true + deletable: true, }; - + // 添加新节点 const currentNodes = [...getNodes.value, newNode]; setNodes(currentNodes); - + // 删除原来的边 - const currentEdges = getEdges.value.filter(edge => edge.id !== edgeInfo.edgeId); - + const currentEdges = getEdges.value.filter( + (edge) => edge.id !== edgeInfo.edgeId, + ); + // 创建新的边:源节点 -> 新节点 -> 目标节点 const newEdge1 = { id: `edge_${Date.now()}_1`, @@ -968,35 +1026,34 @@ const executeInsertNode = (nodeMetaData) => { type: 'normal', data: { sourceStatus: 'default', - targetStatus: 'default' - } + targetStatus: 'default', + }, }; - + const newEdge2 = { - id: `edge_${Date.now()}_2`, + id: `edge_${Date.now()}_2`, source: newNodeId, target: sourceEdge.target, targetHandle: sourceEdge.targetHandle, type: 'normal', data: { sourceStatus: 'default', - targetStatus: 'default' - } + targetStatus: 'default', + }, }; - + // 设置新的边 setEdges([...currentEdges, newEdge1, newEdge2]); - + // 触发工作流状态更新 emits('updateFlowsDebug', false); updateFlowsDebugStatus.value = false; nodeAndLineConnection(); - + // 关闭菜单 closeInsertNodeMenu(); - + ElMessage.success(`${nodeMetaData.name} 节点插入成功`); - } catch (error) { console.error('插入节点失败:', error); ElMessage.error('插入节点失败'); @@ -1131,10 +1188,10 @@ const saveFlow = (updateNodeParameter?, debug?) => { apiId: item.data.nodeId, serviceId: item.data.serviceId, stepId: item.id, - nodeId: item.data.nodeId, // 添加nodeId字段 + nodeId: item.data.nodeId, // 添加nodeId字段 type: item.data.nodeId, }; - + // 对于Code节点,需要特殊处理parameters结构 if (item.data.callId === 'Code') { // Code节点:将所有配置放在parameters中 @@ -1152,7 +1209,7 @@ const saveFlow = (updateNodeParameter?, debug?) => { timeoutSeconds: item.data.timeoutSeconds || 30, memoryLimitMb: item.data.memoryLimitMb || 128, cpuLimit: item.data.cpuLimit || 0.5, - } + }, }; } else { // 其他节点:使用原有逻辑 @@ -1174,10 +1231,12 @@ const saveFlow = (updateNodeParameter?, debug?) => { } else if (item.type === 'branch') { // 处理分支节点保存,确保包含ELSE分支 const choices = item.data.parameters?.input_parameters?.choices || []; - + // 检查是否已有默认分支 - const hasDefaultBranch = choices.some(choice => choice.is_default === true); - + const hasDefaultBranch = choices.some( + (choice) => choice.is_default === true, + ); + // 如果没有默认分支,添加一个ELSE分支 if (!hasDefaultBranch) { choices.push({ @@ -1185,30 +1244,32 @@ const saveFlow = (updateNodeParameter?, debug?) => { name: 'ELSE', is_default: true, conditions: [], - logic: 'and' + logic: 'and', }); } - + newItem = { ...newItem, callId: 'Choice', parameters: { input_parameters: { choices: choices }, - output_parameters: item.data.parameters?.output_parameters || { + output_parameters: item.data.parameters?.output_parameters || { branch_id: { type: 'string', - description: '选中的分支ID' - } - } + description: '选中的分支ID', + }, + }, }, }; } else if (item.type === 'Choice') { // 处理Choice节点保存,确保包含ELSE分支 const choices = item.data.parameters?.input_parameters?.choices || []; - + // 检查是否已有默认分支 - const hasDefaultBranch = choices.some(choice => choice.is_default === true); - + const hasDefaultBranch = choices.some( + (choice) => choice.is_default === true, + ); + // 如果没有默认分支,添加一个ELSE分支 if (!hasDefaultBranch) { choices.push({ @@ -1216,21 +1277,21 @@ const saveFlow = (updateNodeParameter?, debug?) => { name: 'ELSE', is_default: true, conditions: [], - logic: 'and' + logic: 'and', }); } - + newItem = { ...newItem, callId: 'Choice', parameters: { input_parameters: { choices: choices }, - output_parameters: item.data.parameters?.output_parameters || { + output_parameters: item.data.parameters?.output_parameters || { branch_id: { type: 'string', - description: '选中的分支ID' - } - } + description: '选中的分支ID', + }, + }, }, }; } @@ -1252,28 +1313,37 @@ const saveFlow = (updateNodeParameter?, debug?) => { updateNodes.forEach((item) => { if (item.stepId === updateNodeParameter.id) { if (item.type === 'Code') { - item.parameters.input_parameters = updateNodeParameter.parameters.input_parameters; - item.parameters.output_parameters = updateNodeParameter.parameters.output_parameters; + item.parameters.input_parameters = + updateNodeParameter.parameters.input_parameters; + item.parameters.output_parameters = + updateNodeParameter.parameters.output_parameters; item.parameters.code = updateNodeParameter.parameters.code; item.parameters.codeType = updateNodeParameter.parameters.codeType; - item.parameters.securityLevel = updateNodeParameter.parameters.securityLevel; - item.parameters.timeoutSeconds = updateNodeParameter.parameters.timeoutSeconds; - item.parameters.memoryLimitMb = updateNodeParameter.parameters.memoryLimitMb; + item.parameters.securityLevel = + updateNodeParameter.parameters.securityLevel; + item.parameters.timeoutSeconds = + updateNodeParameter.parameters.timeoutSeconds; + item.parameters.memoryLimitMb = + updateNodeParameter.parameters.memoryLimitMb; item.parameters.cpuLimit = updateNodeParameter.parameters.cpuLimit; } else if (item.callId === 'DirectReply') { // 确保parameters对象存在 if (!item.parameters) { item.parameters = {}; } - item.parameters.input_parameters = updateNodeParameter.parameters.input_parameters; - item.parameters.output_parameters = updateNodeParameter.parameters.output_parameters; + item.parameters.input_parameters = + updateNodeParameter.parameters.input_parameters; + item.parameters.output_parameters = + updateNodeParameter.parameters.output_parameters; } else if (item.callId === 'Choice') { // 条件分支节点 if (!item.parameters) { item.parameters = {}; } - item.parameters.input_parameters = updateNodeParameter.parameters.input_parameters; - item.parameters.output_parameters = updateNodeParameter.parameters.output_parameters; + item.parameters.input_parameters = + updateNodeParameter.parameters.input_parameters; + item.parameters.output_parameters = + updateNodeParameter.parameters.output_parameters; } else if (item.type === 'start') { item.variables == updateNodeParameter.variables; } else if (item.inputStream !== undefined) { @@ -1281,17 +1351,6 @@ const saveFlow = (updateNodeParameter?, debug?) => { if (!item.parameters) { item.parameters = {}; } - // 当Node以yaml编辑器形式修改了参数 - // 检查updateNodeParameter.inputStream是否包含新的数据结构 - if (updateNodeParameter.inputStream.input_parameters !== undefined && - updateNodeParameter.inputStream.output_parameters !== undefined) { - - item.parameters.input_parameters = updateNodeParameter.inputStream.input_parameters; - item.parameters.output_parameters = updateNodeParameter.inputStream.output_parameters; - } else { - // 旧格式:兼容处理 - item.parameters.input_parameters = updateNodeParameter.inputStream; - } } item.name = updateNodeParameter.name; item.description = updateNodeParameter.description; @@ -1353,12 +1412,17 @@ defineExpose({
@@ -1366,7 +1430,7 @@ defineExpose({
拖拉拽新建节点
- +
@@ -1379,14 +1443,10 @@ defineExpose({
-
- 节点 -
-
- 应用 -
+
节点
+
应用
- +
- - + +
@@ -1594,7 +1662,9 @@ defineExpose({
-
{{ $t(`flow.${StatusInfoTitle[debugStatus]}`) }}
+
+ {{ $t(`flow.${StatusInfoTitle[debugStatus]}`) }} +
+ + + + + + + + + + + + - + - + - + - + - + - + \ No newline at end of file + diff --git a/src/views/createapp/components/workFlowConfig/ApiCallDrawer.vue b/src/views/createapp/components/workFlowConfig/ApiCallDrawer.vue new file mode 100644 index 0000000000000000000000000000000000000000..5a29edc9774a9262b29f533640d2230cc200007e --- /dev/null +++ b/src/views/createapp/components/workFlowConfig/ApiCallDrawer.vue @@ -0,0 +1,830 @@ + + + + + diff --git a/src/views/createapp/components/workFlowConfig/LLMDrawer.vue b/src/views/createapp/components/workFlowConfig/LLMDrawer.vue new file mode 100644 index 0000000000000000000000000000000000000000..7391aa56771cbddc5bb066ac6908a203d7ab72b4 --- /dev/null +++ b/src/views/createapp/components/workFlowConfig/LLMDrawer.vue @@ -0,0 +1,581 @@ + + + + + diff --git a/src/views/createapp/components/workFlowConfig/MCPDrawer.vue b/src/views/createapp/components/workFlowConfig/MCPDrawer.vue new file mode 100644 index 0000000000000000000000000000000000000000..bab042347331de0817898614d2419978daad42a1 --- /dev/null +++ b/src/views/createapp/components/workFlowConfig/MCPDrawer.vue @@ -0,0 +1,384 @@ + + + + + diff --git a/src/views/createapp/components/workFlowConfig/RAGDrawer.vue b/src/views/createapp/components/workFlowConfig/RAGDrawer.vue new file mode 100644 index 0000000000000000000000000000000000000000..d30a9548e2e15cbcdb2f52bd5a6fefa3b653051b --- /dev/null +++ b/src/views/createapp/components/workFlowConfig/RAGDrawer.vue @@ -0,0 +1,538 @@ + + + + + diff --git a/vite.config.ts b/vite.config.ts index 685ac9061bf00a2f6bde8671566d29f4515a8c4e..667eb2301b7d11dd3cf113552450f47fc6c8e3ed 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -20,7 +20,7 @@ import type { UserConfigExport } from 'vite'; // https://vitejs.dev/config/ export default ({ mode }): UserConfigExport => { const env = loadEnv(mode, process.cwd()); - + // 开发模式使用 '/',生产模式使用 './' const baseUrl = mode === 'development' ? '/' : './'; return defineConfig({ @@ -72,10 +72,10 @@ export default ({ mode }): UserConfigExport => { }, server: { - host: '10.211.55.10', + host: 'localhost', hmr: true, - port: 8080, - origin: 'http://10.211.55.10:8080', + port: 3000, + origin: 'http://localhost:3000', headers: { 'Access-Control-Allow-Origin': '*', },