@logicflow/extension 2.2.0-alpha.5 → 2.2.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +15 -0
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/es/bpmn-elements-adapter/json2xml.d.ts +2 -1
- package/es/bpmn-elements-adapter/json2xml.js +18 -4
- package/es/bpmn-elements-adapter/xml2json.js +2 -7
- package/es/components/control/index.js +3 -3
- package/es/index.d.ts +1 -0
- package/es/index.js +2 -0
- package/es/materials/curved-edge/index.js +41 -25
- package/es/pool/LaneModel.d.ts +90 -0
- package/es/pool/LaneModel.js +252 -0
- package/es/pool/LaneView.d.ts +40 -0
- package/es/pool/LaneView.js +202 -0
- package/es/pool/PoolModel.d.ts +120 -0
- package/es/pool/PoolModel.js +586 -0
- package/es/pool/PoolView.d.ts +17 -0
- package/es/pool/PoolView.js +76 -0
- package/es/pool/constant.d.ts +15 -0
- package/es/pool/constant.js +17 -0
- package/es/pool/index.d.ts +89 -0
- package/es/pool/index.js +524 -0
- package/es/pool/utils.d.ts +19 -0
- package/es/pool/utils.js +33 -0
- package/lib/bpmn-elements-adapter/json2xml.d.ts +2 -1
- package/lib/bpmn-elements-adapter/json2xml.js +19 -4
- package/lib/bpmn-elements-adapter/xml2json.js +2 -7
- package/lib/components/control/index.js +3 -3
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -0
- package/lib/materials/curved-edge/index.js +41 -25
- package/lib/pool/LaneModel.d.ts +90 -0
- package/lib/pool/LaneModel.js +255 -0
- package/lib/pool/LaneView.d.ts +40 -0
- package/lib/pool/LaneView.js +205 -0
- package/lib/pool/PoolModel.d.ts +120 -0
- package/lib/pool/PoolModel.js +589 -0
- package/lib/pool/PoolView.d.ts +17 -0
- package/lib/pool/PoolView.js +79 -0
- package/lib/pool/constant.d.ts +15 -0
- package/lib/pool/constant.js +20 -0
- package/lib/pool/index.d.ts +89 -0
- package/lib/pool/index.js +527 -0
- package/lib/pool/utils.d.ts +19 -0
- package/lib/pool/utils.js +38 -0
- package/package.json +5 -5
- package/src/bpmn-elements-adapter/json2xml.ts +18 -4
- package/src/bpmn-elements-adapter/xml2json.ts +2 -8
- package/src/components/control/index.ts +3 -3
- package/src/dynamic-group/index.ts +0 -1
- package/src/index.ts +2 -0
- package/src/materials/curved-edge/index.ts +47 -30
- package/src/pool/LaneModel.ts +226 -0
- package/src/pool/LaneView.ts +220 -0
- package/src/pool/PoolModel.ts +631 -0
- package/src/pool/PoolView.ts +75 -0
- package/src/pool/constant.ts +19 -0
- package/src/pool/index.ts +621 -0
- package/src/pool/utils.ts +46 -0
- package/stats.html +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAllowMoveTo = exports.isBoundsInLane = void 0;
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param bounds
|
|
7
|
+
* @param group
|
|
8
|
+
*/
|
|
9
|
+
function isBoundsInLane(bounds, group) {
|
|
10
|
+
var minX = bounds.minX, minY = bounds.minY, maxX = bounds.maxX, maxY = bounds.maxY;
|
|
11
|
+
var x = group.x, y = group.y, width = group.width, height = group.height;
|
|
12
|
+
return (minX >= x - width / 2 &&
|
|
13
|
+
maxX <= x + width / 2 &&
|
|
14
|
+
minY >= y - height / 2 &&
|
|
15
|
+
maxY <= y + height / 2);
|
|
16
|
+
}
|
|
17
|
+
exports.isBoundsInLane = isBoundsInLane;
|
|
18
|
+
/**
|
|
19
|
+
* 判断 bounds 是否可以移动到下一个范围
|
|
20
|
+
* @param groupBounds
|
|
21
|
+
* @param node
|
|
22
|
+
* @param deltaX
|
|
23
|
+
* @param deltaY
|
|
24
|
+
*/
|
|
25
|
+
function isAllowMoveTo(groupBounds, node, deltaX, deltaY) {
|
|
26
|
+
var minX = groupBounds.minX, minY = groupBounds.minY, maxX = groupBounds.maxX, maxY = groupBounds.maxY;
|
|
27
|
+
var x = node.x, y = node.y, width = node.width, height = node.height;
|
|
28
|
+
// DONE: 计算节点坐标 (x, y) 可移动的范围,并判断 x + deltaX, y + deltaY 是否在范围内
|
|
29
|
+
var allowMoveMinX = minX + width / 2;
|
|
30
|
+
var allowMoveMinY = minY + height / 2;
|
|
31
|
+
var allowMoveMaxX = maxX - width / 2;
|
|
32
|
+
var allowMoveMaxY = maxY - height / 2;
|
|
33
|
+
return {
|
|
34
|
+
x: x + deltaX >= allowMoveMinX && x + deltaX <= allowMoveMaxX,
|
|
35
|
+
y: y + deltaY >= allowMoveMinY && y + deltaY <= allowMoveMaxY,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
exports.isAllowMoveTo = isAllowMoveTo;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logicflow/extension",
|
|
3
|
-
"version": "2.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.7",
|
|
4
4
|
"description": "LogicFlow Extensions",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "es/index.js",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"author": "Logicflow-Team",
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@logicflow/
|
|
24
|
-
"@logicflow/
|
|
23
|
+
"@logicflow/vue-node-registry": "1.2.0-alpha.6",
|
|
24
|
+
"@logicflow/core": "2.2.0-alpha.6"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@antv/hierarchy": "^0.6.11",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"preact": "^10.17.1",
|
|
33
33
|
"rangy": "^1.3.1",
|
|
34
34
|
"vanilla-picker": "^2.12.3",
|
|
35
|
-
"@logicflow/core": "2.2.0-alpha.
|
|
36
|
-
"@logicflow/vue-node-registry": "1.2.0-alpha.
|
|
35
|
+
"@logicflow/core": "2.2.0-alpha.6",
|
|
36
|
+
"@logicflow/vue-node-registry": "1.2.0-alpha.6"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"less": "^4.1.1",
|
|
@@ -24,6 +24,17 @@ function handleAttributes(obj: any): any {
|
|
|
24
24
|
return obj
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function escapeXml(text: string) {
|
|
28
|
+
if (text == null) return ''
|
|
29
|
+
return text
|
|
30
|
+
.toString()
|
|
31
|
+
.replace(/&/g, '&')
|
|
32
|
+
.replace(/</g, '<')
|
|
33
|
+
.replace(/>/g, '>')
|
|
34
|
+
.replace(/"/g, '"')
|
|
35
|
+
.replace(/'/g, ''')
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
function getAttributes(obj: any) {
|
|
28
39
|
let tmp = obj
|
|
29
40
|
try {
|
|
@@ -33,7 +44,7 @@ function getAttributes(obj: any) {
|
|
|
33
44
|
} catch (error) {
|
|
34
45
|
tmp = JSON.stringify(handleAttributes(obj)).replace(/"/g, "'")
|
|
35
46
|
}
|
|
36
|
-
return tmp
|
|
47
|
+
return escapeXml(String(tmp))
|
|
37
48
|
}
|
|
38
49
|
|
|
39
50
|
const tn = '\t\n'
|
|
@@ -44,8 +55,11 @@ function toXml(obj: any, name: string, depth: number) {
|
|
|
44
55
|
let str = ''
|
|
45
56
|
const prefix = tn + frontSpace
|
|
46
57
|
if (name === '-json') return ''
|
|
58
|
+
if (obj !== 0 && obj !== false && !obj) {
|
|
59
|
+
return `${prefix}<${name} />`
|
|
60
|
+
}
|
|
47
61
|
if (name === '#text') {
|
|
48
|
-
return prefix + obj
|
|
62
|
+
return prefix + escapeXml(String(obj))
|
|
49
63
|
}
|
|
50
64
|
if (name === '#cdata-section') {
|
|
51
65
|
return `${prefix}<![CDATA[${obj}]]>`
|
|
@@ -74,7 +88,7 @@ function toXml(obj: any, name: string, depth: number) {
|
|
|
74
88
|
str +=
|
|
75
89
|
attributes + (children !== '' ? `>${children}${prefix}</${name}>` : ' />')
|
|
76
90
|
} else {
|
|
77
|
-
str += `${prefix}<${name}>${obj
|
|
91
|
+
str += `${prefix}<${name}>${escapeXml(String(obj))}</${name}>`
|
|
78
92
|
}
|
|
79
93
|
|
|
80
94
|
return str
|
|
@@ -88,4 +102,4 @@ function lfJson2Xml(obj: any) {
|
|
|
88
102
|
return xmlStr
|
|
89
103
|
}
|
|
90
104
|
|
|
91
|
-
export { lfJson2Xml, handleAttributes }
|
|
105
|
+
export { lfJson2Xml, handleAttributes, escapeXml }
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// @ts-nocheck
|
|
7
7
|
|
|
8
8
|
import { has } from 'lodash-es'
|
|
9
|
+
import { escapeXml } from './json2xml'
|
|
9
10
|
// ========================================================================
|
|
10
11
|
// XML.ObjTree -- XML source code from/to JavaScript object like E4X
|
|
11
12
|
// ========================================================================
|
|
@@ -287,14 +288,7 @@ XML.ObjTree.prototype.scalar_to_xml = function (name, text) {
|
|
|
287
288
|
}
|
|
288
289
|
|
|
289
290
|
// method: xml_escape( text )
|
|
290
|
-
|
|
291
|
-
XML.ObjTree.prototype.xml_escape = function (text) {
|
|
292
|
-
return text
|
|
293
|
-
.replace(/&/g, '&')
|
|
294
|
-
.replace(/</g, '<')
|
|
295
|
-
.replace(/>/g, '>')
|
|
296
|
-
.replace(/"/g, '"')
|
|
297
|
-
}
|
|
291
|
+
XML.ObjTree.prototype.xml_escape = escapeXml
|
|
298
292
|
|
|
299
293
|
/*
|
|
300
294
|
// ========================================================================
|
|
@@ -130,13 +130,13 @@ export class Control {
|
|
|
130
130
|
} else {
|
|
131
131
|
itemContainer.append(icon)
|
|
132
132
|
}
|
|
133
|
-
switch (item.
|
|
134
|
-
case '
|
|
133
|
+
switch (item.key) {
|
|
134
|
+
case 'undo':
|
|
135
135
|
this.lf.on('history:change', ({ data: { undoAble } }: any) => {
|
|
136
136
|
itemContainer.className = undoAble ? NORMAL : DISABLED
|
|
137
137
|
})
|
|
138
138
|
break
|
|
139
|
-
case '
|
|
139
|
+
case 'redo':
|
|
140
140
|
this.lf.on('history:change', ({ data: { redoAble } }: any) => {
|
|
141
141
|
itemContainer.className = redoAble ? NORMAL : DISABLED
|
|
142
142
|
})
|
|
@@ -328,7 +328,6 @@ export class DynamicGroup {
|
|
|
328
328
|
}: Omit<CallbackArgs<'node:click'>, 'e' | 'position'>) => {
|
|
329
329
|
const nodeModel = this.lf.getNodeModelById(node.id)
|
|
330
330
|
this.sendNodeToFront(nodeModel)
|
|
331
|
-
|
|
332
331
|
// 重置所有 group 的 zIndex,防止 group 节点 zIndex 增长为正数(目的是保持 group 节点在最底层)
|
|
333
332
|
if (this.topGroupZIndex > DEFAULT_TOP_Z_INDEX) {
|
|
334
333
|
const { nodes } = this.lf.graphModel
|
package/src/index.ts
CHANGED
|
@@ -97,50 +97,67 @@ function getMidPoints(
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* 生成局部路径片段(包含圆角)
|
|
102
|
+
* - 输入为上一个顶点、当前拐点、下一个顶点,计算方向组合并选择圆弧象限
|
|
103
|
+
* - 将圆角半径限制在相邻两段长度的一半以内,避免过度弯曲
|
|
104
|
+
* @param prevPoint 上一个顶点
|
|
105
|
+
* @param cornerPoint 当前拐点(圆角所在拐点)
|
|
106
|
+
* @param nextPoint 下一个顶点
|
|
107
|
+
* @param cornerRadius 圆角半径上限
|
|
108
|
+
* @returns 局部 path 字符串(包含 L/Q 操作)
|
|
109
|
+
*/
|
|
100
110
|
function getPartialPath(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
111
|
+
prevPoint: PointTuple,
|
|
112
|
+
cornerPoint: PointTuple,
|
|
113
|
+
nextPoint: PointTuple,
|
|
114
|
+
cornerRadius: number,
|
|
105
115
|
): string {
|
|
106
|
-
//
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
// 轴对齐容差(像素),用于消除微小误差
|
|
117
|
+
const epsilon = 1
|
|
118
|
+
|
|
119
|
+
const resolveDir = (a: PointTuple, b: PointTuple): DirectionType => {
|
|
120
|
+
const dx = b[0] - a[0]
|
|
121
|
+
const dy = b[1] - a[1]
|
|
122
|
+
const adx = Math.abs(dx)
|
|
123
|
+
const ady = Math.abs(dy)
|
|
124
|
+
if (ady <= epsilon && adx > epsilon) {
|
|
125
|
+
return dx < 0 ? 'l' : 'r'
|
|
126
|
+
}
|
|
127
|
+
if (adx <= epsilon && ady > epsilon) {
|
|
128
|
+
return dy < 0 ? 't' : 'b'
|
|
129
|
+
}
|
|
130
|
+
if (adx <= epsilon && ady <= epsilon) {
|
|
131
|
+
return ''
|
|
132
|
+
}
|
|
133
|
+
// 非严格对齐时,选择更接近的轴
|
|
134
|
+
return adx < ady ? (dx < 0 ? 'l' : 'r') : dy < 0 ? 't' : 'b'
|
|
118
135
|
}
|
|
119
136
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
} else if (Math.abs(cur[1] - next[1]) <= tolerance) {
|
|
123
|
-
dir2 = cur[0] > next[0] ? 'l' : 'r'
|
|
124
|
-
}
|
|
137
|
+
const dir1: DirectionType = resolveDir(prevPoint, cornerPoint)
|
|
138
|
+
const dir2: DirectionType = resolveDir(cornerPoint, nextPoint)
|
|
125
139
|
|
|
126
140
|
const r =
|
|
127
141
|
Math.min(
|
|
128
|
-
Math.hypot(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
142
|
+
Math.hypot(cornerPoint[0] - prevPoint[0], cornerPoint[1] - prevPoint[1]) /
|
|
143
|
+
2,
|
|
144
|
+
Math.hypot(nextPoint[0] - cornerPoint[0], nextPoint[1] - cornerPoint[1]) /
|
|
145
|
+
2,
|
|
146
|
+
cornerRadius,
|
|
147
|
+
) || (1 / 5) * cornerRadius
|
|
132
148
|
|
|
133
149
|
const key = `${dir1}${dir2}`
|
|
134
150
|
const orientation: ArcQuadrantType = directionMap[key] || '-'
|
|
135
|
-
let path =
|
|
151
|
+
let path = ''
|
|
136
152
|
|
|
137
153
|
if (orientation === '-') {
|
|
138
|
-
|
|
154
|
+
// 仅移动到当前拐点,由下一次迭代决定如何从拐点继续(直线或圆角)
|
|
155
|
+
path += `L ${cornerPoint[0]} ${cornerPoint[1]}`
|
|
139
156
|
} else {
|
|
140
|
-
const [mid1, mid2] = getMidPoints(
|
|
157
|
+
const [mid1, mid2] = getMidPoints(cornerPoint, key, orientation, r)
|
|
141
158
|
if (mid1 && mid2) {
|
|
142
|
-
path += `L ${mid1[0]} ${mid1[1]} Q ${
|
|
143
|
-
;[
|
|
159
|
+
path += `L ${mid1[0]} ${mid1[1]} Q ${cornerPoint[0]} ${cornerPoint[1]} ${mid2[0]} ${mid2[1]}`
|
|
160
|
+
;[cornerPoint[0], cornerPoint[1]] = mid2
|
|
144
161
|
}
|
|
145
162
|
}
|
|
146
163
|
return path
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 基于DynamicGroup重新实现的泳道节点组件
|
|
3
|
+
* 继承DynamicGroupNodeModel和DynamicGroupNode,提供泳道特定功能
|
|
4
|
+
*/
|
|
5
|
+
import LogicFlow from '@logicflow/core'
|
|
6
|
+
import { DynamicGroupNodeModel } from '../dynamic-group'
|
|
7
|
+
import { forEach } from 'lodash-es'
|
|
8
|
+
import { laneConfig } from './constant'
|
|
9
|
+
|
|
10
|
+
export class LaneModel extends DynamicGroupNodeModel {
|
|
11
|
+
readonly isLane: boolean = true
|
|
12
|
+
defaultZIndex: number = -1
|
|
13
|
+
|
|
14
|
+
initNodeData(data: LogicFlow.NodeConfig) {
|
|
15
|
+
super.initNodeData(data)
|
|
16
|
+
// 泳道特定配置
|
|
17
|
+
this.width = data.width || laneConfig.defaultWidth
|
|
18
|
+
this.height = data.height || laneConfig.defaultHeight
|
|
19
|
+
this.draggable = true // 允许拖拽(实际拖拽逻辑由泳池控制)
|
|
20
|
+
this.resizable = true // 允许调整大小
|
|
21
|
+
this.rotatable = false // 禁止旋转
|
|
22
|
+
|
|
23
|
+
// 设置泳道层级
|
|
24
|
+
// 如果传入了zIndex,使用传入的值,否则默认为2
|
|
25
|
+
// 泳道层级应该比所属泳池高,确保显示在泳池上方
|
|
26
|
+
this.defaultZIndex = data.zIndex || -1
|
|
27
|
+
this.setZIndex(this.defaultZIndex)
|
|
28
|
+
this.autoToFront = true
|
|
29
|
+
|
|
30
|
+
this.text.editable = true
|
|
31
|
+
this.style.stroke = '#000'
|
|
32
|
+
this.style.strokeWidth = 1
|
|
33
|
+
|
|
34
|
+
// 泳道属性配置
|
|
35
|
+
this.properties = {
|
|
36
|
+
...this.properties,
|
|
37
|
+
processRef: '', // 流程引用标识
|
|
38
|
+
panels: ['processRef'], // 可配置面板
|
|
39
|
+
direction: data.properties?.direction || 'vertical',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 设置折叠尺寸(泳道不支持折叠,设置为与正常尺寸相同)
|
|
43
|
+
this.collapsedWidth = this.width
|
|
44
|
+
this.collapsedHeight = this.height
|
|
45
|
+
this.expandWidth = this.width
|
|
46
|
+
this.expandHeight = this.height
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setAttributes(): void {
|
|
50
|
+
super.setAttributes()
|
|
51
|
+
this.updateTextPosition()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setZIndex(zIndex: number) {
|
|
55
|
+
this.zIndex = Math.min(zIndex, this.defaultZIndex) || this.defaultZIndex
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 重写折叠方法 - 泳道不支持折叠
|
|
60
|
+
*/
|
|
61
|
+
toggleCollapse() {
|
|
62
|
+
// 泳道不支持折叠功能,保持展开状态
|
|
63
|
+
this.isCollapsed = false
|
|
64
|
+
this.setProperties({ isCollapsed: false })
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 获取所属泳池ID
|
|
69
|
+
*/
|
|
70
|
+
getPoolId(): string | null {
|
|
71
|
+
try {
|
|
72
|
+
// 检查graphModel是否存在
|
|
73
|
+
if (!this.graphModel) {
|
|
74
|
+
console.warn('GraphModel is not available')
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 安全地获取泳池ID
|
|
79
|
+
const poolModel = this.graphModel.nodes.find((node) => {
|
|
80
|
+
return node.children && node.children.has(this.id)
|
|
81
|
+
})
|
|
82
|
+
return poolModel?.id || null
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('Error getting pool ID:', error)
|
|
85
|
+
return null
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 获取所属泳池模型
|
|
91
|
+
*/
|
|
92
|
+
getPoolModel(): any {
|
|
93
|
+
try {
|
|
94
|
+
const poolId = this.getPoolId()
|
|
95
|
+
if (!poolId) {
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 检查graphModel是否存在
|
|
100
|
+
if (!this.graphModel) {
|
|
101
|
+
console.warn('GraphModel is not available for getting pool model')
|
|
102
|
+
return null
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const poolModel = this.graphModel.getNodeModelById(poolId)
|
|
106
|
+
return poolModel || null
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error('Error getting pool model:', error)
|
|
109
|
+
return null
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 动态修改泳道属性
|
|
115
|
+
*/
|
|
116
|
+
changeAttribute({ width, height, x, y }: any) {
|
|
117
|
+
if (width) this.width = width // 更新宽度
|
|
118
|
+
if (height) this.height = height // 更新高度
|
|
119
|
+
if (x) this.x = x // 更新X坐标
|
|
120
|
+
if (y) this.y = y // 更新Y坐标
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 重写获取数据方法,添加泳道特定属性
|
|
125
|
+
*/
|
|
126
|
+
getData(): LogicFlow.NodeData {
|
|
127
|
+
const data = super.getData()
|
|
128
|
+
// const poolModel = this.getPoolModel()
|
|
129
|
+
return {
|
|
130
|
+
...data,
|
|
131
|
+
properties: {
|
|
132
|
+
...data.properties,
|
|
133
|
+
width: this.width,
|
|
134
|
+
height: this.height,
|
|
135
|
+
processRef: this.properties.processRef,
|
|
136
|
+
direction: this.properties.direction,
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* 重写 isAllowAppendIn,禁止 Lane 嵌套
|
|
142
|
+
*/
|
|
143
|
+
isAllowAppendIn(nodeData: LogicFlow.NodeData): boolean {
|
|
144
|
+
// 禁止 Lane 节点被添加到 Lane 中
|
|
145
|
+
return String(nodeData.type) !== 'lane'
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 获取需要移动的节点
|
|
150
|
+
* @param groupModel
|
|
151
|
+
*/
|
|
152
|
+
getNodesInGroup(groupModel: DynamicGroupNodeModel): string[] {
|
|
153
|
+
const nodeIds: string[] = []
|
|
154
|
+
const {
|
|
155
|
+
properties: { parent },
|
|
156
|
+
isDragging,
|
|
157
|
+
} = groupModel
|
|
158
|
+
if (isDragging && parent) {
|
|
159
|
+
nodeIds.push(parent as string)
|
|
160
|
+
}
|
|
161
|
+
forEach(Array.from(groupModel.children), (nodeId: string) => {
|
|
162
|
+
const nodeModel = this.graphModel.getNodeModelById(nodeId)
|
|
163
|
+
// 只有非 Lane 类型的节点才会被带动
|
|
164
|
+
if (
|
|
165
|
+
nodeModel &&
|
|
166
|
+
!nodeModel.isDragging &&
|
|
167
|
+
String(nodeModel.type) !== 'lane'
|
|
168
|
+
) {
|
|
169
|
+
nodeIds.push(nodeId)
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
return nodeIds
|
|
173
|
+
}
|
|
174
|
+
getNodeStyle() {
|
|
175
|
+
const style = super.getNodeStyle()
|
|
176
|
+
style.strokeWidth = 2
|
|
177
|
+
return style
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 获取文本样式
|
|
181
|
+
*/
|
|
182
|
+
getTextStyle() {
|
|
183
|
+
const { isHorizontal = false } = this.properties
|
|
184
|
+
const style = super.getTextStyle()
|
|
185
|
+
style.overflowMode = 'ellipsis'
|
|
186
|
+
style.strokeWidth = 2
|
|
187
|
+
style.textWidth = isHorizontal ? this.height : this.width
|
|
188
|
+
style.textHeight = isHorizontal ? this.width : this.height
|
|
189
|
+
if (isHorizontal) {
|
|
190
|
+
style.transform = 'rotate(-90deg)'
|
|
191
|
+
style.textAlign = 'center'
|
|
192
|
+
}
|
|
193
|
+
return style
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* 获取子泳道
|
|
198
|
+
*/
|
|
199
|
+
getSubNodes() {
|
|
200
|
+
const children: any[] = []
|
|
201
|
+
Array.from(this.children).forEach((childId) => {
|
|
202
|
+
const childModel = this.graphModel.getNodeModelById(childId)
|
|
203
|
+
if (childModel) {
|
|
204
|
+
children.push(childModel)
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
return children
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* 初始化文本位置 - 根据布局方向设置文本位置
|
|
212
|
+
*/
|
|
213
|
+
updateTextPosition() {
|
|
214
|
+
if (this.properties.isHorizontal) {
|
|
215
|
+
// 横向泳池:文本显示在左侧标题区域
|
|
216
|
+
this.text.x = this.x - this.width / 2 + laneConfig.titleSize / 2
|
|
217
|
+
this.text.y = this.y
|
|
218
|
+
} else {
|
|
219
|
+
// 纵向泳池:文本显示在顶部标题区域
|
|
220
|
+
this.text.x = this.x
|
|
221
|
+
this.text.y = this.y - this.height / 2 + laneConfig.titleSize / 2
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export default null
|