Skip to content

Commit f30c6af

Browse files
committed
fix NodeRouterManager
1 parent e437704 commit f30c6af

7 files changed

Lines changed: 158 additions & 59 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { useContext } from 'react';
2+
3+
import { NodeRenderContext } from '../context';
4+
5+
export function useNodeRenderContext() {
6+
return useContext(NodeRenderContext);
7+
}

frontend/packages/flow-pc/flow-pc-design/src/components/design-editor/node-components/action/table.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import React, {useContext} from "react";
1+
import React from "react";
22
import {Space, Switch} from "antd";
33
import {Table} from "@flow-engine/flow-pc-ui";
4-
import {NodeRenderContext} from "@/components/design-editor/context";
54
import {ActionManager} from "@/components/design-editor/node-components/action/index";
5+
import {useNodeRenderContext} from "@/components/design-editor/hooks/use-node-render-context";
66

77
interface ActionTableProps {
88
value: any[];
99
onChange: (data: any[]) => void;
1010
}
1111

1212
export const ActionTable: React.FC<ActionTableProps> = (props) => {
13-
const {node} = useContext(NodeRenderContext);
13+
const {node} = useNodeRenderContext();
1414
const actions = node.getNodeRegistry()?.meta.actions || [];
1515
const actionManager = new ActionManager(props.value,props.onChange);
1616
const datasource = actionManager.getDatasource(actions);

frontend/packages/flow-pc/flow-pc-design/src/components/design-editor/node-components/header/index.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
1-
import React, {useCallback, useContext, useMemo, useState} from "react";
1+
import React, {useCallback, useMemo, useState} from "react";
22
import {useIsSidebar} from "@/components/design-editor/hooks";
33
import {Button, Flex, Input, Space, theme} from "antd";
44
import {nodeFormPanelFactory} from "@/components/design-editor/components/sidebar";
55
import {usePanelManager} from "@flowgram.ai/panel-manager-plugin";
6-
import {NodeRenderContext} from "@/components/design-editor/context";
76
import {Field, FieldRenderProps} from "@flowgram.ai/fixed-layout-editor";
87
import {CloseOutlined, EditOutlined} from "@ant-design/icons";
98
import {NodeIcon} from "@/components/design-editor/components/node-icon";
109
import {NodeType} from "@/components/design-editor/typings/node-type";
1110
import {FlowNodeRegistry} from "@/components/design-editor/typings";
11+
import {useNodeRenderContext} from "@/components/design-editor/hooks/use-node-render-context";
1212

1313
interface HeaderTitleProps {
1414
title: string;
1515
onChange: (value: string) => void;
1616
readonly?: boolean;
1717
}
1818

19-
const HeaderTitle: React.FC<HeaderTitleProps> = ({ title, onChange, readonly }) => {
20-
const { token } = theme.useToken();
19+
const HeaderTitle: React.FC<HeaderTitleProps> = ({title, onChange, readonly}) => {
20+
const {token} = theme.useToken();
2121
const [editTitle, setEditTitle] = useState(false);
2222
const isSidebar = useIsSidebar();
23-
const { node } = useContext(NodeRenderContext);
23+
const {node} = useNodeRenderContext();
2424

2525
const registry = node.getNodeRegistry<FlowNodeRegistry>();
2626
const editTitleDisabled = useMemo(() => {
27-
const { meta } = registry;
27+
const {meta} = registry;
2828
return meta?.editTitleDisable ?? false;
2929
}, [registry, node]);
3030

@@ -44,9 +44,9 @@ const HeaderTitle: React.FC<HeaderTitleProps> = ({ title, onChange, readonly })
4444
<Input
4545
autoFocus
4646
size="small"
47-
style={{ width: 200 }}
47+
style={{width: 200}}
4848
defaultValue={title}
49-
onChange={(e)=>{
49+
onChange={(e) => {
5050
handleChange(e.target.value);
5151
}}
5252
onBlur={() => setEditTitle(false)}
@@ -62,23 +62,23 @@ const HeaderTitle: React.FC<HeaderTitleProps> = ({ title, onChange, readonly })
6262
<Space>
6363
<span>{title}</span>
6464
<EditOutlined
65-
style={{ color: token.colorPrimary, cursor: "pointer" }}
65+
style={{color: token.colorPrimary, cursor: "pointer"}}
6666
onClick={() => setEditTitle(true)}
6767
/>
6868
</Space>
6969
);
7070
};
7171

72-
interface NodeHeaderProps{
72+
interface NodeHeaderProps {
7373
style?: React.CSSProperties;
7474
iconEnable?: boolean;
7575
}
7676

7777
export const NodeHeader: React.FC<NodeHeaderProps> = (props) => {
78-
const { node } = useContext(NodeRenderContext);
78+
const {node} = useNodeRenderContext();
7979
const isSidebar = useIsSidebar();
8080
const panelManager = usePanelManager();
81-
const { token } = theme.useToken();
81+
const {token} = theme.useToken();
8282
const iconEnable = props.iconEnable ?? true;
8383

8484
const nodeType = node.getNodeRegistry<FlowNodeRegistry>().type as NodeType;
@@ -103,9 +103,9 @@ export const NodeHeader: React.FC<NodeHeaderProps> = (props) => {
103103
align="center"
104104
>
105105
<Space>
106-
{iconEnable && <NodeIcon type={nodeType} />}
106+
{iconEnable && <NodeIcon type={nodeType}/>}
107107
<Field name="title">
108-
{({ field: { value, onChange } }: FieldRenderProps<string>) => (
108+
{({field: {value, onChange}}: FieldRenderProps<string>) => (
109109
<HeaderTitle
110110
title={value}
111111
onChange={onChange}
@@ -117,7 +117,7 @@ export const NodeHeader: React.FC<NodeHeaderProps> = (props) => {
117117
{isSidebar && (
118118
<Button
119119
type="text"
120-
icon={<CloseOutlined style={{ color: token.colorPrimary }} />}
120+
icon={<CloseOutlined style={{color: token.colorPrimary}}/>}
121121
onClick={handleClose}
122122
/>
123123
)}

frontend/packages/flow-pc/flow-pc-design/src/components/design-editor/node-components/panel/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import React, {useCallback, useContext, useMemo, useState} from "react";
1+
import React, {useCallback, useMemo, useState} from "react";
22
import {Flex, theme} from "antd";
33
import {CloseCircleOutlined} from "@ant-design/icons";
4-
import {NodeFormContext, NodeRenderContext} from "@/components/design-editor/context";
4+
import {NodeFormContext} from "@/components/design-editor/context";
55
import {FlowNodeJSON, FlowNodeRegistry} from "@/components/design-editor/typings";
66
import {FormRenderProps, useClientContext} from "@flowgram.ai/fixed-layout-editor";
77
import {useIsSidebar} from "@/components/design-editor/hooks";
8+
import {useNodeRenderContext} from "@/components/design-editor/hooks/use-node-render-context";
89

910
interface NodePanelProps {
1011
children?: React.ReactNode;
@@ -24,7 +25,7 @@ export const NodePanel: React.FC<NodePanelProps> = (props) => {
2425

2526
export const $NodePanel: React.FC<NodePanelProps> = (props) => {
2627
const [isHovered, setIsHovered] = useState(false);
27-
const {node, deleteNode} = useContext(NodeRenderContext);
28+
const {node, deleteNode} = useNodeRenderContext();
2829
const clientContext = useClientContext();
2930
const registry = node.getNodeRegistry<FlowNodeRegistry>();
3031
const isSidebar = useIsSidebar();

frontend/packages/flow-pc/flow-pc-design/src/components/design-panel/manager/node.ts

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,50 @@ export class NodeConvertorManager {
9595
*/
9696
export class NodeRouterManager {
9797
private readonly nodes: FlowNode[];
98+
private readonly nodeList:FlowNode[];
99+
100+
private readonly displayNodeTypes:string[];
98101

99102
constructor(nodes: FlowNode[]) {
100103
this.nodes = nodes;
104+
this.displayNodeTypes = [];
105+
this.nodeList = [];
106+
this.initDisplayNodeTypes();
107+
this.initNodeList();
108+
}
109+
110+
private initDisplayNodeTypes(){
111+
this.displayNodeTypes.push('APPROVAL');
112+
this.displayNodeTypes.push('DELAY');
113+
this.displayNodeTypes.push('END');
114+
this.displayNodeTypes.push('HANDLE');
115+
this.displayNodeTypes.push('NOTIFY');
116+
this.displayNodeTypes.push('ROUTER');
117+
this.displayNodeTypes.push('START');
118+
this.displayNodeTypes.push('SUB_PROCESS');
119+
this.displayNodeTypes.push('TRIGGER');
120+
}
121+
122+
123+
private initNodeList(){
124+
this.fetchNodes(this.nodes);
125+
}
126+
127+
private isDisplayNode(node:FlowNode){
128+
const nodeType = node.type;
129+
return this.displayNodeTypes.includes(nodeType);
130+
}
131+
132+
private fetchNodes(nodes:FlowNode[]){
133+
for (const node of nodes) {
134+
if(this.isDisplayNode(node)){
135+
this.nodeList.push(node);
136+
}
137+
const blocks = node.blocks || [];
138+
if (node.blocks && node.blocks.length > 0){
139+
this.fetchNodes(blocks);
140+
}
141+
}
101142
}
102143

103144
public size() {
@@ -106,18 +147,36 @@ export class NodeRouterManager {
106147

107148
/**
108149
* 查看全部的可选节点
109-
* TODO 需要对blocks的节点进行展开查看,并提出条件控制节点
110150
*/
111151
public getNodes() {
112-
return this.nodes;
152+
return this.nodeList.map(node => {
153+
return {
154+
label:node.name,
155+
value:node.id
156+
}
157+
});
113158
}
114159

115160
/**
116161
* 获取可退回的节点
117-
* TODO 需要对blocks的节点进行展开查看,并提出条件控制节点
118162
* @param nodeId
119163
*/
120164
public getBackNodes(nodeId: string) {
121-
return this.nodes;
165+
const list:FlowNode[] = [];
166+
let matchCurrent = false;
167+
for (const node of this.nodeList) {
168+
if(!matchCurrent) {
169+
list.push(node);
170+
}
171+
if(node.id === nodeId) {
172+
matchCurrent = true;
173+
}
174+
}
175+
return list.map(node => {
176+
return {
177+
label:node.name,
178+
value:node.id
179+
}
180+
});
122181
}
123182
}

frontend/packages/flow-pc/flow-pc-design/src/components/script/plugins/view/error-trigger-view.tsx

Lines changed: 56 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,87 @@
11
import React from "react";
2-
import {NodeTitleGroovyConvertor} from "@/components/script/services/convertor/node-title";
32
import {GroovyScriptConvertorUtil} from "@/components/script/utils/convertor";
4-
import {GroovyScriptPreview} from "@/components/script/components/groovy-script-preview";
5-
import {VariablePicker} from "@/components/script/components/variable-picker";
6-
import {Button, Input, Space} from "antd";
3+
import {Button, Form, Select, Space} from "antd";
74
import {CodeOutlined, ReloadOutlined} from "@ant-design/icons";
85
import {ErrorTriggerViewPlugin, VIEW_KEY} from "@/components/script/plugins/error-trigger-view-type";
96
import {ViewBindPlugin} from "@flow-engine/flow-types";
7+
import {DEFAULT_ERROR_TRIGGER_SCRIPT} from "@/components/script/default-script";
8+
import {useNodeRouterManager} from "@/components/design-panel/hooks/use-node-router-manager";
9+
import {useNodeRenderContext} from "@/components/design-editor/hooks/use-node-render-context";
10+
import {ErrorTriggerConvertor} from "@/components/script/services/convertor/error-trigger";
1011

11-
const {TextArea} = Input;
1212

1313
/**
14-
* TODO 异常触发界面
14+
* TODO 异常配置界面
1515
* @param props
1616
* @constructor
1717
*/
1818
export const ErrorTriggerPluginView: React.FC<ErrorTriggerViewPlugin> = (props) => {
19-
const nodeTitleGroovyConvertor = new NodeTitleGroovyConvertor(props.script, props.variables);
2019
const ErrorTriggerPluginViewComponent = ViewBindPlugin.getInstance().get(VIEW_KEY);
20+
const [type,setType] = React.useState('node');
21+
22+
const nodeRouterManager = useNodeRouterManager();
23+
const { node } = useNodeRenderContext();
24+
2125
if(ErrorTriggerPluginViewComponent){
2226
return (
2327
<ErrorTriggerPluginViewComponent {...props} />
2428
);
2529
}
2630

27-
const title = GroovyScriptConvertorUtil.getScriptTitle(props.script);
28-
2931
return (
3032
<div>
31-
<div>
32-
预览
33-
<GroovyScriptPreview
34-
script={props.script}
35-
multiline={true}
36-
/>
37-
</div>
33+
<Form
34+
initialValues={{
35+
type: type,
36+
}}
37+
>
38+
<Form.Item
39+
name={"type"}
40+
label={"触发类型"}
41+
>
42+
<Select
43+
options={[
44+
{
45+
label:'跳转节点',
46+
value:'node'
47+
},
48+
{
49+
label:'跳转用户',
50+
value:'user'
51+
}
52+
]}
53+
onChange={(value) => {
54+
setType(value);
55+
}}
56+
/>
3857

58+
</Form.Item>
3959

40-
<div>
41-
内容
42-
<TextArea
43-
value={title}
44-
onChange={(e) => {
45-
props.onChange(nodeTitleGroovyConvertor.resetExpression(e.target.value));
46-
}}
47-
placeholder="请输入标题配置脚本,支持使用变量"
48-
autoSize={{minRows: 3, maxRows: 12}}
49-
/>
50-
</div>
60+
{type === "node" && (
61+
<Form.Item
62+
name={"node"}
63+
label={"指定节点"}
64+
>
65+
<Select
66+
options={nodeRouterManager.getBackNodes(node.id)}
67+
onChange={(value,option) => {
68+
const script = ErrorTriggerConvertor.goNode(option as any);
69+
props.onChange(script);
70+
}}
71+
/>
72+
</Form.Item>
73+
)}
74+
75+
{type === "user" && (
76+
<div>选择人员</div>
77+
)}
78+
</Form>
5179

5280
<Space
5381
style={{
5482
marginTop: 8
5583
}}
5684
>
57-
<VariablePicker
58-
mappings={props.variables}
59-
onSelect={(variable) => {
60-
props.onChange(nodeTitleGroovyConvertor.addVariable(variable));
61-
}}
62-
/>
6385
<Button
6486
icon={<CodeOutlined/>}
6587
onClick={() => {
@@ -72,7 +94,7 @@ export const ErrorTriggerPluginView: React.FC<ErrorTriggerViewPlugin> = (props)
7294
icon={<ReloadOutlined/>}
7395
danger={true}
7496
onClick={() => {
75-
props.onChange(nodeTitleGroovyConvertor.getDefaultScript());
97+
props.onChange(DEFAULT_ERROR_TRIGGER_SCRIPT);
7698
}}
7799
>
78100
重置脚本
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export class ErrorTriggerConvertor {
2+
3+
public static goNode(node:{label:string,value:string}){
4+
return `// @SCRIPT_TITLE 回退至${node.label}
5+
def run(request){
6+
return $bind.createErrorThrow('${node.value}');
7+
}`
8+
};
9+
10+
}

0 commit comments

Comments
 (0)