vue-wiring-diagram 1.1.25 → 1.1.26

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.
Files changed (32) hide show
  1. package/README.md +93 -93
  2. package/dist/style.css +1 -1
  3. package/dist/vue-wiring-diagram.es.js +4502 -4489
  4. package/dist/vue-wiring-diagram.umd.js +35 -35
  5. package/package.json +1 -1
  6. package/packages/components/Shortcuts.vue +31 -31
  7. package/packages/components/baseShape.js +62 -62
  8. package/packages/components/common.js +105 -105
  9. package/packages/components/edge-control/arrow-line.vue +292 -292
  10. package/packages/components/edge-control/condition.vue +110 -110
  11. package/packages/components/edge-control/default-line.vue +156 -156
  12. package/packages/components/edge-control/index.vue +94 -94
  13. package/packages/components/edge-control/pipe-line.vue +354 -354
  14. package/packages/components/editor/index.vue +590 -590
  15. package/packages/components/enums.js +80 -80
  16. package/packages/components/graph-control/index.vue +121 -121
  17. package/packages/components/image-control/group-form.vue +114 -114
  18. package/packages/components/image-control/image-condition.vue +117 -117
  19. package/packages/components/image-control/image-form.vue +184 -184
  20. package/packages/components/image-control/image-management.vue +213 -213
  21. package/packages/components/image-control/index.vue +290 -290
  22. package/packages/components/portsOptions.js +21 -21
  23. package/packages/components/preview/index.vue +399 -400
  24. package/packages/components/settings.js +262 -262
  25. package/packages/components/text-control/index.vue +472 -457
  26. package/packages/components/tools.js +256 -256
  27. package/packages/http.js +104 -104
  28. package/packages/index.js +43 -43
  29. package/packages/styles/animation.scss +27 -27
  30. package/packages/styles/dialog.scss +4 -4
  31. package/packages/styles/editor.scss +165 -165
  32. package/packages/styles/elPath.scss +257 -257
