|
@@ -175,7 +175,7 @@ export const FlowChart: FC<FlowChartProps> = ({ goals, msgGroups = {}, onNodeCli
|
|
|
const nodes: LayoutNode[] = []; // 所有节点列表
|
|
const nodes: LayoutNode[] = []; // 所有节点列表
|
|
|
const edges: LayoutEdge[] = []; // 所有连接线列表
|
|
const edges: LayoutEdge[] = []; // 所有连接线列表
|
|
|
|
|
|
|
|
- const NODE_HEIGHT = 80; // 节点间距(纵向)
|
|
|
|
|
|
|
+ const NODE_HEIGHT = 110; // 节点间距(纵向)
|
|
|
const centerX = dimensions.width / 2; // 主链节点的 X 坐标(居中)
|
|
const centerX = dimensions.width / 2; // 主链节点的 X 坐标(居中)
|
|
|
const HORIZONTAL_OFFSET = 0; // 子节点水平偏移量
|
|
const HORIZONTAL_OFFSET = 0; // 子节点水平偏移量
|
|
|
|
|
|
|
@@ -452,7 +452,7 @@ export const FlowChart: FC<FlowChartProps> = ({ goals, msgGroups = {}, onNodeCli
|
|
|
* 并且调整后续节点的位置,填补折叠后的空白
|
|
* 并且调整后续节点的位置,填补折叠后的空白
|
|
|
*/
|
|
*/
|
|
|
const visibleData = useMemo(() => {
|
|
const visibleData = useMemo(() => {
|
|
|
- const NODE_HEIGHT = 80;
|
|
|
|
|
|
|
+ const NODE_HEIGHT = 110;
|
|
|
|
|
|
|
|
// 1. 找出所有折叠的边
|
|
// 1. 找出所有折叠的边
|
|
|
const collapsedEdgesList = layoutData.edges.filter((e) => e.collapsed);
|
|
const collapsedEdgesList = layoutData.edges.filter((e) => e.collapsed);
|
|
@@ -582,9 +582,9 @@ export const FlowChart: FC<FlowChartProps> = ({ goals, msgGroups = {}, onNodeCli
|
|
|
*/
|
|
*/
|
|
|
const getArcPath = (source: LayoutNode, target: LayoutNode, level: number) => {
|
|
const getArcPath = (source: LayoutNode, target: LayoutNode, level: number) => {
|
|
|
const sx = source.x;
|
|
const sx = source.x;
|
|
|
- const sy = source.y;
|
|
|
|
|
|
|
+ const sy = source.y + 25; // 从节点底部出发
|
|
|
const tx = target.x;
|
|
const tx = target.x;
|
|
|
- const ty = target.y;
|
|
|
|
|
|
|
+ const ty = target.y - 25; // 到节点顶部结束
|
|
|
|
|
|
|
|
// 弧线向右偏移,偏移量根据层级递减
|
|
// 弧线向右偏移,偏移量根据层级递减
|
|
|
// 外层弧线偏移量大,内层弧线偏移量小
|
|
// 外层弧线偏移量大,内层弧线偏移量小
|
|
@@ -604,7 +604,7 @@ export const FlowChart: FC<FlowChartProps> = ({ goals, msgGroups = {}, onNodeCli
|
|
|
* @returns SVG 路径字符串
|
|
* @returns SVG 路径字符串
|
|
|
*/
|
|
*/
|
|
|
const getLinePath = (source: LayoutNode, target: LayoutNode) => {
|
|
const getLinePath = (source: LayoutNode, target: LayoutNode) => {
|
|
|
- return `M ${source.x},${source.y} L ${target.x},${target.y}`;
|
|
|
|
|
|
|
+ return `M ${source.x},${source.y + 25} L ${target.x},${target.y - 25}`;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -745,16 +745,47 @@ export const FlowChart: FC<FlowChartProps> = ({ goals, msgGroups = {}, onNodeCli
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
- <path
|
|
|
|
|
- key={edge.id}
|
|
|
|
|
- d={path}
|
|
|
|
|
- fill="none"
|
|
|
|
|
- stroke={color}
|
|
|
|
|
- strokeWidth={strokeWidth}
|
|
|
|
|
- markerEnd="url(#arrow-default)" // 箭头
|
|
|
|
|
- style={{ cursor: edge.collapsible ? "pointer" : "default" }} // 可折叠的显示手型光标
|
|
|
|
|
- onClick={() => edge.collapsible && toggleCollapse(edge.id)} // 点击切换折叠状态
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <g key={edge.id}>
|
|
|
|
|
+ <path
|
|
|
|
|
+ d={path}
|
|
|
|
|
+ fill="none"
|
|
|
|
|
+ stroke={color}
|
|
|
|
|
+ strokeWidth={strokeWidth}
|
|
|
|
|
+ markerEnd="url(#arrow-default)" // 箭头
|
|
|
|
|
+ style={{ cursor: edge.collapsible ? "pointer" : "default" }} // 可折叠的显示手型光标
|
|
|
|
|
+ onClick={() => edge.collapsible && toggleCollapse(edge.id)} // 点击切换折叠状态
|
|
|
|
|
+ />
|
|
|
|
|
+ {/* 折叠状态提示徽章 */}
|
|
|
|
|
+ {edge.collapsed && (
|
|
|
|
|
+ <g
|
|
|
|
|
+ transform={`translate(${(edge.source.x + edge.target.x) / 2},${
|
|
|
|
|
+ (edge.source.y + edge.target.y) / 2
|
|
|
|
|
+ })`}
|
|
|
|
|
+ onClick={(e) => {
|
|
|
|
|
+ e.stopPropagation();
|
|
|
|
|
+ toggleCollapse(edge.id);
|
|
|
|
|
+ }}
|
|
|
|
|
+ style={{ cursor: "pointer" }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <circle
|
|
|
|
|
+ r={10}
|
|
|
|
|
+ fill="#FFFFFF"
|
|
|
|
|
+ stroke={color}
|
|
|
|
|
+ strokeWidth={1}
|
|
|
|
|
+ />
|
|
|
|
|
+ <text
|
|
|
|
|
+ x={0}
|
|
|
|
|
+ y={4}
|
|
|
|
|
+ fontSize={10}
|
|
|
|
|
+ fill={color}
|
|
|
|
|
+ textAnchor="middle"
|
|
|
|
|
+ fontWeight="bold"
|
|
|
|
|
+ >
|
|
|
|
|
+ {edge.children ? edge.children.length : "+"}
|
|
|
|
|
+ </text>
|
|
|
|
|
+ </g>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </g>
|
|
|
);
|
|
);
|
|
|
})}
|
|
})}
|
|
|
</g>
|
|
</g>
|
|
@@ -784,7 +815,7 @@ export const FlowChart: FC<FlowChartProps> = ({ goals, msgGroups = {}, onNodeCli
|
|
|
<rect
|
|
<rect
|
|
|
x={-70}
|
|
x={-70}
|
|
|
y={-25}
|
|
y={-25}
|
|
|
- width={140}
|
|
|
|
|
|
|
+ width={150}
|
|
|
height={50}
|
|
height={50}
|
|
|
rx={8}
|
|
rx={8}
|
|
|
fill={isGoal ? "#E3F2FD" : "#F5F5F5"} // 目标节点浅蓝色,消息节点灰色
|
|
fill={isGoal ? "#E3F2FD" : "#F5F5F5"} // 目标节点浅蓝色,消息节点灰色
|
|
@@ -793,15 +824,22 @@ export const FlowChart: FC<FlowChartProps> = ({ goals, msgGroups = {}, onNodeCli
|
|
|
/>
|
|
/>
|
|
|
{/* 节点文本(带 Tooltip) */}
|
|
{/* 节点文本(带 Tooltip) */}
|
|
|
<Tooltip content={text}>
|
|
<Tooltip content={text}>
|
|
|
- <text
|
|
|
|
|
- x={0}
|
|
|
|
|
- y={5}
|
|
|
|
|
- fontSize={12}
|
|
|
|
|
- fill={textColor}
|
|
|
|
|
- textAnchor="middle"
|
|
|
|
|
|
|
+ <foreignObject
|
|
|
|
|
+ x={-70}
|
|
|
|
|
+ y={-25}
|
|
|
|
|
+ width={150}
|
|
|
|
|
+ height={50}
|
|
|
>
|
|
>
|
|
|
- {text.length > 10 ? text.slice(0, 10) + "..." : text}
|
|
|
|
|
- </text>
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="w-full h-full flex items-center justify-center text-xs text-center leading-[1.2] px-1 box-border line-clamp-3"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ color: textColor,
|
|
|
|
|
+ WebkitBoxPack: "center", // 垂直居中
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {text}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </foreignObject>
|
|
|
</Tooltip>
|
|
</Tooltip>
|
|
|
</g>
|
|
</g>
|
|
|
);
|
|
);
|