@tmagic/editor 1.8.0-beta.3 → 1.8.0-beta.4

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 (66) hide show
  1. package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +15 -1
  2. package/dist/es/hooks/use-code-block-edit.js +6 -3
  3. package/dist/es/hooks/use-data-source-edit.js +5 -2
  4. package/dist/es/hooks/use-stage.js +6 -3
  5. package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  6. package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +6 -2
  7. package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +3 -0
  8. package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +42 -29
  9. package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +4 -2
  10. package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +5 -1
  11. package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +5 -2
  12. package/dist/es/layouts/history-list/composables.js +53 -1
  13. package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +5 -1
  14. package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  15. package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +3 -3
  16. package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  17. package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
  18. package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  19. package/dist/es/layouts/sidebar/data-source/useContentMenu.js +1 -1
  20. package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +5 -5
  21. package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +1 -1
  22. package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +1 -1
  23. package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +8 -8
  24. package/dist/es/services/codeBlock.js +25 -10
  25. package/dist/es/services/dataSource.js +24 -10
  26. package/dist/es/services/editor.js +98 -46
  27. package/dist/es/services/history.js +2 -0
  28. package/dist/es/services/keybinding.js +3 -3
  29. package/dist/es/style.css +16 -4
  30. package/dist/es/utils/content-menu.js +17 -9
  31. package/dist/style.css +16 -4
  32. package/dist/tmagic-editor.umd.cjs +343 -144
  33. package/package.json +7 -7
  34. package/src/components/CompareForm.vue +19 -1
  35. package/src/hooks/use-code-block-edit.ts +4 -3
  36. package/src/hooks/use-data-source-edit.ts +2 -2
  37. package/src/hooks/use-stage.ts +3 -3
  38. package/src/layouts/NavMenu.vue +1 -1
  39. package/src/layouts/history-list/Bucket.vue +6 -2
  40. package/src/layouts/history-list/BucketTab.vue +3 -0
  41. package/src/layouts/history-list/GroupRow.vue +20 -3
  42. package/src/layouts/history-list/HistoryDiffDialog.vue +2 -1
  43. package/src/layouts/history-list/HistoryListPanel.vue +4 -0
  44. package/src/layouts/history-list/PageTab.vue +5 -1
  45. package/src/layouts/history-list/composables.ts +60 -0
  46. package/src/layouts/props-panel/PropsPanel.vue +5 -1
  47. package/src/layouts/sidebar/ComponentListPanel.vue +9 -5
  48. package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
  49. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -1
  50. package/src/layouts/sidebar/code-block/useContentMenu.ts +1 -1
  51. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -1
  52. package/src/layouts/sidebar/data-source/useContentMenu.ts +1 -1
  53. package/src/layouts/sidebar/layer/LayerMenu.vue +19 -11
  54. package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
  55. package/src/layouts/workspace/viewer/Stage.vue +1 -1
  56. package/src/layouts/workspace/viewer/ViewerMenu.vue +8 -8
  57. package/src/services/codeBlock.ts +33 -9
  58. package/src/services/dataSource.ts +30 -8
  59. package/src/services/editor.ts +111 -34
  60. package/src/services/history.ts +7 -0
  61. package/src/services/keybinding.ts +3 -3
  62. package/src/theme/history-list-panel.scss +15 -1
  63. package/src/theme/props-panel.scss +3 -3
  64. package/src/type.ts +58 -2
  65. package/src/utils/content-menu.ts +18 -9
  66. package/types/index.d.ts +96 -25
@@ -79,6 +79,20 @@ var CompareForm_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
79
79
  }
80
80
  return !isEqual(curValue, lastValue);
81
81
  };
