Browse Source

fix: 全局参数验证重复name

pull/82/head
cp3hnu 1 year ago
parent
commit
eadcff1e92
4 changed files with 117 additions and 114 deletions
  1. +1
    -14
      react-ui/src/pages/Experiment/training/index.jsx
  2. +1
    -1
      react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.less
  3. +20
    -2
      react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx
  4. +95
    -97
      react-ui/src/pages/Pipeline/editPipeline/index.jsx

+ 1
- 14
react-ui/src/pages/Experiment/training/index.jsx View File

@@ -21,8 +21,8 @@ function ExperimentText() {
const navgite = useNavigate(); const navgite = useNavigate();
const locationParams = useParams(); //新版本获取路由参数接口 const locationParams = useParams(); //新版本获取路由参数接口
const [paramsModalOpen, openParamsModal, closeParamsModal] = useVisible(false); const [paramsModalOpen, openParamsModal, closeParamsModal] = useVisible(false);

const graphRef = useRef(); const graphRef = useRef();

const getGraphData = (data) => { const getGraphData = (data) => {
if (graph) { if (graph) {
// 修改历史数据有蓝色边框的问题 // 修改历史数据有蓝色边框的问题
@@ -202,9 +202,6 @@ function ExperimentText() {
}, },
}, },
defaultEdge: { defaultEdge: {
// type: 'quadratic',
// type: 'cubic-vertical',

style: { style: {
endArrow: { endArrow: {
// 设置终点箭头 // 设置终点箭头
@@ -226,16 +223,6 @@ function ExperimentText() {
}, },
}, },
}, },
defaultCombo: {
type: 'rect',
fixCollapseSize: 70,
style: {
fill: '#00e0ff0d',
stroke: '#00e0ff',
lineDash: [5, 10],
cursor: 'pointer',
},
},
}); });
graph.on('node:click', (e) => { graph.on('node:click', (e) => {
if (e.target.get('name') !== 'anchor-point' && e.item) { if (e.target.get('name') !== 'anchor-point' && e.item) {


+ 1
- 1
react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.less View File

@@ -11,7 +11,7 @@


:global { :global {
.anticon.anticon-question-circle { .anticon.anticon-question-circle {
margin-top: -14px;
margin-top: -12px;
} }
} }
} }


+ 20
- 2
react-ui/src/pages/Pipeline/components/GlobalParamsDrawer/index.tsx View File

@@ -76,9 +76,27 @@ const GlobalParamsDrawer = forwardRef(
{...restField} {...restField}
name={[name, 'param_name']} name={[name, 'param_name']}
label="参数名称" label="参数名称"
rules={[{ required: true, message: '请输入参数名称' }]}
validateTrigger={[]}
rules={[
{ required: true, message: '请输入参数名称' },
{
validator: (_, value) => {
const list = form.getFieldValue('global_param') || [];
const names = list.filter((item: any) => item?.param_name === value);
if (value && names.length > 1) {
return Promise.reject('参数名称不能重复');
} else {
return Promise.resolve();
}
},
},
]}
> >
<Input placeholder="请输入参数名称" allowClear />
<Input
placeholder="请输入参数名称"
allowClear
onBlur={() => form.validateFields()}
/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
{...restField} {...restField}


+ 95
- 97
react-ui/src/pages/Pipeline/editPipeline/index.jsx View File

@@ -13,13 +13,12 @@ import GlobalParamsDrawer from '../components/GlobalParamsDrawer';
import ModelMenu from '../components/ModelMenu'; import ModelMenu from '../components/ModelMenu';
import styles from './index.less'; import styles from './index.less';
import Props from './props'; import Props from './props';
import { findAllParentNodes, findFirstDuplicate } from './utils';
import { findAllParentNodes } from './utils';


let graph = null; let graph = null;


const EditPipeline = () => { const EditPipeline = () => {
const navgite = useNavigate(); const navgite = useNavigate();
let contextMenu = {};
const locationParams = useParams(); //新版本获取路由参数接口 const locationParams = useParams(); //新版本获取路由参数接口
const graphRef = useRef(); const graphRef = useRef();
const paramsDrawerRef = useRef(); const paramsDrawerRef = useRef();
@@ -31,10 +30,23 @@ const EditPipeline = () => {
let dragSourceNode; let dragSourceNode;


useEffect(() => { useEffect(() => {
initMenu();
initGraph();
getFirstWorkflow(locationParams.id); getFirstWorkflow(locationParams.id);

const changeSize = () => {
if (!graph || graph.get('destroyed')) return;
if (!graphRef.current) return;
graph.changeSize(graphRef.current.clientWidth, graphRef.current.clientHeight);
graph.fitView();
};

window.addEventListener('resize', changeSize);
return () => {
window.removeEventListener('resize', changeSize);
};
}, []); }, []);


// 拖拽结束,添加新节点
const onDragEnd = (val) => { const onDragEnd = (val) => {
const { x, y } = val; const { x, y } = val;
const point = graph.getPointByClient(x, y); const point = graph.getPointByClient(x, y);
@@ -45,11 +57,14 @@ const EditPipeline = () => {
y: point.y, y: point.y,
id: val.component_name + '-' + s8(), id: val.component_name + '-' + s8(),
isCluster: false, isCluster: false,
formError: true,
}; };
// console.log('model', model); // console.log('model', model);
graph.addItem('node', model, false); graph.addItem('node', model, false);
}; };
const formChange = (val) => {

// 节点数据发生变化
const handleFormChange = (val) => {
if (graph) { if (graph) {
const data = graph.save(); const data = graph.save();
const index = data.nodes.findIndex((item) => { const index = data.nodes.findIndex((item) => {
@@ -68,6 +83,8 @@ const EditPipeline = () => {
graph.translate(lastPoint.x - newPoint.x, lastPoint.y - newPoint.y); graph.translate(lastPoint.x - newPoint.x, lastPoint.y - newPoint.y);
} }
}; };

// 保存
const savePipeline = async (val) => { const savePipeline = async (val) => {
const [res, error] = await to(paramsDrawerRef.current.validateFields()); const [res, error] = await to(paramsDrawerRef.current.validateFields());
if (error) { if (error) {
@@ -76,13 +93,6 @@ const EditPipeline = () => {
return; return;
} }


const duplicateName = findFirstDuplicate(res.global_param || []);
if (duplicateName) {
message.error('全局参数配置有重复的参数名称:' + duplicateName);
openParamsDrawer();
return;
}

// const [propsRes, propsError] = await to(propsRef.current.getFieldsValue()); // const [propsRes, propsError] = await to(propsRef.current.getFieldsValue());
// if (propsError) { // if (propsError) {
// message.error('基本信息必填项需配置'); // message.error('基本信息必填项需配置');
@@ -108,6 +118,8 @@ const EditPipeline = () => {
}); });
}, 500); }, 500);
}; };

// 渲染数据
const getGraphData = (data) => { const getGraphData = (data) => {
if (graph) { if (graph) {
// 修改历史数据有蓝色边框的问题 // 修改历史数据有蓝色边框的问题
@@ -122,6 +134,8 @@ const EditPipeline = () => {
}, 500); }, 500);
} }
}; };

// 处理并行边,暂时没有用
const processParallelEdgesOnAnchorPoint = ( const processParallelEdgesOnAnchorPoint = (
edges, edges,
offsetDiff = 15, offsetDiff = 15,
@@ -242,11 +256,11 @@ const EditPipeline = () => {
} }
return false; return false;
}; };

// 复制节点
const cloneElement = (item) => { const cloneElement = (item) => {
console.log(item);
let data = graph.save(); let data = graph.save();
const nodeId = s8(); const nodeId = s8();
console.log(item.getModel());
data.nodes.push({ data.nodes.push({
...item.getModel(), ...item.getModel(),
label: item.getModel().label + '-copy', label: item.getModel().label + '-copy',
@@ -256,66 +270,22 @@ const EditPipeline = () => {
}); });
graph.changeData(data); graph.changeData(data);
}; };
const getFirstWorkflow = (val) => {
getWorkflowById(val).then((ret) => {
if (ret && ret.data) {
setGlobalParam(ret.data.global_param || []);
}
if (graph && ret.data && ret.data.dag) {
getGraphData(JSON.parse(ret.data.dag));
}
});
};
// 上下文菜单
const initMenu = () => {
// const selectedNodes = this.selectedNodes;
contextMenu = new G6.Menu({
getContent(evt) {
const type = evt.item.getType();
const cloneDisplay = type === 'node' ? 'block' : 'none';
return `
<ul style="position: absolute;
width: 100px;
padding-left:0;
display:flex;
flex-direction: column;
align-items:center;
left: 0px;
top: 0px;
background-color: #ffffff;
font-size: 14px;
color: #333333;
overflow-y: auto;">
<li style="padding: 10px 20px;cursor: pointer; display: ${cloneDisplay}" code="clone">复制</li>
<li style="padding: 10px 20px;cursor: pointer;" code="delete">删除</li>
</ul>`;
},
handleMenuClick: (target, item) => {
switch (target.getAttribute('code')) {
case 'delete':
graph.removeItem(item);
break;
case 'clone':
cloneElement(item);
break;
default:
break;
}
},
// offsetX and offsetY include the padding of the parent container
// 需要加上父级容器的 padding-left 16 与自身偏移量 10
offsetX: 16 + 10,
// 需要加上父级容器的 padding-top 24 、画布兄弟元素高度、与自身偏移量 10
offsetY: 0,
// the types of items that allow the menu show up
// 在哪些类型的元素上响应
itemTypes: ['node', 'edge'],
});


initGraph();
// 获取流水线详情
const getFirstWorkflow = async (val) => {
const [res] = await to(getWorkflowById(val));
if (res && res.data) {
const { global_param, dag } = res.data;
setGlobalParam(global_param || []);
if (dag) {
getGraphData(JSON.parse(dag));
}
}
}; };


// 初始化图
const initGraph = () => { const initGraph = () => {
const contextMenu = initMenu();
G6.registerNode( G6.registerNode(
'rect-node', 'rect-node',
{ {
@@ -515,6 +485,7 @@ const EditPipeline = () => {
}, },
cursor: 'pointer', cursor: 'pointer',
lineWidth: 1, lineWidth: 1,
lineAppendWidth: 4,
opacity: 1, opacity: 1,
stroke: '#CDD0DC', stroke: '#CDD0DC',
radius: 1, radius: 1,
@@ -527,19 +498,13 @@ const EditPipeline = () => {
}, },
}, },
}, },
defaultCombo: {
type: 'rect',
fixCollapseSize: 70,
style: {
fill: '#00e0ff0d',
stroke: '#00e0ff',
lineDash: [5, 10],
cursor: 'pointer',
},
},
}); });

