diff --git a/src/views/settings/workflow/component/InputSourceManager.vue b/src/views/settings/workflow/component/InputSourceManager.vue index 31698e7..ccef596 100644 --- a/src/views/settings/workflow/component/InputSourceManager.vue +++ b/src/views/settings/workflow/component/InputSourceManager.vue @@ -55,9 +55,9 @@ import { ref, computed } from 'vue'; import type { Node } from '@vue-flow/core'; interface NodeData { - label: string; - nodeCode: string; - inputSource: Array<{ nodeId: string; field: string[]; quoteOutput?: boolean }> | null; + label?: string; + nodeCode?: string; + inputSource?: Array<{ nodeId: string; field: string[]; quoteOutput?: boolean }> | null; formConfig?: any[]; modelConfig?: any; skillName?: string; @@ -74,8 +74,8 @@ interface ParamOption { } const props = defineProps<{ - selectedNode: Node | null; - nodes: Node[]; + selectedNode: Node | null; + nodes: Node[]; edges: any[]; }>(); @@ -89,19 +89,19 @@ const selectedParam = ref(''); // 当前节点的 inputSource const currentInputSource = computed(() => { - if (!props.selectedNode?.data.inputSource) return []; + if (!props.selectedNode?.data?.inputSource) return []; return props.selectedNode.data.inputSource.filter((item) => item.field && item.field.length > 0); }); // 获取节点名称 const getNodeName = (nodeId: string) => { const node = props.nodes.find((n) => n.id === nodeId); - return node?.data.label || nodeId; + return node?.data?.label || nodeId; }; // 获取所有上级节点(用于显示输出引用选项) const availableParentNodes = computed(() => { - if (!props.selectedNode) return []; + if (!props.selectedNode?.data) return []; // 获取已经引用了字段的节点ID列表 const inputSource = props.selectedNode.data.inputSource; @@ -134,7 +134,7 @@ const availableParentNodes = computed(() => { const parentNodes = allParentIds .map((parentId) => { const parentNode = props.nodes.find((n) => n.id === parentId); - if (!parentNode) return null; + if (!parentNode?.data) return null; const nodeCode = String(parentNode.data.nodeCode || '').toLowerCase(); const isJudge = ['判断', 'judge', 'condition', 'if', 'branch', 'gateway'].some((k) => nodeCode.includes(k)); @@ -144,7 +144,7 @@ const availableParentNodes = computed(() => { return { id: parentId, - name: parentNode.data.label, + name: parentNode.data.label || parentId, }; }) .filter(Boolean); @@ -154,7 +154,7 @@ const availableParentNodes = computed(() => { // 检查节点输出是否被引用 const isNodeOutputQuoted = (nodeId: string): boolean => { - if (!props.selectedNode) return false; + if (!props.selectedNode?.data) return false; const inputSource = props.selectedNode.data.inputSource; if (!Array.isArray(inputSource)) return false; @@ -177,7 +177,7 @@ const availableParams = computed(() => { .filter((e) => e.target === nodeId) .forEach((edge) => { const parent = props.nodes.find((n) => n.id === edge.source); - if (parent && parent.data.nodeCode !== '__start__' && parent.data.nodeCode !== 'judge') { + if (parent?.data && parent.data.nodeCode !== '__start__' && parent.data.nodeCode !== 'judge') { params.push({ label: `${parent.data.label}.output`, value: `\${${parent.id}.output}`, diff --git a/src/views/settings/workflow/component/NodeConfigPanel.vue b/src/views/settings/workflow/component/NodeConfigPanel.vue index 1851666..1b7943f 100644 --- a/src/views/settings/workflow/component/NodeConfigPanel.vue +++ b/src/views/settings/workflow/component/NodeConfigPanel.vue @@ -4,16 +4,16 @@
- + - {{ selectedNode.data.nodeCode }} + {{ selectedNode.data?.nodeCode }} 选择模型 -
+
{{ selectedNode.data.modelConfig.modelName }} @@ -23,7 +23,7 @@ 选择技能 -
+
{{ selectedNode.data.skillName }} @@ -80,7 +80,7 @@ | null; + label?: string; + nodeCode?: string; + inputSource?: Array<{ nodeId: string; field: string[]; quoteOutput?: boolean }> | null; formConfig?: any[]; modelConfig?: any; skillName?: string; @@ -118,15 +118,15 @@ interface NodeConfig { } const props = defineProps<{ - selectedNode: Node | null; + selectedNode: Node | null; availableParams: ParamRef[]; nodeConfig: NodeConfig | null; - allNodes: Node[]; + allNodes: Node[]; allEdges: any[]; }>(); const emit = defineEmits<{ - (e: 'update:selectedNode', node: Node): void; + (e: 'update:selectedNode', node: Node): void; (e: 'addParam', param: ParamRef): void; (e: 'openModelSelector'): void; (e: 'removeModel'): void; @@ -138,7 +138,7 @@ const emit = defineEmits<{ }>(); const updateNodeLabel = (newLabel: string) => { - if (!props.selectedNode) return; + if (!props.selectedNode?.data) return; const updatedNode = { ...props.selectedNode, data: { @@ -150,13 +150,13 @@ const updateNodeLabel = (newLabel: string) => { }; const getFieldValue = (fieldName: string) => { - if (!props.selectedNode?.data.formConfig) return ''; + if (!props.selectedNode?.data?.formConfig) return ''; const field = props.selectedNode.data.formConfig.find((f: any) => f.field === fieldName); return field?.value ?? ''; }; const updateFieldValue = (fieldName: string, value: any) => { - if (!props.selectedNode) return; + if (!props.selectedNode?.data) return; const formConfig = props.selectedNode.data.formConfig || []; const existingIndex = formConfig.findIndex((f: any) => f.field === fieldName); diff --git a/src/views/settings/workflow/index.vue b/src/views/settings/workflow/index.vue index dcbc149..6ea3709 100644 --- a/src/views/settings/workflow/index.vue +++ b/src/views/settings/workflow/index.vue @@ -35,7 +35,12 @@
- + + :user-workflow-list="userWorkflowList" + :template-workflow-list="templateWorkflowList" + :current-editing-id="currentEditingWorkflowId" + :loading="workflowListLoading" + @edit="editWorkflow" + @delete="deleteWorkflowAction" + @create="createNewWorkflow" + />
- + @@ -102,9 +113,9 @@ import ModelSelector from '/@/components/model/ModelSelector.vue'; import SkillSelector from '/@/components/skill/SkillSelector.vue'; interface NodeData { - label: string; - nodeCode: string; - inputSource: Array<{ nodeId: string; field: string[]; quoteOutput?: boolean }> | null; + label?: string; + nodeCode?: string; + inputSource?: Array<{ nodeId: string; field: string[]; quoteOutput?: boolean }> | null; formConfig?: any[]; modelConfig?: any; skillName?: string; @@ -146,7 +157,7 @@ const nodeConfigMap = computed(() => { // 当前选中节点的配置 const currentNodeConfig = computed(() => { - if (!selectedNode.value) return null; + if (!selectedNode.value?.data?.nodeCode) return null; return nodeConfigMap.value.get(selectedNode.value.data.nodeCode) || null; }); @@ -164,9 +175,9 @@ const saveForm = ref({ description: '', }); -const nodes = ref[]>([]); +const nodes = ref[]>([]); const edges = ref([]); -const selectedNode = ref | null>(null); +const selectedNode = ref | null>(null); let nodeId = 0; // 模型选择器相关状态 @@ -186,7 +197,7 @@ const showSkillSelector = ref(false); const selectedSkillData = ref(null); const deleteSelectedNode = async () => { - if (!selectedNode.value) return; + if (!selectedNode.value?.data) return; if (selectedNode.value.data.nodeCode === '__start__') { ElMessage.warning('开始节点不能删除'); @@ -212,7 +223,7 @@ const onConnect = (connection: Connection) => { const source = findNode(connection.source); const target = findNode(connection.target); - if (!source || !target) return; + if (!source?.data || !target?.data) return; if (target.data.nodeCode === '__start__') { ElMessage.warning('开始节点不能被连接'); @@ -237,11 +248,11 @@ const onConnect = (connection: Connection) => { ElMessage.success('连接成功'); }; -const onNodeClick = (event: { node: Node }) => { +const onNodeClick = (event: { node: Node }) => { selectedNode.value = event.node; }; -const updateSelectedNode = (updatedNode: Node) => { +const updateSelectedNode = (updatedNode: Node) => { selectedNode.value = updatedNode; // 同步更新到 nodes 数组 const index = nodes.value.findIndex((n) => n.id === updatedNode.id); @@ -260,7 +271,7 @@ const availableParams = computed(() => { .filter((e) => e.target === nodeId) .forEach((edge) => { const parent = findNode(edge.source); - if (parent && parent.data.nodeCode !== '__start__' && parent.data.nodeCode !== 'judge') { + if (parent?.data && parent.data.nodeCode !== '__start__' && parent.data.nodeCode !== 'judge') { parents.push({ id: parent.id, label: `${parent.data.label}.output` }); } findParents(edge.source, visited); @@ -271,15 +282,15 @@ const availableParams = computed(() => { }); const addParam = (param: ParamRef) => { - if (!selectedNode.value) return; - + if (!selectedNode.value?.data) return; + if (!selectedNode.value.data.inputSource) { selectedNode.value.data.inputSource = []; } - + // 查找是否已存在该节点的引用 const existingIndex = selectedNode.value.data.inputSource.findIndex((item) => item.nodeId === param.id); - + if (existingIndex >= 0) { // 已存在,添加 output 到 field 数组 const existing = selectedNode.value.data.inputSource[existingIndex]; @@ -302,9 +313,9 @@ const addParam = (param: ParamRef) => { // 模型选择确认 const handleModelConfirm = (model: any) => { - if (!selectedNode.value) return; + if (!selectedNode.value?.data) return; - const updatedNode = { + const updatedNode: Node = { ...selectedNode.value, data: { ...selectedNode.value.data, @@ -330,9 +341,9 @@ const handleModelConfirm = (model: any) => { // 移除模型 const handleRemoveModel = () => { - if (!selectedNode.value) return; + if (!selectedNode.value?.data) return; - const updatedNode = { + const updatedNode: Node = { ...selectedNode.value, data: { ...selectedNode.value.data, @@ -353,9 +364,9 @@ const handleRemoveModel = () => { // 技能选择确认 const handleSkillConfirm = (skill: any) => { - if (!selectedNode.value) return; + if (!selectedNode.value?.data) return; - const updatedNode = { + const updatedNode: Node = { ...selectedNode.value, data: { ...selectedNode.value.data, @@ -376,9 +387,9 @@ const handleSkillConfirm = (skill: any) => { // 移除技能 const handleRemoveSkill = () => { - if (!selectedNode.value) return; + if (!selectedNode.value?.data) return; - const updatedNode = { + const updatedNode: Node = { ...selectedNode.value, data: { ...selectedNode.value.data, @@ -399,7 +410,7 @@ const handleRemoveSkill = () => { // 删除上级参数字段 const handleRemoveField = (nodeId: string, fieldName: string) => { - if (!selectedNode.value) return; + if (!selectedNode.value?.data) return; const inputSource = selectedNode.value.data.inputSource || []; const nodeIndex = inputSource.findIndex((item) => item.nodeId === nodeId); @@ -416,7 +427,7 @@ const handleRemoveField = (nodeId: string, fieldName: string) => { updatedInputSource = inputSource.filter((_, idx) => idx !== nodeIndex); } - const updatedNode = { + const updatedNode: Node = { ...selectedNode.value, data: { ...selectedNode.value.data, @@ -435,7 +446,7 @@ const handleRemoveField = (nodeId: string, fieldName: string) => { // 切换节点输出引用 const handleToggleOutput = (nodeId: string, enabled: boolean) => { - if (!selectedNode.value) return; + if (!selectedNode.value?.data) return; const inputSource = selectedNode.value.data.inputSource || []; const nodeIndex = inputSource.findIndex((item) => item.nodeId === nodeId); @@ -458,7 +469,7 @@ const handleToggleOutput = (nodeId: string, enabled: boolean) => { ]; } - const updatedNode = { + const updatedNode: Node = { ...selectedNode.value, data: { ...selectedNode.value.data, @@ -473,13 +484,13 @@ const handleToggleOutput = (nodeId: string, enabled: boolean) => { } const parentNode = nodes.value.find((n) => n.id === nodeId); - const nodeName = parentNode?.data.label || '节点'; + const nodeName = parentNode?.data?.label || '节点'; ElMessage.success(enabled ? `已开启引入 ${nodeName} 的输出` : `已关闭引入 ${nodeName} 的输出`); }; // 通过参数值添加上级参数 const handleAddParamByValue = (paramValue: string) => { - if (!selectedNode.value) return; + if (!selectedNode.value?.data) return; const match = paramValue.match(/\$\{([^.]+)\.(.+)\}/); if (!match) return; @@ -514,7 +525,7 @@ const handleAddParamByValue = (paramValue: string) => { ]; } - const updatedNode = { + const updatedNode: Node = { ...selectedNode.value, data: { ...selectedNode.value.data, @@ -532,14 +543,14 @@ const handleAddParamByValue = (paramValue: string) => { }; // 辅助函数:判断是否为开始节点 -const isStartNode = (node: Node) => { - return node.data.nodeCode === START_NODE_CODE; +const isStartNode = (node: Node) => { + return node.data?.nodeCode === START_NODE_CODE; }; // 辅助函数:判断是否为判断节点 -const isJudgeNode = (node: Node) => { - const nodeCode = (node.data.nodeCode || '').toLowerCase(); - const nodeName = (node.data.label || '').toLowerCase(); +const isJudgeNode = (node: Node) => { + const nodeCode = (node.data?.nodeCode || '').toLowerCase(); + const nodeName = (node.data?.label || '').toLowerCase(); return JUDGE_KEYWORDS.some((k) => nodeCode.includes(k) || nodeName.includes(k)); }; @@ -659,10 +670,10 @@ const createNewWorkflow = () => { edges.value = []; selectedNode.value = null; nodeId = 0; - + // 添加默认开始节点 addDefaultStartNode(); - + ElMessage.success('已清空画布,可以开始创建新工作流'); }; @@ -690,7 +701,7 @@ const loadWorkflowFromDsl = (dsl: any) => { const loadedNodes = (dsl.nodes || []).map((n: any) => { // 确保 inputSource 使用新结构 let normalizedInputSource: Array<{ nodeId: string; field: string[]; quoteOutput?: boolean }> | null = null; - + if (n.inputSource) { if (Array.isArray(n.inputSource)) { // 检查是否为新结构(对象数组) @@ -775,18 +786,18 @@ const confirmSaveWorkflow = async () => { startNodeId: nodes.value[0]?.id || '', nodes: nodes.value.map((n) => ({ id: n.id, - nodeCode: n.data.nodeCode || 'unknown', - name: n.data.label || '', + nodeCode: n.data?.nodeCode || 'unknown', + name: n.data?.label || '', type: n.type || 'default', - skillName: n.data.skillName || null, + skillName: n.data?.skillName || null, config: { - nodeCode: n.data.nodeCode || 'unknown', + nodeCode: n.data?.nodeCode || 'unknown', x: n.position?.x || 0, y: n.position?.y || 0, }, - inputSource: n.data.inputSource || null, - formConfig: n.data.formConfig || null, - modelConfig: n.data.modelConfig || null, + inputSource: n.data?.inputSource || null, + formConfig: n.data?.formConfig || null, + modelConfig: n.data?.modelConfig || null, outputResult: null, })), edges: edges.value.map((e) => ({