<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flowchart Editor</title>
<style>
#app {
display: flex;
width: 100%;
height: 100%;
}
.left {
flex: 1;
border: 1px solid #ddd;
padding: 10px;
}
.left-item {
cursor: pointer;
padding: 5px;
border: 1px solid #ddd;
margin-bottom: 5px;
}
.right {
flex: 3;
border: 1px solid #ddd;
}
/* 添加模态框的样式 */
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
</style>
</head>
<body>
<div id="app">
<div class="left">
<div class="left-item" v-for="item in tasklist"
@click="addNode(item)"
@mouseover="handleMouseOver"
>
{{ item.name }}
</div>
</div>
<div class="right" id="graph-container"></div>
<!-- 在 #app 内部添加模态框的 HTML 结构 -->
<div v-if="showModal" class="modal" @click="showModal = false">
<p>模态框内容</p>
<button @click.stop="goToOtherPage">前往其他页面</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script src="https://gw.alipayobjects.com/os/lib/antv/g6/4.3.7/dist/g6.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
tasklist: [
{ id: 1, name: 'Start', color: 'orange' },
{ id: 2, name: 'Process', color: 'green' },
{ id: 3, name: 'End', color: 'yellow' }
],
graph: null,
selectedNode: null,
nodeArr: [],
nodeRelation: [],
showModal: false,
modalTimeout: null,
},
mounted() {
this.initGraph();
},
methods: {
handleMouseOver() {
// 在两秒后显示模态框
this.modalTimeout = setTimeout(() => {
this.showModal = true;
}, 2000);
},
goToOtherPage() {
location.href = '/paint3'; // 替换为目标页面的 URL
},
initGraph() {
this.graph = new G6.Graph({
container: 'graph-container',
width: 1100,
height: 600,
modes: {
default: ['drag-node', 'drag-canvas']
},
defaultNode: {
type: 'rect', // 设置节点类型为长方形
style: {
lineWidth: 2,
stroke: '#5B8FF9',
fill: '#C6E5FF'
}
},
defaultEdge: {
style: {
endArrow: {
path: G6.Arrow.triangle(10, 20, 0),
fill: 'green',
offset: -1 // 将箭头向后移动一点,使其更靠近节点
},
lineWidth: 3, // 设置边的宽度
stroke: 'green'
}
},
});
this.graph.on('node:click', evt => {
const clickedNode = evt.item;
if (this.selectedNode && this.selectedNode !== clickedNode) {
const sourceId = this.selectedNode.get('id');
const targetId = clickedNode.get('id');
const sourceLabel = this.selectedNode.getModel().label;
const targetLabel = clickedNode.getModel().label;
// 检查新边是否会形成闭环
if (!this.doesEdgeCreateLoop(sourceId, targetId)) {
this.graph.addItem('edge', {
source: sourceId,
target: targetId,
style: {
endArrow: {
path: G6.Arrow.triangle(10, 20, 5),
fill: 'green'
}
}
});
// 添加边关系到 nodeRelation
this.nodeRelation.push(`${sourceLabel}>>${targetLabel}`);
console.log(this.nodeRelation,'this.nodeRelation--add')
// 添加node到 nodeArr
if (!this.nodeArr.includes(sourceLabel)) {
this.nodeArr.push(sourceLabel);
}
if (!this.nodeArr.includes(targetLabel)) {
this.nodeArr.push(targetLabel);
}
console.log(this.nodeArr,'this.nodeArr--add')
}
this.selectedNode = null;
} else {
this.selectedNode = clickedNode;
}
});
this.graph.on('edge:click', (evt) => {
const edge = evt.item;
const sourceLabel = edge.getSource().getModel().label;
const targetLabel = edge.getTarget().getModel().label;
// 从 nodeRelation 中删除边
const edgeIndex = this.nodeRelation.indexOf(`${sourceLabel}>>${targetLabel}`);
if (edgeIndex > -1) {
this.nodeRelation.splice(edgeIndex, 1);
}
// 从 nodeArr 中删除不再参与连线的节点
[sourceLabel, targetLabel].forEach(label => {
if (!this.nodeRelation.some(rel => rel.includes(label))) {
const nodeIndex = this.nodeArr.indexOf(label);
if (nodeIndex > -1) {
this.nodeArr.splice(nodeIndex, 1);
}
}
});
console.log(this.nodeRelation,'this.nodeRelation--del')
console.log(this.nodeArr,'this.nodeArr---del')
// 删除边
this.graph.removeItem(edge);
});
},
addNode(item) {
if (this.graph.findById(`node-${item.id}`)) return;
console.log(item.id,'node-id-------')
const model = {
id: `node-${item.id}`,
label: item.name,
x: Math.random() * 800,
y: Math.random() * 600,
style: {
fill: item.color, // 设置节点颜色与左侧被点击的节点颜色一致
stroke: item.color
}
};
this.graph.addItem('node', model);
},
doesEdgeCreateLoop(sourceId, targetId) {
const visited = new Set();
let hasLoop = false;
const dfs = (nodeId) => {
if (nodeId === sourceId) {
hasLoop = true;
return;
}
if (visited.has(nodeId)) {
return;
}
visited.add(nodeId);
const edges = this.graph.getEdges();
edges.forEach(edge => {
if (edge.getSource().getID() === nodeId) {
const nextNodeId = edge.getTarget().getID();
if (!visited.has(nextNodeId)) {
dfs(nextNodeId);
}
}
});
};
dfs(targetId);
return hasLoop;
}
}
});
</script>
</body>
</html>