Skip to content

Commit 054a635

Browse files
author
zhanbo.lh
committed
feat: 增加通用节点渲染能力
1 parent 69a25d7 commit 054a635

File tree

7 files changed

+180
-8
lines changed

7 files changed

+180
-8
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import CustomNode from '../CustomNode';
88
import useStore from '../../models/store';
99

1010
const CandidateNode = () => {
11-
const reactflow = useReactFlow();
1211
const { zoom } = useViewport();
12+
const reactflow = useReactFlow();
1313

1414
const {
1515
nodes,
@@ -31,6 +31,9 @@ const CandidateNode = () => {
3131
}))
3232
);
3333

34+
35+
console.log(candidateNode, 'candidateNode+++')
36+
3437
useEventListener('click', (ev) => {
3538
if (!candidateNode) {
3639
return;
@@ -76,7 +79,7 @@ const CandidateNode = () => {
7679
transformOrigin: '0 0',
7780
}}
7881
>
79-
<CustomNode {...candidateNode as any} />
82+
<CustomNode {...candidateNode as any} type={candidateNode?.data?._nodeType } />
8083
</div>
8184
);
8285
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import './index.less';
1414
export default memo((props: any) => {
1515
const { id, type, data, layout, isConnectable, selected, onClick } = props;
1616
const { widgets, settingMap } = useContext(ConfigContext);
17-
const NodeWidget = widgets[`${capitalize(type)}Node`];
17+
const NodeWidget = widgets[`${capitalize(type)}Node`] || widgets['CommonNode'];
1818

1919
const [isHovered, setIsHovered] = useState(false);
2020
const reactflow = useReactFlow();
@@ -67,9 +67,6 @@ export default memo((props: any) => {
6767
sourcePosition = Position.Bottom;
6868
}
6969

70-
console.log(settingMap, 'settingMap=====')
71-
72-
7370
return (
7471
<div
7572
className={classNames('xflow-node-container', {

packages/x-flow/src/nodes/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { default as StartNode } from './node-start';
2-
export { default as EndNode } from './node-end';
2+
export { default as EndNode } from './node-end';
3+
export { default as CommonNode } from './node-common';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.custom-node-start {
2+
width: 240px;
3+
padding: 0 12px;
4+
background: #fff;
5+
border-radius: 12px;
6+
7+
.title {
8+
display: flex;
9+
height: 50px;
10+
align-items: center;
11+
span {
12+
font-weight: bold;
13+
margin-left: 8px;
14+
}
15+
}
16+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React, { memo, useContext } from 'react';
2+
import { ConfigContext } from '../../models/context';
3+
import NodeContainer from '../../components/NodeContainer';
4+
5+
6+
export default memo((props: any) => {
7+
const { type, onClick } = props;
8+
const { settingMap } = useContext(ConfigContext);
9+
const nodeSetting = settingMap[type] || {};
10+
11+
return (
12+
<NodeContainer
13+
className='custom-node-code'
14+
title={nodeSetting.title}
15+
icon={{
16+
type: nodeSetting?.icon.type,
17+
style: { fontSize: 14, color: '#fff' },
18+
bgColor: nodeSetting?.icon.bgColor || '#F79009'
19+
}}
20+
onClick={onClick}
21+
hideDesc={true}
22+
/>
23+
);
24+
});
25+
26+
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { useEffect, useRef } from 'react';
2+
import { AnyObject } from 'antd/lib/_util/type';
3+
import FormRender, { useForm } from 'form-render';
4+
import { ICard, TYPES } from '../../constant';
5+
import FAutoComplete from '../../../components/FAutoComplete';
6+
7+
export interface GlobalOutputProps {
8+
data?: AnyObject;
9+
onChange: (data: AnyObject) => void;
10+
flowList: ICard[];
11+
inputItem: ICard;
12+
readonly?: boolean;
13+
}
14+
15+
const getSchema = (request: any) => ({
16+
type: 'object',
17+
displayType: 'row',
18+
properties: {
19+
list: {
20+
type: 'array',
21+
widget: 'tableList',
22+
props: {
23+
hideMove: true,
24+
hideCopy: true,
25+
size: 'small',
26+
addBtnProps: {
27+
type: 'dashed',
28+
},
29+
actionColumnProps: {
30+
width: 60,
31+
},
32+
},
33+
items: {
34+
type: 'object',
35+
properties: {
36+
name: {
37+
title: '名称',
38+
type: 'string',
39+
width: 200,
40+
placeholder: '请输入',
41+
rules: [
42+
{
43+
pattern: /^[a-zA-Z_][a-zA-Z0-9_]*$/,
44+
message: '只能包含字母、数字和下划线且以字母或划线开头',
45+
},
46+
],
47+
},
48+
dataType: {
49+
title: '类型',
50+
type: 'string',
51+
enum: TYPES.map((el) => el.toUpperCase()),
52+
enumNames: TYPES,
53+
width: 120,
54+
widget: 'select',
55+
placeholder: '请选择',
56+
},
57+
value: {
58+
title: '值',
59+
type: 'string',
60+
widget: 'FAutoComplete',
61+
props: {
62+
placeholder: '${组件名.output}',
63+
request,
64+
},
65+
},
66+
},
67+
},
68+
},
69+
},
70+
});
71+
72+
export default (props: GlobalOutputProps) => {
73+
const { data, onChange, inputItem, flowList, readonly } = props;
74+
75+
const form = useForm();
76+
const flowListRef = useRef<any>();
77+
const inputRef = useRef<any>();
78+
79+
useEffect(() => {
80+
flowListRef.current = flowList;
81+
inputRef.current = inputItem;
82+
}, [flowList, inputItem]);
83+
84+
const watch = {
85+
'#': (allValues: any) => {
86+
onChange({ ...data, ...allValues });
87+
}
88+
};
89+
90+
const request = (val: string) => {
91+
return new Promise((resolve) => {
92+
setTimeout(() => {
93+
const inputValue = inputRef.current?.data;
94+
const inputText = 'inputs';
95+
const options = (inputValue?.list || [])
96+
.filter((el: any) => !!el.name)
97+
.map((item: any) => '${#' + `${inputText}.${item.name}` + `}`);
98+
const nodes = (flowListRef?.current || [])
99+
.filter((el: any) => el.code !== 'Output')
100+
.map((item: any) => {
101+
return '${#' + `${item.code}.output` + `}`;
102+
});
103+
104+
resolve(
105+
[...options, ...nodes]
106+
.filter((el: string) => val && el.includes(val))
107+
.map((el: string) => {
108+
return {
109+
value: el,
110+
};
111+
}),
112+
);
113+
}, 10);
114+
});
115+
};
116+
const schema = getSchema(request);
117+
118+
return (
119+
<FormRender
120+
schema={schema}
121+
form={form}
122+
watch={watch}
123+
readOnly={readonly}
124+
widgets={{ FAutoComplete }}
125+
onMount={() => {
126+
form.setValues({ list: data?.list });
127+
}}
128+
/>
129+
);
130+
}

packages/x-flow/src/nodes/node-start/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import NodeContainer from '../../components/NodeContainer';
44
export default memo((props: any) => {
55
const { onClick } = props;
66

7-
87
return (
98
<NodeContainer
109
className='custom-node-code'

0 commit comments

Comments
 (0)