hookehuyr

fix

1 /* 1 /*
2 - * @Date: 2025-03-10 13:15:30 2 + * @Date: 2025-03-13 18:34:16
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-13 16:20:00 4 + * @LastEditTime: 2025-03-16 00:21:53
5 * @FilePath: /logic-flow2/src/router/index.js 5 * @FilePath: /logic-flow2/src/router/index.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -120,6 +120,11 @@ const router = createRouter({ ...@@ -120,6 +120,11 @@ const router = createRouter({
120 name: 'dynamic-group', 120 name: 'dynamic-group',
121 component: () => import('../views/dynamic-group/index.vue') 121 component: () => import('../views/dynamic-group/index.vue')
122 }, 122 },
123 + {
124 + path: '/api-graphModel',
125 + name: 'api-graphModel',
126 + component: () => import('../views/api/graphModel.vue')
127 + },
123 ] 128 ]
124 }) 129 })
125 130
......
1 /* 1 /*
2 * @Date: 2025-03-13 16:11:47 2 * @Date: 2025-03-13 16:11:47
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-13 17:09:32 4 + * @LastEditTime: 2025-03-16 00:39:21
5 * @FilePath: /logic-flow2/src/views/adv-menu/customNode.js 5 * @FilePath: /logic-flow2/src/views/adv-menu/customNode.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -13,6 +13,15 @@ class CustomModel extends RectNodeModel { ...@@ -13,6 +13,15 @@ class CustomModel extends RectNodeModel {
13 const { 13 const {
14 properties: { isDisabledNode }, 14 properties: { isDisabledNode },
15 } = this; 15 } = this;
16 + // 设置节点是否可以被连接
17 + this.sourceRules.push({
18 + message: "禁用节点不能作为连接源",
19 + validate: () => !isDisabledNode
20 + });
21 + this.targetRules.push({
22 + message: "禁用节点不能作为连接目标",
23 + validate: () => !isDisabledNode
24 + });
16 if (!isDisabledNode) { 25 if (!isDisabledNode) {
17 // 单独为非禁用的元素设置菜单。 26 // 单独为非禁用的元素设置菜单。
18 this.menu = [ 27 this.menu = [
...@@ -46,8 +55,15 @@ class CustomModel extends RectNodeModel { ...@@ -46,8 +55,15 @@ class CustomModel extends RectNodeModel {
46 // 添加 getNodeStyle 方法 55 // 添加 getNodeStyle 方法
47 getNodeStyle() { 56 getNodeStyle() {
48 const style = super.getNodeStyle(); 57 const style = super.getNodeStyle();
58 + const { isDisabledNode } = this.properties;
59 + if (isDisabledNode) {
60 + style.stroke = "#999999";
61 + style.fill = "#f0f0f0";
62 + style.strokeDasharray = "3 3";
63 + } else {
49 style.stroke = "#1E90FF"; 64 style.stroke = "#1E90FF";
50 style.fill = "#F0F8FF"; 65 style.fill = "#F0F8FF";
66 + }
51 return style; 67 return style;
52 } 68 }
53 } 69 }
......
1 <!-- 1 <!--
2 * @Date: 2025-03-10 16:52:35 2 * @Date: 2025-03-10 16:52:35
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-13 16:51:49 4 + * @LastEditTime: 2025-03-16 00:45:35
5 * @FilePath: /logic-flow2/src/views/adv-menu/index.vue 5 * @FilePath: /logic-flow2/src/views/adv-menu/index.vue
6 * @Description: 拖拽面板 6 * @Description: 拖拽面板
7 --> 7 -->
...@@ -48,7 +48,8 @@ onMounted(() => { ...@@ -48,7 +48,8 @@ onMounted(() => {
48 nodes: [ 48 nodes: [
49 { id: "node1", type: "rect", x: 200, y: 100 }, 49 { id: "node1", type: "rect", x: 200, y: 100 },
50 { id: "node2", type: "circle", x: 400, y: 100 }, 50 { id: "node2", type: "circle", x: 400, y: 100 },
51 - { id: "node3", type: "custom-node", x: 600, y: 100 }, 51 + { id: "node3", type: "custom-node", x: 600, y: 100, properties: { isDisabledNode: true } },
52 + { id: "node4", type: "custom-node", x: 600, y: 300, properties: { isDisabledNode: false } },
52 ], 53 ],
53 edges: [{ id: "edge1", sourceNodeId: "node1", targetNodeId: "node2" }], 54 edges: [{ id: "edge1", sourceNodeId: "node1", targetNodeId: "node2" }],
54 }); 55 });
......
1 +import { RectNode, RectNodeModel } from "@logicflow/core";
2 +
3 +class CustomNodeModel extends RectNodeModel {
4 + // 重写获取文本位置的方法
5 + getTextStyle() {
6 + const style = super.getTextStyle();
7 + style.textWidth = 200; // 设置更大的文本宽度
8 + return style;
9 + }
10 +}
11 +
12 +class CustomNode extends RectNode {
13 + // 扩大文本点击区域
14 + getTextBBox() {
15 + const { model } = this.props;
16 + const { x, y, width, height } = model;
17 + return {
18 + x: x - width / 2,
19 + y: y - height / 2,
20 + width: width,
21 + height: height,
22 + };
23 + }
24 +}
25 +
26 +export default {
27 + type: "custom-rect",
28 + view: CustomNode,
29 + model: CustomNodeModel,
30 +};
1 +<template>
2 + <div class="container">
3 + <div ref="container" class="flow-container"></div>
4 + </div>
5 +</template>
6 +
7 +<script setup>
8 +import LogicFlow from "@logicflow/core";
9 +import { MiniMap, Control } from "@logicflow/extension";
10 +import CustomNode from './customNode';
11 +const container = ref(null);
12 +let lf = null;
13 +
14 +onMounted(() => {
15 + nextTick(() => {
16 + lf = new LogicFlow({
17 + container: container.value,
18 + grid: true,
19 + plugins: [MiniMap, Control],
20 + width: container.value.offsetWidth,
21 + height: container.value.offsetHeight
22 + });
23 +
24 + // 注册自定义节点
25 + lf.register(CustomNode);
26 +
27 + // 监听节点点击事件,点击时进入编辑模式
28 + lf.on("node:click", ({ data }) => {
29 + lf.graphModel.editText(data.id);
30 + });
31 +
32 + // 监听文本编辑完成事件
33 + lf.on("text:update", ({ data }) => {
34 + console.log("文本更新为:", data.text);
35 + });
36 +
37 + // 渲染初始数据
38 + lf.render({
39 + nodes: [
40 + {
41 + id: "node1",
42 + type: "rect",
43 + x: 100,
44 + y: 100,
45 + text: "点击编辑文本"
46 + },
47 + {
48 + id: "node2",
49 + type: "custom-rect", // 使用自定义节点类型
50 + x: 200,
51 + y: 200,
52 + text: "点击编辑文本"
53 + }
54 + ]
55 + });
56 + });
57 +});
58 +
59 +// 判断节点是否可连接
60 +const checkNodeConnectable = (targetNode, sourceNode) => {
61 + return targetNode.type === 'rect';
62 +}
63 +</script>
64 +
65 +<style scoped>
66 +.container {
67 + width: 100vw;
68 + height: 100vh;
69 +}
70 +.flow-container {
71 + width: 100%;
72 + height: 100%;
73 + min-height: 500px;
74 +}
75 +</style>
1 <!-- 1 <!--
2 * @Date: 2025-03-10 16:52:35 2 * @Date: 2025-03-10 16:52:35
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-14 21:42:06 4 + * @LastEditTime: 2025-03-15 19:24:15
5 * @FilePath: /logic-flow2/src/views/control.vue 5 * @FilePath: /logic-flow2/src/views/control.vue
6 * @Description: 拖拽面板 6 * @Description: 拖拽面板
7 --> 7 -->
...@@ -18,107 +18,72 @@ const container = ref(null); ...@@ -18,107 +18,72 @@ const container = ref(null);
18 let lf = null; 18 let lf = null;
19 19
20 onMounted(() => { 20 onMounted(() => {
21 + nextTick(() => { // 使用 nextTick 确保 DOM 已挂载
21 lf = new LogicFlow({ 22 lf = new LogicFlow({
22 container: container.value, 23 container: container.value,
23 grid: true, 24 grid: true,
24 plugins: [MiniMap, Control], 25 plugins: [MiniMap, Control],
25 }); 26 });
26 27
27 - lf.extension.control.addItem({ 28 + // 监听锚点拖拽连线成功事件
28 - key: "mini-map", 29 + lf.on("anchor:drop", ({ data, e }) => {
29 - iconClass: "custom-minimap", 30 + console.log("手动创建连线成功:", {
30 - title: "", 31 + edgeId: data.id,
31 - text: "导航", 32 + sourceNode: data.sourceNodeId,
32 - onMouseEnter: (lf, ev) => { 33 + targetNode: data.targetNodeId,
33 - const position = lf.getPointByClient(ev.x, ev.y); 34 + edgeType: data.type
34 - lf.extension.miniMap.show(
35 - position.domOverlayPosition.x - 120,
36 - position.domOverlayPosition.y + 35
37 - );
38 - },
39 - onClick: (lf, ev) => {
40 - const position = lf.getPointByClient(ev.x, ev.y);
41 - lf.extension.miniMap.show(
42 - position.domOverlayPosition.x - 120,
43 - position.domOverlayPosition.y + 35
44 - );
45 - },
46 }); 35 });
47 -
48 - // 添加克隆节点功能
49 - lf.extension.control.addItem({
50 - key: "clone-node",
51 - iconClass: "custom-clone",
52 - title: "克隆节点",
53 - text: "克隆",
54 - onClick: (lf, ev) => {
55 - const nodes = lf.getSelectElements().nodes;
56 - if (nodes.length) {
57 - nodes.forEach((node) => {
58 - const { x, y, type, properties } = node;
59 - // 在原节点右侧50px处创建新节点
60 - lf.addNode({
61 - type,
62 - x: x + 50,
63 - y,
64 - properties,
65 }); 36 });
37 +
38 + // 监听所有连线创建事件(包括手动和自动)
39 + lf.on("edge:add", ({ data, e }) => {
40 + console.log("连线创建事件:", {
41 + edgeId: data.id,
42 + sourceNode: data.sourceNodeId,
43 + targetNode: data.targetNodeId,
44 + edgeType: data.type,
45 + isManual: e ? true : false, // render 时创建的边,e 为 undefined
46 + createType: e ? '手动创建' : 'render创建'
66 }); 47 });
67 - } 48 + console.log("监听到连线创建:", data);
68 - console.warn("克隆节点", lf.getGraphData());
69 - },
70 }); 49 });
71 50
72 - 51 + // graphModel 的事件监听 - 更底层,返回原始数据
73 - // 添加修改节点ID功能 52 + const { eventCenter } = lf.graphModel;
74 - lf.extension.control.addItem({ 53 + eventCenter.on("node:click", (args) => {
75 - key: "change-node-id", 54 + console.log("graphModel node:click", {
76 - iconClass: "custom-edit", 55 + position: args.position, // 原始坐标
77 - title: "修改节点ID", 56 + data: args.data, // 原始节点数据
78 - text: "改ID", 57 + e: args.e // 原始事件对象
79 - onClick: (lf, ev) => {
80 - const nodes = lf.getSelectElements().nodes;
81 - if (nodes.length === 1) {
82 - const node = nodes[0];
83 - const newId = `node_${Date.now()}`; // 生成新ID
84 - lf.changeNodeId(node.id, newId);
85 - } else {
86 - alert('请选择一个节点');
87 - }
88 - },
89 }); 58 });
90 -
91 - // 添加获取节点信息功能
92 - lf.extension.control.addItem({
93 - key: "get-node-info",
94 - iconClass: "custom-info",
95 - title: "获取节点信息",
96 - text: "节点信息",
97 - onClick: (lf, ev) => {
98 - const nodes = lf.getSelectElements().nodes;
99 - if (nodes.length === 1) {
100 - const node = nodes[0];
101 - // 获取节点 model
102 - const nodeModel = lf.getNodeModelById(node.id);
103 - // 获取节点数据
104 - const nodeData = lf.getNodeDataById(node.id);
105 -
106 - console.log('节点Model:', nodeModel);
107 - console.log('节点Data:', nodeData);
108 - } else {
109 - alert('请选择一个节点');
110 - }
111 - },
112 }); 59 });
113 60
114 - lf.extension.control.removeItem("mini-map"); 61 + // LogicFlow 实例的事件监听 - 更上层,返回处理后的数据
62 + lf.on("node:click", ({ data, e }) => {
63 + console.log("lf node:click", {
64 + id: data.id, // 节点ID
65 + type: data.type, // 节点类型
66 + properties: data.properties, // 节点属性
67 + x: data.x, // 处理后的坐标
68 + y: data.y
69 + });
70 + });
115 71
116 lf.render({ 72 lf.render({
117 nodes: [ 73 nodes: [
118 { id: "node1", type: "rect", x: 200, y: 100 }, 74 { id: "node1", type: "rect", x: 200, y: 100 },
119 { id: "node2", type: "circle", x: 400, y: 100 }, 75 { id: "node2", type: "circle", x: 400, y: 100 },
120 ], 76 ],
121 - edges: [{ id: "edge1", sourceNodeId: "node1", targetNodeId: "node2" }], 77 + // edges: [{ id: "edge1", sourceNodeId: "node1", targetNodeId: "node2", type: "polyline" }],
78 + });
79 +
80 + // 然后手动添加边,这样会触发 edge:add 事件
81 + lf.addEdge({
82 + id: "edge2",
83 + sourceNodeId: "node1",
84 + targetNodeId: "node2",
85 + type: "polyline"
86 + });
122 }); 87 });
123 }); 88 });
124 </script> 89 </script>
...@@ -135,5 +100,6 @@ onMounted(() => { ...@@ -135,5 +100,6 @@ onMounted(() => {
135 flex: 1; 100 flex: 1;
136 width: 100%; 101 width: 100%;
137 height: 100%; 102 height: 100%;
103 + min-height: 500px; /* 可添加最小高度作为保底 */
138 } 104 }
139 </style> 105 </style>
......
1 <!-- 1 <!--
2 * @Date: 2025-03-10 14:37:31 2 * @Date: 2025-03-10 14:37:31
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-14 13:53:06 4 + * @LastEditTime: 2025-03-16 00:22:53
5 * @FilePath: /logic-flow2/src/views/home.vue 5 * @FilePath: /logic-flow2/src/views/home.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
28 <el-button type="primary" @click="goTo('selection-select')">selection-select</el-button> 28 <el-button type="primary" @click="goTo('selection-select')">selection-select</el-button>
29 <el-button type="primary" @click="goTo('snapshot')">snapshot</el-button> 29 <el-button type="primary" @click="goTo('snapshot')">snapshot</el-button>
30 <el-button type="primary" @click="goTo('dynamic-group')">dynamic-group</el-button> 30 <el-button type="primary" @click="goTo('dynamic-group')">dynamic-group</el-button>
31 + <el-button type="primary" @click="goTo('api-graphModel')">api-graphModel</el-button>
31 </template> 32 </template>
32 33
33 <script setup> 34 <script setup>
......