vue-wiring-diagram 1.0.16 → 1.0.17

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.
@@ -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
- // 获取所有节点中 data.type 为 text 的节点
114
- const textNodes = ref([])
111
+ // 节点
112
+ const cells = ref([])
113
+ // 参数
114
+ const allFields = ref([])
115
115
 
116
116
  /**
117
117
  * 刷新数据
118
118
  */
119
119
  const refreshData = () => {
120
- textNodes.value = getNodes()
121
- const regex = /\$\{(.*?)\}/g;
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
- if (!textNodes) {
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
- const realData = await getRealData(allFields.value)
158
+ let realData = await getRealData(allFields.value).catch(() => {
159
+ isAllowRefresh.value = true
160
+ })
164
161
 
165
162
  isAllowRefresh.value = true
166
163
 
167
- if (!Array.isArray(realData) || !realData.length) {
168
- return
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
- * 获取所有节点中 data.type 为 text 的节点
181
+ * 替换模板字符串
182
+ * @param str 模板字符串
183
+ * @param fields 替换数组
184
+ * @returns {*}
191
185
  */
192
- const getNodes = () => {
193
- const nodes = graph.value.getNodes()
194
- return nodes.filter(node => node.data?.type === 'text')
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 str 模板字符串
200
- * @param replacements 替换数组
201
- * @returns {*}
200
+ * 设置管道
201
+ * @param cell
202
+ * @param value
202
203
  */
203
- const replaceAllTemplateLiteralsWithArray = (str, replacements) => {
204
- let index = 0;
205
- return str.replace(/\$\{.*?\}/g, () => {
206
- if (index < replacements.length) {
207
- return replacements[index++];
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
- return '--'; // 如果替换数组长度不够,返回空字符串或其他默认值
210
- });
213
+ }
211
214
  }
212
215
 
213
216
  /**
214
217
  * \@description 画布自适应
215
218
  */
216
219
  const zoomToFit = () => {
217
- graph.value.zoomToFit({maxScale: 10, padding: 20})
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
- field: []
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
- line: {
100
- stroke: '#ffffff',
101
- strokeWidth: 1,
102
- sourceMarker: {
103
- args: {
104
- width: 10,
105
- height: 10,
106
- offset: 0,
107
- },
108
- name: null
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
- targetMarker: {
111
- args: {
112
- width: 10,
113
- height: 10,
114
- offset: 0,
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 getDeviceList = () => {
172
- get('/cny/custom/deviceList').then(res => {
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
- get('/cny/custom/monitorInfo', {
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(regexp, '--')
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(regexp)
216
+ const matches = content.match(defaultMatch)
223
217
  const index = matches?.length || 0
224
- props.payload.data.field.push({
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(regexp)
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.field.splice(index, 1)
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
- getDeviceList()
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
+ }