82
+ const removeStyleDisplayConfig = (formConfig) => formConfig.map((item) => {
83
+ if (!("type" in item)) return item;
84
+ if (item?.type !== "tab" || !Array.isArray(item.items)) return item;
85
+ return {
86
+ ...item,
87
+ items: item.items.map((tabPane) => {
88
+ if (tabPane?.title !== "样式" || !Array.isArray(tabPane.items)) return tabPane;
89
+ return {
90
+ ...tabPane,
91
+ display: true
92
+ };
93
+ })
94
+ };
95
+ });
82
96
  /**
83
97
  * 内置的默认 FormConfig 加载逻辑:按 `category` 从对应 service / 工具取配置。
84
98
  * 作为 ctx.defaultLoadConfig 透传给自定义 `loadConfig`,方便复用与二次加工。
@@ -87,7 +101,7 @@ var CompareForm_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
87
101
  switch (props.category) {
88
102
  case "node":
89
103
  if (!props.type) return [];
90
- return await propsService.getPropsConfig(props.type);
104
+ return removeStyleDisplayConfig(await propsService.getPropsConfig(props.type));
91
105
  case "data-source": return dataSourceService.getFormConfig(props.type || "base");
92
106
  case "code-block": return getCodeBlockFormConfig({
93
107
  paramColConfig: codeBlockService.getParamsColConfig(),
@@ -33,12 +33,15 @@ var useCodeBlockEdit = (codeBlockService) => {
33
33
  await nextTick();
34
34
  codeBlockEditorRef.value?.show();
35
35
  };
36
- const deleteCode = async (key) => {
37
- codeBlockService.deleteCodeDslByIds([key]);
36
+ const deleteCode = async (key, { historySource } = {}) => {
37
+ codeBlockService.deleteCodeDslByIds([key], { historySource });
38
38
  };
39
39
  const submitCodeBlockHandler = async (values, eventData) => {
40
40
  if (!codeId.value) return;
41
- await codeBlockService.setCodeDslById(codeId.value, values, { changeRecords: eventData?.changeRecords });
41
+ await codeBlockService.setCodeDslById(codeId.value, values, {
42
+ changeRecords: eventData?.changeRecords,
43
+ historySource: "props"
44
+ });
42
45
  codeBlockEditorRef.value?.hide();
43
46
  };
44
47
  return {
@@ -12,8 +12,11 @@ var useDataSourceEdit = (dataSourceService) => {
12
12
  editDialog.value.show();
13
13
  };
14
14
  const submitDataSourceHandler = (value, eventData) => {
15
- if (value.id) dataSourceService.update(value, { changeRecords: eventData.changeRecords });
16
- else dataSourceService.add(value);
15
+ if (value.id) dataSourceService.update(value, {
16
+ changeRecords: eventData.changeRecords,
17
+ historySource: "props"
18
+ });
19
+ else dataSourceService.add(value, { historySource: "props" });
17
20
  editDialog.value?.hide();
18
21
  };
19
22
  return {
@@ -96,14 +96,17 @@ var useStage = (stageOptions) => {
96
96
  changeRecordList.push(buildChangeRecords(style, "style"));
97
97
  });
98
98
  if (configs.length === 0) return;
99
- editor_default.update(configs, { changeRecordList });
99
+ editor_default.update(configs, {
100
+ changeRecordList,
101
+ historySource: "stage"
102
+ });
100
103
  });
101
104
  stage.on("sort", (ev) => {
102
- editor_default.sort(ev.src, ev.dist);
105
+ editor_default.sort(ev.src, ev.dist, { historySource: "stage" });
103
106
  });
104
107
  stage.on("remove", (ev) => {
105
108
  const nodes = ev.data.map(({ el }) => editor_default.getNodeById(getIdFromEl()(el) || ""));
106
- editor_default.remove(nodes.filter((node) => Boolean(node)));
109
+ editor_default.remove(nodes.filter((node) => Boolean(node)), { historySource: "stage" });
107
110
  });
108
111
  stage.on("select-parent", () => {
109
112
  const parent = editor_default.get("parent");
@@ -45,7 +45,7 @@ var NavMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
45
45
  disabled: () => editorService.get("node")?.type === NodeType.PAGE,
46
46
  handler: () => {
47
47
  const node = editorService.get("node");
48
- node && editorService.remove(node);
48
+ node && editorService.remove(node, { historySource: "toolbar" });
49
49
  }
50
50
  });
51
51
  break;
@@ -1,4 +1,4 @@
1
- import { formatHistoryFullTime, formatHistoryTime, groupTimestamp } from "./composables.js";
1
+ import { formatHistoryFullTime, formatHistoryTime, groupSource, groupTimestamp } from "./composables.js";
2
2
  import GroupRow_default from "./GroupRow.js";
3
3
  import InitialRow_default from "./InitialRow.js";
4
4
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, openBlock, renderList, toDisplayString, unref } from "vue";
@@ -22,6 +22,7 @@ var Bucket_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineC
22
22
  describeGroup: {},
23
23
  describeStep: {},
24
24
  isStepDiffable: {},
25
+ isStepRevertable: {},
25
26
  expanded: {},
26
27
  gotoEnabled: {
27
28
  type: Boolean,
@@ -53,6 +54,7 @@ var Bucket_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineC
53
54
  merged: group.steps.length > 1,
54
55
  "op-type": group.opType,
55
56
  desc: __props.describeGroup(group),
57
+ source: unref(groupSource)(group),
56
58
  time: unref(formatHistoryTime)(unref(groupTimestamp)(group)),
57
59
  "time-title": unref(formatHistoryFullTime)(unref(groupTimestamp)(group)),
58
60
  "step-count": group.steps.length,
@@ -62,7 +64,8 @@ var Bucket_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineC
62
64
  isCurrent: s.isCurrent,
63
65
  desc: __props.describeStep(s.step),
64
66
  diffable: __props.isStepDiffable ? __props.isStepDiffable(s.step) : false,
65
- revertable: s.applied,
67
+ revertable: s.applied && (__props.isStepRevertable ? __props.isStepRevertable(s.step) : true),
68
+ source: s.step.source,
66
69
  time: unref(formatHistoryTime)(s.step.timestamp),
67
70
  timeTitle: unref(formatHistoryFullTime)(s.step.timestamp)
68
71
  })),
@@ -79,6 +82,7 @@ var Bucket_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineC
79
82
  "merged",
80
83
  "op-type",
81
84
  "desc",
85
+ "source",
82
86
  "time",
83
87
  "time-title",
84
88
  "step-count",
@@ -16,6 +16,7 @@ var BucketTab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
16
16
  describeGroup: {},
17
17
  describeStep: {},
18
18
  isStepDiffable: {},
19
+ isStepRevertable: {},
19
20
  expanded: {},
20
21
  gotoEnabled: {
21
22
  type: Boolean,
@@ -45,6 +46,7 @@ var BucketTab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
45
46
  "describe-group": __props.describeGroup,
46
47
  "describe-step": __props.describeStep,
47
48
  "is-step-diffable": __props.isStepDiffable,
49
+ "is-step-revertable": __props.isStepRevertable,
48
50
  expanded: __props.expanded,
49
51
  "goto-enabled": __props.gotoEnabled,
50
52
  onToggle: _cache[0] || (_cache[0] = (key) => _ctx.$emit("toggle", key)),
@@ -60,6 +62,7 @@ var BucketTab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
60
62
  "describe-group",
61
63
  "describe-step",
62
64
  "is-step-diffable",
65
+ "is-step-revertable",
63
66
  "expanded",
64
67
  "goto-enabled"
65
68
  ]);
@@ -1,25 +1,27 @@
1
- import { opLabel } from "./composables.js";
1
+ import { opLabel, sourceLabel } from "./composables.js";
2
2
  import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, openBlock, renderList, toDisplayString, unref, withModifiers } from "vue";
3
3
  //#region packages/editor/src/layouts/history-list/GroupRow.vue?vue&type=script&setup=true&lang.ts
4
4
  var _hoisted_1 = ["title"];
5
5
  var _hoisted_2 = ["title"];
6
6
  var _hoisted_3 = { class: "m-editor-history-list-item-desc" };
7
7
  var _hoisted_4 = ["title"];
8
- var _hoisted_5 = {
9
- key: 1,
8
+ var _hoisted_5 = ["title"];
9
+ var _hoisted_6 = {
10
+ key: 2,
10
11
  class: "m-editor-history-list-item-merge"
11
12
  };
12
- var _hoisted_6 = {
13
+ var _hoisted_7 = {
13
14
  key: 0,
14
15
  class: "m-editor-history-list-substeps"
15
16
  };
16
- var _hoisted_7 = ["title"];
17
- var _hoisted_8 = { class: "m-editor-history-list-item-index" };
18
- var _hoisted_9 = { class: "m-editor-history-list-substep-desc" };
19
- var _hoisted_10 = ["title"];
20
- var _hoisted_11 = ["onClick"];
21
- var _hoisted_12 = ["onClick"];
17
+ var _hoisted_8 = ["title"];
18
+ var _hoisted_9 = { class: "m-editor-history-list-item-index" };
19
+ var _hoisted_10 = { class: "m-editor-history-list-substep-desc" };
20
+ var _hoisted_11 = ["title"];
21
+ var _hoisted_12 = ["title"];
22
22
  var _hoisted_13 = ["onClick"];
23
+ var _hoisted_14 = ["onClick"];
24
+ var _hoisted_15 = ["onClick"];
23
25
  var GroupRow_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
24
26
  name: "MEditorHistoryListGroupRow",
25
27
  __name: "GroupRow",
@@ -29,6 +31,7 @@ var GroupRow_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defin
29
31
  merged: { type: Boolean },
30
32
  opType: {},
31
33
  desc: {},
34
+ source: {},
32
35
  time: {},
33
36
  timeTitle: {},
34
37
  stepCount: {},
@@ -127,35 +130,40 @@ var GroupRow_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defin
127
130
  }, toDisplayString(headIndexLabel.value), 9, _hoisted_2),
128
131
  createElementVNode("span", { class: normalizeClass(["m-editor-history-list-item-op", `op-${__props.opType}`]) }, toDisplayString(unref(opLabel)(__props.opType)), 3),
129
132
  createElementVNode("span", _hoisted_3, toDisplayString(__props.desc), 1),
130
- __props.time ? (openBlock(), createElementBlock("span", {
133
+ !__props.merged && unref(sourceLabel)(__props.source) ? (openBlock(), createElementBlock("span", {
131
134
  key: 0,
135
+ class: "m-editor-history-list-item-source",
136
+ title: `操作途径:${unref(sourceLabel)(__props.source)}`
137
+ }, toDisplayString(unref(sourceLabel)(__props.source)), 9, _hoisted_4)) : createCommentVNode("v-if", true),
138
+ !__props.merged && __props.time ? (openBlock(), createElementBlock("span", {
139
+ key: 1,
132
140
  class: "m-editor-history-list-item-time",
133
141
  title: __props.timeTitle || __props.time
134
- }, toDisplayString(__props.time), 9, _hoisted_4)) : createCommentVNode("v-if", true),
135
- __props.merged ? (openBlock(), createElementBlock("span", _hoisted_5, "合并 " + toDisplayString(__props.stepCount) + " 步", 1)) : createCommentVNode("v-if", true),
142
+ }, toDisplayString(__props.time), 9, _hoisted_5)) : createCommentVNode("v-if", true),
143
+ __props.merged ? (openBlock(), createElementBlock("span", _hoisted_6, "合并 " + toDisplayString(__props.stepCount) + " 步", 1)) : createCommentVNode("v-if", true),
136
144
  !__props.merged && headRevertable.value ? (openBlock(), createElementBlock("span", {
137
- key: 2,
145
+ key: 3,
138
146
  class: "m-editor-history-list-item-revert",
139
147
  title: "将该步骤的修改作为一次新操作反向应用(不影响后续历史)",
140
148
  onClick: _cache[0] || (_cache[0] = withModifiers(($event) => onRevertClick(__props.subSteps[0].index), ["stop"]))
141
149
  }, "回滚")) : createCommentVNode("v-if", true),
142
150
  !__props.merged && __props.gotoEnabled && !__props.isCurrent && __props.subSteps.length ? (openBlock(), createElementBlock("span", {
143
- key: 3,
151
+ key: 4,
144
152
  class: "m-editor-history-list-item-goto",
145
153
  title: "回到该记录",
146
154
  onClick: _cache[1] || (_cache[1] = withModifiers(($event) => onGotoClick(__props.subSteps[0].index), ["stop"]))
147
155
  }, "回到")) : createCommentVNode("v-if", true),
148
156
  !__props.merged && headDiffable.value ? (openBlock(), createElementBlock("span", {
149
- key: 4,
157
+ key: 5,
150
158
  class: "m-editor-history-list-item-diff",
151
159
  title: "查看修改差异",
152
160
  onClick: _cache[2] || (_cache[2] = withModifiers(($event) => onDiffClick(__props.subSteps[0].index), ["stop"]))
153
161
  }, "查看差异")) : createCommentVNode("v-if", true),
154
162
  __props.merged ? (openBlock(), createElementBlock("span", {
155
- key: 5,
163
+ key: 6,
156
164
  class: normalizeClass(["m-editor-history-list-group-toggle", { "is-expanded": __props.expanded }])
157
165
  }, "▾", 2)) : createCommentVNode("v-if", true)
158
- ], 10, _hoisted_1), __props.merged && __props.expanded ? (openBlock(), createElementBlock("ul", _hoisted_6, [(openBlock(true), createElementBlock(Fragment, null, renderList(subStepsDisplay.value, (s) => {
166
+ ], 10, _hoisted_1), __props.merged && __props.expanded ? (openBlock(), createElementBlock("ul", _hoisted_7, [(openBlock(true), createElementBlock(Fragment, null, renderList(subStepsDisplay.value, (s) => {
159
167
  return openBlock(), createElementBlock("li", {
160
168
  key: s.index,
161
169
  class: normalizeClass({
@@ -164,32 +172,37 @@ var GroupRow_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defin
164
172
  }),
165
173
  title: subStepTitle(s)
166
174
  }, [
167
- createElementVNode("span", _hoisted_8, "#" + toDisplayString(s.index + 1), 1),
168
- createElementVNode("span", _hoisted_9, toDisplayString(s.desc), 1),
169
- s.time ? (openBlock(), createElementBlock("span", {
175
+ createElementVNode("span", _hoisted_9, "#" + toDisplayString(s.index + 1), 1),
176
+ createElementVNode("span", _hoisted_10, toDisplayString(s.desc), 1),
177
+ unref(sourceLabel)(s.source) ? (openBlock(), createElementBlock("span", {
170
178
  key: 0,
179
+ class: "m-editor-history-list-item-source",
180
+ title: `操作途径:${unref(sourceLabel)(s.source)}`
181
+ }, toDisplayString(unref(sourceLabel)(s.source)), 9, _hoisted_11)) : createCommentVNode("v-if", true),
182
+ s.time ? (openBlock(), createElementBlock("span", {
183
+ key: 1,
171
184
  class: "m-editor-history-list-item-time",
172
185
  title: s.timeTitle || s.time
173
- }, toDisplayString(s.time), 9, _hoisted_10)) : createCommentVNode("v-if", true),
186
+ }, toDisplayString(s.time), 9, _hoisted_12)) : createCommentVNode("v-if", true),
174
187
  s.revertable ? (openBlock(), createElementBlock("span", {
175
- key: 1,
188
+ key: 2,
176
189
  class: "m-editor-history-list-item-revert",
177
190
  title: "将该步骤的修改作为一次新操作反向应用(不影响后续历史)",
178
191
  onClick: withModifiers(($event) => onRevertClick(s.index), ["stop"])
179
- }, "回滚", 8, _hoisted_11)) : createCommentVNode("v-if", true),
192
+ }, "回滚", 8, _hoisted_13)) : createCommentVNode("v-if", true),
180
193
  __props.gotoEnabled && !s.isCurrent ? (openBlock(), createElementBlock("span", {
181
- key: 2,
194
+ key: 3,
182
195
  class: "m-editor-history-list-item-goto",
183
196
  title: "回到该记录",
184
197
  onClick: withModifiers(($event) => onGotoClick(s.index), ["stop"])
185
- }, "回到", 8, _hoisted_12)) : createCommentVNode("v-if", true),
198
+ }, "回到", 8, _hoisted_14)) : createCommentVNode("v-if", true),
186
199
  s.diffable ? (openBlock(), createElementBlock("span", {
187
- key: 3,
200
+ key: 4,
188
201
  class: "m-editor-history-list-item-diff",
189
202
  title: "查看修改差异",
190
203
  onClick: withModifiers(($event) => onDiffClick(s.index), ["stop"])
191
- }, "查看差异", 8, _hoisted_13)) : createCommentVNode("v-if", true)
192
- ], 10, _hoisted_7);
204
+ }, "查看差异", 8, _hoisted_15)) : createCommentVNode("v-if", true)
205
+ ], 10, _hoisted_8);
193
206
  }), 128))])) : createCommentVNode("v-if", true)], 2);
194
207
  };
195
208
  }
@@ -88,11 +88,13 @@ var HistoryDiffDialog_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
88
88
  };
89
89
  const targetText = computed(() => {
90
90
  if (!payload.value) return "";
91
- const prefix = {
91
+ const categoryText = {
92
92
  node: "节点",
93
93
  "data-source": "数据源",
94
94
  "code-block": "代码块"
95
- }[payload.value.category] || "";
95
+ };
96
+ const { category } = payload.value;
97
+ const prefix = category ? categoryText[category] : "";
96
98
  const label = payload.value.targetLabel || payload.value.type || "";
97
99
  const { id } = payload.value;
98
100
  return [prefix, id !== void 0 && id !== "" ? `${label}(${id})` : label].filter(Boolean).join(":");
@@ -1,6 +1,6 @@
1
1
  import { useServices } from "../../hooks/use-services.js";
2
2
  import Icon_default from "../../components/Icon.js";
3
- import { describeCodeBlockGroup, describeCodeBlockStep, describeDataSourceGroup, describeDataSourceStep, useHistoryList } from "./composables.js";
3
+ import { describeCodeBlockGroup, describeCodeBlockStep, describeDataSourceGroup, describeDataSourceStep, isCodeBlockStepRevertable, isDataSourceStepRevertable, useHistoryList } from "./composables.js";
4
4
  import BucketTab_default from "./BucketTab.js";
5
5
  import HistoryDiffDialog_default from "./HistoryDiffDialog.js";
6
6
  import PageTab_default from "./PageTab.js";
@@ -274,6 +274,7 @@ var HistoryListPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
274
274
  "describe-group": unref(describeDataSourceGroup),
275
275
  "describe-step": unref(describeDataSourceStep),
276
276
  "is-step-diffable": isDataSourceStepDiffable,
277
+ "is-step-revertable": unref(isDataSourceStepRevertable),
277
278
  onToggle: unref(toggleGroup),
278
279
  onGoto: onDataSourceGoto,
279
280
  onGotoInitial: onDataSourceGotoInitial,
@@ -284,6 +285,7 @@ var HistoryListPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
284
285
  "expanded",
285
286
  "describe-group",
286
287
  "describe-step",
288
+ "is-step-revertable",
287
289
  "onToggle"
288
290
  ])]),
289
291
  _: 1
@@ -300,6 +302,7 @@ var HistoryListPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
300
302
  "describe-group": unref(describeCodeBlockGroup),
301
303
  "describe-step": unref(describeCodeBlockStep),
302
304
  "is-step-diffable": isCodeBlockStepDiffable,
305
+ "is-step-revertable": unref(isCodeBlockStepRevertable),
303
306
  onToggle: unref(toggleGroup),
304
307
  onGoto: onCodeBlockGoto,
305
308
  onGotoInitial: onCodeBlockGotoInitial,
@@ -310,6 +313,7 @@ var HistoryListPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
310
313
  "expanded",
311
314
  "describe-group",
312
315
  "describe-step",
316
+ "is-step-revertable",
313
317
  "onToggle"
314
318
  ])]),
315
319
  _: 1
@@ -1,4 +1,4 @@
1
- import { describePageGroup, describePageStep, formatHistoryFullTime, formatHistoryTime, groupTimestamp } from "./composables.js";
1
+ import { describePageGroup, describePageStep, formatHistoryFullTime, formatHistoryTime, groupSource, groupTimestamp, isPageStepRevertable } from "./composables.js";
2
2
  import GroupRow_default from "./GroupRow.js";
3
3
  import InitialRow_default from "./InitialRow.js";
4
4
  import { TMagicScrollbar } from "@tmagic/design";
@@ -57,6 +57,7 @@ var PageTab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
57
57
  merged: group.steps.length > 1,
58
58
  "op-type": group.opType,
59
59
  desc: unref(describePageGroup)(group),
60
+ source: unref(groupSource)(group),
60
61
  time: unref(formatHistoryTime)(unref(groupTimestamp)(group)),
61
62
  "time-title": unref(formatHistoryFullTime)(unref(groupTimestamp)(group)),
62
63
  "step-count": group.steps.length,
@@ -66,7 +67,8 @@ var PageTab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
66
67
  isCurrent: s.isCurrent,
67
68
  desc: unref(describePageStep)(s.step),
68
69
  diffable: isPageStepDiffable(s.step),
69
- revertable: s.applied,
70
+ revertable: s.applied && unref(isPageStepRevertable)(s.step),
71
+ source: s.step.source,
70
72
  time: unref(formatHistoryTime)(s.step.timestamp),
71
73
  timeTitle: unref(formatHistoryFullTime)(s.step.timestamp)
72
74
  })),
@@ -82,6 +84,7 @@ var PageTab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
82
84
  "merged",
83
85
  "op-type",
84
86
  "desc",
87
+ "source",
85
88
  "time",
86
89
  "time-title",
87
90
  "step-count",
@@ -73,6 +73,28 @@ var opLabel = (op) => {
73
73
  default: return "修改";
74
74
  }
75
75
  };
76
+ /** 内置操作途径的中文文案;自定义来源直接回显原值,未知 / 缺省返回空串(UI 据此不渲染)。 */
77
+ var HISTORY_SOURCE_LABELS = {
78
+ stage: "画布",
79
+ tree: "树面板",
80
+ "component-panel": "组件面板",
81
+ props: "配置面板",
82
+ code: "源码",
83
+ "stage-contextmenu": "画布菜单",
84
+ "tree-contextmenu": "树菜单",
85
+ toolbar: "工具栏",
86
+ shortcut: "快捷键",
87
+ rollback: "回滚",
88
+ api: "接口",
89
+ ai: "AI",
90
+ unknown: "未知"
91
+ };
92
+ /** 操作途径文案:用于历史面板展示「画布 / 树面板 / 配置面板…」标签。 */
93
+ var sourceLabel = (source = "unknown") => {
94
+ return HISTORY_SOURCE_LABELS[source] ?? `${source}`;
95
+ };
96
+ /** 取一组历史步骤里最后一步(最近一次)的操作途径,用于组头部展示。 */
97
+ var groupSource = (group) => group.steps[group.steps.length - 1]?.step.source;
76
98
  var nameOf = (node) => node?.name || node?.type || `${node?.id ?? ""}`;