bindEvents();
};

const bindEvents = () => {
graph.on('node:click', (e) => { graph.on('node:click', (e) => {
e.stopPropagation();
if (e.target.get('name') !== 'anchor-point' && e.item) { if (e.target.get('name') !== 'anchor-point' && e.item) {
// 获取所有的上游节点 // 获取所有的上游节点
const parentNodes = findAllParentNodes(graph, e.item); const parentNodes = findAllParentNodes(graph, e.item);
@@ -558,16 +523,6 @@ const EditPipeline = () => {
type: type:
targetAnchorIdx === 0 || targetAnchorIdx === 1 ? 'cubic-vertical' : 'cubic-horizontal', targetAnchorIdx === 0 || targetAnchorIdx === 1 ? 'cubic-vertical' : 'cubic-horizontal',
}); });

// update the curveOffset for parallel edges
// const edges = graph.save().edges;
// processParallelEdgesOnAnchorPoint(edges);
// graph.getEdges().forEach((edge, i) => {
// graph.updateItem(edge, {
// curveOffset: edges[i].curveOffset,
// curvePosition: edges[i].curvePosition,
// });
// });
}); });
// 删除边时,修改 anchor-point 的 links 值 // 删除边时,修改 anchor-point 的 links 值
graph.on('afterremoveitem', (e) => { graph.on('afterremoveitem', (e) => {
@@ -639,13 +594,56 @@ const EditPipeline = () => {
graph.setItemState(e.item, 'drop', false); graph.setItemState(e.item, 'drop', false);
dropAnchorIdx = undefined; dropAnchorIdx = undefined;
}); });
window.onresize = () => {
if (!graph || graph.get('destroyed')) return;
if (!graphRef.current) return;
graph.changeSize(graphRef.current.clientWidth, graphRef.current.clientHeight);
graph.fitView();
};
}; };

