Commit 22733b60 authored by 吴永生#A02208's avatar 吴永生#A02208

feat: 查看模版接口联调

parent 2e9b040a
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 09:56:57 * @Date: 2022-06-13 09:56:57
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-13 09:59:29 * @LastEditTime: 2022-06-23 14:42:26
* @FilePath: /bkunyun/src/api/api_manager.ts * @FilePath: /bkunyun/src/api/api_manager.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -29,6 +29,7 @@ const RESTAPI = { ...@@ -29,6 +29,7 @@ const RESTAPI = {
API_WORKBENCH_DELETE_TEMPLATE: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`, //项目管理员-删除工作流模板 API_WORKBENCH_DELETE_TEMPLATE: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`, //项目管理员-删除工作流模板
API_WORKBENCH_ADD_TEMPLATE_LIST: `${BACKEND_API_URI_PREFIX}/cpp/workbench/product/workflowspec`, //项目管理员-添加工作流模板-模板列表 API_WORKBENCH_ADD_TEMPLATE_LIST: `${BACKEND_API_URI_PREFIX}/cpp/workbench/product/workflowspec`, //项目管理员-添加工作流模板-模板列表
API_WORKBENCH_ADD_TEMPLATE: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`, //项目管理员-添加工作流模板-提交 API_WORKBENCH_ADD_TEMPLATE: `${BACKEND_API_URI_PREFIX}/cpp/workbench/project/workflowspec`, //项目管理员-添加工作流模板-提交
API_FETCH_TEMPLATE_INFO: `${BACKEND_API_URI_PREFIX}/cpp/workbench/workflowspec`, //项目管理员-添加工作流模板-提交
}; };
export default RESTAPI; export default RESTAPI;
...@@ -176,7 +176,7 @@ export function useHttp(raw?: boolean) { ...@@ -176,7 +176,7 @@ export function useHttp(raw?: boolean) {
export default rawHttp; export default rawHttp;
export interface IResponse<T> { export interface IResponse<T> {
errorCode: number; errorCode?: number;
massage: string; massage?: string;
data: T; data: T;
} }
...@@ -202,6 +202,16 @@ const getDataFileDelPackage = (params: getDataFileDelPackageParams) => { ...@@ -202,6 +202,16 @@ const getDataFileDelPackage = (params: getDataFileDelPackageParams) => {
}); });
}; };
// 点击使用模版,获取模版数据
const fetchTemplateConfigInfo = (params: {id: string}) => {
return request({
url: `${Api.API_FETCH_TEMPLATE_INFO}/${params.id}`,
method: "get",
});
};
export { export {
current, current,
menu, menu,
...@@ -218,4 +228,5 @@ export { ...@@ -218,4 +228,5 @@ export {
getDataFileMovePackage, getDataFileMovePackage,
getDataFileDel, getDataFileDel,
getDataFileDelPackage, getDataFileDelPackage,
fetchTemplateConfigInfo
}; };
...@@ -14,14 +14,14 @@ import fileSelectIcon from "@/assets/project/fileSelect.svg"; ...@@ -14,14 +14,14 @@ import fileSelectIcon from "@/assets/project/fileSelect.svg";
import questionMark from "@/assets/project/questionMark.svg"; import questionMark from "@/assets/project/questionMark.svg";
type ConfigFormProps = { type ConfigFormProps = {
templateConfigInfo: ITemplateConfig; templateConfigInfo?: ITemplateConfig;
setParameter: any; setParameter: any;
}; };
const ConfigForm = (props: ConfigFormProps) => { const ConfigForm = (props: ConfigFormProps) => {
const { templateConfigInfo, setParameter } = props; const { templateConfigInfo, setParameter } = props;
const [name, setName] = useState<string>( const [name, setName] = useState<string>(
`${templateConfigInfo.title}_${moment(new Date()).format( `${templateConfigInfo?.title}_${moment(new Date()).format(
"YYYY_MM_DD_HH_mm" "YYYY_MM_DD_HH_mm"
)}` )}`
); // 任务名称 ); // 任务名称
...@@ -47,7 +47,7 @@ const ConfigForm = (props: ConfigFormProps) => { ...@@ -47,7 +47,7 @@ const ConfigForm = (props: ConfigFormProps) => {
const renderTasks: IRenderTasks = useMemo(() => { const renderTasks: IRenderTasks = useMemo(() => {
const result: IRenderTasks = []; const result: IRenderTasks = [];
templateConfigInfo.tasks.forEach((task, taskIndex) => { templateConfigInfo?.tasks.forEach((task, taskIndex) => {
if (task.type === "BATCH") { if (task.type === "BATCH") {
result.push({ ...task, flows: [] }); result.push({ ...task, flows: [] });
} else { } else {
...@@ -126,7 +126,7 @@ const ConfigForm = (props: ConfigFormProps) => { ...@@ -126,7 +126,7 @@ const ConfigForm = (props: ConfigFormProps) => {
<div className={styles.templateDescBox}> <div className={styles.templateDescBox}>
<div className={styles.templateDescTitle}>模板描述</div> <div className={styles.templateDescTitle}>模板描述</div>
<div className={styles.templateDesc}> <div className={styles.templateDesc}>
{templateConfigInfo.description} {templateConfigInfo?.description || ""}
</div> </div>
</div> </div>
<div <div
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-21 15:25:25 * @Date: 2022-06-21 15:25:25
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-22 10:40:30 * @LastEditTime: 2022-06-23 18:20:50
* @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/WorkFlow/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/WorkFlow/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
...@@ -10,7 +10,7 @@ import Flow from "../../components/Flow"; ...@@ -10,7 +10,7 @@ import Flow from "../../components/Flow";
import { ITemplateConfig } from "../interface"; import { ITemplateConfig } from "../interface";
interface IProps { interface IProps {
templateConfigInfo: ITemplateConfig; templateConfigInfo?: ITemplateConfig;
} }
const WorkFlow = (props: IProps) => { const WorkFlow = (props: IProps) => {
const { templateConfigInfo } = props; const { templateConfigInfo } = props;
......
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-21 20:03:56 * @Date: 2022-06-21 20:03:56
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com * @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-22 17:29:16 * @LastEditTime: 2022-06-23 18:25:23
* @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/index.tsx * @FilePath: /bkunyun/src/views/Project/ProjectSubmitWork/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
import { useState } from "react"; import { useEffect, useState } from "react";
import styles from "./index.module.css"; import styles from "./index.module.css";
import { templateConfigJson } from "./mock";
import ConfigForm from "./ConfigForm"; import ConfigForm from "./ConfigForm";
import WorkFlow from "./WorkFlow"; import WorkFlow from "./WorkFlow";
import ButtonComponent from "@/components/mui/Button"; import ButtonComponent from "@/components/mui/Button";
...@@ -16,11 +15,28 @@ import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew"; ...@@ -16,11 +15,28 @@ import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
import IconButton from "@mui/material/IconButton"; import IconButton from "@mui/material/IconButton";
import { ITemplateConfig } from "./interface"; import { ITemplateConfig } from "./interface";
import _ from "lodash"; import _ from "lodash";
import useMyRequest from "@/hooks/useMyRequest";
import { fetchTemplateConfigInfo } from "@/api/project_api";
import { useLocation } from "react-router-dom";
import { IResponse } from "@/api/http";
const ProjectSubmitWork = () => { const ProjectSubmitWork = () => {
const [templateConfigInfo, setTemplateConfigInfo] = useState<ITemplateConfig>( const [templateConfigInfo, setTemplateConfigInfo] =
templateConfigJson as any useState<ITemplateConfig>();
); const location: any = useLocation();
/** 获取模版数据 */
const { run } = useMyRequest(fetchTemplateConfigInfo, {
onSuccess: (res: IResponse<ITemplateConfig>) => {
setTemplateConfigInfo(res.data);
},
});
useEffect(() => {
run({
id: location?.state?.id,
});
}, [location?.state?.id, run]);
const setParameter = (value: any, taskId: string, parameterName: string) => { const setParameter = (value: any, taskId: string, parameterName: string) => {
const result: ITemplateConfig = _.cloneDeep(templateConfigInfo); const result: ITemplateConfig = _.cloneDeep(templateConfigInfo);
...@@ -60,18 +76,18 @@ const ProjectSubmitWork = () => { ...@@ -60,18 +76,18 @@ const ProjectSubmitWork = () => {
</IconButton> </IconButton>
<div className={styles.swTemplateTitle}> <div className={styles.swTemplateTitle}>
{templateConfigInfo.title} {templateConfigInfo?.title}
</div> </div>
<div className={styles.swTemplateVersionBox}> <div className={styles.swTemplateVersionBox}>
<span className={styles.swHeaderLable}>版本:</span> <span className={styles.swHeaderLable}>版本:</span>
<span className={styles.swHeaderValue}> <span className={styles.swHeaderValue}>
{templateConfigInfo.version} {templateConfigInfo?.version}
</span> </span>
</div> </div>
<div className={styles.swTemplateUpdateTimeBox}> <div className={styles.swTemplateUpdateTimeBox}>
<span className={styles.swHeaderLable}>更新时间:</span> <span className={styles.swHeaderLable}>更新时间:</span>
<span className={styles.swHeaderValue}> <span className={styles.swHeaderValue}>
{templateConfigInfo.updateTime} {templateConfigInfo?.updateTime}
</span> </span>
</div> </div>
<div className={styles.swHeaderGoback}></div> <div className={styles.swHeaderGoback}></div>
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-17 14:48:57
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-23 14:53:30
* @FilePath: /bkunyun/src/views/Project/ProjectWorkbench/workbenchTemplate/components/templateBox.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { memo, useCallback, useEffect, useMemo, useState } from "react"; import { memo, useCallback, useEffect, useMemo, useState } from "react";
import styles from "../index.module.css"; import styles from "../index.module.css";
import { Box, Typography } from "@mui/material"; import { Box, Typography } from "@mui/material";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import usePass from "@/hooks/usePass"; import usePass from "@/hooks/usePass";
import { useNavigate } from "react-router-dom";
const TemplateBox = (props: any) => { const TemplateBox = (props: any) => {
const info = props.data const info = props.data;
const isPass = usePass(); const isPass = usePass();
const navigate = useNavigate();
const addTemplateBlock = useCallback(
(id: string) => {
navigate(`/product/cadd/projectSubmitWork`, {
state: { id },
});
},
[navigate]
);
return ( return (
<Box className={styles.templateBlock} > <Box className={styles.templateBlock}>
<Box> <Box>
<Typography sx={{ fontSize: '14px', fontWeight: '600', color: '#1E2633', marginBottom: "4px", overflow: 'hidden', textOverflow: 'ellipsis' }}>{info.title}</Typography> <Typography
<Box sx={{ display: 'flex', marginBottom: "8px" }} > sx={{
<Typography sx={{ fontSize: '12px', fontWeight: '400', color: '#1370FF', marginRight: "24px" }}>版本:{info.version}</Typography> fontSize: "14px",
<Typography sx={{ fontSize: '12px', fontWeight: '400', color: '#1370FF' }}>更新时间:{info.updateTime}</Typography> fontWeight: "600",
color: "#1E2633",
marginBottom: "4px",
overflow: "hidden",
textOverflow: "ellipsis",
}}
>
{info.title}
</Typography>
<Box sx={{ display: "flex", marginBottom: "8px" }}>
<Typography
sx={{
fontSize: "12px",
fontWeight: "400",
color: "#1370FF",
marginRight: "24px",
}}
>
版本:{info.version}
</Typography>
<Typography
sx={{ fontSize: "12px", fontWeight: "400", color: "#1370FF" }}
>
更新时间:{info.updateTime}
</Typography>
</Box> </Box>
<Typography className={styles.templateDescText} >{info.description}</Typography> <Typography className={styles.templateDescText}>
{info.description}
</Typography>
</Box> </Box>
<Box sx={{ <Box
display: 'flex', justifyContent: 'end' sx={{
}} > display: "flex",
{ justifyContent: "end",
isPass("PROJECT_WORKBENCH_FLOES_USE", 'MANAGER') && <Button }}
>
{isPass("PROJECT_WORKBENCH_FLOES_USE", "MANAGER") && (
<Button
style={{ backgroundColor: "#F0F2F5", color: "#565C66" }} style={{ backgroundColor: "#F0F2F5", color: "#565C66" }}
variant="contained" variant="contained"
onClick={() => { props.startDialog(info.id) }} onClick={() => {
props.startDialog(info.id);
}}
size="small" size="small"
> >
删除模版 删除模版
</Button> </Button>
} )}
{ {isPass("PROJECT_WORKBENCH_FLOES_USE", "USER") && (
isPass("PROJECT_WORKBENCH_FLOES_USE", 'USER') && <Button <Button
style={{ backgroundColor: "#1370FF", marginLeft: "12px" }} style={{ backgroundColor: "#1370FF", marginLeft: "12px" }}
variant="contained" variant="contained"
// onClick={addTemplateBlock} onClick={() => addTemplateBlock(info.id)}
size="small" size="small"
> >
使用模版 使用模版
</Button> </Button>
} )}
</Box> </Box>
</Box> </Box>
); );
......
.batchNode { .batchNode {
background-color: #fff; background-color: #fff;
border-radius: 4px; border-radius: 4px;
padding: 16px; /* padding: 12px 20px; */
border: 1px solid #e6e8eb; border: 1px solid #e6e8eb;
border-left: 4px solid #e6e8eb; border-left: 4px solid #e6e8eb;
display: flex;
align-items: center;
} }
.selectBatchNode { .selectBatchNode {
...@@ -11,7 +13,7 @@ ...@@ -11,7 +13,7 @@
} }
.batchRotate { .batchRotate {
transform: rotate(-90deg); transform: translateX(-50%) rotate(-90deg);
} }
.flowNode { .flowNode {
......
import { ITemplateConfig, IEdge } from "../../ProjectSubmitWork/interface"; import {
ITemplateConfig,
IEdge,
ITask,
} from "../../ProjectSubmitWork/interface";
import ReactFlow, { import ReactFlow, {
addEdge,
MiniMap, MiniMap,
Controls, Controls,
Background, Background,
...@@ -8,11 +11,13 @@ import ReactFlow, { ...@@ -8,11 +11,13 @@ import ReactFlow, {
useEdgesState, useEdgesState,
Handle, Handle,
Position, Position,
ReactFlowProps,
} from "react-flow-renderer"; } from "react-flow-renderer";
import { useCallback, useMemo } from "react"; import { useCallback, useMemo } from "react";
import classNames from "classnames";
import { IBatchNode, ILine } from "./interface";
import styles from "./index.module.css"; import styles from "./index.module.css";
import classNames from "classnames";
/* /*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com * @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-22 10:15:22 * @Date: 2022-06-22 10:15:22
...@@ -21,33 +26,49 @@ import classNames from "classnames"; ...@@ -21,33 +26,49 @@ import classNames from "classnames";
* @FilePath: /bkunyun/src/views/Project/components/Flow/index.tsx * @FilePath: /bkunyun/src/views/Project/components/Flow/index.tsx
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
interface IProps { interface IProps extends ReactFlowProps {
data: ITemplateConfig; data?: ITemplateConfig;
} }
const BatchNode = (props: any) => { /** 自定义batch节点 */
const BatchNode = (props: IBatchNode) => {
const { data } = props; const { data } = props;
const { dotStatus, style, isFlowNode, label } = data;
return ( return (
<div <div
className={classNames({ className={classNames({
[styles.batchNode]: true, [styles.batchNode]: true,
[styles.selectBatchNode]: false, [styles.selectBatchNode]: false,
})} })}
style={data.style} style={style}
title="2222"
> >
<Handle type="target" position={Position.Top} /> {dotStatus?.isInput ? (
<Handle
style={{ background: "#fff ", border: "1px solid #D1D6DE" }}
type="target"
position={Position.Top}
/>
) : null}
<div <div
className={classNames({ className={classNames({
[styles.batchRotate]: false, [styles.batchRotate]: isFlowNode,
})} })}
> >
{data.label || ""} {label || ""}
</div> </div>
<Handle type="source" position={Position.Bottom} id="a" /> {dotStatus?.isOutput ? (
<Handle
style={{ background: "#fff ", border: "1px solid #D1D6DE" }}
type="source"
position={Position.Bottom}
/>
) : null}
</div> </div>
); );
}; };
/** 自定义flow节点 */
const FlowNode = (props: any) => { const FlowNode = (props: any) => {
const { data } = props; const { data } = props;
return ( return (
...@@ -56,9 +77,22 @@ const FlowNode = (props: any) => { ...@@ -56,9 +77,22 @@ const FlowNode = (props: any) => {
[styles.flowNode]: true, [styles.flowNode]: true,
})} })}
> >
<Handle type="target" position={Position.Top} /> {data?.dotStatus?.isInput ? (
<div>{data.label || ""}</div> <Handle
<Handle type="source" position={Position.Bottom} id="a" /> style={{ background: "#C2C6CC " }}
type="target"
position={Position.Top}
/>
) : null}
<div>{data?.label || ""}</div>
{data?.dotStatus?.isOutput ? (
<Handle
style={{ background: "#C2C6CC " }}
type="source"
position={Position.Bottom}
id="a"
/>
) : null}
</div> </div>
); );
}; };
...@@ -66,17 +100,53 @@ const FlowNode = (props: any) => { ...@@ -66,17 +100,53 @@ const FlowNode = (props: any) => {
const Flow = (props: IProps) => { const Flow = (props: IProps) => {
const { data } = props; const { data } = props;
/** 自定义的节点类型 */
const nodeTypes = useMemo(() => { const nodeTypes = useMemo(() => {
return { batchNode: BatchNode, flowNode: FlowNode }; return { batchNode: BatchNode, flowNode: FlowNode };
}, []); }, []);
const getBatchStyle = useCallback( /** 获取是否有输入节点或者是否有输出节点 */
const nodesInputAndOutputStatus = useCallback(
(id: string) => {
/** 所有的连线 */
const lineArr: IEdge[] = [];
data?.tasks?.length &&
data?.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,
};
},
[data?.tasks]
);
/** 获取是否有流节点 */
const isFlowNode = useCallback(
(id: string) => { (id: string) => {
return (
data?.tasks?.length &&
data?.tasks?.some((item) => {
return item.parentNode === id;
})
);
},
[data?.tasks]
);
/** 通过子flow节点计算batch节点的样式 */
const getBatchStyle = useCallback(
(value: ITask) => {
const positionXArr: number[] = []; const positionXArr: number[] = [];
const positionYArr: number[] = []; const positionYArr: number[] = [];
data?.tasks?.length && data?.tasks?.length &&
data?.tasks?.forEach((item) => { data?.tasks?.forEach((item) => {
if (item.parentNode === id) { if (item.parentNode === value.id) {
positionXArr.push(item.position?.x || 0); positionXArr.push(item.position?.x || 0);
positionYArr.push(item.position?.y || 0); positionYArr.push(item.position?.y || 0);
} }
...@@ -88,14 +158,14 @@ const Flow = (props: IProps) => { ...@@ -88,14 +158,14 @@ const Flow = (props: IProps) => {
return a - b; return a - b;
}); });
let width = 176, let width = 176,
height = 44; height = 22;
if (positionXArr?.length) { if (positionXArr?.length) {
const val = positionXArr[positionXArr.length - 1] - positionXArr[0]; const val = positionXArr[positionXArr.length - 1] + 150;
width = val ? val : width; width = val > 176 ? val : width;
} }
if (positionXArr?.length) { if (positionXArr?.length) {
const val = positionYArr[positionYArr.length - 1] - positionYArr[0]; const val = positionYArr[positionYArr.length - 1];
height = val ? val : height; height = val > 22 ? val : height;
} }
return { return {
width, width,
...@@ -105,34 +175,43 @@ const Flow = (props: IProps) => { ...@@ -105,34 +175,43 @@ const Flow = (props: IProps) => {
[data?.tasks] [data?.tasks]
); );
/** 生成初始化node节点 */
const initialNodes = useMemo(() => { const initialNodes = useMemo(() => {
const val: any = []; const val: any = [];
data?.tasks?.length && data?.tasks?.length &&
data?.tasks.forEach((item) => { data?.tasks.forEach((item) => {
if (item.type === "BATCH") {
console.log(getBatchStyle(item.id));
}
val.push({ val.push({
id: item.id, id: item.id,
type: item.type === "BATCH" ? "batchNode" : "flowNode", type: item.type === "BATCH" ? "batchNode" : "flowNode",
data: { label: item.title || "", style: getBatchStyle(item.id) }, data: {
label: item.title || "",
/** 是否有流节点 */
isFlowNode: isFlowNode(item.id),
/** 输入输出圆点状态 */
dotStatus: nodesInputAndOutputStatus(item.id),
/** 样式 */
style: {
...getBatchStyle(item),
padding: isFlowNode(item.id) ? "20px" : "12px 20px",
},
},
position: item.position, position: item.position,
// style: { width: 176, height: 500 }, ...(item.type === "BATCH" ? { style: { zIndex: -1 } } : {}),
...(item.type === "BATCH" ? { style: getBatchStyle(item.id) } : {}),
...(item.parentNode ? { parentNode: item.parentNode } : {}), ...(item.parentNode ? { parentNode: item.parentNode } : {}),
...(item.type === "BATCH" ? { extent: "parent" } : {}), ...(item.type === "BATCH" ? { extent: "parent" } : {}),
}); });
}); });
return val; return val;
}, [data?.tasks, getBatchStyle]); }, [data?.tasks, getBatchStyle, isFlowNode, nodesInputAndOutputStatus]);
/** 生成初始化的连线节点 */
const initialEdges = useMemo(() => { const initialEdges = useMemo(() => {
const val: any = []; const val: ILine[] = [];
data?.tasks?.length && data?.tasks?.length &&
data?.tasks.forEach((item) => { data?.tasks.forEach((item) => {
val.push(...item.edges); val.push(...item.edges);
}); });
val.map((item: IEdge) => { val.map((item: ILine) => {
return { return {
id: item.id, id: item.id,
label: item.label, label: item.label,
...@@ -143,43 +222,18 @@ const Flow = (props: IProps) => { ...@@ -143,43 +222,18 @@ const Flow = (props: IProps) => {
return val; return val;
}, [data]); }, [data]);
console.log(initialEdges, initialNodes, 11111); const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [nodes, setNodes, onNodesChange] = useNodesState<any>(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = (params: any) => setEdges((eds) => addEdge(params, eds));
const onInit = (reactFlowInstance: any) =>
console.log("flow loaded:", reactFlowInstance);
return ( return (
<ReactFlow <ReactFlow
nodes={nodes} nodes={nodes}
edges={edges} edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
onInit={onInit}
fitView fitView
attributionPosition="top-right" proOptions={{ hideAttribution: true, account: "" }}
nodeTypes={nodeTypes} nodeTypes={nodeTypes}
{...props}
> >
<MiniMap
// nodeStrokeColor={(n) => {
// if (n.style?.background) return n.style.background;
// if (n.type === "input") return "#0041d0";
// if (n.type === "output") return "#ff0072";
// if (n.type === "default") return "#1a192b";
// return "#eee";
// }}
// nodeColor={(n) => {
// if (n.style?.background) return n.style.background;
// return "#fff";
// }}
nodeBorderRadius={2}
/>
<Controls /> <Controls />
<Background color="#aaa" gap={16} /> <Background color="#aaa" gap={16} />
</ReactFlow> </ReactFlow>
......
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-23 11:00:29
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-23 11:19:59
* @FilePath: /bkunyun/src/views/Project/components/Flow/interface.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { CSSProperties } from "react";
/** 线的参数 */
export interface ILine {
id: string,
label: string,
source: string,
target: string,
}
export interface IDotStatus {
isInput: boolean;
isOutput: boolean
}
export interface IBatchNodeData {
label: string;
isFlowNode: boolean;
dotStatus: IDotStatus;
style?: CSSProperties;
}
export interface IBatchNode {
data: IBatchNodeData
}
\ No newline at end of file
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