Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
bkunyun
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
bkunyun
Commits
a1e043c4
Commit
a1e043c4
authored
Jul 12, 2022
by
吴永生#A02208
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: flow组件优化拆分
parent
4af3d4d3
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
278 additions
and
195 deletions
+278
-195
interface.ts
src/views/Project/ProjectSubmitWork/interface.ts
+4
-3
index.module.css
...ect/components/Flow/components/BatchNode/index.module.css
+4
-10
index.tsx
...ws/Project/components/Flow/components/BatchNode/index.tsx
+103
-0
index.module.css
...ject/components/Flow/components/FlowNode/index.module.css
+16
-0
index.tsx
...ews/Project/components/Flow/components/FlowNode/index.tsx
+74
-0
index.tsx
src/views/Project/components/Flow/index.tsx
+73
-180
interface.ts
src/views/Project/components/Flow/interface.ts
+4
-2
No files found.
src/views/Project/ProjectSubmitWork/interface.ts
View file @
a1e043c4
...
...
@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-21 20:03:56
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-
09 15:57:24
* @LastEditTime: 2022-07-
12 11:51:17
* @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/interface.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
...
...
@@ -23,7 +23,8 @@ export interface IParameter {
tags
:
Array
<
string
>
;
source
:
string
;
productId
:
string
;
tasks
:
ITask
[];
// tasks: ITask[];
isLine
?:
boolean
;
validators
:
Array
<
IValidator
>
;
choices
:
Array
<
IChoice
>
;
error
?:
boolean
;
...
...
@@ -93,7 +94,7 @@ export interface IEdge {
sourceHandle
:
string
;
target
:
string
;
targetHandle
:
string
;
label
:
string
;
label
?
:
string
;
}
// 提交任务时的动态表单的数据结构
...
...
src/views/Project/components/Flow/index.module.css
→
src/views/Project/components/Flow/
components/BatchNode/
index.module.css
View file @
a1e043c4
...
...
@@ -20,16 +20,6 @@
border-left
:
4px
solid
#ff4e4e
;
}
.batchRotate
{
transform
:
translateX
(
-50%
)
rotate
(
-90deg
);
}
.flowNode
{
background-color
:
#f5f6f7
;
border-radius
:
2px
;
padding
:
6px
12px
;
}
.successDot
{
display
:
inline-block
;
line-height
:
22px
;
...
...
@@ -45,3 +35,7 @@
border
:
1px
solid
#1370ff
;
border-left
:
4px
solid
#1370ff
;
}
.batchRotate
{
transform
:
translateX
(
-50%
)
rotate
(
-90deg
);
}
src/views/Project/components/Flow/components/BatchNode/index.tsx
0 → 100644
View file @
a1e043c4
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-12 11:20:29
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-12 11:28:57
* @FilePath: /bkunyun/src/views/Project/components/Flow/components/BatchNode.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import
{
Tooltip
}
from
"@mui/material"
;
import
classNames
from
"classnames"
;
import
{
useMemo
}
from
"react"
;
import
{
Handle
,
Position
}
from
"react-flow-renderer"
;
import
{
uuid
}
from
"@/utils/util"
;
import
{
IBatchNode
}
from
"../../interface"
;
import
styles
from
"./index.module.css"
;
/** 自定义batch节点 */
const
BatchNode
=
(
props
:
IBatchNode
)
=>
{
const
{
data
}
=
props
;
const
{
style
,
isFlowNode
,
selectedStatus
,
info
:
{
title
,
isCheck
,
executionStatus
,
parameters
},
}
=
data
;
/** 获取输入参数数组 */
const
inParamsArr
=
useMemo
(()
=>
{
return
parameters
.
filter
((
item
)
=>
{
return
item
.
parameterGroup
===
"in"
;
});
},
[
parameters
]);
/** 获取输出参数数组 */
const
outParamsArr
=
useMemo
(()
=>
{
return
parameters
.
filter
((
item
)
=>
{
return
item
.
parameterGroup
===
"out"
;
});
},
[
parameters
]);
return
(
<
div
className=
{
classNames
({
[
styles
.
batchNode
]:
true
,
[
styles
.
selectedBatchBox
]:
selectedStatus
,
[
styles
.
runBatchNode
]:
executionStatus
===
"Running"
,
[
styles
.
doneBatchNode
]:
executionStatus
===
"Done"
,
[
styles
.
errorBatchNode
]:
executionStatus
===
"Failed"
,
})
}
style=
{
style
}
>
{
inParamsArr
?.
length
&&
inParamsArr
.
map
((
item
,
index
)
=>
{
return
(
<
Tooltip
title=
{
item
.
name
}
key=
{
uuid
()
}
>
<
Handle
id=
{
item
.
name
}
style=
{
{
background
:
"#fff "
,
border
:
item
.
error
?
"1px solid #FF4E4E"
:
"1px solid #D1D6DE"
,
left
:
index
*
20
+
20
,
}
}
type=
"target"
position=
{
Position
.
Top
}
/>
</
Tooltip
>
);
})
}
<
div
className=
{
classNames
({
[
styles
.
batchRotate
]:
isFlowNode
,
})
}
>
{
title
||
""
}
{
isCheck
&&
<
span
className=
{
styles
.
successDot
}
></
span
>
}
</
div
>
{
outParamsArr
?.
length
&&
outParamsArr
.
map
((
item
,
index
)
=>
{
return
(
<
Tooltip
title=
{
item
.
name
}
key=
{
uuid
()
}
>
<
Handle
id=
{
item
.
name
}
style=
{
{
background
:
"#fff "
,
border
:
"1px solid #D1D6DE"
,
left
:
index
*
20
+
20
,
}
}
type=
"source"
position=
{
Position
.
Bottom
}
/>
</
Tooltip
>
);
})
}
</
div
>
);
};
export
default
BatchNode
;
src/views/Project/components/Flow/components/FlowNode/index.module.css
0 → 100644
View file @
a1e043c4
.flowNode
{
background-color
:
#f5f6f7
;
border-radius
:
2px
;
padding
:
6px
12px
;
}
.successDot
{
display
:
inline-block
;
line-height
:
22px
;
vertical-align
:
middle
;
width
:
8px
;
height
:
8px
;
background-color
:
#0dd09b
;
border-radius
:
8px
;
margin-left
:
8px
;
}
src/views/Project/components/Flow/components/FlowNode/index.tsx
0 → 100644
View file @
a1e043c4
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-12 11:29:46
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-12 11:32:20
* @FilePath: /bkunyun/src/views/Project/components/Flow/components/FlowNode/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import
classNames
from
"classnames"
;
import
{
Handle
,
Position
}
from
"react-flow-renderer"
;
import
{
IExecutionStatus
}
from
"@/views/Project/ProjectSubmitWork/interface"
;
import
jobFail
from
"@/assets/project/jobFail.svg"
;
import
jobRun
from
"@/assets/project/jobRun.svg"
;
import
jobSue
from
"@/assets/project/jobSue.svg"
;
import
styles
from
"./index.module.css"
;
/** 自定义flow节点 */
const
FlowNode
=
(
props
:
any
)
=>
{
/** 获取imgUrl */
const
getImgUrl
=
(
type
:
IExecutionStatus
)
=>
{
if
(
type
===
"Done"
)
{
return
jobSue
;
}
if
(
type
===
"Failed"
)
{
return
jobFail
;
}
if
(
type
===
"Running"
)
{
return
jobRun
;
}
return
undefined
;
};
const
{
data
}
=
props
;
const
{
dotStatus
,
info
:
{
title
,
isCheck
,
executionStatus
},
}
=
data
;
return
(
<
div
className=
{
classNames
({
[
styles
.
flowNode
]:
true
,
})
}
>
{
dotStatus
?.
isInput
?
(
<
Handle
style=
{
{
background
:
"#C2C6CC "
,
left
:
12
}
}
type=
"target"
position=
{
Position
.
Top
}
/>
)
:
null
}
<
div
style=
{
{
display
:
"flex"
,
alignItems
:
"center"
}
}
>
{
title
||
""
}
{
isCheck
&&
<
span
className=
{
styles
.
successDot
}
></
span
>
}
{
getImgUrl
(
executionStatus
)
&&
(
<
img
style=
{
{
marginLeft
:
"6px"
}
}
src=
{
getImgUrl
(
executionStatus
)
}
alt=
""
/>
)
}
</
div
>
{
dotStatus
?.
isOutput
?
(
<
Handle
style=
{
{
background
:
"#C2C6CC "
,
left
:
12
}
}
type=
"source"
position=
{
Position
.
Bottom
}
/>
)
:
null
}
</
div
>
);
};
export
default
FlowNode
;
src/views/Project/components/Flow/index.tsx
View file @
a1e043c4
...
...
@@ -3,30 +3,18 @@ import ReactFlow, {
Background
,
useNodesState
,
useEdgesState
,
Handle
,
Position
,
ReactFlowProps
,
Node
,
applyNodeChanges
,
applyEdgeChanges
,
EdgeChange
,
NodeChange
,
Connection
,
}
from
"react-flow-renderer"
;
import
{
useCallback
,
useEffect
,
useMemo
,
useState
}
from
"react"
;
import
classNames
from
"classnames"
;
import
jobFail
from
"@/assets/project/jobFail.svg"
;
import
jobRun
from
"@/assets/project/jobRun.svg"
;
import
jobSue
from
"@/assets/project/jobSue.svg"
;
import
{
IEdge
,
IExecutionStatus
,
ITask
,
}
from
"../../ProjectSubmitWork/interface"
;
import
{
IBatchNode
,
ILine
}
from
"./interface"
;
import
{
uuid
}
from
"@/utils/util"
;
import
{
IEdge
,
IParameter
,
ITask
}
from
"../../ProjectSubmitWork/interface"
;
import
{
ILine
}
from
"./interface"
;
import
BatchNode
from
"./components/BatchNode"
;
import
FlowNode
from
"./components/FlowNode"
;
import
styles
from
"./index.module.css"
;
import
{
Tooltip
}
from
"@mui/material"
;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-22 10:15:22
...
...
@@ -51,144 +39,6 @@ interface IProps extends ReactFlowProps {
onFlowNodeClick
?:
(
val
:
string
)
=>
void
;
}
/** 获取imgUrl */
const
getImgUrl
=
(
type
:
IExecutionStatus
)
=>
{
if
(
type
===
"Done"
)
{
return
jobSue
;
}
if
(
type
===
"Failed"
)
{
return
jobFail
;
}
if
(
type
===
"Running"
)
{
return
jobRun
;
}
return
undefined
;
};
/** 自定义batch节点 */
const
BatchNode
=
(
props
:
IBatchNode
)
=>
{
const
{
data
}
=
props
;
const
{
dotStatus
,
style
,
isFlowNode
,
selectedStatus
,
info
:
{
title
,
isCheck
,
executionStatus
,
parameters
},
}
=
data
;
/** 获取输入参数数组 */
const
inParamsArr
=
useMemo
(()
=>
{
return
parameters
.
filter
((
item
)
=>
{
return
item
.
parameterGroup
===
"in"
;
});
},
[
parameters
]);
/** 获取输出参数数组 */
const
outParamsArr
=
useMemo
(()
=>
{
return
parameters
.
filter
((
item
)
=>
{
return
item
.
parameterGroup
===
"out"
;
});
},
[
parameters
]);
return
(
<
div
className=
{
classNames
({
[
styles
.
batchNode
]:
true
,
[
styles
.
selectedBatchBox
]:
selectedStatus
,
[
styles
.
runBatchNode
]:
executionStatus
===
"Running"
,
[
styles
.
doneBatchNode
]:
executionStatus
===
"Done"
,
[
styles
.
errorBatchNode
]:
executionStatus
===
"Failed"
,
})
}
style=
{
style
}
>
{
inParamsArr
?.
length
&&
inParamsArr
.
map
((
item
,
index
)
=>
{
return
(
<
Tooltip
title=
{
item
.
name
}
>
<
Handle
// title=
{
item
.
name
}
style=
{
{
background
:
"#fff "
,
border
:
"1px solid #D1D6DE"
,
left
:
index
*
20
+
20
,
}
}
type=
"target"
position=
{
Position
.
Top
}
/>
</
Tooltip
>
);
})
}
<
div
className=
{
classNames
({
[
styles
.
batchRotate
]:
isFlowNode
,
})
}
>
{
title
||
""
}
{
isCheck
&&
<
span
className=
{
styles
.
successDot
}
></
span
>
}
</
div
>
{
outParamsArr
?.
length
&&
outParamsArr
.
map
((
item
,
index
)
=>
{
return
(
<
Tooltip
title=
{
item
.
name
}
>
<
Handle
style=
{
{
background
:
"#fff "
,
border
:
"1px solid #D1D6DE"
,
left
:
index
*
20
+
20
,
}
}
type=
"source"
position=
{
Position
.
Bottom
}
/>
</
Tooltip
>
);
})
}
</
div
>
);
};
/** 自定义flow节点 */
const
FlowNode
=
(
props
:
any
)
=>
{
const
{
data
}
=
props
;
const
{
dotStatus
,
info
:
{
title
,
isCheck
,
executionStatus
},
}
=
data
;
return
(
<
div
className=
{
classNames
({
[
styles
.
flowNode
]:
true
,
})
}
>
{
dotStatus
?.
isInput
?
(
<
Handle
style=
{
{
background
:
"#C2C6CC "
,
left
:
12
}
}
type=
"target"
position=
{
Position
.
Top
}
/>
)
:
null
}
<
div
style=
{
{
display
:
"flex"
,
alignItems
:
"center"
}
}
>
{
title
||
""
}
{
isCheck
&&
<
span
className=
{
styles
.
successDot
}
></
span
>
}
{
getImgUrl
(
executionStatus
)
&&
(
<
img
style=
{
{
marginLeft
:
"6px"
}
}
src=
{
getImgUrl
(
executionStatus
)
}
alt=
""
/>
)
}
</
div
>
{
dotStatus
?.
isOutput
?
(
<
Handle
style=
{
{
background
:
"#C2C6CC "
,
left
:
12
}
}
type=
"source"
position=
{
Position
.
Bottom
}
id=
"a"
/>
)
:
null
}
</
div
>
);
};
const
Flow
=
(
props
:
IProps
)
=>
{
const
{
tasks
,
...
...
@@ -309,7 +159,6 @@ const Flow = (props: IProps) => {
type
:
item
.
type
===
"BATCH"
?
"batchNode"
:
"flowNode"
,
/** 每一项的数据 */
data
:
{
// label: item.title || "",
info
:
item
,
...(
item
.
type
===
"BATCH"
?
{
...
...
@@ -321,10 +170,6 @@ const Flow = (props: IProps) => {
:
inSideNodeId
===
item
.
id
,
}
:
{}),
// /** 是否选中 */
// isCheck: item.isCheck,
/** 运行状态 */
// executionStatus: item.executionStatus,
/** 输入输出圆点状态 */
dotStatus
:
nodesInputAndOutputStatus
(
item
.
id
),
...
...
@@ -374,13 +219,11 @@ const Flow = (props: IProps) => {
val
.
push
(
newLine
);
},
[]);
});
return
val
.
map
((
item
:
ILine
)
=>
{
const
a
=
val
.
map
((
item
:
ILine
)
=>
{
const
newSelectId
=
selectedNodeId
?
selectedNodeId
:
inSideNodeId
;
return
{
id
:
item
.
id
,
source
:
item
.
source
,
target
:
item
.
target
,
type
:
"smoothstep"
,
...
item
,
// type: "smoothstep",
...(
item
?.
batchId
===
newSelectId
?
{
style
:
{
stroke
:
"#1370FF"
},
animated
:
true
}
:
{}),
...
...
@@ -389,6 +232,7 @@ const Flow = (props: IProps) => {
label
:
item
.
label
?
`(
${
item
.
label
}
)`
:
""
,
};
});
return
a
;
},
[
inSideNodeId
,
selectedNodeId
,
tasks
]);
/** flowNode点击事件 */
...
...
@@ -421,9 +265,9 @@ const Flow = (props: IProps) => {
};
/** node节点 */
const
[
nodes
,
setNodes
]
=
useNodesState
(
initialNodes
);
const
[
nodes
,
setNodes
,
onNodesChange
]
=
useNodesState
(
initialNodes
);
/** 连线数组 */
const
[
edges
,
setEdges
]
=
useEdgesState
(
initialEdges
);
const
[
edges
,
setEdges
,
onEdgesChange
]
=
useEdgesState
(
initialEdges
);
useEffect
(()
=>
{
setEdges
(
initialEdges
);
...
...
@@ -433,20 +277,69 @@ const Flow = (props: IProps) => {
setNodes
(
initialNodes
);
},
[
initialNodes
,
setNodes
]);
const
onNodesChange
=
useCallback
(
(
changes
:
NodeChange
[])
=>
{
console
.
log
(
changes
,
"1111"
);
setNodes
((
ns
)
=>
applyNodeChanges
(
changes
,
ns
));
/** 节点拖动停止 */
const
onNodeDragStop
=
useCallback
(
(
event
:
React
.
MouseEvent
,
node
:
Node
)
=>
{
const
newVal
=
(
tasks
?.
length
&&
tasks
.
map
((
item
)
=>
{
if
(
item
.
id
===
node
.
id
)
{
return
{
...
item
,
position
:
node
.
position
,
};
}
else
{
return
item
;
}
}))
||
[];
setTasks
&&
setTasks
(
newVal
);
},
[
setTasks
,
tasks
]
);
const
connectModifyParameters
=
useCallback
(
(
parameters
:
IParameter
[],
edgeItem
:
Connection
)
=>
{
return
parameters
.
map
((
item
)
=>
{
if
(
item
.
name
===
edgeItem
.
targetHandle
)
{
return
{
...
item
,
isLine
:
true
};
}
else
{
return
item
;
}
});
},
[
setNodes
]
[]
);
const
onEdgesChange
=
useCallback
(
(
changes
:
EdgeChange
[])
=>
{
console
.
log
(
changes
,
"222222"
);
setEdges
((
es
)
=>
applyEdgeChanges
(
changes
,
es
));
const
onConnect
=
useCallback
(
(
val
:
Connection
)
=>
{
const
newVal
=
(
tasks
?.
length
&&
tasks
?.
map
((
item
)
=>
{
if
(
item
.
id
===
val
.
source
)
{
return
{
...
item
,
edges
:
[
...
item
.
edges
,
{
...
val
,
id
:
uuid
(),
},
],
};
}
else
if
(
item
.
id
===
val
.
target
)
{
return
{
...
item
,
parameters
:
connectModifyParameters
(
item
.
parameters
,
val
),
};
}
else
{
return
item
;
}
}))
||
[];
setTasks
&&
setTasks
(
newVal
as
ITask
[]);
},
[
setEdge
s
]
[
connectModifyParameters
,
setTasks
,
task
s
]
);
return
(
...
...
@@ -456,8 +349,8 @@ const Flow = (props: IProps) => {
fitView=
{
flowType
===
"default"
?
true
:
false
}
onNodesChange=
{
onNodesChange
}
onEdgesChange=
{
onEdgesChange
}
deleteKeyCode=
{
[
"13"
]
}
//
onConnect={onConnect}
onNodeDragStop=
{
onNodeDragStop
}
onConnect=
{
onConnect
}
// proOptions={{ hideAttribution: true, account: "" }}
nodeTypes=
{
nodeTypes
}
onPaneClick=
{
handlePaneClick
}
...
...
src/views/Project/components/Flow/interface.ts
View file @
a1e043c4
...
...
@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-23 11:00:29
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-1
1 15:24:53
* @LastEditTime: 2022-07-1
2 00:26:48
* @FilePath: /bkunyun/src/views/Project/components/Flow/interface.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
...
...
@@ -13,10 +13,12 @@ import { ITask } from "../../ProjectSubmitWork/interface";
/** 线的参数 */
export
interface
ILine
{
id
:
string
,
label
:
string
,
label
?
:
string
,
batchId
?:
string
,
source
:
string
,
target
:
string
,
sourceHandle
:
string
,
targetHandle
:
string
,
}
export
interface
IDotStatus
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment