@tmagic/editor 1.8.0-beta.2 → 1.8.0-beta.20

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 (306) hide show
  1. package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +43 -9
  2. package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +8 -4
  3. package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +3 -2
  4. package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +22 -98
  5. package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +32 -9
  6. package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +68 -17
  7. package/dist/es/components/Icon.vue_vue_type_script_setup_true_lang.js +1 -1
  8. package/dist/es/components/Resizer.vue_vue_type_script_setup_true_lang.js +1 -1
  9. package/dist/es/components/ScrollBar.js +0 -1
  10. package/dist/es/components/ScrollBar.vue_vue_type_script_setup_true_lang.js +1 -1
  11. package/dist/es/components/ScrollViewer.vue_vue_type_script_setup_true_lang.js +1 -1
  12. package/dist/es/components/SearchInput.vue_vue_type_script_setup_true_lang.js +1 -1
  13. package/dist/es/components/SplitView.vue_vue_type_script_setup_true_lang.js +1 -1
  14. package/dist/es/components/ToolButton.vue_vue_type_script_setup_true_lang.js +7 -7
  15. package/dist/es/components/Tree.vue_vue_type_script_setup_true_lang.js +1 -1
  16. package/dist/es/components/TreeNode.vue_vue_type_script_setup_true_lang.js +1 -1
  17. package/dist/es/components/ViewForm.js +5 -0
  18. package/dist/es/components/ViewForm.vue_vue_type_script_setup_true_lang.js +58 -0
  19. package/dist/es/editorProps.js +9 -1
  20. package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +16 -5
  21. package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +7 -7
  22. package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +81 -44
  23. package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +10 -3
  24. package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +7 -19
  25. package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +13 -6
  26. package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +11 -8
  27. package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +39 -12
  28. package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +11 -20
  29. package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +11 -6
  30. package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +30 -14
  31. package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +11 -4
  32. package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +5 -2
  33. package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +38 -6
  34. package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +151 -153
  35. package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +5 -2
  36. package/dist/es/fields/PageFragmentSelect.vue_vue_type_script_setup_true_lang.js +5 -2
  37. package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +8 -10
  38. package/dist/es/fields/StyleSetter/components/BackgroundPosition.vue_vue_type_script_setup_true_lang.js +5 -2
  39. package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +28 -6
  40. package/dist/es/fields/StyleSetter/components/Box.vue_vue_type_script_setup_true_lang.js +1 -1
  41. package/dist/es/fields/StyleSetter/icons/align-items/Center.js +31 -0
  42. package/dist/es/fields/StyleSetter/icons/align-items/FlexEnd.js +31 -0
  43. package/dist/es/fields/StyleSetter/icons/align-items/FlexStart.js +31 -0
  44. package/dist/es/fields/StyleSetter/icons/align-items/SpaceAround.js +50 -0
  45. package/dist/es/fields/StyleSetter/icons/align-items/SpaceBetween.js +50 -0
  46. package/dist/es/fields/StyleSetter/icons/background-repeat/NoRepeat.js +7 -7
  47. package/dist/es/fields/StyleSetter/icons/background-repeat/Repeat.js +6 -3
  48. package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatX.js +29 -6
  49. package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatY.js +32 -6
  50. package/dist/es/fields/StyleSetter/icons/display/Block.js +1 -1
  51. package/dist/es/fields/StyleSetter/icons/display/Flex.js +1 -1
  52. package/dist/es/fields/StyleSetter/icons/display/Inline.js +1 -1
  53. package/dist/es/fields/StyleSetter/icons/display/InlineBlock.js +1 -1
  54. package/dist/es/fields/StyleSetter/icons/display/None.js +1 -1
  55. package/dist/es/fields/StyleSetter/icons/flex-direction/Column.js +11 -3
  56. package/dist/es/fields/StyleSetter/icons/flex-direction/ColumnReverse.js +11 -3
  57. package/dist/es/fields/StyleSetter/icons/flex-direction/Row.js +11 -3
  58. package/dist/es/fields/StyleSetter/icons/flex-direction/RowReverse.js +11 -3
  59. package/dist/es/fields/StyleSetter/icons/justify-content/Center.js +17 -3
  60. package/dist/es/fields/StyleSetter/icons/justify-content/FlexEnd.js +19 -3
  61. package/dist/es/fields/StyleSetter/icons/justify-content/FlexStart.js +19 -3
  62. package/dist/es/fields/StyleSetter/icons/justify-content/SpaceAround.js +37 -3
  63. package/dist/es/fields/StyleSetter/icons/justify-content/SpaceBetween.js +33 -3
  64. package/dist/es/fields/StyleSetter/icons/text-align/Center.js +1 -1
  65. package/dist/es/fields/StyleSetter/icons/text-align/Left.js +1 -1
  66. package/dist/es/fields/StyleSetter/icons/text-align/Right.js +1 -1
  67. package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +56 -30
  68. package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +7 -4
  69. package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +35 -26
  70. package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +76 -48
  71. package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +29 -23
  72. package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +7 -4
  73. package/dist/es/fields/UISelect.js +0 -1
  74. package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +5 -2
  75. package/dist/es/hooks/use-code-block-edit.js +6 -3
  76. package/dist/es/hooks/use-compare-form.js +119 -0
  77. package/dist/es/hooks/use-data-source-edit.js +5 -2
  78. package/dist/es/hooks/use-stage.js +9 -4
  79. package/dist/es/icons/CenterIcon.vue_vue_type_script_setup_true_lang.js +1 -1
  80. package/dist/es/icons/CodeIcon.vue_vue_type_script_setup_true_lang.js +1 -1
  81. package/dist/es/icons/DatasourceIcon.js +17 -0
  82. package/dist/es/icons/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +1 -1
  83. package/dist/es/index.js +24 -10
  84. package/dist/es/initService.js +19 -13
  85. package/dist/es/layouts/AddPageBox.vue_vue_type_script_setup_true_lang.js +1 -1
  86. package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +24 -12
  87. package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +25 -18
  88. package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +4 -4
  89. package/dist/es/layouts/NavMenuColumn.vue_vue_type_script_setup_true_lang.js +1 -1
  90. package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +25 -38
  91. package/dist/es/layouts/history-list/BucketTab.js +5 -0
  92. package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +62 -0
  93. package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +177 -88
  94. package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +139 -37
  95. package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +164 -107
  96. package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +44 -9
  97. package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +49 -53
  98. package/dist/es/layouts/history-list/composables.js +138 -108
  99. package/dist/es/layouts/history-list/useHistoryList.js +56 -0
  100. package/dist/es/layouts/history-list/useHistoryRevert.js +317 -0
  101. package/dist/es/layouts/page-bar/AddButton.vue_vue_type_script_setup_true_lang.js +1 -1
  102. package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +5 -3
  103. package/dist/es/layouts/page-bar/PageBarScrollContainer.vue_vue_type_script_setup_true_lang.js +1 -1
  104. package/dist/es/layouts/page-bar/PageList.vue_vue_type_script_setup_true_lang.js +1 -1
  105. package/dist/es/layouts/page-bar/Search.vue_vue_type_script_setup_true_lang.js +2 -2
  106. package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +50 -7
  107. package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +33 -13
  108. package/dist/es/layouts/props-panel/use-style-panel.js +3 -2
  109. package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +3 -3
  110. package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +26 -38
  111. package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +4 -4
  112. package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +4 -4
  113. package/dist/es/layouts/sidebar/code-block/useContentMenu.js +19 -4
  114. package/dist/es/layouts/sidebar/data-source/DataSourceAddButton.vue_vue_type_script_setup_true_lang.js +1 -1
  115. package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +23 -6
  116. package/dist/es/layouts/sidebar/data-source/DataSourceList.vue_vue_type_script_setup_true_lang.js +1 -1
  117. package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +27 -5
  118. package/dist/es/layouts/sidebar/data-source/useContentMenu.js +19 -4
  119. package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +8 -8
  120. package/dist/es/layouts/sidebar/layer/LayerNodeContent.js +5 -0
  121. package/dist/es/layouts/sidebar/layer/LayerNodeContent.vue_vue_type_script_setup_true_lang.js +46 -0
  122. package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +2 -2
  123. package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +3 -2
  124. package/dist/es/layouts/sidebar/layer/use-click.js +3 -3
  125. package/dist/es/layouts/sidebar/layer/use-node-status.js +2 -2
  126. package/dist/es/layouts/workspace/Breadcrumb.vue_vue_type_script_setup_true_lang.js +1 -1
  127. package/dist/es/layouts/workspace/Workspace.vue_vue_type_script_setup_true_lang.js +1 -1
  128. package/dist/es/layouts/workspace/viewer/NodeListMenu.vue_vue_type_script_setup_true_lang.js +9 -3
  129. package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +2 -2
  130. package/dist/es/layouts/workspace/viewer/StageOverlay.vue_vue_type_script_setup_true_lang.js +1 -1
  131. package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +16 -16
  132. package/dist/es/plugin.js +5 -2
  133. package/dist/es/services/codeBlock.js +137 -56
  134. package/dist/es/services/dataSource.js +122 -52
  135. package/dist/es/services/dep.js +162 -41
  136. package/dist/es/services/editor.js +613 -179
  137. package/dist/es/services/history.js +350 -386
  138. package/dist/es/services/keybinding.js +6 -6
  139. package/dist/es/services/props.js +3 -2
  140. package/dist/es/services/storage.js +2 -2
  141. package/dist/es/services/ui.js +10 -2
  142. package/dist/es/style.css +549 -113
  143. package/dist/es/utils/config.js +4 -1
  144. package/dist/es/utils/const.js +2 -2
  145. package/dist/es/utils/content-menu.js +19 -11
  146. package/dist/es/utils/data-source/index.js +34 -11
  147. package/dist/es/utils/dep/collect-worker-client.js +114 -0
  148. package/dist/es/utils/dep/idle-task.js +47 -22
  149. package/dist/es/utils/dep/worker.js +1 -1
  150. package/dist/es/utils/editor.js +103 -49
  151. package/dist/es/utils/event.js +123 -0
  152. package/dist/es/utils/history.js +220 -0
  153. package/dist/es/utils/indexed-db.js +86 -0
  154. package/dist/es/utils/monaco-editor.js +22 -6
  155. package/dist/es/utils/operator.js +2 -2
  156. package/dist/es/utils/props.js +114 -33
  157. package/dist/es/utils/type-match-rules.js +367 -0
  158. package/dist/es/utils/undo-redo.js +60 -1
  159. package/dist/style.css +549 -113
  160. package/dist/themes/magic-admin.css +3028 -0
  161. package/dist/tmagic-editor.umd.cjs +14273 -10029
  162. package/package.json +8 -8
  163. package/src/Editor.vue +43 -2
  164. package/src/components/CodeBlockEditor.vue +3 -0
  165. package/src/components/CompareForm.vue +18 -146
  166. package/src/components/ContentMenu.vue +44 -8
  167. package/src/components/FloatingBox.vue +84 -9
  168. package/src/components/ScrollBar.vue +0 -67
  169. package/src/components/ToolButton.vue +2 -2
  170. package/src/components/ViewForm.vue +55 -0
  171. package/src/editorProps.ts +30 -0
  172. package/src/fields/Code.vue +10 -2
  173. package/src/fields/CodeLink.vue +2 -5
  174. package/src/fields/CodeSelect.vue +54 -40
  175. package/src/fields/CodeSelectCol.vue +8 -1
  176. package/src/fields/CondOpSelect.vue +2 -24
  177. package/src/fields/DataSourceFieldSelect/FieldSelect.vue +16 -2
  178. package/src/fields/DataSourceFieldSelect/Index.vue +14 -5
  179. package/src/fields/DataSourceFields.vue +42 -8
  180. package/src/fields/DataSourceInput.vue +10 -28
  181. package/src/fields/DataSourceMethodSelect.vue +9 -4
  182. package/src/fields/DataSourceMethods.vue +42 -21
  183. package/src/fields/DataSourceMocks.vue +3 -0
  184. package/src/fields/DisplayConds.vue +18 -1
  185. package/src/fields/EventSelect.vue +145 -161
  186. package/src/fields/StyleSetter/Index.vue +3 -12
  187. package/src/fields/StyleSetter/components/Border.vue +15 -6
  188. package/src/fields/StyleSetter/icons/align-items/Center.vue +19 -0
  189. package/src/fields/StyleSetter/icons/align-items/FlexEnd.vue +19 -0
  190. package/src/fields/StyleSetter/icons/align-items/FlexStart.vue +19 -0
  191. package/src/fields/StyleSetter/icons/align-items/SpaceAround.vue +34 -0
  192. package/src/fields/StyleSetter/icons/align-items/SpaceBetween.vue +34 -0
  193. package/src/fields/StyleSetter/icons/align-items/index.ts +5 -0
  194. package/src/fields/StyleSetter/icons/background-repeat/NoRepeat.vue +20 -4
  195. package/src/fields/StyleSetter/icons/background-repeat/Repeat.vue +10 -28
  196. package/src/fields/StyleSetter/icons/background-repeat/RepeatX.vue +4 -5
  197. package/src/fields/StyleSetter/icons/background-repeat/RepeatY.vue +4 -5
  198. package/src/fields/StyleSetter/icons/flex-direction/Column.vue +4 -3
  199. package/src/fields/StyleSetter/icons/flex-direction/ColumnReverse.vue +4 -3
  200. package/src/fields/StyleSetter/icons/flex-direction/Row.vue +4 -3
  201. package/src/fields/StyleSetter/icons/flex-direction/RowReverse.vue +4 -3
  202. package/src/fields/StyleSetter/icons/justify-content/Center.vue +5 -2
  203. package/src/fields/StyleSetter/icons/justify-content/FlexEnd.vue +15 -2
  204. package/src/fields/StyleSetter/icons/justify-content/FlexStart.vue +15 -2
  205. package/src/fields/StyleSetter/icons/justify-content/SpaceAround.vue +28 -3
  206. package/src/fields/StyleSetter/icons/justify-content/SpaceBetween.vue +28 -2
  207. package/src/fields/StyleSetter/pro/Background.vue +99 -55
  208. package/src/fields/StyleSetter/pro/Border.vue +9 -11
  209. package/src/fields/StyleSetter/pro/Font.vue +66 -64
  210. package/src/fields/StyleSetter/pro/Layout.vue +211 -139
  211. package/src/fields/StyleSetter/pro/Position.vue +69 -67
  212. package/src/fields/StyleSetter/pro/Transform.vue +23 -25
  213. package/src/fields/UISelect.vue +0 -12
  214. package/src/hooks/index.ts +1 -0
  215. package/src/hooks/use-code-block-edit.ts +4 -3
  216. package/src/hooks/use-compare-form.ts +187 -0
  217. package/src/hooks/use-data-source-edit.ts +2 -2
  218. package/src/hooks/use-stage.ts +5 -3
  219. package/src/icons/DatasourceIcon.vue +7 -0
  220. package/src/index.ts +12 -0
  221. package/src/initService.ts +26 -16
  222. package/src/layouts/CodeEditor.vue +34 -11
  223. package/src/layouts/Framework.vue +15 -8
  224. package/src/layouts/NavMenu.vue +3 -3
  225. package/src/layouts/history-list/Bucket.vue +33 -41
  226. package/src/layouts/history-list/BucketTab.vue +72 -0
  227. package/src/layouts/history-list/GroupRow.vue +190 -93
  228. package/src/layouts/history-list/HistoryDiffDialog.vue +169 -90
  229. package/src/layouts/history-list/HistoryListPanel.vue +191 -95
  230. package/src/layouts/history-list/InitialRow.vue +38 -8
  231. package/src/layouts/history-list/PageTab.vue +67 -43
  232. package/src/layouts/history-list/composables.ts +239 -125
  233. package/src/layouts/history-list/useHistoryList.ts +60 -0
  234. package/src/layouts/history-list/useHistoryRevert.ts +425 -0
  235. package/src/layouts/page-bar/PageBar.vue +4 -2
  236. package/src/layouts/props-panel/FormPanel.vue +72 -6
  237. package/src/layouts/props-panel/PropsPanel.vue +62 -18
  238. package/src/layouts/props-panel/use-style-panel.ts +4 -3
  239. package/src/layouts/sidebar/ComponentListPanel.vue +10 -6
  240. package/src/layouts/sidebar/Sidebar.vue +13 -6
  241. package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
  242. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +5 -2
  243. package/src/layouts/sidebar/code-block/useContentMenu.ts +14 -2
  244. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +34 -2
  245. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +29 -4
  246. package/src/layouts/sidebar/data-source/useContentMenu.ts +14 -2
  247. package/src/layouts/sidebar/layer/LayerMenu.vue +21 -13
  248. package/src/layouts/sidebar/layer/LayerNodeContent.vue +57 -0
  249. package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
  250. package/src/layouts/sidebar/layer/LayerPanel.vue +4 -1
  251. package/src/layouts/sidebar/layer/use-click.ts +3 -3
  252. package/src/layouts/sidebar/layer/use-node-status.ts +2 -2
  253. package/src/layouts/workspace/viewer/NodeListMenu.vue +4 -1
  254. package/src/layouts/workspace/viewer/Stage.vue +1 -1
  255. package/src/layouts/workspace/viewer/ViewerMenu.vue +15 -15
  256. package/src/plugin.ts +6 -3
  257. package/src/services/codeBlock.ts +152 -47
  258. package/src/services/dataSource.ts +120 -41
  259. package/src/services/dep.ts +292 -47
  260. package/src/services/editor.ts +820 -224
  261. package/src/services/history.ts +449 -412
  262. package/src/services/keybinding.ts +6 -6
  263. package/src/services/ui.ts +33 -5
  264. package/src/theme/code-block.scss +37 -0
  265. package/src/theme/common/var.scss +1 -1
  266. package/src/theme/component-list-panel.scss +2 -2
  267. package/src/theme/data-source-field.scss +4 -0
  268. package/src/theme/display-conds.scss +11 -0
  269. package/src/theme/event.scss +70 -1
  270. package/src/theme/floating-box.scss +9 -1
  271. package/src/theme/framework.scss +4 -1
  272. package/src/theme/history-list-panel.scss +157 -23
  273. package/src/theme/layer-node-content.scss +14 -0
  274. package/src/theme/nav-menu.scss +5 -1
  275. package/src/theme/page-bar.scss +0 -4
  276. package/src/theme/props-panel.scss +5 -4
  277. package/src/theme/scroll-bar.scss +64 -0
  278. package/src/theme/style-setter/border.scss +17 -5
  279. package/src/theme/theme.scss +4 -0
  280. package/src/theme/themes/magic-admin/index.scss +214 -0
  281. package/src/theme/ui-select.scss +9 -0
  282. package/src/type.ts +668 -124
  283. package/src/utils/config.ts +9 -1
  284. package/src/utils/const.ts +3 -2
  285. package/src/utils/content-menu.ts +20 -11
  286. package/src/utils/data-source/index.ts +32 -12
  287. package/src/utils/dep/collect-worker-client.ts +149 -0
  288. package/src/utils/dep/idle-task.ts +72 -35
  289. package/src/utils/dep/worker.ts +113 -9
  290. package/src/utils/editor.ts +166 -60
  291. package/src/utils/event.ts +224 -0
  292. package/src/utils/history.ts +286 -0
  293. package/src/utils/index.ts +4 -0
  294. package/src/utils/indexed-db.ts +122 -0
  295. package/src/utils/monaco-editor.ts +27 -0
  296. package/src/utils/operator.ts +2 -2
  297. package/src/utils/props.ts +114 -11
  298. package/src/utils/type-match-rules.ts +684 -0
  299. package/src/utils/undo-redo.ts +88 -0
  300. package/types/index.d.ts +1979 -515
  301. package/dist/es/layouts/history-list/CodeBlockTab.js +0 -5
  302. package/dist/es/layouts/history-list/CodeBlockTab.vue_vue_type_script_setup_true_lang.js +0 -62
  303. package/dist/es/layouts/history-list/DataSourceTab.js +0 -5
  304. package/dist/es/layouts/history-list/DataSourceTab.vue_vue_type_script_setup_true_lang.js +0 -62
  305. package/src/layouts/history-list/CodeBlockTab.vue +0 -61
  306. package/src/layouts/history-list/DataSourceTab.vue +0 -61
