import React, { useRef, useEffect, useState } from "react";
|
import { Button, message, Modal } from 'antd';
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
import { solarizedlight } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
import './GraphTools.less'
|
|
export const GraphTools = ({ graphRef, isReady }) => {
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [preCode, setPreCode] = useState(null);
|
|
const handleOk = () => {
|
setIsModalOpen(false);
|
};
|
|
const handleCancel = () => {
|
setIsModalOpen(false);
|
};
|
|
//预览代码
|
const prewCode = () => {
|
const graph = graphRef.current;
|
if (isReady) {
|
const data = graph.toJSON();
|
|
const edges = [];
|
const nodes = [];
|
let rootNode = null;
|
data.cells.forEach((item) => {
|
if (item.shape == "edge") {
|
edges.push(item)
|
} else {
|
nodes.push(item)
|
if (item.data.root) {
|
rootNode = item;
|
}
|
}
|
})
|
|
if (rootNode == null) {
|
message.warning('请设置程序入口组件');
|
return;
|
}
|
|
const codeContent = transCode(rootNode, nodes, graph)
|
console.log(codeContent);
|
|
setPreCode(codeContent);
|
setIsModalOpen(true);
|
}
|
}
|
|
const exportData = () => {
|
const graph = graphRef.current;
|
if (isReady) {
|
const data = graph.toJSON();
|
console.log(data);
|
// 这里你可以将数据发送到服务器或保存到本地
|
|
const edges = [];
|
const nodes = [];
|
let rootNode = null;
|
data.cells.forEach((item) => {
|
if (item.shape == "edge") {
|
edges.push(item)
|
} else {
|
nodes.push(item)
|
if (item.data.root) {
|
rootNode = item;
|
}
|
}
|
})
|
|
if (rootNode == null) {
|
message.warning('请设置程序入口组件');
|
return;
|
}
|
|
console.log(getDescendants(rootNode, nodes, graph));
|
|
const codeContent = transCode(rootNode, nodes, graph)
|
console.log(codeContent);
|
}
|
}
|
|
const transCode = (rootNode, nodes, graph) => {
|
let codeContent = "";
|
let values = nodeDFS(rootNode, nodes, graph);
|
const searchNode = {
|
id: 1,
|
parent: null,
|
logicBool: true
|
};
|
|
let cpValues = JSON.parse(JSON.stringify(values))
|
console.log(cpValues);
|
|
let searchIndex = 0;
|
cpValues.forEach((value) => {
|
if (value.data.isLogic) {
|
value.data.searchLogicId = searchNode.id;
|
value.data.searchLogicBool = searchNode.logicBool;
|
value.data.searchIndex = searchIndex++;
|
|
let tmpSearchNode = JSON.parse(JSON.stringify(searchNode))
|
searchNode.parent = tmpSearchNode;
|
searchNode.id = value.id;
|
searchNode.logicBool = null;
|
searchIndex = 0;
|
} else {
|
let id = searchNode.id;
|
let logicBool = searchNode.logicBool;
|
|
const connectedEdges = graph.getConnectedEdges(value);//取边
|
connectedEdges.forEach((edge) => {
|
let tmpSearchNode = JSON.parse(JSON.stringify(searchNode));
|
while (tmpSearchNode.parent != null) {
|
if (edge.source.cell == tmpSearchNode.id) {
|
logicBool = edge.data.logicBool;//更新方向
|
searchNode.logicBool = edge.data.logicBool;
|
id = tmpSearchNode.id;
|
break;
|
}
|
tmpSearchNode = tmpSearchNode.parent;
|
}
|
})
|
|
value.data.searchLogicId = id;
|
value.data.searchLogicBool = logicBool;
|
value.data.searchIndex = searchIndex++;
|
}
|
})
|
|
console.log(cpValues);
|
console.log(searchNode);
|
|
let tmp = {}
|
let tmpList = []
|
let tmpIndex = 0;
|
for (let i = cpValues.length - 1; i >= 0; i--) {
|
let item = cpValues[i];
|
if (tmp[item.data.searchLogicId] == null) {
|
tmpList[tmpIndex] = [item];
|
tmp[item.data.searchLogicId] = {
|
index: tmpIndex,
|
code: "",
|
codeTrue: "",
|
codeFalse: "",
|
condition: ""
|
};
|
tmpIndex++;
|
} else {
|
tmpList[tmp[item.data.searchLogicId].index].push(item);
|
}
|
}
|
|
console.log(tmp, tmpList);
|
|
tmpList.forEach((item) => {
|
item.forEach((val) => {
|
let originCode = tmp[val.data.searchLogicId].codeTrue;
|
if (!val.data.searchLogicBool) {
|
originCode = tmp[val.data.searchLogicId].codeFalse;
|
}
|
|
let codeContent = val.data.codeContent;
|
|
if (val.data.isLogic) {
|
codeContent = val.id + "_logic_tag";
|
console.log(val.data);
|
tmp[val.id].condition = val.data.codeContent;
|
} else {
|
codeContent = `
|
//**********${val.attrs.text.text}-start**********//
|
${codeContent}
|
//**********${val.attrs.text.text}-start**********//
|
`;
|
}
|
let newCode = `
|
${codeContent}
|
|
${originCode}
|
`;
|
|
console.log(newCode);
|
if (val.data.searchLogicBool) {
|
tmp[val.data.searchLogicId].codeTrue = newCode;
|
} else {
|
tmp[val.data.searchLogicId].codeFalse = newCode;
|
}
|
})
|
})
|
|
let sortTmp = [];
|
for (var key in tmp) {
|
let obj = tmp[key];
|
obj.id = key;
|
sortTmp[tmp[key].index] = obj;
|
}
|
|
// 合并True和False
|
sortTmp.forEach((item) => {
|
let nestedIfCode = "";
|
if (item.condition == "") {
|
nestedIfCode = `
|
${item.codeTrue}
|
${item.codeFalse}
|
`;
|
} else {
|
nestedIfCode = `
|
if(${item.condition}){
|
// 逻辑TRUE
|
${item.codeTrue}
|
}else {
|
// 逻辑FALSE
|
${item.codeFalse}
|
}
|
`;
|
}
|
|
item.code = nestedIfCode;
|
})
|
|
console.log(sortTmp);
|
|
let finalTmp = {};
|
let sortTmpCopy = JSON.parse(JSON.stringify(sortTmp));
|
sortTmpCopy.forEach((item) => {
|
if (item.id != "1") {
|
let codeContent = item.code;
|
sortTmp.forEach((val) => {
|
codeContent = codeContent.replace(val.id + "_logic_tag", val.code);
|
console.log(item, val.id, codeContent);
|
})
|
finalTmp[item.id] = {
|
code: codeContent
|
}
|
}
|
})
|
|
console.log(sortTmpCopy);
|
console.log(finalTmp);
|
|
sortTmpCopy.forEach((item) => {
|
if (item.id == "1") {
|
let finalCode = item.code;
|
for (var key in finalTmp) {
|
let obj = finalTmp[key];
|
finalCode = finalCode.replace(key + "_logic_tag", obj.code);
|
}
|
|
codeContent = finalCode;
|
}
|
})
|
|
codeContent = formatJavaCode(codeContent)
|
return codeContent;
|
}
|
|
const formatJavaCode = (codeString) => {
|
let baseIndentation = " "; //用四个空格表示一个缩进
|
let indentationLevel = 0; //增加这行代码来初始化indentationLevel
|
|
let formattedCode = codeString
|
.replace(/^\s+/mg, '') // 移除每行前面的空白
|
.replace(/(\{|\})/g, ' $& ') // 让大括号周围都有空格
|
// 上面的.replace(/^\s+/mg, '')可能会在括号周围插入多余的空格,所以下面这行代码会移除开头或末尾的空格
|
.replace(/^\s+|\s+$/mg, '')
|
// 用了.split('\n')后,每一行都是数组中的一个元素,所以可以通过减少或增加行开头的空格数来添加或删除缩进
|
.split('\n').reduce((formattedCode, currentLine) => {
|
if (currentLine.includes('}')) {
|
// 如果一行中包含右大括号,我们要减少一个缩进
|
indentationLevel--;
|
}
|
|
let indentation = baseIndentation.repeat(indentationLevel);
|
let indentedLine = indentation + currentLine;
|
|
if (currentLine.includes('{')) {
|
// 如果一行中包含左大括号,那个大括号后面的代码需要额外的一个缩进
|
indentationLevel++;
|
}
|
|
return formattedCode + '\n' + indentedLine;
|
}, '');
|
|
return formattedCode;
|
}
|
|
// const transCode = (rootNode, nodes, graph) => {
|
// let codeContent = "";
|
// const descendants = [];
|
// let stack = [rootNode];
|
|
// let count = 0;
|
// while (stack.length > 0) {
|
// const current = stack.pop();
|
// descendants.push(current);
|
|
// const children = getChildren(current, nodes, graph);
|
// stack.push(...children);
|
|
// // 输出代码
|
// if (!current.data.isLogic) {
|
// const connectedEdges = graph.getConnectedEdges(current);//取边
|
// connectedEdges.forEach((edge) => {
|
// //过滤从自身节点出去的边
|
// if(edge.source.cell != current.id){
|
// //取上一节点
|
// let lastNode = null;
|
// nodes.forEach((node) => {
|
// if(node.id == edge.source.cell){
|
// lastNode = node;
|
// }
|
// })
|
|
// if(lastNode != null) {
|
// //判断节点是否逻辑节点
|
// if(lastNode.data.isLogic){
|
// console.log(lastNode);
|
// let nestedIfCode = "";
|
// if(lastNode.data.logicBool == 'true') {
|
// nestedIfCode = `
|
// if (${lastNode.data.codeContent}) {
|
// ${current.data.codeContent}
|
// }
|
// `;
|
// }else{
|
// nestedIfCode = `
|
// if (!(${lastNode.data.codeContent})) {
|
// ${current.data.codeContent}
|
// }
|
// `;
|
// }
|
|
|
// codeContent += "\n" + nestedIfCode;
|
// console.log(codeContent);
|
// }else{
|
// if (current.data.codeContent != null) {
|
// codeContent += "\n" + current.data.codeContent;
|
// }
|
// }
|
// }
|
// }
|
// console.log(current);
|
// })
|
// } else {
|
// // if (current.data.codeContent != null) {
|
// // codeContent += "\n" + current.data.codeContent;
|
// // }
|
|
// // const connectedEdges = graph.getConnectedEdges(current);
|
// // console.log(connectedEdges);
|
// // stack = []
|
// // let test = []
|
// // connectedEdges.forEach((edge) => {
|
// // nodes.forEach((item) => {
|
// // if (item.id === edge.target.cell && item.id != current.id) {
|
// // test.push(item);
|
// // }
|
// // })
|
// // });
|
// // console.log(test);
|
// // console.log();
|
// // let nestedIfCode = `
|
// // if (true}) {
|
// // ${current.data.codeContent}
|
// // }
|
// // `;
|
|
// // codeContent += "\n" + nestedIfCode;
|
// // console.log(codeContent);
|
// }
|
|
// }
|
|
// console.log(codeContent);
|
// }
|
|
const nodeDFS = (node, nodes, graph) => {
|
let values = [];
|
if (graph) {
|
const connectedEdges = graph.getConnectedEdges(node);
|
const children = [];
|
|
console.log(node);
|
connectedEdges.forEach((edge) => {
|
nodes.forEach((item) => {
|
if (item.id === edge.target.cell && item.id != node.id) {
|
children.push(item);
|
}
|
})
|
});
|
|
console.log(connectedEdges);
|
if (children.length != 0) {
|
console.log(children);
|
children.forEach((node) => {
|
console.log(node);
|
values.push(node);
|
values = values.concat(nodeDFS(node, nodes, graph))
|
})
|
}
|
}
|
|
return values;
|
}
|
|
const getChildren = (node, nodes, graph) => {
|
const connectedEdges = graph.getConnectedEdges(node);
|
const children = [];
|
|
connectedEdges.forEach((edge) => {
|
nodes.forEach((item) => {
|
if (item.id === edge.target.cell && item.id != node.id) {
|
children.push(item);
|
}
|
})
|
});
|
|
return children;
|
}
|
|
const getDescendants = (node, nodes, graph) => {
|
const descendants = [];
|
const stack = [node];
|
|
let count = 0;
|
while (stack.length > 0) {
|
const current = stack.pop();
|
descendants.push(current);
|
|
const children = getChildren(current, nodes, graph);
|
stack.push(...children);
|
}
|
|
return descendants;
|
}
|
|
return (
|
<>
|
<div className="container">
|
<Button type="primary" onClick={exportData}>
|
导出数据
|
</Button>
|
|
<Button type="primary" onClick={prewCode}>
|
预览代码
|
</Button>
|
</div>
|
|
<Modal title="Basic Modal" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
|
<SyntaxHighlighter language="java" style={solarizedlight}>
|
{preCode}
|
</SyntaxHighlighter>
|
</Modal>
|
</>
|
);
|
}
|