优化工作流组件,增强节点数据处理的可选性和安全性,修复潜在的空值引用问题。
This commit is contained in:
@@ -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<NodeData> | null;
|
||||
nodes: Node<NodeData>[];
|
||||
selectedNode: Node<NodeData, any, string> | null;
|
||||
nodes: Node<NodeData, any, string>[];
|
||||
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}`,
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
<div v-if="selectedNode">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="节点名称">
|
||||
<el-input :model-value="selectedNode.data.label" @update:model-value="updateNodeLabel" />
|
||||
<el-input :model-value="selectedNode.data?.label" @update:model-value="updateNodeLabel" />
|
||||
</el-form-item>
|
||||
<el-form-item label="节点类型">
|
||||
<el-tag>{{ selectedNode.data.nodeCode }}</el-tag>
|
||||
<el-tag>{{ selectedNode.data?.nodeCode }}</el-tag>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 模型选择 -->
|
||||
<el-form-item v-if="nodeConfig?.modelConfig && nodeConfig.modelConfig.length > 0" label="选择模型">
|
||||
<el-button type="primary" @click="emit('openModelSelector')" style="width: 100%">选择模型</el-button>
|
||||
<div v-if="selectedNode.data.modelConfig?.modelName" class="selected-tag">
|
||||
<div v-if="selectedNode.data?.modelConfig?.modelName" class="selected-tag">
|
||||
<el-tag type="success" size="large" closable @close="emit('removeModel')">
|
||||
{{ selectedNode.data.modelConfig.modelName }}
|
||||
</el-tag>
|
||||
@@ -23,7 +23,7 @@
|
||||
<!-- 技能选择 -->
|
||||
<el-form-item v-if="nodeConfig?.skillOption" label="选择技能">
|
||||
<el-button type="primary" @click="emit('openSkillSelector')" style="width: 100%">选择技能</el-button>
|
||||
<div v-if="selectedNode.data.skillName" class="selected-tag">
|
||||
<div v-if="selectedNode.data?.skillName" class="selected-tag">
|
||||
<el-tag type="success" size="large" closable @close="emit('removeSkill')">
|
||||
{{ selectedNode.data.skillName }}
|
||||
</el-tag>
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
<!-- 上级参数管理 -->
|
||||
<InputSourceManager
|
||||
v-if="selectedNode.data.nodeCode !== '__start__'"
|
||||
v-if="selectedNode.data?.nodeCode !== '__start__'"
|
||||
:selected-node="selectedNode"
|
||||
:nodes="allNodes"
|
||||
:edges="allEdges"
|
||||
@@ -98,9 +98,9 @@ import type { Node } from '@vue-flow/core';
|
||||
import InputSourceManager from './InputSourceManager.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;
|
||||
@@ -118,15 +118,15 @@ interface NodeConfig {
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
selectedNode: Node<NodeData> | null;
|
||||
selectedNode: Node<NodeData, any, string> | null;
|
||||
availableParams: ParamRef[];
|
||||
nodeConfig: NodeConfig | null;
|
||||
allNodes: Node<NodeData>[];
|
||||
allNodes: Node<NodeData, any, string>[];
|
||||
allEdges: any[];
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:selectedNode', node: Node<NodeData>): void;
|
||||
(e: 'update:selectedNode', node: Node<NodeData, any, string>): 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);
|
||||
|
||||
Reference in New Issue
Block a user