| | |
| | | import React, { useRef, useEffect, useState } from "react"; |
| | | import { Button } from 'antd'; |
| | | 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; |
| | |
| | | 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 ( |
| | | <> |
| | | <Button type="primary" onClick={exportData}> |
| | | 导出数据 |
| | | </Button> |
| | | <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> |
| | | </> |
| | | ); |
| | | } |