Commit 5651e90b authored by chenshouchao's avatar chenshouchao

Merge branch 'feat-20220705-customTemplate' into 'release'

cn- Feat 20220705 custom template

See merge request !99
parents 0ac8a41c ed3d6226
......@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 09:56:57
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-07 18:19:20
* @LastEditTime: 2022-07-10 13:47:53
* @FilePath: /bkunyun/src/api/api_manager.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -37,6 +37,7 @@ const RESTAPI = {
API_SUBMIT_WORKFLOW: `${BACKEND_API_URI_PREFIX}/cpp/workflow/submit`, //提交工作流
API_WORKBENCH_WORKFLOW_TASKINFO: `${BACKEND_API_URI_PREFIX}/cpp/workbench/workflowjob/task-info`, //查询任务某个算子详情
API_OPERATOR_LIST:`${BACKEND_API_URI_PREFIX}/cpp/workflow/actorspecs`, // 获取算子列表
API_VERSION_OPERATOR:`${BACKEND_API_URI_PREFIX}/cpp/workflow/actorversion`, // 获取指定版本算子
};
export default RESTAPI;
export interface IGetOperatorList {
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-08 09:26:58
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-10 13:53:26
* @FilePath: /bkunyun/src/api/workbenchInterface.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
export interface IGetOperatorListParams {
owner: string;
productId: string;
keyword?: string
}
export interface IFetchOperatorListParams {
version: string;
title: string
}
\ No newline at end of file
......@@ -2,13 +2,13 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-07-05 14:00:37
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-07-07 18:24:16
* @LastEditTime: 2022-07-10 13:54:04
* @FilePath: /bkunyun/src/api/workbench_api.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import request from "@/utils/axios/service";
import Api from "./api_manager";
import { IGetOperatorList } from "./workbenchInterface";
import { IGetOperatorListParams, IFetchOperatorListParams } from "./workbenchInterface";
function current() {
return request({
......@@ -129,7 +129,7 @@ const cancelWorkflowJob = (params: workflowJobCancelParams) => {
};
// 获取算子列表数据
const fetchOperatorList = (params: IGetOperatorList) => {
const fetchOperatorList = (params: IGetOperatorListParams) => {
return request({
url: Api.API_OPERATOR_LIST,
method: "get",
......@@ -137,6 +137,15 @@ const fetchOperatorList = (params: IGetOperatorList) => {
});
};
// 获取指定版本算子
const fetchVersionOperator = (params: IFetchOperatorListParams) => {
return request({
url: Api.API_VERSION_OPERATOR,
method: "get",
params,
});
};
export {
current,
menu,
......@@ -147,5 +156,6 @@ export {
getWorkflowJobList,
deleteWorkflowJob,
cancelWorkflowJob,
fetchOperatorList
fetchOperatorList,
fetchVersionOperator
};
......@@ -84,6 +84,7 @@ export default function MyCheckBox(props: IMyCheckBoxProps) {
label={option.label}
name={option.value}
onChange={handleMyCheckBoxOnChange}
disabled={option.disabled}
/>
);
})}
......
......@@ -63,7 +63,11 @@ const MyMenu = (props: IMyMenuProps) => {
};
const handleClose = (value: string) => {
setAnchorEl(null);
};
const handleMenuClick = (value: string) => {
setValue && setValue(value);
setAnchorEl(null);
};
return (
......@@ -82,7 +86,7 @@ const MyMenu = (props: IMyMenuProps) => {
{options.map((option, index) => {
return (
<MenuItem
onClick={() => handleClose(option.value)}
onClick={() => handleMenuClick(option.value)}
selected={value === option.value}
key={index}
>
......
// import * as React from "react";
// import { ReactNode, useEffect } from "react";
// import Box from "@mui/material/Box";
// import ButtonComponent from "./Button";
// import tipsIcon from "@/assets/project/information-outline.svg";
// import Popper from "@mui/material/Popper";
// type IMyPopconfirmProps = {
// title: string | ReactNode;
// cancelText?: string;
// okText?: string;
// showCancel?: boolean;
// onCancel?: any;
// onConfirm?: any;
// children: ReactNode;
// };
// const MyPopconfirm = (props: IMyPopconfirmProps) => {
// const {
// title,
// cancelText = "取消",
// okText = "确认",
// showCancel = true,
// onCancel,
// onConfirm,
// } = props;
// const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
// const handleClick = (event: React.MouseEvent<HTMLElement>) => {
// event.nativeEvent.stopImmediatePropagation();
// setAnchorEl(anchorEl ? null : event.currentTarget);
// };
// const open = Boolean(anchorEl);
// const id = open ? "simple-popper" : undefined;
// const handleCancel = () => {
// setAnchorEl(null);
// onCancel && onCancel();
// };
// const handleOk = () => {
// setAnchorEl(null);
// onConfirm && onConfirm();
// };
// useEffect(() => {
// document.addEventListener("click", (e) => {
// setAnchorEl(null);
// });
// }, []);
// return (
// <div>
// <div aria-describedby={id} onClick={handleClick}>
// {props.children && props.children}
// </div>
// <Popper
// id={id}
// open={open}
// anchorEl={anchorEl}
// sx={{
// zIndex: 2000,
// bgcolor: "#fff",
// minWidth: "200px",
// borderRadius: "2px",
// padding: "20px 16px",
// boxShadow: "0px 3px 10px 0px rgba(0, 24, 57, 0.14)",
// }}
// >
// {/* "0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d", */}
// <Box sx={{ marginBottom: "16px" }}>
// <img
// style={{ marginRight: "12px", position: "relative", top: "3px" }}
// src={tipsIcon}
// alt=""
// />
// {title}
// </Box>
// <Box sx={{ display: "flex", justifyContent: "flex-end" }}>
// {showCancel && (
// <ButtonComponent
// text={cancelText}
// // variant="text"
// size="small"
// color="inherit"
// click={handleCancel}
// style={{ marginRight: "12px" }}
// ></ButtonComponent>
// )}
// <ButtonComponent
// text={okText}
// // variant="text"
// size="small"
// click={handleOk}
// ></ButtonComponent>
// </Box>
// </Popper>
// </div>
// );
// };
// export default MyPopconfirm;
// 确认提示框, 支持同一页面多个提示框
import * as React from "react";
import { ReactNode, useEffect } from "react";
import { ReactNode, useMemo } from "react";
import Box from "@mui/material/Box";
import ButtonComponent from "./Button";
import tipsIcon from "@/assets/project/information-outline.svg";
......@@ -7,17 +112,35 @@ import Popper from "@mui/material/Popper";
type IMyPopconfirmProps = {
title: string | ReactNode;
placement?:
| "auto-end"
| "auto-start"
| "auto"
| "bottom-end"
| "bottom-start"
| "bottom"
| "left-end"
| "left-start"
| "left"
| "right-end"
| "right-start"
| "right"
| "top-end"
| "top-start"
| "top";
anchorEl?: null | HTMLElement;
cancelText?: string;
okText?: string;
showCancel?: boolean;
onCancel?: any;
onConfirm?: any;
children: ReactNode;
};
const MyPopconfirm = (props: IMyPopconfirmProps) => {
const {
title,
anchorEl,
placement = "bottom",
cancelText = "取消",
okText = "确认",
showCancel = true,
......@@ -25,41 +148,26 @@ const MyPopconfirm = (props: IMyPopconfirmProps) => {
onConfirm,
} = props;
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = useMemo(() => {
return Boolean(anchorEl);
}, [anchorEl]);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
event.nativeEvent.stopImmediatePropagation();
setAnchorEl(anchorEl ? null : event.currentTarget);
};
const open = Boolean(anchorEl);
const id = open ? "simple-popper" : undefined;
const handleCancel = () => {
setAnchorEl(null);
onCancel && onCancel();
};
const handleOk = () => {
setAnchorEl(null);
onConfirm && onConfirm();
};
useEffect(() => {
document.addEventListener("click", (e) => {
setAnchorEl(null);
});
}, []);
return (
<div>
<div aria-describedby={id} onClick={handleClick}>
{props.children && props.children}
</div>
<Popper
id={id}
open={open}
anchorEl={anchorEl}
placement={placement}
sx={{
zIndex: 2000,
bgcolor: "#fff",
......@@ -69,7 +177,6 @@ const MyPopconfirm = (props: IMyPopconfirmProps) => {
boxShadow: "0px 3px 10px 0px rgba(0, 24, 57, 0.14)",
}}
>
{/* "0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d", */}
<Box sx={{ marginBottom: "16px" }}>
<img
style={{ marginRight: "12px", position: "relative", top: "3px" }}
......@@ -82,7 +189,6 @@ const MyPopconfirm = (props: IMyPopconfirmProps) => {
{showCancel && (
<ButtonComponent
text={cancelText}
// variant="text"
size="small"
color="inherit"
click={handleCancel}
......@@ -91,13 +197,11 @@ const MyPopconfirm = (props: IMyPopconfirmProps) => {
)}
<ButtonComponent
text={okText}
// variant="text"
size="small"
click={handleOk}
></ButtonComponent>
</Box>
</Popper>
</div>
);
};
......
......@@ -64,6 +64,7 @@ export default function MyRadio(props: IMyRadioProps) {
value={option.value}
control={<Radio />}
label={option.label}
disabled={option.disabled}
/>
);
})}
......
import * as React from 'react';
import Switch from '@mui/material/Switch';
import { ThemeProvider, createTheme } from "@mui/material/styles";
type IMySwitchProps = {
value: boolean;
onChange?: any;
disabled?: boolean;
}
const theme = createTheme({
components: {
MuiSwitch: {
styleOverrides: {
root: {
height: '22px',
width: '40px',
boxSizing: 'border-box',
padding: '0',
},
switchBase:{
top: '4px',
left: '4px',
padding: 0,
'&.Mui-checked': {
left: '2px',
'& + .MuiSwitch-track': {
opacity: 1,
}
},
},
thumb: {
width: '14px',
height: '14px',
color: '#fff'
},
track: {
borderRadius: '11px',
backgroundColor: "#E6E8EB",
opacity: 1,
},
},
},
},
});
const MySwitch = (props: IMySwitchProps) => {
const {value, onChange, disabled= false} = props;
return (
<ThemeProvider theme={theme}>
<Switch checked={value} disabled={disabled} onChange={onChange} />
</ThemeProvider>
)
}
export default MySwitch;
\ No newline at end of file
......@@ -11,27 +11,62 @@ import { isEqual } from "lodash";
import { useState } from "react";
import { Box } from "@mui/system";
import Tab from "@mui/material/Tab";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { TabContext, TabList, TabPanel } from "@mui/lab";
import { Typography } from "@mui/material";
interface ITabList {
label: string;
value: string;
component: JSX.Element;
component: JSX.Element | React.ReactNode;
icon?: string;
iconed?: string;
hide?: boolean;
disabled?: boolean;
}
interface IProps {
tabList: ITabList[];
defaultValue?: string;
allowNullValue?: boolean; // 是否允许空值
}
const theme = createTheme({
components: {
MuiTab: {
styleOverrides: {
root: {
paddingLeft: 0,
paddingRight: 0,
paddingTop: '8px',
paddingBottom: '8px',
minWidth: '20px',
marginRight: '32px',
color: '#8A9099',
selected: {
color: '#1976d2'
},
"&.Mui-disabled": {
color: '#C2C6CC',
},
},
},
},
// #C2C6CC
MuiTabs:{
styleOverrides: {
indicator: {
backgroundColor: '#1370FF',
}
}
},
},
});
const Tabs = (props: IProps) => {
const { tabList, defaultValue } = props;
const { tabList, defaultValue, allowNullValue = false } = props;
const [value, setValue] = useState(
defaultValue || tabList.filter((e) => !e.hide)[0].value
defaultValue ? defaultValue : allowNullValue ? '' : tabList.filter((e) => !e.hide)[0].value
);
const onChange = (val: string) => {
......@@ -58,6 +93,7 @@ const Tabs = (props: IProps) => {
};
return (
<ThemeProvider theme={theme}>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: "#F0F2F5" }}>
<TabList
......@@ -74,6 +110,7 @@ const Tabs = (props: IProps) => {
label={labelRender(item, key)}
value={item.value}
id={item.value}
disabled={item.disabled}
/>
);
})}
......@@ -93,6 +130,7 @@ const Tabs = (props: IProps) => {
);
})}
</TabContext>
</ThemeProvider>
);
};
const handleEqual = (prvProps: IProps, nextProps: IProps) => {
......
......@@ -293,6 +293,30 @@ const ProjectSubmitWork = observer(() => {
}
}, [isPass, state]);
const [goToProjectDataPath, setGoToProjectDataPath] = useState("");
const [popperTitle, setPopperTitle] = useState(
"正在运行的任务终止后将无法重新运行,确认继续吗?"
);
const [anchorEl, setAnchorEl] = useState<any>(null);
const handleCancel = () => {
setAnchorEl(null);
};
const handleShowPopper = (e: any, title: string) => {
setPopperTitle(title);
setAnchorEl(anchorEl ? null : e.currentTarget);
};
const handleConfirm = () => {
if (popperTitle === "正在运行的任务终止后将无法重新运行,确认继续吗?") {
onStopJob();
} else if (popperTitle === "任务被删除后将无法恢复,确认继续吗?") {
onDeleteJob();
} else {
goToProjectData(goToProjectDataPath);
}
};
return (
<div className={styles.swBox}>
{fullScreenShow ? null : (
......@@ -318,7 +342,7 @@ const ProjectSubmitWork = observer(() => {
</div>
{returnPermission && (
<div className={styles.swHeaderRight}>
<MyPopconfirm
{/* <MyPopconfirm
title={
state === "RUNNING"
? "正在运行的任务终止后将无法重新运行,确认继续吗?"
......@@ -327,14 +351,22 @@ const ProjectSubmitWork = observer(() => {
onConfirm={() => {
state === "RUNNING" ? onStopJob() : onDeleteJob();
}}
>
> */}
<ButtonComponent
text={state === "RUNNING" ? "终止" : "删除"}
variant="outlined"
color="secondary"
click={(e: any) =>
handleShowPopper(
e,
state === "RUNNING"
? "正在运行的任务终止后将无法重新运行,确认继续吗?"
: "任务被删除后将无法恢复,确认继续吗?"
)
}
// click={onStopJob}
></ButtonComponent>
</MyPopconfirm>
{/* </MyPopconfirm> */}
</div>
)}
</div>
......@@ -350,13 +382,22 @@ const ProjectSubmitWork = observer(() => {
{randerOutputs1.map((item, index) => {
return (
<div key={index} className={styles.outputLi}>
<MyPopconfirm
{/* <MyPopconfirm
title="即将跳转至项目数据内该任务的结果目录,确认继续吗?"
onConfirm={() =>
goToProjectData(getFolderPath(item.path))
}
> */}
<div
className={styles.outputLiLeft}
onClick={(e: any) => {
handleShowPopper(
e,
"即将跳转至项目数据内该任务的结果目录,确认继续吗?"
);
setGoToProjectDataPath(getFolderPath(item.path));
}}
>
<div className={styles.outputLiLeft}>
<img
className={styles.outputLiLeftImg}
src={
......@@ -366,7 +407,7 @@ const ProjectSubmitWork = observer(() => {
/>
{item.name}
</div>
</MyPopconfirm>
{/* </MyPopconfirm> */}
<span className={styles.outputLiRight}>
{item.size}
</span>
......@@ -622,6 +663,12 @@ const ProjectSubmitWork = observer(() => {
onClick={() => setFullScreenShow(!fullScreenShow)}
alt="全屏"
/>
<MyPopconfirm
title={popperTitle}
anchorEl={anchorEl}
onCancel={handleCancel}
onConfirm={handleConfirm}
/>
</div>
);
});
......
......@@ -202,18 +202,44 @@ const ProjectSubmitWork = observer(() => {
}
};
const [popperTitle, setPopperTitle] = useState(
"提交前请先确认参数填写无误,确认提交吗?"
);
const [anchorEl, setAnchorEl] = useState<any>(null);
const handleCancel = () => {
setAnchorEl(null);
};
const handleShowPopper = (e: any, title: string) => {
setPopperTitle(title);
setAnchorEl(anchorEl ? null : e.currentTarget);
};
const handleConfirm = () => {
if (popperTitle === "提交前请先确认参数填写无误,确认提交吗?") {
handleSubmitForm();
} else {
handleGoBack();
}
};
return (
<div className={styles.swBox}>
{fullScreenShow ? null : (
<div className={styles.swHeader}>
<div className={styles.swHeaderLeft}>
<MyPopconfirm
{/* <MyPopconfirm
title="返回后,当前页面已填写内容将不保存,确认返回吗?"
onConfirm={handleGoBack}
>
> */}
<IconButton
color="primary"
// onClick={() => handleGoBack()}
onClick={(e: any) =>
handleShowPopper(
e,
"返回后,当前页面已填写内容将不保存,确认返回吗?"
)
}
aria-label="upload picture"
component="span"
size="small"
......@@ -226,7 +252,7 @@ const ProjectSubmitWork = observer(() => {
}}
/>
</IconButton>
</MyPopconfirm>
{/* </MyPopconfirm> */}
<div className={styles.swTemplateTitle}>
{templateConfigInfo?.title}
......@@ -250,15 +276,18 @@ const ProjectSubmitWork = observer(() => {
<div className={styles.swHeaderGoback}></div>
</div>
<div className={styles.swHeaderRight}>
<MyPopconfirm
{/* <MyPopconfirm
title="提交前请先确认参数填写无误,确认提交吗?"
onConfirm={handleSubmitForm}
>
> */}
<ButtonComponent
text="提交任务"
// click={handleSubmitForm}
click={(e: any) =>
handleShowPopper(e, "提交前请先确认参数填写无误,确认提交吗?")
}
></ButtonComponent>
</MyPopconfirm>
{/* </MyPopconfirm> */}
</div>
</div>
)}
......@@ -290,6 +319,12 @@ const ProjectSubmitWork = observer(() => {
onClick={() => setFullScreenShow(!fullScreenShow)}
alt="全屏"
/>
<MyPopconfirm
title={popperTitle}
anchorEl={anchorEl}
onCancel={handleCancel}
onConfirm={handleConfirm}
/>
</div>
);
});
......
......@@ -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-07 17:39:49
* @LastEditTime: 2022-07-09 15:57:24
* @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/interface.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -38,6 +38,7 @@ export interface ITask {
title: string;
description: string;
version?: string;
allVersions?: string[]
position: {
x: number;
y: number;
......
......@@ -34,9 +34,14 @@ interface IProps extends ReactFlowProps {
tasks?: ITask[];
/** 点击batch事件 */
onBatchClick?: (val: string) => void;
/** 设置选中节点id */
setSelectedNodeId?: (val: string) => void;
/** 选中的节点id */
selectedNodeId?: string;
/** 类型, edit为编辑类型 */
type?: "edit" | "default";
/** 设置组件数据 组件为编辑状态使用 */
setTasks?: (val: ITask[]) => void;
}
/** 获取imgUrl */
......@@ -140,6 +145,7 @@ const Flow = (props: IProps) => {
setSelectedNodeId,
selectedNodeId,
type: flowType = "default",
setTasks,
} = props;
/** 自定义的节点类型 */
const nodeTypes = useMemo(() => {
......@@ -148,6 +154,27 @@ const Flow = (props: IProps) => {
/** 内部维护的选择的节点Id */
const [inSideNodeId, setInSideNodeId] = useState<string>("");
const deleteSelectBatchNode = useCallback(
(e: any) => {
if (e.keyCode === 8) {
const val =
tasks?.length &&
tasks.filter((item) => {
return item.id !== inSideNodeId && item.parentNode !== inSideNodeId;
});
setTasks && setTasks(val || []);
}
},
[inSideNodeId, setTasks, tasks]
);
useEffect(() => {
window.addEventListener("keyup", deleteSelectBatchNode);
return () => {
window.removeEventListener("keyup", deleteSelectBatchNode);
};
}, [deleteSelectBatchNode]);
/** 获取是否有输入节点或者是否有输出节点 */
const nodesInputAndOutputStatus = useCallback(
(id: string) => {
......@@ -223,10 +250,10 @@ const Flow = (props: IProps) => {
const val: any = [];
tasks?.length &&
tasks.forEach((item) => {
console.log(item, "item");
val.push({
id: item.id,
type: item.type === "BATCH" ? "batchNode" : "flowNode",
/** 每一项的数据 */
data: {
label: item.title || "",
......@@ -240,7 +267,9 @@ const Flow = (props: IProps) => {
: inSideNodeId === item.id,
}
: {}),
/** 是否选中 */
isCheck: item.isCheck,
/** 运行状态 */
executionStatus: item.executionStatus,
/** 输入输出圆点状态 */
dotStatus: nodesInputAndOutputStatus(item.id),
......@@ -250,13 +279,20 @@ const Flow = (props: IProps) => {
padding: isFlowNode(item.id) ? "20px" : "12px 20px",
},
},
/** 坐标 */
position: {
x: Number(item.position?.x) || 0,
y: Number(item.position?.y) || 0,
},
...(item.type === "BATCH" ? { style: { zIndex: -1 } } : {}),
/**
* extent: "parent" 跟随父节点移动
* draggable: false 节点不可移动
*/
...(item.type === "BATCH"
? { style: { zIndex: -1 }, extent: "parent" }
: { draggable: false }),
/** parentNode 父节点ID */
...(item.parentNode ? { parentNode: item.parentNode } : {}),
...(item.type === "BATCH" ? { extent: "parent" } : {}),
});
});
return val;
......@@ -329,9 +365,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);
......@@ -346,7 +382,11 @@ const Flow = (props: IProps) => {
nodes={nodes}
edges={edges}
fitView={flowType === "default" ? true : false}
proOptions={{ hideAttribution: true, account: "" }}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
deleteKeyCode={["13"]}
// onConnect={onConnect}
// proOptions={{ hideAttribution: true, account: "" }}
nodeTypes={nodeTypes}
onPaneClick={handlePaneClick}
onNodeClick={onNodeClick}
......
......@@ -51,3 +51,11 @@
overflow-y: scroll;
height: calc(100% - 48px);
}
.versionBox {
background: #e6e8eb;
color: #1e2633;
cursor: pointer;
padding: 0 8px;
border-radius: 2px;
}
import { OutlinedInput } from "@mui/material";
import SearchIcon from "@mui/icons-material/Search";
import classNames from "classnames";
import { useCallback, useEffect, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { observer } from "mobx-react-lite";
import { toJS } from "mobx";
import cloneDeep from "lodash/cloneDeep";
......@@ -10,7 +10,7 @@ import { IOperatorItemProps, IOperatorListProps } from "./interface";
import { ITask } from "@/views/Project/ProjectSubmitWork/interface";
import useMyRequest from "@/hooks/useMyRequest";
import { IResponse } from "@/api/http";
import { fetchOperatorList } from "@/api/workbench_api";
import { fetchOperatorList, fetchVersionOperator } from "@/api/workbench_api";
import { useStores } from "@/store";
import styles from "./index.module.css";
......@@ -29,7 +29,7 @@ let count = 1;
const OperatorItem = (props: IOperatorItemProps) => {
const {
info: { title, description, tags },
info: { title, description, tags, allVersions, version },
setTemplateConfigInfo,
templateConfigInfo,
setOperatorListData,
......@@ -37,6 +37,7 @@ const OperatorItem = (props: IOperatorItemProps) => {
info,
} = props;
const [isDragStyle, setIsDragStyle] = useState<boolean>(false);
const [versionValue, setVersionValue] = useState<string>("");
/** 拖拽开始 */
const onDragStart = useCallback(() => {
......@@ -44,6 +45,26 @@ const OperatorItem = (props: IOperatorItemProps) => {
count++;
}, []);
// 获取指定版本的算子
const { run: getVersionOperator } = useMyRequest(fetchVersionOperator, {
onSuccess: (res: IResponse<any>) => {
if (res.data) {
let index: number | undefined = undefined;
const newVal = operatorListData.filter((item, i) => {
const bol = item.id === info.id || item.parentNode === info.id;
if (bol && index === undefined) {
index = i;
}
return !bol;
});
if (index !== undefined) {
newVal.splice(index, 0, ...res.data);
}
setOperatorListData(newVal);
}
},
});
/** 通过id查找相对的批流数组 */
const getBatchFlowArr = useCallback(
(id: string) => {
......@@ -121,6 +142,27 @@ const OperatorItem = (props: IOperatorItemProps) => {
]
);
/** 所有版本信息格式化 */
const getAllVersion = useMemo(() => {
return (
allVersions?.length &&
allVersions?.map((item) => {
return { label: item, value: item };
})
);
}, [allVersions]);
/** 切换版本 */
const changeVersion = useCallback(
(val: string) => {
if (val !== versionValue) {
setVersionValue(val);
getVersionOperator({ title: info.title, version: val });
}
},
[getVersionOperator, info.title, versionValue]
);
return (
<div
className={classNames({
......@@ -149,14 +191,15 @@ const OperatorItem = (props: IOperatorItemProps) => {
);
})}
<MyMenu
options={[
{ label: "1.1.0", value: "1.1.0" },
{ label: "1.2.0", value: "1.2.0" },
{ label: "1.3.0", value: "1.3.0" },
]}
value="1.1.0"
options={getAllVersion || []}
value={versionValue || version || ""}
setValue={(val: string) => {
changeVersion(val);
}}
>
<div>ddd</div>
<div className={styles.versionBox}>{`版本:${
versionValue || version
}`}</div>
</MyMenu>
</div>
</div>
......
......@@ -93,15 +93,15 @@
.parameterBox:last-child {
margin-bottom: 0;
}
.parameterTop {
.inOutParameterTop {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.parameterleft {
.inOutParameterleft {
}
.parameterName {
.inOutParameterName {
color: rgba(30, 38, 51, 1);
font-size: 14px;
line-height: 22px;
......@@ -112,7 +112,7 @@
color: rgba(255, 78, 78, 1);
margin-left: 4px;
}
.parameterdataType {
.inOutParameterdataType {
color: rgba(138, 144, 153, 1);
font-size: 12px;
line-height: 20px;
......@@ -133,3 +133,34 @@
line-height: 22px;
color: rgba(138, 144, 153, 1);
}
.paramsGroup{
padding-bottom: 24px;
}
.parameter{
padding: 16px 0 24px;
border-bottom: 1px solid #F0F2F5;
}
.parameter:last-child{
border-bottom: none;
}
.parameterTop{
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.parameterLeft{
}
.parameterName{
font-size: 14px;
color: #1E2633;
line-height: 22px;
font-weight: 600;
}
.parameterClassTypeName{
font-size: 14px;
color: #8A9099;
line-height: 22px;
}
\ No newline at end of file
......@@ -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-08 11:51:07
* @LastEditTime: 2022-07-09 15:11:17
* @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
......@@ -41,19 +41,47 @@ const WorkFlowEdit = (props: IProps) => {
const [leftContentType, setLeftContentType] = useState("list");
const [popperTitle, setPopperTitle] = useState(
"返回后,当前页面已填写内容将不保存,确认返回吗?"
);
// 返回后,当前页面已填写内容将不保存,确认返回吗?
const [anchorEl, setAnchorEl] = useState<any>(null);
const handleCancel = () => {
setAnchorEl(null);
};
const handleShowPopper = (e: any, title: string) => {
setPopperTitle(title);
setAnchorEl(anchorEl ? null : e.currentTarget);
};
const handleConfirm = () => {
if (popperTitle === "返回后,当前页面已填写内容将不保存,确认返回吗?") {
onBack && onBack();
} else {
console.log("提交");
}
};
return (
<div className={styles.swBox}>
<div className={styles.swHeader}>
<div className={styles.swHeaderLeft}>
<MyPopconfirm
{/* <MyPopconfirm
title="返回后,当前页面已填写内容将不保存,确认返回吗?"
onConfirm={onBack}
>
> */}
<IconButton
color="primary"
aria-label="upload picture"
component="span"
size="small"
onClick={(e: any) =>
handleShowPopper(
e,
"返回后,当前页面已填写内容将不保存,确认返回吗?"
)
}
>
<ArrowBackIosNewIcon
sx={{
......@@ -63,18 +91,20 @@ const WorkFlowEdit = (props: IProps) => {
}}
/>
</IconButton>
</MyPopconfirm>
{/* </MyPopconfirm> */}
</div>
<div className={styles.swHeaderRight}>
<MyPopconfirm
{/* <MyPopconfirm
title="提交前请先确认参数填写无误,确认提交吗?"
onConfirm={() => console.log(2)}
>
> */}
<ButtonComponent
text="保存"
// click={handleSubmitForm}
click={(e: any) =>
handleShowPopper(e, "提交前请先确认参数填写无误,确认提交吗?")
}
></ButtonComponent>
</MyPopconfirm>
{/* </MyPopconfirm> */}
</div>
</div>
<div className={styles.swContent}>
......@@ -108,9 +138,19 @@ const WorkFlowEdit = (props: IProps) => {
)}
</div>
<div className={styles.swFlowBox} id="workFlowEditRight">
<Flow tasks={templateConfigInfo} type="edit" />
<Flow
tasks={templateConfigInfo}
setTasks={setTemplateConfigInfo}
type="edit"
/>
</div>
</div>
<MyPopconfirm
title={popperTitle}
anchorEl={anchorEl}
onCancel={handleCancel}
onConfirm={handleConfirm}
/>
</div>
);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment