@mx-sose-front/mx-sose-graph 1.1.8 → 1.2.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 (180) hide show
  1. package/dist/assets/edgeWorker-b57ca007.js +2 -0
  2. package/dist/assets/edgeWorker-b57ca007.js.map +1 -0
  3. package/dist/index.d.ts +994 -31
  4. package/dist/index.esm.js +9541 -5145
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/index.umd.js +1 -1
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/style.css +1 -1
  9. package/package.json +1 -1
  10. package/src/components/Common/Tree.vue +451 -0
  11. package/src/components/Common/index.ts +2 -0
  12. package/src/components/DiagramListTooltip/DiagramListTooltip.vue +1 -2
  13. package/src/components/Edge/Edge.vue +172 -169
  14. package/src/components/Gantt/Gantt.vue +1544 -0
  15. package/src/components/GanttContextMenu/GanttContextMenu.vue +304 -0
  16. package/src/components/InteractionLayer.vue +343 -147
  17. package/src/components/Matrix/Matrix.vue +808 -0
  18. package/src/components/Matrix/index.ts +168 -0
  19. package/src/components/Shape/ConceptualRole.vue +2 -34
  20. package/src/components/Table/Table.vue +1193 -0
  21. package/src/constants/edgeShapeKeys.ts +8 -5
  22. package/src/constants/index.ts +279 -51
  23. package/src/hooks/index.ts +2 -0
  24. package/src/hooks/useChartRowSelection.ts +456 -0
  25. package/src/hooks/useResize.ts +2 -2
  26. package/src/hooks/useVirtualScroll.ts +258 -0
  27. package/src/index.ts +1 -1
  28. package/src/render/shape-renderer.ts +62 -2
  29. package/src/statics/icons/childIcons/AV-1/346/246/202/350/277/260/344/270/216/346/221/230/350/246/201/344/277/241/346/201/257/345/214/205@3x.png +0 -0
  30. package/src/statics/icons/childIcons/AV-1/346/246/202/350/277/260/346/221/230/350/246/201/345/233/276@3x.png +0 -0
  31. package/src/statics/icons/childIcons/AV-2/351/233/206/346/210/220/345/255/227/345/205/270/345/214/205@3x.png +0 -0
  32. package/src/statics/icons/childIcons/AV-2/351/233/206/346/210/220/345/255/227/345/205/270/350/241/250@3x.png +0 -0
  33. package/src/statics/icons/childIcons/CV-1/346/204/277/346/231/257/345/214/205@3x.png +0 -0
  34. package/src/statics/icons/childIcons/CV-1/346/204/277/346/231/257/345/233/276@3x.png +0 -0
  35. package/src/statics/icons/childIcons/CV-2/350/203/275/345/212/233/345/210/206/347/261/273/345/214/205@3x.png +0 -0
  36. package/src/statics/icons/childIcons/CV-2/350/203/275/345/212/233/345/210/206/347/261/273/345/233/276@3x-2.png +0 -0
  37. package/src/statics/icons/childIcons/CV-2/350/203/275/345/212/233/345/210/206/347/261/273/345/233/276@3x-3.png +0 -0
  38. package/src/statics/icons/childIcons/CV-2/350/203/275/345/212/233/345/210/206/347/261/273/345/233/276@3x.png +0 -0
  39. package/src/statics/icons/childIcons/CV-3/350/203/275/345/212/233/345/210/206/346/256/265/345/214/205@3x.png +0 -0
  40. package/src/statics/icons/childIcons/CV-3/350/203/275/345/212/233/351/230/266/346/256/265/347/224/230/347/211/271/345/233/276@3x.png +0 -0
  41. package/src/statics/icons/childIcons/CV-4/350/203/275/345/212/233/344/276/235/350/265/226/345/214/205@3x.png +0 -0
  42. package/src/statics/icons/childIcons/CV-4/350/203/275/345/212/233/344/276/235/350/265/226/345/233/276@3x.png +0 -0
  43. package/src/statics/icons/childIcons/CV-5/350/203/275/345/212/233/345/210/260/347/273/204/347/273/207/347/232/204/345/274/200/345/217/221/346/230/240/345/260/204/345/214/205@3x.png +0 -0
  44. package/src/statics/icons/childIcons/CV-5/350/203/275/345/212/233/345/210/260/347/273/204/347/273/207/347/232/204/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
  45. package/src/statics/icons/childIcons/CV-6/350/203/275/345/212/233/345/210/260/344/270/232/345/212/241/346/264/273/345/212/250/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
  46. package/src/statics/icons/childIcons/CV-6/350/203/275/345/212/233/345/210/260/344/275/234/346/210/230/346/264/273/345/212/250/347/232/204/346/230/240/345/260/204/345/214/205@3x.png +0 -0
  47. package/src/statics/icons/childIcons/CV-7/350/203/275/345/212/233/345/210/260/346/234/215/345/212/241/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
  48. package/src/statics/icons/childIcons/CV-7/350/203/275/345/212/233/345/210/260/346/234/215/345/212/241/347/232/204/346/230/240/345/260/204/345/214/205@3x.png +0 -0
  49. package/src/statics/icons/childIcons/DIV-1/346/246/202/345/277/265/346/225/260/346/215/256/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  50. package/src/statics/icons/childIcons/DIV-1/346/246/202/345/277/265/346/225/260/346/215/256/346/250/241/345/236/213/345/233/276@3x.png +0 -0
  51. package/src/statics/icons/childIcons/DIV-2/351/200/273/350/276/221/346/225/260/346/215/256/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  52. package/src/statics/icons/childIcons/DIV-2/351/200/273/350/276/221/346/225/260/346/215/256/346/250/241/345/236/213/345/233/276@3x.png +0 -0
  53. package/src/statics/icons/childIcons/DIV-3/347/211/251/347/220/206/346/225/260/346/215/256/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  54. package/src/statics/icons/childIcons/OV-1/350/207/252/347/224/261/345/210/206/347/261/273/345/233/276@3x.png +0 -0
  55. package/src/statics/icons/childIcons/OV-1/351/253/230/347/272/247/344/275/234/346/210/230/346/246/202/345/277/265/345/233/276@3x.png +0 -0
  56. package/src/statics/icons/childIcons/OV-1/351/253/230/347/272/247/344/275/234/346/210/230/346/246/202/345/277/265/345/233/276/345/214/205@3x.png +0 -0
  57. package/src/statics/icons/childIcons/OV-2/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/345/206/205/351/203/250/346/217/217/350/277/260/345/233/276@3x-2.png +0 -0
  58. package/src/statics/icons/childIcons/OV-2/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/345/206/205/351/203/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  59. package/src/statics/icons/childIcons/OV-2/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  60. package/src/statics/icons/childIcons/OV-2/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  61. package/src/statics/icons/childIcons/OV-3/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265@3x.png +0 -0
  62. package/src/statics/icons/childIcons/OV-3/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  63. package/src/statics/icons/childIcons/OV-3/345/237/272/347/241/200/350/247/222/350/211/262/344/275/234/346/210/230/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265@3x.png +0 -0
  64. package/src/statics/icons/childIcons/OV-4/347/273/204/347/273/207/345/205/263/347/263/273/345/233/276@3x.png +0 -0
  65. package/src/statics/icons/childIcons/OV-4/347/273/204/347/273/207/345/205/263/347/263/273/345/233/276/345/214/205@3x.png +0 -0
  66. package/src/statics/icons/childIcons/OV-5a/344/275/234/346/210/230/346/264/273/345/212/250/345/210/206/350/247/243/346/240/221/345/214/205@3x.png +0 -0
  67. package/src/statics/icons/childIcons/OV-5a/344/275/234/346/210/230/346/264/273/345/212/250/345/210/206/350/247/243/346/240/221/345/233/276@3x.png +0 -0
  68. package/src/statics/icons/childIcons/OV-5b/344/275/234/346/210/230/346/264/273/345/212/250/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  69. package/src/statics/icons/childIcons/OV-5b/344/275/234/346/210/230/346/264/273/345/212/250/346/250/241/345/236/213/345/233/276@3x.png +0 -0
  70. package/src/statics/icons/childIcons/OV-6a/344/275/234/346/210/230/350/247/204/345/210/231/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  71. package/src/statics/icons/childIcons/OV-6a/344/275/234/346/210/230/350/265/204/346/272/220/345/217/202/346/225/260/345/233/276@3x.png +0 -0
  72. package/src/statics/icons/childIcons/OV-6b/347/212/266/346/200/201/350/275/254/346/215/242/345/233/276@3x.png +0 -0
  73. package/src/statics/icons/childIcons/OV-6b/347/212/266/346/200/201/350/275/254/346/215/242/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  74. package/src/statics/icons/childIcons/OV-6c/344/272/213/344/273/266/350/277/275/350/270/252/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  75. package/src/statics/icons/childIcons/OV-6c/344/275/234/346/210/230/344/272/213/344/273/266/350/267/237/350/270/252/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  76. package/src/statics/icons/childIcons/PV-1/351/241/271/347/233/256/347/273/204/345/220/210/345/205/263/347/263/273/345/214/205@3x.png +0 -0
  77. package/src/statics/icons/childIcons/PV-1/351/241/271/347/233/256/347/273/204/345/220/210/345/205/263/347/263/273/345/233/276@3x.png +0 -0
  78. package/src/statics/icons/childIcons/PV-2/351/241/271/347/233/256/346/227/266/351/227/264/350/277/233/345/272/246/345/214/205@3x.png +0 -0
  79. package/src/statics/icons/childIcons/PV-2/351/241/271/347/233/256/346/227/266/351/227/264/350/277/233/345/272/246/347/224/230/347/211/271/345/233/276@3x.png +0 -0
  80. package/src/statics/icons/childIcons/PV-3/351/241/271/347/233/256/344/270/216/350/203/275/345/212/233/346/230/240/345/260/204/347/237/251/351/230/265@3x.png +0 -0
  81. package/src/statics/icons/childIcons/PV-3/351/241/271/347/233/256/344/270/216/350/203/275/345/212/233/347/232/204/346/230/240/345/260/204/345/214/205@3x.png +0 -0
  82. package/src/statics/icons/childIcons/SV-1 /347/263/273/347/273/237/346/216/245/345/217/243/345/206/205/351/203/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  83. package/src/statics/icons/childIcons/SV-1 /347/263/273/347/273/237/346/216/245/345/217/243/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  84. package/src/statics/icons/childIcons/SV-10a /347/263/273/347/273/237/345/217/202/346/225/260/345/233/276@3x.png +0 -0
  85. package/src/statics/icons/childIcons/SV-10a /347/263/273/347/273/237/350/247/204/345/210/231/346/250/241/345/236/213/350/241/250@3x.png +0 -0
  86. package/src/statics/icons/childIcons/SV-10a/347/263/273/347/273/237/350/247/204/345/210/231/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  87. package/src/statics/icons/childIcons/SV-10b /347/263/273/347/273/237/347/212/266/346/200/201/350/275/254/346/215/242/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  88. package/src/statics/icons/childIcons/SV-10b/347/263/273/347/273/237/347/212/266/346/200/201/350/275/254/346/215/242/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  89. package/src/statics/icons/childIcons/SV-10c /347/263/273/347/273/237/344/272/213/344/273/266/350/267/237/350/270/252/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  90. package/src/statics/icons/childIcons/SV-10c/347/263/273/347/273/237/344/272/213/344/273/266-/350/277/275/350/270/252/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  91. package/src/statics/icons/childIcons/SV-1/347/263/273/347/273/237/346/216/245/345/217/243/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  92. package/src/statics/icons/childIcons/SV-2 /347/263/273/347/273/237/345/206/205/351/203/250/350/265/204/346/272/220/346/265/201/345/212/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  93. package/src/statics/icons/childIcons/SV-2 /347/263/273/347/273/237/350/265/204/346/272/220/346/265/201/345/212/250/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  94. package/src/statics/icons/childIcons/SV-2/347/263/273/347/273/237/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  95. package/src/statics/icons/childIcons/SV-3 /347/263/273/347/273/237 - /347/263/273/347/273/237/347/237/251/351/230/265@3x.png +0 -0
  96. package/src/statics/icons/childIcons/SV-3/347/263/273/347/273/237-/347/263/273/347/273/237/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  97. package/src/statics/icons/childIcons/SV-4 /347/263/273/347/273/237/345/212/237/350/203/275/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  98. package/src/statics/icons/childIcons/SV-4 /347/263/273/347/273/237/345/212/237/350/203/275/346/265/201/347/250/213/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  99. package/src/statics/icons/childIcons/SV-4/347/263/273/347/273/237/345/212/237/350/203/275/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  100. package/src/statics/icons/childIcons/SV-5a /344/270/232/345/212/241/346/264/273/345/212/250/345/210/260/347/263/273/347/273/237/345/212/237/350/203/275/347/232/204/345/217/257/350/277/275/346/272/257/346/200/247/347/237/251/351/230/265@3x.png +0 -0
  101. package/src/statics/icons/childIcons/SV-5a/344/275/234/346/210/230/346/264/273/345/212/250/345/210/260/347/263/273/347/273/237/345/212/237/350/203/275/345/217/257/350/277/275/350/270/252/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  102. package/src/statics/icons/childIcons/SV-5b /344/270/232/345/212/241/346/264/273/345/212/250/345/210/260/347/263/273/347/273/237/347/232/204/345/217/257/350/277/275/346/272/257/346/200/247/347/237/251/351/230/265@3x.png +0 -0
  103. package/src/statics/icons/childIcons/SV-5b/344/275/234/346/210/230/346/264/273/345/212/250/345/210/260/347/263/273/347/273/237/345/217/257/350/277/275/350/270/252/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  104. package/src/statics/icons/childIcons/SV-6 /347/263/273/347/273/237/350/265/204/346/272/220/346/265/201/345/212/250/347/237/251/351/230/265@3x.png +0 -0
  105. package/src/statics/icons/childIcons/SV-6/347/263/273/347/273/237/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  106. package/src/statics/icons/childIcons/SV-7 /347/263/273/347/273/237/345/256/236/351/231/205/345/272/246/351/207/217/347/237/251/351/230/265@3x.png +0 -0
  107. package/src/statics/icons/childIcons/SV-7/347/263/273/347/273/237/345/272/246/351/207/217/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  108. package/src/statics/icons/childIcons/SV-8 /347/263/273/347/273/237/346/274/224/350/277/233/346/217/217/350/277/260/347/224/230/347/211/271/345/233/276@3x.png +0 -0
  109. package/src/statics/icons/childIcons/SV-8/347/263/273/347/273/237/346/274/224/350/277/233/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  110. package/src/statics/icons/childIcons/SV-9 /347/263/273/347/273/237/346/212/200/346/234/257/344/270/216/346/212/200/350/203/275/351/242/204/346/265/213/350/241/250@3x.png +0 -0
  111. package/src/statics/icons/childIcons/SV-9/347/263/273/347/273/237/346/212/200/346/234/257/344/270/216/346/212/200/350/203/275/351/242/204/346/265/213/345/214/205@3x.png +0 -0
  112. package/src/statics/icons/childIcons/StdV-1 /346/240/207/345/207/206/351/205/215/347/275/256/350/241/250@3x.png +0 -0
  113. package/src/statics/icons/childIcons/StdV-1/346/240/207/345/207/206/351/205/215/347/275/256/346/226/207/344/273/266/345/214/205@3x.png +0 -0
  114. package/src/statics/icons/childIcons/StdV-2 /346/240/207/345/207/206/351/242/204/346/265/213/350/241/250@3x.png +0 -0
  115. package/src/statics/icons/childIcons/StdV-2/346/240/207/345/207/206/351/242/204/346/265/213/345/214/205@3x.png +0 -0
  116. package/src/statics/icons/childIcons/SvcV-10a /346/234/215/345/212/241/345/217/202/346/225/260/345/233/276@3x.png +0 -0
  117. package/src/statics/icons/childIcons/SvcV-10a/346/234/215/345/212/241/350/247/204/345/210/231/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  118. package/src/statics/icons/childIcons/SvcV-10b /346/234/215/345/212/241/347/212/266/346/200/201/350/275/254/346/215/242/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  119. package/src/statics/icons/childIcons/SvcV-10b/346/234/215/345/212/241/347/212/266/346/200/201/350/275/254/346/215/242/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  120. package/src/statics/icons/childIcons/SvcV-10c /346/234/215/345/212/241/344/272/213/344/273/266/350/267/237/350/270/252/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  121. package/src/statics/icons/childIcons/SvcV-10c/346/234/215/345/212/241/344/272/213/344/273/266-/350/277/275/350/270/252/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  122. package/src/statics/icons/childIcons/SvcV-1/346/234/215/345/212/241/344/270/212/344/270/213/346/226/207/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  123. package/src/statics/icons/childIcons/SvcV-1/346/234/215/345/212/241/350/203/214/346/231/257/346/250/241/345/236/213/345/214/205@3x.png +0 -0
  124. package/src/statics/icons/childIcons/SvcV-2 /346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  125. package/src/statics/icons/childIcons/SvcV-2/346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  126. package/src/statics/icons/childIcons/SvcV-3a /347/263/273/347/273/237 -/346/234/215/345/212/241/347/237/251/351/230/265@3x-2.png +0 -0
  127. package/src/statics/icons/childIcons/SvcV-3a /347/263/273/347/273/237 -/346/234/215/345/212/241/347/237/251/351/230/265@3x.png +0 -0
  128. package/src/statics/icons/childIcons/SvcV-3a/347/263/273/347/273/237-/346/234/215/345/212/241/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  129. package/src/statics/icons/childIcons/SvcV-3b/346/234/215/345/212/241-/346/234/215/345/212/241/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  130. package/src/statics/icons/childIcons/SvcV-4 /346/234/215/345/212/241/345/212/237/350/203/275/346/217/217/350/277/260/345/233/276@3x.png +0 -0
  131. package/src/statics/icons/childIcons/SvcV-4 /346/234/215/345/212/241/345/212/237/350/203/275/346/265/201/345/233/276@3x.png +0 -0
  132. package/src/statics/icons/childIcons/SvcV-4/346/234/215/345/212/241/345/212/237/350/203/275/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  133. package/src/statics/icons/childIcons/SvcV-5/344/275/234/346/210/230/346/264/273/345/212/250/345/210/260/346/234/215/345/212/241/345/217/257/350/277/275/350/270/252/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  134. package/src/statics/icons/childIcons/SvcV-6 /346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265@3x.png +0 -0
  135. package/src/statics/icons/childIcons/SvcV-6/346/234/215/345/212/241/350/265/204/346/272/220/346/265/201/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  136. package/src/statics/icons/childIcons/SvcV-7 /346/234/215/345/212/241/345/205/270/345/236/213/345/272/246/351/207/217/347/237/251/351/230/265@3x.png +0 -0
  137. package/src/statics/icons/childIcons/SvcV-7/346/234/215/345/212/241/345/272/246/351/207/217/347/237/251/351/230/265/345/214/205@3x.png +0 -0
  138. package/src/statics/icons/childIcons/SvcV-8 /346/234/215/345/212/241/346/274/224/350/277/233/347/224/230/347/211/271/345/233/276@3x.png +0 -0
  139. package/src/statics/icons/childIcons/SvcV-8/346/234/215/345/212/241/346/274/224/350/277/233/346/217/217/350/277/260/345/214/205@3x.png +0 -0
  140. package/src/statics/icons/childIcons/SvcV-9 /346/234/215/345/212/241/346/212/200/346/234/257/344/270/216/346/212/200/350/203/275/351/242/204/346/265/213/350/241/250@3x.png +0 -0
  141. package/src/statics/icons/childIcons/SvcV-9/346/234/215/345/212/241/346/212/200/346/234/257/344/270/216/346/212/200/350/203/275/351/242/204/346/265/213/345/214/205@3x.png +0 -0
  142. package/src/statics/icons/childIcons//344/275/223/347/263/273/346/236/266/346/236/204@3x.png +0 -0
  143. package/src/statics/icons/childIcons//344/275/234/346/210/230/350/247/206/350/247/222@3x.png +0 -0
  144. package/src/statics/icons/childIcons//345/205/250/346/231/257/350/247/206/350/247/222@3x.png +0 -0
  145. package/src/statics/icons/childIcons//345/205/254/345/217/270@3x.png +0 -0
  146. package/src/statics/icons/childIcons//345/215/217/350/256/256@3x.png +0 -0
  147. package/src/statics/icons/childIcons//345/215/217/350/256/256/345/261/202@3x.png +0 -0
  148. package/src/statics/icons/childIcons//345/215/217/350/256/256/346/240/210@3x.png +0 -0
  149. package/src/statics/icons/childIcons//345/221/275/344/273/244@3x.png +0 -0
  150. package/src/statics/icons/childIcons//346/210/230/347/225/245/346/246/202/345/277/265/350/241/250@3x.png +0 -0
  151. package/src/statics/icons/childIcons//346/216/247/345/210/266@3x.png +0 -0
  152. package/src/statics/icons/childIcons//346/224/257/346/214/201@3x.png +0 -0
  153. package/src/statics/icons/childIcons//346/225/260/346/215/256/344/277/241/346/201/257/350/247/206/350/247/222@3x.png +0 -0
  154. package/src/statics/icons/childIcons//346/234/215/345/212/241/350/247/206/350/247/222@3x.png +0 -0
  155. package/src/statics/icons/childIcons//346/240/207/345/207/206@3x.png +0 -0
  156. package/src/statics/icons/childIcons//346/240/207/345/207/206/350/247/206/350/247/222@3x.png +0 -0
  157. package/src/statics/icons/childIcons//347/263/273/347/273/237/350/247/206/350/247/222@3x.png +0 -0
  158. package/src/statics/icons/childIcons//350/203/275/345/212/233/350/247/206/350/247/222@3x.png +0 -0
  159. package/src/statics/icons/childIcons//351/241/271/347/233/256/350/247/206/350/247/222@3x.png +0 -0
  160. package/src/statics/icons/createMenu/down.png +0 -0
  161. package/src/statics/icons/createMenu/remove.png +0 -0
  162. package/src/statics/icons/createMenu/up.png +0 -0
  163. package/src/store/graphStore.ts +238 -45
  164. package/src/types/index.ts +87 -4
  165. package/src/utils/batchAutoExpand.ts +9 -10
  166. package/src/utils/containers.ts +72 -17
  167. package/src/utils/contextMenuUtils.ts +7 -7
  168. package/src/utils/dateUtils.ts +160 -0
  169. package/src/utils/diagram.ts +10 -8
  170. package/src/utils/drag.ts +6 -5
  171. package/src/utils/edgeUtils.ts +344 -427
  172. package/src/utils/edgeWorker.ts +471 -0
  173. package/src/utils/hittest.ts +37 -38
  174. package/src/utils/index.ts +3 -0
  175. package/src/utils/keyboardUtils.ts +5 -5
  176. package/src/utils/packageOutline.ts +96 -0
  177. package/src/utils/rafThrottle.ts +162 -0
  178. package/src/utils/workerManager.ts +335 -0
  179. package/src/view/graph.vue +47 -33
  180. /package/src/statics/icons/childIcons//346/210/230/347/225/{245@3x.png" → 245/345/261/202@3x.png"} +0 -0
