|
@@ -66,9 +66,11 @@ import "./main.css";//重置样式
|
|
|
import defaultnode from './defaultnode.vue'
|
|
|
import PointOnlyNode from './pointonlynode.vue'
|
|
|
import useDragAndDrop from './useDnD';
|
|
|
+import {getNodeCount, setNodeCount} from './useDnD';
|
|
|
import changebak from './changebak.vue'
|
|
|
import { useProjectStore } from '@/store/project'
|
|
|
import emitter from "@/utils/emitter";
|
|
|
+import { onMounted } from 'vue';
|
|
|
|
|
|
const { onInit, onNodeDragStop, onConnect, addEdges, setViewport, toObject,addNodes,updateEdgeData,onConnectStart} = useVueFlow()
|
|
|
|
|
@@ -84,18 +86,83 @@ let mergedObj = ref('');
|
|
|
|
|
|
// 选中节点
|
|
|
let noid = ref([]);
|
|
|
-let Edgeid = ref();
|
|
|
+let Edgeid = ref();//选中线段id
|
|
|
let seledge=ref(null);
|
|
|
+let previousEdge = null; // 用于保存上一个选中的边缘
|
|
|
// 连线颜色
|
|
|
let linecolor=ref('#2267B1')
|
|
|
// 线宽
|
|
|
let linewidth=ref(1);
|
|
|
|
|
|
+let midNodeCounter = 0;//储存中间节点的序号
|
|
|
+
|
|
|
|
|
|
const projectStore = useProjectStore()
|
|
|
let pid = computed(() => projectStore.pid || '')
|
|
|
|
|
|
|
|
|
+// 旧数据存储
|
|
|
+let prevNodes = [...nodes.value];
|
|
|
+let prevEdges = [...edges.value];
|
|
|
+
|
|
|
+// 监听节点变化
|
|
|
+watch(nodes, (newNodes) => {
|
|
|
+ const deletedNodes = prevNodes.filter((node) => !newNodes.some((n) => n.id === node.id));
|
|
|
+ const addedNodes = newNodes.filter((node) => !prevNodes.some((n) => n.id === node.id));
|
|
|
+
|
|
|
+ if (deletedNodes.length > 0) {
|
|
|
+ console.log('Deleted Nodes:', deletedNodes);
|
|
|
+ deletedNodes.forEach((node) => {
|
|
|
+ if (node.data?.pcId) {
|
|
|
+ comdelete(node.data.pcId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (addedNodes.length > 0) {
|
|
|
+ // console.log('Added Nodes:', addedNodes);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新快照
|
|
|
+ prevNodes = [...newNodes];
|
|
|
+}, { deep: true });
|
|
|
+
|
|
|
+// 监听连线变化
|
|
|
+watch(edges, (newEdges) => {
|
|
|
+ const deletedEdges = prevEdges.filter((edge) => !newEdges.some((e) => e.id === edge.id));
|
|
|
+ const addedEdges = newEdges.filter((edge) => !prevEdges.some((e) => e.id === edge.id));
|
|
|
+
|
|
|
+ if (deletedEdges.length > 0) {
|
|
|
+ console.log('Deleted Edges:', deletedEdges);
|
|
|
+ deletedEdges.forEach((edge) => {
|
|
|
+ const sourceNode = prevNodes.find(n => n.id === edge.source);
|
|
|
+ const targetNode = prevNodes.find(n => n.id === edge.target);
|
|
|
+
|
|
|
+ if (!sourceNode || !targetNode) return;
|
|
|
+
|
|
|
+ let npcId = '';
|
|
|
+ let pcId = '';
|
|
|
+
|
|
|
+ // 判断 source 或 target 是否为中间点 comId === '3'
|
|
|
+ if (sourceNode.data?.comId === '3') {
|
|
|
+ npcId = sourceNode.data.npcId;
|
|
|
+ pcId = targetNode.data?.pcId;
|
|
|
+ } else if (targetNode.data?.comId === '3') {
|
|
|
+ npcId = targetNode.data.npcId;
|
|
|
+ pcId = sourceNode.data?.pcId;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (npcId && pcId) {
|
|
|
+ comlinedelete(npcId, pcId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (addedEdges.length > 0) {
|
|
|
+ console.log('Added Edges:', addedEdges);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新快照
|
|
|
+ prevEdges = [...newEdges];
|
|
|
+}, { deep: true });
|
|
|
|
|
|
|
|
|
const resetTransform = () => {
|
|
@@ -112,7 +179,12 @@ const toggleDarkMode = () => {
|
|
|
}
|
|
|
|
|
|
const saveproject = () => {
|
|
|
- let obj = { nodes: toObject().nodes,edges:toObject().edges };
|
|
|
+ let obj = {
|
|
|
+ nodes: toObject().nodes,
|
|
|
+ edges: toObject().edges,
|
|
|
+ midNodeCounter: midNodeCounter, // 添加中间节点计数器
|
|
|
+ nodeCount: getNodeCount(), // 获取当前节点计数
|
|
|
+ };
|
|
|
mergedObj.value=JSON.stringify(obj);
|
|
|
|
|
|
const params = {
|
|
@@ -125,6 +197,10 @@ const saveproject = () => {
|
|
|
};
|
|
|
request(params)
|
|
|
.then((res) => {
|
|
|
+ projectStore.setProjectInfo({
|
|
|
+ ...projectStore.projectInfo,
|
|
|
+ flow: mergedObj.value || '',
|
|
|
+ })
|
|
|
|
|
|
})
|
|
|
.catch((error) => {
|
|
@@ -133,15 +209,84 @@ const saveproject = () => {
|
|
|
}
|
|
|
|
|
|
const removeNode = () => {
|
|
|
+ if (!noid.value) {
|
|
|
+ console.warn('未选中任何节点');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const nodeIdToRemove = noid.value.id;
|
|
|
+
|
|
|
+ vueFlowRef.value.removeNodes(noid.value.id);
|
|
|
|
|
|
+ // 清空当前选中
|
|
|
+ noid.value = null;
|
|
|
+
|
|
|
+ saveproject();
|
|
|
}
|
|
|
|
|
|
const removeEdge = () => {
|
|
|
+ if (!seledge.value) {
|
|
|
+ ElMessage.warning('请先选择要删除的连线');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ vueFlowRef.value.removeEdges(seledge.value); // 移除选中的边
|
|
|
+ seledge.value = null; // 清空选中状态
|
|
|
|
|
|
+ saveproject();
|
|
|
}
|
|
|
|
|
|
const confirmDelete = () => {
|
|
|
+ ElMessageBox.confirm(
|
|
|
+ '确定要删除所有节点和连线吗?此操作不可恢复!',
|
|
|
+ '警告',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确认',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ }
|
|
|
+ )
|
|
|
+ .then(() => {
|
|
|
+
|
|
|
+ vueFlowRef.value.removeNodes(nodes.value)
|
|
|
+ vueFlowRef.value.removeEdges(edges.value)
|
|
|
|
|
|
+ ElMessage.success('所有节点和连线已删除')
|
|
|
+ saveproject();
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ ElMessage.info('已取消删除')
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const comdelete = (pcId) => {
|
|
|
+ const params = {
|
|
|
+ transCode:'ES0005',
|
|
|
+ pcId: pcId
|
|
|
+ }
|
|
|
+ request(params)
|
|
|
+ .then((res) => {
|
|
|
+ // console.log('组件删除成功')
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ ElMessage.error(err.returnMsg);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const comlinedelete = (npcId,pcId) => {
|
|
|
+ const params = {
|
|
|
+ transCode:'ES0005',
|
|
|
+ npcId: npcId,
|
|
|
+ pcId: pcId,
|
|
|
+ type: 0
|
|
|
+ }
|
|
|
+ request(params)
|
|
|
+ .then((res) => {
|
|
|
+ // console.log('组件连线删除成功')
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ ElMessage.error(err.returnMsg);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
|
|
@@ -154,12 +299,42 @@ const customOnDrop = (event) => {
|
|
|
|
|
|
|
|
|
|
|
|
-const onNodeContextMenu = ( event) => {
|
|
|
- console.log('右键点击', event);
|
|
|
+const onNodeContextMenu = ( e) => {
|
|
|
+ console.log('右键点击', e);
|
|
|
}
|
|
|
|
|
|
-const onEdgeClick = (event) => {
|
|
|
- console.log('边数据:', event);
|
|
|
+const onEdgeClick = (e) => {
|
|
|
+ console.log('Edge Click', e.edge);
|
|
|
+ // console.log('所有线段:', edges.value);
|
|
|
+ // 如果已经有选中的边缘
|
|
|
+ if (seledge.value) {
|
|
|
+ // 恢复上一个选中边缘的样式
|
|
|
+ if (previousEdge) {
|
|
|
+ previousEdge.style = {
|
|
|
+ ...previousEdge.style,
|
|
|
+ stroke: previousEdge.originalColor, // 恢复原始颜色
|
|
|
+ strokeWidth: previousEdge.originalWidth,// 恢复原始宽度
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存当前点击的边缘为选中边缘
|
|
|
+ Edgeid.value = e.edge.id;
|
|
|
+ seledge.value = e.edge;
|
|
|
+
|
|
|
+ // 暂时更改当前选中边缘的样式
|
|
|
+ seledge.value.originalColor = seledge.value.style.stroke; // 保存当前边缘的原始颜色
|
|
|
+ seledge.value.originalWidth = seledge.value.style.strokeWidth; // 保存当前边缘的原始宽度
|
|
|
+
|
|
|
+ const isdefault = e.edge.data.type === 'default'; // 判断是否为默认线
|
|
|
+ seledge.value.style = {
|
|
|
+ ...seledge.value.style,
|
|
|
+ stroke: isdefault ? '#2267B1' : 'rgba(255, 255, 0, 0.3)',// 设置选中边缘的颜色
|
|
|
+ strokeWidth: isdefault ? 2 : 6,// 设置选中边缘的宽度
|
|
|
+ };
|
|
|
+
|
|
|
+ // 保存当前选中的边缘作为上一个选中边缘
|
|
|
+ previousEdge = seledge.value;
|
|
|
}
|
|
|
|
|
|
const onNodeClick = (event) => {
|
|
@@ -176,6 +351,11 @@ const onEdgeDoubleClick = (event) => {
|
|
|
noid.value = event.node;
|
|
|
}
|
|
|
|
|
|
+// 监听连接开始,提前取消选中的线段
|
|
|
+onConnectStart(() => {
|
|
|
+ cleanEdgeselect();
|
|
|
+});
|
|
|
+
|
|
|
// 线的类型 default
|
|
|
let lineType = ref('default');
|
|
|
|
|
@@ -193,6 +373,11 @@ onConnect(async (connection) => {
|
|
|
const sourceNode = vueFlowRef.value.getNode(connection.source);
|
|
|
const targetNode = vueFlowRef.value.getNode(connection.target);
|
|
|
|
|
|
+ if(sourceNode.data.comId === '3' && targetNode.data.comId === '3'){
|
|
|
+ console.warn('禁止连接两个中间节点');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
// 是否需要中间节点
|
|
|
const isCom3 = sourceNode.data.comId === '3' || targetNode.data.comId === '3';
|
|
|
|
|
@@ -243,13 +428,36 @@ onConnect(async (connection) => {
|
|
|
const midX = (sourceCenterX + targetCenterX) / 2;
|
|
|
const midY = (sourceCenterY + targetCenterY) / 2;
|
|
|
|
|
|
+ // 计算 sourceNode 和 targetNode 相对于 pointNode 的位置
|
|
|
+ const dxSource = sourceNode.position.x - midX;
|
|
|
+ const dySource = sourceNode.position.y - midY;
|
|
|
+ const dxTarget = targetNode.position.x - midX;
|
|
|
+ const dyTarget = targetNode.position.y - midY;
|
|
|
+
|
|
|
+ // 判断 sourceNode 的主要方向(水平 or 垂直)
|
|
|
+ const isSourceHorizontal = Math.abs(dxSource) > Math.abs(dySource);
|
|
|
+ const sourceDirection = isSourceHorizontal
|
|
|
+ ? (dxSource < 0 ? 'left' : 'right')
|
|
|
+ : (dySource < 0 ? 'top' : 'bottom');
|
|
|
+
|
|
|
+ // 判断 targetNode 的主要方向
|
|
|
+ const isTargetHorizontal = Math.abs(dxTarget) > Math.abs(dyTarget);
|
|
|
+ const targetDirection = isTargetHorizontal
|
|
|
+ ? (dxTarget < 0 ? 'left' : 'right')
|
|
|
+ : (dyTarget < 0 ? 'top' : 'bottom');
|
|
|
+
|
|
|
+
|
|
|
+ midNodeCounter++;
|
|
|
+ const uid = `N${midNodeCounter}`;
|
|
|
+
|
|
|
nodes.value.push({
|
|
|
id: pointNodeId,
|
|
|
type: 'point-only',
|
|
|
position: { x: midX, y: midY },
|
|
|
data: {
|
|
|
comId:'3',
|
|
|
- label: '节点'
|
|
|
+ label: '节点',
|
|
|
+ uid: uid,
|
|
|
},
|
|
|
});
|
|
|
|
|
@@ -269,7 +477,7 @@ onConnect(async (connection) => {
|
|
|
source: connection.source,
|
|
|
sourceHandle: connection.sourceHandle,
|
|
|
target: pointNodeId,
|
|
|
- targetHandle: 'source-left',
|
|
|
+ targetHandle: `source-${sourceDirection}`,
|
|
|
type: 'smoothstep',
|
|
|
color: linecolor.value,
|
|
|
style: { strokeWidth: linewidth.value, stroke: linecolor.value }
|
|
@@ -280,7 +488,7 @@ onConnect(async (connection) => {
|
|
|
const edge2 = {
|
|
|
id: edgeId2,
|
|
|
source: pointNodeId,
|
|
|
- sourceHandle: 'source-right', // 从中间点的右边出发
|
|
|
+ sourceHandle: `source-${targetDirection}`, // 使用计算的方向
|
|
|
target: connection.target,
|
|
|
targetHandle: connection.targetHandle,
|
|
|
type: 'smoothstep',
|
|
@@ -315,6 +523,8 @@ onConnect(async (connection) => {
|
|
|
console.error('中间点处理失败:', err);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ saveproject();
|
|
|
});
|
|
|
|
|
|
const createEdge = async (pid, type, npcId, pcId1, pcId2) => {
|
|
@@ -357,18 +567,48 @@ const createCom3 = async (pid) => {
|
|
|
}
|
|
|
|
|
|
|
|
|
-const flowInit=()=>{
|
|
|
- let nodesflow=JSON.parse(projectStore.projectInfo.flow)
|
|
|
- nodes.value=nodesflow.nodes;
|
|
|
- edges.value=nodesflow.edges;
|
|
|
+const flowInit = () => {
|
|
|
+ let nodesflow = JSON.parse(projectStore.projectInfo.flow || '{"nodes":[],"edges":[]}');
|
|
|
+
|
|
|
+ console.log('初始化流程数据:', nodesflow);
|
|
|
+ nodes.value = nodesflow.nodes;
|
|
|
+ edges.value = nodesflow.edges;
|
|
|
+ // 提取中间节点计数器
|
|
|
+ midNodeCounter = nodesflow.midNodeCounter || 0;
|
|
|
+ // 提取节点计数
|
|
|
+ setNodeCount(nodesflow.nodeCount || 0);
|
|
|
}
|
|
|
|
|
|
-const onMounted = () => {
|
|
|
- setTimeout(function() {
|
|
|
- flowInit();
|
|
|
- }, 1500);
|
|
|
+const cleanEdgeselect = () => {
|
|
|
+ if(seledge.value) {
|
|
|
+ // 恢复选中边缘的原始样式
|
|
|
+ seledge.value.style = {
|
|
|
+ ...seledge.value.style,
|
|
|
+ stroke: seledge.value.originalColor,
|
|
|
+ strokeWidth: previousEdge?.originalWidth || 1, // 恢复原始宽度
|
|
|
+ };
|
|
|
|
|
|
-};
|
|
|
+ // 清空选中的边缘
|
|
|
+ seledge.value = null;
|
|
|
+ Edgeid.value = null;
|
|
|
+ previousEdge = null;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ flowInit();
|
|
|
+
|
|
|
+ // 点击其他区域取消线段选中
|
|
|
+ if (vueFlowRef.value) {
|
|
|
+ vueFlowRef.value.$el.addEventListener('click', (event) => {
|
|
|
+ // 确保点击的不是边缘
|
|
|
+ if (seledge.value && !event.target.closest('.vue-flow__edge')) {
|
|
|
+ cleanEdgeselect();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+});
|
|
|
|
|
|
|
|
|
</script>
|