vue3-wiring-diagram 1.0.1

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 (62) hide show
  1. package/README.md +1727 -0
  2. package/README.zh-CN.md +387 -0
  3. package/dist/style.css +1 -0
  4. package/dist/vue3-wiring-diagram.es.js +34397 -0
  5. package/dist/vue3-wiring-diagram.umd.js +720 -0
  6. package/docs/API.md +482 -0
  7. package/docs/API.zh-CN.md +480 -0
  8. package/package.json +67 -0
  9. package/packages/api/client.js +14 -0
  10. package/packages/api/custom.js +45 -0
  11. package/packages/api/template.js +33 -0
  12. package/packages/api/upload.js +26 -0
  13. package/packages/assets/icons/adaptive.svg +1 -0
  14. package/packages/assets/icons/clear.svg +1 -0
  15. package/packages/assets/icons/dashed.svg +1 -0
  16. package/packages/assets/icons/line.svg +1 -0
  17. package/packages/assets/icons/preview.svg +1 -0
  18. package/packages/assets/icons/redo.svg +1 -0
  19. package/packages/assets/icons/save.svg +1 -0
  20. package/packages/assets/icons/shortcuts.svg +1 -0
  21. package/packages/assets/icons/undo.svg +1 -0
  22. package/packages/assets/image/background.png +0 -0
  23. package/packages/components/Shortcuts.vue +34 -0
  24. package/packages/components/baseShape.js +62 -0
  25. package/packages/components/common.js +177 -0
  26. package/packages/components/edge-adapter.js +10 -0
  27. package/packages/components/edge-animation.js +233 -0
  28. package/packages/components/edge-control/condition.vue +336 -0
  29. package/packages/components/edge-control/index.vue +26 -0
  30. package/packages/components/edge-control/pipe-line.vue +784 -0
  31. package/packages/components/editor/index.vue +1459 -0
  32. package/packages/components/enums.js +80 -0
  33. package/packages/components/graph-control/index.vue +173 -0
  34. package/packages/components/image-control/group-form.vue +116 -0
  35. package/packages/components/image-control/image-condition.vue +118 -0
  36. package/packages/components/image-control/image-form.vue +178 -0
  37. package/packages/components/image-control/image-management.vue +224 -0
  38. package/packages/components/image-control/index.vue +370 -0
  39. package/packages/components/index.js +18 -0
  40. package/packages/components/portsOptions.js +21 -0
  41. package/packages/components/preview/index.vue +563 -0
  42. package/packages/components/settings.js +285 -0
  43. package/packages/components/text-control/index.vue +640 -0
  44. package/packages/components/tools.js +348 -0
  45. package/packages/config/defaults.js +30 -0
  46. package/packages/config/index.js +86 -0
  47. package/packages/core/events.js +48 -0
  48. package/packages/core/runtime.js +24 -0
  49. package/packages/core/schema.js +87 -0
  50. package/packages/core/validators.js +83 -0
  51. package/packages/core/x6-adapter.js +156 -0
  52. package/packages/http.js +191 -0
  53. package/packages/i18n/index.js +664 -0
  54. package/packages/index.js +54 -0
  55. package/packages/presets/edges.js +98 -0
  56. package/packages/presets/nodes.js +44 -0
  57. package/packages/shapes/registry.js +55 -0
  58. package/packages/styles/animation.scss +85 -0
  59. package/packages/styles/dialog.scss +57 -0
  60. package/packages/styles/editor.scss +567 -0
  61. package/packages/styles/elPath.scss +372 -0
  62. package/packages/styles/messageBox.scss +122 -0