77
99
  /**
78
100
  * 默认描述里展示「名称 (id: xxx)」,便于区分同名实体。
@@ -168,5 +190,35 @@ var describeCodeBlockGroup = (group) => {
168
190
  const target = labelWithId(group.steps[group.steps.length - 1].step.newContent?.name || group.steps[0].step.oldContent?.name, group.id);
169
191
  return pathList ? `修改 ${target} · ${pathList}${paths.size > 3 ? "…" : ""}` : `修改 ${target}`;
170
192
  };
193
+ /**
194
+ * 页面 step 是否支持「回滚」(类 git revert):
195
+ * - 新增 / 删除:不依赖 changeRecords,反向应用即删除 / 加回,始终可回滚;
196
+ * - 更新:必须每个被更新节点都带有 changeRecords,才支持按 propPath 局部反向 patch。
197
+ * 缺失 changeRecords 的更新只能整节点替换,会冲掉该节点后续的无关变更,因此不支持回滚。
198
+ */
199
+ var isPageStepRevertable = (step) => {
200
+ if (step.opType !== "update") return true;
201
+ const items = step.updatedItems ?? [];
202
+ if (!items.length) return false;
203
+ return items.every((item) => Boolean(item.changeRecords?.length));
204
+ };
205
+ /**
206
+ * 数据源 step 是否支持「回滚」:
207
+ * - 新增(oldSchema=null)/ 删除(newSchema=null):不依赖 changeRecords,始终可回滚;
208
+ * - 更新(前后 schema 都存在):必须有 changeRecords 才支持局部反向 patch,否则不支持回滚。
209
+ */
210
+ var isDataSourceStepRevertable = (step) => {
211
+ if (step.oldSchema === null || step.newSchema === null) return true;
212
+ return Boolean(step.changeRecords?.length);
213
+ };
214
+ /**
215
+ * 代码块 step 是否支持「回滚」:
216
+ * - 新增(oldContent=null)/ 删除(newContent=null):不依赖 changeRecords,始终可回滚;
217
+ * - 更新(前后 content 都存在):必须有 changeRecords 才支持局部反向 patch,否则不支持回滚。
218
+ */
219
+ var isCodeBlockStepRevertable = (step) => {
220
+ if (step.oldContent === null || step.newContent === null) return true;
221
+ return Boolean(step.changeRecords?.length);
222
+ };
171
223
  //#endregion
