vue-wiring-diagram 1.0.16 → 1.0.18
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/dist/style.css +1 -1
- package/dist/vue-wiring-diagram.es.js +13307 -12823
- package/dist/vue-wiring-diagram.umd.js +259 -259
- package/package.json +1 -1
- package/packages/components/common.js +29 -1
- package/packages/components/edge-control/condition.vue +88 -0
- package/packages/components/edge-control/index.vue +228 -51
- package/packages/components/editor/index.vue +15 -5
- package/packages/components/enums.js +60 -0
- package/packages/components/preview/index.vue +57 -54
- package/packages/components/settings.js +43 -18
- package/packages/components/text-control/index.vue +13 -20
- package/packages/components/tools.js +35 -0
|
@@ -12,6 +12,7 @@ import {onMounted, onUnmounted, ref, shallowRef} from "vue";
|
|
|
12
12
|
import {Graph} from "@antv/x6";
|
|
13
13
|
import {getData, getRealData, showPorts} from "../common.js";
|
|
14
14
|
import {ElMessage} from "element-plus";
|
|
15
|
+
import {defaultMatch, defaultText, setPipeDirection} from "packages/components/tools.js";
|
|
15
16
|
|
|
16
17
|
defineOptions({
|
|
17
18
|
name: 'wiring-diagram-preview'
|
|
@@ -42,9 +43,6 @@ const props = defineProps({
|
|
|
42
43
|
}
|
|
43
44
|
})
|
|
44
45
|
|
|
45
|
-
// 所有字段
|
|
46
|
-
const allFields = ref([])
|
|
47
|
-
|
|
48
46
|
// 画布
|
|
49
47
|
const graph = ref()
|
|
50
48
|
|
|
@@ -94,7 +92,7 @@ const renderData = async () => {
|
|
|
94
92
|
if (props.id) {
|
|
95
93
|
const {background: bg, grid: gd, data: dt} = await getData(props.id);
|
|
96
94
|
background = bg;
|
|
97
|
-
grid =
|
|
95
|
+
grid = gd;
|
|
98
96
|
data = dt;
|
|
99
97
|
} else {
|
|
100
98
|
background = props.background;
|
|
@@ -110,30 +108,27 @@ const renderData = async () => {
|
|
|
110
108
|
|
|
111
109
|
// 定时器
|
|
112
110
|
const timer = ref(null)
|
|
113
|
-
//
|
|
114
|
-
const
|
|
111
|
+
// 节点
|
|
112
|
+
const cells = ref([])
|
|
113
|
+
// 参数
|
|
114
|
+
const allFields = ref([])
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
117
|
* 刷新数据
|
|
118
118
|
*/
|
|
119
119
|
const refreshData = () => {
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
cells.value = graph.value.getCells().filter(cell => cell?.data?.type === 'text' || cell?.data?.type === 'pipe')
|
|
121
|
+
cells.value.forEach(item => {
|
|
122
|
+
if (item?.data?.fields?.length) {
|
|
123
|
+
item.data.fields.forEach(field => {
|
|
124
|
+
if (field.field) {
|
|
125
|
+
allFields.value.push({id: item?.id, fields: item?.data.fields})
|
|
126
|
+
}
|
|
127
|
+
})
|
|
122
128
|
|
|
123
|
-
textNodes.value.forEach(node => {
|
|
124
|
-
// 确保 node.data 和 node.data.field 存在
|
|
125
|
-
if (!node.data || !node.data.field) return;
|
|
126
|
-
|
|
127
|
-
const matches = node.data.content.match(regex);
|
|
128
|
-
allFields.value.push(...node.data.field);
|
|
129
|
-
|
|
130
|
-
if (matches) {
|
|
131
|
-
node.matches = matches;
|
|
132
129
|
}
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
return
|
|
136
|
-
}
|
|
130
|
+
})
|
|
131
|
+
console.log('所有字段', allFields.value)
|
|
137
132
|
setFieldData()
|
|
138
133
|
}
|
|
139
134
|
|
|
@@ -160,61 +155,69 @@ const setFieldData = async () => {
|
|
|
160
155
|
|
|
161
156
|
isAllowRefresh.value = false
|
|
162
157
|
|
|
163
|
-
|
|
158
|
+
let realData = await getRealData(allFields.value).catch(() => {
|
|
159
|
+
isAllowRefresh.value = true
|
|
160
|
+
})
|
|
164
161
|
|
|
165
162
|
isAllowRefresh.value = true
|
|
166
163
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
let length = 0
|
|
172
|
-
textNodes.value.forEach((node, index) => {
|
|
173
|
-
// 确保 node.data 和 node.data.field 存在
|
|
174
|
-
if (!node.data || !node.data.field) return;
|
|
175
|
-
|
|
176
|
-
const matches = node.matches;
|
|
177
|
-
if (matches) {
|
|
178
|
-
const start = index === 0 ? 0 : length || 0;
|
|
179
|
-
const end = length = start + node.data.field.length;
|
|
180
|
-
node.label = replaceAllTemplateLiteralsWithArray(node.data.content, realData.slice(start, end));
|
|
164
|
+
realData?.forEach(item => {
|
|
165
|
+
const cell = graph.value.getCellById(item.id)
|
|
166
|
+
if (cell.data.type === 'text') {
|
|
167
|
+
cell.label = replaceAllTemplateLiteralsWithArray(cell.data.content, item.fields)
|
|
181
168
|
}
|
|
182
|
-
|
|
169
|
+
if (cell.data.type === 'pipe') {
|
|
170
|
+
console.log('管道详情', cell, item.fields?.[0].value)
|
|
171
|
+
setPipe(cell, item.fields?.[0].value)
|
|
172
|
+
// TODO: 暂时不支持管道
|
|
173
|
+
}
|
|
174
|
+
})
|
|
183
175
|
timer.value = setTimeout(() => {
|
|
184
176
|
setFieldData()
|
|
185
177
|
}, 10000)
|
|
186
178
|
}
|
|
187
179
|
|
|
188
|
-
|
|
189
180
|
/**
|
|
190
|
-
*
|
|
181
|
+
* 替换模板字符串
|
|
182
|
+
* @param str 模板字符串
|
|
183
|
+
* @param fields 替换数组
|
|
184
|
+
* @returns {*}
|
|
191
185
|
*/
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
return
|
|
186
|
+
const replaceAllTemplateLiteralsWithArray = (str, fields) => {
|
|
187
|
+
let index = 0
|
|
188
|
+
return str.replace(defaultMatch, (match, p1) => {
|
|
189
|
+
const field = fields.find(item => item.index === index)
|
|
190
|
+
index++
|
|
191
|
+
if (field) {
|
|
192
|
+
return field.value
|
|
193
|
+
} else {
|
|
194
|
+
return defaultText
|
|
195
|
+
}
|
|
196
|
+
})
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
/**
|
|
198
|
-
*
|
|
199
|
-
* @param
|
|
200
|
-
* @param
|
|
201
|
-
* @returns {*}
|
|
200
|
+
* 设置管道
|
|
201
|
+
* @param cell
|
|
202
|
+
* @param value
|
|
202
203
|
*/
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
204
|
+
const setPipe = (cell, value) => {
|
|
205
|
+
if(!cell.data.isCondition) {
|
|
206
|
+
return false
|
|
207
|
+
}
|
|
208
|
+
for (let i = 0; i < cell.data.condition.length; i++) {
|
|
209
|
+
if (value > cell.data.condition[i].min && value <= cell.data.condition[i].max) {
|
|
210
|
+
cell.attr('line2/style/animation', setPipeDirection(cell.data.condition[i].direction))
|
|
211
|
+
return false
|
|
208
212
|
}
|
|
209
|
-
|
|
210
|
-
});
|
|
213
|
+
}
|
|
211
214
|
}
|
|
212
215
|
|
|
213
216
|
/**
|
|
214
217
|
* \@description 画布自适应
|
|
215
218
|
*/
|
|
216
219
|
const zoomToFit = () => {
|
|
217
|
-
graph.value.zoomToFit({maxScale:
|
|
220
|
+
graph.value.zoomToFit({maxScale: 1.4, padding: 20})
|
|
218
221
|
}
|
|
219
222
|
|
|
220
223
|
const previewRef = shallowRef()
|
|
@@ -82,7 +82,7 @@ export const textOptions = {
|
|
|
82
82
|
data: {
|
|
83
83
|
type: 'text',
|
|
84
84
|
content: '文本',
|
|
85
|
-
|
|
85
|
+
fields: []
|
|
86
86
|
},
|
|
87
87
|
ports: {
|
|
88
88
|
groups: {
|
|
@@ -96,24 +96,49 @@ export const textOptions = {
|
|
|
96
96
|
|
|
97
97
|
// 线配置
|
|
98
98
|
export const lineOptions = {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
99
|
+
markup: [
|
|
100
|
+
{
|
|
101
|
+
tagName: 'path',
|
|
102
|
+
selector: 'line1',
|
|
103
|
+
groupSelector: 'lines'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
tagName: 'path',
|
|
107
|
+
selector: 'line2',
|
|
108
|
+
groupSelector: 'lines'
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
attrs: {
|
|
112
|
+
lines: {
|
|
113
|
+
connection: true,
|
|
114
|
+
strokeLinejoin: 'round',
|
|
115
|
+
fill: 'none',
|
|
116
|
+
strokeWidth: 2,
|
|
117
|
+
},
|
|
118
|
+
line1: {
|
|
119
|
+
stroke: '#2364DD',
|
|
120
|
+
strokeWidth: 1,
|
|
109
121
|
},
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
line2: {
|
|
123
|
+
stroke: '#ffffff',
|
|
124
|
+
strokeWidth: 1,
|
|
125
|
+
strokeDasharray: 0,
|
|
126
|
+
sourceMarker: {
|
|
127
|
+
args: {
|
|
128
|
+
width: 10,
|
|
129
|
+
height: 10,
|
|
130
|
+
offset: 0,
|
|
131
|
+
},
|
|
132
|
+
name: null
|
|
133
|
+
},
|
|
134
|
+
targetMarker: {
|
|
135
|
+
args: {
|
|
136
|
+
width: 10,
|
|
137
|
+
height: 10,
|
|
138
|
+
offset: 0,
|
|
139
|
+
},
|
|
140
|
+
name: null
|
|
115
141
|
},
|
|
116
|
-
name: null
|
|
117
142
|
},
|
|
118
|
-
}
|
|
143
|
+
}
|
|
119
144
|
}
|
|
@@ -146,10 +146,12 @@
|
|
|
146
146
|
<script setup>
|
|
147
147
|
import {onMounted, reactive, ref,} from "vue";
|
|
148
148
|
import {DeleteFilled} from '@element-plus/icons-vue'
|
|
149
|
-
import {showPorts} from "../common.js";
|
|
149
|
+
import {getFieldList, showPorts} from "../common.js";
|
|
150
150
|
import {get} from '../../http.js'
|
|
151
151
|
import {ElMessageBox} from "element-plus";
|
|
152
152
|
import {portOption} from "../settings.js";
|
|
153
|
+
import {defaultMatch, defaultText} from "packages/components/tools.js";
|
|
154
|
+
import {getDeviceList} from "/packages/components/common.js";
|
|
153
155
|
|
|
154
156
|
defineOptions({
|
|
155
157
|
name: 'text-control'
|
|
@@ -168,10 +170,8 @@ const fieldList = ref([])
|
|
|
168
170
|
/**
|
|
169
171
|
* 获取设备列表
|
|
170
172
|
*/
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
deviceList.value = res.data
|
|
174
|
-
})
|
|
173
|
+
const getDevices = async () => {
|
|
174
|
+
deviceList.value = await getDeviceList()
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
const deviceCode = ref() // 设备编码
|
|
@@ -190,19 +190,13 @@ const checkDevice = () => {
|
|
|
190
190
|
/**
|
|
191
191
|
* 获取字段列表
|
|
192
192
|
*/
|
|
193
|
-
const getFields = () => {
|
|
194
|
-
|
|
195
|
-
deviceCode: currentDevice.deviceCode,
|
|
196
|
-
fieldType: 1
|
|
197
|
-
}).then(res => {
|
|
198
|
-
fieldList.value = res.data
|
|
199
|
-
})
|
|
193
|
+
const getFields = async () => {
|
|
194
|
+
fieldList.value = await getFieldList(currentDevice.deviceCode)
|
|
200
195
|
}
|
|
201
196
|
|
|
202
|
-
const regexp = /\$\{(.*?)\}/g // 匹配${}
|
|
203
197
|
|
|
204
198
|
const replace = (str) => {
|
|
205
|
-
return str.replace(
|
|
199
|
+
return str.replace(defaultMatch, defaultText)
|
|
206
200
|
}
|
|
207
201
|
|
|
208
202
|
/**
|
|
@@ -219,16 +213,15 @@ const checkField = (row) => {
|
|
|
219
213
|
const content = props.payload.data.content
|
|
220
214
|
props.payload.data.content = text.value = content + '${' + currentDevice.deviceName + '.' + row.name + '}' + unit
|
|
221
215
|
// 查找所有${}
|
|
222
|
-
const matches = content.match(
|
|
216
|
+
const matches = content.match(defaultMatch)
|
|
223
217
|
const index = matches?.length || 0
|
|
224
|
-
props.payload.data.
|
|
218
|
+
props.payload.data.fields.push({
|
|
225
219
|
index: index,
|
|
226
220
|
deviceName: currentDevice.deviceName,
|
|
227
221
|
deviceCode: currentDevice.deviceCode,
|
|
228
222
|
field: row.dataField,
|
|
229
223
|
})
|
|
230
224
|
props.payload.label = replace(props.payload.data.content)
|
|
231
|
-
console.log('label:', props.payload.label, 'content:', props.payload.data.content, 'field:', props.payload.data.field)
|
|
232
225
|
})
|
|
233
226
|
}
|
|
234
227
|
|
|
@@ -271,11 +264,11 @@ const changeContent = () => {
|
|
|
271
264
|
// 判断是否删除的是}
|
|
272
265
|
if (props.payload.data.content.endsWith('}')) {
|
|
273
266
|
// 找出所有的${}
|
|
274
|
-
const matches = props.payload.data.content.match(
|
|
267
|
+
const matches = props.payload.data.content.match(defaultMatch)
|
|
275
268
|
if (matches) {
|
|
276
269
|
const index = matches.length - 1
|
|
277
270
|
// 删除数组中最后一个元素
|
|
278
|
-
props.payload.data.
|
|
271
|
+
props.payload.data.fields.splice(index, 1)
|
|
279
272
|
// 删除字符串中最后一个${}
|
|
280
273
|
text.value = props.payload.data.content.substring(0, props.payload.data.content.lastIndexOf('${'))
|
|
281
274
|
}
|
|
@@ -362,7 +355,7 @@ const deletePort = (id) => {
|
|
|
362
355
|
|
|
363
356
|
onMounted(() => {
|
|
364
357
|
getPorts()
|
|
365
|
-
|
|
358
|
+
getDevices()
|
|
366
359
|
document.addEventListener('selectionchange', () => {
|
|
367
360
|
// 判断是否在输入框内
|
|
368
361
|
if (document.activeElement.tagName === 'TEXTAREA') {
|
|
@@ -4,6 +4,8 @@ import {Snapline} from "@antv/x6-plugin-snapline";
|
|
|
4
4
|
import {Clipboard} from "@antv/x6-plugin-clipboard";
|
|
5
5
|
import {History} from "@antv/x6-plugin-history";
|
|
6
6
|
import {Selection} from "@antv/x6-plugin-selection";
|
|
7
|
+
import {lineOptions} from "packages/components/settings.js";
|
|
8
|
+
import {STOP} from "packages/components/enums.js";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* 图形变换
|
|
@@ -156,6 +158,7 @@ export const addLineTools = (cell) => {
|
|
|
156
158
|
cursor: 'move',
|
|
157
159
|
'stroke-width': 2
|
|
158
160
|
},
|
|
161
|
+
modifiers: ['shift']
|
|
159
162
|
},
|
|
160
163
|
},
|
|
161
164
|
{
|
|
@@ -187,6 +190,25 @@ export const addLineTools = (cell) => {
|
|
|
187
190
|
]);
|
|
188
191
|
}
|
|
189
192
|
|
|
193
|
+
/**
|
|
194
|
+
* 判断是直线还是管道
|
|
195
|
+
*/
|
|
196
|
+
export const isLineOrPipe = () => {
|
|
197
|
+
return lineOptions.attrs.line2.strokeDasharray === 0 ? 'line' : 'pipe'
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* 设置管道方向
|
|
202
|
+
* @param direction none无 forward-pipe正向 reverse-pipe反向
|
|
203
|
+
*/
|
|
204
|
+
export const setPipeDirection = (direction) => {
|
|
205
|
+
if (direction !== 'none') {
|
|
206
|
+
return direction + ' 30s infinite linear'
|
|
207
|
+
} else {
|
|
208
|
+
return ''
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
190
212
|
/**
|
|
191
213
|
* 设置随机数
|
|
192
214
|
* @returns {number}
|
|
@@ -194,3 +216,16 @@ export const addLineTools = (cell) => {
|
|
|
194
216
|
export const setMathRandom = () => {
|
|
195
217
|
return Math.random()
|
|
196
218
|
}
|
|
219
|
+
|
|
220
|
+
// 默认展示的字符串
|
|
221
|
+
export const defaultText = '--'
|
|
222
|
+
|
|
223
|
+
// 默认匹配字符串
|
|
224
|
+
export const defaultMatch = /\$\{(.*?)\}/g
|
|
225
|
+
|
|
226
|
+
// 默认条件单挑配置
|
|
227
|
+
export const defaultCondition = {
|
|
228
|
+
min: 0,
|
|
229
|
+
max: 0,
|
|
230
|
+
direction: STOP,
|
|
231
|
+
}
|