Skip to content

Commit 61363a0

Browse files
author
昔梦
committed
fix:条件节点增加_conditionId+完善条件节点API
1 parent 1b05519 commit 61363a0

File tree

9 files changed

+237
-87
lines changed

9 files changed

+237
-87
lines changed

docs/xflow/demo/switchNode/index.tsx

Lines changed: 112 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,148 @@
11
import XFlow from '@xrenders/xflow';
22
import settings from './setting';
3+
import React from 'react';
34

45
export default () => {
56
const nodes = [
67
{
8+
id: 'hwqfyj734kgwljvt',
79
type: 'Start',
8-
id: '1',
9-
position: { x: -130, y: 290 },
10+
position: {
11+
x: -159.0597703862493,
12+
y: 323.4293111587479,
13+
},
1014
},
1115
{
16+
id: 'kshd2hp4vqm8ww19',
1217
type: 'Switch',
13-
id: '2',
14-
position: { x: 171.25, y: 218.75 },
15-
data: { list: [{ value: '条件1' }] },
18+
position: {
19+
x: 180.79626287562883,
20+
y: 209.9170981759363,
21+
},
22+
data: {
23+
list: [
24+
{
25+
_conditionId: 'condition_1nmzbhnbtv1se6sd', // 对应的 sourceHandle: 'condition_1nmzbhnbtv1se6sd'的边
26+
value: '条件1',
27+
},
28+
{
29+
value: '条件2',
30+
_conditionId: 'condition_enxhwfca1ebn55td', // 对应sourceHandle: 'condition_enxhwfca1ebn55td'的边
31+
},
32+
{
33+
value: '条件3',
34+
_conditionId: 'condition_z1f7b93zwbx1xycu',// 对应sourceHandle: 'condition_z1f7b93zwbx1xycu'的边
35+
},
36+
],
37+
desc: '',
38+
},
1639
},
1740
{
18-
type: 'End',
19-
id: '3',
20-
position: { x: 915, y: 287.5 },
41+
id: 'ql61j2tdli4xage0',
42+
type: 'Prompt',
43+
position: {
44+
x: 578.75,
45+
y: 176.25,
46+
},
47+
},
48+
{
49+
id: 'fab1j735q8iow6u3',
50+
type: 'knowledge',
51+
position: {
52+
x: 577.5,
53+
y: 318.75,
54+
},
2155
},
2256
{
23-
id: 'g29rz9ol4ugqz8m8',
57+
id: '9mc5i628mfrxdow0',
2458
type: 'Prompt',
25-
position: { x: 525, y: 210 },
59+
position: {
60+
x: 603.75,
61+
y: 422.5,
62+
},
2663
},
2764
{
28-
id: 'swqutt73ihfa9lkb',
65+
id: 'xgkajbbgs8cls8r1',
2966
type: 'knowledge',
30-
position: { x: 522.5, y: 472.5 },
67+
position: {
68+
x: 932.5,
69+
y: 556.25,
70+
},
71+
},
72+
{
73+
id: 'anmv2kcadqxj4k63',
74+
type: 'Prompt',
75+
position: {
76+
x: 540,
77+
y: 555,
78+
},
79+
},
80+
{
81+
id: '1obmsf5g1xfsypdj',
82+
type: 'End',
83+
position: {
84+
x: 1359.5373712437117,
85+
y: 359.3804592275014,
86+
},
3187
},
3288
];
3389

3490
const edges = [
3591
{
36-
source: '1',
37-
target: '2',
38-
id: 'xy-edge__1-2',
92+
id: '0lnn4hks9wnz0lnq',
93+
source: 'hwqfyj734kgwljvt',
94+
target: 'kshd2hp4vqm8ww19',
3995
},
4096
{
41-
source: '2',
42-
sourceHandle: 'id_0',
43-
target: 'g29rz9ol4ugqz8m8',
44-
id: 'xy-edge__2id_0-g29rz9ol4ugqz8m8',
97+
id: '5s6af77jbcqvzfod',
98+
source: 'kshd2hp4vqm8ww19',// switch节点的边
99+
target: 'ql61j2tdli4xage0',
100+
sourceHandle: 'condition_1nmzbhnbtv1se6sd', // 对应 _conditionId为'condition_1nmzbhnbtv1se6sd'的条件
45101
},
46-
{ id: 'w6vmrun9sos4t6ds', target: 'swqutt73ihfa9lkb' },
47102
{
48-
source: '2',
49-
sourceHandle: 'id_else',
50-
target: 'swqutt73ihfa9lkb',
51-
id: 'xy-edge__2id_else-swqutt73ihfa9lkb',
103+
id: '6tw709qgc3mtazrv',
104+
source: 'kshd2hp4vqm8ww19',// switch节点的边
105+
target: 'fab1j735q8iow6u3',
106+
sourceHandle: 'condition_enxhwfca1ebn55td', // 对应 _conditionId为'condition_enxhwfca1ebn55td'的条件
52107
},
53108
{
54-
source: 'g29rz9ol4ugqz8m8',
55-
target: '3',
56-
id: 'xy-edge__g29rz9ol4ugqz8m8-3',
109+
id: 'vzlvdo69ljcqegc8',
110+
source: 'kshd2hp4vqm8ww19',// switch节点的边
111+
target: '9mc5i628mfrxdow0',
112+
sourceHandle: 'condition_z1f7b93zwbx1xycu',// 对应 _conditionId为'condition_z1f7b93zwbx1xycu'的条件
57113
},
58114
{
59-
source: 'swqutt73ihfa9lkb',
60-
target: '3',
61-
id: 'xy-edge__swqutt73ihfa9lkb-3',
115+
id: 'j8p8fnr5au9k25pb',
116+
source: 'kshd2hp4vqm8ww19',// switch节点的边
117+
target: 'anmv2kcadqxj4k63',
118+
sourceHandle: 'condition_else',// condition_else 对应默认路径ELSE
119+
},
120+
{
121+
id: '0qfpkc9vcjdb31qp',
122+
source: 'anmv2kcadqxj4k63',
123+
target: 'xgkajbbgs8cls8r1',
124+
},
125+
{
126+
id: '5h05o312rfbj4559',
127+
source: 'ql61j2tdli4xage0',
128+
target: '1obmsf5g1xfsypdj',
129+
},
130+
{
131+
source: 'fab1j735q8iow6u3',
132+
target: '1obmsf5g1xfsypdj',
133+
id: 'xy-edge__fab1j735q8iow6u3-1obmsf5g1xfsypdj',
134+
},
135+
{
136+
source: '9mc5i628mfrxdow0',
137+
target: '1obmsf5g1xfsypdj',
138+
id: 'xy-edge__9mc5i628mfrxdow0-1obmsf5g1xfsypdj',
139+
},
140+
{
141+
source: 'xgkajbbgs8cls8r1',
142+
target: '1obmsf5g1xfsypdj',
143+
id: 'xy-edge__xgkajbbgs8cls8r1-1obmsf5g1xfsypdj',
62144
},
63145
];
64-
65146
return (
66147
<div style={{ height: '600px' }}>
67148
<XFlow

docs/xflow/demo/switchNode/setting.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default [
1111
{
1212
title: '开始',
1313
type: 'Start',
14-
hidden: true,
14+
// hidden: true,
1515
targetHandleHidden: true,
1616
icon: {
1717
type: 'icon-start',
@@ -80,7 +80,7 @@ export default [
8080
{
8181
title: '结束',
8282
type: 'End',
83-
hidden: true,
83+
// hidden: true,
8484
sourceHandleHidden: true,
8585
icon: {
8686
type: 'icon-end',

docs/xflow/nodeBuildIn.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,34 @@ group:
99
# 内置节点
1010

1111
## 条件内置节点
12-
内置条件节点,可以直接设置type为`Switch`使用,条件节点的数据格式为`list:[{value:"条件1"}]`
12+
内置条件节点,可以直接设置type为`Switch`使用。
13+
14+
条件节点的数据格式为`data:{list:[{value:"条件1",_conditionId:"condition_${随机数}"}]}``_conditionId`为边数据的`sourceHandle`,以便条件和边一一对应。
15+
有条件参数value(可以通过自定义条件节点配置面板更改配置参数)的放入list数组里面作为`IF或者ELIF`渲染,没有条件参数的,为默认执行路径`ELSE`,`ELSE`路径的固定`_conditionId``condition_else`,即边数据的`sourceHandle`必须为`condition_else`才能链接`ELSE`链接头,比如:
16+
```js
17+
{
18+
id: 'j8p8fnr5au9k25pb',
19+
source: 'kshd2hp4vqm8ww19',
20+
target: 'anmv2kcadqxj4k63',
21+
sourceHandle: 'condition_else', // else路径的边
22+
}
23+
```
24+
25+
条件节点的每个连接头只能连接一个节点,不能连接多个节点,如果要更换节点,可以通过删除已连接节点或者在连接线上新增节点的方式更换目标节点。
1326

1427
<code src="./demo/switchNode/index.tsx"></code>
1528

1629

1730
## 自定义条件节点
1831
可以通过`nodeWidget`自定义节点面板的渲染,也可以通过`settingSchema``settingWidget`自定义在弹窗中展示的业务配置组件。
32+
```js
33+
const customWidget = ({ data, index }) => {
34+
// data:为data.list循环数据中当前条件的item
35+
// index:为data.list循环数据中当前条件的index
36+
return <p style={{ wordWrap: 'break-word' }}>{data?.value}-{index}</p>;
37+
};
1938

39+
```
2040
<code src="./demo/switchNode/customSwitchNode/index.tsx"></code>
2141
2242
## 并行节点

packages/x-flow/src/components/CustomEdge/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import './index.less';
1515
import { ConfigContext } from '../../models/context';
1616

1717
export default memo((edge: any) => {
18-
const { id, selected, sourceX, sourceY, targetX, targetY, source, target } =
18+
const { id, selected, sourceX, sourceY, targetX, targetY, source, target, sourceHandleId } =
1919
edge;
2020

2121
const reactflow = useReactFlow();
@@ -75,6 +75,7 @@ export default memo((edge: any) => {
7575
id: uuid(),
7676
source,
7777
target: targetId,
78+
...sourceHandleId && { sourceHandle: sourceHandleId }
7879
},
7980
{
8081
id: uuid(),

packages/x-flow/src/components/CustomNode/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default memo((props: any) => {
2828
);
2929
const isSwitchNode = type === 'Switch' || type === 'Parallel'; // 判断是否为条件节点/并行节点
3030
// 增加节点并进行联系
31-
const handleAddNode = (data: any) => {
31+
const handleAddNode = (data: any, sourceHandle?:string) => {
3232
const { screenToFlowPosition } = reactflow;
3333
const { x, y } = screenToFlowPosition({
3434
x: mousePosition.pageX + 100,
@@ -46,6 +46,7 @@ export default memo((props: any) => {
4646
id: uuid(),
4747
source: id,
4848
target: targetId,
49+
...sourceHandle && { sourceHandle }
4950
};
5051
addNodes(newNodes);
5152
addEdges(newEdges);

packages/x-flow/src/components/CustomNode/sourceHandle.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ export default memo((props: any) => {
4747
}}
4848
{...rest}
4949
>
50-
{(selected || isHovered || openNodeSelectPopover) && (
50+
{(selected || isHovered || openNodeSelectPopover ) && (
5151
<>
5252
{switchTitle && (
5353
<div className="xflow-node-switch-title">{switchTitle}</div>
5454
)}
55-
<div className="xflow-node-add-box">
55+
{isConnectable && <div className="xflow-node-add-box">
5656
<NodeSelectPopover
5757
placement="right"
5858
addNode={handleAddNode}
@@ -76,7 +76,7 @@ export default memo((props: any) => {
7676
<PlusOutlined style={{ color: '#fff', fontSize: 10 }} />
7777
</Tooltip>
7878
</NodeSelectPopover>
79-
</div>
79+
</div>}
8080
</>
8181
)}
8282
</Handle>

packages/x-flow/src/components/NodeEditor/index.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import React, { FC, useContext, useEffect, useState } from 'react';
55
import { shallow } from 'zustand/shallow';
66
import { useStore } from '../../hooks/useStore';
77
import { ConfigContext } from '../../models/context';
8+
import { uuid } from '../../utils';
89

910
interface INodeEditorProps {
1011
data: any;
@@ -56,6 +57,19 @@ const NodeEditor: FC<INodeEditorProps> = (props: any) => {
5657
}
5758
if (node) {
5859
// 更新节点的 data
60+
if (node?.data?._nodeType === 'Switch' && data?.list?.length) {
61+
data['list']= data?.list?.map((item,index) => {
62+
if (item?._conditionId) {
63+
return item;
64+
} else {
65+
if (node?.data?.list[index]?._conditionId) {
66+
return { ...item, _conditionId: node?.data?.list[index]?._conditionId };
67+
} else {
68+
return { ...item, _conditionId: `condition_${uuid()}` };
69+
}
70+
}
71+
});
72+
}
5973
node.data = { ...node.data, ...data };
6074
}
6175
});
@@ -65,7 +79,6 @@ const NodeEditor: FC<INodeEditorProps> = (props: any) => {
6579
const watch = {
6680
'#': (allValues: any) => {
6781
handleNodeValueChange({ ...allValues });
68-
// onChange({ id, values: { ...allValues } });
6982
},
7083
};
7184

packages/x-flow/src/components/NodesPopover/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import React, {
1111
} from 'react';
1212
import { useStore } from '../../hooks/useStore';
1313
import { ConfigContext } from '../../models/context';
14-
import { getAntdVersion } from '../../utils';
14+
import { getAntdVersion, uuid } from '../../utils';
1515
import NodesMenu from '../NodesMenu';
1616
import './index.less';
1717

@@ -41,7 +41,11 @@ export default forwardRef((props: any, popoverRef) => {
4141
}, ref);
4242

4343
const handCreateNode = useCallback<any>(({ type }) => {
44-
addNode({ _nodeType: type });
44+
if (type === 'Switch') {
45+
addNode({ _nodeType: type, list: [{ '_conditionId':`condition_${uuid()}`}] });
46+
} else {
47+
addNode({ _nodeType: type });
48+
}
4549
setOpen(false);
4650
onNodeSelectPopoverChange && onNodeSelectPopoverChange(false);
4751
}, []);

0 commit comments

Comments
 (0)