172
- export { describeCodeBlockGroup, describeCodeBlockStep, describeDataSourceGroup, describeDataSourceStep, describePageGroup, describePageStep, formatHistoryFullTime, formatHistoryTime, groupTimestamp, opLabel, useHistoryList };
224
+ export { describeCodeBlockGroup, describeCodeBlockStep, describeDataSourceGroup, describeDataSourceStep, describePageGroup, describePageStep, formatHistoryFullTime, formatHistoryTime, groupSource, groupTimestamp, isCodeBlockStepRevertable, isDataSourceStepRevertable, isPageStepRevertable, opLabel, sourceLabel, useHistoryList };
@@ -69,7 +69,11 @@ var PropsPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
69
69
  if (record.propPath?.startsWith("style") && record.value === "") setValueByKeyPath(record.propPath, record.value, newValue);
70
70
  });
71
71
  }
72
- editorService.update(newValue, { changeRecords: eventData?.changeRecords });
72
+ const historySource = eventData ? "props" : "code";
73
+ editorService.update(newValue, {
74
+ changeRecords: eventData?.changeRecords,
75
+ historySource
76
+ });
73
77
  } catch (e) {
74
78
  emit("submit-error", e);
75
79
  }
@@ -37,7 +37,7 @@ var ComponentListPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
37
37
  name: text,
