Skip to content

Commit 030fc04

Browse files
committed
add flow
1 parent 802f710 commit 030fc04

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+5707
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import React, {Ref, useEffect, useImperativeHandle} from 'react';
2+
import * as monaco from 'monaco-editor';
3+
4+
export interface CodeEditorActionType {
5+
resetValue: (value: string) => void;
6+
getSelectedValue: () => string;
7+
getValue:()=>string;
8+
}
9+
10+
export interface CodeEditorProps {
11+
language?: string,
12+
value?: string,
13+
onChange?: (value: string) => void,
14+
onSelectedRun?: (value: string) => void;
15+
style?: React.CSSProperties;
16+
readonly?:boolean;
17+
theme?:string;
18+
actionRef?: Ref<CodeEditorActionType|undefined>;
19+
}
20+
21+
const CodeEditor: React.FC<CodeEditorProps> = (props) => {
22+
const language = props.language || 'sql';
23+
24+
const actionRef = props.actionRef;
25+
26+
const container = React.useRef(null);
27+
28+
const style = props.style || {
29+
height: "80px",
30+
}
31+
32+
if(actionRef) {
33+
useImperativeHandle(actionRef, () => ({
34+
resetValue: (value: string) => {
35+
const editors = monaco.editor.getEditors();
36+
if(editors.length>0){
37+
const editor = editors[0];
38+
editor.setValue(value);
39+
}
40+
},
41+
getSelectedValue: () => {
42+
const editors = monaco.editor.getEditors();
43+
if (editors.length > 0) {
44+
const editor = editors[0];
45+
const selection = editor.getSelection();
46+
//@ts-ignore
47+
return editor.getModel().getValueInRange(selection);
48+
}
49+
return "";
50+
},
51+
getValue:()=>{
52+
const editors = monaco.editor.getEditors();
53+
if (editors.length > 0) {
54+
const editor = editors[0];
55+
return editor.getValue();
56+
}
57+
return "";
58+
}
59+
}), []);
60+
}
61+
62+
useEffect(() => {
63+
const model = monaco.editor.createModel(props.value || "", language);
64+
const theme = props.theme || "vs-dark";
65+
const editor = monaco.editor.create(
66+
//@ts-ignore
67+
container?.current,
68+
{
69+
automaticLayout: true,
70+
model: model,
71+
fontSize: 14,
72+
theme: theme,
73+
readOnly: props.readonly,
74+
},
75+
);
76+
77+
const subscription = editor.onDidChangeModelContent((event) => {
78+
props.onChange && props.onChange(editor.getValue());
79+
});
80+
81+
let runSelectedCodeActionDispose: monaco.IDisposable | null = null;
82+
if(props.onSelectedRun) {
83+
const runSelectedCodeAction = {
84+
id: "run-code",
85+
label: "Run Selected Code",
86+
contextMenuGroupId: "navigation",
87+
keybindings: [
88+
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyR,
89+
monaco.KeyMod.WinCtrl | monaco.KeyCode.KeyR,
90+
],
91+
run: () => {
92+
const selection = editor.getSelection();
93+
//@ts-ignore
94+
const selectedText = editor.getModel().getValueInRange(selection);
95+
props.onSelectedRun && props.onSelectedRun(selectedText);
96+
},
97+
}
98+
runSelectedCodeActionDispose = monaco.editor.addEditorAction(runSelectedCodeAction);
99+
}
100+
101+
return () => {
102+
editor.dispose();
103+
subscription.dispose();
104+
model.dispose();
105+
106+
if(runSelectedCodeActionDispose!==null){
107+
runSelectedCodeActionDispose.dispose();
108+
}
109+
};
110+
}, [props.readonly]);
111+
112+
return (
113+
<div ref={container} style={style}></div>
114+
);
115+
};
116+
117+
export default CodeEditor;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import {ProForm, ProFormItemProps} from "@ant-design/pro-components";
3+
import CodeEditor, {CodeEditorProps} from "@/components/flow/CodeEditor";
4+
5+
interface ProFormCodeProps extends ProFormItemProps {
6+
codeEditorProps?: CodeEditorProps;
7+
}
8+
9+
const ProFormCode: React.FC<ProFormCodeProps> = (props) => {
10+
11+
const itemProps = {
12+
...props,
13+
codeEditorProps: undefined
14+
};
15+
16+
return (
17+
<ProForm.Item
18+
{...itemProps}
19+
>
20+
<CodeEditor {...props.codeEditorProps}/>
21+
</ProForm.Item>
22+
23+
);
24+
};
25+
26+
export default ProFormCode;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from "react";
2+
import {ModalForm, ProFormDigit} from "@ant-design/pro-components";
3+
import {PostponedFormProps} from "@/components/flow/flow/types";
4+
5+
6+
const PostponedFormView:React.FC<PostponedFormProps> = (props)=>{
7+
8+
return (
9+
<ModalForm
10+
title={"延期调整"}
11+
open={props.visible}
12+
modalProps={{
13+
onCancel: () => {
14+
props.setVisible(false);
15+
},
16+
onClose: () => {
17+
props.setVisible(false);
18+
},
19+
destroyOnClose:true,
20+
}}
21+
onFinish={async (values) => {
22+
props.onFinish(values);
23+
}}
24+
>
25+
<ProFormDigit
26+
name={"hours"}
27+
label={"延期时间"}
28+
tooltip={"以当前时间开始延期,延期单位为小时"}
29+
addonAfter={"小时"}
30+
rules={[
31+
{
32+
required: true,
33+
message: "请输入延期时间"
34+
}
35+
]}
36+
/>
37+
</ModalForm>
38+
)
39+
}
40+
41+
export default PostponedFormView;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React from 'react';
2+
import {Modal, Result} from "antd";
3+
import {ProDescriptions} from "@ant-design/pro-components";
4+
import {FlowResultItem, ResultFormProps} from "@/components/flow/flow/types";
5+
6+
7+
const ResultFormView: React.FC<ResultFormProps> = (props) => {
8+
const {result} = props;
9+
10+
if (!result) {
11+
return null;
12+
}
13+
14+
const resultStateTag = ()=>{
15+
const resultState = result.resultState;
16+
if(resultState === "SUCCESS") {
17+
return "success"
18+
}
19+
if(resultState === "WARNING") {
20+
return "warning"
21+
}
22+
return "info";
23+
};
24+
25+
26+
return (
27+
<Modal
28+
width={"40%"}
29+
height={"60%"}
30+
open={props.visible}
31+
onCancel={() => {
32+
props.setVisible(false);
33+
if (props.flowCloseable) {
34+
props.closeFlow();
35+
}
36+
}}
37+
onClose={() => {
38+
props.setVisible(false);
39+
if (props.flowCloseable) {
40+
props.closeFlow();
41+
}
42+
}}
43+
onOk={() => {
44+
props.setVisible(false);
45+
if (props.flowCloseable) {
46+
props.closeFlow();
47+
}
48+
}}
49+
destroyOnClose={true}
50+
>
51+
52+
<Result
53+
status={resultStateTag()}
54+
title={result.title}
55+
>
56+
{result.items && result.items.map((item: FlowResultItem, index: number) => {
57+
return (
58+
<ProDescriptions
59+
column={2}
60+
>
61+
<ProDescriptions.Item
62+
span={2}
63+
label={item.label}
64+
valueType="text"
65+
>
66+
{item.value}
67+
</ProDescriptions.Item>
68+
</ProDescriptions>
69+
)
70+
})}
71+
</Result>
72+
</Modal>
73+
)
74+
}
75+
76+
export default ResultFormView;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React, {useEffect} from "react";
2+
import {UserSelectProps} from "@/components/flow/flow/types";
3+
import {ModalForm, ProForm, ProFormSelect} from "@ant-design/pro-components";
4+
import {users} from "@/api/user";
5+
6+
7+
const UserSelectView: React.FC<UserSelectProps> = (props) => {
8+
9+
const [form] = ProForm.useForm();
10+
11+
const [userList, setUserList] = React.useState<any[]>([]);
12+
13+
useEffect(() => {
14+
users().then((res) => {
15+
if (res.success) {
16+
const list = res.data.list.filter((item:any)=>{
17+
const specifyUserIds = props.specifyUserIds;
18+
if(specifyUserIds && specifyUserIds.length > 0){
19+
return specifyUserIds.includes(item.id);
20+
}
21+
});
22+
setUserList(list);
23+
// 默认选中当前用户
24+
form.setFieldValue("users", props.currentUserIds);
25+
}
26+
})
27+
}, []);
28+
29+
return (
30+
<ModalForm
31+
form={form}
32+
open={props.visible}
33+
title={"用户选择(模拟测试)"}
34+
modalProps={{
35+
onCancel: () => {
36+
props.setVisible(false);
37+
},
38+
onClose: () => {
39+
props.setVisible(false);
40+
}
41+
}}
42+
onFinish={async (values) => {
43+
const users = values.users;
44+
const selectedUsers = userList.filter((item: any) => {
45+
return users.includes(item.id);
46+
});
47+
props.onFinish(selectedUsers);
48+
props.setVisible(false);
49+
}}
50+
>
51+
<ProFormSelect
52+
mode={"tags"}
53+
name={"users"}
54+
label={"用户"}
55+
options={userList.map((item: any) => {
56+
return {
57+
label: item.name,
58+
value: item.id
59+
}
60+
})}
61+
/>
62+
</ModalForm>
63+
)
64+
}
65+
66+
export default UserSelectView;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from "react";
2+
import {LogicFlow} from "@logicflow/core";
3+
4+
class FlowChartContext{
5+
6+
private readonly lfRef:React.RefObject<LogicFlow>;
7+
8+
constructor(lfRef:React.RefObject<LogicFlow>){
9+
this.lfRef = lfRef;
10+
}
11+
12+
private generateUUID (){
13+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
14+
const r = (Math.random() * 16) | 0;
15+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
16+
return v.toString(16);
17+
});
18+
}
19+
20+
addNode(type:string,name:string){
21+
const uid = this.generateUUID();
22+
this.lfRef.current?.dnd.startDrag({
23+
id: uid,
24+
type: type,
25+
properties: {
26+
id: uid,
27+
name: name,
28+
}
29+
})
30+
}
31+
}
32+
33+
export default FlowChartContext;

0 commit comments

Comments
 (0)