@@ -6,7 +6,7 @@ import { tMagicMessage } from '@tmagic/design';
6
6
  import type { ContainerChangeEventData } from '@tmagic/form';
7
7
 
8
8
  import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
9
- import type { Services } from '@editor/type';
9
+ import type { HistoryOpSource, Services } from '@editor/type';
10
10
 
11
11
  export const useCodeBlockEdit = (codeBlockService: Services['codeBlockService']) => {
12
12
  const codeConfig = ref<Omit<CodeBlockContent, 'content'> & { content: string }>();
@@ -58,8 +58,8 @@ export const useCodeBlockEdit = (codeBlockService: Services['codeBlockService'])
58
58
  };
59
59
 
60
60
  // 删除代码块
61
- const deleteCode = async (key: string) => {
62
- codeBlockService.deleteCodeDslByIds([key]);
61
+ const deleteCode = async (key: string, { historySource }: { historySource?: HistoryOpSource } = {}) => {
62
+ codeBlockService.deleteCodeDslByIds([key], { historySource });
63
63
  };
64
64
 
65
65
  const submitCodeBlockHandler = async (values: CodeBlockContent, eventData?: ContainerChangeEventData) => {
@@ -67,6 +67,7 @@ export const useCodeBlockEdit = (codeBlockService: Services['codeBlockService'])
67
67
 
68
68
  await codeBlockService.setCodeDslById(codeId.value, values, {
69
69
  changeRecords: eventData?.changeRecords,
70
+ historySource: 'props',
70
71
  });
71
72
 
72
73
  codeBlockEditorRef.value?.hide();
@@ -0,0 +1,187 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making TMagicEditor available.
3
+ *
4
+ * Copyright (C) 2025 Tencent. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import { computed, type ComputedRef, inject, provide, type Ref, ref, useTemplateRef, watch, watchEffect } from 'vue';
20
+
21
+ import type { CodeBlockContent, MNode } from '@tmagic/core';
22
+ import { type FormConfig, type FormState, type FormValue, MForm } from '@tmagic/form';
23
+
24
+ import type { CompareFormBaseProps } from '@editor/type';
25
+ import { getCodeBlockFormConfig } from '@editor/utils/code-block';
26
+ import { removeStyleDisplayConfig } from '@editor/utils/props';
27
+
28
+ export interface UseCompareFormReturn {
29
+ config: Ref<FormConfig>;
30
+ currentValues: ComputedRef<FormValue>;
31
+ wrapperStyle: ComputedRef<Record<string, string> | undefined>;
32
+ mergedExtendState: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
33
+ loadConfig: () => Promise<void>;
34
+ formRef: Readonly<Ref<InstanceType<typeof MForm> | null>>;
35
+ normalizeCodeBlockValue: (v: Partial<CodeBlockContent> | Record<string, any> | undefined) => Record<string, any>;
36
+ }
37
+
38
+ /**
39
+ * CompareForm / ViewForm 共用逻辑:
40
+ * - 按 `category`(node / data-source / code-block) 加载 FormConfig(支持自定义 `loadConfig`);
41
+ * - 代码块 `content` 归一化为字符串;
42
+ * - 外层容器固定高度 + 内部滚动的 `wrapperStyle`;
43
+ * - 将 services / stage 注入 MForm.formState,保证 filterFunction 上下文一致。
44
+ *
45
+ * 两个组件的差异仅在于是否做新旧值对比,这部分逻辑保留在各自组件中。
46
+ */
47
+ export const useCompareForm = (props: CompareFormBaseProps): UseCompareFormReturn => {
48
+ provide('services', props.services);
49
+
50
+ const config = ref<FormConfig>([]);
51
+
52
+ /** vs-code 编辑器的 monaco 配置项,沿用 Editor 顶层 provide('codeOptions', ...) 的注入。 */
53
+ const codeOptions = inject<Record<string, any>>('codeOptions', {});
54
+
55
+ /** 将代码块的 content 字段统一成字符串,便于在表单 / 对比中展示 */
56
+ const normalizeCodeBlockValue = (
57
+ v: Partial<CodeBlockContent> | Record<string, any> | undefined,
58
+ ): Record<string, any> => {
59
+ if (!v) return {};
60
+ const next: Record<string, any> = { ...v };
61
+ if (next.content && typeof next.content !== 'string') {
62
+ try {
63
+ next.content = next.content.toString();
64
+ } catch {
65
+ next.content = '';
66
+ }
67
+ }
68
+ return next;
69
+ };
70
+
71
+ const currentValues = computed<FormValue>(() => {
72
+ if (props.category === 'code-block') {
73
+ return normalizeCodeBlockValue(props.value as Partial<CodeBlockContent>);
74
+ }
75
+ return (props.value || {}) as FormValue;
76
+ });
77
+
78
+ /**
79
+ * 外层包裹层的样式:当传入 `height` 时启用固定高度 + 内部滚动,
80
+ * 这样滚动条会出现在组件内部,避免父容器(如 Dialog)自身也产生滚动。
81
+ */
82
+ const wrapperStyle = computed(() => {
83
+ if (!props.height) return undefined;
84
+ const style: Record<string, string> = {
85
+ height: props.height,
86
+ overflow: 'auto',
87
+ };
88
+ return style;
89
+ });
90
+
91
+ const mergedExtendState = (state: FormState) => {
92
+ const extendState = props.extendState ?? ((s: FormState) => s);
93
+ return extendState(props.baseFormState || state);
94
+ };
95
+
96
+ /**
97
+ * 内置的默认 FormConfig 加载逻辑:按 `category` 从对应 service / 工具取配置。
98
+ * 作为 ctx.defaultLoadConfig 透传给自定义 `loadConfig`,方便复用与二次加工。
99
+ */
100
+ const defaultLoadConfig = async (): Promise<FormConfig> => {
101
+ if (!props.services) {
102
+ return [];
103
+ }
104
+
105
+ switch (props.category) {
106
+ case 'node': {
107
+ if (!props.type) {
108
+ return [];
109
+ }
110
+ return removeStyleDisplayConfig(
111
+ await props.services.propsService.getPropsConfig(props.type, { node: props.value as unknown as MNode }),
112
+ );
113
+ }
114
+ case 'data-source': {
115
+ const config = props.services.dataSourceService.getFormConfig(props.type || 'base');
116
+ // 数据源表单外层 tab 的「数据定义」项 status 为 'fields',tab-pane name 随之为 'fields'。
117
+ // 未显式设置 active 时,Tabs 默认取 '0',与 'fields' 不匹配会导致打开弹窗时无默认激活项,
118
+ // 这里与 DataSourceConfigPanel 保持一致,默认激活「数据定义」tab。
119
+ return config.map((item) => ('type' in item && item.type === 'tab' ? { ...item, active: 'fields' } : item));
120
+ }
121
+ case 'code-block': {
122
+ return getCodeBlockFormConfig({
123
+ paramColConfig: props.services.codeBlockService.getParamsColConfig(),
124
+ // 通过传入 dataSourceType 间接表达"是数据源代码块"——在对比 / 展示场景下 props.dataSourceType
125
+ // 由调用方按 step 上下文显式传入,未传则视为普通代码块,「执行时机」字段隐藏。
126
+ isDataSource: () => Boolean(props.dataSourceType),
127
+ dataSourceType: () => props.dataSourceType,
128
+ codeOptions,
129
+ // 对比 / 展示模式只读,不需要校验/语法检查
130
+ editable: false,
131
+ });
132
+ }
133
+ default:
134
+ return [];
135
+ }
136
+ };
137
+
138
+ const loadConfig = async () => {
139
+ if (props.loadConfig) {
140
+ config.value = await props.loadConfig({
141
+ category: props.category as string,
142
+ type: props.type,
143
+ dataSourceType: props.dataSourceType,
144
+ defaultLoadConfig,
145
+ });
146
+ return;
147
+ }
148
+
149
+ config.value = await defaultLoadConfig();
150
+ };
151
+
152
+ watch(
153
+ [() => props.category, () => props.type, () => props.dataSourceType, () => props.loadConfig],
154
+ () => {
155
+ loadConfig();
156
+ },
157
+ { immediate: true },
158
+ );
159
+
160
+ const formRef = useTemplateRef<InstanceType<typeof MForm>>('form');
161
+
162
+ /**
163
+ * 把 services / stage 注入 MForm 的 formState,避免 propsService 注入的表单配置中
164
+ * 形如 `display: ({ services }) => services.uiService.get(...)` 的 filterFunction
165
+ * 在执行时拿不到 `formState.services` 而报错。
166
+ *
167
+ * 与 props-panel/FormPanel.vue 中的注入方式保持一致:
168
+ * - services:整个 useServices() 返回的服务集合;
169
+ * - stage:当前 editorService.get('stage') 的最新值。
170
+ */
171
+ watchEffect(() => {
172
+ if (formRef.value && props.services) {
173
+ formRef.value.formState.stage = props.services.editorService.get('stage');
174
+ formRef.value.formState.services = props.services;
175
+ }
176
+ });
177
+
178
+ return {
179
+ config,
180
+ currentValues,
181
+ wrapperStyle,
182
+ mergedExtendState,
183
+ loadConfig,
184
+ formRef,
185
+ normalizeCodeBlockValue,
186
+ };
187
+ };
@@ -27,9 +27,9 @@ export const useDataSourceEdit = (dataSourceService: Services['dataSourceService
27
27
 
28
28
  const submitDataSourceHandler = (value: DataSourceSchema, eventData: ContainerChangeEventData) => {
29
29
  if (value.id) {
30
- dataSourceService.update(value, { changeRecords: eventData.changeRecords });
30
+ dataSourceService.update(value, { changeRecords: eventData.changeRecords, historySource: 'props' });
31
31
  } else {
32
- dataSourceService.add(value);
32
+ dataSourceService.add(value, { historySource: 'props' });
33
33
  }
34
34
 
35
35
  editDialog.value?.hide();
@@ -28,6 +28,7 @@ export const useStage = (stageOptions: StageOptions) => {
28
28
  containerHighlightClassName: stageOptions.containerHighlightClassName,
29
29
  containerHighlightDuration: stageOptions.containerHighlightDuration,
30
30
  containerHighlightType: stageOptions.containerHighlightType,
31
+ containerHighlightAddOnly: stageOptions.containerHighlightAddOnly,
31
32
  disabledDragStart: stageOptions.disabledDragStart,
32
33
  renderType: stageOptions.renderType,
33
34
  canSelect: (el, event, stop) => {
@@ -48,6 +49,7 @@ export const useStage = (stageOptions: StageOptions) => {
48
49
  disabledMultiSelect: stageOptions.disabledMultiSelect,
49
50
  alwaysMultiSelect: stageOptions.alwaysMultiSelect,
50
51
  disabledRule: stageOptions.disabledRule,
52
+ disabledFlashTip: stageOptions.disabledFlashTip,
51
53
  });
52
54
 
53
55
  watch(
@@ -129,16 +131,16 @@ export const useStage = (stageOptions: StageOptions) => {
129
131
  });
130
132
  if (configs.length === 0) return;
131
133
 
132
- editorService.update(configs, { changeRecordList });
134
+ editorService.update(configs, { changeRecordList, historySource: 'stage' });
133
135
  });
134
136
 
135
137
  stage.on('sort', (ev: SortEventData) => {
136
- editorService.sort(ev.src, ev.dist);
138
+ editorService.sort(ev.src, ev.dist, { historySource: 'stage' });
137
139
  });
138
140
 
139
141
  stage.on('remove', (ev: RemoveEventData) => {
140
142
  const nodes = ev.data.map(({ el }) => editorService.getNodeById(getIdFromEl()(el) || ''));
141
- editorService.remove(nodes.filter((node) => Boolean(node)) as MNode[]);
143
+ editorService.remove(nodes.filter((node) => Boolean(node)) as MNode[], { historySource: 'stage' });
142
144
  });
143
145
 
144
146
  stage.on('select-parent', () => {
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
3
+ <path
4
+ d="M6.25 9.723C4.392 9.6095 2.804 9.137 1.875 8.4775V9.7495C1.875 10.6165 3.7665 11.3365 6.25 11.4745V12.348C4.392 12.2345 2.804 11.763 1.875 11.102V12.3745H1V4.0625C1 2.371 3.742 1 7.125 1C10.507 1 13.249 2.371 13.249 4.0625V6.8255H12.374V5.6405C11.3025 6.5295 9.352 7.1245 7.1245 7.1245C4.897 7.1245 2.947 6.5295 1.8745 5.6405V7.1245C1.8745 7.9915 3.7665 8.712 6.2495 8.85L6.25 9.723ZM7.125 14.999C3.742 14.999 1 13.8245 1 12.3745H1.875C1.875 13.3415 4.225 14.124 7.125 14.124V14.999ZM7.125 6.2495C10.024 6.2495 12.3745 5.2695 12.3745 4.0625C12.3745 2.855 10.0245 1.875 7.1245 1.875C4.225 1.875 1.8745 2.855 1.8745 4.0625C1.8745 5.2695 4.2255 6.2495 7.125 6.2495ZM14.7385 11.9895L14.1295 11.6345C14.1635 11.4485 14.1855 11.2585 14.1855 11.062C14.1843 10.8697 14.1655 10.6779 14.1295 10.489L14.7385 10.134C14.988 9.987 15.073 9.667 14.929 9.416L14.409 8.507C14.3752 8.44726 14.3299 8.39483 14.2757 8.35275C14.2215 8.31066 14.1595 8.27977 14.0933 8.26186C14.027 8.24395 13.9579 8.23938 13.8898 8.24842C13.8218 8.25745 13.7563 8.27992 13.697 8.3145L13.081 8.6735C12.7931 8.42269 12.4616 8.22694 12.103 8.096V7.6495C12.103 7.36 11.8705 7.1245 11.5825 7.1245H10.5415C10.4728 7.12476 10.4049 7.13855 10.3415 7.16507C10.2782 7.1916 10.2206 7.23034 10.1723 7.2791C10.1239 7.32785 10.0856 7.38565 10.0595 7.4492C10.0335 7.51276 10.0202 7.58082 10.0205 7.6495V8.096C9.66186 8.22694 9.33035 8.42269 9.0425 8.6735L8.4265 8.3145C8.36725 8.27999 8.30174 8.2576 8.23377 8.2486C8.1658 8.23961 8.09672 8.24419 8.03053 8.2621C7.96435 8.28001 7.90238 8.31088 7.84821 8.35292C7.79405 8.39495 7.74877 8.44733 7.715 8.507L7.195 9.417C7.12576 9.53751 7.10688 9.68047 7.14246 9.81482C7.17804 9.94917 7.2652 10.0641 7.385 10.1345L7.9945 10.489C7.9585 10.6775 7.9395 10.8695 7.9385 11.062C7.9385 11.2585 7.96 11.4485 7.9945 11.635L7.3855 11.99C7.1355 12.1365 7.0505 12.4565 7.1945 12.7075L7.715 13.6165C7.74877 13.6762 7.79405 13.7285 7.84821 13.7706C7.90238 13.8126 7.96435 13.8435 8.03053 13.8614C8.09672 13.8793 8.1658 13.8839 8.23377 13.8749C8.30174 13.8659 8.36725 13.8435 8.4265 13.809L9.0425 13.4505C9.33023 13.7015 9.66178 13.8972 10.0205 14.028V14.474C10.0205 14.764 10.2535 14.999 10.5415 14.999H11.5825C11.7211 14.9983 11.8538 14.9427 11.9514 14.8442C12.049 14.7458 12.1035 14.6126 12.103 14.474V14.028C12.4616 13.8971 12.7931 13.7013 13.081 13.4505L13.697 13.809C13.7563 13.8434 13.8218 13.8657 13.8897 13.8746C13.9577 13.8835 14.0267 13.8789 14.0929 13.861C14.159 13.8431 14.221 13.8123 14.2751 13.7703C14.3293 13.7283 14.3746 13.6761 14.4085 13.6165L14.929 12.7065C14.998 12.586 15.0168 12.4431 14.9811 12.3089C14.9454 12.1746 14.8583 12.0599 14.7385 11.9895ZM14.092 12.5065L13.852 12.915C13.8193 12.9693 13.7667 13.0086 13.7054 13.0246C13.6441 13.0406 13.579 13.0319 13.524 13.0005L12.8575 12.623C12.5109 13.0069 12.0497 13.2688 11.5425 13.37V13.889C11.5425 14.0185 11.4345 14.124 11.3015 14.124H10.822C10.7907 14.1243 10.7597 14.1184 10.7308 14.1067C10.7018 14.0949 10.6754 14.0776 10.6531 14.0557C10.6308 14.0338 10.6131 14.0077 10.6009 13.9789C10.5887 13.9502 10.5823 13.9193 10.582 13.888V13.37C10.0746 13.2689 9.61328 13.007 9.2665 12.623L8.6 13C8.54495 13.0316 8.47971 13.0403 8.4183 13.0243C8.35688 13.0083 8.30418 12.9689 8.2715 12.9145L8.0315 12.506C8.01582 12.4792 8.00564 12.4496 8.00158 12.4189C7.99752 12.3881 7.99965 12.3569 8.00785 12.327C8.01605 12.297 8.03016 12.2691 8.04933 12.2447C8.0685 12.2203 8.09236 12.2 8.1195 12.185L8.789 11.805C8.70604 11.5658 8.66313 11.3146 8.662 11.0615C8.662 10.8005 8.709 10.552 8.7895 10.3175L8.1195 9.9375C8.09247 9.92244 8.06872 9.90213 8.04964 9.87777C8.03056 9.85341 8.01654 9.82549 8.00839 9.79564C8.00024 9.76579 7.99813 9.73461 8.00218 9.70394C8.00624 9.67326 8.01637 9.64371 8.032 9.617L8.272 9.208C8.30467 9.15373 8.35729 9.1144 8.41858 9.09843C8.47988 9.08245 8.54499 9.09109 8.6 9.1225L9.2665 9.5005C9.61315 9.11663 10.0743 8.85468 10.5815 8.7535V8.235C10.5815 8.105 10.689 8 10.822 8H11.302C11.4345 8 11.542 8.105 11.542 8.236V8.754C12.0492 8.85518 12.5104 9.11713 12.857 9.501L13.524 9.123C13.579 9.09159 13.6441 9.08295 13.7054 9.09893C13.7667 9.1149 13.8193 9.15423 13.852 9.2085L14.092 9.6175C14.1077 9.64423 14.1179 9.67383 14.122 9.70455C14.1261 9.73528 14.124 9.76652 14.1159 9.79643C14.1077 9.82634 14.0937 9.85431 14.0745 9.87871C14.0554 9.90311 14.0316 9.92344 14.0045 9.9385L13.335 10.3185C13.4135 10.5525 13.462 10.801 13.462 11.062C13.462 11.3225 13.4145 11.571 13.335 11.8055L14.0045 12.1855C14.0316 12.2006 14.0554 12.2209 14.0745 12.2453C14.0937 12.2697 14.1077 12.2977 14.1159 12.3276C14.124 12.3575 14.1261 12.3887 14.122 12.4194C14.1179 12.4502 14.1077 12.4798 14.092 12.5065ZM11.062 9.7495C10.7139 9.7495 10.3801 9.88778 10.1339 10.1339C9.88778 10.3801 9.7495 10.7139 9.7495 11.062C9.7495 11.4101 9.88778 11.7439 10.1339 11.9901C10.3801 12.2362 10.7139 12.3745 11.062 12.3745C11.4101 12.3745 11.7439 12.2362 11.9901 11.9901C12.2362 11.7439 12.3745 11.4101 12.3745 11.062C12.3745 10.7139 12.2362 10.3801 11.9901 10.1339C11.7439 9.88778 11.4101 9.7495 11.062 9.7495ZM11.062 11.4995C10.946 11.4995 10.8347 11.4534 10.7526 11.3714C10.6706 11.2893 10.6245 11.178 10.6245 11.062C10.6245 10.946 10.6706 10.8347 10.7526 10.7526C10.8347 10.6706 10.946 10.6245 11.062 10.6245C11.178 10.6245 11.2893 10.6706 11.3714 10.7526C11.4534 10.8347 11.4995 10.946 11.4995 11.062C11.4995 11.178 11.4534 11.2893 11.3714 11.3714C11.2893 11.4534 11.178 11.4995 11.062 11.4995Z"
5
+ />
6
+ </svg>
7
+ </template>
package/src/index.ts CHANGED
@@ -32,6 +32,9 @@ export { DepTargetType } from '@tmagic/core';
32
32
  export * from './type';
33
33
  export * from './hooks';
34
34
  export * from './utils';
35
+ // `isGlobalFlat` 同时在 `@tmagic/design` 和 `./utils/config` 中存在,
36
+ // 通过显式重导一次消除 `export *` 带来的歧义,并固定使用 editor 自己那份。
37
+ export { isGlobalFlat } from './utils/config';
35
38
  export { default as TMagicEditor } from './Editor.vue';
36
39
  export { default as TMagicCodeEditor } from './layouts/CodeEditor.vue';
37
40
  export { default as editorService } from './services/editor';
@@ -44,8 +47,11 @@ export { default as stageOverlayService } from './services/stageOverlay';
44
47
  export { default as uiService } from './services/ui';
45
48
  export { default as codeBlockService } from './services/codeBlock';
46
49
  export { default as depService } from './services/dep';
50
+ export { default as componentListService } from './services/componentList';
51
+ export { default as keybindingService } from './services/keybinding';
47
52
  export { default as ComponentListPanel } from './layouts/sidebar/ComponentListPanel.vue';
48
53
  export { default as LayerPanel } from './layouts/sidebar/layer/LayerPanel.vue';
54
+ export { default as LayerNodeContent } from './layouts/sidebar/layer/LayerNodeContent.vue';
49
55
  export { default as CodeSelect } from './fields/CodeSelect.vue';
50
56
  export { default as CodeSelectCol } from './fields/CodeSelectCol.vue';
51
57
  export { default as DataSourceFields } from './fields/DataSourceFields.vue';
@@ -71,6 +77,12 @@ export { default as SplitView } from './components/SplitView.vue';
71
77
  export { default as Resizer } from './components/Resizer.vue';
72
78
  export { default as CodeBlockEditor } from './components/CodeBlockEditor.vue';
73
79
  export { default as CompareForm } from './components/CompareForm.vue';
80
+ export { default as ViewForm } from './components/ViewForm.vue';
81
+ export { default as HistoryListBucket } from './layouts/history-list/Bucket.vue';
82
+ export { default as HistoryListBucketTab } from './layouts/history-list/BucketTab.vue';
83
+ export { default as HistoryDiffDialog } from './layouts/history-list/HistoryDiffDialog.vue';
84
+ export { confirmHistoryAction } from './layouts/history-list/composables';
85
+ export { useHistoryRevert } from './layouts/history-list/useHistoryRevert';
74
86
  export { default as FloatingBox } from './components/FloatingBox.vue';
75
87
  export { default as Tree } from './components/Tree.vue';
76
88
  export { default as TreeNode } from './components/TreeNode.vue';
@@ -55,7 +55,7 @@ export const initServiceState = (
55
55
  watch(
56
56
  () => props.modelValue,
57
57
  (modelValue) => {
58
- editorService.set('root', modelValue || null);
58
+ editorService.set('root', modelValue || null, { historySource: 'initial' });
59
59
  },
60
60
  {
61
61
  immediate: true,
@@ -333,11 +333,11 @@ export const initServiceEvents = (
333
333
  Promise.all(
334
334
  nodes.map((node) => {
335
335
  if (node.type === NodeType.ROOT) {
336
- return Promise.resolve();
336
+ return Promise.resolve(true);
337
337
  }
338
338
  return depService.collectIdle([node], { pageId: getPageIdByNode(node) }, deep, type);
339
339
  }),
340
- );
340
+ ).then((results) => results.every(Boolean));
341
341
 
342
342
  watch(
343
343
  () => editorService.get('stage'),
@@ -351,7 +351,7 @@ export const initServiceEvents = (
351
351
 
352
352
  if (!node) return;
353
353
 
354
- await collectIdle([node], true, DepTargetType.DATA_SOURCE);
354
+ if (!(await collectIdle([node], true, DepTargetType.DATA_SOURCE))) return;
355
355
  updateStageNode(node);
356
356
  });
357
357
  },
@@ -494,8 +494,10 @@ export const initServiceEvents = (
494
494
 
495
495
  // 新增节点,收集依赖
496
496
  const nodeAddHandler = (nodes: MComponent[]) => {
497
- collectIdle(nodes, true).then(() => {
498
- updateStageNodes(nodes);
497
+ collectIdle(nodes, true).then((completed) => {
498
+ if (completed) {
499
+ updateStageNodes(nodes);
500
+ }
499
501
  });
500
502
  };
501
503
 
@@ -549,8 +551,8 @@ export const initServiceEvents = (
549
551
  if (needRecollectNodes.length) {
550
552
  // 有数据源依赖,需要等依赖重新收集完才更新stage
551
553
  const handler = async () => {
552
- await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE);
553
- await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE_COND);
554
+ if (!(await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE))) return;
555
+ if (!(await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE_COND))) return;
554
556
  updateStageNodes(needRecollectNodes);
555
557
  };
556
558
  handler();
@@ -572,8 +574,10 @@ export const initServiceEvents = (
572
574
 
573
575
  // 历史记录变化时,需要重新收集依赖
574
576
  const historyChangeHandler = (page: MPage | MPageFragment) => {
575
- collectIdle([page], true).then(() => {
576
- updateStageNode(page);
577
+ collectIdle([page], true).then((completed) => {
578
+ if (completed) {
579
+ updateStageNode(page);
580
+ }
577
581
  });
578
582
  };
579
583
 
@@ -654,7 +658,7 @@ export const initServiceEvents = (
654
658
  if (Array.isArray(root?.items)) {
655
659
  depService.clearIdleTasks();
656
660
 
657
- let collectIdlePromises: Promise<void[]>[] = [];
661
+ let collectIdlePromises: Promise<boolean>[] = [];
658
662
  if (isModifyField) {
659
663
  depService.removeTarget(config.id, DepTargetType.DATA_SOURCE);
660
664
  depService.removeTarget(config.id, DepTargetType.DATA_SOURCE_COND);
@@ -679,10 +683,15 @@ export const initServiceEvents = (
679
683
 
680
684
  collectIdlePromises = [collectIdle(root.items, true, DepTargetType.DATA_SOURCE_METHOD)];
681
685
  }
682
- Promise.all(collectIdlePromises)
683
- .then(() => updateDataSourceSchema())
684
- .then(() => updateDsData())
685
- .then(() => updateStageNodes(root.items));
686
+ const handler = async () => {
687
+ const results = await Promise.all(collectIdlePromises);
688
+ if (!results.every(Boolean)) return;
689
+
690
+ updateDataSourceSchema();
691
+ await updateDsData();
692
+ updateStageNodes(root.items);
693
+ };
694
+ handler();
686
695
  }
687
696
  } else if (root?.dataSources) {
688
697
  updateDsData();
@@ -706,11 +715,12 @@ export const initServiceEvents = (
706
715
  const nodeIds = Object.keys(root.dataSourceDeps?.[id] || {});
707
716
  const nodes = getNodes(nodeIds, root.items);
708
717
 
709
- await Promise.all([
718
+ const results = await Promise.all([
710
719
  collectIdle(nodes, false, DepTargetType.DATA_SOURCE),
711
720
  collectIdle(nodes, false, DepTargetType.DATA_SOURCE_COND),
712
721
  collectIdle(nodes, false, DepTargetType.DATA_SOURCE_METHOD),
713
722
  ]);
723
+ if (!results.every(Boolean)) return;
714
724
 
715
725
  updateDataSourceSchema();
716
726
 
@@ -21,12 +21,12 @@ import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, useTe
21
21
  import { FullScreen } from '@element-plus/icons-vue';
22
22
  import { throttle } from 'lodash-es';
23
23
  import type * as Monaco from 'monaco-editor';
24
- import serialize from 'serialize-javascript';
25
24
 
26
25
  import { TMagicButton } from '@tmagic/design';
27
26
 
28
27
  import MIcon from '@editor/components/Icon.vue';
29
28
  import { getEditorConfig } from '@editor/utils/config';
29
+ import { serializeConfig } from '@editor/utils/editor';
30
30
  import loadMonaco from '@editor/utils/monaco-editor';
31
31
 
32
32
  defineOptions({
@@ -163,10 +163,7 @@ const toString = (v: string | any, language: string): string => {
163
163
  if (language === 'json') {
164
164
  value = JSON.stringify(v, null, 2);
165
165
  } else {
166
- value = serialize(v, {
167
- space: 2,
168
- unsafe: true,
169
- }).replace(/"(\w+)":\s/g, '$1: ');
166
+ value = serializeConfig(v);
170
167
  }
171
168
  } else {
172
169
  value = v;
@@ -197,6 +194,9 @@ const values = ref('');
197
194
  const loading = ref(false);
198
195
  const codeEditorEl = useTemplateRef<HTMLDivElement>('codeEditor');
199
196
 
197
+ // 组件是否已卸载,避免异步初始化过程中组件被销毁后继续创建编辑器
198
+ let destroyed = false;
199
+
200
200
  const resizeObserver = new globalThis.ResizeObserver(
201
201
  throttle((): void => {
202
202
  vsEditor?.layout();
@@ -257,11 +257,18 @@ const handleKeyDown = (e: KeyboardEvent) => {
257
257
  }
258
258
  };
259
259
 
260
+ // 判断容器是否仍然有效:组件未卸载、ref 存在且已挂载到文档树中
261
+ // Monaco 在创建编辑器时会向上遍历 parentNode 判断是否处于 shadow DOM,
262
+ // 若容器为 null 或已从文档树脱离,将抛出 "Cannot read properties of null (reading 'parentNode')"
263
+ const isEditorElValid = () => !destroyed && !!codeEditorEl.value && codeEditorEl.value.isConnected;
264
+
260
265
  const init = async () => {
261
- if (!codeEditorEl.value) return;
266
+ if (!isEditorElValid()) return;
262
267
 
263
- if (codeEditorEl.value.clientHeight === 0) {
268
+ if (codeEditorEl.value!.clientHeight === 0) {
264
269
  await nextTick();
270
+ // await 期间组件可能已被卸载或容器被移除
271
+ if (!isEditorElValid()) return;
265
272
  }
266
273
 
267
274
  // 重置缓存的额外高度,因为编辑器重新初始化
@@ -269,6 +276,11 @@ const init = async () => {
269
276
 
270
277
  monaco = await loadMonaco();
271
278
 
279
+ // 加载 monaco 是异步过程,期间组件可能已被卸载或容器被移除
280
+ if (!isEditorElValid()) return;
281
+
282
+ const editorEl = codeEditorEl.value!;
283
+
272
284
  const options = {
273
285
  value: values.value,
274
286
  language: props.language,
@@ -278,7 +290,7 @@ const init = async () => {
278
290
  };
279
291
 
280
292
  if (props.type === 'diff') {
281
- vsDiffEditor = await getEditorConfig('customCreateMonacoDiffEditor')(monaco!, codeEditorEl.value, options);
293
+ vsDiffEditor = await getEditorConfig('customCreateMonacoDiffEditor')(monaco!, editorEl, options);
282
294
 
283
295
  // 监听diff编辑器内容变化
284
296
  vsDiffEditor.getModifiedEditor().onDidChangeModelContent(() => {
@@ -288,7 +300,7 @@ const init = async () => {
288
300
  }
289
301
  });
290
302
  } else {
291
- vsEditor = await getEditorConfig('customCreateMonacoEditor')(monaco!, codeEditorEl.value, options);
303
+ vsEditor = await getEditorConfig('customCreateMonacoEditor')(monaco!, editorEl, options);
292
304
 
293
305
  // 监听编辑器内容变化
294
306
  vsEditor.onDidChangeModelContent(() => {
@@ -299,10 +311,19 @@ const init = async () => {
299
311
  });
300
312
  }
301
313
 
314
+ // 编辑器创建可能是异步的,创建完成后若组件已卸载则立即销毁,避免内存泄漏
315
+ if (destroyed) {
316
+ vsEditor?.dispose();
317
+ vsDiffEditor?.dispose();
318
+ vsEditor = null;
319
+ vsDiffEditor = null;
320
+ return;
321
+ }
322
+
302
323
  setEditorValue(props.initValues, props.modifiedValues);
303
324
 
304
325
  emit('initd', vsEditor);
305
- codeEditorEl.value.addEventListener('keydown', handleKeyDown);
326
+ editorEl.addEventListener('keydown', handleKeyDown);
306
327
 
307
328
  if (props.type !== 'diff' && props.autoSave) {
308
329
  vsEditor?.onDidBlurEditorWidget(() => {
@@ -314,7 +335,7 @@ const init = async () => {
314
335
  });
315
336
  }
316
337
 
317
- resizeObserver.observe(codeEditorEl.value);
338
+ resizeObserver.observe(editorEl);
318
339
  };
319
340
 
320
341
  watch(
@@ -365,6 +386,8 @@ onMounted(async () => {
365
386
  });
366
387
 
367
388
  onBeforeUnmount(() => {
389
+ destroyed = true;
390
+
368
391
  resizeObserver.disconnect();
369
392
 
370
393
  vsEditor?.dispose();
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <div class="m-editor" ref="content" style="min-width: 900px">
2
+ <div
3
+ ref="content"
4
+ :class="['m-editor', theme ? `m-editor--${theme}` : '', theme ? `m-theme--${theme}` : '']"
5
+ style="min-width: 900px"
6
+ >
3
7
  <slot name="header"></slot>
4
8
 
5
9
  <slot name="nav"></slot>
@@ -25,9 +29,9 @@
25
29
  right-class="m-editor-framework-right"
26
30
  :left="hideSidebar ? undefined : columnWidth.left"
27
31
  :right="columnWidth.right"
28
- :min-left="hideSidebar ? 0 : MIN_LEFT_COLUMN_WIDTH"
29
- :min-right="MIN_RIGHT_COLUMN_WIDTH"
30
- :min-center="MIN_CENTER_COLUMN_WIDTH"
32
+ :min-left="hideSidebar ? 0 : minLeftColumnWidth"
33
+ :min-right="minRightColumnWidth"
34
+ :min-center="minCenterColumnWidth"
31
35
  :width="frameworkRect.width"
32
36
  @change="columnWidthChange"
33
37
  >
@@ -78,9 +82,6 @@ import { getEditorConfig } from '@editor/utils/config';
78
82
  import {
79
83
  DEFAULT_LEFT_COLUMN_WIDTH,
80
84
  LEFT_COLUMN_WIDTH_STORAGE_KEY,
81
- MIN_CENTER_COLUMN_WIDTH,
82
- MIN_LEFT_COLUMN_WIDTH,
83
- MIN_RIGHT_COLUMN_WIDTH,
84
85
  RIGHT_COLUMN_WIDTH_STORAGE_KEY,
85
86
  } from '@editor/utils/const';
86
87
 
@@ -100,6 +101,8 @@ const props = defineProps<{
100
101
  pageFilterFunction?: (_page: MPage | MPageFragment, _keyword: string) => boolean;
101
102
  /** 是否隐藏左侧面板 */
102
103
  hideSidebar?: boolean;
104
+ /** 主题名称,会在根节点追加 `m-editor--<theme>` 修饰类 */
105
+ theme?: string;
103
106
  }>();
104
107
 
105
108
  const codeOptions = inject('codeOptions', {});
@@ -116,6 +119,10 @@ const showSrc = computed(() => uiService.get('showSrc'));
116
119
 
117
120
  const columnWidth = computed(() => uiService.get('columnWidth'));
118
121
 
122
+ const minLeftColumnWidth = computed(() => uiService.get('minLeftColumnWidth'));
123
+ const minCenterColumnWidth = computed(() => uiService.get('minCenterColumnWidth'));
124
+ const minRightColumnWidth = computed(() => uiService.get('minRightColumnWidth'));
125
+
119
126
  watch(pageLength, () => {
120
127
  splitViewRef.value?.updateWidth();
121
128
  });
@@ -168,7 +175,7 @@ onBeforeUnmount(() => {
168
175
  const saveCode = (value: string) => {
169
176
  try {
170
177
  const parseDSL = getEditorConfig('parseDSL');
171
- editorService.set('root', parseDSL(value));
178
+ editorService.set('root', parseDSL(value), { historySource: 'root-code' });
172
179
  } catch (e: any) {
173
180
  console.error(e);
174
181
  }
@@ -80,7 +80,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
80
80
  disabled: () => editorService.get('node')?.type === NodeType.PAGE,
81
81
  handler: () => {
82
82
  const node = editorService.get('node');
83
- node && editorService.remove(node);
83
+ node && editorService.remove(node, { historySource: 'toolbar' });
84
84
  },
85
85
  });
86
86
  break;
@@ -90,7 +90,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
90
90
  className: 'undo',
91
91
  icon: markRaw(Back),
92
92
  tooltip: `后退(${ctrl}+z)`,
93
- disabled: () => !historyService.state.canUndo,
93
+ disabled: () => !historyService.canUndo('page', editorService.get('page')?.id),
94
94
  handler: () => editorService.undo(),
95
95
  });
96
96
  break;
@@ -100,7 +100,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
100
100
  className: 'redo',
101
101
  icon: markRaw(Right),
102
102
  tooltip: `前进(${ctrl}+Shift+z)`,
103
- disabled: () => !historyService.state.canRedo,
103
+ disabled: () => !historyService.canRedo('page', editorService.get('page')?.id),
104
104
  handler: () => editorService.redo(),
105
105
  });
106
106
  break;