package/README.md ADDED
@@ -0,0 +1,1727 @@
1
+ <h1 align="center">vue3-wiring-diagram</h1>
2
+
3
+ Vue 3 wiring diagram components based on X6 and Element Plus.
4
+
5
+ [中文文档](#中文文档) | [API Specification](#api-specification) | [中文接口规范](#接口规范)
6
+
7
+ ## Features
8
+
9
+ - Editor, preview, and automatic generation components.
10
+ - Built-in `zh-CN` and `en-US` text.
11
+ - Shared API configuration for `baseURL`, `token`, custom headers, timeout, and image asset prefix.
12
+ - Component `locale` controls both UI text and the `Accept-Language` request header.
13
+ - Element Plus is provided by the host application, so existing host themes can keep taking effect.
14
+
15
+ ## Requirements
16
+
17
+ The host application must use Vue 3 and install Element Plus:
18
+
19
+ ```bash
20
+ npm install vue element-plus @element-plus/icons-vue
21
+ ```
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ npm install vue3-wiring-diagram
27
+ ```
28
+
29
+ ## Basic Host Setup
30
+
31
+ Register Element Plus in the host application first. Then import the plugin style.
32
+
33
+ ```js
34
+ import {createApp} from 'vue'
35
+ import ElementPlus from 'element-plus'
36
+ import 'element-plus/dist/index.css'
37
+ import '@/styles/index.scss'
38
+
39
+ import 'vue3-wiring-diagram/style.css'
40
+ import App from './App.vue'
41
+
42
+ const app = createApp(App)
43
+
44
+ app.use(ElementPlus)
45
+ app.mount('#app')
46
+ ```
47
+
48
+ If your host project uses Vite, dedupe Vue and Element Plus to avoid loading two Vue runtimes:
49
+
50
+ ```js
51
+ // vite.config.js
52
+ export default {
53
+ resolve: {
54
+ dedupe: ['vue', 'element-plus', '@element-plus/icons-vue']
55
+ }
56
+ }
57
+ ```
58
+
59
+ ## Request Configuration
60
+
61
+ Call `configure` before rendering components. `headers` is optional and only needed when your backend requires extra headers, such as tenant id, app id, or custom auth fields. If your backend does not need them, omit `headers`.
62
+
63
+ ```js
64
+ import {
65
+ configure,
66
+ setAssetBaseURL,
67
+ setBaseURL,
68
+ setToken
69
+ } from 'vue3-wiring-diagram'
70
+
71
+ configure({
72
+ baseURL: '/api/cny',
73
+ assetBaseURL: '/api',
74
+ token: 'token',
75
+ timeout: 10000
76
+ })
77
+
78
+ setBaseURL('/api/cny')
79
+ setAssetBaseURL('/api')
80
+ setToken('token')
81
+ ```
82
+
83
+ Optional custom headers:
84
+
85
+ ```js
86
+ configure({
87
+ baseURL: '/api/cny',
88
+ token: 'token',
89
+ headers: {
90
+ 'X-Tenant-Id': 'tenant-id'
91
+ }
92
+ })
93
+ ```
94
+
95
+ Image path example:
96
+
97
+ - API base URL: `/api/cny`
98
+ - Backend image path: `/cny/upload/a.png`
99
+ - Expected browser image URL: `/api/cny/upload/a.png`
100
+
101
+ Use:
102
+
103
+ ```js
104
+ configure({
105
+ baseURL: '/api/cny',
106
+ assetBaseURL: '/api',
107
+ token: 'token'
108
+ })
109
+ ```
110
+
111
+ ## Global Registration
112
+
113
+ Register all public components globally:
114
+
115
+ ```js
116
+ import {createApp} from 'vue'
117
+ import ElementPlus from 'element-plus'
118
+ import vueWiringDiagram, {configure} from 'vue3-wiring-diagram'
119
+ import 'element-plus/dist/index.css'
120
+ import 'vue3-wiring-diagram/style.css'
121
+ import App from './App.vue'
122
+
123
+ configure({
124
+ baseURL: '/api/cny',
125
+ assetBaseURL: '/api',
126
+ token: 'token'
127
+ })
128
+
129
+ const app = createApp(App)
130
+
131
+ app.use(ElementPlus)
132
+ app.use(vueWiringDiagram)
133
+ app.mount('#app')
134
+ ```
135
+
136
+ Then use component tags directly:
137
+
138
+ ```vue
139
+ <wiring-diagram-editor :id="id" :item-id="itemId" locale="zh-CN" />
140
+ <wiring-diagram-preview :id="id" locale="en-US" />
141
+ ```
142
+
143
+ ## On-Demand Import
144
+
145
+ Import only the components needed by a page:
146
+
147
+ ```js
148
+ import {
149
+ WiringDiagramEditor,
150
+ WiringDiagramPreview,
151
+ configure
152
+ } from 'vue3-wiring-diagram'
153
+ import 'vue3-wiring-diagram/style.css'
154
+ ```
155
+
156
+ Short aliases are also exported:
157
+
158
+ ```js
159
+ import {Editor, Preview} from 'vue3-wiring-diagram'
160
+ ```
161
+
162
+ ## Editor
163
+
164
+ The editor loads an existing diagram by `id`, uses `itemId` to load device-related data, and emits diagram JSON through `getJson`.
165
+
166
+ Props:
167
+
168
+ | Prop | Type | Default | Description |
169
+ | --- | --- | --- | --- |
170
+ | `id` | `string` | `''` | Template id. When empty, the editor starts with a blank diagram. |
171
+ | `itemId` | `string` | `''` | Project/item id used by device list APIs. |
172
+ | `locale` | `'zh-CN' \| 'en-US'` | `'zh-CN'` | UI language and request `Accept-Language`. |
173
+
174
+ Events:
175
+
176
+ | Event | Payload |
177
+ | --- | --- |
178
+ | `getJson` | `{ background, grid, data }` |
179
+
180
+ On-demand example:
181
+
182
+ ```vue
183
+ <template>
184
+ <div class="wiring-page">
185
+ <WiringDiagramEditor
186
+ :id="id"
187
+ :item-id="itemId"
188
+ locale="zh-CN"
189
+ @getJson="handleSave"
190
+ />
191
+ </div>
192
+ </template>
193
+
194
+ <script setup>
195
+ import {ref, onMounted} from 'vue'
196
+ import {WiringDiagramEditor, configure, updateData} from 'vue3-wiring-diagram'
197
+ import 'vue3-wiring-diagram/style.css'
198
+
199
+ const id = ref('195')
200
+ const itemId = ref('1115')
201
+
202
+ onMounted(() => {
203
+ configure({
204
+ baseURL: '/api/cny',
205
+ assetBaseURL: '/api',
206
+ token: 'token'
207
+ })
208
+ })
209
+
210
+ const handleSave = (diagram) => {
211
+ updateData(id.value, diagram)
212
+ }
213
+ </script>
214
+
215
+ <style scoped>
216
+ .wiring-page {
217
+ width: 100%;
218
+ height: 100%;
219
+ }
220
+ </style>
221
+ ```
222
+
223
+ Global component example:
224
+
225
+ ```vue
226
+ <wiring-diagram-editor
227
+ :id="id"
228
+ :item-id="itemId"
229
+ locale="zh-CN"
230
+ @getJson="handleSave"
231
+ />
232
+ ```
233
+
234
+ ## Preview
235
+
236
+ The preview component can load data by `id`, or render diagram data passed from the page.
237
+
238
+ Props:
239
+
240
+ | Prop | Type | Default | Description |
241
+ | --- | --- | --- | --- |
242
+ | `id` | `string` | `''` | Template id. When provided, preview loads diagram data through the configured API. |
243
+ | `background` | `object` | `{}` | Diagram background config used when `id` is empty. |
244
+ | `grid` | `object` | `{}` | Diagram grid config used when `id` is empty. |
245
+ | `data` | `object` | `{}` | Diagram JSON used when `id` is empty. |
246
+ | `type` | `string \| null` | `null` | Internal display type for nested preview. |
247
+ | `locale` | `'zh-CN' \| 'en-US'` | `'zh-CN'` | UI language and request `Accept-Language`. |
248
+
249
+ Events:
250
+
251
+ | Event | Payload |
252
+ | --- | --- |
253
+ | `close` | none |
254
+
255
+ Preview by template id:
256
+
257
+ ```vue
258
+ <template>
259
+ <div class="wiring-page">
260
+ <WiringDiagramPreview :id="id" locale="en-US" />
261
+ </div>
262
+ </template>
263
+
264
+ <script setup>
265
+ import {ref, onMounted} from 'vue'
266
+ import {WiringDiagramPreview, configure} from 'vue3-wiring-diagram'
267
+ import 'vue3-wiring-diagram/style.css'
268
+
269
+ const id = ref('195')
270
+
271
+ onMounted(() => {
272
+ configure({
273
+ baseURL: '/api/cny',
274
+ assetBaseURL: '/api',
275
+ token: 'token'
276
+ })
277
+ })
278
+ </script>
279
+ ```
280
+
281
+ Preview by existing diagram JSON:
282
+
283
+ ```vue
284
+ <template>
285
+ <WiringDiagramPreview
286
+ :background="diagram.background"
287
+ :grid="diagram.grid"
288
+ :data="diagram.data"
289
+ locale="zh-CN"
290
+ />
291
+ </template>
292
+
293
+ <script setup>
294
+ import {ref} from 'vue'
295
+ import {WiringDiagramPreview} from 'vue3-wiring-diagram'
296
+ import 'vue3-wiring-diagram/style.css'
297
+
298
+ const diagram = ref({
299
+ background: {},
300
+ grid: {},
301
+ data: {cells: []}
302
+ })
303
+ </script>
304
+ ```
305
+
306
+ ## Public Exports
307
+
308
+ ```js
309
+ import {
310
+ Editor,
311
+ Preview,
312
+ WiringDiagramEditor,
313
+ WiringDiagramPreview,
314
+ configure,
315
+ setBaseURL,
316
+ setAssetBaseURL,
317
+ setToken,
318
+ getData,
319
+ updateData
320
+ } from 'vue3-wiring-diagram'
321
+ ```
322
+
323
+ ## Locale
324
+
325
+ Use `locale` to switch built-in text. It also updates the request `Accept-Language` header for component requests:
326
+
327
+ ```vue
328
+ <wiring-diagram-editor locale="zh-CN" />
329
+ <wiring-diagram-editor locale="en-US" />
330
+ ```
331
+
332
+ Default locale is `zh-CN`.
333
+
334
+ ## Theme
335
+
336
+ The plugin exposes CSS variables. Override them in the host page when needed:
337
+
338
+ ```css
339
+ .wiring-page {
340
+ --wiring-bg: rgb(9 23 87 / 0.6);
341
+ --wiring-panel-bg: rgb(9 23 87 / 0.6);
342
+ --wiring-text-color: #ffffff;
343
+ --wiring-muted-text-color: #ffffff;
344
+ --wiring-border-color: rgb(9 23 87 / 0.6);
345
+ --wiring-primary-color: #2563eb;
346
+ --wiring-primary-soft-color: #2364dd4d;
347
+ }
348
+ ```
349
+
350
+ ## Avoid Duplicate Vue
351
+
352
+ Do not import from the source folder in the host application:
353
+
354
+ ```js
355
+ // Do not do this
356
+ import {WiringDiagramEditor} from '../../wiring-diagram/packages/index.js'
357
+ ```
358
+
359
+ Always import from the package name:
360
+
361
+ ```js
362
+ import {WiringDiagramEditor} from 'vue3-wiring-diagram'
363
+ ```
364
+
365
+ If you see an error like `Cannot read properties of null (reading 'ce')` and the stack points to another package's `node_modules/@vue/runtime-core`, the host is loading two Vue runtimes. Clear the host cache and reinstall:
366
+
367
+ ```bash
368
+ rm -rf node_modules/.vite node_modules/.cache node_modules/vue3-wiring-diagram
369
+ npm install vue3-wiring-diagram
370
+ ```
371
+
372
+ ---
373
+
374
+ <a id="中文文档"></a>
375
+
376
+ # 中文文档
377
+
378
+ 基于 Vue 3、X6、Element Plus 的接线图组件库。
379
+
380
+ [English](#vue3-wiring-diagram) | [API Specification](#api-specification) | [接口规范](#接口规范)
381
+
382
+ ## 功能
383
+
384
+ - 提供编辑器和预览两个核心组件。
385
+ - 内置中文和英文,支持 `zh-CN`、`en-US`。
386
+ - 统一配置接口地址、token、自定义请求头、超时时间和图片资源前缀。
387
+ - 组件 `locale` 同时控制界面文案和请求头 `Accept-Language`。
388
+ - Element Plus 由宿主项目提供,宿主项目已有的 Element Plus 主题样式可以继续生效。
389
+
390
+ ## 环境要求
391
+
392
+ 宿主项目需要使用 Vue 3,并安装 Element Plus:
393
+
394
+ ```bash
395
+ npm install vue element-plus @element-plus/icons-vue
396
+ ```
397
+
398
+ ## 安装
399
+
400
+ ```bash
401
+ npm install vue3-wiring-diagram
402
+ ```
403
+
404
+ ## 宿主项目基础配置
405
+
406
+ 宿主项目先注册 Element Plus,再引入插件样式。
407
+
408
+ ```js
409
+ import {createApp} from 'vue'
410
+ import ElementPlus from 'element-plus'
411
+ import 'element-plus/dist/index.css'
412
+ import '@/styles/index.scss'
413
+
414
+ import 'vue3-wiring-diagram/style.css'
415
+ import App from './App.vue'
416
+
417
+ const app = createApp(App)
418
+
419
+ app.use(ElementPlus)
420
+ app.mount('#app')
421
+ ```
422
+
423
+ 如果宿主项目是 Vite,建议加上 `dedupe`,避免加载两份 Vue:
424
+
425
+ ```js
426
+ // vite.config.js
427
+ export default {
428
+ resolve: {
429
+ dedupe: ['vue', 'element-plus', '@element-plus/icons-vue']
430
+ }
431
+ }
432
+ ```
433
+
434
+ ## 请求配置
435
+
436
+ 组件渲染前调用 `configure`。`headers` 是可选项,只在后端需要额外请求头时使用,例如租户 id、应用 id 或自定义鉴权字段。如果后端不需要,可以不传。
437
+
438
+ ```js
439
+ import {
440
+ configure,
441
+ setAssetBaseURL,
442
+ setBaseURL,
443
+ setToken
444
+ } from 'vue3-wiring-diagram'
445
+
446
+ configure({
447
+ baseURL: '/api/cny',
448
+ assetBaseURL: '/api',
449
+ token: 'token',
450
+ timeout: 10000
451
+ })
452
+
453
+ setBaseURL('/api/cny')
454
+ setAssetBaseURL('/api')
455
+ setToken('token')
456
+ ```
457
+
458
+ 可选自定义请求头:
459
+
460
+ ```js
461
+ configure({
462
+ baseURL: '/api/cny',
463
+ token: 'token',
464
+ headers: {
465
+ 'X-Tenant-Id': 'tenant-id'
466
+ }
467
+ })
468
+ ```
469
+
470
+ 图片路径示例:
471
+
472
+ - 接口地址前缀:`/api/cny`
473
+ - 后端返回图片路径:`/cny/upload/a.png`
474
+ - 浏览器实际图片请求:`/api/cny/upload/a.png`
475
+
476
+ 配置方式:
477
+
478
+ ```js
479
+ configure({
480
+ baseURL: '/api/cny',
481
+ assetBaseURL: '/api',
482
+ token: 'token'
483
+ })
484
+ ```
485
+
486
+ ## 全局引入
487
+
488
+ 一次性注册所有公开组件:
489
+
490
+ ```js
491
+ import {createApp} from 'vue'
492
+ import ElementPlus from 'element-plus'
493
+ import vueWiringDiagram, {configure} from 'vue3-wiring-diagram'
494
+ import 'element-plus/dist/index.css'
495
+ import 'vue3-wiring-diagram/style.css'
496
+ import App from './App.vue'
497
+
498
+ configure({
499
+ baseURL: '/api/cny',
500
+ assetBaseURL: '/api',
501
+ token: 'token'
502
+ })
503
+
504
+ const app = createApp(App)
505
+
506
+ app.use(ElementPlus)
507
+ app.use(vueWiringDiagram)
508
+ app.mount('#app')
509
+ ```
510
+
511
+ 注册后可以直接使用组件标签:
512
+
513
+ ```vue
514
+ <wiring-diagram-editor :id="id" :item-id="itemId" locale="zh-CN" />
515
+ <wiring-diagram-preview :id="id" locale="en-US" />
516
+ ```
517
+
518
+ ## 按需引入
519
+
520
+ 页面里只引入需要的组件:
521
+
522
+ ```js
523
+ import {
524
+ WiringDiagramEditor,
525
+ WiringDiagramPreview,
526
+ configure
527
+ } from 'vue3-wiring-diagram'
528
+ import 'vue3-wiring-diagram/style.css'
529
+ ```
530
+
531
+ 也提供短别名:
532
+
533
+ ```js
534
+ import {Editor, Preview} from 'vue3-wiring-diagram'
535
+ ```
536
+
537
+ ## 编辑器
538
+
539
+ 编辑器可通过 `id` 加载已有图纸,通过 `itemId` 加载设备相关数据,并通过 `getJson` 事件返回图纸 JSON。
540
+
541
+ Props:
542
+
543
+ | 属性 | 类型 | 默认值 | 说明 |
544
+ | --- | --- | --- | --- |
545
+ | `id` | `string` | `''` | 模板 id。为空时打开空白画布。 |
546
+ | `itemId` | `string` | `''` | 项目/站点 id,用于设备列表等接口。 |
547
+ | `locale` | `'zh-CN' \| 'en-US'` | `'zh-CN'` | 组件语言,同时同步请求头 `Accept-Language`。 |
548
+
549
+ 事件:
550
+
551
+ | 事件 | 参数 |
552
+ | --- | --- |
553
+ | `getJson` | `{ background, grid, data }` |
554
+
555
+ 按需引入示例:
556
+
557
+ ```vue
558
+ <template>
559
+ <div class="wiring-page">
560
+ <WiringDiagramEditor
561
+ :id="id"
562
+ :item-id="itemId"
563
+ locale="zh-CN"
564
+ @getJson="handleSave"
565
+ />
566
+ </div>
567
+ </template>
568
+
569
+ <script setup>
570
+ import {ref, onMounted} from 'vue'
571
+ import {WiringDiagramEditor, configure, updateData} from 'vue3-wiring-diagram'
572
+ import 'vue3-wiring-diagram/style.css'
573
+
574
+ const id = ref('195')
575
+ const itemId = ref('1115')
576
+
577
+ onMounted(() => {
578
+ configure({
579
+ baseURL: '/api/cny',
580
+ assetBaseURL: '/api',
581
+ token: 'token'
582
+ })
583
+ })
584
+
585
+ const handleSave = (diagram) => {
586
+ updateData(id.value, diagram)
587
+ }
588
+ </script>
589
+
590
+ <style scoped>
591
+ .wiring-page {
592
+ width: 100%;
593
+ height: 100%;
594
+ }
595
+ </style>
596
+ ```
597
+
598
+ 全局组件示例:
599
+
600
+ ```vue
601
+ <wiring-diagram-editor
602
+ :id="id"
603
+ :item-id="itemId"
604
+ locale="zh-CN"
605
+ @getJson="handleSave"
606
+ />
607
+ ```
608
+
609
+ ## 预览
610
+
611
+ 预览组件可以通过 `id` 加载数据,也可以直接渲染页面传入的图纸 JSON。
612
+
613
+ Props:
614
+
615
+ | 属性 | 类型 | 默认值 | 说明 |
616
+ | --- | --- | --- | --- |
617
+ | `id` | `string` | `''` | 模板 id。传入后会通过配置的接口加载图纸数据。 |
618
+ | `background` | `object` | `{}` | `id` 为空时使用的画布背景配置。 |
619
+ | `grid` | `object` | `{}` | `id` 为空时使用的网格配置。 |
620
+ | `data` | `object` | `{}` | `id` 为空时使用的图纸 JSON。 |
621
+ | `type` | `string \| null` | `null` | 内部多层预览标识。 |
622
+ | `locale` | `'zh-CN' \| 'en-US'` | `'zh-CN'` | 组件语言,同时同步请求头 `Accept-Language`。 |
623
+
624
+ 事件:
625
+
626
+ | 事件 | 参数 |
627
+ | --- | --- |
628
+ | `close` | 无 |
629
+
630
+ 通过模板 id 预览:
631
+
632
+ ```vue
633
+ <template>
634
+ <div class="wiring-page">
635
+ <WiringDiagramPreview :id="id" locale="en-US" />
636
+ </div>
637
+ </template>
638
+
639
+ <script setup>
640
+ import {ref, onMounted} from 'vue'
641
+ import {WiringDiagramPreview, configure} from 'vue3-wiring-diagram'
642
+ import 'vue3-wiring-diagram/style.css'
643
+
644
+ const id = ref('195')
645
+
646
+ onMounted(() => {
647
+ configure({
648
+ baseURL: '/api/cny',
649
+ assetBaseURL: '/api',
650
+ token: 'token'
651
+ })
652
+ })
653
+ </script>
654
+ ```
655
+
656
+ 通过已有图纸 JSON 预览:
657
+
658
+ ```vue
659
+ <template>
660
+ <WiringDiagramPreview
661
+ :background="diagram.background"
662
+ :grid="diagram.grid"
663
+ :data="diagram.data"
664
+ locale="zh-CN"
665
+ />
666
+ </template>
667
+
668
+ <script setup>
669
+ import {ref} from 'vue'
670
+ import {WiringDiagramPreview} from 'vue3-wiring-diagram'
671
+ import 'vue3-wiring-diagram/style.css'
672
+
673
+ const diagram = ref({
674
+ background: {},
675
+ grid: {},
676
+ data: {cells: []}
677
+ })
678
+ </script>
679
+ ```
680
+
681
+ ## 公开导出
682
+
683
+ ```js
684
+ import {
685
+ Editor,
686
+ Preview,
687
+ WiringDiagramEditor,
688
+ WiringDiagramPreview,
689
+ configure,
690
+ setBaseURL,
691
+ setAssetBaseURL,
692
+ setToken,
693
+ getData,
694
+ updateData
695
+ } from 'vue3-wiring-diagram'
696
+ ```
697
+
698
+ ## 中英文
699
+
700
+ 通过 `locale` 切换组件内置文本,同时会同步组件请求头里的 `Accept-Language`:
701
+
702
+ ```vue
703
+ <wiring-diagram-editor locale="zh-CN" />
704
+ <wiring-diagram-editor locale="en-US" />
705
+ ```
706
+
707
+ 默认是 `zh-CN`。
708
+
709
+ ## 样式
710
+
711
+ 插件暴露 CSS 变量,宿主页面可以按需覆盖:
712
+
713
+ ```css
714
+ .wiring-page {
715
+ --wiring-bg: rgb(9 23 87 / 0.6);
716
+ --wiring-panel-bg: rgb(9 23 87 / 0.6);
717
+ --wiring-text-color: #ffffff;
718
+ --wiring-muted-text-color: #ffffff;
719
+ --wiring-border-color: rgb(9 23 87 / 0.6);
720
+ --wiring-primary-color: #2563eb;
721
+ --wiring-primary-soft-color: #2364dd4d;
722
+ }
723
+ ```
724
+
725
+ 如果宿主项目已有 Element Plus 全局样式,可以继续保留。插件样式只处理接线图内部布局和少量必要样式。
726
+
727
+ ## 避免重复 Vue
728
+
729
+ 宿主项目不要直接从插件源码目录引入:
730
+
731
+ ```js
732
+ // 不要这样写
733
+ import {WiringDiagramEditor} from '../../wiring-diagram/packages/index.js'
734
+ ```
735
+
736
+ 应该从包名引入:
737
+
738
+ ```js
739
+ import {WiringDiagramEditor} from 'vue3-wiring-diagram'
740
+ ```
741
+
742
+ 如果出现下面的错误:
743
+
744
+ ```text
745
+ Cannot read properties of null (reading 'ce')
746
+ ```
747
+
748
+ 并且堆栈里出现其他包下面的:
749
+
750
+ ```text
751
+ node_modules/@vue/runtime-core
752
+ ```
753
+
754
+ 说明宿主项目加载了两份 Vue。清理宿主项目缓存后重新安装:
755
+
756
+ ```bash
757
+ rm -rf node_modules/.vite node_modules/.cache node_modules/vue3-wiring-diagram
758
+ npm install vue3-wiring-diagram
759
+ ```
760
+
761
+ ---
762
+
763
+ # API Specification
764
+
765
+ This document describes the backend APIs used by `vue3-wiring-diagram`. A host application can integrate the editor and preview components by implementing the following endpoints, request parameters, and response structures.
766
+
767
+ [中文接口规范](./API.zh-CN.md)
768
+
769
+ ## Base Rules
770
+
771
+ All requests are based on `configure({ baseURL })`. Example:
772
+
773
+ ```js
774
+ configure({
775
+ baseURL: '/api/cny',
776
+ assetBaseURL: '/api',
777
+ token: 'token'
778
+ })
779
+ ```
780
+
781
+ When the component requests `/template/selectOne`, the actual browser request is:
782
+
783
+ ```text
784
+ /api/cny/template/selectOne
785
+ ```
786
+
787
+ ## Request Headers
788
+
789
+ | Field | Type | Required | Description |
790
+ | --- | --- | --- | --- |
791
+ | `token` | `string` | No | Set by `configure({ token })` or `setToken(token)`. The plugin writes it to the `token` request header. |
792
+ | `Accept-Language` | `zh-CN \| en-US` | No | Set automatically from component `locale`. `locale="zh-CN"` sends `zh-CN`; `locale="en-US"` sends `en-US`. |
793
+ | Custom headers | `string` | No | Passed through by `configure({ headers })`, such as tenant id, app id, organization id, or custom auth fields. The plugin does not require them. |
794
+
795
+ ## Standard Response
796
+
797
+ All JSON APIs should return:
798
+
799
+ ```json
800
+ {
801
+ "code": 200,
802
+ "msg": "success",
803
+ "data": {}
804
+ }
805
+ ```
806
+
807
+ | Field | Type | Required | Description |
808
+ | --- | --- | --- | --- |
809
+ | `code` | `number` | Yes | Business status code. The plugin treats `code === 200` as success. |
810
+ | `msg` | `string` | No | Message used for failure prompts. |
811
+ | `data` | `any` | No | Business data. Each endpoint defines its own `data` structure. |
812
+
813
+ APIs must return JSON, not HTML. HTML responses are treated as invalid API responses.
814
+
815
+ ## 1. Get Diagram Detail
816
+
817
+ Used by the editor to load an existing diagram and by preview to render by `id`.
818
+
819
+ ```text
820
+ GET /template/selectOne
821
+ ```
822
+
823
+ ### Request Parameters
824
+
825
+ | Field | Type | Required | Description |
826
+ | --- | --- | --- | --- |
827
+ | `id` | `string \| number` | Yes | Diagram template id, matching the component `id` prop. |
828
+
829
+ ### Response `data`
830
+
831
+ ```json
832
+ {
833
+ "id": 195,
834
+ "remark": "{\"background\":{},\"grid\":{},\"data\":{\"cells\":[]}}"
835
+ }
836
+ ```
837
+
838
+ | Field | Type | Required | Description |
839
+ | --- | --- | --- | --- |
840
+ | `id` | `string \| number` | No | Diagram template id. The plugin does not depend on it. |
841
+ | `remark` | `string` | Yes | Diagram JSON string. It must be `JSON.stringify({ background, grid, data })`. |
842
+
843
+ ### Parsed `remark`
844
+
845
+ | Field | Type | Required | Description |
846
+ | --- | --- | --- | --- |
847
+ | `background` | `object` | Yes | X6 graph background configuration. |
848
+ | `grid` | `object` | Yes | X6 graph grid configuration. |
849
+ | `data` | `object` | Yes | X6 diagram data, usually containing `cells`. |
850
+ | `data.cells` | `array` | Yes | X6 node and edge list. |
851
+
852
+ ## 2. Save Diagram
853
+
854
+ Used by the editor to save diagram data.
855
+
856
+ ```text
857
+ POST /template/insert
858
+ ```
859
+
860
+ ### Request Body
861
+
862
+ ```json
863
+ {
864
+ "id": "195",
865
+ "remark": "{\"background\":{},\"grid\":{},\"data\":{\"cells\":[]}}"
866
+ }
867
+ ```
868
+
869
+ | Field | Type | Required | Description |
870
+ | --- | --- | --- | --- |
871
+ | `id` | `string \| number` | Yes | Diagram template id. |
872
+ | `remark` | `string` | Yes | Diagram JSON string. The plugin sends `JSON.stringify({ background, grid, data })`. |
873
+
874
+ ### Response `data`
875
+
876
+ | Field | Type | Required | Description |
877
+ | --- | --- | --- | --- |
878
+ | `data` | `any` | No | The plugin only checks `code === 200`; it does not depend on this data. |
879
+
880
+ ## 3. Get Device List
881
+
882
+ Used by text, image, pipe, and arrow controls to bind devices.
883
+
884
+ ```text
885
+ GET /custom/deviceList
886
+ ```
887
+
888
+ ### Request Parameters
889
+
890
+ | Field | Type | Required | Description |
891
+ | --- | --- | --- | --- |
892
+ | `itemIds` | `string \| number` | Yes | Project/site id, matching the editor `itemId` prop. |
893
+
894
+ ### Response `data`
895
+
896
+ ```json
897
+ [
898
+ {
899
+ "deviceName": "Device Name",
900
+ "deviceCode": "device-code"
901
+ }
902
+ ]
903
+ ```
904
+
905
+ | Field | Type | Required | Description |
906
+ | --- | --- | --- | --- |
907
+ | `deviceName` | `string` | Yes | Device name shown in select options. |
908
+ | `deviceCode` | `string` | Yes | Device code used to query fields and save bindings. |
909
+
910
+ ## 4. Get Device Field List
911
+
912
+ Used by text, image, pipe, and arrow controls to select monitoring fields.
913
+
914
+ ```text
915
+ GET /custom/monitorInfo
916
+ ```
917
+
918
+ ### Request Parameters
919
+
920
+ | Field | Type | Required | Description |
921
+ | --- | --- | --- | --- |
922
+ | `deviceCode` | `string` | Yes | Device code from `/custom/deviceList`. |
923
+ | `fieldType` | `number` | Yes | Field type. The plugin always sends `1`. |
924
+
925
+ ### Response `data`
926
+
927
+ ```json
928
+ [
929
+ {
930
+ "name": "Voltage",
931
+ "dataField": "voltage",
932
+ "unit": "V"
933
+ }
934
+ ]
935
+ ```
936
+
937
+ | Field | Type | Required | Description |
938
+ | --- | --- | --- | --- |
939
+ | `name` | `string` | Yes | Field name shown in select options and text bindings. |
940
+ | `dataField` | `string` | Yes | Field code saved to diagram node `fields[].field`. |
941
+ | `unit` | `string` | No | Unit used in text binding prompts. |
942
+
943
+ ## 5. Get DI Field List
944
+
945
+ Used by pipe dynamic flow settings.
946
+
947
+ ```text
948
+ GET /template/getDiField
949
+ ```
950
+
951
+ ### Request Parameters
952
+
953
+ | Field | Type | Required | Description |
954
+ | --- | --- | --- | --- |
955
+ | `itemIds` | `string \| number` | Yes | Project/site id, matching the editor `itemId` prop. |
956
+
957
+ ### Response `data`
958
+
959
+ ```json
960
+ [
961
+ {
962
+ "deviceCode": "device-code",
963
+ "field": "status",
964
+ "deviceName": "Device Name",
965
+ "name": "Running Status"
966
+ }
967
+ ]
968
+ ```
969
+
970
+ | Field | Type | Required | Description |
971
+ | --- | --- | --- | --- |
972
+ | `deviceCode` | `string` | Yes | Device code. The plugin combines it with `field` as an internal unique id. |
973
+ | `field` | `string` | Yes | Field code. |
974
+ | `deviceName` | `string` | No | Device name. |
975
+ | `name` | `string` | No | Field name. |
976
+
977
+ ## 6. Get Real-Time Data
978
+
979
+ Used by preview to refresh text, pipe, arrow, and image status. The plugin sends batches of up to 5 cells.
980
+
981
+ ```text
982
+ POST /custom/arrRealData2
983
+ ```
984
+
985
+ ### Request Body
986
+
987
+ ```json
988
+ [
989
+ {
990
+ "id": "x6-cell-id",
991
+ "fields": [
992
+ {
993
+ "index": 0,
994
+ "deviceName": "Device Name",
995
+ "deviceCode": "device-code",
996
+ "field": "voltage"
997
+ }
998
+ ]
999
+ }
1000
+ ]
1001
+ ```
1002
+
1003
+ | Field | Type | Required | Description |
1004
+ | --- | --- | --- | --- |
1005
+ | `id` | `string` | Yes | X6 node or edge id. Return it unchanged so the plugin can locate the cell to update. |
1006
+ | `fields` | `array` | Yes | Bound field list for this cell. |
1007
+ | `fields[].index` | `number` | Yes | Field index. Text templates match this index by `${}` order. |
1008
+ | `fields[].deviceName` | `string` | No | Device name. |
1009
+ | `fields[].deviceCode` | `string` | Yes | Device code. |
1010
+ | `fields[].field` | `string` | Yes | Field code. |
1011
+
1012
+ ### Response `data`
1013
+
1014
+ ```json
1015
+ [
1016
+ {
1017
+ "id": "x6-cell-id",
1018
+ "fields": [
1019
+ {
1020
+ "index": 0,
1021
+ "field": "voltage",
1022
+ "value": 220,
1023
+ "valueName": "220V"
1024
+ }
1025
+ ]
1026
+ }
1027
+ ]
1028
+ ```
1029
+
1030
+ | Field | Type | Required | Description |
1031
+ | --- | --- | --- | --- |
1032
+ | `id` | `string` | Yes | X6 node or edge id. Must match the request `id`. |
1033
+ | `fields` | `array` | Yes | Real-time field values. |
1034
+ | `fields[].index` | `number` | Yes | Field index used by text replacement. |
1035
+ | `fields[].field` | `string` | No | Field code. |
1036
+ | `fields[].value` | `string \| number \| boolean` | Yes | Raw value used by pipe, arrow, and image condition checks. |
1037
+ | `fields[].valueName` | `string` | No | Display value. Text components prefer this value for `${}` replacement. |
1038
+
1039
+ ## 7. Get Image Groups and Images
1040
+
1041
+ Used by the left stencil, image management, and image condition replacement.
1042
+
1043
+ ```text
1044
+ GET /custom/groupList
1045
+ ```
1046
+
1047
+ ### Request Parameters
1048
+
1049
+ None.
1050
+
1051
+ ### Response `data`
1052
+
1053
+ `data` can be an array directly, or a paged object containing `records`, `list`, `items`, or `rows`.
1054
+
1055
+ ```json
1056
+ [
1057
+ {
1058
+ "id": 1,
1059
+ "groupName": "Meter",
1060
+ "sort": 1,
1061
+ "isShow": 1,
1062
+ "pictureList": [
1063
+ {
1064
+ "id": 10,
1065
+ "groupId": 1,
1066
+ "imageName": "Meter",
1067
+ "imageUrl": "/cny/upload/meter.png",
1068
+ "sort": 1,
1069
+ "isShow": 1
1070
+ }
1071
+ ]
1072
+ }
1073
+ ]
1074
+ ```
1075
+
1076
+ | Field | Type | Required | Description |
1077
+ | --- | --- | --- | --- |
1078
+ | `id` | `string \| number` | Yes | Image group id. |
1079
+ | `groupName` | `string` | Yes | Image group name used as the left stencil group title. |
1080
+ | `sort` | `number` | No | Sort value. |
1081
+ | `isShow` | `number` | No | Visibility flag. Recommended: `1` visible, `0` hidden. |
1082
+ | `pictureList` | `array` | Yes | Image list under this group. |
1083
+ | `pictureList[].id` | `string \| number` | Yes | Image id. |
1084
+ | `pictureList[].groupId` | `string \| number` | Yes | Parent group id. |
1085
+ | `pictureList[].imageName` | `string` | Yes | Image name. |
1086
+ | `pictureList[].imageUrl` | `string` | Yes | Image URL. It can be an absolute URL or a relative path, such as `/cny/upload/meter.png`. |
1087
+ | `pictureList[].sort` | `number` | No | Image sort value. |
1088
+ | `pictureList[].isShow` | `number` | No | Visibility flag. Recommended: `1` visible, `0` hidden. |
1089
+
1090
+ ## 8. Create Image Group
1091
+
1092
+ ```text
1093
+ POST /custom/saveGroup
1094
+ ```
1095
+
1096
+ ### Request Body
1097
+
1098
+ | Field | Type | Required | Description |
1099
+ | --- | --- | --- | --- |
1100
+ | `groupName` | `string` | Yes | Group name. Recommended length: 1 to 20 characters. |
1101
+ | `sort` | `number` | Yes | Sort value. |
1102
+ | `isShow` | `number` | Yes | Visibility flag. `1` visible, `0` hidden. |
1103
+
1104
+ ### Response `data`
1105
+
1106
+ The plugin only checks `code === 200`; it does not depend on this data.
1107
+
1108
+ ## 9. Update Image Group
1109
+
1110
+ ```text
1111
+ POST /custom/updateGroup
1112
+ ```
1113
+
1114
+ ### Request Body
1115
+
1116
+ | Field | Type | Required | Description |
1117
+ | --- | --- | --- | --- |
1118
+ | `id` | `string \| number` | Yes | Group id. |
1119
+ | `groupName` | `string` | Yes | Group name. Recommended length: 1 to 20 characters. |
1120
+ | `sort` | `number` | Yes | Sort value. |
1121
+ | `isShow` | `number` | Yes | Visibility flag. `1` visible, `0` hidden. |
1122
+
1123
+ ### Response `data`
1124
+
1125
+ The plugin only checks `code === 200`; it does not depend on this data.
1126
+
1127
+ ## 10. Delete Image Group
1128
+
1129
+ ```text
1130
+ GET /custom/removeGroup/{id}
1131
+ ```
1132
+
1133
+ ### Path Parameters
1134
+
1135
+ | Field | Type | Required | Description |
1136
+ | --- | --- | --- | --- |
1137
+ | `id` | `string \| number` | Yes | Image group id to delete. |
1138
+
1139
+ ### Response `data`
1140
+
1141
+ The plugin only checks `code === 200`; it does not depend on this data.
1142
+
1143
+ ## 11. Upload Image File
1144
+
1145
+ ```text
1146
+ POST /file/fileUpload
1147
+ Content-Type: multipart/form-data
1148
+ ```
1149
+
1150
+ ### Request Body
1151
+
1152
+ | Field | Type | Required | Description |
1153
+ | --- | --- | --- | --- |
1154
+ | `file` | `File` | Yes | Image file. The plugin validates that the MIME type contains `image`. |
1155
+
1156
+ ### Response `data`
1157
+
1158
+ ```json
1159
+ "/cny/upload/meter.png"
1160
+ ```
1161
+
1162
+ | Field | Type | Required | Description |
1163
+ | --- | --- | --- | --- |
1164
+ | `data` | `string` | Yes | Uploaded image URL. It is submitted as `imageUrl` when saving an image. |
1165
+
1166
+ ## 12. Create or Update Image
1167
+
1168
+ ```text
1169
+ POST /custom/savePicture
1170
+ ```
1171
+
1172
+ ### Request Body
1173
+
1174
+ | Field | Type | Required | Description |
1175
+ | --- | --- | --- | --- |
1176
+ | `id` | `string \| number` | No | Image id. Empty for create; existing id for edit. |
1177
+ | `groupId` | `string \| number` | Yes | Parent image group id. |
1178
+ | `imageName` | `string` | Yes | Image name. Recommended length: 1 to 20 characters. |
1179
+ | `imageUrl` | `string` | Yes | Image URL, usually from `/file/fileUpload` response `data`. |
1180
+ | `sort` | `number` | Yes | Sort value. |
1181
+ | `isShow` | `number` | Yes | Visibility flag. `1` visible, `0` hidden. |
1182
+
1183
+ ### Response `data`
1184
+
1185
+ The plugin only checks `code === 200`; it does not depend on this data.
1186
+
1187
+ ## 13. Delete Image
1188
+
1189
+ ```text
1190
+ GET /custom/removePicture/{id}
1191
+ ```
1192
+
1193
+ ### Path Parameters
1194
+
1195
+ | Field | Type | Required | Description |
1196
+ | --- | --- | --- | --- |
1197
+ | `id` | `string \| number` | Yes | Image id to delete. |
1198
+
1199
+ ### Response `data`
1200
+
1201
+ The plugin only checks `code === 200`; it does not depend on this data.
1202
+
1203
+ ## 14. Get Template List
1204
+
1205
+ Used by image node jump-source selection.
1206
+
1207
+ ```text
1208
+ GET /template/listPage
1209
+ ```
1210
+
1211
+ ### Request Parameters
1212
+
1213
+ The plugin always sends:
1214
+
1215
+ ```json
1216
+ {
1217
+ "pageNum": 1,
1218
+ "pageSize": 9999
1219
+ }
1220
+ ```
1221
+
1222
+ | Field | Type | Required | Description |
1223
+ | --- | --- | --- | --- |
1224
+ | `pageNum` | `number` | Yes | Page number. The plugin always sends `1`. |
1225
+ | `pageSize` | `number` | Yes | Page size. The plugin always sends `9999`. |
1226
+
1227
+ ### Response `data`
1228
+
1229
+ ```json
1230
+ {
1231
+ "records": [
1232
+ {
1233
+ "id": 195,
1234
+ "name": "Main Diagram"
1235
+ }
1236
+ ]
1237
+ }
1238
+ ```
1239
+
1240
+ | Field | Type | Required | Description |
1241
+ | --- | --- | --- | --- |
1242
+ | `records` | `array` | Yes | Template list. |
1243
+ | `records[].id` | `string \| number` | Yes | Template id. |
1244
+ | `records[].name` | `string` | Yes | Template name shown in select options. |
1245
+
1246
+ ---
1247
+
1248
+ # 接口规范
1249
+
1250
+ 本文档描述 `vue3-wiring-diagram` 组件运行时用到的后端接口。宿主项目只要按以下路径、入参和返回结构实现接口,即可接入编辑器和预览组件。
1251
+
1252
+ ## 基础约定
1253
+
1254
+ 所有接口都基于 `configure({ baseURL })` 配置的地址发起请求。例如:
1255
+
1256
+ ```js
1257
+ configure({
1258
+ baseURL: '/api/cny',
1259
+ assetBaseURL: '/api',
1260
+ token: 'token'
1261
+ })
1262
+ ```
1263
+
1264
+ 组件内部请求 `/template/selectOne` 时,浏览器实际请求地址为:
1265
+
1266
+ ```text
1267
+ /api/cny/template/selectOne
1268
+ ```
1269
+
1270
+ ## 请求头
1271
+
1272
+ | 字段 | 类型 | 必填 | 说明 |
1273
+ | --- | --- | --- | --- |
1274
+ | `token` | `string` | 否 | 通过 `configure({ token })` 或 `setToken(token)` 设置。插件会写入请求头 `token`。 |
1275
+ | `Accept-Language` | `zh-CN \| en-US` | 否 | 由组件 `locale` 自动设置。`locale="zh-CN"` 时传 `zh-CN`,`locale="en-US"` 时传 `en-US`。 |
1276
+ | 自定义请求头 | `string` | 否 | 通过 `configure({ headers })` 透传给后端。例如租户 id、应用 id、组织 id 等。插件不强制要求。 |
1277
+
1278
+ ## 统一响应结构
1279
+
1280
+ 所有 JSON 接口建议返回以下结构:
1281
+
1282
+ ```json
1283
+ {
1284
+ "code": 200,
1285
+ "msg": "success",
1286
+ "data": {}
1287
+ }
1288
+ ```
1289
+
1290
+ | 字段 | 类型 | 必填 | 说明 |
1291
+ | --- | --- | --- | --- |
1292
+ | `code` | `number` | 是 | 状态码。插件内部以 `code === 200` 判断业务成功。 |
1293
+ | `msg` | `string` | 否 | 提示信息。失败时会用于页面提示。 |
1294
+ | `data` | `any` | 否 | 业务数据。不同接口结构不同,详见下文。 |
1295
+
1296
+ 注意:接口必须返回 JSON,不能返回 HTML。否则插件会认为响应格式错误。
1297
+
1298
+ ## 1. 获取图纸详情
1299
+
1300
+ 用于编辑器加载已有图纸,也用于预览组件按 `id` 预览。
1301
+
1302
+ ```text
1303
+ GET /template/selectOne
1304
+ ```
1305
+
1306
+ ### 入参
1307
+
1308
+ | 字段 | 类型 | 必填 | 说明 |
1309
+ | --- | --- | --- | --- |
1310
+ | `id` | `string \| number` | 是 | 图纸模板 id,对应组件传入的 `id`。 |
1311
+
1312
+ ### 返回 `data`
1313
+
1314
+ ```json
1315
+ {
1316
+ "id": 195,
1317
+ "remark": "{\"background\":{},\"grid\":{},\"data\":{\"cells\":[]}}"
1318
+ }
1319
+ ```
1320
+
1321
+ | 字段 | 类型 | 必填 | 说明 |
1322
+ | --- | --- | --- | --- |
1323
+ | `id` | `string \| number` | 否 | 图纸模板 id。插件不强依赖该字段。 |
1324
+ | `remark` | `string` | 是 | 图纸 JSON 字符串。必须是 `JSON.stringify({ background, grid, data })` 后的字符串。 |
1325
+
1326
+ ### `remark` 解析后的结构
1327
+
1328
+ | 字段 | 类型 | 必填 | 说明 |
1329
+ | --- | --- | --- | --- |
1330
+ | `background` | `object` | 是 | X6 画布背景配置。 |
1331
+ | `grid` | `object` | 是 | X6 网格配置。 |
1332
+ | `data` | `object` | 是 | X6 图纸数据,通常包含 `cells`。 |
1333
+ | `data.cells` | `array` | 是 | X6 节点和连线数组。 |
1334
+
1335
+ ## 2. 保存图纸
1336
+
1337
+ 用于编辑器保存图纸。
1338
+
1339
+ ```text
1340
+ POST /template/insert
1341
+ ```
1342
+
1343
+ ### 入参
1344
+
1345
+ ```json
1346
+ {
1347
+ "id": "195",
1348
+ "remark": "{\"background\":{},\"grid\":{},\"data\":{\"cells\":[]}}"
1349
+ }
1350
+ ```
1351
+
1352
+ | 字段 | 类型 | 必填 | 说明 |
1353
+ | --- | --- | --- | --- |
1354
+ | `id` | `string \| number` | 是 | 图纸模板 id。 |
1355
+ | `remark` | `string` | 是 | 图纸 JSON 字符串。插件会把 `{ background, grid, data }` 使用 `JSON.stringify` 后传给后端。 |
1356
+
1357
+ ### 返回 `data`
1358
+
1359
+ | 字段 | 类型 | 必填 | 说明 |
1360
+ | --- | --- | --- | --- |
1361
+ | `data` | `any` | 否 | 插件只判断 `code === 200`,不依赖具体返回数据。 |
1362
+
1363
+ ## 3. 获取设备列表
1364
+
1365
+ 用于文本、图片、管道、箭头等组件绑定设备。
1366
+
1367
+ ```text
1368
+ GET /custom/deviceList
1369
+ ```
1370
+
1371
+ ### 入参
1372
+
1373
+ | 字段 | 类型 | 必填 | 说明 |
1374
+ | --- | --- | --- | --- |
1375
+ | `itemIds` | `string \| number` | 是 | 项目/站点 id,对应编辑器组件传入的 `itemId`。 |
1376
+
1377
+ ### 返回 `data`
1378
+
1379
+ ```json
1380
+ [
1381
+ {
1382
+ "deviceName": "设备名称",
1383
+ "deviceCode": "device-code"
1384
+ }
1385
+ ]
1386
+ ```
1387
+
1388
+ | 字段 | 类型 | 必填 | 说明 |
1389
+ | --- | --- | --- | --- |
1390
+ | `deviceName` | `string` | 是 | 设备名称,用于下拉框展示。 |
1391
+ | `deviceCode` | `string` | 是 | 设备编码,用于查询字段列表和保存绑定关系。 |
1392
+
1393
+ ## 4. 获取设备字段列表
1394
+
1395
+ 用于文本、图片、管道、箭头等组件选择监测字段。
1396
+
1397
+ ```text
1398
+ GET /custom/monitorInfo
1399
+ ```
1400
+
1401
+ ### 入参
1402
+
1403
+ | 字段 | 类型 | 必填 | 说明 |
1404
+ | --- | --- | --- | --- |
1405
+ | `deviceCode` | `string` | 是 | 设备编码,来自 `/custom/deviceList` 的 `deviceCode`。 |
1406
+ | `fieldType` | `number` | 是 | 字段类型。插件固定传 `1`。 |
1407
+
1408
+ ### 返回 `data`
1409
+
1410
+ ```json
1411
+ [
1412
+ {
1413
+ "name": "电压",
1414
+ "dataField": "voltage",
1415
+ "unit": "V"
1416
+ }
1417
+ ]
1418
+ ```
1419
+
1420
+ | 字段 | 类型 | 必填 | 说明 |
1421
+ | --- | --- | --- | --- |
1422
+ | `name` | `string` | 是 | 字段名称,用于下拉框展示和文本模板绑定。 |
1423
+ | `dataField` | `string` | 是 | 字段编码,会保存到图纸节点的 `fields[].field` 中。 |
1424
+ | `unit` | `string` | 否 | 单位。文本绑定时用于展示提示。 |
1425
+
1426
+ ## 5. 获取 DI 字段列表
1427
+
1428
+ 用于管道动态流向相关字段选择。
1429
+
1430
+ ```text
1431
+ GET /template/getDiField
1432
+ ```
1433
+
1434
+ ### 入参
1435
+
1436
+ | 字段 | 类型 | 必填 | 说明 |
1437
+ | --- | --- | --- | --- |
1438
+ | `itemIds` | `string \| number` | 是 | 项目/站点 id,对应编辑器组件传入的 `itemId`。 |
1439
+
1440
+ ### 返回 `data`
1441
+
1442
+ ```json
1443
+ [
1444
+ {
1445
+ "deviceCode": "device-code",
1446
+ "field": "status",
1447
+ "deviceName": "设备名称",
1448
+ "name": "运行状态"
1449
+ }
1450
+ ]
1451
+ ```
1452
+
1453
+ | 字段 | 类型 | 必填 | 说明 |
1454
+ | --- | --- | --- | --- |
1455
+ | `deviceCode` | `string` | 是 | 设备编码。插件会和 `field` 拼成内部唯一 id。 |
1456
+ | `field` | `string` | 是 | 字段编码。 |
1457
+ | `deviceName` | `string` | 否 | 设备名称。 |
1458
+ | `name` | `string` | 否 | 字段名称。 |
1459
+
1460
+ ## 6. 获取实时数据
1461
+
1462
+ 用于预览组件刷新文本、管道、箭头和图片的实时状态。插件会按批次调用,每批最多 5 个节点。
1463
+
1464
+ ```text
1465
+ POST /custom/arrRealData2
1466
+ ```
1467
+
1468
+ ### 入参
1469
+
1470
+ ```json
1471
+ [
1472
+ {
1473
+ "id": "x6-cell-id",
1474
+ "fields": [
1475
+ {
1476
+ "index": 0,
1477
+ "deviceName": "设备名称",
1478
+ "deviceCode": "device-code",
1479
+ "field": "voltage"
1480
+ }
1481
+ ]
1482
+ }
1483
+ ]
1484
+ ```
1485
+
1486
+ | 字段 | 类型 | 必填 | 说明 |
1487
+ | --- | --- | --- | --- |
1488
+ | `id` | `string` | 是 | X6 节点或连线 id。后端需要原样返回,用于插件定位要更新的图元。 |
1489
+ | `fields` | `array` | 是 | 该图元绑定的字段列表。 |
1490
+ | `fields[].index` | `number` | 是 | 字段索引。文本模板中会按 `${}` 出现顺序匹配。 |
1491
+ | `fields[].deviceName` | `string` | 否 | 设备名称。 |
1492
+ | `fields[].deviceCode` | `string` | 是 | 设备编码。 |
1493
+ | `fields[].field` | `string` | 是 | 字段编码。 |
1494
+
1495
+ ### 返回 `data`
1496
+
1497
+ ```json
1498
+ [
1499
+ {
1500
+ "id": "x6-cell-id",
1501
+ "fields": [
1502
+ {
1503
+ "index": 0,
1504
+ "field": "voltage",
1505
+ "value": 220,
1506
+ "valueName": "220V"
1507
+ }
1508
+ ]
1509
+ }
1510
+ ]
1511
+ ```
1512
+
1513
+ | 字段 | 类型 | 必填 | 说明 |
1514
+ | --- | --- | --- | --- |
1515
+ | `id` | `string` | 是 | X6 节点或连线 id,必须和入参中的 `id` 一致。 |
1516
+ | `fields` | `array` | 是 | 字段实时值列表。 |
1517
+ | `fields[].index` | `number` | 是 | 字段索引。文本替换时按该字段匹配。 |
1518
+ | `fields[].field` | `string` | 否 | 字段编码。 |
1519
+ | `fields[].value` | `string \| number \| boolean` | 是 | 原始值。管道、箭头、图片条件判断会使用该值。 |
1520
+ | `fields[].valueName` | `string` | 否 | 展示值。文本组件会优先使用该字段替换 `${}`。 |
1521
+
1522
+ ## 7. 获取图片分组和图片列表
1523
+
1524
+ 用于左侧元件库、图片管理、图片条件替换。
1525
+
1526
+ ```text
1527
+ GET /custom/groupList
1528
+ ```
1529
+
1530
+ ### 入参
1531
+
1532
+ 无。
1533
+
1534
+ ### 返回 `data`
1535
+
1536
+ `data` 可以直接是数组,也可以是分页对象中的 `records`、`list`、`items` 或 `rows`。
1537
+
1538
+ ```json
1539
+ [
1540
+ {
1541
+ "id": 1,
1542
+ "groupName": "电表",
1543
+ "sort": 1,
1544
+ "isShow": 1,
1545
+ "pictureList": [
1546
+ {
1547
+ "id": 10,
1548
+ "groupId": 1,
1549
+ "imageName": "电表",
1550
+ "imageUrl": "/cny/upload/meter.png",
1551
+ "sort": 1,
1552
+ "isShow": 1
1553
+ }
1554
+ ]
1555
+ }
1556
+ ]
1557
+ ```
1558
+
1559
+ | 字段 | 类型 | 必填 | 说明 |
1560
+ | --- | --- | --- | --- |
1561
+ | `id` | `string \| number` | 是 | 图片分组 id。 |
1562
+ | `groupName` | `string` | 是 | 图片分组名称,用于左侧分组标题。 |
1563
+ | `sort` | `number` | 否 | 排序值。 |
1564
+ | `isShow` | `number` | 否 | 是否显示。建议 `1` 表示显示,`0` 表示隐藏。 |
1565
+ | `pictureList` | `array` | 是 | 分组下的图片列表。 |
1566
+ | `pictureList[].id` | `string \| number` | 是 | 图片 id。 |
1567
+ | `pictureList[].groupId` | `string \| number` | 是 | 所属分组 id。 |
1568
+ | `pictureList[].imageName` | `string` | 是 | 图片名称。 |
1569
+ | `pictureList[].imageUrl` | `string` | 是 | 图片地址。可以是完整 URL,也可以是相对路径,例如 `/cny/upload/meter.png`。 |
1570
+ | `pictureList[].sort` | `number` | 否 | 图片排序值。 |
1571
+ | `pictureList[].isShow` | `number` | 否 | 是否显示。建议 `1` 表示显示,`0` 表示隐藏。 |
1572
+
1573
+ ## 8. 新增图片分组
1574
+
1575
+ ```text
1576
+ POST /custom/saveGroup
1577
+ ```
1578
+
1579
+ ### 入参
1580
+
1581
+ | 字段 | 类型 | 必填 | 说明 |
1582
+ | --- | --- | --- | --- |
1583
+ | `groupName` | `string` | 是 | 分组名称,长度建议 1 到 20 个字符。 |
1584
+ | `sort` | `number` | 是 | 排序值。 |
1585
+ | `isShow` | `number` | 是 | 是否显示。`1` 表示显示,`0` 表示隐藏。 |
1586
+
1587
+ ### 返回 `data`
1588
+
1589
+ 插件只判断 `code === 200`,不依赖具体返回数据。
1590
+
1591
+ ## 9. 更新图片分组
1592
+
1593
+ ```text
1594
+ POST /custom/updateGroup
1595
+ ```
1596
+
1597
+ ### 入参
1598
+
1599
+ | 字段 | 类型 | 必填 | 说明 |
1600
+ | --- | --- | --- | --- |
1601
+ | `id` | `string \| number` | 是 | 分组 id。 |
1602
+ | `groupName` | `string` | 是 | 分组名称,长度建议 1 到 20 个字符。 |
1603
+ | `sort` | `number` | 是 | 排序值。 |
1604
+ | `isShow` | `number` | 是 | 是否显示。`1` 表示显示,`0` 表示隐藏。 |
1605
+
1606
+ ### 返回 `data`
1607
+
1608
+ 插件只判断 `code === 200`,不依赖具体返回数据。
1609
+
1610
+ ## 10. 删除图片分组
1611
+
1612
+ ```text
1613
+ GET /custom/removeGroup/{id}
1614
+ ```
1615
+
1616
+ ### 路径参数
1617
+
1618
+ | 字段 | 类型 | 必填 | 说明 |
1619
+ | --- | --- | --- | --- |
1620
+ | `id` | `string \| number` | 是 | 要删除的图片分组 id。 |
1621
+
1622
+ ### 返回 `data`
1623
+
1624
+ 插件只判断 `code === 200`,不依赖具体返回数据。
1625
+
1626
+ ## 11. 上传图片文件
1627
+
1628
+ ```text
1629
+ POST /file/fileUpload
1630
+ Content-Type: multipart/form-data
1631
+ ```
1632
+
1633
+ ### 入参
1634
+
1635
+ | 字段 | 类型 | 必填 | 说明 |
1636
+ | --- | --- | --- | --- |
1637
+ | `file` | `File` | 是 | 图片文件。插件会校验文件 MIME 类型包含 `image`。 |
1638
+
1639
+ ### 返回 `data`
1640
+
1641
+ ```json
1642
+ "/cny/upload/meter.png"
1643
+ ```
1644
+
1645
+ | 字段 | 类型 | 必填 | 说明 |
1646
+ | --- | --- | --- | --- |
1647
+ | `data` | `string` | 是 | 上传后的图片地址。保存图片时会作为 `imageUrl` 提交。 |
1648
+
1649
+ ## 12. 新增或更新图片
1650
+
1651
+ ```text
1652
+ POST /custom/savePicture
1653
+ ```
1654
+
1655
+ ### 入参
1656
+
1657
+ | 字段 | 类型 | 必填 | 说明 |
1658
+ | --- | --- | --- | --- |
1659
+ | `id` | `string \| number` | 否 | 图片 id。新增时可为空,编辑时传原图片 id。 |
1660
+ | `groupId` | `string \| number` | 是 | 所属图片分组 id。 |
1661
+ | `imageName` | `string` | 是 | 图片名称,长度建议 1 到 20 个字符。 |
1662
+ | `imageUrl` | `string` | 是 | 图片地址,通常来自 `/file/fileUpload` 返回的 `data`。 |
1663
+ | `sort` | `number` | 是 | 排序值。 |
1664
+ | `isShow` | `number` | 是 | 是否显示。`1` 表示显示,`0` 表示隐藏。 |
1665
+
1666
+ ### 返回 `data`
1667
+
1668
+ 插件只判断 `code === 200`,不依赖具体返回数据。
1669
+
1670
+ ## 13. 删除图片
1671
+
1672
+ ```text
1673
+ GET /custom/removePicture/{id}
1674
+ ```
1675
+
1676
+ ### 路径参数
1677
+
1678
+ | 字段 | 类型 | 必填 | 说明 |
1679
+ | --- | --- | --- | --- |
1680
+ | `id` | `string \| number` | 是 | 要删除的图片 id。 |
1681
+
1682
+ ### 返回 `data`
1683
+
1684
+ 插件只判断 `code === 200`,不依赖具体返回数据。
1685
+
1686
+ ## 14. 获取模板列表
1687
+
1688
+ 用于图片节点的跳转图源选择。
1689
+
1690
+ ```text
1691
+ GET /template/listPage
1692
+ ```
1693
+
1694
+ ### 入参
1695
+
1696
+ 插件固定传:
1697
+
1698
+ ```json
1699
+ {
1700
+ "pageNum": 1,
1701
+ "pageSize": 9999
1702
+ }
1703
+ ```
1704
+
1705
+ | 字段 | 类型 | 必填 | 说明 |
1706
+ | --- | --- | --- | --- |
1707
+ | `pageNum` | `number` | 是 | 页码。插件固定传 `1`。 |
1708
+ | `pageSize` | `number` | 是 | 每页数量。插件固定传 `9999`。 |
1709
+
1710
+ ### 返回 `data`
1711
+
1712
+ ```json
1713
+ {
1714
+ "records": [
1715
+ {
1716
+ "id": 195,
1717
+ "name": "主接线图"
1718
+ }
1719
+ ]
1720
+ }
1721
+ ```
1722
+
1723
+ | 字段 | 类型 | 必填 | 说明 |
1724
+ | --- | --- | --- | --- |
1725
+ | `records` | `array` | 是 | 模板列表。 |
1726
+ | `records[].id` | `string \| number` | 是 | 模板 id。 |
1727
+ | `records[].name` | `string` | 是 | 模板名称,用于下拉框展示。 |