@@ -1,30 +1,59 @@
1
1
  // edge-utils.ts
2
- import type { Shape } from "../types";
2
+ import type { Shape, Waypoint } from "../types";
3
3
  import { pickTarget } from "./hittest";
4
4
  import { useGraphStore } from '../store/graphStore';
5
5
  import { snapPinToParentEdge } from './pinUtils';
6
6
  import type { IHighlightUtils } from "../hooks/useHighlight";
7
+ import { workerManager } from './workerManager';
7
8
 
8
9
 
9
10
  export class EdgeUtils {
10
11
  /**
11
- * 更新与指定图元相关的连线端点
12
+ * 更新与指定图元相关的连线端点(同步版本)
12
13
  * @param shapes 所有图元
13
14
  * @param changedIds 发生变化的图元ID列表
14
15
  * @param updateShape 更新图元的回调函数
16
+ * @param edgeIndex 可选,nodeId → 关联 edges 的索引(来自 graphStore.edgesByNodeId)
17
+ * @param shapeMapIndex 可选,id → Shape 的索引(来自 graphStore.shapeMap)
15
18
  */
16
19
  static updateRelatedEdges(
17
20
  shapes: Shape[],
18
21
  changedIds: string[],
19
- updateShape: (shape: Shape) => void
22
+ updateShape: (shape: Shape) => void,
23
+ edgeIndex?: Map<string, Shape[]>,
24
+ shapeMapIndex?: Map<string, Shape>
20
25
  ) {
21
- const edges = shapes.filter((shape) => shape.shapeType === "edge");
26
+ // 收集与 changedIds 相关的所有 edge(去重)
27
+ let relatedEdges: Shape[]
28
+ if (edgeIndex) {
29
+ const seen = new Set<string>()
30
+ relatedEdges = []
31
+ for (const id of changedIds) {
32
+ const edges = edgeIndex.get(id)
33
+ if (edges) {
34
+ for (const e of edges) {
35
+ if (!seen.has(e.id)) {
36
+ seen.add(e.id)
37
+ relatedEdges.push(e)
38
+ }
39
+ }
40
+ }
41
+ }
42
+ } else {
43
+ // 回退:全量 filter
44
+ relatedEdges = shapes.filter((shape) => shape.shapeType === "edge")
45
+ }
46
+
47
+ // 用于 O(1) 查找 source/target shape
48
+ const findShape = shapeMapIndex
49
+ ? (id: string) => shapeMapIndex.get(id) ?? null
50
+ : (id: string) => shapes.find(s => s.id === id) ?? null
22
51
 
23
52
  // 按源-目标对分组,为每组中的线条生成不同的偏移
24
53
  // 同时处理反向连接(A→B 和 B→A)的情况
25
54
  const edgeGroups = new Map<string, Shape[]>();
26
55
 
27
- edges.forEach((edge) => {
56
+ relatedEdges.forEach((edge) => {
28
57
  if (edge.sourceId && edge.targetId) {
29
58
  // 创建源-目标对的规范化键(确保 A-B 和 B-A 使用相同的键)
30
59
  const isForward = edge.sourceId.localeCompare(edge.targetId) <= 0;
@@ -39,76 +68,28 @@ export class EdgeUtils {
39
68
  }
40
69
  });
41
70
 
71
+ const changedSet = new Set(changedIds)
72
+
42
73
  // 处理每个分组
43
74
  edgeGroups.forEach((groupEdges, groupKey) => {
44
75
  if (groupEdges.length > 1) {
45
76
  // 如果同一源-目标对有多个线条,为每条线生成不同的偏移
46
77
  groupEdges.forEach((edge, index) => {
47
- const sourceChanged = edge.sourceId && changedIds.includes(edge.sourceId);
48
- const targetChanged = edge.targetId && changedIds.includes(edge.targetId);
78
+ const sourceChanged = edge.sourceId && changedSet.has(edge.sourceId);
79
+ const targetChanged = edge.targetId && changedSet.has(edge.targetId);
49
80
 
50
81
  if (sourceChanged || targetChanged) {
51
- const sourceShape = shapes.find((s) => s.id === edge.sourceId);
52
- const targetShape = shapes.find((s) => s.id === edge.targetId);
82
+ const sourceShape = edge.sourceId ? findShape(edge.sourceId) : null;
83
+ const targetShape = edge.targetId ? findShape(edge.targetId) : null;
53
84
 
54
85
  if (sourceShape && targetShape && sourceShape.bounds && targetShape.bounds) {
55
- // 计算基本连接点
56
- const { x: sx = 0, y: sy = 0, width: sw = 0, height: sh = 0 } = sourceShape.bounds;
57
- const { x: tx = 0, y: ty = 0, width: tw = 0, height: th = 0 } = targetShape.bounds;
58
-
59
- // 计算中心点
60
- const sourceCenter = { x: sx + sw / 2, y: sy + sh / 2 };
61
- const targetCenter = { x: tx + tw / 2, y: ty + th / 2 };
62
-
63
- // 计算连接方向
64
- const dx = targetCenter.x - sourceCenter.x;
65
- const dy = targetCenter.y - sourceCenter.y;
66
-
67
- // 生成基于索引的偏移量(小到不会明显影响,但足以分开线条)
68
- const offsetDistance = 5 * (index + 1);
69
-
70
- // 根据方向计算偏移方向
71
- let offsetX = 0, offsetY = 0;
72
- if (Math.abs(dx) > Math.abs(dy)) {
73
- // 水平方向为主,垂直偏移
74
- offsetY = offsetDistance;
75
- } else {
76
- // 垂直方向为主,水平偏移
77
- offsetX = offsetDistance;
78
- }
79
-
80
- // 确保线条交替偏移方向,避免全部偏向一侧
81
- if (index % 2 === 1) {
82
- offsetX = -offsetX;
83
- offsetY = -offsetY;
84
- }
85
-
86
- // 确定连接点,添加偏移
87
- let sourcePoint, targetPoint;
88
-
89
- if (Math.abs(dx) > Math.abs(dy)) {
90
- // 水平方向
91
- sourcePoint = dx > 0
92
- ? { x: sx + sw, y: sourceCenter.y + offsetY }
93
- : { x: sx, y: sourceCenter.y + offsetY };
94
-
95
- targetPoint = dx > 0
96
- ? { x: tx, y: targetCenter.y + offsetY }
97
- : { x: tx + tw, y: targetCenter.y + offsetY };
98
- } else {
99
- // 垂直方向
100
- sourcePoint = dy > 0
101
- ? { x: sourceCenter.x + offsetX, y: sy + sh }
102
- : { x: sourceCenter.x + offsetX, y: sy };
103
-
104
- targetPoint = dy > 0
105
- ? { x: targetCenter.x + offsetX, y: ty }
106
- : { x: targetCenter.x + offsetX, y: ty + th };
107
- }
108
-
109
- // 更新连线,只使用源点和目标点确保线条保持直线
110
- // 通过调整端点位置而不是添加中间点来避免线条重叠
111
- const waypoints = [sourcePoint, targetPoint];
86
+ // 使用最短距离边中点算法(与 completeConnection 一致)
87
+ const { waypoints } = this.buildEdgeWaypoints(
88
+ sourceShape.bounds,
89
+ targetShape.bounds,
90
+ index,
91
+ sourceShape.id === targetShape.id
92
+ );
112
93
 
113
94
  const updatedEdge = {
114
95
  ...edge,
@@ -120,54 +101,27 @@ export class EdgeUtils {
120
101
  }
121
102
  });
122
103
  } else {
123
- // 单线条情况,使用原有的逻辑
104
+ // 单线条情况
124
105
  const edge = groupEdges[0];
125
- const sourceChanged = edge.sourceId && changedIds.includes(edge.sourceId);
126
- const targetChanged = edge.targetId && changedIds.includes(edge.targetId);
106
+ const sourceChanged = edge.sourceId && changedSet.has(edge.sourceId);
107
+ const targetChanged = edge.targetId && changedSet.has(edge.targetId);
127
108
 
128
109
  if (sourceChanged || targetChanged) {
129
- const sourceShape = shapes.find((s) => s.id === edge.sourceId);
130
- const targetShape = shapes.find((s) => s.id === edge.targetId);
110
+ const sourceShape = edge.sourceId ? findShape(edge.sourceId) : null;
111
+ const targetShape = edge.targetId ? findShape(edge.targetId) : null;
131
112
 
132
113
  if (sourceShape && targetShape && sourceShape.bounds && targetShape.bounds) {
133
- const { x: sx = 0, y: sy = 0, width: sw = 0, height: sh = 0 } = sourceShape.bounds;
134
- const { x: tx = 0, y: ty = 0, width: tw = 0, height: th = 0 } = targetShape.bounds;
135
-
136
- // 计算中心点
137
- const sourceCenter = { x: sx + sw / 2, y: sy + sh / 2 };
138
- const targetCenter = { x: tx + tw / 2, y: ty + th / 2 };
139
-
140
- // 计算连接方向
141
- const dx = targetCenter.x - sourceCenter.x;
142
- const dy = targetCenter.y - sourceCenter.y;
143
-
144
- // 确定连接点
145
- let sourcePoint, targetPoint;
146
-
147
- if (Math.abs(dx) > Math.abs(dy)) {
148
- // 水平方向
149
- sourcePoint = dx > 0
150
- ? { x: sx + sw, y: sourceCenter.y }
151
- : { x: sx, y: sourceCenter.y };
152
-
153
- targetPoint = dx > 0
154
- ? { x: tx, y: targetCenter.y }
155
- : { x: tx + tw, y: targetCenter.y };
156
- } else {
157
- // 垂直方向
158
- sourcePoint = dy > 0
159
- ? { x: sourceCenter.x, y: sy + sh }
160
- : { x: sourceCenter.x, y: sy };
161
-
162
- targetPoint = dy > 0
163
- ? { x: targetCenter.x, y: ty }
164
- : { x: targetCenter.x, y: ty + th };
165
- }
114
+ // 使用最短距离边中点算法(与 completeConnection 一致),index=0 无偏移
115
+ const { waypoints } = this.buildEdgeWaypoints(
116
+ sourceShape.bounds,
117
+ targetShape.bounds,
118
+ 0,
119
+ sourceShape.id === targetShape.id
120
+ );
166
121
 
167
- // 更新连线
168
122
  const updatedEdge = {
169
123
  ...edge,
170
- waypointId: JSON.stringify([sourcePoint, targetPoint]),
124
+ waypointId: JSON.stringify(waypoints),
171
125
  };
172
126
 
173
127
  updateShape(updatedEdge);
@@ -177,6 +131,46 @@ export class EdgeUtils {
177
131
  });
178
132
  }
179
133
 
134
+ /**
135
+ * 更新与指定图元相关的连线端点(异步版本,使用 Web Worker)
136
+ * 内置竞态控制:如果在 Worker 返回前又发起了新的调用,旧结果会被丢弃。
137
+ * @param shapes 所有图元
138
+ * @param changedIds 发生变化的图元ID列表
139
+ * @param updateShape 更新图元的回调函数
140
+ * @param edgeIndex 可选,nodeId → 关联 edges 的索引(来自 graphStore.edgesByNodeId)
141
+ * @param shapeMapIndex 可选,id → Shape 的索引(来自 graphStore.shapeMap)
142
+ */
143
+ static async updateRelatedEdgesAsync(
144
+ shapes: Shape[],
145
+ changedIds: string[],
146
+ updateShape: (shape: Shape) => void,
147
+ edgeIndex?: Map<string, Shape[]>,
148
+ shapeMapIndex?: Map<string, Shape>
149
+ ): Promise<void> {
150
+ try {
151
+ const { version, result: updatedEdges } = await workerManager.updateRelatedEdges(
152
+ shapes,
153
+ changedIds,
154
+ edgeIndex,
155
+ shapeMapIndex
156
+ );
157
+
158
+ // 竞态保护:只采纳最新版本的结果,丢弃过期计算
159
+ if (!workerManager.isLatestVersion('updateRelatedEdges', version)) {
160
+ return;
161
+ }
162
+
163
+ // 更新所有返回的边缘
164
+ updatedEdges.forEach((edge: Shape) => {
165
+ updateShape(edge);
166
+ });
167
+ } catch (error) {
168
+ console.error('Error in updateRelatedEdgesAsync:', error);
169
+ // 回退到同步版本
170
+ this.updateRelatedEdges(shapes, changedIds, updateShape, edgeIndex, shapeMapIndex);
171
+ }
172
+ }
173
+
180
174
  /**
181
175
  * 获取图形的四个中心点(上下左右)
182
176
  */
@@ -208,14 +202,153 @@ export class EdgeUtils {
208
202
  }
209
203
 
210
204
  /**
211
- * 找到距离鼠标位置最近的连接点
205
+ * 生成图元自连接时使用的半环路径。
206
+ * 路径使用正交折线,从图元上边中点出发,沿右侧绕到下边中点,
207
+ * 让自连接的观感更接近矩形转角线。
208
+ */
209
+ static buildSelfLoopWaypoints(
210
+ bounds: { x?: number; y?: number; width?: number; height?: number },
211
+ groupIndex: number = 0
212
+ ): {
213
+ sourcePoint: { x: number; y: number };
214
+ targetPoint: { x: number; y: number };
215
+ waypoints: Waypoint[];
216
+ } {
217
+ const safeBounds = {
218
+ x: bounds.x ?? 0,
219
+ y: bounds.y ?? 0,
220
+ width: bounds.width ?? 0,
221
+ height: bounds.height ?? 0,
222
+ };
223
+
224
+ const { x, y, width, height } = safeBounds;
225
+ const centerX = x + width / 2;
226
+ const sourcePoint = { x: centerX, y };
227
+ const targetPoint = { x: centerX, y: y + height };
228
+
229
+ // 保持上下抬升高度不变,只缩短右侧外扩距离,让右边那段线更贴近图元。
230
+ const outwardOffset = Math.max(width * 0.24, 20) + groupIndex * 12;
231
+ const verticalPadding = Math.max(height * 0.45, 26) + groupIndex * 10;
232
+ const upperPoint = {
233
+ x: centerX,
234
+ y: y - verticalPadding,
235
+ };
236
+ const upperRightPoint = {
237
+ x: x + width + outwardOffset,
238
+ y: y - verticalPadding,
239
+ };
240
+ const lowerRightPoint = {
241
+ x: x + width + outwardOffset,
242
+ y: y + height + verticalPadding,
243
+ };
244
+ const lowerPoint = {
245
+ x: centerX,
246
+ y: y + height + verticalPadding,
247
+ };
248
+
249
+ return {
250
+ sourcePoint,
251
+ targetPoint,
252
+ waypoints: [sourcePoint, upperPoint, upperRightPoint, lowerRightPoint, lowerPoint, targetPoint],
253
+ };
254
+ }
255
+
256
+ /**
257
+ * 统一生成边的折点数据。
258
+ * 普通连线仍使用最近边中点,自连接则走专用半环路径。
259
+ */
260
+ static buildEdgeWaypoints(
261
+ sBounds: { x?: number; y?: number; width?: number; height?: number },
262
+ tBounds: { x?: number; y?: number; width?: number; height?: number },
263
+ groupIndex: number,
264
+ isSelfLoop: boolean
265
+ ): {
266
+ sourcePoint: { x: number; y: number };
267
+ targetPoint: { x: number; y: number };
268
+ waypoints: Waypoint[];
269
+ } {
270
+ if (isSelfLoop) {
271
+ return this.buildSelfLoopWaypoints(sBounds, groupIndex);
272
+ }
273
+
274
+ const { sourcePoint, targetPoint } = this.calcBestEndpoints(
275
+ sBounds,
276
+ tBounds,
277
+ groupIndex
278
+ );
279
+
280
+ return {
281
+ sourcePoint,
282
+ targetPoint,
283
+ waypoints: [sourcePoint, targetPoint],
284
+ };
285
+ }
286
+
287
+ /**
288
+ * 计算两个图元之间的最佳连接端点(共用算法)
289
+ * 使用 4×4 边中点最短距离组合,与 completeConnection 保持一致。
290
+ * @param sBounds 源图元 bounds
291
+ * @param tBounds 目标图元 bounds
292
+ * @param groupIndex 同源-目标对中的索引,0 表示无偏移
293
+ */
294
+ static calcBestEndpoints(
295
+ sBounds: { x?: number; y?: number; width?: number; height?: number },
296
+ tBounds: { x?: number; y?: number; width?: number; height?: number },
297
+ groupIndex: number
298
+ ): { sourcePoint: { x: number; y: number }; targetPoint: { x: number; y: number } } {
299
+ const sb = { x: sBounds.x ?? 0, y: sBounds.y ?? 0, width: sBounds.width ?? 0, height: sBounds.height ?? 0 };
300
+ const tb = { x: tBounds.x ?? 0, y: tBounds.y ?? 0, width: tBounds.width ?? 0, height: tBounds.height ?? 0 };
301
+ const sourcePoints = this.getShapeCenterPoints(sb);
302
+ const targetPoints = this.getShapeCenterPoints(tb);
303
+
304
+ // 4×4 组合取最短距离
305
+ let minDist = Infinity;
306
+ let bestSrc = sourcePoints.top;
307
+ let bestTgt = targetPoints.top;
308
+ for (const sp of Object.values(sourcePoints)) {
309
+ for (const tp of Object.values(targetPoints)) {
310
+ const d = this.getDistance(sp, tp);
311
+ if (d < minDist) {
312
+ minDist = d;
313
+ bestSrc = sp;
314
+ bestTgt = tp;
315
+ }
316
+ }
317
+ }
318
+
319
+ // 多线偏移
320
+ if (groupIndex > 0) {
321
+ const dx = (tb.x + tb.width / 2) - (sb.x + sb.width / 2);
322
+ const dy = (tb.y + tb.height / 2) - (sb.y + sb.height / 2);
323
+ const offsetDistance = 5 * (groupIndex + 1);
324
+ let offsetX = 0, offsetY = 0;
325
+ if (Math.abs(dx) > Math.abs(dy)) {
326
+ offsetY = offsetDistance;
327
+ } else {
328
+ offsetX = offsetDistance;
329
+ }
330
+ if (groupIndex % 2 === 1) {
331
+ offsetX = -offsetX;
332
+ offsetY = -offsetY;
333
+ }
334
+ return {
335
+ sourcePoint: { x: bestSrc.x + offsetX, y: bestSrc.y + offsetY },
336
+ targetPoint: { x: bestTgt.x + offsetX, y: bestTgt.y + offsetY },
337
+ };
338
+ }
339
+
340
+ return { sourcePoint: bestSrc, targetPoint: bestTgt };
341
+ }
342
+
343
+ /**
344
+ * 找到距离鼠标位置最近的连接点(同步版本)
212
345
  */
213
346
  static findNearestConnectPoint(
214
347
  mousePos: { x: number; y: number },
215
348
  shape: Shape | undefined,
216
- diagramBounds: any
349
+ diagramBounds?: any
217
350
  ) {
218
- if (!shape?.bounds || !diagramBounds) return null;
351
+ if (!shape?.bounds) return null;
219
352
 
220
353
  const mouseX = mousePos.x;
221
354
  const mouseY = mousePos.y;
@@ -290,6 +423,22 @@ export class EdgeUtils {
290
423
  }
291
424
  }
292
425
 
426
+ /**
427
+ * 找到距离鼠标位置最近的连接点(异步版本,使用 Web Worker)
428
+ */
429
+ static async findNearestConnectPointAsync(
430
+ mousePos: { x: number; y: number },
431
+ shape: Shape | undefined
432
+ ): Promise<any> {
433
+ try {
434
+ return await workerManager.findNearestConnectPoint(mousePos, shape);
435
+ } catch (error) {
436
+ console.error('Error in findNearestConnectPointAsync:', error);
437
+ // 回退到同步版本(这里简化处理,不传递 diagramBounds)
438
+ return this.findNearestConnectPoint(mousePos, shape, null);
439
+ }
440
+ }
441
+
293
442
  /**
294
443
  * 完成连接操作,计算最终连接点
295
444
  */
@@ -298,223 +447,63 @@ export class EdgeUtils {
298
447
  targetShape: Shape,
299
448
  clickPoint: { x: number; y: number },
300
449
  currentConnectPoint: { x: number; y: number },
301
- shapes: Shape[] = [] // 添加shapes参数,避免在静态方法中使用组合式函数
450
+ shapes: Shape[] = []
302
451
  ) {
303
- // 如果源图元和目标图元是同一个,直接返回 null
304
- if (sourceShape?.id && targetShape.id && sourceShape.id === targetShape.id) {
305
- return null;
306
- }
307
-
452
+ // 自连接不再直接拦截,而是交给专用的半环路径逻辑处理。
308
453
  if (!targetShape.bounds || !sourceShape?.bounds) return null;
309
454
 
310
- // 计算源图元和目标图元的中心
311
- const { x: sx = 0, y: sy = 0, width: sw = 0, height: sh = 0 } = sourceShape.bounds;
312
- const { x: tx = 0, y: ty = 0, width: tw = 0, height: th = 0 } = targetShape.bounds;
313
-
314
- const sourceCenter = { x: sx + sw / 2, y: sy + sh / 2 };
315
- const targetCenter = { x: tx + tw / 2, y: ty + th / 2 };
316
-
317
- // 获取两个图元的所有边中点
318
- const sourcePoints = this.getShapeCenterPoints({
319
- x: sourceShape.bounds.x ?? 0,
320
- y: sourceShape.bounds.y ?? 0,
321
- width: sourceShape.bounds.width ?? 0,
322
- height: sourceShape.bounds.height ?? 0,
323
- });
324
- const targetPoints = this.getShapeCenterPoints({
325
- x: targetShape.bounds.x ?? 0,
326
- y: targetShape.bounds.y ?? 0,
327
- width: targetShape.bounds.width ?? 0,
328
- height: targetShape.bounds.height ?? 0,
329
- });
330
-
331
- // 找出源图元和目标图元之间距离最短的边中点组合
332
- let minDistance = Infinity;
333
- let bestSourcePoint = sourcePoints.top; // 默认值
334
- let bestTargetPoint = targetPoints.top; // 默认值
335
-
336
- // 遍历所有可能的源点和目标点组合
337
- Object.values(sourcePoints).forEach(sourcePoint => {
338
- Object.values(targetPoints).forEach(targetPoint => {
339
- const distance = this.getDistance(sourcePoint, targetPoint);
340
- if (distance < minDistance) {
341
- minDistance = distance;
342
- bestSourcePoint = sourcePoint;
343
- bestTargetPoint = targetPoint;
344
- }
345
- });
346
- });
347
-
348
- // 使用最短距离的点作为连接点
349
- const startPoint = bestSourcePoint;
350
- let targetPoint = bestTargetPoint;
351
-
352
- // 以下是原始代码,保留以处理特殊情况(如果需要的话)
353
- /*
354
- const { x = 0, y = 0, width = 0, height = 0 } = targetShape.bounds;
355
-
356
- const left = x;
357
- const right = x + width;
358
- const top = y;
359
- const bottom = y + height;
360
-
361
- const relativeX = clickPoint.x - x;
362
- const relativeY = clickPoint.y - y;
363
-
364
- const isInTopArea = relativeY < 0;
365
- const isInBottomArea = relativeY > height;
366
- const isInLeftArea = relativeX < 0;
367
- const isInRightArea = relativeX > width;
368
-
369
- if (isInTopArea) {
370
- const constrainedX = Math.max(left, Math.min(right, clickPoint.x));
371
- targetPoint = { x: constrainedX, y: top };
372
- } else if (isInBottomArea) {
373
- const constrainedX = Math.max(left, Math.min(right, clickPoint.x));
374
- targetPoint = { x: constrainedX, y: bottom };
375
- } else if (isInLeftArea) {
376
- const constrainedY = Math.max(top, Math.min(bottom, clickPoint.y));
377
- targetPoint = { x: left, y: constrainedY };
378
- } else if (isInRightArea) {
379
- const constrainedY = Math.max(top, Math.min(bottom, clickPoint.y));
380
- targetPoint = { x: right, y: constrainedY };
381
- } else {
382
- const distances = {
383
- top: Math.abs(clickPoint.y - top),
384
- bottom: Math.abs(clickPoint.y - bottom),
385
- left: Math.abs(clickPoint.x - left),
386
- right: Math.abs(clickPoint.x - right),
387
- };
388
-
389
- const nearestEdge = Object.entries(distances).reduce(
390
- (min, [key, distance]) =>
391
- distance < min.distance ? { key, distance } : min,
392
- { key: "top", distance: Infinity }
393
- );
394
-
395
- switch (nearestEdge.key) {
396
- case "top":
397
- targetPoint = { x: clickPoint.x, y: top };
398
- break;
399
- case "bottom":
400
- targetPoint = { x: clickPoint.x, y: bottom };
401
- break;
402
- case "left":
403
- targetPoint = { x: left, y: clickPoint.y };
404
- break;
405
- case "right":
406
- targetPoint = { x: right, y: clickPoint.y };
407
- break;
408
- default:
409
- targetPoint = { x: x + width / 2, y: y + height / 2 };
410
- }
411
- }
412
- */
413
-
414
- // 计算路径点 - 直接返回两点连线,保留转折逻辑作为注释
415
-
416
- // 检查是否已存在相同源和目标的边,以及反向连接的边,为新边添加偏移以避免重合
455
+ // 检查是否已存在相同源和目标的边,以及反向连接的边
417
456
  const existingEdges = shapes.filter(
418
457
  shape => shape.shapeType === 'edge' &&
419
458
  ((shape.sourceId === sourceShape?.id && shape.targetId === targetShape.id) ||
420
459
  (shape.sourceId === targetShape.id && shape.targetId === sourceShape?.id))
421
460
  );
422
-
423
- // 计算连接方向
424
- const dx = targetCenter.x - sourceCenter.x;
425
- const dy = targetCenter.y - sourceCenter.y;
426
-
427
- // 为新连线添加偏移量,避免与已存在的连线重叠
428
- let adjustedStartPoint = { ...startPoint };
429
- let adjustedEndPoint = { ...targetPoint };
430
-
431
- if (existingEdges.length > 0) {
432
- // 新连线的索引(从0开始)
433
- const index = existingEdges.length;
434
-
435
- // 生成基于索引的偏移量
436
- const offsetDistance = 5 * (index + 1);
437
-
438
- // 根据方向计算偏移方向
439
- let offsetX = 0, offsetY = 0;
440
- if (Math.abs(dx) > Math.abs(dy)) {
441
- // 水平方向为主,垂直偏移
442
- offsetY = offsetDistance;
443
- } else {
444
- // 垂直方向为主,水平偏移
445
- offsetX = offsetDistance;
446
- }
447
-
448
- // 确保线条交替偏移方向,避免全部偏向一侧
449
- if (index % 2 === 1) {
450
- offsetX = -offsetX;
451
- offsetY = -offsetY;
452
- }
453
-
454
- // 应用偏移量到连接点
455
- adjustedStartPoint = { x: startPoint.x + offsetX, y: startPoint.y + offsetY };
456
- adjustedEndPoint = { x: targetPoint.x + offsetX, y: targetPoint.y + offsetY };
457
- }
458
-
459
- // 使用调整后的点作为waypoints
460
- const waypoints = [adjustedStartPoint, adjustedEndPoint];
461
-
462
- /* 保留转折逻辑以备后续使用
463
- const deltaX = Math.abs(endPoint.x - startPoint.x);
464
- const deltaY = Math.abs(endPoint.y - startPoint.y);
465
-
466
- // 计算偏移量,每条现有边增加15px的偏移
467
- const offsetAmount = existingEdges.length * 15;
468
-
469
- waypoints = [startPoint];
470
- if (deltaX > 0 || deltaY > 0) {
471
- let midPoint;
472
-
473
- // 如果有现有边,使用偏移的路径以避免重合
474
- if (existingEdges.length > 0) {
475
- // 根据连接方向决定偏移方向
476
- if (deltaX <= deltaY) {
477
- // 垂直方向为主,水平偏移
478
- const offsetDir = existingEdges.length % 2 === 0 ? 1 : -1; // 交替偏移方向
479
- midPoint = {
480
- x: endPoint.x + offsetDir * offsetAmount,
481
- y: startPoint.y
482
- };
483
- } else {
484
- // 水平方向为主,垂直偏移
485
- const offsetDir = existingEdges.length % 2 === 0 ? 1 : -1; // 交替偏移方向
486
- midPoint = {
487
- x: startPoint.x,
488
- y: endPoint.y + offsetDir * offsetAmount
489
- };
490
- }
491
- } else {
492
- // 没有现有边,使用标准直角路径
493
- midPoint = deltaX <= deltaY
494
- ? { x: endPoint.x, y: startPoint.y }
495
- : { x: startPoint.x, y: endPoint.y };
496
- }
497
461
 
498
- if (midPoint.x !== startPoint.x || midPoint.y !== startPoint.y) {
499
- if (midPoint.x !== endPoint.x || midPoint.y !== endPoint.y) {
500
- waypoints.push(midPoint);
501
- }
502
- }
503
- }
504
- waypoints.push(endPoint);
505
- */
462
+ // groupIndex 用来区分同一对图元之间的多条边,自环也复用这一层偏移。
463
+ const groupIndex = existingEdges.length;
464
+ const { sourcePoint, targetPoint, waypoints } = this.buildEdgeWaypoints(
465
+ sourceShape.bounds,
466
+ targetShape.bounds,
467
+ groupIndex,
468
+ sourceShape.id === targetShape.id
469
+ );
506
470
 
507
471
  return {
508
472
  sourceId: sourceShape?.id,
509
473
  sourceModelId: sourceShape?.modelId,
510
474
  targetId: targetShape.id,
511
475
  targetModelId: targetShape.modelId,
512
- sourcePoint: adjustedStartPoint,
513
- targetPoint: adjustedEndPoint,
476
+ sourcePoint,
477
+ targetPoint,
514
478
  waypoints,
515
479
  };
516
480
  }
517
481
 
482
+ /**
483
+ * 完成连接操作,计算最终连接点(异步版本,使用 Web Worker)
484
+ */
485
+ static async completeConnectionAsync(
486
+ sourceShape: Shape | undefined,
487
+ targetShape: Shape,
488
+ clickPoint: { x: number; y: number },
489
+ currentConnectPoint: { x: number; y: number },
490
+ shapes: Shape[] = []
491
+ ): Promise<any> {
492
+ try {
493
+ return await workerManager.completeConnection(
494
+ sourceShape,
495
+ targetShape,
496
+ clickPoint,
497
+ currentConnectPoint,
498
+ shapes
499
+ );
500
+ } catch (error) {
501
+ console.error('Error in completeConnectionAsync:', error);
502
+ // 回退到同步版本
503
+ return this.completeConnection(sourceShape, targetShape, clickPoint, currentConnectPoint, shapes);
504
+ }
505
+ }
506
+
518
507
  /**
519
508
  * 计算线路径点
520
509
  * 当前实现:直接返回两点连线,暂时不添加转折点
@@ -582,7 +571,7 @@ export class EdgeUtils {
582
571
  if (!sourceShape?.bounds) return null;
583
572
 
584
573
  // 如果提供了鼠标位置,使用findNearestConnectPoint计算初始连接点
585
- if (initialMousePos && diagramBounds) {
574
+ if (initialMousePos) {
586
575
  // 直接使用传入的鼠标位置(屏幕坐标)调用findNearestConnectPoint
587
576
  // findNearestConnectPoint方法内部会进行坐标转换
588
577
  const nearestPoint = this.findNearestConnectPoint(initialMousePos, sourceShape, diagramBounds);
@@ -655,20 +644,24 @@ export class EdgeUtils {
655
644
  }
656
645
 
657
646
  /**
658
- * 初始化所有连线的端点
647
+ * 初始化所有连线的端点(同步版本)
659
648
  * 用于在初始加载后端数据后,自动计算所有连线的合适端点,避免线横跨图元
660
649
  * @param shapes 所有图元列表
661
650
  * @param updateShape 更新图元的回调函数
651
+ * @param shapeMapIndex 可选,id → Shape 的索引(来自 graphStore.shapeMap)
662
652
  */
663
- static initializeAllEdgeEndpoints(shapes: Shape[], updateShape: (shape: Shape) => void) {
653
+ static initializeAllEdgeEndpoints(shapes: Shape[], updateShape: (shape: Shape) => void, shapeMapIndex?: Map<string, Shape>) {
664
654
  const edges = shapes.filter((shape) => shape.shapeType === "edge");
665
655
 
666
- // 按源-目标对分组,为每组中的线条生成不同的偏移
656
+ const findShape = shapeMapIndex
657
+ ? (id: string) => shapeMapIndex.get(id) ?? null
658
+ : (id: string) => shapes.find(s => s.id === id) ?? null
659
+
660
+ // 按源-目标对分组
667
661
  const edgeGroups = new Map<string, Shape[]>();
668
662
 
669
663
  edges.forEach((edge) => {
670
664
  if (edge.sourceId && edge.targetId) {
671
- // 创建源-目标对的规范化键(确保 A-B 和 B-A 使用相同的键)
672
665
  const isForward = edge.sourceId.localeCompare(edge.targetId) <= 0;
673
666
  const groupKey = isForward
674
667
  ? `${edge.sourceId}-${edge.targetId}`
@@ -681,133 +674,57 @@ export class EdgeUtils {
681
674
  }
682
675
  });
683
676
 
684
- // 处理每个分组
685
- edgeGroups.forEach((groupEdges, groupKey) => {
686
- if (groupEdges.length > 1) {
687
- // 如果同一源-目标对有多个线条,为每条线生成不同的偏移
688
- groupEdges.forEach((edge, index) => {
689
- const sourceShape = shapes.find((s) => s.id === edge.sourceId);
690
- const targetShape = shapes.find((s) => s.id === edge.targetId);
691
-
692
- if (sourceShape && targetShape && sourceShape.bounds && targetShape.bounds) {
693
- // 计算基本连接点
694
- const { x: sx = 0, y: sy = 0, width: sw = 0, height: sh = 0 } = sourceShape.bounds;
695
- const { x: tx = 0, y: ty = 0, width: tw = 0, height: th = 0 } = targetShape.bounds;
696
-
697
- // 计算中心点
698
- const sourceCenter = { x: sx + sw / 2, y: sy + sh / 2 };
699
- const targetCenter = { x: tx + tw / 2, y: ty + th / 2 };
700
-
701
- // 计算连接方向
702
- const dx = targetCenter.x - sourceCenter.x;
703
- const dy = targetCenter.y - sourceCenter.y;
704
-
705
- // 生成基于索引的偏移量(小到不会明显影响,但足以分开线条)
706
- const offsetDistance = 5 * (index + 1);
707
-
708
- // 根据方向计算偏移方向
709
- let offsetX = 0, offsetY = 0;
710
- if (Math.abs(dx) > Math.abs(dy)) {
711
- // 水平方向为主,垂直偏移
712
- offsetY = offsetDistance;
713
- } else {
714
- // 垂直方向为主,水平偏移
715
- offsetX = offsetDistance;
716
- }
717
-
718
- // 确保线条交替偏移方向,避免全部偏向一侧
719
- if (index % 2 === 1) {
720
- offsetX = -offsetX;
721
- offsetY = -offsetY;
722
- }
723
-
724
- // 确定连接点,添加偏移
725
- let sourcePoint, targetPoint;
726
-
727
- if (Math.abs(dx) > Math.abs(dy)) {
728
- // 水平方向
729
- sourcePoint = dx > 0
730
- ? { x: sx + sw, y: sourceCenter.y + offsetY }
731
- : { x: sx, y: sourceCenter.y + offsetY };
732
-
733
- targetPoint = dx > 0
734
- ? { x: tx, y: targetCenter.y + offsetY }
735
- : { x: tx + tw, y: targetCenter.y + offsetY };
736
- } else {
737
- // 垂直方向
738
- sourcePoint = dy > 0
739
- ? { x: sourceCenter.x + offsetX, y: sy + sh }
740
- : { x: sourceCenter.x + offsetX, y: sy };
741
-
742
- targetPoint = dy > 0
743
- ? { x: targetCenter.x + offsetX, y: ty }
744
- : { x: targetCenter.x + offsetX, y: ty + th };
745
- }
746
-
747
- // 更新连线,只使用源点和目标点确保线条保持直线
748
- const waypoints = [sourcePoint, targetPoint];
749
-
750
- const updatedEdge = {
751
- ...edge,
752
- waypointId: JSON.stringify(waypoints),
753
- };
754
-
755
- updateShape(updatedEdge);
756
- }
757
- });
758
- } else {
759
- // 单线条情况
760
- const edge = groupEdges[0];
761
- const sourceShape = shapes.find((s) => s.id === edge.sourceId);
762
- const targetShape = shapes.find((s) => s.id === edge.targetId);
677
+ // 处理每个分组,使用 calcBestEndpoints 共用算法
678
+ edgeGroups.forEach((groupEdges) => {
679
+ groupEdges.forEach((edge, index) => {
680
+ const sourceShape = edge.sourceId ? findShape(edge.sourceId) : null;
681
+ const targetShape = edge.targetId ? findShape(edge.targetId) : null;
763
682
 
764
683
  if (sourceShape && targetShape && sourceShape.bounds && targetShape.bounds) {
765
- const { x: sx = 0, y: sy = 0, width: sw = 0, height: sh = 0 } = sourceShape.bounds;
766
- const { x: tx = 0, y: ty = 0, width: tw = 0, height: th = 0 } = targetShape.bounds;
767
-
768
- // 计算中心点
769
- const sourceCenter = { x: sx + sw / 2, y: sy + sh / 2 };
770
- const targetCenter = { x: tx + tw / 2, y: ty + th / 2 };
771
-
772
- // 计算连接方向
773
- const dx = targetCenter.x - sourceCenter.x;
774
- const dy = targetCenter.y - sourceCenter.y;
775
-
776
- // 确定连接点
777
- let sourcePoint, targetPoint;
778
-
779
- if (Math.abs(dx) > Math.abs(dy)) {
780
- // 水平方向
781
- sourcePoint = dx > 0
782
- ? { x: sx + sw, y: sourceCenter.y }
783
- : { x: sx, y: sourceCenter.y };
784
-
785
- targetPoint = dx > 0
786
- ? { x: tx, y: targetCenter.y }
787
- : { x: tx + tw, y: targetCenter.y };
788
- } else {
789
- // 垂直方向
790
- sourcePoint = dy > 0
791
- ? { x: sourceCenter.x, y: sy + sh }
792
- : { x: sourceCenter.x, y: sy };
793
-
794
- targetPoint = dy > 0
795
- ? { x: targetCenter.x, y: ty }
796
- : { x: targetCenter.x, y: ty + th };
797
- }
684
+ const groupIndex = groupEdges.length > 1 ? index : 0;
685
+ const { waypoints } = this.buildEdgeWaypoints(
686
+ sourceShape.bounds,
687
+ targetShape.bounds,
688
+ groupIndex,
689
+ sourceShape.id === targetShape.id
690
+ );
798
691
 
799
- // 更新连线
800
692
  const updatedEdge = {
801
693
  ...edge,
802
- waypointId: JSON.stringify([sourcePoint, targetPoint]),
694
+ waypointId: JSON.stringify(waypoints),
803
695
  };
804
696
 
805
697
  updateShape(updatedEdge);
806
698
  }
807
- }
699
+ });
808
700
  });
809
701
  }
810
702
 
703
+ /**
704
+ * 初始化所有连线的端点(异步版本,使用 Web Worker)
705
+ * 用于在初始加载后端数据后,自动计算所有连线的合适端点,避免线横跨图元
706
+ * @param shapes 所有图元列表
707
+ * @param updateShape 更新图元的回调函数
708
+ * @param shapeMapIndex 可选,id → Shape 的索引(来自 graphStore.shapeMap)
709
+ */
710
+ static async initializeAllEdgeEndpointsAsync(shapes: Shape[], updateShape: (shape: Shape) => void, shapeMapIndex?: Map<string, Shape>): Promise<void> {
711
+ try {
712
+ const updatedEdges = await workerManager.initializeAllEdgeEndpoints(
713
+ shapes,
714
+ shapeMapIndex
715
+ );
716
+
717
+ // 更新所有返回的边缘
718
+ updatedEdges.forEach(edge => {
719
+ updateShape(edge);
720
+ });
721
+ } catch (error) {
722
+ console.error('Error in initializeAllEdgeEndpointsAsync:', error);
723
+ // 回退到同步版本
724
+ this.initializeAllEdgeEndpoints(shapes, updateShape, shapeMapIndex);
725
+ }
726
+ }
727
+
811
728
  /**
812
729
  * 根据 pin 的方向和位置计算连接点
813
730
  * 连接点位于 pin 的外侧边缘(远离父图元的一侧):