38
38
  type,
39
39
  ...data
40
- });
40
+ }, void 0, { historySource: "component-panel" });
41
41
  };
42
42
  const dragstartHandler = ({ text, type, data = {} }, e) => {
43
43
  e.dataTransfer?.setData("text/json", serialize({
@@ -78,7 +78,7 @@ var CodeBlockList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
78
78
  const editCode = (id) => {
79
79
  emit("edit", id);
80
80
  };
81
- const deleteCode = async (id) => {
81
+ const deleteCode = async (id, { historySource } = {}) => {
82
82
  const currentCode = codeList.value.find((codeItem) => codeItem.id === id);
83
83
  const existBinds = Boolean(currentCode?.items?.length);
84
84
  const undeleteableList = codeBlockService.getUndeletableList() || [];
@@ -88,7 +88,7 @@ var CodeBlockList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
88
88
  cancelButtonText: "取消",
89
89
  type: "warning"
90
90
  });
91
- emit("remove", id);
91
+ emit("remove", id, { historySource });
92
92
  } else if (typeof props.customError === "function") props.customError(id, existBinds ? CodeDeleteErrorType.BIND : CodeDeleteErrorType.UNDELETEABLE);
93
93
  else if (existBinds) tMagicMessage.error("代码块存在绑定关系,不可删除");
94
94
  else tMagicMessage.error("代码块不可删除");
@@ -138,7 +138,7 @@ var CodeBlockList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
138
138
  default: withCtx(() => [createVNode(Icon_default, {
139
139
  icon: unref(Close),
140
140
  class: "edit-icon",
141
- onClick: withModifiers(($event) => deleteCode(`${data.key}`), ["stop"])
141
+ onClick: withModifiers(($event) => deleteCode(`${data.key}`, { historySource: "tree" }), ["stop"])
142
142
  }, null, 8, ["icon", "onClick"])]),
143
143
  _: 2
144
144
  }, 1024)) : createCommentVNode("v-if", true),
