@tmagic/editor 1.8.0-beta.1 → 1.8.0-beta.11

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 (232) hide show
  1. package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +31 -5
  2. package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +21 -113
  3. package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +7 -1
  4. package/dist/es/components/CompareForm.js +5 -0
  5. package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +196 -0
  6. package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  7. package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +2 -2
  8. package/dist/es/components/Icon.vue_vue_type_script_setup_true_lang.js +1 -1
  9. package/dist/es/components/Resizer.vue_vue_type_script_setup_true_lang.js +1 -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/editorProps.js +2 -0
  18. package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +20 -4
  19. package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +3 -6
  20. package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +19 -3
  21. package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +42 -8
  22. package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  23. package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +14 -6
  24. package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +3 -3
  25. package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +41 -16
  26. package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +2 -2
  27. package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +9 -5
  28. package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +40 -19
  29. package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +17 -9
  30. package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +4 -2
  31. package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +1 -1
  32. package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +59 -12
  33. package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +12 -7
  34. package/dist/es/fields/PageFragmentSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  35. package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +1 -1
  36. package/dist/es/fields/StyleSetter/components/BackgroundPosition.vue_vue_type_script_setup_true_lang.js +1 -1
  37. package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +28 -6
  38. package/dist/es/fields/StyleSetter/components/Box.vue_vue_type_script_setup_true_lang.js +1 -1
  39. package/dist/es/fields/StyleSetter/icons/background-repeat/NoRepeat.js +1 -1
  40. package/dist/es/fields/StyleSetter/icons/background-repeat/Repeat.js +1 -1
  41. package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatX.js +1 -1
  42. package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatY.js +1 -1
  43. package/dist/es/fields/StyleSetter/icons/display/Block.js +1 -1
  44. package/dist/es/fields/StyleSetter/icons/display/Flex.js +1 -1
  45. package/dist/es/fields/StyleSetter/icons/display/Inline.js +1 -1
  46. package/dist/es/fields/StyleSetter/icons/display/InlineBlock.js +1 -1
  47. package/dist/es/fields/StyleSetter/icons/display/None.js +1 -1
  48. package/dist/es/fields/StyleSetter/icons/flex-direction/Column.js +1 -1
  49. package/dist/es/fields/StyleSetter/icons/flex-direction/ColumnReverse.js +1 -1
  50. package/dist/es/fields/StyleSetter/icons/flex-direction/Row.js +1 -1
  51. package/dist/es/fields/StyleSetter/icons/flex-direction/RowReverse.js +1 -1
  52. package/dist/es/fields/StyleSetter/icons/justify-content/Center.js +1 -1
  53. package/dist/es/fields/StyleSetter/icons/justify-content/FlexEnd.js +1 -1
  54. package/dist/es/fields/StyleSetter/icons/justify-content/FlexStart.js +1 -1
  55. package/dist/es/fields/StyleSetter/icons/justify-content/SpaceAround.js +1 -1
  56. package/dist/es/fields/StyleSetter/icons/justify-content/SpaceBetween.js +1 -1
  57. package/dist/es/fields/StyleSetter/icons/text-align/Center.js +1 -1
  58. package/dist/es/fields/StyleSetter/icons/text-align/Left.js +1 -1
  59. package/dist/es/fields/StyleSetter/icons/text-align/Right.js +1 -1
  60. package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +1 -1
  61. package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +1 -1
  62. package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +1 -1
  63. package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +1 -1
  64. package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +1 -1
  65. package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +1 -1
  66. package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +9 -6
  67. package/dist/es/hooks/use-code-block-edit.js +7 -4
  68. package/dist/es/hooks/use-data-source-edit.js +5 -2
  69. package/dist/es/hooks/use-stage.js +22 -10
  70. package/dist/es/icons/CenterIcon.vue_vue_type_script_setup_true_lang.js +1 -1
  71. package/dist/es/icons/CodeIcon.vue_vue_type_script_setup_true_lang.js +1 -1
  72. package/dist/es/icons/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +1 -1
  73. package/dist/es/index.js +14 -3
  74. package/dist/es/initService.js +7 -7
  75. package/dist/es/layouts/AddPageBox.vue_vue_type_script_setup_true_lang.js +1 -1
  76. package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +7 -6
  77. package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +14 -9
  78. package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +12 -4
  79. package/dist/es/layouts/NavMenuColumn.vue_vue_type_script_setup_true_lang.js +1 -1
  80. package/dist/es/layouts/history-list/Bucket.js +5 -0
  81. package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +71 -0
  82. package/dist/es/layouts/history-list/BucketTab.js +5 -0
  83. package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +62 -0
  84. package/dist/es/layouts/history-list/GroupRow.js +5 -0
  85. package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +269 -0
  86. package/dist/es/layouts/history-list/HistoryDiffDialog.js +5 -0
  87. package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +294 -0
  88. package/dist/es/layouts/history-list/HistoryListPanel.js +5 -0
  89. package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +327 -0
  90. package/dist/es/layouts/history-list/InitialRow.js +5 -0
  91. package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +83 -0
  92. package/dist/es/layouts/history-list/PageTab.js +5 -0
  93. package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +95 -0
  94. package/dist/es/layouts/history-list/composables.js +184 -0
  95. package/dist/es/layouts/history-list/useHistoryList.js +56 -0
  96. package/dist/es/layouts/history-list/useHistoryRevert.js +313 -0
  97. package/dist/es/layouts/page-bar/AddButton.vue_vue_type_script_setup_true_lang.js +1 -1
  98. package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +5 -3
  99. package/dist/es/layouts/page-bar/PageBarScrollContainer.vue_vue_type_script_setup_true_lang.js +1 -1
  100. package/dist/es/layouts/page-bar/PageList.vue_vue_type_script_setup_true_lang.js +1 -1
  101. package/dist/es/layouts/page-bar/Search.vue_vue_type_script_setup_true_lang.js +2 -2
  102. package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  103. package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +6 -2
  104. package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +2 -2
  105. package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +8 -4
  106. package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +4 -4
  107. package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +2 -2
  108. package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
  109. package/dist/es/layouts/sidebar/data-source/DataSourceAddButton.vue_vue_type_script_setup_true_lang.js +1 -1
  110. package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +19 -6
  111. package/dist/es/layouts/sidebar/data-source/DataSourceList.vue_vue_type_script_setup_true_lang.js +1 -1
  112. package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +25 -3
  113. package/dist/es/layouts/sidebar/data-source/useContentMenu.js +1 -1
  114. package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +6 -6
  115. package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +2 -2
  116. package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  117. package/dist/es/layouts/sidebar/layer/use-node-status.js +1 -1
  118. package/dist/es/layouts/workspace/Breadcrumb.vue_vue_type_script_setup_true_lang.js +1 -1
  119. package/dist/es/layouts/workspace/Workspace.vue_vue_type_script_setup_true_lang.js +1 -1
  120. package/dist/es/layouts/workspace/viewer/NodeListMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  121. package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +2 -2
  122. package/dist/es/layouts/workspace/viewer/StageOverlay.vue_vue_type_script_setup_true_lang.js +1 -1
  123. package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +9 -9
  124. package/dist/es/services/BaseService.js +31 -68
  125. package/dist/es/services/codeBlock.js +286 -8
  126. package/dist/es/services/componentList.js +2 -2
  127. package/dist/es/services/dataSource.js +287 -8
  128. package/dist/es/services/dep.js +21 -9
  129. package/dist/es/services/editor.js +655 -194
  130. package/dist/es/services/events.js +2 -2
  131. package/dist/es/services/history.js +390 -47
  132. package/dist/es/services/keybinding.js +5 -5
  133. package/dist/es/services/props.js +8 -8
  134. package/dist/es/services/stageOverlay.js +2 -2
  135. package/dist/es/services/storage.js +2 -2
  136. package/dist/es/services/ui.js +5 -2
  137. package/dist/es/style.css +456 -8
  138. package/dist/es/utils/code-block.js +122 -0
  139. package/dist/es/utils/content-menu.js +19 -12
  140. package/dist/es/utils/data-source/index.js +2 -0
  141. package/dist/es/utils/dep/worker.js +1 -1
  142. package/dist/es/utils/editor.js +105 -51
  143. package/dist/es/utils/history.js +220 -0
  144. package/dist/es/utils/indexed-db.js +86 -0
  145. package/dist/es/utils/undo-redo.js +80 -1
  146. package/dist/style.css +456 -8
  147. package/dist/tmagic-editor.umd.cjs +11149 -6646
  148. package/package.json +8 -8
  149. package/src/Editor.vue +25 -1
  150. package/src/components/CodeBlockEditor.vue +20 -109
  151. package/src/components/CodeParams.vue +6 -0
  152. package/src/components/CompareForm.vue +277 -0
  153. package/src/components/ToolButton.vue +2 -2
  154. package/src/editorProps.ts +9 -0
  155. package/src/fields/Code.vue +19 -3
  156. package/src/fields/CodeLink.vue +2 -5
  157. package/src/fields/CodeSelect.vue +17 -1
  158. package/src/fields/CodeSelectCol.vue +37 -3
  159. package/src/fields/DataSourceFieldSelect/FieldSelect.vue +23 -3
  160. package/src/fields/DataSourceFieldSelect/Index.vue +2 -2
  161. package/src/fields/DataSourceFields.vue +48 -10
  162. package/src/fields/DataSourceInput.vue +3 -3
  163. package/src/fields/DataSourceMethodSelect.vue +12 -4
  164. package/src/fields/DataSourceMethods.vue +55 -24
  165. package/src/fields/DataSourceMocks.vue +13 -3
  166. package/src/fields/DataSourceSelect.vue +4 -1
  167. package/src/fields/EventSelect.vue +57 -8
  168. package/src/fields/KeyValue.vue +17 -4
  169. package/src/fields/StyleSetter/components/Border.vue +15 -6
  170. package/src/fields/UISelect.vue +5 -2
  171. package/src/hooks/use-code-block-edit.ts +9 -5
  172. package/src/hooks/use-data-source-edit.ts +2 -2
  173. package/src/hooks/use-stage.ts +26 -9
  174. package/src/index.ts +8 -0
  175. package/src/initService.ts +1 -1
  176. package/src/layouts/CodeEditor.vue +17 -5
  177. package/src/layouts/Framework.vue +11 -6
  178. package/src/layouts/NavMenu.vue +12 -3
  179. package/src/layouts/history-list/Bucket.vue +91 -0
  180. package/src/layouts/history-list/BucketTab.vue +72 -0
  181. package/src/layouts/history-list/GroupRow.vue +304 -0
  182. package/src/layouts/history-list/HistoryDiffDialog.vue +281 -0
  183. package/src/layouts/history-list/HistoryListPanel.vue +367 -0
  184. package/src/layouts/history-list/InitialRow.vue +71 -0
  185. package/src/layouts/history-list/PageTab.vue +118 -0
  186. package/src/layouts/history-list/composables.ts +309 -0
  187. package/src/layouts/history-list/useHistoryList.ts +60 -0
  188. package/src/layouts/history-list/useHistoryRevert.ts +421 -0
  189. package/src/layouts/page-bar/PageBar.vue +4 -2
  190. package/src/layouts/props-panel/PropsPanel.vue +5 -1
  191. package/src/layouts/sidebar/ComponentListPanel.vue +9 -5
  192. package/src/layouts/sidebar/Sidebar.vue +8 -3
  193. package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
  194. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -1
  195. package/src/layouts/sidebar/code-block/useContentMenu.ts +1 -1
  196. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +31 -2
  197. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +27 -2
  198. package/src/layouts/sidebar/data-source/useContentMenu.ts +1 -1
  199. package/src/layouts/sidebar/layer/LayerMenu.vue +19 -11
  200. package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
  201. package/src/layouts/sidebar/layer/use-node-status.ts +9 -6
  202. package/src/layouts/workspace/viewer/Stage.vue +1 -1
  203. package/src/layouts/workspace/viewer/ViewerMenu.vue +8 -8
  204. package/src/services/BaseService.ts +35 -86
  205. package/src/services/codeBlock.ts +361 -5
  206. package/src/services/dataSource.ts +336 -6
  207. package/src/services/dep.ts +32 -9
  208. package/src/services/editor.ts +834 -194
  209. package/src/services/history.ts +509 -49
  210. package/src/services/keybinding.ts +3 -3
  211. package/src/services/props.ts +2 -2
  212. package/src/services/ui.ts +7 -0
  213. package/src/theme/history-list-panel.scss +557 -0
  214. package/src/theme/page-bar.scss +0 -4
  215. package/src/theme/props-panel.scss +3 -3
  216. package/src/theme/style-setter/border.scss +4 -1
  217. package/src/theme/theme.scss +1 -0
  218. package/src/type.ts +613 -31
  219. package/src/utils/code-block.ts +150 -0
  220. package/src/utils/content-menu.ts +25 -13
  221. package/src/utils/data-source/index.ts +2 -0
  222. package/src/utils/dep/worker.ts +5 -3
  223. package/src/utils/editor.ts +166 -60
  224. package/src/utils/history.ts +286 -0
  225. package/src/utils/index.ts +3 -0
  226. package/src/utils/indexed-db.ts +122 -0
  227. package/src/utils/undo-redo.ts +111 -0
  228. package/types/index.d.ts +3197 -896
  229. package/dist/es/utils/compose.js +0 -44
  230. package/dist/es/utils/editor-history.js +0 -100
  231. package/src/utils/compose.ts +0 -52
  232. package/src/utils/editor-history.ts +0 -138