// 上下文菜单
const initMenu = () => {
const contextMenu = new G6.Menu({
getContent(evt) {
const type = evt.item.getType();
const cloneDisplay = type === 'node' ? 'block' : 'none';
return `
<ul style="position: absolute;
width: 100px;
padding-left:0;
display:flex;
flex-direction: column;
align-items:center;
left: 0px;
top: 0px;
background-color: #ffffff;
font-size: 14px;
color: #333333;
overflow-y: auto;">
<li style="padding: 10px 20px;cursor: pointer; display: ${cloneDisplay}" code="clone">复制</li>
<li style="padding: 10px 20px;cursor: pointer;" code="delete">删除</li>
</ul>`;
},
handleMenuClick: (target, item) => {
switch (target.getAttribute('code')) {
case 'delete':
graph.removeItem(item);
break;
case 'clone':
cloneElement(item);
break;
default:
break;
}
},
// offsetX and offsetY include the padding of the parent container
// 需要加上父级容器的 padding-left 16 与自身偏移量 10
offsetX: 16 + 10,
// 需要加上父级容器的 padding-top 24 、画布兄弟元素高度、与自身偏移量 10
offsetY: 0,
// the types of items that allow the menu show up
// 在哪些类型的元素上响应
itemTypes: ['node', 'edge'],
});

return contextMenu;
};

return ( return (
<div className={styles['pipeline-container']}> <div className={styles['pipeline-container']}>
<ModelMenu onComponentDragEnd={onDragEnd}></ModelMenu> <ModelMenu onComponentDragEnd={onDragEnd}></ModelMenu>
@@ -687,7 +685,7 @@ const EditPipeline = () => {
</div> </div>
<div className={styles['pipeline-container__workflow__graph']} ref={graphRef}></div> <div className={styles['pipeline-container__workflow__graph']} ref={graphRef}></div>
</div> </div>
<Props ref={propsRef} onParentChange={formChange}></Props>
<Props ref={propsRef} onParentChange={handleFormChange}></Props>
<GlobalParamsDrawer <GlobalParamsDrawer
ref={paramsDrawerRef} ref={paramsDrawerRef}
open={paramsDrawerOpen} open={paramsDrawerOpen}


Loading…
Cancel
Save