@@ -38,7 +38,7 @@ var CodeBlockListPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
38
38
  if (codeBlockListRef.value) for (const [, status] of codeBlockListRef.value.nodeStatusMap.entries()) status.selected = false;
39
39
  };
40
40
  const { nodeContentMenuHandler, menuData: contentMenuData, contentMenuHideHandler } = useContentMenu((id) => {
41
- codeBlockListRef.value?.deleteCode(id);
41
+ codeBlockListRef.value?.deleteCode(id, { historySource: "tree-contextmenu" });
42
42
  });
43
43
  const menuData = computed(() => props.customContentMenu(contentMenuData, "code-block"));
44
44
  return (_ctx, _cache) => {
@@ -26,7 +26,7 @@ var useContentMenu = (deleteCode) => {
26
26
  const codeBlock = codeBlockService.getCodeContentById(selectId);
27
27
  if (!codeBlock) return;
28
28
  const newCodeId = await codeBlockService.getUniqueId();
29
- codeBlockService.setCodeDslById(newCodeId, cloneDeep(codeBlock));
29
+ codeBlockService.setCodeDslById(newCodeId, cloneDeep(codeBlock), { historySource: "tree-contextmenu" });
30
30
  }
31
31
  },
32
32
  {
@@ -55,7 +55,7 @@ var DataSourceListPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE
55
55
  cancelButtonText: "取消",
56
56
  type: "warning"
57
57
  });
