From 1f5c6acb98359151c8aedcf389b0427a5c56a76a Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Wed, 12 Jun 2024 16:09:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A8=A1=E5=9E=8B=E6=BC=94=E5=8C=96?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=95=B0=E6=8D=AE=E9=9B=86=E7=9A=84=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/mock/model.ts | 338 ++++++++++++++++++ react-ui/package.json | 2 +- .../Model/components/ModelEvolution/utils.tsx | 89 +++-- 3 files changed, 379 insertions(+), 50 deletions(-) create mode 100644 react-ui/mock/model.ts diff --git a/react-ui/mock/model.ts b/react-ui/mock/model.ts new file mode 100644 index 00000000..02054802 --- /dev/null +++ b/react-ui/mock/model.ts @@ -0,0 +1,338 @@ +import { defineMock } from 'umi'; + +export default defineMock({ + 'POST /api/mmp/modelDependency/queryModelAtlas': { + code: 200, + msg: '操作成功', + data: { + current_model_id: 29, + exp_ins_id: 229, + version: 'v0.2.0', + ref_item: null, + train_task: { + name: '模型训练测试导出0529', + ins_id: 229, + task_id: 'model-train-5d76f002', + }, + train_dataset: [ + { + dataset_id: 20, + dataset_version: 'v0.1.0', + dataset_name: '手写体识别模型依赖测试训练数据集', + }, + ], + train_params: ['256', '2'], + train_image: '172.20.32.187/machine-learning/pytorch:pytorch_1.9.1_cuda11.1_detection_aim', + test_dataset: [ + { + dataset_id: 20, + dataset_version: 'v0.1.0', + dataset_name: '手写体识别模型依赖测试训练数据集', + }, + ], + project_dependency: { + url: 'https://openi.pcl.ac.cn/somunslotus/somun202304241505581.git', + name: 'somun202304241505581', + branch: 'train_ci_test', + }, + parent_models_map: [ + { + model_id: 29, + model_version: 'v0.1.0', + model_name: 'mnist模型演化', + }, + ], + parent_models: [ + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.1.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: null, + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + ], + children_models: [ + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.3.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: [], + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.31.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: [], + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.4.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: [ + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.6.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: [], + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.7.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: [], + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + ], + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.5.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: [ + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.10.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: [], + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + { + current_model_id: 29, + exp_ins_id: null, + version: 'v0.11.0', + ref_item: null, + train_task: {}, + train_dataset: [], + train_params: [], + train_image: null, + test_dataset: [], + project_dependency: {}, + parent_models_map: [], + parent_models: [], + children_models: [], + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + ], + workflow_id: null, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172558449/mnist_epoch1_0.00.pkl', + file_name: 'mnist_epoch1_0.00.pkl', + file_size: '176.63 KB', + create_by: 'admin', + create_time: '2024-06-12T06:09:56.000+00:00', + }, + }, + ], + workflow_id: 144, + model_version_dependcy_vo: { + name: 'mnist模型演化', + description: '手写体识别模型演化', + available_range: 0, + model_type: '37', + model_tag: '46', + model_type_name: 'PyTorch', + model_tag_name: '图像转文本', + url: 'models/admin/1718172760650/mnist_cnn.pt', + file_name: 'mnist_cnn.pt', + file_size: '176.76 KB', + create_by: 'admin', + create_time: '2024-06-12T06:12:42.000+00:00', + }, + }, + }, +}); diff --git a/react-ui/package.json b/react-ui/package.json index ac2bc997..cc1a3278 100644 --- a/react-ui/package.json +++ b/react-ui/package.json @@ -33,7 +33,7 @@ "serve": "umi-serve", "start": "cross-env UMI_ENV=dev max dev", "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev max dev", - "start:no-mock": "cross-env MOCK=none UMI_ENV=dev max dev", + "start:mock": "cross-env REACT_APP_ENV=dev UMI_ENV=dev max dev", "start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev max dev", "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev", "test": "jest", diff --git a/react-ui/src/pages/Model/components/ModelEvolution/utils.tsx b/react-ui/src/pages/Model/components/ModelEvolution/utils.tsx index 4570b5de..78fdb87a 100644 --- a/react-ui/src/pages/Model/components/ModelEvolution/utils.tsx +++ b/react-ui/src/pages/Model/components/ModelEvolution/utils.tsx @@ -9,8 +9,8 @@ export const vGap = nodeHeight + 20; export const hGap = nodeHeight + 20; export const ellipseWidth = nodeWidth; -// 数据集节点矩形数组 -const datasetRects: Rect[] = []; +// 数据集节点 +const datasetNodes: NodeConfig[] = []; export enum NodeType { current = 'current', @@ -22,8 +22,8 @@ export enum NodeType { } export type Rect = { - x: number; - y: number; + x: number; // 矩形中心的 x 坐标 + y: number; // 矩形中心的 y 坐标 width: number; height: number; }; @@ -142,14 +142,6 @@ export function normalizeTreeData(apiData: ModelDepsAPIData): ModelDepsData { normalizedData.id = `$M_${normalizedData.current_model_id}_${normalizedData.version}`; normalizedData.label = getLabel(normalizedData); normalizedData.style = getStyle(NodeType.current); - // let first1 = { ...normalizedData.children[0] }; - // let first2 = { ...normalizedData.children[0] }; - // let first3 = { ...normalizedData.children[0] }; - // first1.current_model_id = 202020; - // first2.current_model_id = 202021; - // first3.current_model_id = 202022; - // normalizedData.children.push(first1, first2, first3); - normalizeChildren(normalizedData.children as ModelDepsData[]); // 将 parent_models 转换成树形结构 @@ -191,14 +183,12 @@ export function getGraphData(data: ModelDepsData): GraphData { const edges: EdgeConfig[] = []; Util.traverseTree(treeLayoutData, (node: NodeConfig, parent: NodeConfig) => { const data = node.data as ModelDepsData; - console.log('data', data); - // 当前模型显示数据集和项目 if (data.model_type === NodeType.current) { addDatasetDependency(data, node, nodes, edges); addProjectDependency(data, node, nodes, edges); } else if (data.model_type === NodeType.children) { - adjustChildrenPosition(node); + adjustDatasetPosition(node); } nodes.push({ ...data, @@ -224,17 +214,17 @@ const addDatasetDependency = ( ) => { const { train_dataset, test_dataset } = data; train_dataset.forEach((item) => { - item.id = `$DTrain_${item.dataset_id}`; + item.id = `$DTrain_${item.dataset_id}_${item.dataset_version}`; item.model_type = NodeType.trainDataset; item.style = getStyle(NodeType.trainDataset); }); test_dataset.forEach((item) => { - item.id = `$DTest_${item.dataset_id}`; + item.id = `$DTest_${item.dataset_id}_${item.dataset_version}`; item.model_type = NodeType.testDataset; item.style = getStyle(NodeType.testDataset); }); - datasetRects.length = 0; + datasetNodes.length = 0; const len = train_dataset.length + test_dataset.length; [...train_dataset, ...test_dataset].forEach((item, index) => { const node = { ...item }; @@ -246,9 +236,10 @@ const addDatasetDependency = ( fittingString(node.dataset_version, ellipseWidth - 12, 8); const half = len / 2 - 0.5; - node.x = currentNode.x! - (half - index) * (ellipseWidth + hGap); + node.x = currentNode.x! - (half - index) * (ellipseWidth + hGap / 2); node.y = currentNode.y! - nodeHeight - vGap; nodes.push(node); + datasetNodes.push(node); edges.push({ source: currentNode.id, target: node.id, @@ -256,12 +247,6 @@ const addDatasetDependency = ( targetAnchor: 3, type: 'cubic-vertical', }); - datasetRects.push({ - x: node.x - ellipseWidth / 2, - y: node.y - nodeHeight / 2, - width: ellipseWidth, - height: nodeHeight, - }); }); }; @@ -275,7 +260,7 @@ const addProjectDependency = ( const { project_dependency } = data; if (project_dependency?.url) { const node = { ...project_dependency }; - node.id = `$P_${node.url}`; + node.id = `$P_${node.url}_${node.branch}`; node.model_type = NodeType.project; node.type = 'rect'; node.label = fittingString(node.name, nodeWidth - 12, 8); @@ -296,42 +281,48 @@ const addProjectDependency = ( }; // 判断两个矩形是否相交 -function isRectanglesIntersect(rect1: Rect, rect2: Rect) { - return !( - rect1.x + rect1.width < rect2.x || - rect1.x > rect2.x + rect2.width || - rect1.y + rect1.height < rect2.y || - rect1.y > rect2.y + rect2.height - ); +function isRectanglesOverlap(rect1: Rect, rect2: Rect) { + const a2x = rect1.x + rect1.width / 2; + const a2y = rect1.y + rect1.height / 2; + const b1x = rect2.x - rect2.width / 2; + const b1y = rect2.y - rect2.height / 2; + return b1y <= a2y && b1x <= a2x; } // 判断子节点是否与数据集节点重叠 -function isChildrenIntersectDataset(rects: Rect[], childrenRect: Rect) { - for (const r of rects) { - if (isRectanglesIntersect(r, childrenRect)) { - return r; +function isChildrenOverlapDataset(nodes: NodeConfig[], childrenRect: Rect) { + for (const node of nodes) { + const rect = { x: node.x!, y: node.y!, width: nodeWidth, height: nodeHeight }; + if (isRectanglesOverlap(rect, childrenRect)) { + return childrenRect; } } return null; } -// 计算子节点位置 -function adjustChildrenPosition(node: NodeConfig) { +// 调整数据集位置 +function adjustDatasetPosition(node: NodeConfig) { const nodeRect = { - x: node.x! - nodeWidth / 2, - y: node.y! - nodeHeight / 2, + x: node.x!, + y: node.y!, width: nodeWidth, height: nodeHeight, }; - const overlapRect = isChildrenIntersectDataset(datasetRects, nodeRect); + const overlapRect = isChildrenOverlapDataset(datasetNodes, nodeRect); if (overlapRect) { - const offsetY = nodeRect.y - overlapRect.y; - const space = 10; //(vGap + Math.abs(offsetY) - nodeHeight) / 2; - if (offsetY >= 0) { - node.y = node.y! + (nodeHeight - offsetY + space); - } else { - node.y = node.y! - (nodeHeight - Math.abs(offsetY) + space); - } + console.log(node); + + const adjustRect = { + x: overlapRect.x - nodeWidth - hGap / 2, + y: overlapRect.y, + width: overlapRect.width, + height: overlapRect.height, + }; + const lastNode = datasetNodes[datasetNodes.length - 1] as NodeConfig; + const distance = lastNode.x! - adjustRect.x; + datasetNodes.forEach((item) => { + item.x = item.x! - distance; + }); } }