@steedos/steedos-plugin-schema-builder 2.3.0-beta.9 → 2.3.0

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 (44) hide show
  1. package/package.json +2 -2
  2. package/src/objects.action.js +5 -0
  3. package/src/objects.object.yml +6 -0
  4. package/webapp/src/g6/behavior/activate-relations/index.tsx +160 -0
  5. package/webapp/src/g6/behavior/darg/index.tsx +146 -0
  6. package/webapp/src/g6/behavior/index.tsx +5 -0
  7. package/webapp/src/g6/model/editor-background.png +0 -0
  8. package/webapp/src/g6/model/index.tsx +574 -0
  9. package/webapp/src/g6/model/model-node.tsx +1080 -0
  10. package/webapp/src/g6/model/model.scss +163 -0
  11. package/webapp/src/g6/model/toolbar.tsx +360 -0
  12. package/webapp/src/g6/shape/base-sharp/index.tsx +19 -0
  13. package/webapp/src/g6/shape/index.tsx +0 -0
  14. package/webapp/src/g6/util/graph.tsx +60 -0
  15. package/webapp/src/g6/util/hooks.tsx +26 -0
  16. package/webapp/src/g6/util/index.tsx +20 -0
  17. package/webapp/src/hook/index.tsx +47 -0
  18. package/webapp/src/index.tsx +25 -0
  19. package/webapp/src/page/dva-model/index.tsx +70 -0
  20. package/webapp/src/page/dva-model/reducer/arrange.tsx +16 -0
  21. package/webapp/src/page/dva-model/reducer/index.tsx +7 -0
  22. package/webapp/src/page/dva-model/reducer/init.tsx +61 -0
  23. package/webapp/src/page/dva-model/reducer/model.tsx +126 -0
  24. package/webapp/src/page/dva-model/reducer/on-expand.tsx +27 -0
  25. package/webapp/src/page/dva-model/style.tsx +88 -0
  26. package/webapp/src/page/hooks/callback.tsx +54 -0
  27. package/webapp/src/page/hooks/fullscreen.tsx +34 -0
  28. package/webapp/src/page/hooks/pagehooks.tsx +127 -0
  29. package/webapp/src/page/hooks/resize.tsx +20 -0
  30. package/webapp/src/page/index.tsx +393 -0
  31. package/webapp/src/page/model-navi/index.tsx +329 -0
  32. package/webapp/src/page/model-navi/style.scss +111 -0
  33. package/webapp/src/page/util/index.tsx +234 -0
  34. package/webapp/src/page/util/layout-nodes/index.tsx +185 -0
  35. package/webapp/src/pdm/index.tsx +50 -0
  36. package/webapp/src/pdm/pdm-json/index.js +224 -0
  37. package/webapp/src/pdm/pdm-json/removeDiacritics.js +96 -0
  38. package/webapp/src/style.less +14 -0
  39. package/webapp/src/tree/index.tsx +46 -0
  40. package/webapp/src/tree/style.scss +26 -0
  41. package/webapp/src/type/field.tsx +10 -0
  42. package/webapp/src/type/index.tsx +3 -0
  43. package/webapp/src/type/model.tsx +12 -0
  44. package/webapp/src/type/module.tsx +4 -0
