|
@@ -457,9 +457,25 @@ function CustomNode({ data, selected, id }: any) {
|
|
|
// 从节点ID中提取序号,或使用data中的nodeId
|
|
// 从节点ID中提取序号,或使用data中的nodeId
|
|
|
const nodeId = data.nodeId || (id ? String(parseInt(id.split('-').pop() || '0') % 1000).padStart(3, '0') : '001');
|
|
const nodeId = data.nodeId || (id ? String(parseInt(id.split('-').pop() || '0') % 1000).padStart(3, '0') : '001');
|
|
|
|
|
|
|
|
|
|
+ // 处理节点名称:如果超过6个字符则换行
|
|
|
|
|
+ const formatNodeLabel = (text: string): string[] => {
|
|
|
|
|
+ if (!text) return [];
|
|
|
|
|
+ if (text.length <= 6) return [text];
|
|
|
|
|
+
|
|
|
|
|
+ // 如果超过6个字符,按6个字符分割
|
|
|
|
|
+ const lines: string[] = [];
|
|
|
|
|
+ for (let i = 0; i < text.length; i += 6) {
|
|
|
|
|
+ lines.push(text.slice(i, i + 6));
|
|
|
|
|
+ }
|
|
|
|
|
+ return lines;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const nodeLabel = data.label || config?.label || '';
|
|
|
|
|
+ const labelLines = formatNodeLabel(nodeLabel);
|
|
|
|
|
+
|
|
|
return (
|
|
return (
|
|
|
<div
|
|
<div
|
|
|
- className={`relative px-4 py-4 rounded-lg shadow-sm border-2 w-[180px] h-auto min-h-[140px] bg-white ${
|
|
|
|
|
|
|
+ className={`relative px-4 py-4 rounded-lg shadow-sm border-2 w-[200px] min-w-[200px] max-w-[200px] h-auto min-h-[140px] bg-white ${
|
|
|
selected
|
|
selected
|
|
|
? 'border-blue-500 shadow-md ring-1 ring-blue-200'
|
|
? 'border-blue-500 shadow-md ring-1 ring-blue-200'
|
|
|
: 'border-gray-200 hover:border-gray-300'
|
|
: 'border-gray-200 hover:border-gray-300'
|
|
@@ -554,8 +570,16 @@ function CustomNode({ data, selected, id }: any) {
|
|
|
)}
|
|
)}
|
|
|
</div>
|
|
</div>
|
|
|
{/* 中间:节点名称 */}
|
|
{/* 中间:节点名称 */}
|
|
|
- <div className="font-semibold text-sm text-gray-900 leading-tight text-center break-words w-full flex-1 flex items-center justify-center px-1">
|
|
|
|
|
- {data.label || config?.label}
|
|
|
|
|
|
|
+ <div className="font-semibold text-sm text-gray-900 leading-tight text-center break-words w-full flex-1 flex flex-col items-center justify-center px-1">
|
|
|
|
|
+ {labelLines.length > 1 ? (
|
|
|
|
|
+ labelLines.map((line, index) => (
|
|
|
|
|
+ <span key={index} className="block">
|
|
|
|
|
+ {line}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ ))
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <span>{nodeLabel}</span>
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
{/* 底部:ID */}
|
|
{/* 底部:ID */}
|
|
|
<div className="text-xs text-gray-500 text-center flex-shrink-0">
|
|
<div className="text-xs text-gray-500 text-center flex-shrink-0">
|
|
@@ -628,9 +652,38 @@ function CustomEdgeWithDelete({
|
|
|
style,
|
|
style,
|
|
|
type: propType,
|
|
type: propType,
|
|
|
}: any) {
|
|
}: any) {
|
|
|
- // 从全局 edges 中查找对应的边来获取 type
|
|
|
|
|
|
|
+ // 从全局 edges 中查找对应的边来获取 type 和 fixedLength
|
|
|
const edge = globalEdges.find(e => e.id === id);
|
|
const edge = globalEdges.find(e => e.id === id);
|
|
|
const edgeType = edge?.type || propType || 'straight';
|
|
const edgeType = edge?.type || propType || 'straight';
|
|
|
|
|
+ const fixedLength = (edge as any)?.data?.fixedLength || (edge as any)?.fixedLength;
|
|
|
|
|
+
|
|
|
|
|
+ // 计算实际距离
|
|
|
|
|
+ const dx = targetX - sourceX;
|
|
|
|
|
+ const dy = targetY - sourceY;
|
|
|
|
|
+ const actualDistance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
|
+
|
|
|
|
|
+ // 如果设置了 fixedLength 且实际距离大于 fixedLength,则调整起点和终点
|
|
|
|
|
+ let adjustedSourceX = sourceX;
|
|
|
|
|
+ let adjustedSourceY = sourceY;
|
|
|
|
|
+ let adjustedTargetX = targetX;
|
|
|
|
|
+ let adjustedTargetY = targetY;
|
|
|
|
|
+
|
|
|
|
|
+ if (fixedLength && actualDistance > fixedLength && actualDistance > 0.001) {
|
|
|
|
|
+ // 计算单位方向向量
|
|
|
|
|
+ const unitX = dx / actualDistance;
|
|
|
|
|
+ const unitY = dy / actualDistance;
|
|
|
|
|
+
|
|
|
|
|
+ // 计算需要缩短的距离(从两端各缩短一半)
|
|
|
|
|
+ const shortenDistance = (actualDistance - fixedLength) / 2;
|
|
|
|
|
+
|
|
|
|
|
+ // 调整起点(向目标方向移动)
|
|
|
|
|
+ adjustedSourceX = sourceX + unitX * shortenDistance;
|
|
|
|
|
+ adjustedSourceY = sourceY + unitY * shortenDistance;
|
|
|
|
|
+
|
|
|
|
|
+ // 调整终点(向源点方向移动)
|
|
|
|
|
+ adjustedTargetX = targetX - unitX * shortenDistance;
|
|
|
|
|
+ adjustedTargetY = targetY - unitY * shortenDistance;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 根据边的类型选择路径生成函数
|
|
// 根据边的类型选择路径生成函数
|
|
|
let edgePath: string;
|
|
let edgePath: string;
|
|
@@ -641,19 +694,19 @@ function CustomEdgeWithDelete({
|
|
|
// 使用 smoothstep 路径(平滑步进曲线,可以拐弯)
|
|
// 使用 smoothstep 路径(平滑步进曲线,可以拐弯)
|
|
|
// 调整 borderRadius 参数使曲线更平滑
|
|
// 调整 borderRadius 参数使曲线更平滑
|
|
|
[edgePath, labelX, labelY] = getSmoothStepPath({
|
|
[edgePath, labelX, labelY] = getSmoothStepPath({
|
|
|
- sourceX,
|
|
|
|
|
- sourceY,
|
|
|
|
|
- targetX,
|
|
|
|
|
- targetY,
|
|
|
|
|
|
|
+ sourceX: adjustedSourceX,
|
|
|
|
|
+ sourceY: adjustedSourceY,
|
|
|
|
|
+ targetX: adjustedTargetX,
|
|
|
|
|
+ targetY: adjustedTargetY,
|
|
|
borderRadius: 15, // 圆角半径,使曲线更平滑
|
|
borderRadius: 15, // 圆角半径,使曲线更平滑
|
|
|
});
|
|
});
|
|
|
} else {
|
|
} else {
|
|
|
// 使用直线路径
|
|
// 使用直线路径
|
|
|
[edgePath, labelX, labelY] = getStraightPath({
|
|
[edgePath, labelX, labelY] = getStraightPath({
|
|
|
- sourceX,
|
|
|
|
|
- sourceY,
|
|
|
|
|
- targetX,
|
|
|
|
|
- targetY,
|
|
|
|
|
|
|
+ sourceX: adjustedSourceX,
|
|
|
|
|
+ sourceY: adjustedSourceY,
|
|
|
|
|
+ targetX: adjustedTargetX,
|
|
|
|
|
+ targetY: adjustedTargetY,
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1477,6 +1530,9 @@ export default function ProcessDesigner() {
|
|
|
type: 'arrowclosed',
|
|
type: 'arrowclosed',
|
|
|
color: '#000000',
|
|
color: '#000000',
|
|
|
},
|
|
},
|
|
|
|
|
+ data: {
|
|
|
|
|
+ fixedLength: edge.data?.fixedLength || 150, // 保留导入的 fixedLength 或设置为默认值 150
|
|
|
|
|
+ },
|
|
|
};
|
|
};
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -1665,6 +1721,9 @@ export default function ProcessDesigner() {
|
|
|
type: 'arrowclosed',
|
|
type: 'arrowclosed',
|
|
|
color: '#000000',
|
|
color: '#000000',
|
|
|
},
|
|
},
|
|
|
|
|
+ data: {
|
|
|
|
|
+ fixedLength: 150, // 设置连接线固定长度为150
|
|
|
|
|
+ },
|
|
|
};
|
|
};
|
|
|
// 保存历史
|
|
// 保存历史
|
|
|
const newHistory = history.slice(0, historyIndex + 1);
|
|
const newHistory = history.slice(0, historyIndex + 1);
|
|
@@ -1689,6 +1748,9 @@ export default function ProcessDesigner() {
|
|
|
type: 'arrowclosed',
|
|
type: 'arrowclosed',
|
|
|
color: '#000000',
|
|
color: '#000000',
|
|
|
},
|
|
},
|
|
|
|
|
+ data: {
|
|
|
|
|
+ fixedLength: 150, // 设置连接线固定长度为150
|
|
|
|
|
+ },
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
console.log('创建新边,类型:', newEdge.type, '边对象:', newEdge);
|
|
console.log('创建新边,类型:', newEdge.type, '边对象:', newEdge);
|
|
@@ -1752,12 +1814,17 @@ export default function ProcessDesigner() {
|
|
|
|
|
|
|
|
// 更新边的连接点
|
|
// 更新边的连接点
|
|
|
const updatedEdges = [...eds];
|
|
const updatedEdges = [...eds];
|
|
|
|
|
+ const existingEdge = updatedEdges[edgeIndex];
|
|
|
updatedEdges[edgeIndex] = {
|
|
updatedEdges[edgeIndex] = {
|
|
|
- ...updatedEdges[edgeIndex],
|
|
|
|
|
|
|
+ ...existingEdge,
|
|
|
source: newConnection.source!,
|
|
source: newConnection.source!,
|
|
|
target: newConnection.target!,
|
|
target: newConnection.target!,
|
|
|
sourceHandle: sourceHandle || undefined,
|
|
sourceHandle: sourceHandle || undefined,
|
|
|
targetHandle: targetHandle || undefined,
|
|
targetHandle: targetHandle || undefined,
|
|
|
|
|
+ data: {
|
|
|
|
|
+ ...(existingEdge.data || {}),
|
|
|
|
|
+ fixedLength: (existingEdge.data as any)?.fixedLength || 150, // 保留或设置 fixedLength
|
|
|
|
|
+ },
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
console.log('连接线已更新:', updatedEdges[edgeIndex]);
|
|
console.log('连接线已更新:', updatedEdges[edgeIndex]);
|
|
@@ -2845,6 +2912,9 @@ export default function ProcessDesigner() {
|
|
|
type: 'arrowclosed',
|
|
type: 'arrowclosed',
|
|
|
color: '#000000',
|
|
color: '#000000',
|
|
|
},
|
|
},
|
|
|
|
|
+ data: {
|
|
|
|
|
+ fixedLength: edge.data?.fixedLength || 150, // 保留导入的 fixedLength 或设置为默认值 150
|
|
|
|
|
+ },
|
|
|
};
|
|
};
|
|
|
});
|
|
});
|
|
|
|
|
|