58
- dataSourceService.remove(id);
58
+ dataSourceService.remove(id, { historySource: "tree-contextmenu" });
59
59
  };
60
60
  const dataSourceListRef = useTemplateRef("dataSourceList");
61
61
  const filterTextChangeHandler = (val) => {
@@ -25,7 +25,7 @@ var useContentMenu = () => {
25
25
  if (!selectId) return;
26
26
  const ds = dataSourceService.getDataSourceById(selectId);
27
27
  if (!ds) return;
28
- dataSourceService.add(cloneDeep(ds));
28
+ dataSourceService.add(cloneDeep(ds), { historySource: "tree-contextmenu" });
29
29
  }
30
30
  },
31
31
  {
@@ -32,7 +32,7 @@ var LayerMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
32
32
  name: component.text,
33
33
  type: component.type,
34
34
  ...component.data || {}
35
- });
35
+ }, void 0, { historySource: "tree-contextmenu" });
36
36
  }
37
37
  }));
38
38
  const getSubMenuData = computed(() => {
@@ -41,7 +41,7 @@ var LayerMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
41
41
  type: "button",
42
42
  icon: Files,
43
43
  handler: () => {
44
- editorService.add({ type: "tab-pane" });
44
+ editorService.add({ type: "tab-pane" }, void 0, { historySource: "tree-contextmenu" });
45
45
  }
46
46
  }];
