hookehuyr

feat: 新增release页面和自定义多边形节点

新增release.vue页面,用于展示拖拽面板。在node-model中新增自定义多边形节点,并更新相关路由和依赖配置。
This diff is collapsed. Click to expand it.
...@@ -145,6 +145,11 @@ const router = createRouter({ ...@@ -145,6 +145,11 @@ const router = createRouter({
145 name: 'api-transform-model', 145 name: 'api-transform-model',
146 component: () => import('../views/api/transformModel.vue') 146 component: () => import('../views/api/transformModel.vue')
147 }, 147 },
148 + {
149 + path: '/release',
150 + name: 'release',
151 + component: () => import('../views/release.vue')
152 + },
148 ] 153 ]
149 }) 154 })
150 155
......
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-19 00:57:55 4 + * @LastEditTime: 2025-03-19 10:46:41
5 * @FilePath: /logic-flow2/src/views/api/transformModel.vue 5 * @FilePath: /logic-flow2/src/views/api/transformModel.vue
6 * @Description: 拖拽面板 6 * @Description: 拖拽面板
7 --> 7 -->
...@@ -59,14 +59,17 @@ const centerView = () => { ...@@ -59,14 +59,17 @@ const centerView = () => {
59 if (nodes.length === 0) return; 59 if (nodes.length === 0) return;
60 60
61 // 计算所有节点的边界框 61 // 计算所有节点的边界框
62 - const bounds = nodes.reduce((acc, node) => { 62 + const bounds = nodes.reduce(
63 - const { x, y } = node; 63 + (acc, node) => {
64 - acc.minX = Math.min(acc.minX, x); 64 + const { x, y } = node;
65 - acc.maxX = Math.max(acc.maxX, x); 65 + acc.minX = Math.min(acc.minX, x);
66 - acc.minY = Math.min(acc.minY, y); 66 + acc.maxX = Math.max(acc.maxX, x);
67 - acc.maxY = Math.max(acc.maxY, y); 67 + acc.minY = Math.min(acc.minY, y);
68 - return acc; 68 + acc.maxY = Math.max(acc.maxY, y);
69 - }, { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity }); 69 + return acc;
70 + },
71 + { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity }
72 + );
70 73
71 // 计算中心点和范围 74 // 计算中心点和范围
72 const centerX = (bounds.minX + bounds.maxX) / 2; 75 const centerX = (bounds.minX + bounds.maxX) / 2;
...@@ -82,6 +85,7 @@ onMounted(() => { ...@@ -82,6 +85,7 @@ onMounted(() => {
82 lf = new LogicFlow({ 85 lf = new LogicFlow({
83 container: container.value, 86 container: container.value,
84 grid: true, 87 grid: true,
88 + nodeTextDraggable: true,
85 }); 89 });
86 90
87 // 监听点击画布功能 91 // 监听点击画布功能
...@@ -89,12 +93,11 @@ onMounted(() => { ...@@ -89,12 +93,11 @@ onMounted(() => {
89 console.log("Canvas clicked at:", e.x, e.y); 93 console.log("Canvas clicked at:", e.x, e.y);
90 }); 94 });
91 95
92 - lf.on('node:click', (e) => { 96 + lf.on("node:click", (e) => {
93 console.log(e); 97 console.log(e);
94 // 示例:HTML坐标转换为画布坐标 98 // 示例:HTML坐标转换为画布坐标
95 console.warn(e); 99 console.warn(e);
96 100
97 -
98 const htmlPoint = { x: 100, y: 100 }; 101 const htmlPoint = { x: 100, y: 100 };
99 const { transformModel } = lf.graphModel; 102 const { transformModel } = lf.graphModel;
100 const canvasPoint = transformModel.HtmlPointToCanvasPoint(htmlPoint); 103 const canvasPoint = transformModel.HtmlPointToCanvasPoint(htmlPoint);
...@@ -116,14 +119,17 @@ onMounted(() => { ...@@ -116,14 +119,17 @@ onMounted(() => {
116 const nodes = lf.graphModel.nodes; 119 const nodes = lf.graphModel.nodes;
117 if (nodes.length === 0) return; 120 if (nodes.length === 0) return;
118 121
119 - const bounds = nodes.reduce((acc, node) => { 122 + const bounds = nodes.reduce(
120 - const { x, y } = node; 123 + (acc, node) => {
121 - acc.minX = Math.min(acc.minX, x); 124 + const { x, y } = node;
122 - acc.maxX = Math.max(acc.maxX, x); 125 + acc.minX = Math.min(acc.minX, x);
123 - acc.minY = Math.min(acc.minY, y); 126 + acc.maxX = Math.max(acc.maxX, x);
124 - acc.maxY = Math.max(acc.maxY, y); 127 + acc.minY = Math.min(acc.minY, y);
125 - return acc; 128 + acc.maxY = Math.max(acc.maxY, y);
126 - }, { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity }); 129 + return acc;
130 + },
131 + { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity }
132 + );
127 133
128 const centerX = (bounds.minX + bounds.maxX) / 2; 134 const centerX = (bounds.minX + bounds.maxX) / 2;
129 const centerY = (bounds.minY + bounds.maxY) / 2; 135 const centerY = (bounds.minY + bounds.maxY) / 2;
...@@ -133,7 +139,10 @@ onMounted(() => { ...@@ -133,7 +139,10 @@ onMounted(() => {
133 // transformModel.focusOn(centerX, centerY, width, height); 139 // transformModel.focusOn(centerX, centerY, width, height);
134 }, 0); 140 }, 0);
135 141
136 - 142 + const { editConfigModel } = lf.graphModel;
143 + editConfigModel.updateEditConfig({
144 + stopZoomGraph: true,
145 + });
137 }); 146 });
138 </script> 147 </script>
139 148
......
1 +/*
2 + * @Date: 2025-03-19 17:24:14
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-19 17:24:38
5 + * @FilePath: /logic-flow2/src/views/node-model/customPolygon.js
6 + * @Description: 文件描述
7 + */
8 +import { PolygonNode, PolygonNodeModel } from '@logicflow/core';
9 +
10 +class CustomPolygonModel extends PolygonNodeModel {
11 + // 默认四边形 => 八边形
12 + setAttributes() {
13 + const width = 100;
14 + const height = 100;
15 + const x = 50;
16 + const y = 50;
17 + // 计算多边形的八个顶点, 中心点为[50, 50], 宽高均为100
18 + const pointList = [
19 + [x - 0.205 * width, y - 0.5 * height],
20 + [x + 0.205 * width, y - 0.5 * height],
21 + [x + 0.5 * width, y - 0.205 * height],
22 + [x + 0.5 * width, y + 0.205 * height],
23 + [x + 0.205 * width, y + 0.5 * height],
24 + [x - 0.205 * width, y + 0.5 * height],
25 + [x - 0.5 * width, y + 0.205 * height],
26 + [x - 0.5 * width, y - 0.205 * height],
27 + ];
28 + this.points = pointList;
29 + }
30 +
31 + getTextStyle() {
32 + const { refX = 0, refY = 0 } = this.properties;
33 + const style = super.getTextStyle();
34 +
35 + // 通过 transform 重新设置 text 的位置:向下移动70px
36 + return {
37 + ...style,
38 + transform: `matrix(1 0 0 1 ${refX} ${refY + 70})`,
39 + };
40 + }
41 +}
42 +
43 +export default {
44 + type: 'custom-polygon',
45 + view: PolygonNode,
46 + model: CustomPolygonModel,
47 +};
1 /* 1 /*
2 * @Date: 2025-03-11 15:09:49 2 * @Date: 2025-03-11 15:09:49
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-11 15:45:06 4 + * @LastEditTime: 2025-03-19 17:26:16
5 - * @FilePath: /logic-flow2/src/views/node/data.js 5 + * @FilePath: /logic-flow2/src/views/node-model/data.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
8 export default { 8 export default {
...@@ -47,5 +47,12 @@ export default { ...@@ -47,5 +47,12 @@ export default {
47 height: 130, 47 height: 130,
48 }, 48 },
49 }, 49 },
50 + {
51 + id: '4',
52 + type: 'custom-polygon',
53 + x: 100,
54 + y: 300,
55 + text: 'custom-polygon',
56 + }
50 ], 57 ],
51 }; 58 };
......
1 <!-- 1 <!--
2 * @Date: 2025-03-11 15:07:29 2 * @Date: 2025-03-11 15:07:29
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-03-11 16:18:37 4 + * @LastEditTime: 2025-03-19 17:31:46
5 - * @FilePath: /logic-flow2/src/views/node/index.vue 5 + * @FilePath: /logic-flow2/src/views/node-model/index.vue
6 * @Description: 自定义节点model 6 * @Description: 自定义节点model
7 --> 7 -->
8 <template> 8 <template>
...@@ -12,9 +12,10 @@ ...@@ -12,9 +12,10 @@
12 </template> 12 </template>
13 13
14 <script setup> 14 <script setup>
15 -import LogicFlow from '@logicflow/core'; 15 +import LogicFlow from "@logicflow/core";
16 -import UserTask from './customRect'; 16 +import UserTask from "./customRect";
17 -import data from './data'; 17 +import customPolygon from "./customPolygon";
18 +import data from "./data";
18 19
19 const SilentConfig = { 20 const SilentConfig = {
20 isSilentMode: true, 21 isSilentMode: true,
...@@ -35,6 +36,15 @@ onMounted(() => { ...@@ -35,6 +36,15 @@ onMounted(() => {
35 }); 36 });
36 37
37 lf.register(UserTask); 38 lf.register(UserTask);
39 + lf.register(customPolygon);
40 +
41 + lf.on("node:click", ({ data }) => {
42 + if (data.type === "custom-polygon") {
43 + const node = lf.getNodeModelById(data.id);
44 + console.log("节点顶点坐标:", node.points);
45 + }
46 + });
47 +
38 lf.render(data); 48 lf.render(data);
39 lf.translateCenter(); 49 lf.translateCenter();
40 }); 50 });
......
1 +<!--
2 + * @Date: 2025-03-10 16:52:35
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2025-03-19 11:32:33
5 + * @FilePath: /logic-flow2/src/views/release.vue
6 + * @Description: 拖拽面板
7 +-->
8 +<template>
9 + <div class="container">
10 + <div ref="container" class="flow-container"></div>
11 + </div>
12 +</template>
13 +
14 +<script setup>
15 +import LogicFlow from "@logicflow/core";
16 +
17 +const container = ref(null);
18 +let lf = null;
19 +
20 +onMounted(() => {
21 + lf = new LogicFlow({
22 + container: container.value,
23 + grid: true,
24 + nodeTextDraggable: true,
25 + nodeTextEdit: true,
26 + edgeTextEdit: true,
27 + stopScrollGraph: true,
28 + stopZoomGraph: false,
29 + style: {
30 + rect: {
31 + width: 100,
32 + height: 50,
33 + radius: 8,
34 + },
35 + circle: {
36 + r: 30,
37 + },
38 + },
39 + });
40 +
41 + lf.render({
42 + nodes: [
43 + {
44 + id: "start",
45 + type: "rect",
46 + x: 200,
47 + y: 100,
48 + text: "开始",
49 + properties: {
50 + nodeType: "start",
51 + style: {
52 + fill: "#e8f7ff",
53 + stroke: "#1890ff",
54 + strokeWidth: 2,
55 + },
56 + textStyle: {
57 + color: "#1890ff",
58 + fontSize: 16,
59 + fontWeight: "bold",
60 + },
61 + },
62 + },
63 + {
64 + id: "process",
65 + type: "circle",
66 + x: 400,
67 + y: 100,
68 + text: "处理",
69 + properties: {
70 + nodeType: "process",
71 + style: {
72 + fill: "#fff7e6",
73 + stroke: "#ffa940",
74 + strokeWidth: 2,
75 + },
76 + },
77 + },
78 + ],
79 + edges: [
80 + {
81 + id: "edge1",
82 + sourceNodeId: "start",
83 + targetNodeId: "process",
84 + type: "polyline",
85 + text: "流转",
86 + properties: {
87 + style: {
88 + stroke: "#1890ff",
89 + strokeWidth: 2,
90 + },
91 + },
92 + },
93 + ],
94 + });
95 +
96 + // 监听节点点击
97 + lf.on("node:click", ({ data }) => {
98 + console.log("点击节点:", data);
99 + });
100 +
101 + // 监听连线完成
102 + lf.on("edge:connect", ({ data }) => {
103 + console.log("连线完成:", data);
104 + });
105 +
106 + // 监听画布缩放
107 + lf.on("graph:transform", (transform) => {
108 + console.log("画布变换:", transform);
109 + });
110 +
111 + // 居中显示
112 + lf.translateCenter();
113 +});
114 +</script>
115 +
116 +<style scoped>
117 +.container {
118 + width: 100vw;
119 + height: 100vh;
120 + display: flex;
121 + flex-direction: column;
122 +}
123 +
124 +.flow-container {
125 + flex: 1;
126 + width: 100%;
127 + height: 100%;
128 +}
129 +</style>