@@ -1,400 +1,399 @@
1
- /**
2
- * @Author: HuaYJ
3
- * @Date: 2024/12/10 10:01
4
- */
5
- <template>
6
- <div style="width: 100%; height: 100%;position: relative">
7
- <div id="preview-container" ref="previewRef" @dblclick="zoomToFit"></div>
8
- <div class="spinner" v-if="loading">
9
- <div class="spinner1"></div>
10
- </div>
11
- </div>
12
- </template>
13
-
14
- <script setup>
15
- import {onMounted, onUnmounted, ref, shallowRef} from "vue";
16
- import {Graph} from "@antv/x6";
17
- import {getData, getRealData, showPorts} from "../common.js";
18
- import {ElMessage} from "element-plus";
19
- import {defaultMatch, defaultText, setPipeDirection, setSunCloudImageUrl} from "packages/components/tools.js";
20
- import {ARROWFORWARD, FLASHING} from "packages/components/enums.js";
21
- import {arrowBackward, arrowForward, backgroundOptions, gridOptions} from "packages/components/settings.js";
22
- import {isSunOs} from "packages";
23
-
24
- defineOptions({
25
- name: 'wiring-diagram-preview'
26
- })
27
-
28
- const props = defineProps({
29
- id: {
30
- type: String,
31
- default: ''
32
- },
33
- background: {
34
- type: Object,
35
- default: () => {
36
- return {}
37
- }
38
- },
39
- grid: {
40
- type: Object,
41
- default: () => {
42
- return {}
43
- }
44
- },
45
- data: {
46
- type: Object,
47
- default: () => {
48
- return {}
49
- }
50
- }
51
- })
52
-
53
- // 画布
54
- const graph = ref()
55
-
56
- /**
57
- * 初始化画布
58
- */
59
- const initGraph = () => {
60
- window.__x6_instances__ = []
61
- const container = document.getElementById('preview-container')
62
- graph.value = new Graph({
63
- container: container,
64
- autoResize: true, // 画布自适应
65
- panning: true, // 画布可拖动
66
- mousewheel: true, // 画布可缩放
67
- connecting: {
68
- router: 'orth',
69
- connectionPoint: {
70
- name: 'anchor',
71
- },
72
- anchor: 'center',
73
- },
74
- interacting: {
75
- nodeMovable: false,
76
- magnetConnectable: false,
77
- edgeMovable: false,
78
- edgeLabelMovable: false,
79
- arrowheadMovable: false,
80
- vertexMovable: false,
81
- vertexAddable: false,
82
- vertexDeletable: false,
83
- }
84
- })
85
- window.__x6_instances__.push(container)
86
-
87
- /**
88
- * 画布空白区域双击事件
89
- */
90
- graph.value.on('blank:dblclick', () => {
91
- setFieldData()
92
- })
93
-
94
- graph.value.on('render:done', () => {
95
- showPorts("#preview-container", false)
96
- zoomToFit()
97
- })
98
- }
99
-
100
- /**
101
- * 渲染数据
102
- */
103
- const renderData = async () => {
104
- let background, grid, data;
105
- if (props.id) {
106
- const options = await getData(props.id)
107
- background = options?.background || backgroundOptions;
108
- grid = options?.grid || gridOptions;
109
- data = options?.data || {cells: []};
110
- } else {
111
- background = props.background;
112
- grid = {};
113
- data = props.data;
114
- }
115
-
116
- graph.value.drawBackground(background);
117
- graph.value.drawGrid(grid);
118
- graph.value.fromJSON(data);
119
- refreshData()
120
- }
121
-
122
- // 定时器
123
- const timer = ref(null)
124
- // 节点
125
- const cells = ref([])
126
- // 参数
127
- const allFields = ref([])
128
- // 标志位判断组件是否已销毁
129
- const isDestroyed = ref(false)
130
- // 加载中
131
- const loading = ref(false)
132
-
133
- /**
134
- * 刷新数据
135
- */
136
- const refreshData = () => {
137
- cells.value = graph.value.getCells().filter(cell => cell?.data?.type === 'text' || cell?.data?.type === 'pipe' || cell?.data?.type === 'arrow' || cell?.data?.type == 'image' )
138
- cells.value.forEach(item => {
139
- if (item?.data?.fields?.length) {
140
- allFields.value.push({id: item?.id, fields: item?.data.fields})
141
- }
142
- })
143
- setFieldData()
144
- }
145
-
146
- // 是否允许刷新数据
147
- const isAllowRefresh = ref(true)
148
-
149
- /**
150
- * 设置字段数据
151
- * @returns {Promise<void>}
152
- */
153
- const setFieldData = async () => {
154
- loading.value = true
155
- if (!allFields.value.length) {
156
- loading.value = false
157
- return
158
- }
159
-
160
- if (!isAllowRefresh.value) {
161
- ElMessage.warning('数据正在更新中,请稍后再试')
162
- return
163
- }
164
-
165
- if (timer.value) {
166
- clearInterval(timer.value)
167
- }
168
-
169
- isAllowRefresh.value = false
170
- console.log('字段数据', allFields.value)
171
- await getDataBatch(allFields.value)
172
-
173
- if (isDestroyed.value) {
174
- return
175
- }
176
-
177
- timer.value = setTimeout(() => {
178
- setFieldData()
179
- }, 10000)
180
- }
181
-
182
- /**
183
- * 分批次获取数据 每批次获取最多 10 条数据
184
- * @param fields 字段数组
185
- * @param batch
186
- */
187
- const getDataBatch = async (fields, batch = 0) => {
188
- let size = 5 // 每批次获取数量
189
- if (isDestroyed.value) {
190
- return
191
- }
192
- if (fields.length > batch * size) {
193
- const batchData = fields.slice(batch * size, batch * size + size)
194
- console.log('批次:', batch, '数据:', batchData)
195
- batch++
196
- setRealData(await getRealData(batchData))
197
- await getDataBatch(fields, batch)
198
- } else {
199
- loading.value = false
200
- isAllowRefresh.value = true
201
- }
202
- }
203
-
204
- /**
205
- * 根据不同类型设置实时数据
206
- */
207
- const setRealData = (realData) => {
208
- realData?.forEach(item => {
209
- const cell = graph.value.getCellById(item.id)
210
- if (cell.data.type === 'text') {
211
- cell.label = replaceAllTemplateLiteralsWithArray(cell.data.content, item.fields)
212
- }
213
- if (cell.data.type === 'pipe') {
214
- console.log('管道详情', cell, item.fields?.[0].value)
215
- setPipe(cell, item.fields?.[0].value)
216
- }
217
-
218
- if (cell.data.type === 'arrow') {
219
- setArrow(cell, item.fields?.[0].value)
220
- }
221
-
222
- if (cell.shape === 'image') {
223
- console.log('图片详情', cell, item.fields)
224
- setImage(cell, item.fields)
225
- }
226
- })
227
- }
228
-
229
- /**
230
- * 替换模板字符串
231
- * @param str 模板字符串
232
- * @param fields 替换数组
233
- * @returns {*}
234
- */
235
- const replaceAllTemplateLiteralsWithArray = (str, fields) => {
236
- let index = 0
237
- return str.replace(defaultMatch, () => {
238
- const field = fields.find(item => item.index === index)
239
- index++
240
- if (field) {
241
- return field.value
242
- } else {
243
- return defaultText
244
- }
245
- })
246
- }
247
-
248
- /**
249
- * 设置管道
250
- * @param cell
251
- * @param value
252
- */
253
- const setPipe = (cell, value) => {
254
- if (!cell.data.isCondition) {
255
- return false
256
- }
257
- console.log('进入设置管道阶段start:', cell)
258
- console.log('管道条件判断设置:', cell.data.condition)
259
- for (let i = 0; i < cell.data.condition.length; i++) {
260
- console.log('┌──────单个设置管道阶段start:───────┐')
261
- console.log('条件:', cell.data.condition[i])
262
- console.log('判断条件是否通过:', Number(value) > cell.data.condition[i].min && Number(value) < cell.data.condition[i].max)
263
- if (Number(value) > cell.data.condition[i].min && Number(value) < cell.data.condition[i].max) {
264
- console.log('管道条件判断设置的动画:', setPipeDirection(cell.data.condition[i].direction))
265
- cell.attr('pipe/style/animation', setPipeDirection(cell.data.condition[i].direction))
266
- console.log('设置过后的属性:', cell)
267
- console.log('└────────单个条件结束判断────────┘')
268
- return false
269
- }
270
- console.log('└─────────单个条件结束判断───────┘')
271
- }
272
- }
273
- /**
274
- * 设置箭头
275
- * @param cell
276
- * @param value
277
- */
278
- const setArrow = (cell, value) => {
279
- console.log(cell, value)
280
- if (!cell.data.isCondition) {
281
- return false
282
- }
283
- for (let i = 0; i < cell.data.condition.length; i++) {
284
- if (Number(value) > cell.data.condition[i].min && Number(value) < cell.data.condition[i].max) {
285
- cell.attr('arrow/style/animation', cell.data.condition[i].animation === FLASHING ? 'flashing 2s infinite linear' : '')
286
- cell.attr('arrow/d', cell.data.condition[i].direction === ARROWFORWARD ? arrowForward : arrowBackward)
287
- cell.attr('arrow/display', cell.data.condition[i].display)
288
- return false
289
- }
290
- }
291
- }
292
-
293
- /**
294
- * 设置图片 - 支持条件控制更换元件
295
- * @param cell 图片单元格
296
- * @param fields 设备字段数据
297
- */
298
- const setImage = (cell, fields) => {
299
- if (!cell.data.isCondition) {
300
- return false
301
- }
302
- console.log('进入设置图片阶段:', cell)
303
- console.log('图片条件判断设置:', cell.data.condition)
304
- console.log('设备字段数据:', fields)
305
-
306
- // 如果没有字段数据,直接返回
307
- if (!fields || fields.length === 0) {
308
- return false
309
- }
310
-
311
- // 获取设备值(图片目前只支持单设备)
312
- const field = fields[0]
313
- // value1 有值则使用
314
- const value = Number((field.value1 || field.value1 == 0)?field.value1:field.value )
315
-
316
- // 根据条件判断更换图片
317
- for (let i = 0; i < cell.data.condition.length; i++) {
318
- const condition = cell.data.condition[i]
319
- console.log(cell.data,'cell.data55555555');
320
- if (value > condition.min && value < condition.max) {
321
- if (condition.imageUrl) {
322
- console.log('更换图片为:', setSunCloudImageUrl(condition?.imageUrl))
323
- cell.attr('image/xlink:href', isSunOs ? condition?.imageUrl : setSunCloudImageUrl(condition?.imageUrl))
324
- }
325
- return false
326
- }
327
- }
328
-
329
- console.log('未匹配到条件,保持原图片')
330
- }
331
-
332
- /**
333
- * \@description 画布自适应
334
- */
335
- const zoomToFit = () => {
336
- graph.value.zoomToFit({maxScale: 1.4, padding: 20})
337
- }
338
-
339
- const previewRef = shallowRef()
340
-
341
- /**
342
- * 监听浏览器窗口变化
343
- */
344
- const watchBrowser = () => {
345
- const observer = new ResizeObserver(() => {
346
- zoomToFit()
347
- })
348
- observer.observe(previewRef.value)
349
- }
350
-
351
- onMounted(() => {
352
- isDestroyed.value = false
353
- initGraph()
354
- renderData()
355
- watchBrowser()
356
- })
357
-
358
-
359
- onUnmounted(() => {
360
- isDestroyed.value = true
361
- clearInterval(timer.value)
362
- })
363
- </script>
364
-
365
- <style lang="scss">
366
- @use "../../styles/animation.scss";
367
-
368
- #preview-container {
369
- position: relative;
370
- }
371
-
372
- .spinner {
373
- position: absolute;
374
- top: 10px;
375
- left: 10px;
376
- background-image: linear-gradient(rgb(186, 66, 255) 35%, rgb(0, 225, 255));
377
- width: 20px;
378
- height: 20px;
379
- animation: spinning82341 1.7s linear infinite;
380
- text-align: center;
381
- border-radius: 50px;
382
- filter: blur(1px);
383
- box-shadow: 0px -5px 50px 0px rgb(186, 66, 255), 0px 5px 50px 0px rgb(0, 225, 255);
384
- }
385
-
386
- .spinner1 {
387
- background-color: rgb(36, 36, 36);
388
- width: 20px;
389
- height: 20px;
390
- border-radius: 50px;
391
- filter: blur(4px);
392
- }
393
-
394
- @keyframes spinning82341 {
395
- to {
396
- transform: rotate(360deg);
397
- }
398
- }
399
-
400
- </style>
1
+ /**
2
+ * @Author: HuaYJ
3
+ * @Date: 2024/12/10 10:01
4
+ */
5
+ <template>
6
+ <div style="width: 100%; height: 100%;position: relative">
7
+ <div id="preview-container" ref="previewRef" @dblclick="zoomToFit"></div>
8
+ <div class="spinner" v-if="loading">
9
+ <div class="spinner1"></div>
10
+ </div>
11
+ </div>
12
+ </template>
13
+
14
+ <script setup>
15
+ import {onMounted, onUnmounted, ref, shallowRef} from "vue";
16
+ import {Graph} from "@antv/x6";
17
+ import {getData, getRealData, showPorts} from "../common.js";
18
+ import {ElMessage} from "element-plus";
19
+ import {defaultMatch, defaultText, setPipeDirection, setSunCloudImageUrl} from "packages/components/tools.js";
20
+ import {ARROWFORWARD, FLASHING} from "packages/components/enums.js";
21
+ import {arrowBackward, arrowForward, backgroundOptions, gridOptions} from "packages/components/settings.js";
22
+ import {isSunOs} from "packages";
23
+
24
+ defineOptions({
25
+ name: 'wiring-diagram-preview'
26
+ })
27
+
28
+ const props = defineProps({
29
+ id: {
30
+ type: String,
31
+ default: ''
32
+ },
33
+ background: {
34
+ type: Object,
35
+ default: () => {
36
+ return {}
37
+ }
38
+ },
39
+ grid: {
40
+ type: Object,
41
+ default: () => {
42
+ return {}
43
+ }
44
+ },
45
+ data: {
46
+ type: Object,
47
+ default: () => {
48
+ return {}
49
+ }
50
+ }
51
+ })
52
+
53
+ // 画布
54
+ const graph = ref()
55
+
56
+ /**
57
+ * 初始化画布
58
+ */
59
+ const initGraph = () => {
60
+ window.__x6_instances__ = []
61
+ const container = document.getElementById('preview-container')
62
+ graph.value = new Graph({
63
+ container: container,
64
+ autoResize: true, // 画布自适应
65
+ panning: true, // 画布可拖动
66
+ mousewheel: true, // 画布可缩放
67
+ connecting: {
68
+ router: 'orth',
69
+ connectionPoint: {
70
+ name: 'anchor',
71
+ },
72
+ anchor: 'center',
73
+ },
74
+ interacting: {
75
+ nodeMovable: false,
76
+ magnetConnectable: false,
77
+ edgeMovable: false,
78
+ edgeLabelMovable: false,
79
+ arrowheadMovable: false,
80
+ vertexMovable: false,
81
+ vertexAddable: false,
82
+ vertexDeletable: false,
83
+ }
84
+ })
85
+ window.__x6_instances__.push(container)
86
+
87
+ /**
88
+ * 画布空白区域双击事件
89
+ */
90
+ graph.value.on('blank:dblclick', () => {
91
+ setFieldData()
92
+ })
93
+
94
+ graph.value.on('render:done', () => {
95
+ showPorts("#preview-container", false)
96
+ zoomToFit()
97
+ })
98
+ }
99
+
100
+ /**
101
+ * 渲染数据
102
+ */
103
+ const renderData = async () => {
104
+ let background, grid, data;
105
+ if (props.id) {
106
+ const options = await getData(props.id)
107
+ background = options?.background || backgroundOptions;
108
+ grid = options?.grid || gridOptions;
109
+ data = options?.data || {cells: []};
110
+ } else {
111
+ background = props.background;
112
+ grid = {};
113
+ data = props.data;
114
+ }
115
+
116
+ graph.value.drawBackground(background);
117
+ graph.value.drawGrid(grid);
118
+ graph.value.fromJSON(data);
119
+ refreshData()
120
+ }
121
+
122
+ // 定时器
123
+ const timer = ref(null)
124
+ // 节点
125
+ const cells = ref([])
126
+ // 参数
127
+ const allFields = ref([])
128
+ // 标志位判断组件是否已销毁
129
+ const isDestroyed = ref(false)
130
+ // 加载中
131
+ const loading = ref(false)
132
+
133
+ /**
134
+ * 刷新数据
135
+ */
136
+ const refreshData = () => {
137
+ cells.value = graph.value.getCells().filter(cell => cell?.data?.type === 'text' || cell?.data?.type === 'pipe' || cell?.data?.type === 'arrow' || cell?.data?.type == 'image' )
138
+ cells.value.forEach(item => {
139
+ if (item?.data?.fields?.length) {
140
+ allFields.value.push({id: item?.id, fields: item?.data.fields})
141
+ }
142
+ })
143
+ setFieldData()
144
+ }
145
+
146
+ // 是否允许刷新数据
147
+ const isAllowRefresh = ref(true)
148
+
149
+ /**
150
+ * 设置字段数据
151
+ * @returns {Promise<void>}
152
+ */
153
+ const setFieldData = async () => {
154
+ loading.value = true
155
+ if (!allFields.value.length) {
156
+ loading.value = false
157
+ return
158
+ }
159
+
160
+ if (!isAllowRefresh.value) {
161
+ ElMessage.warning('数据正在更新中,请稍后再试')
162
+ return
163
+ }
164
+
165
+ if (timer.value) {
166
+ clearInterval(timer.value)
167
+ }
168
+
169
+ isAllowRefresh.value = false
170
+ console.log('字段数据', allFields.value)
171
+ await getDataBatch(allFields.value)
172
+
173
+ if (isDestroyed.value) {
174
+ return
175
+ }
176
+
177
+ timer.value = setTimeout(() => {
178
+ setFieldData()
179
+ }, 10000)
180
+ }
181
+
182
+ /**
183
+ * 分批次获取数据 每批次获取最多 10 条数据
184
+ * @param fields 字段数组
185
+ * @param batch
186
+ */
187
+ const getDataBatch = async (fields, batch = 0) => {
188
+ let size = 5 // 每批次获取数量
189
+ if (isDestroyed.value) {
190
+ return
191
+ }
192
+ if (fields.length > batch * size) {
193
+ const batchData = fields.slice(batch * size, batch * size + size)
194
+ console.log('批次:', batch, '数据:', batchData)
195
+ batch++
196
+ setRealData(await getRealData(batchData))
197
+ await getDataBatch(fields, batch)
198
+ } else {
199
+ loading.value = false
200
+ isAllowRefresh.value = true
201
+ }
202
+ }
203
+
204
+ /**
205
+ * 根据不同类型设置实时数据
206
+ */
207
+ const setRealData = (realData) => {
208
+ realData?.forEach(item => {
209
+ const cell = graph.value.getCellById(item.id)
210
+ if (cell.data.type === 'text') {
211
+ cell.label = replaceAllTemplateLiteralsWithArray(cell.data.content, item.fields)
212
+ }
213
+ if (cell.data.type === 'pipe') {
214
+ console.log('管道详情', cell, item.fields?.[0].value)
215
+ setPipe(cell, item.fields?.[0].value)
216
+ }
217
+
218
+ if (cell.data.type === 'arrow') {
219
+ setArrow(cell, item.fields?.[0].value)
220
+ }
221
+
222
+ if (cell.shape === 'image') {
223
+ console.log('图片详情', cell, item.fields)
224
+ setImage(cell, item.fields)
225
+ }
226
+ })
227
+ }
228
+
229
+ /**
230
+ * 替换模板字符串
231
+ * @param str 模板字符串
232
+ * @param fields 替换数组
233
+ * @returns {*}
234
+ */
235
+ const replaceAllTemplateLiteralsWithArray = (str, fields) => {
236
+ let index = 0
237
+ return str.replace(defaultMatch, () => {
238
+ const field = fields.find(item => item.index === index)
239
+ index++
240
+ if (field) {
241
+ return field.value
242
+ } else {
243
+ return defaultText
244
+ }
245
+ })
246
+ }
247
+
248
+ /**
249
+ * 设置管道
250
+ * @param cell
251
+ * @param value
252
+ */
253
+ const setPipe = (cell, value) => {
254
+ if (!cell.data.isCondition) {
255
+ return false
256
+ }
257
+ console.log('进入设置管道阶段start:', cell)
258
+ console.log('管道条件判断设置:', cell.data.condition)
259
+ for (let i = 0; i < cell.data.condition.length; i++) {
260
+ console.log('┌──────单个设置管道阶段start:───────┐')
261
+ console.log('条件:', cell.data.condition[i])
262
+ console.log('判断条件是否通过:', Number(value) > cell.data.condition[i].min && Number(value) < cell.data.condition[i].max)
263
+ if (Number(value) > cell.data.condition[i].min && Number(value) < cell.data.condition[i].max) {
264
+ console.log('管道条件判断设置的动画:', setPipeDirection(cell.data.condition[i].direction))
265
+ cell.attr('pipe/style/animation', setPipeDirection(cell.data.condition[i].direction))
266
+ console.log('设置过后的属性:', cell)
267
+ console.log('└────────单个条件结束判断────────┘')
268
+ return false
269
+ }
270
+ console.log('└─────────单个条件结束判断───────┘')
271
+ }
272
+ }
273
+ /**
274
+ * 设置箭头
275
+ * @param cell
276
+ * @param value
277
+ */
278
+ const setArrow = (cell, value) => {
279
+ console.log(cell, value)
280
+ if (!cell.data.isCondition) {
281
+ return false
282
+ }
283
+ for (let i = 0; i < cell.data.condition.length; i++) {
284
+ if (Number(value) > cell.data.condition[i].min && Number(value) < cell.data.condition[i].max) {
285
+ cell.attr('arrow/style/animation', cell.data.condition[i].animation === FLASHING ? 'flashing 2s infinite linear' : '')
286
+ cell.attr('arrow/d', cell.data.condition[i].direction === ARROWFORWARD ? arrowForward : arrowBackward)
287
+ cell.attr('arrow/display', cell.data.condition[i].display)
288
+ return false
289
+ }
290
+ }
291
+ }
292
+
293
+ /**
294
+ * 设置图片 - 支持条件控制更换元件
295
+ * @param cell 图片单元格
296
+ * @param fields 设备字段数据
297
+ */
298
+ const setImage = (cell, fields) => {
299
+ if (!cell.data.isCondition) {
300
+ return false
301
+ }
302
+ console.log('进入设置图片阶段:', cell)
303
+ console.log('图片条件判断设置:', cell.data.condition)
304
+ console.log('设备字段数据:', fields)
305
+
306
+ // 如果没有字段数据,直接返回
307
+ if (!fields || fields.length === 0) {
308
+ return false
309
+ }
310
+
311
+ // 获取设备值(图片目前只支持单设备)
312
+ const field = fields[0]
313
+ const value = Number(field.value)
314
+
315
+ // 根据条件判断更换图片
316
+ for (let i = 0; i < cell.data.condition.length; i++) {
317
+ const condition = cell.data.condition[i]
318
+ console.log(cell.data,'cell.data55555555');
319
+ if (value > condition.min && value < condition.max) {
320
+ if (condition.imageUrl) {
321
+ console.log('更换图片为:', setSunCloudImageUrl(condition?.imageUrl))
322
+ cell.attr('image/xlink:href', isSunOs ? condition?.imageUrl : setSunCloudImageUrl(condition?.imageUrl))
323
+ }
324
+ return false
325
+ }
326
+ }
327
+
328
+ console.log('未匹配到条件,保持原图片')
329
+ }
330
+
331
+ /**
332
+ * \@description 画布自适应
333
+ */
334
+ const zoomToFit = () => {
335
+ graph.value.zoomToFit({maxScale: 1.4, padding: 20})
336
+ }
337
+
338
+ const previewRef = shallowRef()
339
+
340
+ /**
341
+ * 监听浏览器窗口变化
342
+ */
343
+ const watchBrowser = () => {
344
+ const observer = new ResizeObserver(() => {
345
+ zoomToFit()
346
+ })
347
+ observer.observe(previewRef.value)
348
+ }
349
+
350
+ onMounted(() => {
351
+ isDestroyed.value = false
352
+ initGraph()
353
+ renderData()
354
+ watchBrowser()
355
+ })
356
+
357
+
358
+ onUnmounted(() => {
359
+ isDestroyed.value = true
360
+ clearInterval(timer.value)
361
+ })
362
+ </script>
363
+
364
+ <style lang="scss">
365
+ @use "../../styles/animation.scss";
366
+
367
+ #preview-container {
368
+ position: relative;
369
+ }
370
+
371
+ .spinner {
372
+ position: absolute;
373
+ top: 10px;
374
+ left: 10px;
375
+ background-image: linear-gradient(rgb(186, 66, 255) 35%, rgb(0, 225, 255));
376
+ width: 20px;
377
+ height: 20px;
378
+ animation: spinning82341 1.7s linear infinite;
379
+ text-align: center;
380
+ border-radius: 50px;
381
+ filter: blur(1px);
382
+ box-shadow: 0px -5px 50px 0px rgb(186, 66, 255), 0px 5px 50px 0px rgb(0, 225, 255);
383
+ }
384
+
385
+ .spinner1 {
386
+ background-color: rgb(36, 36, 36);
387
+ width: 20px;
388
+ height: 20px;
389
+ border-radius: 50px;
390
+ filter: blur(4px);
391
+ }
392
+
393
+ @keyframes spinning82341 {
394
+ to {
395
+ transform: rotate(360deg);
396
+ }
397
+ }
398
+
399
+ </style>