@@ -0,0 +1,1080 @@
1
+ import G6 from '@antv/g6'
2
+
3
+
4
+ const setNodeStateAttr = (state, s, cfg) => {
5
+ if (cfg.config.styleConfig[state]) {
6
+ Object.entries(cfg.config.styleConfig[state].node).forEach(([k, v]) => {
7
+ s.attr(k, v)
8
+ })
9
+ }
10
+ }
11
+
12
+ // const mapNodeStateAttr = (state, s, cfg, isMap) => {
13
+ // if (cfg.config.styleConfig[state]) {
14
+ // Object.entries(cfg.config.styleConfig[state].node).forEach(([k, v]) => {
15
+ // s.attr(k, v)
16
+ // })
17
+ // }
18
+ // }
19
+
20
+
21
+ const isEng = (str) => {
22
+ for (let i = 0; i < str.length; i++) {
23
+ const charCode = str.charCodeAt(i)
24
+ if (charCode < 0 || charCode > 128) {
25
+ return false
26
+ }
27
+ }
28
+ return true
29
+
30
+ }
31
+
32
+ const getSplitStrings = (str: string) => {
33
+ if (isEng(str)) return getEngGroup(str)
34
+ const reg = /.{5}/g
35
+ const rs = str.match(reg) || [str]
36
+ rs.push(str.substring(rs.join('').length))
37
+ return rs
38
+ }
39
+
40
+ const getEngGroup = (str: string) => {
41
+ const strs = str.replace(/(?<!^)([A-Z])/g, `-$1`)
42
+ return strs.split('-')
43
+ }
44
+
45
+ const getLen = (str: string) => {
46
+ /// <summary>获得字符串实际长度,中文2,英文1</summary>
47
+ /// <param name="str">要获得长度的字符串</param>
48
+ // tslint:disable-next-line: one-variable-per-declaration
49
+ let realLength = 0,
50
+ len = str.length,
51
+ charCode = -1
52
+
53
+ for (let i = 0; i < len; i++) {
54
+ charCode = str.charCodeAt(i)
55
+ if (charCode >= 0 && charCode <= 128) realLength += 1; else realLength += 2
56
+ }
57
+
58
+ return realLength
59
+ } // tslint:disable-next-line: interface-over-type-literal
60
+
61
+ const getTopAnch = (num, y = 0) => {
62
+ let res = []
63
+ for (let i = 0 ; i < num ; i ++) {
64
+ res.push([(i + 1) / num, y])
65
+
66
+ }
67
+ return res
68
+ }
69
+
70
+ const getBottomAnch = (num, y = 1) => {
71
+ let res = []
72
+ for (let i = 0 ; i <= num ; i ++) {
73
+ res.push([(i) / num, y])
74
+
75
+ }
76
+ return res
77
+ }
78
+
79
+ const getLeftAnch = (num, x= 0) => {
80
+ let res = []
81
+ for (let i = 0 ; i < num ; i ++) {
82
+ res.push([x, (i + 1) / num])
83
+
84
+ }
85
+ return res
86
+ }
87
+
88
+ const getRightAnch = (num, x = 1) => {
89
+ let res = []
90
+ for (let i = 0 ; i <= num ; i ++) {
91
+ res.push([x, (i) / num])
92
+
93
+ }
94
+ return res
95
+ }
96
+
97
+ export interface IModelNodeShapeCfg {
98
+ config: {
99
+ width: number;
100
+ headerHeight: number;
101
+ fieldHeight: number;
102
+ labelSize: number;
103
+ styleConfig: {
104
+ default: {
105
+ node: any;
106
+ edge: any;
107
+ };
108
+ active: {
109
+ node: any;
110
+ edge: any;
111
+ };
112
+ selected: {
113
+ node: any;
114
+ edge: any;
115
+ };
116
+ };
117
+ }
118
+ data: {
119
+ label: string;
120
+ key: string;
121
+ fields: IField[];
122
+ name: string;
123
+ aggregateRoot: boolean;
124
+ aggregateModelKey: string ;
125
+ belongAggregate: string;
126
+ moduleKey: string;
127
+ store: any;
128
+ }
129
+ style: any
130
+ isNoModule?: boolean
131
+ isKeySharp?: boolean
132
+ active?: boolean
133
+ selected?: boolean
134
+ into?: boolean
135
+ out?: boolean
136
+ hide?: boolean
137
+ inactive?: boolean
138
+ isCardSharp?: boolean
139
+ showNameOrLabel?: boolean
140
+ }
141
+ export interface IField {
142
+ key: string
143
+ label: string
144
+ originalKey: string
145
+ type: string
146
+ isForeign?: boolean
147
+ relationModel?: string
148
+ }
149
+
150
+ const Relation = {
151
+ ToOne: '1:1',
152
+ ToMany: '1:n',
153
+ lookup:'查找'
154
+ }
155
+
156
+ const getLength = (length) => {
157
+ return length >= 8 ? length : 8
158
+ }
159
+
160
+ export const register = ({ colors }) => {
161
+ G6.registerEdge('console-line', {
162
+
163
+ // afterDraw(cfg, group) {
164
+ // // get the first shape in the group, it is the edge's path here=
165
+ // const shape = group.get('children')[0];
166
+ // // the start position of the edge's path
167
+ // const startPoint = shape.getPoint(0);
168
+
169
+ // // add red circle shape
170
+ // const circle = group.addShape('circle', {
171
+ // attrs: {
172
+ // x: startPoint.x,
173
+ // y: startPoint.y,
174
+ // fill: '#1890ff',
175
+ // r: 6,
176
+ // text: 'aaa',
177
+ // },
178
+ // name: 'circle-shape',
179
+ // });
180
+
181
+ // // animation for the red circle
182
+ // circle.animate(
183
+ // ratio => {
184
+ // // the operations in each frame. Ratio ranges from 0 to 1 indicating the prograss of the animation. Returns the modified configurations
185
+ // // get the position on the edge according to the ratio
186
+ // const tmpPoint = shape.getPoint(ratio);
187
+ // // returns the modified configurations here, x and y here
188
+ // return {
189
+ // x: tmpPoint.x,
190
+ // y: tmpPoint.y,
191
+ // };
192
+ // },
193
+ // {
194
+ // repeat: true, // Whether executes the animation repeatly
195
+ // duration: 3000, // the duration for executing once
196
+ // },
197
+ // );
198
+ // },
199
+
200
+
201
+ labelAutoRotate: true,
202
+ // update(a,b,c) {
203
+ // console.log(a,b,c)
204
+ // }
205
+ update: null,
206
+ }, 'cubic')
207
+
208
+ G6.registerEdge('console-arrange-line', {
209
+ labelAutoRotate: true,
210
+ update: null,
211
+ }, 'cubic')
212
+
213
+ G6.registerEdge('console-loop', {
214
+ afterDraw(cfg, group) {
215
+ // get the first shape in the group, it is the edge's path here=
216
+ const shape = group.get('children')[0];
217
+ // the start position of the edge's path
218
+ const startPoint = shape.getPoint(0);
219
+
220
+ // add red circle shape
221
+ const circle = group.addShape('circle', {
222
+ attrs: {
223
+ x: startPoint.x,
224
+ y: startPoint.y,
225
+ fill: '#1890ff',
226
+ r: 6,
227
+ },
228
+ name: 'circle-shape',
229
+ });
230
+
231
+ // animation for the red circle
232
+ circle.animate(
233
+ ratio => {
234
+ // the operations in each frame. Ratio ranges from 0 to 1 indicating the prograss of the animation. Returns the modified configurations
235
+ // get the position on the edge according to the ratio
236
+ const tmpPoint = shape.getPoint(ratio);
237
+ // returns the modified configurations here, x and y here
238
+ return {
239
+ x: tmpPoint.x,
240
+ y: tmpPoint.y,
241
+ };
242
+ },
243
+ {
244
+ repeat: true, // Whether executes the animation repeatly
245
+ duration: 3000, // the duration for executing once
246
+ },
247
+ );
248
+ },
249
+ }, 'console-loop')
250
+
251
+ G6.registerNode('console-model-Node', {
252
+ getAnchorPoints(cfg) {
253
+ const {
254
+ config,
255
+ data,
256
+ } = cfg
257
+ const {
258
+ fields,
259
+ } = data
260
+ const h = config.headerHeight + getLength(fields.length) * config.fieldHeight
261
+ return [[0, config.headerHeight / 2 / h], // 左上方
262
+ [1, config.headerHeight / 2 / h], // 右上方
263
+ ...fields.map((field, index) => {
264
+ const x = 10 / config.width
265
+ const l = config.headerHeight + config.fieldHeight * (index + 1) - config.fieldHeight / 2
266
+ const y = l / h
267
+ return [x, y]
268
+ }), ...fields.map((field, index) => {
269
+ const x = (config.width - 10) / config.width
270
+ const l = config.headerHeight + config.fieldHeight * (index + 1) - config.fieldHeight / 2
271
+ const y = l / h
272
+ return [x, y]
273
+ }),
274
+ ...getTopAnch(50)
275
+ // ...getBottomAnch(50),
276
+ // ...getLeftAnch(100),
277
+ // ...getRightAnch(100),
278
+ ]
279
+ },
280
+
281
+ allRender(cfg: IModelNodeShapeCfg, item) {
282
+ // cfg.data.store
283
+ },
284
+
285
+ update(cfg: IModelNodeShapeCfg, item, state) {
286
+ // console.log(cfg.data.key)
287
+ const {
288
+ isKeySharp,
289
+ active,
290
+ selected,
291
+ into,
292
+ inactive,
293
+ isCardSharp,
294
+ out,
295
+ isNoModule,
296
+ showNameOrLabel
297
+ } = cfg
298
+ const group = item.getContainer()
299
+ const children = group.get('children')
300
+ children.forEach((s) => {
301
+ const id = s.attr('id')
302
+
303
+ this.allRender(cfg, s)
304
+
305
+ // setNodeStateAttr('default', s, cfg)
306
+ // isNoModule && setNodeStateAttr('isNoModule', s , cfg)
307
+ s.attr('opacity', isNoModule ? 0.3 : 1)
308
+
309
+ switch (id) {
310
+ case 'keySharp':
311
+ // s.attr('fill', cfg.isKeySharp ? '#191919' : 'white')
312
+ // fill: '#CCFFFF',
313
+ // stroke: 'red',
314
+ // opacity: 0.2,
315
+ setNodeStateAttr('default', s, cfg)
316
+ // isNoModule && setNodeStateAttr('isNoModule', s , cfg)
317
+
318
+ inactive && setNodeStateAttr('inactive', s, cfg)
319
+ active && setNodeStateAttr('active', s, cfg)
320
+ selected && setNodeStateAttr('selected', s, cfg)
321
+ into && setNodeStateAttr('into', s, cfg)
322
+ out && setNodeStateAttr('out', s, cfg)
323
+ // const pointWidth = 200
324
+ if (isCardSharp) {
325
+ setNodeStateAttr('cardSharp', s, cfg)
326
+ // if (!s.attr('old_height')) {
327
+ // s.attr('old_height', s.attr('height'))
328
+ // }
329
+ // s.attr('height', pointWidth)
330
+ // if (!s.attr('old_width')) {
331
+ // s.attr('old_width', s.attr('width'))
332
+ // }
333
+ // s.attr('width', pointWidth)
334
+
335
+ if (!s.attr('old_fill')) {
336
+ s.attr('old_fill', s.attr('fill'))
337
+ }
338
+ s.attr('fill', cfg.data.aggregateRoot ? colors.blue : colors.head)
339
+
340
+ } else {
341
+ // if (s.attr('old_height')) {
342
+ // s.attr('height', s.attr('old_height'))
343
+ // }
344
+ // if (s.attr('old_width')) {
345
+ // s.attr('width', s.attr('old_width'))
346
+ // }
347
+
348
+ if (s.attr('old_fill')) {
349
+ s.attr('fill', s.attr('old_fill'))
350
+ }
351
+ }
352
+ break
353
+
354
+ case 'headerlabel1.1':
355
+ case 'headerlabel1.2':
356
+ // s.attr('opacity', !cfg.isKeySharp && active ? 1 : 0)
357
+ s.set('visible', !cfg.isKeySharp && active && !cfg.isCardSharp)
358
+ // s.attr('opacity', inactive && !into && !out && !active ? 0.2 : 1)
359
+ break
360
+
361
+ case 'headerlabel0':
362
+ case 'headerlabel1':
363
+ s.set('visible', !cfg.isKeySharp && !cfg.isCardSharp)
364
+ const fieldLable1 = s.attr('fieldLable')
365
+ if(fieldLable1) {
366
+ s.attr('text', showNameOrLabel ? fieldLable1 : s.attr('nameLable'))
367
+ }
368
+ // s.attr('opacity', 1)
369
+ break
370
+ case 'header':
371
+ // s.attr('opacity', !cfg.isKeySharp ? 1 : 0)
372
+ //selected && setNodeStateAttr('selected', s, cfg)
373
+ s.attr('fill', selected ? 'rgba(11,108,149)' : colors.blue)
374
+ s.set('visible', !cfg.isCardSharp)
375
+ // s.attr('opacity', 1)
376
+ break
377
+
378
+ case 'headerlabel2':
379
+ case 'headerlabel3':
380
+ // s.attr('opacity', cfg.isKeySharp ? 1 : 0)
381
+ // s.attr('opacity', inactive && !into && !out && !active ? 0.2 : 1)
382
+ const _showNameOrLabel = s.get('showNameOrLabel')
383
+ if(_showNameOrLabel && showNameOrLabel) {
384
+ s.set('visible', cfg.isKeySharp && !cfg.isCardSharp)
385
+ } else {
386
+ if(!_showNameOrLabel && !showNameOrLabel)
387
+ s.set('visible', cfg.isKeySharp && !cfg.isCardSharp)
388
+ else {
389
+ s.set('visible', false)
390
+ }
391
+ }
392
+
393
+ break
394
+
395
+ case 'field':
396
+ // s.attr('opacity', !cfg.isKeySharp && !s.attr('fieldHoverShow') ? 0.9 : 0)
397
+
398
+ const isInactive = inactive && !into && !out && !active ? 0.2 : 1
399
+ const isO = !cfg.isKeySharp && !s.attr('fieldHoverShow') ? isInactive : 0
400
+ // s.attr('opacity', isO)
401
+ s.set('visible', !cfg.isKeySharp) // Object.entries(cfg.config.styleConfig.active.node).forEach(([k, v]) => {
402
+ // s.attr(k, v)
403
+ // })
404
+ const fieldLable = s.attr('fieldLable')
405
+ if(fieldLable) {
406
+ s.attr('text', showNameOrLabel ? fieldLable : s.attr('nameLable'))
407
+ }
408
+
409
+ break
410
+
411
+ case 'field-text':
412
+ // s.attr('opacity', inactive && !into && !out && !active ? 0.2 : 1)
413
+ // s.attr('opacity', !cfg.isKeySharp ? 1 : 0)
414
+ s.set('visible', !cfg.isKeySharp) // active && setNodeStateAttr('active', s , cfg)
415
+ // selected && setNodeStateAttr('selected', s , cfg)
416
+
417
+ break
418
+
419
+ default: break
420
+ }
421
+ }) // this.render(cfg, group)
422
+
423
+ if (cfg.hide) {
424
+ item.hide()
425
+ } else {
426
+ item.show()
427
+ }
428
+ },
429
+
430
+ // shouldUpdate(type) {
431
+ // alert(type)
432
+ // return false
433
+ // },
434
+ afterDraw(cfg, group) {
435
+ if (cfg.hide) {
436
+ group.hide()
437
+ }
438
+ },
439
+
440
+ render: (cfg: IModelNodeShapeCfg, group) => {
441
+ const {
442
+ config,
443
+ data,
444
+ showNameOrLabel
445
+ } = cfg
446
+
447
+ data.aggregateRoot = true
448
+
449
+ const bg = data.aggregateRoot ? colors.blue : colors.head
450
+ const font = data.aggregateRoot ? colors.white : colors.blue
451
+ const mFront = data.aggregateRoot ? colors.white : colors.black
452
+
453
+ const nodeColors = { bg , font, mFront }
454
+
455
+ group.addShape('rect', {
456
+ visible: false,
457
+ name: data.key,
458
+ draggable: true,
459
+ attrs: {
460
+ y: -(getLength(data.fields.length) * config.fieldHeight / 2) - config.headerHeight / 2 ,
461
+ x: -(config.width / 2) ,
462
+ width: config.width ,
463
+ height: config.headerHeight,
464
+ radius: [10, 10, 0, 0],
465
+ // text: data.label,
466
+ id: 'header',
467
+ // fontSize: config.fieldHeight - 12,
468
+ // opacity: !cfg.isKeySharp ? 1 : 0,
469
+ className: 'header',
470
+ shadowColor: 'rgba(0,0,0,0.06)',
471
+ cursor: 'move',
472
+ // shadowBlur: 1,
473
+ // shadowOffsetX: 1,
474
+ // shadowOffsetY: 2,
475
+ // radius: [2, 4],
476
+ fill: nodeColors.bg,
477
+ },
478
+ })
479
+
480
+ // group.addShape('text', {
481
+ // visible: !cfg.isKeySharp,
482
+ // name: data.key,
483
+ // fontFamily: '',
484
+ // draggable: true,
485
+ // attrs: {
486
+ // fontFamily: 'iconFont',
487
+ // x: -(config.width / 2) + 20,
488
+ // y: -(getLength(data.fields.length) * config.fieldHeight / 2),
489
+ // text: '😎',
490
+ // // text: '\ue6b2',
491
+ // id: 'headerlabel1',
492
+ // cursor: 'move',
493
+ // fontSize: config.headerHeight / 2,
494
+ // // opacity: !cfg.isKeySharp ? 1 : 0,
495
+ // className: 'headerlabel',
496
+ // textBaseline: 'middle',
497
+ // textAlign: 'left',
498
+ // // radius: [2, 4],
499
+ // fill: nodeColors.font,
500
+ // },
501
+ // })
502
+
503
+ group.addShape('text', {
504
+ visible: !cfg.isKeySharp,
505
+ name: data.key,
506
+ fontFamily: '',
507
+ draggable: true,
508
+ attrs: {
509
+ // fontFamily: 'iconFont',
510
+ x: -(config.width / 2) + 20 ,
511
+ y: -(getLength(data.fields.length) * config.fieldHeight / 2),
512
+ text: showNameOrLabel ? data.key : data.label,
513
+ fieldLable: data.key,
514
+ nameLable: data.label,
515
+ // text: '\ue6b2',
516
+ id: 'headerlabel1',
517
+ cursor: 'move',
518
+ fontSize: config.fieldHeight / 2 ,
519
+ // opacity: !cfg.isKeySharp ? 1 : 0,
520
+ className: 'headerlabel',
521
+ textBaseline: 'middle',
522
+ textAlign: 'left',
523
+ fontWeight: 20,
524
+ // radius: [2, 4],
525
+ fill: nodeColors.mFront,
526
+ },
527
+ })
528
+
529
+ // cfg.data.aggregateModelKey && group.addShape('text', {
530
+ // visible: cfg.data.aggregateModelKey,
531
+ // name: data.key,
532
+ // fontFamily: '',
533
+ // draggable: true,
534
+ // attrs: {
535
+ // fontFamily: 'iconFont',
536
+ // x: (config.width / 2) - 100,
537
+ // y: -(getLength(data.fields.length) * config.fieldHeight / 2),
538
+ // text: '聚合关系',
539
+ // arg: cfg.data.aggregateModelKey,
540
+ // // text: cfg.data.aggregateModelKey,
541
+ // // text: '\ue6b2',
542
+ // id: 'headerlabel1',
543
+ // cursor: 'pointer',
544
+ // click: 'arrangeShow',
545
+ // // cursor: 'move',
546
+ // fontSize: config.labelSize,
547
+ // // opacity: !cfg.isKeySharp ? 1 : 0,
548
+ // className: 'headerlabel',
549
+ // textBaseline: 'middle',
550
+ // textAlign: 'left',
551
+ // // radius: [2, 4],
552
+ // fill: nodeColors.font,
553
+ // },
554
+ // })
555
+
556
+ group.addShape('text', {
557
+ visible: !cfg.isKeySharp,
558
+ name: data.key,
559
+ fontFamily: '',
560
+ draggable: true,
561
+ attrs: {
562
+ fontFamily: 'iconFont',
563
+ x: (config.width / 2) - 40,
564
+ y: -(getLength(data.fields.length) * config.fieldHeight / 2),
565
+ text: '查看',
566
+ // text: '\ue6b2',
567
+ id: 'headerlabel1',
568
+ cursor: 'pointer',
569
+ click: 'modelEdit',
570
+ // cursor: 'move',
571
+ fontSize: config.labelSize,
572
+ // opacity: !cfg.isKeySharp ? 1 : 0,
573
+ className: 'headerlabel',
574
+ textBaseline: 'middle',
575
+ textAlign: 'left',
576
+ // radius: [2, 4],
577
+ fill: nodeColors.font,
578
+ },
579
+ })
580
+
581
+ // group.addShape('text', {
582
+ // visible: !cfg.isKeySharp,
583
+ // attrs: {
584
+ // x: config.width / 2 - 40,
585
+ // y: -(data.fields.length * config.fieldHeight / 2),
586
+ // text: '✎',
587
+ // click: 'modelEdit',
588
+ // fontSize: config.headerHeight - 6,
589
+ // id: 'headerlabel1.1',
590
+ // className: 'headerlabel',
591
+ // textBaseline: 'middle',
592
+ // textAlign: 'left',
593
+ // cursor: 'pointer',
594
+ // fill: 'black',
595
+ // },
596
+ // })
597
+
598
+ // group.addShape('text', {
599
+ // visible: !cfg.isKeySharp,
600
+ // attrs: {
601
+ // x: (config.width) / 2 - 40 ,
602
+ // y: -((data.fields.length * config.fieldHeight) / 2) ,
603
+ // text: '✘',
604
+ // click: 'modelDel',
605
+ // id: 'headerlabel1.2',
606
+ // fontSize: config.headerHeight - 6 ,
607
+ // className: 'headerlabel',
608
+ // textBaseline: 'middle',
609
+ // textAlign: 'left',
610
+ // cursor: 'pointer',
611
+ // fill: 'red',
612
+ // },
613
+ // })
614
+ // group.addShape('text', {
615
+ // visible: cfg.isKeySharp,
616
+ // attrs: {
617
+ // x: 0,
618
+ // y: -(config.headerHeight + data.fields.length * config.fieldHeight) / 6,
619
+ // fontSize: config.width * 2 / (getLen(data.name)),
620
+ // text: data.name ,
621
+ // opacity: cfg.isKeySharp ? 1 : 0,
622
+ // id: 'headerlabel2',
623
+ // className: 'headerlabel',
624
+ // textBaseline: 'middle',
625
+ // textAlign: 'center',
626
+ // // radius: [2, 4],
627
+ // fill: 'black',
628
+ // },
629
+ // })
630
+
631
+ // const nameList = ((data.name.replace(/\(/, '-').replace(/\)/, '')) || '').split('_').flatMap((nameStr) => nameStr.split('-')).flatMap((nameStr) => nameStr.split('/')).flatMap((a) => getSplitStrings(a)).filter((a) => a)
632
+ const nameList = [data.name]
633
+ const height = config.headerHeight + (data.fields.length >= 12 ? data.fields.length : 12) * config.fieldHeight
634
+ const nameLength = nameList.length
635
+ nameList.forEach((nameText, index) => {
636
+ group.addShape('text', {
637
+ visible: cfg.isKeySharp && !showNameOrLabel,
638
+ name: nameText,
639
+ showNameOrLabel: false,
640
+ draggable: true,
641
+ attrs: {
642
+ x: 0,
643
+ y: - height / 2 + height / (nameLength + 1) * (index + 1),
644
+ fontSize: config.width / 5,
645
+ text: nameText,
646
+ // opacity: index === nameLength - 1 ? 1 : 0.3,
647
+ id: 'headerlabel2',
648
+ className: 'headerlabel',
649
+ textBaseline: 'middle',
650
+ textAlign: 'center',
651
+ // radius: [2, 4],
652
+ fill: 'black',
653
+ },
654
+ })
655
+ })
656
+
657
+ // const nameList1 = ((data.key.replace(/\(/, '-').replace(/\)/, '')) || '').split('_').flatMap((nameStr) => nameStr.split('-')).flatMap((nameStr) => nameStr.split('/')).flatMap((a) => getSplitStrings(a)).filter((a) => a)
658
+ const nameList1 = [data.key]
659
+ const height1 = config.headerHeight + (data.fields.length >= 12 ? data.fields.length : 12) * config.fieldHeight
660
+ const nameLength1 = nameList.length
661
+ nameList1.forEach((nameText, index) => {
662
+ group.addShape('text', {
663
+ visible: cfg.isKeySharp && showNameOrLabel,
664
+ showNameOrLabel: true,
665
+ name: nameText,
666
+ draggable: true,
667
+ attrs: {
668
+ x: 0,
669
+ y: - height1 / 2 + height1 / (nameLength1 + 1) * (index + 1),
670
+ fontSize: config.width / 5,
671
+ text: nameText,
672
+ // opacity: index === nameLength - 1 ? 1 : 0.3,
673
+ id: 'headerlabel2',
674
+ className: 'headerlabel',
675
+ textBaseline: 'middle',
676
+ textAlign: 'center',
677
+ // radius: [2, 4],
678
+ fill: 'black',
679
+ },
680
+ })
681
+ })
682
+
683
+
684
+ // group.addShape('text', {
685
+ // visible: cfg.isKeySharp,
686
+ // attrs: {
687
+ // x: 0,
688
+ // y: (config.headerHeight + data.fields.length * config.fieldHeight) / 6,
689
+ // fontSize: 20,
690
+ // text: data.key,
691
+ // id: 'headerlabel3',
692
+ // opacity: cfg.isKeySharp ? 1 : 0,
693
+ // className: 'headerlabel',
694
+ // textBaseline: 'middle',
695
+ // textAlign: 'center',
696
+ // // radius: [2, 4],
697
+ // fill: 'black',
698
+ // },
699
+ // })
700
+ // group.addShape('text', {
701
+ // attrs: {
702
+ // x: (config.width),
703
+ // y: (config.headerHeight + data.fields.length * config.fieldHeight) / 6,
704
+ // fontSize: 20,
705
+ // text: data.key,
706
+ // id: 'headerlabel4',
707
+ // opacity: cfg.isKeySharp ? 1 : 0,
708
+ // className: 'headerlabel',
709
+ // textBaseline: 'middle',
710
+ // textAlign: 'center',
711
+ // // radius: [2, 4],
712
+ // fill: 'black',
713
+ // },
714
+ // })
715
+
716
+ data.fields.forEach((field, index) => {
717
+ const {
718
+ relationModel,
719
+ type,
720
+ isForeign,
721
+ required,
722
+ } = field
723
+
724
+ const hasCircle = isForeign || required
725
+
726
+ const y = -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * index + config.fieldHeight / 2 - 2
727
+ group.addShape('rect', {
728
+ visible: !cfg.isKeySharp,
729
+ name: field.key,
730
+ draggable: true,
731
+ attrs: {
732
+ x: -(config.width / 2) + 2 ,
733
+ fieldName: field.key,
734
+ name: field.key,
735
+ draggable: true,
736
+ fieldBg: true,
737
+ arg: field.originalKey,
738
+ fieldHover: true,
739
+ y: -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * index,
740
+ // stroke: 'black',
741
+ width: config.width - 4,
742
+ id: 'field',
743
+ height: config.fieldHeight,
744
+ // click: 'fieldEdit',
745
+ // radius: [2, 4],
746
+ // fill: field.isForeign ? '#dee1e6' : 'white',
747
+ // ...cfg.style || {},
748
+ // fill: field.isForeign ? '#dee1e6' : 'white',
749
+ fill: 'white',
750
+ cursor: 'move',
751
+ // ...cfg.style || {},
752
+ },
753
+ })
754
+
755
+ group.addShape('path', {
756
+ // visible: !cfg.isKeySharp,
757
+ draggable: true,
758
+ name: field.key,
759
+ attrs: {
760
+ draggable: true,
761
+ fieldName: field.key,
762
+ name: field.key,
763
+ // startArrow: {
764
+ // path: 'M 10,0 L -10,-10 L -10,10 Z', // 自定义箭头为中心点在(0, 0),指向 x 轴正方向的path
765
+ // d: 10,
766
+ // },
767
+ // endArrow: {
768
+ // path: 'M 10,0 L -10,-10 L -10,10 Z', // 自定义箭头为中心点在(0, 0),指向 x 轴正方向的path
769
+ // d: 10,
770
+ // },
771
+ path: [
772
+ [ 'M', - config.width / 2 + 20, y + 2 ],
773
+ [ 'L', config.width / 2 - 40 , y + 2 ],
774
+ ],
775
+ // stroke: colors.head,
776
+ stroke: colors.head,
777
+ // stroke: isForeign ? colors.blue : colors.head,
778
+ lineWidth: 1,
779
+ lineDash: [ 5, 5 ],
780
+ opacity: 0.1,
781
+ },
782
+ })
783
+
784
+ isForeign && group.addShape('circle', {
785
+ visible: false,
786
+ name: field.key,
787
+ draggable: true,
788
+ attrs: {
789
+ x: -(config.width / 2) + 10,
790
+ fieldName: field.key,
791
+ name: field.key,
792
+ draggable: true,
793
+ arg: field.originalKey,
794
+ fieldHover: true,
795
+ y: -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * index + config.fieldHeight / 2 - 2 ,
796
+ // stroke: 'black',
797
+ // width: 4,
798
+ id: 'field',
799
+ r: 2,
800
+ // height: 4,
801
+ // click: 'fieldEdit',
802
+ // radius: [2, 4],
803
+ // fill: field.isForeign ? '#dee1e6' : 'white',
804
+ // ...cfg.style || {},
805
+ // fill: field.isForeign ? '#dee1e6' : 'white',
806
+ fill: required ? 'red' : '#dee1e6',
807
+ cursor: 'move',
808
+ // ...cfg.style || {},
809
+ },
810
+ })
811
+
812
+ group.addShape('text', {
813
+ visible: !cfg.isKeySharp,
814
+ name: field.key,
815
+ draggable: true,
816
+ attrs: {
817
+ x: -config.width / 2 + 20,
818
+ fieldHover: true,
819
+ name: field.key,
820
+ draggable: true,
821
+ // click: 'fieldEdit',
822
+ y: -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * index + config.fieldHeight / 2,
823
+ text: showNameOrLabel? field.originalKey : field.label,
824
+ fieldName: field.key,
825
+ arg: field.originalKey,
826
+ fontSize: config.labelSize,
827
+ textBaseline: 'middle',
828
+ cursor: 'move',
829
+ id: 'field',
830
+ fieldLable: field.originalKey,
831
+ nameLable: field.label,
832
+ textAlign: 'start',
833
+ // opacity: !cfg.isKeySharp ? 1 : 0,
834
+ // radius: [2, 4],
835
+ fill: required ? 'red' : ('black'), // fill: 'rgb(153,153,153)',
836
+ // fill: field.isForeign ? 'black' : 'black',
837
+
838
+ },
839
+ })
840
+ // group.addShape('text', {
841
+ // visible: !cfg.isKeySharp,
842
+ // name: field.key,
843
+ // draggable: true,
844
+ // attrs: {
845
+ // x: -config.width / 2 + 20,
846
+ // fieldHover: true,
847
+ // name: field.key,
848
+ // draggable: true,
849
+ // // click: 'fieldEdit',
850
+ // y: -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * index + config.fieldHeight / 2,
851
+ // text: field.originalKey,
852
+ // fieldName: field.key,
853
+ // arg: field.originalKey,
854
+ // fontSize: config.labelSize,
855
+ // textBaseline: 'middle',
856
+ // cursor: 'move',
857
+ // id: 'field',
858
+ // textAlign: 'start',
859
+ // // opacity: !cfg.isKeySharp ? 1 : 0,
860
+ // // radius: [2, 4],
861
+ // fill: required ? 'red' : ('rgba(0,0,0,0.60)'), // fill: 'rgb(153,153,153)',
862
+ // // fill: field.isForeign ? 'black' : 'black',
863
+
864
+ // },
865
+ // })
866
+ const RelationType = Relation[field.type] || field.type
867
+ const text = isForeign ?( field.type && RelationType ? `${RelationType}(${relationModel ||''})` : relationModel) : `${field.type || ''}`
868
+ group.addShape('text', {
869
+ visible: !cfg.isKeySharp,
870
+ name: field.key,
871
+ draggable: true,
872
+ attrs: {
873
+ x: config.width / 2 - 20,
874
+ fieldHover: !isForeign,
875
+
876
+ // click: 'fieldEdit',
877
+ y: -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * index + config.fieldHeight / 2,
878
+ text,
879
+ id: 'field',
880
+ textBaseline: 'middle',
881
+ fieldName: field.key,
882
+ arg: field,
883
+ fontSize: config.labelSize,
884
+ click: isForeign ? 'fieldSelect' : undefined,
885
+ textAlign: 'right',
886
+ cursor: isForeign ? 'pointer' : 'undefined',
887
+ // opacity: !cfg.isKeySharp ? 1 : 0,
888
+ // radius: [2, 4],
889
+ // fill: field.isForeign ? 'black' : 'black',
890
+ fill: ('rgba(11,108,149)'),
891
+ },
892
+ })
893
+ // group.addShape('text', {
894
+ // visible: !cfg.isKeySharp,
895
+ // name: field.key,
896
+ // draggable: true,
897
+ // attrs: {
898
+
899
+ // x: config.width / 2 - 30,
900
+ // y: -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * index + config.fieldHeight / 2,
901
+ // text: '✎',
902
+ // click: 'fieldEdit',
903
+ // arg: field.originalKey,
904
+ // fieldHoverShow: true,
905
+ // fieldHover: true,
906
+ // fieldName: field.key,
907
+ // fontSize: config.fieldHeight - 16,
908
+ // // fontSize: config.headerHeight - 6 ,
909
+ // id: 'field',
910
+ // // cursor: 'pointer',
911
+ // opacity: 0,
912
+ // // className: 'headerlabel',
913
+ // textBaseline: 'middle',
914
+ // textAlign: 'left',
915
+ // cursor: 'pointer',
916
+ // // radius: [2, 4],
917
+ // fill: 'black',
918
+ // },
919
+ // })
920
+
921
+ isForeign && group.addShape('circle', {
922
+ visible: false,
923
+ name: field.key,
924
+ draggable: true,
925
+ attrs: {
926
+ x: config.width / 2 - 10,
927
+ fieldName: field.key,
928
+ name: field.key,
929
+ draggable: true,
930
+ arg: field.originalKey,
931
+ fieldHover: true,
932
+ y: -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * index + config.fieldHeight / 2 - 2,
933
+ // stroke: 'black',
934
+ // width: 4,
935
+ id: 'field',
936
+ r: 2,
937
+ // height: 4,
938
+ // click: 'fieldEdit',
939
+ // radius: [2, 4],
940
+ // fill: field.isForeign ? '#dee1e6' : 'white',
941
+ // ...cfg.style || {},
942
+ // fill: field.isForeign ? '#dee1e6' : 'white',
943
+ // fill: required ? 'red' : ('rgba(11,108,149)'),
944
+ fill: ('rgba(11,108,149)'),
945
+ cursor: 'move',
946
+ // ...cfg.style || {},
947
+ },
948
+ })
949
+
950
+ })
951
+
952
+ // const h = config.headerHeight + data.fields.length * config.fieldHeight
953
+
954
+ const diffLength = getLength(data.fields.length) - data.fields.length
955
+ if (diffLength) {
956
+ for (let i = 0 ; i < diffLength ; i ++) {
957
+ // ---
958
+ group.addShape('rect', {
959
+ name: i,
960
+ draggable: true,
961
+ visible: !cfg.isKeySharp,
962
+ attrs: {
963
+ x: -(config.width / 2) + 2,
964
+ // fieldBg: true,
965
+ // fieldHover: true,
966
+ y: -((config.headerHeight + getLength(data.fields.length) * config.fieldHeight) / 2) + config.headerHeight + config.fieldHeight * (data.fields.length + i),
967
+ // stroke: 'black',
968
+ width: config.width - 4,
969
+ id: 'field',
970
+ height: config.fieldHeight,
971
+ // click: 'fieldEdit',
972
+ // radius: [2, 4],
973
+ // fill: field.isForeign ? '#dee1e6' : 'white',
974
+ // ...cfg.style || {},
975
+ // fill: field.isForeign ? '#dee1e6' : 'white',
976
+ fill: 'white',
977
+ cursor: 'move',
978
+ // ...cfg.style || {},
979
+ },
980
+
981
+ // ---
982
+ })
983
+ }
984
+ }
985
+
986
+ // const anchors = [
987
+ // [0, 0], // 左上方
988
+ // ...data.fields.map((_, i) => {
989
+ // if (_.isForeign) {
990
+ // const x = 0
991
+ // const l = config.headerHeight + data.fields.length * (i + 1)
992
+ // const y = l / h
993
+ // return [x, y, i]
994
+ // } else return null
995
+ // }),
996
+ // ].filter((a) => a)
997
+ // group.addShape('circle', {
998
+ // attrs: {
999
+ // x: -config.width / 2,
1000
+ // y: (config.headerHeight / 2) - h / 2,
1001
+ // r: 2,
1002
+ // fill: 'green',
1003
+ // },
1004
+ // })
1005
+ // anchors.forEach(([x, y, i ]) => {
1006
+ // group.addShape('circle', {
1007
+ // attrs: {
1008
+ // x: -config.width / 2,
1009
+ // y: (config.headerHeight + config.fieldHeight * (i) + (config.fieldHeight / 2)) - h / 2,
1010
+ // r: 2,
1011
+ // fill: 'red',
1012
+ // },
1013
+ // })
1014
+ // })
1015
+ },
1016
+
1017
+ setState(name, value, item) {// const names = name.split('-')
1018
+ // if (names[0] === 'fieldHover' && value) {
1019
+ // let target = null
1020
+ // item.getContainer().findAll((sharp) => sharp.attr('fieldBg')).forEach((sharp) => {
1021
+ // if (sharp.attr('fieldName') === names[1]) target = sharp
1022
+ // if (sharp.attr('fill-old')) {
1023
+ // sharp.attr('fill', sharp.attr('fill-old'))
1024
+ // sharp.attr('fill-old', undefined)
1025
+ // }
1026
+ // })
1027
+ // if (target) {
1028
+ // if (!target.attr('fill-old')) {
1029
+ // target.attr('fill-old', target.attr('fill'))
1030
+ // }
1031
+ // target.attr('fill', 'blue')
1032
+ // }
1033
+ // }
1034
+ },
1035
+
1036
+ draw: function drawShape(cfg: IModelNodeShapeCfg, group) {
1037
+ const {
1038
+ config,
1039
+ data,
1040
+ } = cfg
1041
+ const height = config.headerHeight + getLength(data.fields.length) * config.fieldHeight
1042
+
1043
+ // group.addShape('rect', {
1044
+ // name: data.key,
1045
+ // draggable: true,
1046
+ // attrs: {
1047
+ // id: 'keySharpBord',
1048
+ // x: -(config.width / 2),
1049
+ // y: - height / 2,
1050
+ // width: config.width,
1051
+ // cursor: 'move',
1052
+ // stroke: colors.blue,
1053
+ // // opacity: 0.85,
1054
+ // height,
1055
+ // ...cfg.config.styleConfig.default.node,
1056
+ // },
1057
+ // })
1058
+
1059
+ let keyShape = group.addShape('rect', {
1060
+ name: data.key,
1061
+ draggable: true,
1062
+ attrs: {
1063
+ id: 'keySharp',
1064
+ x: -(config.width / 2) ,
1065
+ y: - height / 2,
1066
+ width: config.width,
1067
+ cursor: 'move',
1068
+
1069
+ // opacity: 0.85,
1070
+ height : height + 10,
1071
+ ...cfg.config.styleConfig.default.node,
1072
+
1073
+ },
1074
+ })
1075
+
1076
+ this.render(cfg, group)
1077
+ return keyShape
1078
+ },
1079
+ }, 'single-shape')
1080
+ }