@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
@@ -0,0 +1,1193 @@
1
+ <template>
2
+ <div class="gantt-container" @click="onContainerClick">
3
+ <!-- 左侧表格 -->
4
+ <div
5
+ class="gantt-left"
6
+ :class="{ 'with-search-bar': showSearchBar }"
7
+ ref="tableContainerRef"
8
+ @scroll="() => syncVirtualViewportState()"
9
+ >
10
+ <table class="gantt-table" :style="{ width: tableWidth + 'px' }">
11
+ <!-- 用 colgroup 统一控制整列宽度 -->
12
+ <colgroup>
13
+ <col
14
+ v-for="col in displayColumns"
15
+ :key="col.configId"
16
+ :style="{ width: getColumnWidth(col.configId) + 'px' }"
17
+ />
18
+ </colgroup>
19
+ <thead>
20
+ <tr class="header-row-2">
21
+ <th v-for="col in displayColumns" :key="col.id" class="col-date">
22
+ <div class="th-content">
23
+ <div v-if="col.configId == 'index'" style="text-align: center">
24
+ {{ col.name }}
25
+ </div>
26
+ <div v-else class="th-label">{{ col.name }}</div>
27
+ <div
28
+ v-if="col.configId !== 'index'"
29
+ class="col-resizer"
30
+ @mousedown="startColumnResize(col.configId, $event)"
31
+ ></div>
32
+ </div>
33
+ </th>
34
+ </tr>
35
+ </thead>
36
+
37
+ <tbody>
38
+ <!-- 上方占位空间 -->
39
+ <tr
40
+ v-if="virtualTopSpacerHeight > 0"
41
+ class="table-spacer-row"
42
+ aria-hidden="true"
43
+ >
44
+ <td :colspan="visibleColumnSpan">
45
+ <div
46
+ class="table-spacer"
47
+ :style="{ height: virtualTopSpacerHeight + 'px' }"
48
+ ></div>
49
+ </td>
50
+ </tr>
51
+
52
+ <!-- 虚拟行 -->
53
+ <tr
54
+ v-for="row in virtualRows"
55
+ :key="row.item.id"
56
+ class="gantt-row"
57
+ :class="{ 'row-selected': selectedRowIds.has(row.item.id) }"
58
+ @click.stop="selectRow(row.item.id, $event)"
59
+ @contextmenu="handleContextMenu(row.item, $event)"
60
+ >
61
+ <td
62
+ v-for="col in displayColumns"
63
+ :key="col.configId"
64
+ class="col-date"
65
+ :title="getDisplayCellValue(row.item, col)"
66
+ @dblclick.stop="
67
+ col.configId !== 'index' && openCellEditor(row.item, col)
68
+ "
69
+ >
70
+ <!-- 编辑态:根据列的 valueType 渲染不同编辑控件(Element Plus) -->
71
+ <template v-if="isCellEditing(row.item.id, col.configId)">
72
+ <!-- 布尔:单选(与属性面板保持一致) -->
73
+ <el-radio-group
74
+ v-if="editingTextCell?.editorType === 'Boolean'"
75
+ v-model="editingTextCell!.value"
76
+ class="cell-boolean-group"
77
+ @click.stop
78
+ @change="saveTextEdit(row.item, col.configId)"
79
+ >
80
+ <el-radio :label="true" size="small">是</el-radio>
81
+ <el-radio :label="false" size="small">否</el-radio>
82
+ </el-radio-group>
83
+ <!-- 日期:日期时间选择器 -->
84
+ <el-date-picker
85
+ v-else-if="editingTextCell?.editorType === 'Date'"
86
+ :ref="setEditingInputRef"
87
+ v-model="editingTextCell!.value"
88
+ type="datetime"
89
+ size="small"
90
+ class="cell-date"
91
+ format="YYYY-MM-DD HH:mm:ss"
92
+ value-format="YYYY-MM-DD HH:mm:ss"
93
+ :teleported="false"
94
+ :clearable="true"
95
+ :editable="false"
96
+ @click.stop
97
+ @change="saveTextEdit(row.item, col.configId)"
98
+ @blur="saveTextEdit(row.item, col.configId)"
99
+ @keydown.esc.prevent="closeCellEditor"
100
+ />
101
+ <!-- 枚举:下拉选择,选项来自后端 literals -->
102
+ <el-select
103
+ v-else-if="
104
+ editingTextCell?.editorType === 'Enumeration' &&
105
+ col.literals &&
106
+ col.literals.length
107
+ "
108
+ v-model="editingTextCell!.value"
109
+ size="small"
110
+ class="cell-select"
111
+ @click.stop
112
+ @change="saveTextEdit(row.item, col.configId)"
113
+ @blur="saveTextEdit(row.item, col.configId)"
114
+ >
115
+ <el-option
116
+ v-for="opt in col.literals"
117
+ :key="opt.value"
118
+ :label="opt.key"
119
+ :value="opt.value"
120
+ />
121
+ </el-select>
122
+ <!-- 富文本:先用 textarea(属性面板是弹窗富文本,这里做轻量版) -->
123
+ <el-input
124
+ v-else-if="editingTextCell?.editorType === 'Html'"
125
+ :ref="setEditingInputRef"
126
+ v-model="editingTextCell!.value"
127
+ type="textarea"
128
+ autosize
129
+ size="small"
130
+ class="cell-textarea"
131
+ @click.stop
132
+ @blur="saveTextEdit(row.item, col.configId)"
133
+ @keydown.esc.prevent="closeCellEditor"
134
+ />
135
+ <!-- 其他(String、Integer 等):文本/数字输入框 -->
136
+ <el-input
137
+ v-else
138
+ :ref="setEditingInputRef"
139
+ v-model="editingTextCell!.value"
140
+ :type="
141
+ editingTextCell?.editorType === 'Integer'
142
+ ? 'number'
143
+ : 'text'
144
+ "
145
+ size="small"
146
+ class="cell-input"
147
+ @click.stop
148
+ @blur="saveTextEdit(row.item, col.configId)"
149
+ @keydown.enter.prevent="saveTextEdit(row.item, col.configId)"
150
+ @keydown.esc.prevent="closeCellEditor"
151
+ />
152
+ </template>
153
+
154
+ <!-- 显示态 -->
155
+ <template v-else>
156
+ <div
157
+ v-if="col.configId === 'index'"
158
+ class="item-index"
159
+ style="text-align: center"
160
+ >
161
+ {{ row.index + 1 }}
162
+ </div>
163
+ <div
164
+ v-else-if="
165
+ col.valueType === 'Boolean' &&
166
+ hasBooleanCellValue(row.item, col.configId)
167
+ "
168
+ class="item-name cell-boolean-display"
169
+ >
170
+ <el-radio-group
171
+ :model-value="normalizeBooleanValue((row.item as any)[col.configId])"
172
+ class="cell-boolean-group"
173
+ :disabled="col.isReadonly === true"
174
+ @click.stop
175
+ @change="handleBooleanCellChange(row.item, col.configId, $event)"
176
+ >
177
+ <el-radio :label="true" size="small">是</el-radio>
178
+ <el-radio :label="false" size="small">否</el-radio>
179
+ </el-radio-group>
180
+ </div>
181
+ <div v-else-if="col.valueType === 'Boolean'" class="item-name"></div>
182
+ <div v-else class="item-name">
183
+ <div
184
+ v-if="getDisplayCellIcon(row.item, col)"
185
+ class="expand-icon"
186
+ >
187
+ <img
188
+ :src="
189
+ getIcon('childIcons', getDisplayCellIcon(row.item, col))
190
+ "
191
+ alt=""
192
+ style="width: 16px; height: 16px; display: block"
193
+ />
194
+ </div>
195
+ <span class="cell-text">{{
196
+ getDisplayCellValue(row.item, col)
197
+ }}</span>
198
+ </div>
199
+ </template>
200
+ </td>
201
+ </tr>
202
+
203
+ <!-- 下方占位空间 -->
204
+ <tr
205
+ v-if="virtualBottomSpacerHeight > 0"
206
+ class="table-spacer-row"
207
+ aria-hidden="true"
208
+ >
209
+ <td :colspan="visibleColumnSpan">
210
+ <div
211
+ class="table-spacer"
212
+ :style="{ height: virtualBottomSpacerHeight + 'px' }"
213
+ ></div>
214
+ </td>
215
+ </tr>
216
+ </tbody>
217
+ </table>
218
+ </div>
219
+ <!-- 右键菜单 -->
220
+ <GanttContextMenu
221
+ v-model:visible="showContextMenu"
222
+ :position="contextMenuPosition"
223
+ :can-move-up="canMoveUp"
224
+ :can-move-down="canMoveDown"
225
+ @property-config="handlePropertyConfig"
226
+ @tree-highlight="handleTreeHighlight"
227
+ @move-up="handleMoveUpFromMenu"
228
+ @move-down="handleMoveDownFromMenu"
229
+ @delete="handleDeleteFromMenu"
230
+ @remove="handleRemoveFromMenu"
231
+ />
232
+ </div>
233
+ </template>
234
+
235
+ <script setup lang="ts">
236
+ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
237
+ import type { Shape, GanttData, GanttColumn } from "../../types";
238
+ import { eventBus } from "../../store/eventBus";
239
+ import GanttContextMenu from "../GanttContextMenu/GanttContextMenu.vue";
240
+ import { getIcon } from "../../utils/iconLoader";
241
+ import { useChartRowSelection, useVirtualScroll } from "../../hooks";
242
+ /**
243
+ * 组件入参
244
+ */
245
+ interface Props {
246
+ shape: Shape;
247
+ }
248
+
249
+ const props = defineProps<Props>();
250
+
251
+ /**
252
+ * 前端内置固定列:序号列
253
+ */
254
+ const indexColumn = {
255
+ configId: "index",
256
+ name: "序号",
257
+ isShow: true,
258
+ isReadonly: false,
259
+ };
260
+ /**
261
+ * 当前组件内部使用的行数据类型
262
+ * 允许动态字段,便于适配后端返回的任意列
263
+ */
264
+ // 列宽度状态(动态调整,使用 configId 作为 key)
265
+ const columnWidths = ref<Record<string, number>>({});
266
+ /**
267
+ * 搜索输入框 ref
268
+ */
269
+ const searchInputRef = ref<HTMLInputElement | null>(null);
270
+
271
+ /**
272
+ * 表格容器 ref(用于虚拟滚动)
273
+ */
274
+ const tableContainerRef = ref<HTMLDivElement | null>(null);
275
+
276
+ /**
277
+ * 当前编辑中的输入框 ref
278
+ */
279
+ const editingInputRef = ref<HTMLInputElement | null>(null);
280
+
281
+ /**
282
+ * 搜索相关状态
283
+ */
284
+ const showSearchBar = ref(false);
285
+ const searchKeyword = ref("");
286
+ const searchMatchedIds = ref<string[]>([]);
287
+ const currentMatchIndex = ref(-1);
288
+ /**
289
+ * 默认列配置
290
+ * 没有后端列配置时,使用这组默认列
291
+ */
292
+ const defaultColumns = ref<GanttColumn[]>([]);
293
+
294
+ // 甘特图数据:使用后端数据
295
+ type GanttItem = GanttData & { hasChildren: boolean };
296
+ const ganttItems = ref<GanttItem[]>([]);
297
+ /**
298
+ * 除序号列之外的第一列 configId(displayColumns[1])
299
+ */
300
+ const firstDataColId = computed(() => {
301
+ return displayColumns.value[1]?.configId || "";
302
+ });
303
+ /**
304
+ * 实际表格数据
305
+ * 优先使用后端数据,没有则使用 mock 数据
306
+ */
307
+ // const ganttItems = ref<GanttItem[]>([...mockData.value])
308
+
309
+ // 列配置:优先使用后端数据
310
+ const columnConfig = ref<any[]>([...defaultColumns.value]);
311
+
312
+ /**
313
+ * 当前可见列
314
+ */
315
+ const visibleColumns = computed(() => {
316
+ return columnConfig.value.filter((col) => col.isShow);
317
+ });
318
+ /**
319
+ * 最终渲染列
320
+ * 序号列固定在最左侧
321
+ */
322
+ const displayColumns = computed(() => {
323
+ return [indexColumn, ...visibleColumns.value];
324
+ });
325
+
326
+ /**
327
+ * 过滤后的数据(用于搜索)
328
+ * 如果没有搜索关键字,返回所有数据
329
+ */
330
+ const filteredGanttItems = computed(() => {
331
+ const keyword = searchKeyword.value.trim().toLowerCase();
332
+ if (!keyword) {
333
+ return ganttItems.value;
334
+ }
335
+
336
+ if (searchMatchedIds.value.length === 0) {
337
+ return [];
338
+ }
339
+
340
+ return ganttItems.value.filter((item) =>
341
+ searchMatchedIds.value.includes(item.id),
342
+ );
343
+ });
344
+
345
+ // ========== 虚拟滚动 ==========
346
+ const TABLE_HEADER_HEIGHT = 28;
347
+ const TABLE_ROW_HEIGHT = 32;
348
+ const TABLE_VIRTUAL_OVERSCAN = 8;
349
+
350
+ const {
351
+ virtualRows,
352
+ virtualTopSpacerHeight,
353
+ virtualBottomSpacerHeight,
354
+ virtualStartIndex,
355
+ virtualEndIndex,
356
+ syncVirtualViewportState,
357
+ visibleColumnSpan,
358
+ } = useVirtualScroll(filteredGanttItems, {
359
+ itemHeight: TABLE_ROW_HEIGHT,
360
+ headerHeight: TABLE_HEADER_HEIGHT,
361
+ overscan: TABLE_VIRTUAL_OVERSCAN,
362
+ containerRef: tableContainerRef,
363
+ columnCount: computed(() => displayColumns.value.length),
364
+ });
365
+
366
+ /**
367
+ * 监听虚拟索引变化,自动关闭不可见行的编辑状态
368
+ */
369
+ watch([virtualStartIndex, virtualEndIndex], () => {
370
+ if (!editingTextCell.value) return;
371
+
372
+ const renderedIds = new Set(virtualRows.value.map(({ item }) => item.id));
373
+ if (!renderedIds.has(editingTextCell.value.id)) {
374
+ closeCellEditor();
375
+ }
376
+ });
377
+
378
+ /**
379
+ * 行交互状态
380
+ * 统一复用表格/甘特图共享的行选择与右键菜单逻辑
381
+ */
382
+ const {
383
+ canMoveDown,
384
+ canMoveUp,
385
+ clearSelection,
386
+ contextMenuPosition,
387
+ deleteRows,
388
+ handleContextMenu,
389
+ handleDeleteFromMenu,
390
+ handleMoveDownFromMenu,
391
+ handleMoveUpFromMenu,
392
+ handlePropertyConfig,
393
+ handleRemoveFromMenu,
394
+ handleTreeHighlight,
395
+ moveDown,
396
+ moveUp,
397
+ onRemoveSuccess,
398
+ removeRows,
399
+ selectLastRow,
400
+ selectRow,
401
+ selectedRowIds,
402
+ showContextMenu,
403
+ } = useChartRowSelection<GanttItem>({
404
+ items: ganttItems,
405
+ rowSelectedEvent: "table-row-selected",
406
+ onClearSelection: () => {
407
+ closeCellEditor();
408
+ },
409
+ onDeleteRows: () => {
410
+ closeCellEditor();
411
+ },
412
+ onAfterRemoveSuccess: () => {
413
+ closeCellEditor();
414
+ },
415
+ });
416
+
417
+ /**
418
+ * 当前编辑中的单元格
419
+ * 增加 editorType / column 信息,便于根据 valueType 渲染不同编辑控件
420
+ */
421
+ const editingTextCell = ref<{
422
+ id: string;
423
+ field: string;
424
+ value: any;
425
+ editorType?: string;
426
+ column?: any;
427
+ } | null>(null);
428
+
429
+ // 根据 configId 获取默认列宽
430
+ function getDefaultColumnWidth(configId: string): number {
431
+ if (configId === "index") {
432
+ return 50;
433
+ }
434
+ // 其他列默认中等宽度
435
+ return 400;
436
+ }
437
+ function getColumnWidth(configId: string): number {
438
+ if (configId === "index") {
439
+ return 50;
440
+ }
441
+ return columnWidths.value[configId] || getDefaultColumnWidth(configId);
442
+ }
443
+
444
+ /**
445
+ * 点击空白区域,清空选中并关闭编辑态
446
+ */
447
+ function onContainerClick() {
448
+ clearSelection();
449
+ }
450
+ /**
451
+ * 新增行
452
+ */
453
+ function addRow() {
454
+ eventBus.emit("table-add-row");
455
+ }
456
+ /**
457
+ * 搜索结果显示文本
458
+ */
459
+ const searchResultText = computed(() => {
460
+ if (!searchKeyword.value.trim()) return "";
461
+ if (searchMatchedIds.value.length === 0) return "0 of 0";
462
+ return `${currentMatchIndex.value + 1} of ${searchMatchedIds.value.length}`;
463
+ });
464
+
465
+ /**
466
+ * 上一条 / 下一条按钮状态
467
+ */
468
+ const canGoPrev = computed(() => {
469
+ return searchMatchedIds.value.length > 0 && currentMatchIndex.value > 0;
470
+ });
471
+
472
+ const canGoNext = computed(() => {
473
+ return (
474
+ searchMatchedIds.value.length > 0 &&
475
+ currentMatchIndex.value < searchMatchedIds.value.length - 1
476
+ );
477
+ });
478
+
479
+ /**
480
+ * 执行搜索
481
+ * 搜索范围为当前可见列
482
+ */
483
+ function runSearch() {
484
+ const keyword = searchKeyword.value.trim().toLowerCase();
485
+ if (!keyword) {
486
+ searchMatchedIds.value = [];
487
+ currentMatchIndex.value = -1;
488
+ return;
489
+ }
490
+
491
+ // 模糊匹配:搜索所有可见列的值
492
+ const matched = ganttItems.value.filter((item) => {
493
+ return visibleColumns.value.some((col) => {
494
+ const value = getDisplayCellValue(item, col);
495
+ return value.toLowerCase().includes(keyword);
496
+ });
497
+ });
498
+
499
+ searchMatchedIds.value = matched.map((item) => item.id);
500
+ currentMatchIndex.value = searchMatchedIds.value.length > 0 ? 0 : -1;
501
+
502
+ // 自动选中第一个匹配项
503
+ if (currentMatchIndex.value >= 0) {
504
+ selectRow(searchMatchedIds.value[0]);
505
+ }
506
+ }
507
+
508
+ /**
509
+ * 搜索输入事件
510
+ */
511
+ function onSearchInput() {
512
+ runSearch();
513
+ }
514
+
515
+ /**
516
+ * 跳转上一条匹配
517
+ */
518
+ function gotoPrevMatch() {
519
+ if (!canGoPrev.value) return;
520
+ currentMatchIndex.value--;
521
+ selectRow(searchMatchedIds.value[currentMatchIndex.value]);
522
+ }
523
+
524
+ /**
525
+ * 跳转下一条匹配
526
+ */
527
+ function gotoNextMatch() {
528
+ if (!canGoNext.value) return;
529
+ currentMatchIndex.value++;
530
+ selectRow(searchMatchedIds.value[currentMatchIndex.value]);
531
+ }
532
+
533
+ /**
534
+ * 打开搜索栏
535
+ */
536
+ function openSearch() {
537
+ showSearchBar.value = true;
538
+ nextTick(() => {
539
+ searchInputRef.value?.focus();
540
+ });
541
+ }
542
+
543
+ /**
544
+ * 关闭搜索栏
545
+ */
546
+ function closeSearch() {
547
+ showSearchBar.value = false;
548
+ searchKeyword.value = "";
549
+ searchMatchedIds.value = [];
550
+ currentMatchIndex.value = -1;
551
+ }
552
+
553
+ /**
554
+ * 工具栏指令监听
555
+ */
556
+ function onGanttToolbarAction(action: string) {
557
+ const actionMap: Record<string, () => void> = {
558
+ chartNewModel: addRow,
559
+ chartDelete: deleteRows,
560
+ chartRemove: removeRows,
561
+ chartMoveUp: moveUp,
562
+ chartMoveDown: moveDown,
563
+ chartSearch: openSearch,
564
+ };
565
+ const fn = actionMap[action];
566
+ if (!fn) return;
567
+ fn();
568
+ }
569
+ /**
570
+ * 判断当前单元格是否正在编辑
571
+ */
572
+ function isCellEditing(rowId: string, field: string) {
573
+ return (
574
+ editingTextCell.value?.id === rowId &&
575
+ editingTextCell.value?.field === field
576
+ );
577
+ }
578
+
579
+ /**
580
+ * 设置当前编辑输入框 ref
581
+ */
582
+ function setEditingInputRef(el: HTMLInputElement | null | any) {
583
+ editingInputRef.value = el;
584
+ }
585
+
586
+ /**
587
+ * 打开单元格编辑
588
+ * 根据列的 valueType 选择合适的编辑控件
589
+ */
590
+ function openCellEditor(item: GanttItem, col: any) {
591
+ if (col.isReadonly === true) return;
592
+ if (!hasCellProperty(item, col.configId)) return;
593
+
594
+ // 原始值直接从数据行中读取,避免使用展示值(例如枚举的 label)
595
+ const rawValue = (item as any)[col.configId];
596
+
597
+ console.log("[graph-table-openCellEditor] valueType:", col.valueType, {
598
+ configId: col.configId,
599
+ column: col,
600
+ value: rawValue ?? null,
601
+ });
602
+
603
+ if (col.valueType === "Boolean") {
604
+ return;
605
+ }
606
+
607
+ // 复杂类型:交给宿主应用使用“属性面板同款编辑器”处理
608
+ // 这样 graph 包保持轻量,不强依赖业务侧的弹窗/选择器实现
609
+ // 复杂值类型不走表格内联编辑,统一交给宿主侧弹出属性面板同款编辑器。
610
+ // Transfer 在业务上对应“选择用例”穿梭框,双击单元格时也要走这条链路。
611
+ const complexTypes = new Set([
612
+ "Element",
613
+ "Element_List",
614
+ "Relations_End",
615
+ "ValueSpecification",
616
+ "NoString",
617
+ "Transfer",
618
+ "Html",
619
+ "Htmld",
620
+ ]);
621
+ if (complexTypes.has(col.valueType)) {
622
+ eventBus.emit("table-cell-open-editor", {
623
+ item,
624
+ column: col,
625
+ configId: col.configId,
626
+ valueType: col.valueType,
627
+ value: rawValue ?? null,
628
+ });
629
+ return;
630
+ }
631
+
632
+ editingTextCell.value = {
633
+ id: item.id,
634
+ field: col.configId,
635
+ value: rawValue ?? "",
636
+ editorType: col.valueType,
637
+ column: col,
638
+ };
639
+ nextTick(() => {
640
+ const inst = editingInputRef.value as any;
641
+ inst?.focus?.();
642
+ inst?.select?.();
643
+ });
644
+ }
645
+
646
+ function getRawCellValue(item: any, configId: string) {
647
+ const v = item?.[configId];
648
+ return v;
649
+ }
650
+
651
+ function hasCellProperty(item: any, configId: string): boolean {
652
+ return !!item && Object.prototype.hasOwnProperty.call(item, configId);
653
+ }
654
+
655
+ function normalizeBooleanValue(value: any): boolean | undefined {
656
+ if (value === null || value === undefined || value === "") {
657
+ return undefined;
658
+ }
659
+
660
+ if (typeof value === "boolean") {
661
+ return value;
662
+ }
663
+
664
+ if (typeof value === "string") {
665
+ if (value === "true") return true;
666
+ if (value === "false") return false;
667
+ if (value === "1") return true;
668
+ if (value === "0") return false;
669
+ }
670
+
671
+ if (typeof value === "number") {
672
+ if (value === 1) return true;
673
+ if (value === 0) return false;
674
+ }
675
+
676
+ return undefined;
677
+ }
678
+
679
+ function hasBooleanCellValue(item: any, configId: string): boolean {
680
+ if (!hasCellProperty(item, configId)) {
681
+ return false;
682
+ }
683
+
684
+ return normalizeBooleanValue(item[configId]) !== undefined;
685
+ }
686
+
687
+ function stripHtmlTags(value: unknown): string {
688
+ return String(value ?? "")
689
+ .replace(/<[^>]+>/g, "")
690
+ .replace(/&nbsp;/gi, " ")
691
+ .replace(/\s+/g, " ")
692
+ .trim();
693
+ }
694
+
695
+ function handleBooleanCellChange(
696
+ item: GanttItem,
697
+ field: string,
698
+ value: string | number | boolean | undefined,
699
+ ) {
700
+ if (!hasBooleanCellValue(item, field)) {
701
+ return;
702
+ }
703
+
704
+ const oldValue = getRawCellValue(item as any, field);
705
+ const normalizedOldValue = normalizeBooleanValue(oldValue);
706
+ const normalizedNewValue = normalizeBooleanValue(value);
707
+
708
+ if (normalizedOldValue === normalizedNewValue) {
709
+ return;
710
+ }
711
+
712
+ eventBus.emit("gantt-cell-edit", {
713
+ item,
714
+ configId: field,
715
+ oldValue,
716
+ newValue: normalizedNewValue,
717
+ });
718
+ }
719
+
720
+ /**
721
+ * 保存单元格值
722
+ */
723
+ function saveTextEdit(item: GanttItem, field: string) {
724
+ if (!editingTextCell.value || editingTextCell.value.value === undefined) {
725
+ editingTextCell.value = null;
726
+ return;
727
+ }
728
+
729
+ const oldValue = getRawCellValue(item as any, field);
730
+ const newValue = editingTextCell.value.value;
731
+
732
+ // 值未改变,直接关闭编辑
733
+ if (oldValue === newValue) {
734
+ editingTextCell.value = null;
735
+ return;
736
+ }
737
+
738
+ // 发送编辑事件到父组件(与 Gantt 使用相同的事件名)
739
+ eventBus.emit("gantt-cell-edit", {
740
+ item,
741
+ configId: field,
742
+ oldValue,
743
+ newValue,
744
+ });
745
+
746
+ // 暂时关闭编辑状态(等待接口返回)
747
+ editingTextCell.value = null;
748
+ }
749
+
750
+ /**
751
+ * 关闭单元格编辑
752
+ */
753
+ function closeCellEditor() {
754
+ editingTextCell.value = null;
755
+ editingInputRef.value = null;
756
+ }
757
+ //监听获取后端列配置
758
+ watch(
759
+ () => props.shape.attributeColumns,
760
+ (columns) => {
761
+ if (columns && columns.length > 0) {
762
+ columnConfig.value = columns;
763
+ // 初始化列宽(如果还没有设置)
764
+ columns.forEach((col: any) => {
765
+ if (col.configId !== "index" && !columnWidths.value[col.configId]) {
766
+ columnWidths.value[col.configId] = getDefaultColumnWidth(
767
+ col.configId,
768
+ );
769
+ }
770
+ });
771
+ // 同步到工具栏菜单
772
+ eventBus.emit("chart-columns-from-backend", columns);
773
+ } else {
774
+ // 没有后端数据时使用默认配置
775
+ columnConfig.value = [...defaultColumns.value];
776
+ }
777
+ },
778
+ { immediate: true },
779
+ );
780
+ // 统一提取对象/对象数组类型单元格的展示文本和图标,避免 Element_List 展示成 [object Object]。
781
+ function getCellDisplayMeta(value: any): { text: string; icon: string } {
782
+ if (Array.isArray(value)) {
783
+ const objectItems = value.filter(
784
+ (item) => item && typeof item === "object",
785
+ );
786
+ const text = objectItems
787
+ .map((item: any) => item.nodeName || item.modelName || "")
788
+ .filter(Boolean)
789
+ .join("、");
790
+
791
+ return {
792
+ text: text || String(value ?? ""),
793
+ icon: objectItems.find((item: any) => item.icon)?.icon || "",
794
+ };
795
+ }
796
+
797
+ if (value && typeof value === "object") {
798
+ return {
799
+ text: value.nodeName || value.modelName || String(value ?? ""),
800
+ icon: value.icon || "",
801
+ };
802
+ }
803
+
804
+ return {
805
+ text: String(value ?? ""),
806
+ icon: "",
807
+ };
808
+ }
809
+
810
+ // 根据列配置获取“展示值”(用于单元格展示 / title)
811
+ function getDisplayCellValue(
812
+ item: GanttData & { hasChildren: boolean },
813
+ col: any,
814
+ ): string {
815
+ const configId = col.configId;
816
+ const value = (item as any)[configId];
817
+
818
+ if (col.valueType === "Html" || col.valueType === "Htmld") {
819
+ return stripHtmlTags(value);
820
+ }
821
+
822
+ if (col.valueType === "Boolean") {
823
+ const normalizedValue = normalizeBooleanValue(value);
824
+ if (normalizedValue === true) return "是";
825
+ if (normalizedValue === false) return "否";
826
+ return "";
827
+ }
828
+
829
+ // 枚举类型:用 literals 中的 key 作为展示文案
830
+ if (
831
+ col.valueType === "Enumeration" &&
832
+ col.literals &&
833
+ Array.isArray(col.literals)
834
+ ) {
835
+ const matched = col.literals.find((opt: any) => opt.value === value);
836
+ return matched?.key ?? String(value ?? "");
837
+ }
838
+
839
+ return getCellDisplayMeta(value).text;
840
+ }
841
+
842
+ // 获取单元格应展示的图标。
843
+ // 第一列仍然优先展示行本身图标,其他对象/对象数组列则展示值里的 icon。
844
+ function getDisplayCellIcon(
845
+ item: GanttData & { hasChildren: boolean },
846
+ col: any,
847
+ ): string {
848
+ if (col.configId === firstDataColId.value && item.icon) {
849
+ return item.icon;
850
+ }
851
+
852
+ return getCellDisplayMeta((item as any)[col.configId]).icon;
853
+ }
854
+ // 根据 configId 获取“原始值”(用于比较 old/new、搜索等)
855
+ function getCellValue(
856
+ item: GanttData & { hasChildren: boolean },
857
+ configId: string,
858
+ ): string {
859
+ return getCellDisplayMeta((item as any)[configId]).text;
860
+ }
861
+ // 列宽调整
862
+ function startColumnResize(columnKey: string, e: MouseEvent) {
863
+ if (columnKey === "index") return;
864
+
865
+ e.stopPropagation();
866
+ e.preventDefault();
867
+
868
+ const startX = e.clientX;
869
+ const startWidth = getColumnWidth(columnKey);
870
+
871
+ const onMove = (ev: MouseEvent) => {
872
+ const delta = ev.clientX - startX;
873
+ const nextWidth = Math.max(200, startWidth + delta);
874
+ columnWidths.value[columnKey] = nextWidth;
875
+ };
876
+
877
+ const onUp = () => {
878
+ document.removeEventListener("mousemove", onMove);
879
+ document.removeEventListener("mouseup", onUp);
880
+ document.body.style.cursor = "";
881
+ document.body.style.userSelect = "";
882
+ };
883
+
884
+ document.body.style.cursor = "col-resize";
885
+ document.body.style.userSelect = "none";
886
+ document.addEventListener("mousemove", onMove);
887
+ document.addEventListener("mouseup", onUp);
888
+ }
889
+ function handleCanvasColumnChange(columns: any[]) {
890
+ if (columns && columns.length > 0) {
891
+ columnConfig.value = columns;
892
+
893
+ // 初始化列宽(如果还没有设置)
894
+ columns.forEach((col: any) => {
895
+ if (col.configId !== "index" && !columnWidths.value[col.configId]) {
896
+ columnWidths.value[col.configId] = getDefaultColumnWidth(col.configId);
897
+ }
898
+ });
899
+
900
+ // 同步到工具栏菜单
901
+ // eventBus.emit('chart-columns-from-backend', columns)
902
+ }
903
+ }
904
+
905
+ // 监听后端数据变化
906
+ function handleCanvasDataChange(data: any[]) {
907
+ if (data && data.length > 0) {
908
+ ganttItems.value = data.map((d) => ({
909
+ ...d,
910
+ hasChildren: false,
911
+ })) as (GanttData & { hasChildren: boolean })[];
912
+ }
913
+ }
914
+
915
+ // 监听列配置变更(来自工具栏菜单)
916
+ function onColumnConfigChange(config: Array<any>) {
917
+ columnConfig.value = config;
918
+ }
919
+ const tableWidth = computed(() => {
920
+ return displayColumns.value.reduce((total, col) => {
921
+ return total + getColumnWidth(col.configId);
922
+ }, 0);
923
+ });
924
+ /**
925
+ * 生命周期:注册事件
926
+ */
927
+ onMounted(() => {
928
+ eventBus.on("table-toolbar-action", onGanttToolbarAction);
929
+ eventBus.on("canvas-data-change", handleCanvasDataChange);
930
+ eventBus.on("chart-column-config", onColumnConfigChange);
931
+ eventBus.on("canvas-data-column", handleCanvasColumnChange);
932
+ //监听移除成功事件
933
+ eventBus.on("table-gantt-remove:success", onRemoveSuccess);
934
+ // 新增成功回执:直接选中最后一条
935
+ eventBus.on("table-gantt-add:success", selectLastRow);
936
+ });
937
+
938
+ /**
939
+ * 生命周期:卸载事件
940
+ */
941
+ onUnmounted(() => {
942
+ eventBus.off("table-toolbar-action", onGanttToolbarAction);
943
+ eventBus.off("canvas-data-change", handleCanvasDataChange);
944
+ eventBus.off("chart-column-config", onColumnConfigChange);
945
+ eventBus.off("canvas-data-column", handleCanvasColumnChange);
946
+ eventBus.off("table-gantt-remove:success", onRemoveSuccess);
947
+ eventBus.off("table-gantt-add:success", selectLastRow);
948
+ });
949
+ </script>
950
+
951
+ <style scoped lang="scss">
952
+ /* 甘特表格容器 */
953
+ .gantt-container {
954
+ --header-row-h: 28px;
955
+ --data-row-h: 32px;
956
+
957
+ position: relative;
958
+ display: flex;
959
+ width: 100%;
960
+ height: 100%;
961
+ border: 1px solid #dcdfe6;
962
+ background: #fff;
963
+ overflow: hidden;
964
+ font-size: 12px;
965
+ font-family:
966
+ "Source Han Sans SC", "Microsoft YaHei", "PingFang SC", Arial, sans-serif;
967
+ }
968
+ /* 左侧表格区域 */
969
+ .gantt-left {
970
+ width: 100%;
971
+ overflow: auto;
972
+ }
973
+
974
+ .gantt-left.with-search-bar {
975
+ margin-top: 36px;
976
+ }
977
+
978
+ /* 虚拟滚动占位行 */
979
+ .table-spacer-row td {
980
+ height: 0;
981
+ padding: 0;
982
+ border: none !important;
983
+ }
984
+
985
+ .table-spacer {
986
+ width: 1px;
987
+ }
988
+
989
+ /* 表格 */
990
+ .gantt-table {
991
+ border-collapse: separate;
992
+ border-spacing: 0;
993
+ table-layout: fixed;
994
+ }
995
+
996
+ .th-content {
997
+ position: relative;
998
+ display: flex;
999
+ align-items: center;
1000
+ width: 100%;
1001
+ height: 100%;
1002
+ min-width: 0;
1003
+ box-sizing: border-box;
1004
+ }
1005
+ .th-content > :nth-child(1) {
1006
+ margin-left: 4px;
1007
+ }
1008
+ .gantt-table th,
1009
+ .gantt-table td {
1010
+ box-sizing: border-box;
1011
+ padding: 0 8px;
1012
+ border: none;
1013
+ border-bottom: 1px solid #ebeef5;
1014
+ border-right: 1px solid #ebeef5;
1015
+ text-align: left;
1016
+ vertical-align: middle;
1017
+ white-space: nowrap;
1018
+ overflow: hidden;
1019
+ text-overflow: ellipsis;
1020
+ }
1021
+
1022
+ .gantt-table th:first-child,
1023
+ .gantt-table td:first-child {
1024
+ border-left: 1px solid #ebeef5;
1025
+ width: 50px;
1026
+ min-width: 50px;
1027
+ max-width: 50px;
1028
+ }
1029
+
1030
+ /* 表头第二行 */
1031
+ .header-row-2 th {
1032
+ position: sticky;
1033
+ z-index: 1;
1034
+ height: var(--header-row-h);
1035
+ background: #f5f7fa;
1036
+ border-bottom-color: #dcdfe6;
1037
+ font-weight: 500;
1038
+ color: #606266;
1039
+ }
1040
+
1041
+ /* 数据行 */
1042
+ .gantt-table td {
1043
+ height: var(--data-row-h);
1044
+ }
1045
+
1046
+ /* 列样式 */
1047
+ .col-name {
1048
+ text-align: left;
1049
+ }
1050
+
1051
+ .col-td {
1052
+ text-align: center;
1053
+ }
1054
+
1055
+ .col-index {
1056
+ width: 60px !important;
1057
+ }
1058
+
1059
+ .th-label {
1060
+ font-weight: 600;
1061
+ }
1062
+ .cell-text {
1063
+ flex: 1;
1064
+ min-width: 0;
1065
+ overflow: hidden;
1066
+ text-overflow: ellipsis;
1067
+ white-space: nowrap;
1068
+ }
1069
+ /* 展开图标 */
1070
+ .expand-icon {
1071
+ display: inline-block;
1072
+ margin-right: 4px;
1073
+ cursor: pointer;
1074
+ user-select: none;
1075
+ }
1076
+
1077
+ /* 名称文本 */
1078
+ .item-name {
1079
+ display: inline-block;
1080
+ width: 100%;
1081
+ overflow: hidden;
1082
+ text-overflow: ellipsis;
1083
+ vertical-align: middle;
1084
+ display: flex;
1085
+ align-items: center;
1086
+ min-width: 0;
1087
+ }
1088
+
1089
+ .expand-icon {
1090
+ flex: 0 0 auto;
1091
+ display: inline-flex;
1092
+ align-items: center;
1093
+ justify-content: center;
1094
+ margin-right: 5px;
1095
+ cursor: pointer;
1096
+ user-select: none;
1097
+ }
1098
+
1099
+ .item-index {
1100
+ text-align: center;
1101
+ }
1102
+
1103
+ /* 单元格编辑输入框(Element Plus 包一层外壳,尽量贴合现有样式) */
1104
+ .cell-input {
1105
+ width: 100%;
1106
+ }
1107
+
1108
+ .cell-input :deep(.el-input__wrapper) {
1109
+ padding: 0 6px;
1110
+ height: 24px;
1111
+ box-shadow: 0 0 0 1px #409eff inset;
1112
+ border-radius: 3px;
1113
+ }
1114
+
1115
+ .cell-select {
1116
+ width: 100%;
1117
+ }
1118
+
1119
+ .cell-select :deep(.el-input__wrapper) {
1120
+ min-height: 24px;
1121
+ height: 24px;
1122
+ padding: 0 6px;
1123
+ border-radius: 3px;
1124
+ }
1125
+
1126
+ .cell-boolean-display {
1127
+ overflow: visible;
1128
+ }
1129
+
1130
+ .cell-boolean-group {
1131
+ display: inline-flex;
1132
+ align-items: center;
1133
+ height: 24px;
1134
+ }
1135
+
1136
+ .cell-boolean-group :deep(.el-radio) {
1137
+ align-items: center;
1138
+ margin-right: 10px;
1139
+ margin-bottom: 0;
1140
+ }
1141
+
1142
+ .cell-boolean-group :deep(.el-radio:last-child) {
1143
+ margin-right: 0;
1144
+ }
1145
+
1146
+ .cell-boolean-group :deep(.el-radio__label) {
1147
+ padding-left: 4px;
1148
+ }
1149
+
1150
+ .cell-date {
1151
+ width: 100%;
1152
+ }
1153
+
1154
+ .cell-date :deep(.el-input__wrapper) {
1155
+ min-height: 24px;
1156
+ height: 24px;
1157
+ padding: 0 6px;
1158
+ border-radius: 3px;
1159
+ }
1160
+
1161
+ .cell-textarea {
1162
+ width: 100%;
1163
+ }
1164
+
1165
+ .cell-textarea :deep(.el-textarea__inner) {
1166
+ font-size: 12px;
1167
+ line-height: 18px;
1168
+ padding: 4px 6px;
1169
+ }
1170
+
1171
+ .col-resizer {
1172
+ position: absolute;
1173
+ right: -8px;
1174
+ top: 0;
1175
+ bottom: 0;
1176
+ width: 5px;
1177
+ cursor: col-resize;
1178
+ user-select: none;
1179
+ }
1180
+
1181
+ .col-resizer:hover {
1182
+ background-color: rgba(64, 158, 255, 0.1);
1183
+ }
1184
+
1185
+ /* 选中行高亮 */
1186
+ .row-selected {
1187
+ background-color: #ecf5ff !important;
1188
+ }
1189
+
1190
+ .gantt-row.row-selected td {
1191
+ background-color: #ecf5ff;
1192
+ }
1193
+ </style>