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
91794fa1
Commit
91794fa1
authored
Jul 06, 2022
by
chenshouchao
Browse files
Options
Browse Files
Download
Plain Diff
fix: 解决冲突
parents
f1da6197
2cfbf2e2
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1144 additions
and
999 deletions
+1144
-999
index.tsx
src/views/Project/ProjectJobDetail/index.tsx
+490
-493
index.tsx
...iews/Project/ProjectWorkbench/workbenchTemplate/index.tsx
+229
-223
interface.tsx
.../Project/ProjectWorkbench/workbenchTemplate/interface.tsx
+13
-0
index.tsx
src/views/Project/components/Flow/index.tsx
+300
-279
index.module.css
...ews/WorkFlowEdit/components/OperatorList/index.module.css
+35
-0
index.tsx
src/views/WorkFlowEdit/components/OperatorList/index.tsx
+60
-0
interface.ts
src/views/WorkFlowEdit/components/OperatorList/interface.ts
+12
-0
index.module.css
src/views/WorkFlowEdit/index.module.css
+2
-2
index.tsx
src/views/WorkFlowEdit/index.tsx
+3
-2
No files found.
src/views/Project/ProjectJobDetail/index.tsx
View file @
91794fa1
...
...
@@ -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-06 1
1:01:44
* @LastEditTime: 2022-07-06 1
7:05:13
* @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
...
...
@@ -39,39 +39,39 @@ import { storageUnitFromB } from "@/utils/util";
import
styles
from
"./index.module.css"
;
const
stateMap
=
{
RUNNING
:
"正在运行"
,
ABORTED
:
"运行终止"
,
FAILED
:
"运行失败"
,
SUCCEEDED
:
"运行成功"
,
RUNNING
:
"正在运行"
,
ABORTED
:
"运行终止"
,
FAILED
:
"运行失败"
,
SUCCEEDED
:
"运行成功"
,
};
const
statusMap
=
{
Done
:
"运行完成"
,
Running
:
"正在运行"
,
Failed
:
"运行失败"
,
Pending
:
"等待运行"
,
Done
:
"运行完成"
,
Running
:
"正在运行"
,
Failed
:
"运行失败"
,
Pending
:
"等待运行"
,
};
type
IStatus
=
"Done"
|
"Running"
|
"Failed"
|
"Pending"
;
let
randerOutputs
:
Array
<
any
>
=
[];
const
ProjectSubmitWork
=
observer
(()
=>
{
const
{
currentProjectStore
}
=
useStores
();
const
fileToken
=
toJS
(
currentProjectStore
.
currentProjectInfo
.
filetoken
);
const
projectId
=
toJS
(
currentProjectStore
.
currentProjectInfo
.
id
);
const
[
workFlowJobInfo
,
setWorkFlowJobInfo
]
=
useState
<
ITaskInfo
>
();
const
[
patchInfo
,
setPatchInfo
]
=
useState
<
any
>
();
const
[
activePatchId
,
setActivePatchId
]
=
useState
<
string
>
(
""
);
const
[
overviewActive
,
setOverviewActive
]
=
useState
(
true
);
const
[
activeFlowIndex
,
setActiveFlowIndex
]
=
useState
<
number
>
(
0
);
const
[
showOptions
,
setShowOptions
]
=
useState
<
boolean
>
(
false
);
const
[
randerOutputs1
,
setRanderOutputs
]
=
useState
<
Array
<
any
>>
([]);
const
location
:
any
=
useLocation
();
const
navigate
=
useNavigate
();
const
message
=
useMessage
();
const
[
fullScreenShow
,
setFullScreenShow
]
=
useState
<
boolean
>
(
false
);
const
{
currentProjectStore
}
=
useStores
();
const
fileToken
=
toJS
(
currentProjectStore
.
currentProjectInfo
.
filetoken
);
const
projectId
=
toJS
(
currentProjectStore
.
currentProjectInfo
.
id
);
const
[
workFlowJobInfo
,
setWorkFlowJobInfo
]
=
useState
<
ITaskInfo
>
();
const
[
patchInfo
,
setPatchInfo
]
=
useState
<
any
>
();
const
[
activePatchId
,
setActivePatchId
]
=
useState
<
string
>
(
""
);
const
[
overviewActive
,
setOverviewActive
]
=
useState
(
true
);
const
[
activeFlowIndex
,
setActiveFlowIndex
]
=
useState
<
number
>
(
0
);
const
[
showOptions
,
setShowOptions
]
=
useState
<
boolean
>
(
false
);
const
[
randerOutputs1
,
setRanderOutputs
]
=
useState
<
Array
<
any
>>
([]);
const
location
:
any
=
useLocation
();
const
navigate
=
useNavigate
();
const
message
=
useMessage
();
const
[
fullScreenShow
,
setFullScreenShow
]
=
useState
<
boolean
>
(
false
);
const
{
name
,
state
}
=
workFlowJobInfo
||
{};
const
{
name
,
state
}
=
workFlowJobInfo
||
{};
/** 获取模版数据 */
const
{
run
}
=
useMyRequest
(
fetchWorkFlowJob
,
{
...
...
@@ -90,14 +90,13 @@ const ProjectSubmitWork = observer(() => {
});
},
[
location
?.
state
,
run
]);
const
{
run
:
getworkFlowTaskInfoRun
}
=
useMyRequest
(
getworkFlowTaskInfo
,
{
onSuccess
:
(
res
)
=>
{
setPatchInfo
(
res
.
data
);
},
});
const
{
run
:
getworkFlowTaskInfoRun
}
=
useMyRequest
(
getworkFlowTaskInfo
,
{
onSuccess
:
(
res
)
=>
{
setPatchInfo
(
res
.
data
);
},
});
const
goToProjectData
=
(
path
:
string
)
=>
{
console
.
log
(
path
);
path
=
path
.
slice
(
13
);
if
(
path
)
{
navigate
(
`/product/cadd/projectData`
,
{
...
...
@@ -126,393 +125,391 @@ const ProjectSubmitWork = observer(() => {
});
},
[
navigate
]);
const
outputPathTransform
=
(
path
:
string
)
=>
{
path
=
path
.
slice
(
13
);
return
`ProjectData
${
path
}
`
;
};
const
outputPathTransform
=
(
path
:
string
)
=>
{
path
=
path
.
slice
(
13
);
return
`ProjectData
${
path
}
`
;
};
const
getOutouts
=
(
outputs
:
any
)
=>
{
if
(
outputs
)
{
let
result
=
Object
.
keys
(
outputs
);
let
arr
=
result
.
map
((
item
)
=>
{
let
type
=
"file"
;
if
(
outputs
[
item
].
indexOf
(
"dataset"
)
!==
-
1
)
{
type
=
"dataset"
;
}
return
{
name
:
item
,
type
,
path
:
outputs
[
item
],
size
:
0
,
};
});
arr
.
forEach
(
async
(
item
,
index
)
=>
{
if
(
item
.
type
===
"dataset"
)
{
await
getDataSetSize
(
item
,
index
);
}
else
{
await
getFileSize
(
item
,
index
);
}
});
randerOutputs
=
arr
;
setRanderOutputs
([...
randerOutputs
]);
}
else
{
randerOutputs
=
[];
setRanderOutputs
([]);
}
};
const
getOutouts
=
(
outputs
:
any
)
=>
{
if
(
outputs
)
{
let
result
=
Object
.
keys
(
outputs
);
let
arr
=
result
.
map
((
item
)
=>
{
let
type
=
"file"
;
if
(
outputs
[
item
].
indexOf
(
"dataset"
)
!==
-
1
)
{
type
=
"dataset"
;
}
return
{
name
:
item
,
type
,
path
:
outputs
[
item
],
size
:
0
,
};
});
arr
.
forEach
(
async
(
item
,
index
)
=>
{
if
(
item
.
type
===
"dataset"
)
{
await
getDataSetSize
(
item
,
index
);
}
else
{
await
getFileSize
(
item
,
index
);
}
});
randerOutputs
=
arr
;
setRanderOutputs
([...
randerOutputs
]);
}
else
{
randerOutputs
=
[];
setRanderOutputs
([]);
}
};
const
getDataSetSize
=
async
(
item
:
any
,
index
:
number
)
=>
{
let
path
=
item
.
path
.
slice
(
13
);
const
lastIndex
=
path
.
lastIndexOf
(
"/"
);
if
(
lastIndex
===
-
1
)
{
path
=
"/"
;
}
else
{
path
=
path
.
slice
(
0
,
lastIndex
+
1
);
}
const
res
=
await
getDataFind
({
projectId
:
projectId
as
string
,
path
:
path
,
});
res
.
data
.
forEach
((
item1
:
any
)
=>
{
if
(
item1
.
name
===
item
.
path
.
slice
(
item
.
path
.
lastIndexOf
(
"/"
)
+
1
))
{
randerOutputs
[
index
].
size
=
`
${
item1
.
size
}
条`
;
setRanderOutputs
([...
randerOutputs
]);
}
});
};
const
getDataSetSize
=
async
(
item
:
any
,
index
:
number
)
=>
{
let
path
=
item
.
path
.
slice
(
13
);
const
lastIndex
=
path
.
lastIndexOf
(
"/"
);
if
(
lastIndex
===
-
1
)
{
path
=
"/"
;
}
else
{
path
=
path
.
slice
(
0
,
lastIndex
+
1
);
}
const
res
=
await
getDataFind
({
projectId
:
projectId
as
string
,
path
:
path
,
});
res
.
data
.
forEach
((
item1
:
any
)
=>
{
if
(
item1
.
name
===
item
.
path
.
slice
(
item
.
path
.
lastIndexOf
(
"/"
)
+
1
))
{
randerOutputs
[
index
].
size
=
`
${
item1
.
size
}
条`
;
setRanderOutputs
([...
randerOutputs
]);
}
});
};
const
getFileSize
=
(
item
:
any
,
index
:
number
)
=>
{
let
path
=
item
.
path
.
slice
(
13
);
const
lastIndex
=
path
.
lastIndexOf
(
"/"
);
if
(
lastIndex
===
-
1
)
{
path
=
"/"
;
}
else
{
path
=
path
.
slice
(
0
,
lastIndex
+
1
);
}
CloudEController
.
JobOutFileList
(
path
,
fileToken
as
string
,
projectId
as
string
,
false
)?.
then
((
res
)
=>
{
if
(
Array
.
isArray
(
res
.
data
))
{
res
.
data
.
forEach
((
item1
)
=>
{
if
(
item1
.
name
===
item
.
path
.
slice
(
item
.
path
.
lastIndexOf
(
"/"
)
+
1
))
{
randerOutputs
[
index
].
size
=
`
${
item1
.
size
?
storageUnitFromB
(
Number
(
item1
.
size
))
:
"-"
}
`
;
setRanderOutputs
([...
randerOutputs
]);
}
});
}
});
};
const
getFileSize
=
(
item
:
any
,
index
:
number
)
=>
{
let
path
=
item
.
path
.
slice
(
13
);
const
lastIndex
=
path
.
lastIndexOf
(
"/"
);
if
(
lastIndex
===
-
1
)
{
path
=
"/"
;
}
else
{
path
=
path
.
slice
(
0
,
lastIndex
+
1
);
}
CloudEController
.
JobOutFileList
(
path
,
fileToken
as
string
,
projectId
as
string
,
false
)?.
then
((
res
)
=>
{
if
(
Array
.
isArray
(
res
.
data
))
{
res
.
data
.
forEach
((
item1
)
=>
{
if
(
item1
.
name
===
item
.
path
.
slice
(
item
.
path
.
lastIndexOf
(
"/"
)
+
1
))
{
randerOutputs
[
index
].
size
=
`
${
item1
.
size
?
storageUnitFromB
(
Number
(
item1
.
size
))
:
"-"
}
`
;
setRanderOutputs
([...
randerOutputs
]);
}
});
}
});
};
// 取消作业
const
{
run
:
cancelWorkJob
}
=
useMyRequest
(
cancelWorkflowJob
,
{
onSuccess
:
(
res
:
IResponse
<
boolean
>
)
=>
{
const
{
errorCode
}
=
res
;
if
(
errorCode
===
0
)
{
message
.
success
(
"操作成功!"
);
}
onBack
();
},
});
// 取消作业
const
{
run
:
cancelWorkJob
}
=
useMyRequest
(
cancelWorkflowJob
,
{
onSuccess
:
(
res
:
IResponse
<
boolean
>
)
=>
{
const
{
errorCode
}
=
res
;
if
(
errorCode
===
0
)
{
message
.
success
(
"操作成功!"
);
}
onBack
();
},
});
// 取消作业
const
{
run
:
deleteWorkJob
}
=
useMyRequest
(
deleteWorkflowJob
,
{
onSuccess
:
(
res
:
IResponse
<
boolean
>
)
=>
{
const
{
errorCode
}
=
res
;
if
(
errorCode
===
0
)
{
message
.
success
(
"操作成功!"
);
}
onBack
();
},
});
// 取消作业
const
{
run
:
deleteWorkJob
}
=
useMyRequest
(
deleteWorkflowJob
,
{
onSuccess
:
(
res
:
IResponse
<
boolean
>
)
=>
{
const
{
errorCode
}
=
res
;
if
(
errorCode
===
0
)
{
message
.
success
(
"操作成功!"
);
}
onBack
();
},
});
const
handleBatch
=
(
id
:
string
)
=>
{
setActivePatchId
(
id
);
if
(
id
)
{
setActiveFlowIndex
(
0
);
getworkFlowTaskInfoRun
({
jobId
:
workFlowJobInfo
?.
id
as
string
,
taskId
:
id
,
});
}
};
const
handleBatch
=
(
id
:
string
)
=>
{
setActivePatchId
(
id
);
if
(
id
)
{
setActiveFlowIndex
(
0
);
getworkFlowTaskInfoRun
({
jobId
:
workFlowJobInfo
?.
id
as
string
,
taskId
:
id
,
});
}
};
const
randerParameters
=
useMemo
(()
=>
{
if
(
patchInfo
?.
children
)
{
if
(
patchInfo
.
children
.
length
>
0
)
{
return
patchInfo
.
children
[
activeFlowIndex
].
parameters
;
}
else
{
return
patchInfo
?.
parameters
;
}
}
else
{
return
patchInfo
?.
parameters
;
}
},
[
activeFlowIndex
,
patchInfo
]);
const
randerParameters
=
useMemo
(()
=>
{
if
(
patchInfo
?.
children
)
{
if
(
patchInfo
.
children
.
length
>
0
)
{
return
patchInfo
.
children
[
activeFlowIndex
].
parameters
;
}
else
{
return
patchInfo
?.
parameters
;
}
}
else
{
return
patchInfo
?.
parameters
;
}
},
[
activeFlowIndex
,
patchInfo
]);
const
handleParams
=
()
=>
{
setOverviewActive
(
false
);
setShowOptions
(
!
showOptions
);
};
const
handleParams
=
()
=>
{
setOverviewActive
(
false
);
setShowOptions
(
!
showOptions
);
};
const
handleDownLoad
=
(
path
:
string
)
=>
{
if
(
path
.
indexOf
(
"/home/cloudam"
)
!==
-
1
)
{
path
=
path
.
slice
(
13
);
}
CloudEController
.
JobFileDownload
(
path
,
fileToken
as
string
,
projectId
as
string
);
};
const
handleDownLoad
=
(
path
:
string
)
=>
{
if
(
path
.
indexOf
(
"/home/cloudam"
)
!==
-
1
)
{
path
=
path
.
slice
(
13
);
}
CloudEController
.
JobFileDownload
(
path
,
fileToken
as
string
,
projectId
as
string
);
};
/** 终止任务 */
const
onStopJob
=
useCallback
(()
=>
{
cancelWorkJob
({
jobid
:
workFlowJobInfo
?.
id
||
""
,
});
},
[
cancelWorkJob
,
workFlowJobInfo
?.
id
]);
/** 终止任务 */
const
onStopJob
=
useCallback
(()
=>
{
cancelWorkJob
({
jobid
:
workFlowJobInfo
?.
id
||
""
,
});
},
[
cancelWorkJob
,
workFlowJobInfo
?.
id
]);
/** 删除任务 */
const
onDeleteJob
=
useCallback
(()
=>
{
deleteWorkJob
({
id
:
workFlowJobInfo
?.
id
||
""
,
});
},
[
deleteWorkJob
,
workFlowJobInfo
?.
id
]);
/** 删除任务 */
const
onDeleteJob
=
useCallback
(()
=>
{
deleteWorkJob
({
id
:
workFlowJobInfo
?.
id
||
""
,
});
},
[
deleteWorkJob
,
workFlowJobInfo
?.
id
]);
return
(
<
div
className=
{
styles
.
swBox
}
>
{
fullScreenShow
?
null
:
(
<
div
className=
{
styles
.
swHeader
}
>
<
div
className=
{
styles
.
swHeaderLeft
}
>
<
IconButton
color=
"primary"
onClick=
{
onBack
}
aria
-
label=
"upload picture"
component=
"span"
size=
"small"
>
<
ArrowBackIosNewIcon
sx=
{
{
color
:
"rgba(194, 198, 204, 1)"
,
width
:
"12px"
,
height
:
"12px"
,
}
}
/>
</
IconButton
>
return
(
<
div
className=
{
styles
.
swBox
}
>
{
fullScreenShow
?
null
:
(
<
div
className=
{
styles
.
swHeader
}
>
<
div
className=
{
styles
.
swHeaderLeft
}
>
<
IconButton
color=
"primary"
onClick=
{
onBack
}
aria
-
label=
"upload picture"
component=
"span"
size=
"small"
>
<
ArrowBackIosNewIcon
sx=
{
{
color
:
"rgba(194, 198, 204, 1)"
,
width
:
"12px"
,
height
:
"12px"
,
}
}
/>
</
IconButton
>
<
div
className=
{
styles
.
swTemplateTitle
}
>
{
name
}
</
div
>
</
div
>
<
div
className=
{
styles
.
swHeaderRight
}
>
<
MyPopconfirm
title=
{
state
===
"RUNNING"
?
"正在运行的任务终止后将无法重新运行,确认继续吗?"
:
"任务被删除后将无法恢复,确认继续吗?"
}
onConfirm=
{
()
=>
{
state
===
"RUNNING"
?
onStopJob
()
:
onDeleteJob
();
}
}
>
<
ButtonComponent
text=
{
state
===
"RUNNING"
?
"终止"
:
"删除"
}
variant=
"outlined"
color=
"secondary"
// click=
{
onStopJob
}
></
ButtonComponent
>
</
MyPopconfirm
>
</
div
>
</
div
>
)
}
<
div
className=
{
styles
.
swContent
}
>
{
fullScreenShow
?
null
:
(
<
div
className=
{
styles
.
swFormBox
}
>
{
!
activePatchId
&&
(
<
div
className=
{
styles
.
taskInfo
}
>
<
div
className=
{
styles
.
title
}
>
任务结果
</
div
>
{
workFlowJobInfo
?.
outputs
&&
(
<
div
className=
{
styles
.
taskResults
}
>
{
randerOutputs1
.
map
((
item
,
index
)
=>
{
return
(
<
div
key=
{
index
}
className=
{
styles
.
outputLi
}
>
<
MyPopconfirm
title=
"即将跳转至项目数据内该任务的结果目录,确认继续吗?"
onConfirm=
{
()
=>
goToProjectData
(
getFolderPath
(
item
.
path
))
}
>
<
div
className=
{
styles
.
outputLiLeft
}
>
<
img
className=
{
styles
.
outputLiLeftImg
}
src=
{
item
.
type
===
"file"
?
fileIcon
:
dataSetIcon
}
alt=
""
/>
{
item
.
name
}
</
div
>
</
MyPopconfirm
>
<
span
className=
{
styles
.
outputLiRight
}
>
{
item
.
size
}
</
span
>
</
div
>
);
})
}
</
div
>
)
}
{
!
workFlowJobInfo
?.
outputs
&&
(
<
div
className=
{
styles
.
notResults
}
>
暂无结果文件
</
div
>
)
}
<
div
className=
{
styles
.
title
}
>
任务信息
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
任务名称
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
title=
{
name
}
>
{
name
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
任务ID
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
title=
{
workFlowJobInfo
?.
id
}
>
{
workFlowJobInfo
?.
id
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
输出路径
</
div
>
<
div
className=
{
classNames
({
[
styles
.
taskInfoValue
]:
true
,
[
styles
.
taskInfoValueClick
]:
true
,
})
}
onClick=
{
()
=>
goToProjectData
(
workFlowJobInfo
?.
outputPath
as
string
)
}
>
{
workFlowJobInfo
?.
outputPath
?
outputPathTransform
(
workFlowJobInfo
?.
outputPath
)
:
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
运行状态
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
state
===
"SUCCEEDED"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobSue
}
alt=
""
/>
)
}
{
state
===
"RUNNING"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobRun
}
alt=
""
/>
)
}
{
state
===
"ABORTED"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobStop
}
alt=
""
/>
)
}
{
state
===
"FAILED"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobFail
}
alt=
""
/>
)
}
{
state
?
stateMap
[
state
]
:
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
源模板
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
specTitle
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
源模板版本
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
specVersion
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
花费(元)
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
jobCost
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
创建人
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
creator
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
创建时间
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
createTime
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
运行时间
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
costTime
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
日志文件
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
logPath
&&
(
<
span
className=
{
styles
.
taskInfoDownload
}
onClick=
{
()
=>
handleDownLoad
(
workFlowJobInfo
?.
logPath
)
}
>
下载
</
span
>
)
}
{
!
workFlowJobInfo
?.
logPath
&&
"-"
}
</
div
>
</
div
>
</
div
>
)
}
{
activePatchId
&&
(
<
div
className=
{
styles
.
suanziInfo
}
>
<
div
className=
{
styles
.
title
}
>
{
patchInfo
?.
title
}
</
div
>
<
div
className=
{
styles
.
tabs
}
>
<
div
className=
{
classNames
({
[
styles
.
tabLi
]:
true
,
[
styles
.
tabLiAcitve
]:
overviewActive
,
})
}
onClick=
{
()
=>
setOverviewActive
(
true
)
}
>
概览
</
div
>
<
div
className=
{
classNames
({
[
styles
.
tabLi
]:
true
,
[
styles
.
tabLiAcitve
]:
!
overviewActive
,
})
}
// onClick=
{()
=
>
setOverviewActive(false)}
onClick=
{
()
=>
handleParams
()
}
>
{
patchInfo
?.
children
.
length
>
0
?
patchInfo
?.
children
[
activeFlowIndex
].
title
:
patchInfo
?.
title
}
{
showOptions
&&
patchInfo
?.
children
.
length
>
0
&&
(
<
div
className=
{
styles
.
options
}
>
{
patchInfo
?.
children
.
map
((
item
:
any
,
index
:
number
)
=>
{
return
(
<
div
<
div
className=
{
styles
.
swTemplateTitle
}
>
{
name
}
</
div
>
</
div
>
<
div
className=
{
styles
.
swHeaderRight
}
>
<
MyPopconfirm
title=
{
state
===
"RUNNING"
?
"正在运行的任务终止后将无法重新运行,确认继续吗?"
:
"任务被删除后将无法恢复,确认继续吗?"
}
onConfirm=
{
()
=>
{
state
===
"RUNNING"
?
onStopJob
()
:
onDeleteJob
();
}
}
>
<
ButtonComponent
text=
{
state
===
"RUNNING"
?
"终止"
:
"删除"
}
variant=
"outlined"
color=
"secondary"
// click=
{
onStopJob
}
></
ButtonComponent
>
</
MyPopconfirm
>
</
div
>
</
div
>
)
}
<
div
className=
{
styles
.
swContent
}
>
{
fullScreenShow
?
null
:
(
<
div
className=
{
styles
.
swFormBox
}
>
{
!
activePatchId
&&
(
<
div
className=
{
styles
.
taskInfo
}
>
<
div
className=
{
styles
.
title
}
>
任务结果
</
div
>
{
workFlowJobInfo
?.
outputs
&&
(
<
div
className=
{
styles
.
taskResults
}
>
{
randerOutputs1
.
map
((
item
,
index
)
=>
{
return
(
<
div
key=
{
index
}
className=
{
styles
.
outputLi
}
>
<
MyPopconfirm
title=
"即将跳转至项目数据内该任务的结果目录,确认继续吗?"
onConfirm=
{
()
=>
goToProjectData
(
getFolderPath
(
item
.
path
))
}
>
<
div
className=
{
styles
.
outputLiLeft
}
>
<
img
className=
{
styles
.
outputLiLeftImg
}
src=
{
item
.
type
===
"file"
?
fileIcon
:
dataSetIcon
}
alt=
""
/>
{
item
.
name
}
</
div
>
</
MyPopconfirm
>
<
span
className=
{
styles
.
outputLiRight
}
>
{
item
.
size
}
</
span
>
</
div
>
);
})
}
</
div
>
)
}
{
!
workFlowJobInfo
?.
outputs
&&
(
<
div
className=
{
styles
.
notResults
}
>
暂无结果文件
</
div
>
)
}
<
div
className=
{
styles
.
title
}
>
任务信息
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
任务名称
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
title=
{
name
}
>
{
name
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
任务ID
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
title=
{
workFlowJobInfo
?.
id
}
>
{
workFlowJobInfo
?.
id
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
输出路径
</
div
>
<
div
className=
{
classNames
({
[
styles
.
taskInfoValue
]:
true
,
[
styles
.
taskInfoValueClick
]:
true
,
})
}
onClick=
{
()
=>
goToProjectData
(
workFlowJobInfo
?.
outputPath
as
string
)
}
>
{
workFlowJobInfo
?.
outputPath
?
outputPathTransform
(
workFlowJobInfo
?.
outputPath
)
:
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
运行状态
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
state
===
"SUCCEEDED"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobSue
}
alt=
""
/>
)
}
{
state
===
"RUNNING"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobRun
}
alt=
""
/>
)
}
{
state
===
"ABORTED"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobStop
}
alt=
""
/>
)
}
{
state
===
"FAILED"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobFail
}
alt=
""
/>
)
}
{
state
?
stateMap
[
state
]
:
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
源模板
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
specTitle
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
源模板版本
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
specVersion
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
花费(元)
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
jobCost
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
创建人
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
creator
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
创建时间
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
createTime
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
运行时间
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
costTime
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
日志文件
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
workFlowJobInfo
?.
logPath
&&
(
<
span
className=
{
styles
.
taskInfoDownload
}
onClick=
{
()
=>
handleDownLoad
(
workFlowJobInfo
?.
logPath
)
}
>
下载
</
span
>
)
}
{
!
workFlowJobInfo
?.
logPath
&&
"-"
}
</
div
>
</
div
>
</
div
>
)
}
{
activePatchId
&&
(
<
div
className=
{
styles
.
suanziInfo
}
>
<
div
className=
{
styles
.
title
}
>
{
patchInfo
?.
title
}
</
div
>
<
div
className=
{
styles
.
tabs
}
>
<
div
className=
{
classNames
({
[
styles
.
tabLi
]:
true
,
[
styles
.
tabLiAcitve
]:
overviewActive
,
})
}
onClick=
{
()
=>
setOverviewActive
(
true
)
}
>
概览
</
div
>
<
div
className=
{
classNames
({
[
styles
.
tabLi
]:
true
,
[
styles
.
tabLiAcitve
]:
!
overviewActive
,
})
}
// onClick=
{()
=
>
setOverviewActive(false)}
onClick=
{
()
=>
handleParams
()
}
>
{
patchInfo
?.
children
.
length
>
0
?
patchInfo
?.
children
[
activeFlowIndex
].
title
:
patchInfo
?.
title
}
{
showOptions
&&
patchInfo
?.
children
.
length
>
0
&&
(
<
div
className=
{
styles
.
options
}
>
{
patchInfo
?.
children
.
map
((
item
:
any
,
index
:
number
)
=>
{
return
(
<
div
key=
{
index
}
className=
{
classNames
({
[
styles
.
option
]:
true
,
...
...
@@ -523,95 +520,95 @@ const ProjectSubmitWork = observer(() => {
>
{
item
.
title
}
</
div
>
);
})
}
</
div
>
)
}
</
div
>
</
div
>
{
overviewActive
&&
(
<
div
className=
{
styles
.
overview
}
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
描述
</
div
>
<
div
className=
{
classNames
({
[
styles
.
taskInfoValue
]:
true
,
[
styles
.
taskInfoValueShowAll
]:
true
,
})
}
>
{
patchInfo
?.
description
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
算子版本
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
patchInfo
?.
creator
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
算子状态
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
patchInfo
?.
status
===
"Done"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobSue
}
alt=
""
/>
)
}
{
patchInfo
?.
status
===
"Running"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobRun
}
alt=
""
/>
)
}
{
patchInfo
?.
status
===
"Failed"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobFail
}
alt=
""
/>
)
}
{
statusMap
[
patchInfo
?.
status
as
IStatus
]
}
</
div
>
</
div
>
</
div
>
)
}
{
!
overviewActive
&&
(
<
div
className=
{
styles
.
params
}
>
{
randerParameters
.
map
((
parameter
:
any
)
=>
{
return
(
<
div
className=
{
styles
.
taskInfoLi
}
key=
{
parameter
.
name
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
{
parameter
.
name
}
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
parameter
.
value
||
"-"
}
</
div
>
</
div
>
);
})
}
</
div
>
)
}
</
div
>
)
}
</
div
>
)
}
<
div
className=
{
styles
.
swFlowBox
}
style=
{
fullScreenShow
?
{
height
:
"100vh"
}
:
undefined
}
>
<
Flow
tasks=
{
workFlowJobInfo
?.
tasks
}
onBatchClick=
{
handleBatch
}
/>
</
div
>
</
div
>
<
img
className=
{
styles
.
fullScreenBox
}
src=
{
fullScreenShow
?
partialScreen
:
fullScreen
}
onClick=
{
()
=>
setFullScreenShow
(
!
fullScreenShow
)
}
alt=
"全屏"
/>
</
div
>
);
);
})
}
</
div
>
)
}
</
div
>
</
div
>
{
overviewActive
&&
(
<
div
className=
{
styles
.
overview
}
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
描述
</
div
>
<
div
className=
{
classNames
({
[
styles
.
taskInfoValue
]:
true
,
[
styles
.
taskInfoValueShowAll
]:
true
,
})
}
>
{
patchInfo
?.
description
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
算子版本
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
patchInfo
?.
creator
||
"-"
}
</
div
>
</
div
>
<
div
className=
{
styles
.
taskInfoLi
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
算子状态
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
patchInfo
?.
status
===
"Done"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobSue
}
alt=
""
/>
)
}
{
patchInfo
?.
status
===
"Running"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobRun
}
alt=
""
/>
)
}
{
patchInfo
?.
status
===
"Failed"
&&
(
<
img
className=
{
styles
.
taskInfoValueIcon
}
src=
{
jobFail
}
alt=
""
/>
)
}
{
statusMap
[
patchInfo
?.
status
as
IStatus
]
}
</
div
>
</
div
>
</
div
>
)
}
{
!
overviewActive
&&
(
<
div
className=
{
styles
.
params
}
>
{
randerParameters
.
map
((
parameter
:
any
)
=>
{
return
(
<
div
className=
{
styles
.
taskInfoLi
}
key=
{
parameter
.
name
}
>
<
div
className=
{
styles
.
taskInfoParams
}
>
{
parameter
.
name
}
</
div
>
<
div
className=
{
styles
.
taskInfoValue
}
>
{
parameter
.
value
||
"-"
}
</
div
>
</
div
>
);
})
}
</
div
>
)
}
</
div
>
)
}
</
div
>
)
}
<
div
className=
{
styles
.
swFlowBox
}
style=
{
fullScreenShow
?
{
height
:
"100vh"
}
:
undefined
}
>
<
Flow
tasks=
{
workFlowJobInfo
?.
tasks
}
onBatchClick=
{
handleBatch
}
/>
</
div
>
</
div
>
<
img
className=
{
styles
.
fullScreenBox
}
src=
{
fullScreenShow
?
partialScreen
:
fullScreen
}
onClick=
{
()
=>
setFullScreenShow
(
!
fullScreenShow
)
}
alt=
"全屏"
/>
</
div
>
);
});
export
default
ProjectSubmitWork
;
src/views/Project/ProjectWorkbench/workbenchTemplate/index.tsx
View file @
91794fa1
...
...
@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-05-31 10:18:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-0
5 18:06:17
* @LastEditTime: 2022-07-0
6 17:32:50
* @FilePath: /bkunyun/src/views/Project/ProjectSetting/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
...
...
@@ -22,259 +22,265 @@ import SimpleDialog from "./components/simpleDialog";
import
AddTemplate
from
"./components/addTemplate"
;
import
noData
from
"../../../../assets/project/noTemplate.svg"
;
import
{
getWorkbenchTemplate
,
deleteWorkbenchTemplate
,
getAddWorkbenchTemplate
,
addWorkbenchTemplate
,
getWorkbenchTemplate
,
deleteWorkbenchTemplate
,
getAddWorkbenchTemplate
,
addWorkbenchTemplate
,
}
from
"@/api/workbench_api"
;
import
usePass
from
"@/hooks/usePass"
;
import
React
FlowEdit
from
"@/views/WorkFlowEdit"
;
import
Work
FlowEdit
from
"@/views/WorkFlowEdit"
;
import
{
useStores
}
from
"@/store"
;
import
{
ICustomTemplate
}
from
"./interface"
;
import
styles
from
"./index.module.css"
;
const
ProjectMembers
=
observer
(()
=>
{
const
{
currentProjectStore
}
=
useStores
();
const
projectIdData
=
toJS
(
currentProjectStore
.
currentProjectInfo
.
id
);
const
{
currentProjectStore
}
=
useStores
();
const
projectIdData
=
toJS
(
currentProjectStore
.
currentProjectInfo
.
id
);
const
isPass
=
usePass
();
const
isPass
=
usePass
();
/** 搜索模板名称 */
const
[
templateName
,
setTemplateName
]
=
useState
(
""
);
/** 模板列表 */
const
[
templateList
,
setTemplateList
]
=
useState
([]);
/** 选中的模板id */
const
[
templateId
,
setTemplateId
]
=
useState
(
""
);
/** 简单弹窗(删除模板) */
const
[
openDialog
,
setOpenDialog
]
=
useState
(
false
);
/** 增加模板 */
const
[
openAddTemplate
,
setOpenAddTemplate
]
=
useState
(
false
);
/** 可增加模板列表 */
const
[
addTemplateList
,
setAddTemplateList
]
=
useState
([]);
/** 已选择增加的模板列表 */
const
[
selectTemplateData
,
setSelectTemplateData
]
=
useState
<
string
[]
>
([]);
/** 搜索模板名称 */
const
[
templateName
,
setTemplateName
]
=
useState
(
""
);
/** 模板列表 */
const
[
templateList
,
setTemplateList
]
=
useState
([]);
/** 选中的模板id */
const
[
templateId
,
setTemplateId
]
=
useState
(
""
);
/** 简单弹窗(删除模板) */
const
[
openDialog
,
setOpenDialog
]
=
useState
(
false
);
/** 增加模板 */
const
[
openAddTemplate
,
setOpenAddTemplate
]
=
useState
(
false
);
/** 可增加模板列表 */
const
[
addTemplateList
,
setAddTemplateList
]
=
useState
([]);
/** 已选择增加的模板列表 */
const
[
selectTemplateData
,
setSelectTemplateData
]
=
useState
<
string
[]
>
([]);
// 获取模板列表
const
{
run
:
getTemplateInfo
}
=
useMyRequest
(
getWorkbenchTemplate
,
{
onSuccess
:
(
result
:
any
)
=>
{
setTemplateList
(
result
.
data
);
},
}
);
/** 是否显示自定义模版编辑并带有参数 */
const
[
customTemplateInfo
,
setCustomTemplateInfo
]
=
useState
<
ICustomTemplate
>
(
{
show
:
false
,
}
);
// 删除模板
const
{
run
:
delTemplate
}
=
useMyRequest
(
deleteWorkbenchTemplate
,
{
onSuccess
:
(
result
:
any
)
=>
{
setOpenDialog
(
false
);
getTemplateInfo
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
title
:
templateName
,
});
},
});
// 获取模板列表
const
{
run
:
getTemplateInfo
}
=
useMyRequest
(
getWorkbenchTemplate
,
{
onSuccess
:
(
result
:
any
)
=>
{
setTemplateList
(
result
.
data
);
},
});
// 添加工作流模板-获取模板列表
const
{
run
:
getAddTemplateList
}
=
useMyRequest
(
getAddWorkbenchTemplate
,
{
onSuccess
:
(
result
:
any
)
=>
{
setAddTemplateList
(
result
.
data
);
setOpenAddTemplate
(
true
);
},
});
// 删除模板
const
{
run
:
delTemplate
}
=
useMyRequest
(
deleteWorkbenchTemplate
,
{
onSuccess
:
(
result
:
any
)
=>
{
setOpenDialog
(
false
);
getTemplateInfo
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
title
:
templateName
,
});
},
});
// 项目管理员-添加工作流模板-提交
const
{
run
:
addTemplate
}
=
useMyRequest
(
addWorkbenchTemplate
,
{
onSuccess
:
(
result
:
any
)
=>
{
setOpenAddTemplate
(
false
);
getTemplateInfo
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
});
setSelectTemplateData
([]);
},
});
// 添加工作流模板-获取模板列表
const
{
run
:
getAddTemplateList
}
=
useMyRequest
(
getAddWorkbenchTemplate
,
{
onSuccess
:
(
result
:
any
)
=>
{
setAddTemplateList
(
result
.
data
);
setOpenAddTemplate
(
true
);
},
});
useEffect
(()
=>
{
getTemplateInfo
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
});
},
[
currentProjectStore
.
currentProjectInfo
.
id
,
getTemplateInfo
]);
// 项目管理员-添加工作流模板-提交
const
{
run
:
addTemplate
}
=
useMyRequest
(
addWorkbenchTemplate
,
{
onSuccess
:
(
result
:
any
)
=>
{
setOpenAddTemplate
(
false
);
getTemplateInfo
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
});
setSelectTemplateData
([]);
},
});
useEffect
(()
=>
{
console
.
log
(
"projectIdData: "
,
projectIdData
);
},
[
projectIdData
]);
useEffect
(()
=>
{
getTemplateInfo
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
});
},
[
currentProjectStore
.
currentProjectInfo
.
id
,
getTemplateInfo
]);
/** 删除模板 */
const
deleteTemplate
=
()
=>
{
delTemplate
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
workflowSpecId
:
templateId
,
});
};
useEffect
(()
=>
{
console
.
log
(
"projectIdData: "
,
projectIdData
);
},
[
projectIdData
]);
/** 打开弹窗 */
const
startDialog
=
(
id
:
string
)
=>
{
setTemplateId
(
id
);
setOpenDialog
(
true
);
};
/** 删除模板 */
const
deleteTemplate
=
()
=>
{
delTemplate
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
workflowSpecId
:
templateId
,
});
};
/** 关闭弹窗 */
const
closeDialog
=
()
=>
{
setOpenDialog
(
false
);
};
/** 打开弹窗 */
const
startDialog
=
(
id
:
string
)
=>
{
setTemplateId
(
id
);
setOpenDialog
(
true
);
};
/** 增加模板 */
const
addTemplateBlock
=
()
=>
{
getAddTemplateList
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
productId
:
"cadd"
,
});
};
/** 关闭弹窗 */
const
closeDialog
=
()
=>
{
setOpenDialog
(
false
);
};
/** 关闭增加模板 */
const
closeAddTemplateBlock
=
()
=>
{
setOpenAddTemplate
(
false
);
setSelectTemplateData
([]);
};
/** 增加模板 */
const
addTemplateBlock
=
()
=>
{
getAddTemplateList
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
productId
:
"cadd"
,
});
};
/** 增加模板操作 */
const
addTemplateCallback
=
()
=>
{
addTemplate
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
workflowSpecIds
:
selectTemplateData
,
});
};
/** 关闭增加模板 */
const
closeAddTemplateBlock
=
()
=>
{
setOpenAddTemplate
(
false
);
setSelectTemplateData
([]);
};
/** 搜索模板 */
const
searchTemplateNameCallback
=
(
data
:
any
)
=>
{
getAddTemplateList
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
productId
:
"cadd"
,
title
:
data
,
});
};
/** 增加模板操作 */
const
addTemplateCallback
=
()
=>
{
addTemplate
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
workflowSpecIds
:
selectTemplateData
,
});
};
const
templateSelectCallback
=
(
data
:
string
)
=>
{
let
list
:
string
[]
=
[...
selectTemplateData
];
if
(
selectTemplateData
.
filter
((
e
)
=>
e
===
data
).
length
>
0
)
{
list
=
list
.
filter
((
e
)
=>
e
!==
data
);
setSelectTemplateData
(
list
);
}
else
{
list
.
push
(
data
);
setSelectTemplateData
(
list
);
}
};
/** 搜索模板 */
const
searchTemplateNameCallback
=
(
data
:
any
)
=>
{
getAddTemplateList
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
productId
:
"cadd"
,
title
:
data
,
});
};
const
searchChange
=
(
data
:
any
)
=>
{
setTemplateName
(
data
.
length
>
30
?
data
.
slice
(
0
,
30
)
:
data
);
};
const
templateSelectCallback
=
(
data
:
string
)
=>
{
let
list
:
string
[]
=
[...
selectTemplateData
];
if
(
selectTemplateData
.
filter
((
e
)
=>
e
===
data
).
length
>
0
)
{
list
=
list
.
filter
((
e
)
=>
e
!==
data
);
setSelectTemplateData
(
list
);
}
else
{
list
.
push
(
data
);
setSelectTemplateData
(
list
);
}
};
useEffect
(()
=>
{
setTimeout
(()
=>
{
getTemplateInfo
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
title
:
templateName
,
});
},
300
);
},
[
templateName
]);
const
searchChange
=
(
data
:
any
)
=>
{
setTemplateName
(
data
.
length
>
30
?
data
.
slice
(
0
,
30
)
:
data
);
};
return
(
<
Box
className=
{
styles
.
headerBox
}
>
<
Box
className=
{
styles
.
tabBox
}
>
<
OutlinedInput
onChange=
{
(
e
:
any
)
=>
{
searchChange
(
e
.
target
.
value
);
}
}
value=
{
templateName
}
placeholder=
"输入关键词搜索"
size=
"small"
sx=
{
{
width
:
340
,
height
:
32
}
}
endAdornment=
{
<
SearchIcon
style=
{
{
color
:
"#8A9099"
}
}
/>
}
/>
useEffect
(()
=>
{
setTimeout
(()
=>
{
getTemplateInfo
({
projectId
:
currentProjectStore
.
currentProjectInfo
.
id
as
string
,
title
:
templateName
,
});
},
300
);
},
[
templateName
]);
{
templateList
.
length
>
0
&&
isPass
(
"PROJECT_WORKBENCH_FLOES_ADD"
,
"MANAGER"
)
&&
(
<
Button
text=
{
"添加工作流模版"
}
img=
{
<
Add
/>
}
click=
{
addTemplateBlock
}
size=
{
"small"
}
/>
)
}
</
Box
>
return
(
<
Box
className=
{
styles
.
headerBox
}
>
<
Box
className=
{
styles
.
tabBox
}
>
<
OutlinedInput
onChange=
{
(
e
:
any
)
=>
{
searchChange
(
e
.
target
.
value
);
}
}
value=
{
templateName
}
placeholder=
"输入关键词搜索"
size=
"small"
sx=
{
{
width
:
340
,
height
:
32
}
}
endAdornment=
{
<
SearchIcon
style=
{
{
color
:
"#8A9099"
}
}
/>
}
/>
{
templateList
.
length
===
0
&&
templateName
.
length
>
0
&&
(
<
Box
sx=
{
{
display
:
"flex"
,
alignItems
:
"center"
,
flexDirection
:
"column"
,
minHeight
:
"calc(100vh - 376px)"
,
justifyContent
:
"center"
,
}
}
>
<
img
alt=
""
src=
{
noData
}
/>
<
Typography
sx=
{
{
fontSize
:
"12px"
,
fontWeight
:
"400"
,
color
:
"#8A9099"
}
}
>
暂未开启模版
</
Typography
>
</
Box
>
)
}
{
templateList
.
length
>
0
&&
(
<
Box
sx=
{
{
display
:
"flex"
,
flexWrap
:
"wrap"
,
marginLeft
:
"-8px"
}
}
>
{
templateList
&&
templateList
.
length
>
0
&&
templateList
.
map
((
item
,
key
)
=>
{
return
(
<
TemplateBox
data=
{
item
}
startDialog=
{
startDialog
}
key=
{
key
}
/>
);
})
}
</
Box
>
)
}
{
templateList
.
length
===
0
&&
templateName
.
length
===
0
&&
isPass
(
"PROJECT_WORKBENCH_FLOES_ADD"
,
"MANAGER"
)
&&
(
<
Box
className=
{
styles
.
addNewTemplate
}
onClick=
{
addTemplateBlock
}
>
<
Add
sx=
{
{
color
:
"#565C66"
,
fontSize
:
"20px"
,
width
:
"30px"
,
height
:
"30px"
,
}
}
/>
<
Typography
sx=
{
{
fontSize
:
"14px"
,
fontWeight
:
"400"
,
color
:
"#8A9099"
,
marginTop
:
"15px"
,
}
}
>
添加工作流模版
</
Typography
>
</
Box
>
)
}
{
templateList
.
length
>
0
&&
isPass
(
"PROJECT_WORKBENCH_FLOES_ADD"
,
"MANAGER"
)
&&
(
<
Button
text=
{
"添加工作流模版"
}
img=
{
<
Add
/>
}
click=
{
addTemplateBlock
}
size=
{
"small"
}
/>
)
}
</
Box
>
<
AddTemplate
openAddTemplate=
{
openAddTemplate
}
closeAddTemplateBlock=
{
closeAddTemplateBlock
}
addTemplateList=
{
addTemplateList
}
templateSelectCallback=
{
templateSelectCallback
}
selectTemplateData=
{
selectTemplateData
}
addTemplateCallback=
{
addTemplateCallback
}
searchTemplateNameCallback=
{
searchTemplateNameCallback
}
/>
{
templateList
.
length
===
0
&&
templateName
.
length
>
0
&&
(
<
Box
sx=
{
{
display
:
"flex"
,
alignItems
:
"center"
,
flexDirection
:
"column"
,
minHeight
:
"calc(100vh - 376px)"
,
justifyContent
:
"center"
,
}
}
>
<
img
alt=
""
src=
{
noData
}
/>
<
Typography
sx=
{
{
fontSize
:
"12px"
,
fontWeight
:
"400"
,
color
:
"#8A9099"
}
}
>
暂未开启模版
</
Typography
>
</
Box
>
)
}
{
templateList
.
length
>
0
&&
(
<
Box
sx=
{
{
display
:
"flex"
,
flexWrap
:
"wrap"
,
marginLeft
:
"-8px"
}
}
>
{
templateList
&&
templateList
.
length
>
0
&&
templateList
.
map
((
item
,
key
)
=>
{
return
<
TemplateBox
data=
{
item
}
startDialog=
{
startDialog
}
/>;
})
}
</
Box
>
)
}
{
templateList
.
length
===
0
&&
templateName
.
length
===
0
&&
isPass
(
"PROJECT_WORKBENCH_FLOES_ADD"
,
"MANAGER"
)
&&
(
<
Box
className=
{
styles
.
addNewTemplate
}
onClick=
{
addTemplateBlock
}
>
<
Add
sx=
{
{
color
:
"#565C66"
,
fontSize
:
"20px"
,
width
:
"30px"
,
height
:
"30px"
,
}
}
/>
<
Typography
sx=
{
{
fontSize
:
"14px"
,
fontWeight
:
"400"
,
color
:
"#8A9099"
,
marginTop
:
"15px"
,
}
}
>
添加工作流模版
</
Typography
>
</
Box
>
)
}
{
/* <ReactFlowEdit/> */
}
<
AddTemplate
openAddTemplate=
{
openAddTemplate
}
closeAddTemplateBlock=
{
closeAddTemplateBlock
}
addTemplateList=
{
addTemplateList
}
templateSelectCallback=
{
templateSelectCallback
}
selectTemplateData=
{
selectTemplateData
}
addTemplateCallback=
{
addTemplateCallback
}
searchTemplateNameCallback=
{
searchTemplateNameCallback
}
/>
<
SimpleDialog
text=
{
"确认移除该模板吗?"
}
title=
{
"删除模板"
}
openDialog=
{
openDialog
}
closeDialog=
{
closeDialog
}
onConfirm=
{
deleteTemplate
}
/>
</
Box
>
);
{
customTemplateInfo
?.
show
?
<
WorkFlowEdit
/>
:
null
}
<
SimpleDialog
text=
{
"确认移除该模板吗?"
}
title=
{
"删除模板"
}
openDialog=
{
openDialog
}
closeDialog=
{
closeDialog
}
onConfirm=
{
deleteTemplate
}
/>
</
Box
>
);
});
export
default
memo
(
ProjectMembers
);
src/views/Project/ProjectWorkbench/workbenchTemplate/interface.tsx
0 → 100644
View file @
91794fa1
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-06 14:44:13
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-06 14:47:28
* @FilePath: /bkunyun/src/views/Project/ProjectWorkbench/workbenchTemplate/interface.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
export
interface
ICustomTemplate
{
show
?:
boolean
;
id
?:
string
;
}
\ No newline at end of file
src/views/Project/components/Flow/index.tsx
View file @
91794fa1
import
ReactFlow
,
{
Controls
,
Background
,
useNodesState
,
useEdgesState
,
Handle
,
Position
,
ReactFlowProps
,
Node
,
Controls
,
Background
,
useNodesState
,
useEdgesState
,
Handle
,
Position
,
ReactFlowProps
,
Node
,
}
from
"react-flow-renderer"
;
import
{
useCallback
,
useEffect
,
useMemo
,
useState
}
from
"react"
;
import
classNames
from
"classnames"
;
...
...
@@ -14,7 +14,11 @@ 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
{
IEdge
,
IExecutionStatus
,
ITask
,
}
from
"../../ProjectSubmitWork/interface"
;
import
{
IBatchNode
,
ILine
}
from
"./interface"
;
import
styles
from
"./index.module.css"
;
...
...
@@ -27,300 +31,317 @@ import styles from "./index.module.css";
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
interface
IProps
extends
ReactFlowProps
{
tasks
?:
ITask
[];
/** 点击batch事件 */
onBatchClick
?:
(
val
:
string
)
=>
void
;
setSelectedNodeId
?:
(
val
:
string
)
=>
void
;
selectedNodeId
?:
string
;
tasks
?:
ITask
[];
/** 点击batch事件 */
onBatchClick
?:
(
val
:
string
)
=>
void
;
setSelectedNodeId
?:
(
val
:
string
)
=>
void
;
selectedNodeId
?:
string
;
}
/** 获取imgUrl */
const
getImgUrl
=
(
type
:
IExecutionStatus
)
=>
{
if
(
type
===
'Done'
)
{
return
jobSue
}
if
(
type
===
'Failed'
)
{
return
jobFail
}
if
(
type
===
'Running'
)
{
return
jobRun
}
return
undefined
}
/** 获取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
,
label
,
selectedStatus
}
=
data
;
return
(
<
div
className=
{
classNames
({
[
styles
.
batchNode
]:
true
,
[
styles
.
selectedBatchBox
]:
selectedStatus
,
[
styles
.
selectBatchNode
]:
selectedStatus
,
})
}
style=
{
style
}
>
{
dotStatus
?.
isInput
?
(
<
Handle
style=
{
{
background
:
"#fff "
,
border
:
"1px solid #D1D6DE"
,
left
:
20
}
}
type=
"target"
position=
{
Position
.
Top
}
/>
)
:
null
}
<
div
className=
{
classNames
({
[
styles
.
batchRotate
]:
isFlowNode
,
})
}
>
{
label
||
""
}
{
data
.
isCheck
&&
<
span
className=
{
styles
.
successDot
}
></
span
>
}
</
div
>
{
dotStatus
?.
isOutput
?
(
<
Handle
style=
{
{
background
:
"#fff "
,
border
:
"1px solid #D1D6DE"
,
left
:
20
}
}
type=
"source"
position=
{
Position
.
Bottom
}
/>
)
:
null
}
</
div
>
);
const
{
data
}
=
props
;
const
{
dotStatus
,
style
,
isFlowNode
,
label
,
selectedStatus
}
=
data
;
return
(
<
div
className=
{
classNames
({
[
styles
.
batchNode
]:
true
,
[
styles
.
selectedBatchBox
]:
selectedStatus
,
[
styles
.
selectBatchNode
]:
selectedStatus
,
})
}
style=
{
style
}
>
{
dotStatus
?.
isInput
?
(
<
Handle
style=
{
{
background
:
"#fff "
,
border
:
"1px solid #D1D6DE"
,
left
:
20
}
}
type=
"target"
position=
{
Position
.
Top
}
/>
)
:
null
}
<
div
className=
{
classNames
({
[
styles
.
batchRotate
]:
isFlowNode
,
})
}
>
{
label
||
""
}
{
data
.
isCheck
&&
<
span
className=
{
styles
.
successDot
}
></
span
>
}
</
div
>
{
dotStatus
?.
isOutput
?
(
<
Handle
style=
{
{
background
:
"#fff "
,
border
:
"1px solid #D1D6DE"
,
left
:
20
}
}
type=
"source"
position=
{
Position
.
Bottom
}
/>
)
:
null
}
</
div
>
);
};
/** 自定义flow节点 */
const
FlowNode
=
(
props
:
any
)
=>
{
const
{
data
}
=
props
;
return
(
<
div
className=
{
classNames
({
[
styles
.
flowNode
]:
true
,
})
}
>
{
data
?.
dotStatus
?.
isInput
?
(
<
Handle
style=
{
{
background
:
"#C2C6CC "
,
left
:
12
}
}
type=
"target"
position=
{
Position
.
Top
}
/>
)
:
null
}
<
div
style=
{
{
display
:
"flex"
,
alignItems
:
"center"
}
}
>
{
data
?.
label
||
""
}
{
data
.
isCheck
&&
<
span
className=
{
styles
.
successDot
}
></
span
>
}
{
getImgUrl
(
data
.
executionStatus
)
&&
<
img
style=
{
{
marginLeft
:
"6px"
}
}
src=
{
getImgUrl
(
data
.
executionStatus
)
}
alt=
""
/>
}
</
div
>
{
data
?.
dotStatus
?.
isOutput
?
(
<
Handle
style=
{
{
background
:
"#C2C6CC "
,
left
:
12
}
}
type=
"source"
position=
{
Position
.
Bottom
}
id=
"a"
/>
)
:
null
}
</
div
>
);
const
{
data
}
=
props
;
return
(
<
div
className=
{
classNames
({
[
styles
.
flowNode
]:
true
,
})
}
>
{
data
?.
dotStatus
?.
isInput
?
(
<
Handle
style=
{
{
background
:
"#C2C6CC "
,
left
:
12
}
}
type=
"target"
position=
{
Position
.
Top
}
/>
)
:
null
}
<
div
style=
{
{
display
:
"flex"
,
alignItems
:
"center"
}
}
>
{
data
?.
label
||
""
}
{
data
.
isCheck
&&
<
span
className=
{
styles
.
successDot
}
></
span
>
}
{
getImgUrl
(
data
.
executionStatus
)
&&
(
<
img
style=
{
{
marginLeft
:
"6px"
}
}
src=
{
getImgUrl
(
data
.
executionStatus
)
}
alt=
""
/>
)
}
</
div
>
{
data
?.
dotStatus
?.
isOutput
?
(
<
Handle
style=
{
{
background
:
"#C2C6CC "
,
left
:
12
}
}
type=
"source"
position=
{
Position
.
Bottom
}
id=
"a"
/>
)
:
null
}
</
div
>
);
};
const
Flow
=
(
props
:
IProps
)
=>
{
const
{
tasks
,
onBatchClick
,
setSelectedNodeId
,
selectedNodeId
}
=
props
;
/** 自定义的节点类型 */
const
nodeTypes
=
useMemo
(()
=>
{
return
{
batchNode
:
BatchNode
,
flowNode
:
FlowNode
};
},
[]);
const
{
tasks
,
onBatchClick
,
setSelectedNodeId
,
selectedNodeId
}
=
props
;
/** 自定义的节点类型 */
const
nodeTypes
=
useMemo
(()
=>
{
return
{
batchNode
:
BatchNode
,
flowNode
:
FlowNode
};
},
[]);
/** 内部维护的选择的节点Id */
const
[
inSideNodeId
,
setInSideNodeId
]
=
useState
<
string
>
(
""
);
/** 获取是否有输入节点或者是否有输出节点 */
const
nodesInputAndOutputStatus
=
useCallback
(
(
id
:
string
)
=>
{
/** 所有的连线 */
const
lineArr
:
IEdge
[]
=
[];
tasks
?.
length
&&
tasks
.
forEach
((
item
)
=>
{
lineArr
.
push
(...
item
.
edges
);
});
/** 所有的输入节点ID */
const
isInput
=
lineArr
?.
some
((
item
)
=>
item
.
target
===
id
);
/** 所有的输出节点ID */
const
isOutput
=
lineArr
?.
some
((
item
)
=>
item
.
source
===
id
);
return
{
isInput
,
isOutput
,
};
},
[
tasks
]
);
/** 获取是否有输入节点或者是否有输出节点 */
const
nodesInputAndOutputStatus
=
useCallback
(
(
id
:
string
)
=>
{
/** 所有的连线 */
const
lineArr
:
IEdge
[]
=
[];
tasks
?.
length
&&
tasks
.
forEach
((
item
)
=>
{
lineArr
.
push
(...
item
.
edges
);
});
/** 所有的输入节点ID */
const
isInput
=
lineArr
?.
some
((
item
)
=>
item
.
target
===
id
);
/** 所有的输出节点ID */
const
isOutput
=
lineArr
?.
some
((
item
)
=>
item
.
source
===
id
);
return
{
isInput
,
isOutput
,
};
},
[
tasks
]
);
/** 获取是否有流节点 */
const
isFlowNode
=
useCallback
(
(
id
:
string
)
=>
{
return
(
tasks
?.
length
&&
tasks
?.
some
((
item
)
=>
{
return
item
.
parentNode
===
id
;
})
);
},
[
tasks
]
);
/** 获取是否有流节点 */
const
isFlowNode
=
useCallback
(
(
id
:
string
)
=>
{
return
(
tasks
?.
length
&&
tasks
?.
some
((
item
)
=>
{
return
item
.
parentNode
===
id
;
})
);
},
[
tasks
]
);
/** 通过子flow节点计算batch节点的样式 */
const
getBatchStyle
=
useCallback
(
(
value
:
ITask
)
=>
{
const
positionXArr
:
number
[]
=
[];
const
positionYArr
:
number
[]
=
[];
tasks
?.
length
&&
tasks
?.
forEach
((
item
)
=>
{
if
(
item
.
parentNode
===
value
.
id
)
{
positionXArr
.
push
(
item
.
position
?.
x
||
0
);
positionYArr
.
push
(
item
.
position
?.
y
||
0
);
}
});
positionXArr
.
sort
((
a
,
b
)
=>
{
return
a
-
b
;
});
positionYArr
.
sort
((
a
,
b
)
=>
{
return
a
-
b
;
});
let
width
=
176
,
height
=
22
;
if
(
positionXArr
?.
length
)
{
const
val
=
positionXArr
[
positionXArr
.
length
-
1
]
+
150
;
width
=
val
>
176
?
val
:
width
;
}
if
(
positionYArr
?.
length
)
{
const
val
=
positionYArr
[
positionYArr
.
length
-
1
];
height
=
val
>
22
?
val
:
height
;
}
return
{
width
,
height
,
};
},
[
tasks
]
);
/** 通过子flow节点计算batch节点的样式 */
const
getBatchStyle
=
useCallback
(
(
value
:
ITask
)
=>
{
const
positionXArr
:
number
[]
=
[];
const
positionYArr
:
number
[]
=
[];
tasks
?.
length
&&
tasks
?.
forEach
((
item
)
=>
{
if
(
item
.
parentNode
===
value
.
id
)
{
positionXArr
.
push
(
item
.
position
?.
x
||
0
);
positionYArr
.
push
(
item
.
position
?.
y
||
0
);
}
});
positionXArr
.
sort
((
a
,
b
)
=>
{
return
a
-
b
;
});
positionYArr
.
sort
((
a
,
b
)
=>
{
return
a
-
b
;
});
let
width
=
176
,
height
=
22
;
if
(
positionXArr
?.
length
)
{
const
val
=
positionXArr
[
positionXArr
.
length
-
1
]
+
150
;
width
=
val
>
176
?
val
:
width
;
}
if
(
positionYArr
?.
length
)
{
const
val
=
positionYArr
[
positionYArr
.
length
-
1
];
height
=
val
>
22
?
val
:
height
;
}
return
{
width
,
height
,
};
},
[
tasks
]
);
/** 生成初始化node节点 */
const
initialNodes
=
useMemo
(()
=>
{
const
val
:
any
=
[];
tasks
?.
length
&&
tasks
.
forEach
((
item
)
=>
{
val
.
push
({
id
:
item
.
id
,
type
:
item
.
type
===
"BATCH"
?
"batchNode"
:
"flowNode"
,
data
:
{
label
:
item
.
title
||
""
,
/** 生成初始化node节点 */
const
initialNodes
=
useMemo
(()
=>
{
const
val
:
any
=
[];
tasks
?.
length
&&
tasks
.
forEach
((
item
)
=>
{
val
.
push
({
id
:
item
.
id
,
type
:
item
.
type
===
"BATCH"
?
"batchNode"
:
"flowNode"
,
data
:
{
label
:
item
.
title
||
""
,
...(
item
.
type
===
"BATCH"
?
{
/** 是否有流节点 */
isFlowNode
:
isFlowNode
(
item
.
id
),
/** 选中状态 */
selectedStatus
:
selectedNodeId
===
item
.
id
,
}
:
{}),
isCheck
:
item
.
isCheck
,
executionStatus
:
item
.
executionStatus
,
/** 输入输出圆点状态 */
dotStatus
:
nodesInputAndOutputStatus
(
item
.
id
),
/** 样式 */
style
:
{
...
getBatchStyle
(
item
),
padding
:
isFlowNode
(
item
.
id
)
?
"20px"
:
"12px 20px"
,
},
},
position
:
{
x
:
Number
(
item
.
position
.
x
),
y
:
Number
(
item
.
position
.
y
)
},
...(
item
.
type
===
"BATCH"
?
{
style
:
{
zIndex
:
-
1
}
}
:
{}),
...(
item
.
parentNode
?
{
parentNode
:
item
.
parentNode
}
:
{}),
...(
item
.
type
===
"BATCH"
?
{
extent
:
"parent"
}
:
{}),
});
});
return
val
;
},
[
tasks
,
isFlowNode
,
selectedNodeId
,
nodesInputAndOutputStatus
,
getBatchStyle
,
]);
...(
item
.
type
===
"BATCH"
?
{
/** 是否有流节点 */
isFlowNode
:
isFlowNode
(
item
.
id
),
/** 选中状态 */
selectedStatus
:
selectedNodeId
?
selectedNodeId
===
item
.
id
:
inSideNodeId
===
item
.
id
,
}
:
{}),
isCheck
:
item
.
isCheck
,
executionStatus
:
item
.
executionStatus
,
/** 输入输出圆点状态 */
dotStatus
:
nodesInputAndOutputStatus
(
item
.
id
),
/** 样式 */
style
:
{
...
getBatchStyle
(
item
),
padding
:
isFlowNode
(
item
.
id
)
?
"20px"
:
"12px 20px"
,
},
},
position
:
{
x
:
Number
(
item
.
position
.
x
),
y
:
Number
(
item
.
position
.
y
)
},
...(
item
.
type
===
"BATCH"
?
{
style
:
{
zIndex
:
-
1
}
}
:
{}),
...(
item
.
parentNode
?
{
parentNode
:
item
.
parentNode
}
:
{}),
...(
item
.
type
===
"BATCH"
?
{
extent
:
"parent"
}
:
{}),
});
});
return
val
;
},
[
tasks
,
isFlowNode
,
selectedNodeId
,
inSideNodeId
,
nodesInputAndOutputStatus
,
getBatchStyle
,
]);
/** 生成初始化的连线节点 */
const
initialEdges
=
useMemo
(()
=>
{
const
val
:
ILine
[]
=
[];
tasks
?.
length
&&
tasks
.
forEach
((
item
)
=>
{
item
.
edges
.
forEach
((
every
)
=>
{
const
newLine
=
{
...
every
,
batchId
:
item
.
parentNode
?
item
.
parentNode
:
item
.
id
,
};
val
.
push
(
newLine
);
},
[]);
});
return
val
.
map
((
item
:
ILine
)
=>
{
return
{
id
:
item
.
id
,
source
:
item
.
source
,
target
:
item
.
target
,
type
:
"smoothstep"
,
...(
item
?.
batchId
===
selectedNodeId
?
{
style
:
{
stroke
:
"#1370FF"
},
animated
:
true
}
:
{}),
labelStyle
:
{
fill
:
"#8A9099"
},
labelBgStyle
:
{
fill
:
"#F7F8FA "
},
label
:
item
.
label
?
`(
${
item
.
label
}
)`
:
""
,
};
});
},
[
selectedNodeId
,
tasks
]);
/** 生成初始化的连线节点 */
const
initialEdges
=
useMemo
(()
=>
{
const
val
:
ILine
[]
=
[];
tasks
?.
length
&&
tasks
.
forEach
((
item
)
=>
{
item
.
edges
.
forEach
((
every
)
=>
{
const
newLine
=
{
...
every
,
batchId
:
item
.
parentNode
?
item
.
parentNode
:
item
.
id
,
};
val
.
push
(
newLine
);
},
[]);
});
return
val
.
map
((
item
:
ILine
)
=>
{
const
newSelectId
=
selectedNodeId
?
selectedNodeId
:
inSideNodeId
;
return
{
id
:
item
.
id
,
source
:
item
.
source
,
target
:
item
.
target
,
type
:
"smoothstep"
,
...(
item
?.
batchId
===
newSelectId
?
{
style
:
{
stroke
:
"#1370FF"
},
animated
:
true
}
:
{}),
labelStyle
:
{
fill
:
"#8A9099"
},
labelBgStyle
:
{
fill
:
"#F7F8FA "
},
label
:
item
.
label
?
`(
${
item
.
label
}
)`
:
""
,
};
});
},
[
inSideNodeId
,
selectedNodeId
,
tasks
]);
/** flowNode点击事件 */
const
onNodeClick
=
(
e
:
any
,
node
:
Node
)
=>
{
tasks
?.
forEach
((
item
)
=>
{
if
(
item
.
id
===
node
.
id
)
{
if
(
item
.
parentNode
)
{
setSelectedNodeId
&&
setSelectedNodeId
(
item
.
parentNode
);
onBatchClick
&&
onBatchClick
(
item
.
parentNode
);
document
.
getElementById
(
`point
${
item
.
parentNode
}
`
)?.
scrollIntoView
(
true
)
}
else
{
setSelectedNodeId
&&
setSelectedNodeId
(
node
.
id
);
onBatchClick
&&
onBatchClick
(
node
.
id
||
""
);
document
.
getElementById
(
`point
${
node
.
id
}
`
)?.
scrollIntoView
(
true
)
}
}
});
};
/** flowNode点击事件 */
const
onNodeClick
=
(
e
:
any
,
node
:
Node
)
=>
{
tasks
?.
forEach
((
item
)
=>
{
if
(
item
.
id
===
node
.
id
)
{
if
(
item
.
parentNode
)
{
setSelectedNodeId
?
setSelectedNodeId
(
item
.
parentNode
)
:
setInSideNodeId
(
item
.
parentNode
);
onBatchClick
&&
onBatchClick
(
item
.
parentNode
);
document
.
getElementById
(
`point
${
item
.
parentNode
}
`
)
?.
scrollIntoView
(
true
);
}
else
{
setSelectedNodeId
?
setSelectedNodeId
(
node
.
id
)
:
setInSideNodeId
(
node
.
id
);
onBatchClick
&&
onBatchClick
(
node
.
id
||
""
);
document
.
getElementById
(
`point
${
node
.
id
}
`
)?.
scrollIntoView
(
true
);
}
}
});
};
const
handlePaneClick
=
()
=>
{
setSelectedNodeId
&&
setSelectedNodeId
(
''
);
onBatchClick
&&
onBatchClick
(
''
);
}
const
handlePaneClick
=
()
=>
{
setSelectedNodeId
?
setSelectedNodeId
(
""
)
:
setInSideNodeId
(
""
);
onBatchClick
&&
onBatchClick
(
""
);
};
/** node节点 */
const
[
nodes
,
setNodes
]
=
useNodesState
(
initialNodes
);
/** 连线数组 */
const
[
edges
,
setEdges
]
=
useEdgesState
(
initialEdges
);
/** node节点 */
const
[
nodes
,
setNodes
]
=
useNodesState
(
initialNodes
);
/** 连线数组 */
const
[
edges
,
setEdges
]
=
useEdgesState
(
initialEdges
);
useEffect
(()
=>
{
setEdges
(
initialEdges
);
},
[
initialEdges
,
setEdges
]);
useEffect
(()
=>
{
setEdges
(
initialEdges
);
},
[
initialEdges
,
setEdges
]);
useEffect
(()
=>
{
setNodes
(
initialNodes
);
},
[
initialNodes
,
setNodes
]);
useEffect
(()
=>
{
setNodes
(
initialNodes
);
},
[
initialNodes
,
setNodes
]);
return
(
<
ReactFlow
nodes=
{
nodes
}
edges=
{
edges
}
fitView
proOptions=
{
{
hideAttribution
:
true
,
account
:
""
}
}
nodeTypes=
{
nodeTypes
}
onPaneClick=
{
handlePaneClick
}
onNodeClick=
{
onNodeClick
}
{
...
props
}
>
<
Controls
/>
<
Background
color=
"#aaa"
gap=
{
16
}
/>
</
ReactFlow
>
);
return
(
<
ReactFlow
nodes=
{
nodes
}
edges=
{
edges
}
fitView
proOptions=
{
{
hideAttribution
:
true
,
account
:
""
}
}
nodeTypes=
{
nodeTypes
}
onPaneClick=
{
handlePaneClick
}
onNodeClick=
{
onNodeClick
}
{
...
props
}
>
<
Controls
/>
<
Background
color=
"#aaa"
gap=
{
16
}
/>
</
ReactFlow
>
);
};
export
default
Flow
;
src/views/WorkFlowEdit/components/OperatorList/index.module.css
0 → 100644
View file @
91794fa1
.operatorItemBox
{
background-color
:
#fff
;
border-radius
:
4px
;
cursor
:
grab
;
padding
:
16px
0
;
border-bottom
:
1px
solid
#f0f2f5
;
}
.operatorItemTitle
{
user-select
:
none
;
font-size
:
14px
;
color
:
#1e2633
;
}
.operatorItemText
{
color
:
#8a9099
;
margin
:
8px
0
;
font-size
:
12px
;
user-select
:
none
;
display
:
-webkit-box
;
-webkit-line-clamp
:
3
;
-webkit-box-orient
:
vertical
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
.labelBox
{
user-select
:
none
;
display
:
inline-block
;
border-radius
:
2px
;
font-size
:
12px
;
padding
:
2px
8px
;
}
.footerBx
{
display
:
flex
;
align-items
:
center
;
}
src/views/WorkFlowEdit/components/OperatorList/index.tsx
0 → 100644
View file @
91794fa1
import
{
IOperatorItemProps
}
from
"./interface"
;
import
{
OutlinedInput
}
from
"@mui/material"
;
import
SearchIcon
from
"@mui/icons-material/Search"
;
import
styles
from
"./index.module.css"
;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-06 15:16:01
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-06 16:27:16
* @FilePath: /bkunyun/src/views/WorkFlowEdit/components/OperatorList/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
const
OperatorItem
=
(
props
:
IOperatorItemProps
)
=>
{
const
{
info
}
=
props
;
return
(
<
div
className=
{
styles
.
operatorItemBox
}
>
<
h2
className=
{
styles
.
operatorItemTitle
}
>
说什么呢啊
</
h2
>
<
div
className=
{
styles
.
operatorItemText
}
>
STU utility
是一个R-packa标处理目标处理,目标处理目标处理标处理目标处理后期委屈好委屈农,博啊发布丢我被欺安度切换阿斯顿几切换,i的亲戚我好奇你eqeqeweqeqeeqeqeqeqeq。
</
div
>
<
div
className=
{
styles
.
footerBx
}
>
<
span
className=
{
styles
.
labelBox
}
style=
{
{
background
:
true
?
"#EBF3FF"
:
"#E3FAEC"
,
color
:
true
?
"#1370FF"
:
"#02AB83"
,
}
}
>
公共平台
</
span
>
<
OutlinedInput
onChange=
{
(
e
:
any
)
=>
{
console
.
log
(
e
.
target
.
value
);
}
}
// value={templateName}
placeholder=
"输入关键词搜索"
size=
"small"
sx=
{
{
flex
:
1
,
height
:
32
}
}
endAdornment=
{
<
SearchIcon
style=
{
{
color
:
"#8A9099"
}
}
/>
}
/>
</
div
>
</
div
>
);
};
const
OperatorList
=
()
=>
{
const
arr
=
[
222
,
3333
,
339
];
return
(
<>
{
arr
.
map
((
item
)
=>
{
return
<
OperatorItem
key=
{
item
}
info=
{
item
}
/>;
})
}
</>
);
};
export
default
OperatorList
;
src/views/WorkFlowEdit/components/OperatorList/interface.ts
0 → 100644
View file @
91794fa1
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-06 15:32:11
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-06 15:32:42
* @FilePath: /bkunyun/src/views/WorkFlowEdit/components/OperatorList/interface.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
export
interface
IOperatorItemProps
{
info
:
any
}
\ No newline at end of file
src/views/WorkFlowEdit/index.module.css
View file @
91794fa1
...
...
@@ -32,10 +32,10 @@
.swFormBox
{
background-color
:
#fff
;
border-right
:
1
xp
solid
rgba
(
235
,
237
,
240
,
1
);
width
:
608
px
;
width
:
360
px
;
overflow-y
:
scroll
;
box-sizing
:
border-box
;
padding
:
36
px
;
padding
:
24
px
;
}
.swFlowBox
{
flex
:
1
;
...
...
src/views/WorkFlowEdit/index.tsx
View file @
91794fa1
...
...
@@ -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-0
5 16:31:28
* @LastEditTime: 2022-07-0
6 15:21:55
* @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
...
...
@@ -14,6 +14,7 @@ import { useLocation, useNavigate } from "react-router-dom";
import
MyPopconfirm
from
"@/components/mui/MyPopconfirm"
;
import
ButtonComponent
from
"@/components/mui/Button"
;
import
{
ITemplateConfig
}
from
"../Project/ProjectSubmitWork/interface"
;
import
OperatorList
from
"./components/OperatorList"
;
import
styles
from
'./index.module.css'
...
...
@@ -64,7 +65,7 @@ const WorkFlowEdit = () => {
</
div
>
<
div
className=
{
styles
.
swContent
}
>
<
div
className=
{
styles
.
swFormBox
}
>
左侧
<
OperatorList
/>
</
div
>
<
div
className=
{
styles
.
swFlowBox
}
>
右侧
...
...
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