47
47
  if (node.value?.items) return componentList.value.reduce((subMenuData, group, index) => subMenuData.concat(createMenuItems(group), index < componentList.value.length - 1 ? [{
@@ -68,9 +68,9 @@ var LayerMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
68
68
  items: getSubMenuData.value
69
69
  },
70
70
  useCopyMenu(),
71
- usePasteMenu(),
72
- useDeleteMenu(),
73
- useMoveToMenu(services),
71
+ usePasteMenu("tree-contextmenu"),
72
+ useDeleteMenu("tree-contextmenu"),
73
+ useMoveToMenu(services, "tree-contextmenu"),
74
74
  ...props.layerContentMenu
75
75
  ], "layer"));
76
76
  const show = (e) => {
@@ -13,7 +13,7 @@ var LayerNodeTool_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
13
13
  editorService.update({
14
14
  id: props.data.id,
15
15
  visible
16
- });
16
+ }, { historySource: "tree" });
17
17
  };
18
18
  return (_ctx, _cache) => {
19
19
  return __props.data.type !== "page" ? (openBlock(), createBlock(unref(TMagicButton), {
@@ -226,7 +226,7 @@ var Stage_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCo
226
226
  left: calcValueByFontsize(doc, left / zoom.value)
227
227
  };
228
228
  config.data.inputEvent = e;
229
- editorService.add(config.data, parent);
229
+ editorService.add(config.data, parent, { historySource: "component-panel" });
230
230
  }
231
231
  };
232
232
  return (_ctx, _cache) => {