sqlNode.js
4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import { HtmlNode, HtmlNodeModel, h } from '@logicflow/core'
class SqlNode extends HtmlNode {
/**
* 1.1.7版本后支持在view中重写锚点形状。
* 重写锚点新增
*/
// 自定义锚点形状
getAnchorShape(anchorData) {
const { x, y, type } = anchorData
// 将锚点渲染为矩形,左右锚点使用不同的样式类
return h('rect', {
x: x - 5,
y: y - 5,
width: 10,
height: 10,
className: `custom-anchor ${
type === 'left' ? 'incoming-anchor' : 'outgoing-anchor'
}`,
})
}
setHtml(rootEl) { // 渲染节点的 HTML 内容
rootEl.innerHTML = ''
const {
properties: { fields, tableName },
} = this.props.model
rootEl.setAttribute('class', 'table-container')
const container = document.createElement('div')
container.className = `table-node table-color-${Math.ceil(
Math.random() * 4,
)}`
const tableNameElement = document.createElement('div')
tableNameElement.innerText = tableName
tableNameElement.className = 'table-name'
container.appendChild(tableNameElement)
const fragment = document.createDocumentFragment()
for (let i = 0; i < fields.length; i++) {
const item = fields[i]
const itemElement = document.createElement('div')
itemElement.className = 'table-felid'
const itemKey = document.createElement('span')
itemKey.innerText = item.key
const itemType = document.createElement('span')
itemType.innerText = item.type
itemType.className = 'felid-type'
itemElement.appendChild(itemKey)
itemElement.appendChild(itemType)
fragment.appendChild(itemElement)
}
container.appendChild(fragment)
rootEl.appendChild(container)
}
}
class SqlNodeModel extends HtmlNodeModel {
/**
* 给model自定义添加字段方法
*/
addField(item) {
this.properties.fields.unshift(item) // 在字段列表开头添加新字段
this.setAttributes() // 更新节点尺寸
// 为了保持节点顶部位置不变,在节点变化后,对节点进行一个位移,位移距离为添加高度的一半。
this.move(0, 24 / 2) // 调整节点位置保持顶部对齐
// 更新节点连接边的path
this.incoming.edges.forEach((edge) => {
// 调用自定义的更新方案
edge.updatePathByAnchor()
})
this.outgoing.edges.forEach((edge) => {
// 调用自定义的更新方案
edge.updatePathByAnchor()
})
}
getOutlineStyle() {
const style = super.getOutlineStyle()
style.stroke = 'none' // 移除选中外框
style.hover.stroke = 'none' // 设置节点轮廓为透明
return style
}
// 如果不用修改锚地形状,可以重写颜色相关样式
getAnchorStyle(anchorInfo) {
const style = super.getAnchorStyle()
if (anchorInfo.type === 'left') { // 左侧锚点红色(输入)
style.fill = 'red'
style.hover.fill = 'transparent'
style.hover.stroke = 'transparent'
style.className = 'lf-hide-default'
} else { // 右侧锚点绿色(输出)
style.fill = 'green'
}
return style
}
setAttributes() { // 设置节点属性
this.width = 200; // 设置节点宽度为 200
const {
properties: { fields },
} = this
this.height = 60 + fields.length * 24; // 根据字段数量计算高度
// 添加连线规则:
// 1. 只能从右侧锚点连出
// 2. 只能连接到左侧锚点
const circleOnlyAsTarget = {
message: '只允许从右边的锚点连出',
validate: (sourceNode, targetNode, sourceAnchor) => {
return sourceAnchor.type === 'right'
},
}
this.sourceRules.push(circleOnlyAsTarget)
this.targetRules.push({
message: '只允许连接左边的锚点',
validate: (sourceNode, targetNode, sourceAnchor, targetAnchor) => {
return targetAnchor.type === 'left'
},
})
}
getDefaultAnchor() { // 获取默认锚点
const {
id,
x,
y,
width,
height,
isHovered,
isSelected,
properties: { fields, isConnection },
} = this
const anchors = []
fields.forEach((felid, index) => {
// 如果是连出,就不显示左边的锚点
if (isConnection || !(isHovered || isSelected)) {
anchors.push({
x: x - width / 2 + 10,
y: y - height / 2 + 60 + index * 24,
id: `${id}_${felid.key}_left`,
edgeAddable: false, // 设置左侧锚点不能作为连线起点, 自定义锚点支持设置edgeAddable属性,用于控制是否可以在此锚点手动创建连线。
type: 'left',
})
}
if (!isConnection) {
anchors.push({
x: x + width / 2 - 10,
y: y - height / 2 + 60 + index * 24,
id: `${id}_${felid.key}_right`,
type: 'right',
})
}
})
return anchors
}
}
export default {
type: 'sql-node',
model: SqlNodeModel,
view: SqlNode,
}