@@ -1,12 +1,14 @@
1
- import BaseService_default from "./BaseService.js";
1
+ import BaseService from "./BaseService.js";
2
+ import { createStackStep, describeRevertStep, getLastPushedHistoryIds } from "../utils/history.js";
3
+ import history_default from "./history.js";
2
4
  import storage_default, { Protocol } from "./storage.js";
3
5
  import { COPY_DS_STORAGE_KEY } from "../utils/editor.js";
4
6
  import editor_default from "./editor.js";
5
7
  import { getFormConfig, getFormValue } from "../utils/data-source/index.js";
6
- import { guid, toLine } from "@tmagic/utils";
8
+ import { getValueByKeyPath, guid, setValueByKeyPath, toLine } from "@tmagic/utils";
7
9
  import { Target, Watcher } from "@tmagic/core";
8
10
  import { reactive } from "vue";
9
- import { cloneDeep, get } from "lodash-es";
11
+ import { cloneDeep as cloneDeep$1, get } from "lodash-es";
10
12
  //#region packages/editor/src/services/dataSource.ts
11
13
  var canUsePluginMethods = {
12
14
  async: [],
@@ -25,7 +27,7 @@ var canUsePluginMethods = {
25
27
  "createId"
26
28
  ]
27
29
  };
28
- var DataSource = class extends BaseService_default {
30
+ var DataSource = class extends BaseService {
29
31
  state = reactive({
30
32
  datasourceTypeList: [],
31
33
  dataSources: [],
@@ -35,6 +37,12 @@ var DataSource = class extends BaseService_default {
35
37
  events: {},
36
38
  methods: {}
37
39
  });
40
+ /**
41
+ * 最近一次写入历史栈的数据源历史记录 uuid。
42
+ * 供 *AndGetHistoryId 系列方法在调用 add / update / remove 后取回本次产生的历史记录 id;
43
+ * 普通方法不读取它,调用前由 *AndGetHistoryId 重置为 null。
44
+ */
45
+ lastPushedHistoryId = null;
38
46
  constructor() {
39
47
  super(canUsePluginMethods.sync.map((methodName) => ({
40
48
  name: methodName,
@@ -71,32 +79,205 @@ var DataSource = class extends BaseService_default {
71
79
  setFormMethod(type, value = []) {
72
80
  this.get("methods")[toLine(type)] = value;
73
81
  }
74
- add(config) {
82
+ /**
83
+ * 新增数据源
84
+ * @param config 数据源配置
85
+ * @param options 可选配置
86
+ * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
87
+ * @param options.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
88
+ */
89
+ add(config, { doNotPushHistory = false, historyDescription, historySource } = {}) {
75
90
  const newConfig = {
76
91
  ...config,
77
92
  id: config.id && !this.getDataSourceById(config.id) ? config.id : this.createId()
78
93
  };
79
94
  this.get("dataSources").push(newConfig);
95
+ if (!doNotPushHistory) {
96
+ const step = createStackStep(newConfig.id, {
97
+ oldValue: null,
98
+ newValue: newConfig,
99
+ historyDescription,
100
+ source: historySource
101
+ });
102
+ this.lastPushedHistoryId = (step ? history_default.push("dataSource", step, newConfig.id) : null)?.uuid ?? null;
103
+ }
80
104
  this.emit("add", newConfig);
105
+ this.emit("change", this.get("dataSources"));
81
106
  return newConfig;
82
107
  }
83
- update(config, { changeRecords = [] } = {}) {
108
+ /**
109
+ * 更新数据源
110
+ * @param config 数据源配置
111
+ * @param data 额外数据
112
+ * @param data.changeRecords form 端变更记录
113
+ * @param data.doNotPushHistory 是否不写入历史记录(默认 false)
114
+ * @param data.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
115
+ */
116
+ update(config, { changeRecords = [], doNotPushHistory = false, historyDescription, historySource } = {}) {
84
117
  const dataSources = this.get("dataSources");
85
118
  const index = dataSources.findIndex((ds) => ds.id === config.id);
86
119
  const oldConfig = dataSources[index];
87
- const newConfig = cloneDeep(config);
120
+ const newConfig = cloneDeep$1(config);
88
121
  dataSources[index] = newConfig;
122
+ if (!doNotPushHistory) {
123
+ const step = createStackStep(newConfig.id, {
124
+ oldValue: oldConfig ? cloneDeep$1(oldConfig) : null,
125
+ newValue: newConfig,
126
+ changeRecords,
127
+ historyDescription,
128
+ source: historySource
129
+ });
130
+ this.lastPushedHistoryId = (step ? history_default.push("dataSource", step, newConfig.id) : null)?.uuid ?? null;
131
+ }
89
132
  this.emit("update", newConfig, {
90
133
  oldConfig,
91
134
  changeRecords
92
135
  });
136
+ this.emit("change", this.get("dataSources"));
93
137
  return newConfig;
94
138
  }
95
- remove(id) {
139
+ /**
140
+ * 删除数据源
141
+ * @param id 数据源 id
142
+ * @param options 可选配置
143
+ * @param options.doNotPushHistory 是否不写入历史记录(默认 false)
144
+ * @param options.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
145
+ */
146
+ remove(id, { doNotPushHistory = false, historyDescription, historySource } = {}) {
96
147
  const dataSources = this.get("dataSources");
97
148
  const index = dataSources.findIndex((ds) => ds.id === id);
149
+ const oldConfig = index !== -1 ? dataSources[index] : null;
98
150
  dataSources.splice(index, 1);
151
+ if (oldConfig && !doNotPushHistory) {
152
+ const step = createStackStep(id, {
153
+ oldValue: cloneDeep$1(oldConfig),
154
+ newValue: null,
155
+ historyDescription,
156
+ source: historySource
157
+ });
158
+ this.lastPushedHistoryId = (step ? history_default.push("dataSource", step, id) : null)?.uuid ?? null;
159
+ }
99
160
  this.emit("remove", id);
161
+ this.emit("change", this.get("dataSources"));
162
+ }
163
+ /**
164
+ * 下列 *AndGetHistoryId 方法与对应的 add / update / remove 行为完全一致,
165
+ * 返回值在 {@link DslOpWithHistoryIdsResult} 中同时包含原操作结果与本次写入历史栈的 uuid 列表({@link DataSourceStepValue.uuid}),
166
+ * 可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
167
+ *
168
+ * 当本次操作未写入历史(doNotPushHistory 为 true、或无对应记录)时 historyIds 为 `[]`。
169
+ */
170
+ /** 等价于 {@link add},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
171
+ addAndGetHistoryId(config, options = {}) {
172
+ this.lastPushedHistoryId = null;
173
+ return {
174
+ result: this.add(config, options),
175
+ historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId)
176
+ };
177
+ }
178
+ /** 等价于 {@link update},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
179
+ updateAndGetHistoryId(config, options = {}) {
180
+ this.lastPushedHistoryId = null;
181
+ return {
182
+ result: this.update(config, options),
183
+ historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId)
184
+ };
185
+ }
186
+ /** 等价于 {@link remove},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
187
+ removeAndGetHistoryId(id, options = {}) {
188
+ this.lastPushedHistoryId = null;
189
+ this.remove(id, options);
190
+ return {
191
+ result: void 0,
192
+ historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId)
193
+ };
194
+ }
195
+ /**
196
+ * 撤销指定数据源的最近一次变更。
197
+ *
198
+ * 内部走 add / update / remove,因此会自动触发 dataSourceService 的事件,
199
+ * 由 initService 中的对应 handler 重新收集 dep(DATA_SOURCE / DATA_SOURCE_COND / DATA_SOURCE_METHOD)。
200
+ * 所有写回都带 `doNotPushHistory: true`,避免在历史栈里产生新的记录。
201
+ *
202
+ * @param id 数据源 id
203
+ * @returns 撤销的 step;栈不存在或已无可撤销时返回 null
204
+ */
205
+ undo(id) {
206
+ const step = history_default.undo("dataSource", id);
207
+ if (!step) return null;
208
+ this.applyHistoryStep(step, true);
209
+ return step;
210
+ }
211
+ /**
212
+ * 重做指定数据源的下一次变更。
213
+ * @param id 数据源 id
214
+ * @returns 重做的 step;栈不存在或已无可重做时返回 null
215
+ */
216
+ redo(id) {
217
+ const step = history_default.redo("dataSource", id);
218
+ if (!step) return null;
219
+ this.applyHistoryStep(step, false);
220
+ return step;
221
+ }
222
+ /** 是否可对指定数据源撤销。 */
223
+ canUndo(id) {
224
+ return history_default.canUndo("dataSource", id);
225
+ }
226
+ /** 是否可对指定数据源重做。 */
227
+ canRedo(id) {
228
+ return history_default.canRedo("dataSource", id);
229
+ }
230
+ /**
231
+ * 跳转指定数据源的历史栈到目标游标。语义同 editor.gotoPageStep。
232
+ *
233
+ * @param id 数据源 id
234
+ * @param targetCursor 目标游标位置(已应用步骤数量)
235
+ * @returns 实际移动到的最终游标位置
236
+ */
237
+ goto(id, targetCursor) {
238
+ let cursor = history_default.getCursor("dataSource", id);
239
+ const target = Math.max(0, targetCursor);
240
+ while (cursor > target) {
241
+ if (!this.undo(id)) break;
242
+ cursor -= 1;
243
+ }
244
+ while (cursor < target) {
245
+ if (!this.redo(id)) break;
246
+ cursor += 1;
247
+ }
248
+ return cursor;
249
+ }
250
+ /**
251
+ * 「回滚」指定数据源历史步骤(类 git revert 语义):
252
+ * - 不动原始栈结构(不移动 cursor、不丢弃任何步骤);
253
+ * - 把目标 step 的修改**反向应用**一次,并作为**新步骤**追加到栈顶;
254
+ * - 仅对已应用的步骤生效——未应用步骤本身就不存在于当前 schema 中,反向无意义。
255
+ *
256
+ * @param id 数据源 id
257
+ * @param index 目标 step 在该栈中的索引(0 为最早),通常由历史面板传入
258
+ * @returns 反向后产生的新 step;目标不存在 / 未应用时返回 null
259
+ */
260
+ revert(id, index) {
261
+ const entry = history_default.getStepList("dataSource", id)[index];
262
+ if (!entry?.applied) return null;
263
+ const { oldSchema, newSchema, changeRecords } = entry.step.diff?.[0] ?? {};
264
+ if (oldSchema && newSchema && !changeRecords?.length) return null;
265
+ const description = `回滚 #${index + 1}: ${describeRevertStep(entry.step.data.id, entry.step.diff?.[0], (s) => s.title)}`;
266
+ return this.applyRevertStep(entry.step, description);
267
+ }
268
+ /**
269
+ * 通过历史记录 uuid 回滚数据源历史步骤,语义同 {@link revert},
270
+ * 仅无需调用方再传 dataSourceId 与 index:内部会按 uuid 在全部数据源栈中定位对应步骤后再回滚。
271
+ * 按数组顺序依次回滚,返回与入参同序的结果列表(某项失败时为 `null`)。
272
+ *
273
+ * @param uuids 目标历史记录的 uuid 列表,通常由 {@link addAndGetHistoryId} 等方法返回的 `historyIds`
274
+ */
275
+ revertById(uuids) {
276
+ return uuids.map((uuid) => {
277
+ const location = history_default.findStepLocationByUuid("dataSource", uuid);
278
+ if (!location) return null;
279
+ return this.revert(location.id, location.index);
280
+ });
100
281
  }
101
282
  createId() {
102
283
  return `ds_${guid()}`;
@@ -151,6 +332,104 @@ var DataSource = class extends BaseService_default {
151
332
  if (!this.getDataSourceById(item.id)) this.add(item);
152
333
  });
153
334
  }
335
+ /**
336
+ * 反向应用一个 step 并以新 step 入栈(不带 doNotPushHistory)。逻辑与 applyHistoryStep(reverse=true)
337
+ * 同构,差异仅在于走对应的公共 add / update / remove 而不是带 doNotPushHistory 的版本。
338
+ */
339
+ applyRevertStep(step, historyDescription) {
340
+ const { id } = step.data;
341
+ const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
342
+ if (!oldSchema && newSchema) {
343
+ this.remove(`${id}`, {
344
+ historyDescription,
345
+ historySource: "rollback"
346
+ });
347
+ return history_default.getStepList("dataSource", id).slice(-1)[0]?.step ?? null;
348
+ }
349
+ if (oldSchema && !newSchema) {
350
+ this.add(cloneDeep$1(oldSchema), {
351
+ historyDescription,
352
+ historySource: "rollback"
353
+ });
354
+ return history_default.getStepList("dataSource", id).slice(-1)[0]?.step ?? null;
355
+ }
356
+ if (!oldSchema || !newSchema) return null;
357
+ if (changeRecords?.length) {
358
+ const current = this.getDataSourceById(`${id}`);
359
+ if (!current) return null;
360
+ const patched = cloneDeep$1(current);
361
+ let fallbackToFullReplace = false;
362
+ for (const record of changeRecords) {
363
+ if (!record.propPath) {
364
+ fallbackToFullReplace = true;
365
+ break;
366
+ }
367
+ const value = cloneDeep$1(getValueByKeyPath(record.propPath, oldSchema));
368
+ setValueByKeyPath(record.propPath, value, patched);
369
+ }
370
+ this.update(fallbackToFullReplace ? cloneDeep$1(oldSchema) : patched, {
371
+ changeRecords,
372
+ historyDescription,
373
+ historySource: "rollback"
374
+ });
375
+ return history_default.getStepList("dataSource", id).slice(-1)[0]?.step ?? null;
376
+ }
377
+ this.update(cloneDeep$1(oldSchema), {
378
+ historyDescription,
379
+ historySource: "rollback"
380
+ });
381
+ return history_default.getStepList("dataSource", id).slice(-1)[0]?.step ?? null;
382
+ }
383
+ /**
384
+ * 把一条历史 step 应用到当前数据源服务上。
385
+ *
386
+ * 复用现有的 add / update / remove,目的是借助它们发出的事件触发 initService 中
387
+ * 的依赖收集逻辑(DATA_SOURCE / DATA_SOURCE_COND / DATA_SOURCE_METHOD)。
388
+ * 所有写回都带 `doNotPushHistory: true`,确保不会在历史栈里产生新的记录。
389
+ *
390
+ * - oldSchema=null, newSchema≠null:原始为新增 → undo 删除;redo 再次 add
391
+ * - oldSchema≠null, newSchema=null:原始为删除 → undo 还原 add;redo 再次删除
392
+ * - 两侧都有:原始为更新 → 按 changeRecords 局部 patch;缺省退化为整 schema 替换
393
+ *
394
+ * @param step 历史 step
395
+ * @param reverse true=撤销,false=重做
396
+ */
397
+ applyHistoryStep(step, reverse) {
398
+ const { id } = step.data;
399
+ const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
400
+ if (!oldSchema && newSchema) {
401
+ if (reverse) this.remove(`${id}`, { doNotPushHistory: true });
402
+ else this.add(cloneDeep$1(newSchema), { doNotPushHistory: true });
403
+ return;
404
+ }
405
+ if (oldSchema && !newSchema) {
406
+ if (reverse) this.add(cloneDeep$1(oldSchema), { doNotPushHistory: true });
407
+ else this.remove(`${id}`, { doNotPushHistory: true });
408
+ return;
409
+ }
410
+ if (!oldSchema || !newSchema) return;
411
+ const sourceForValues = reverse ? oldSchema : newSchema;
412
+ if (changeRecords?.length) {
413
+ const current = this.getDataSourceById(`${id}`);
414
+ if (!current) return;
415
+ const patched = cloneDeep$1(current);
416
+ let fallbackToFullReplace = false;
417
+ for (const record of changeRecords) {
418
+ if (!record.propPath) {
419
+ fallbackToFullReplace = true;
420
+ break;
421
+ }
422
+ const value = cloneDeep$1(getValueByKeyPath(record.propPath, sourceForValues));
423
+ setValueByKeyPath(record.propPath, value, patched);
424
+ }
425
+ this.update(fallbackToFullReplace ? cloneDeep$1(sourceForValues) : patched, {
426
+ changeRecords,
427
+ doNotPushHistory: true
428
+ });
429
+ return;
430
+ }
431
+ this.update(cloneDeep$1(sourceForValues), { doNotPushHistory: true });
432
+ }
154
433
  };
155
434
  var dataSource_default = new DataSource();
156
435
  //#endregion
@@ -1,4 +1,4 @@
1
- import BaseService_default from "./BaseService.js";
1
+ import BaseService from "./BaseService.js";
2
2
  import { IdleTask } from "../utils/dep/idle-task.js";
3
3
  import WorkerWrapper from "../utils/dep/worker.js";
4
4
  import { isPage } from "@tmagic/utils";
@@ -7,7 +7,7 @@ import { reactive, shallowReactive } from "vue";
7
7
  import { throttle } from "lodash-es";
8
8
  import serialize from "serialize-javascript";
9
9
  //#region packages/editor/src/services/dep.ts
10
- var Dep = class extends BaseService_default {
10
+ var Dep = class extends BaseService {
11
11
  state = shallowReactive({
12
12
  collecting: false,
13
13
  taskLength: 0
@@ -52,9 +52,12 @@ var Dep = class extends BaseService_default {
52
52
  }
53
53
  collect(nodes, depExtendedData = {}, deep = false, type) {
54
54
  this.set("collecting", true);
55
- this.watcher.collectByCallback(nodes, type, ({ node, target }) => {
56
- this.collectNode(node, target, depExtendedData, deep);
57
- });
55
+ const targets = this.watcher.getCollectableTargets(type);
56
+ if (targets.length) for (const node of nodes) {
57
+ if (isPage(node)) for (const target of targets) this.removePageDep(target, depExtendedData);
58
+ else this.watcher.removeTargetsDep(targets, node);
59
+ this.watcher.collectItems(node, targets, depExtendedData, deep);
60
+ }
58
61
  this.set("collecting", false);
59
62
  this.emit("collected", nodes, deep);
60
63
  this.emit("ds-collected", nodes, deep);
@@ -103,7 +106,7 @@ var Dep = class extends BaseService_default {
103
106
  target.deps = reactive(depsData[target.type][target.id]);
104
107
  if (target.type === DepTargetType.DATA_SOURCE && dsl.dataSourceDeps) dsl.dataSourceDeps[target.id] = target.deps;
105
108
  else if (target.type === DepTargetType.DATA_SOURCE_COND && dsl.dataSourceCondDeps) dsl.dataSourceCondDeps[target.id] = target.deps;
106
- else if (target.type === DepTargetType.DATA_SOURCE_METHOD) dsl.dataSourceMethodDeps[target.id] = target.deps;
109
+ else if (target.type === DepTargetType.DATA_SOURCE_METHOD && dsl.dataSourceMethodDeps) dsl.dataSourceMethodDeps[target.id] = target.deps;
107
110
  }
108
111
  });
109
112
  this.set("collecting", false);
@@ -114,9 +117,8 @@ var Dep = class extends BaseService_default {
114
117
  });
115
118
  }
116
119
  collectNode(node, target, depExtendedData = {}, deep = false) {
117
- if (isPage(node)) {
118
- for (const [depKey, dep] of Object.entries(target.deps)) if (dep.data?.pageId && dep.data.pageId === depExtendedData.pageId) delete target.deps[depKey];
119
- } else this.watcher.removeTargetDep(target, node);
120
+ if (isPage(node)) this.removePageDep(target, depExtendedData);
121
+ else this.watcher.removeTargetDep(target, node);
120
122
  this.watcher.collectItem(node, target, depExtendedData, deep);
121
123
  }
122
124
  clear(nodes) {
@@ -155,6 +157,16 @@ var Dep = class extends BaseService_default {
155
157
  emit(eventName, ...args) {
156
158
  return super.emit(eventName, ...args);
157
159
  }
160
+ /**
161
+ * 删除指定 page 在该 target 下的旧依赖:
162
+ * 按 pageId 匹配,可清掉页面内已被删除节点的残留依赖
163
+ */
164
+ removePageDep(target, depExtendedData = {}) {
165
+ for (const depKey of Object.keys(target.deps)) {
166
+ const dep = target.deps[depKey];
167
+ if (dep.data?.pageId && dep.data.pageId === depExtendedData.pageId) delete target.deps[depKey];
168
+ }
169
+ }
158
170
  enqueueTask(node, target, depExtendedData, deep) {
159
171
  this.idleTask.enqueueTask(({ node, deep, target }) => {
160
172
  this.collectNode(node, target, depExtendedData, deep);