@tmagic/editor 1.8.0-beta.3 → 1.8.0-beta.5
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.
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +15 -1
- package/dist/es/components/ToolButton.vue_vue_type_script_setup_true_lang.js +6 -6
- package/dist/es/hooks/use-code-block-edit.js +6 -3
- package/dist/es/hooks/use-data-source-edit.js +5 -2
- package/dist/es/hooks/use-stage.js +6 -3
- package/dist/es/index.js +6 -3
- package/dist/es/initService.js +1 -1
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +19 -51
- package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +22 -36
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +152 -93
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +36 -10
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +334 -208
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +28 -7
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +47 -57
- package/dist/es/layouts/history-list/composables.js +118 -25
- package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +5 -1
- package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +5 -1
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/data-source/useContentMenu.js +1 -1
- package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/es/services/codeBlock.js +105 -42
- package/dist/es/services/dataSource.js +85 -35
- package/dist/es/services/editor.js +317 -122
- package/dist/es/services/history.js +270 -204
- package/dist/es/services/keybinding.js +3 -3
- package/dist/es/services/ui.js +3 -0
- package/dist/es/style.css +65 -10
- package/dist/es/utils/content-menu.js +17 -9
- package/dist/es/utils/editor.js +35 -1
- package/dist/es/utils/history.js +223 -0
- package/dist/es/utils/indexed-db.js +86 -0
- package/dist/es/utils/undo-redo.js +60 -1
- package/dist/style.css +65 -10
- package/dist/tmagic-editor.umd.cjs +2047 -954
- package/package.json +7 -7
- package/src/components/CompareForm.vue +21 -1
- package/src/components/ToolButton.vue +2 -2
- package/src/hooks/use-code-block-edit.ts +4 -3
- package/src/hooks/use-data-source-edit.ts +2 -2
- package/src/hooks/use-stage.ts +3 -3
- package/src/index.ts +1 -0
- package/src/initService.ts +1 -1
- package/src/layouts/Framework.vue +1 -1
- package/src/layouts/NavMenu.vue +1 -1
- package/src/layouts/history-list/Bucket.vue +34 -67
- package/src/layouts/history-list/BucketTab.vue +46 -51
- package/src/layouts/history-list/GroupRow.vue +150 -98
- package/src/layouts/history-list/HistoryDiffDialog.vue +96 -69
- package/src/layouts/history-list/HistoryListPanel.vue +298 -111
- package/src/layouts/history-list/InitialRow.vue +25 -9
- package/src/layouts/history-list/PageTab.vue +58 -48
- package/src/layouts/history-list/composables.ts +210 -29
- package/src/layouts/page-bar/PageBar.vue +4 -2
- package/src/layouts/props-panel/PropsPanel.vue +5 -1
- package/src/layouts/sidebar/ComponentListPanel.vue +9 -5
- package/src/layouts/sidebar/Sidebar.vue +6 -1
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -1
- package/src/layouts/sidebar/code-block/useContentMenu.ts +1 -1
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -1
- package/src/layouts/sidebar/data-source/useContentMenu.ts +1 -1
- package/src/layouts/sidebar/layer/LayerMenu.vue +19 -11
- package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
- package/src/layouts/workspace/viewer/Stage.vue +1 -1
- package/src/layouts/workspace/viewer/ViewerMenu.vue +8 -8
- package/src/services/codeBlock.ts +129 -35
- package/src/services/dataSource.ts +105 -34
- package/src/services/editor.ts +470 -157
- package/src/services/history.ts +312 -203
- package/src/services/keybinding.ts +3 -3
- package/src/services/ui.ts +7 -0
- package/src/theme/history-list-panel.scss +87 -6
- package/src/theme/page-bar.scss +0 -4
- package/src/theme/props-panel.scss +3 -3
- package/src/type.ts +221 -61
- package/src/utils/content-menu.ts +18 -9
- package/src/utils/editor.ts +41 -1
- package/src/utils/history.ts +298 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/indexed-db.ts +122 -0
- package/src/utils/undo-redo.ts +88 -0
- package/types/index.d.ts +871 -308
|
@@ -3,44 +3,24 @@ import BaseService from "./BaseService.js";
|
|
|
3
3
|
import props_default from "./props.js";
|
|
4
4
|
import history_default from "./history.js";
|
|
5
5
|
import storage_default, { Protocol } from "./storage.js";
|
|
6
|
-
import { COPY_STORAGE_KEY, calcAlignCenterStyle, calcLayerTargetIndex, calcMoveStyle, classifyDragSources, collectRelatedNodes, editorNodeMergeCustomizer, fixNodePosition, getInitPositionStyle, getNodeIndex, getPageFragmentList, getPageList, moveItemsInContainer, resolveSelectedNode, setChildrenLayout, setLayout, toggleFixedPosition } from "../utils/editor.js";
|
|
6
|
+
import { COPY_STORAGE_KEY, calcAlignCenterStyle, calcLayerTargetIndex, calcMoveStyle, classifyDragSources, collectRelatedNodes, describeStepForRevert, editorNodeMergeCustomizer, fixNodePosition, getInitPositionStyle, getNodeIndex, getPageFragmentList, getPageList, moveItemsInContainer, resolveSelectedNode, setChildrenLayout, setLayout, toggleFixedPosition } from "../utils/editor.js";
|
|
7
7
|
import { beforePaste, getAddParent } from "../utils/operator.js";
|
|
8
8
|
import { isFixed } from "@tmagic/stage";
|
|
9
|
-
import { getNodeInfo, getNodePath, getValueByKeyPath, isPage, isPageFragment, setValueByKeyPath } from "@tmagic/utils";
|
|
9
|
+
import { getNodeInfo, getNodePath, getValueByKeyPath, guid, isPage, isPageFragment, setValueByKeyPath } from "@tmagic/utils";
|
|
10
10
|
import { NodeType } from "@tmagic/core";
|
|
11
11
|
import { reactive, toRaw } from "vue";
|
|
12
|
-
import { cloneDeep as cloneDeep$1, isObject, mergeWith, uniq } from "lodash-es";
|
|
12
|
+
import { cloneDeep as cloneDeep$1, isEmpty, isEqual, isObject, mergeWith, uniq } from "lodash-es";
|
|
13
13
|
//#region packages/editor/src/services/editor.ts
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* 把「变更前后节点快照」列表归一成 update 类型的 {@link StepDiffItem} 列表,供 {@link StepValue.diff} 使用。
|
|
16
|
+
* `changeRecords` 来自 form 端的 propPath/value 列表,撤销/重做时只对这些 propPath 做局部更新;
|
|
17
|
+
* 缺省(未传 / 空数组)才退化为整节点替换。
|
|
17
18
|
*/
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const label = node?.name || node?.type || (node?.id !== void 0 ? `${node.id}` : "");
|
|
24
|
-
return `撤回新增 ${count} 个节点${count === 1 && label ? `(${label})` : ""}`;
|
|
25
|
-
}
|
|
26
|
-
case "remove": {
|
|
27
|
-
const count = step.removedItems?.length ?? 0;
|
|
28
|
-
const node = step.removedItems?.[0]?.node;
|
|
29
|
-
const label = node?.name || node?.type || (node?.id !== void 0 ? `${node.id}` : "");
|
|
30
|
-
return `还原已删除的 ${count} 个节点${count === 1 && label ? `(${label})` : ""}`;
|
|
31
|
-
}
|
|
32
|
-
default: {
|
|
33
|
-
const items = step.updatedItems ?? [];
|
|
34
|
-
if (items.length === 1) {
|
|
35
|
-
const { newNode, oldNode, changeRecords } = items[0];
|
|
36
|
-
const target = newNode?.name || newNode?.type || oldNode?.name || oldNode?.type || `${newNode?.id ?? ""}`;
|
|
37
|
-
const propPath = changeRecords?.[0]?.propPath;
|
|
38
|
-
return propPath ? `还原 ${target} · ${propPath}` : `还原 ${target}`;
|
|
39
|
-
}
|
|
40
|
-
return `还原 ${items.length} 个节点的修改`;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
};
|
|
19
|
+
var buildUpdateDiff = (items) => items.map(({ oldNode, newNode, changeRecords }) => ({
|
|
20
|
+
oldSchema: oldNode,
|
|
21
|
+
newSchema: newNode,
|
|
22
|
+
...changeRecords?.length ? { changeRecords } : {}
|
|
23
|
+
}));
|
|
44
24
|
var Editor = class extends BaseService {
|
|
45
25
|
state = reactive({
|
|
46
26
|
root: null,
|
|
@@ -58,6 +38,12 @@ var Editor = class extends BaseService {
|
|
|
58
38
|
alwaysMultiSelect: false
|
|
59
39
|
});
|
|
60
40
|
selectionBeforeOp = null;
|
|
41
|
+
/**
|
|
42
|
+
* 最近一次 pushOpHistory 写入的历史记录 uuid。
|
|
43
|
+
* 供 *AndGetHistoryId 系列方法在调用普通操作后取回本次产生的历史记录 id;
|
|
44
|
+
* 普通操作不会读取它,调用前由 *AndGetHistoryId 重置为 null。
|
|
45
|
+
*/
|
|
46
|
+
lastPushedHistoryId = null;
|
|
61
47
|
constructor() {
|
|
62
48
|
super(canUsePluginMethods.async.map((methodName) => ({
|
|
63
49
|
name: methodName,
|
|
@@ -72,8 +58,9 @@ var Editor = class extends BaseService {
|
|
|
72
58
|
* 设置当前指点节点配置
|
|
73
59
|
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength
|
|
74
60
|
* @param value MNode
|
|
61
|
+
* @param options.historySource 设置 root 时,本次变更写入历史记录的「操作来源」(仅 name === 'root' 时生效)
|
|
75
62
|
*/
|
|
76
|
-
set(name, value) {
|
|
63
|
+
set(name, value, options = {}) {
|
|
77
64
|
const preValue = this.state[name];
|
|
78
65
|
this.state[name] = value;
|
|
79
66
|
if (name === "nodes" && Array.isArray(value)) this.set("node", value[0]);
|
|
@@ -84,6 +71,13 @@ var Editor = class extends BaseService {
|
|
|
84
71
|
this.state.pageLength = getPageList(app).length || 0;
|
|
85
72
|
this.state.pageFragmentLength = getPageFragmentList(app).length || 0;
|
|
86
73
|
this.state.stageLoading = this.state.pageLength !== 0;
|
|
74
|
+
if (preValue && !isEmpty(preValue)) this.pushRootDiffHistory(preValue, app, options.historySource);
|
|
75
|
+
else app.items?.forEach((pageNode) => {
|
|
76
|
+
if (pageNode?.id !== void 0 && !history_default.getPageMarker(pageNode.id)) history_default.setPageMarker(pageNode.id, {
|
|
77
|
+
name: pageNode.name,
|
|
78
|
+
source: options.historySource
|
|
79
|
+
});
|
|
80
|
+
});
|
|
87
81
|
} else {
|
|
88
82
|
this.state.pageLength = 0;
|
|
89
83
|
this.state.pageFragmentLength = 0;
|
|
@@ -109,7 +103,23 @@ var Editor = class extends BaseService {
|
|
|
109
103
|
getNodeInfo(id, raw = true) {
|
|
110
104
|
let root = this.get("root");
|
|
111
105
|
if (raw) root = toRaw(root);
|
|
112
|
-
|
|
106
|
+
if (!root) return {
|
|
107
|
+
node: null,
|
|
108
|
+
parent: null,
|
|
109
|
+
page: null
|
|
110
|
+
};
|
|
111
|
+
if (id === root.id) return {
|
|
112
|
+
node: root,
|
|
113
|
+
parent: null,
|
|
114
|
+
page: null
|
|
115
|
+
};
|
|
116
|
+
const pageIdStr = `${this.get("page")?.id || ""}`;
|
|
117
|
+
const currentPageNode = root.items?.find((item) => `${item.id}` === pageIdStr);
|
|
118
|
+
if (currentPageNode && `${id}` !== pageIdStr) {
|
|
119
|
+
const info = getNodeInfo(id, currentPageNode);
|
|
120
|
+
if (info.node) return info;
|
|
121
|
+
}
|
|
122
|
+
return getNodeInfo(id, root, currentPageNode);
|
|
113
123
|
}
|
|
114
124
|
/**
|
|
115
125
|
* 根据ID获取指点节点配置
|
|
@@ -269,7 +279,7 @@ var Editor = class extends BaseService {
|
|
|
269
279
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
270
280
|
* @returns 添加后的节点
|
|
271
281
|
*/
|
|
272
|
-
async add(addNode, parent, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription } = {}) {
|
|
282
|
+
async add(addNode, parent, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
273
283
|
this.captureSelectionBeforeOp();
|
|
274
284
|
const stage = this.get("stage");
|
|
275
285
|
const addNodes = [];
|
|
@@ -302,18 +312,26 @@ var Editor = class extends BaseService {
|
|
|
302
312
|
}
|
|
303
313
|
if (!(isPage(newNodes[0]) || isPageFragment(newNodes[0]))) {
|
|
304
314
|
const pageForOp = this.getNodeInfo(newNodes[0].id, false).page;
|
|
305
|
-
if (!doNotPushHistory)
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
if (!doNotPushHistory) {
|
|
316
|
+
const parentId = (this.getParentById(newNodes[0].id, false) ?? this.get("root")).id;
|
|
317
|
+
this.pushOpHistory("add", {
|
|
318
|
+
diff: newNodes.map((n) => {
|
|
319
|
+
const p = this.getParentById(n.id, false);
|
|
320
|
+
const idx = p ? getNodeIndex(n.id, p) : -1;
|
|
321
|
+
return {
|
|
322
|
+
newSchema: cloneDeep$1(toRaw(n)),
|
|
323
|
+
parentId,
|
|
324
|
+
index: typeof idx === "number" ? idx : -1
|
|
325
|
+
};
|
|
326
|
+
}),
|
|
327
|
+
pageData: {
|
|
328
|
+
name: pageForOp?.name || "",
|
|
329
|
+
id: pageForOp.id
|
|
330
|
+
},
|
|
331
|
+
historyDescription,
|
|
332
|
+
source: historySource
|
|
333
|
+
});
|
|
334
|
+
} else this.selectionBeforeOp = null;
|
|
317
335
|
}
|
|
318
336
|
this.emit("add", newNodes);
|
|
319
337
|
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
@@ -379,7 +397,7 @@ var Editor = class extends BaseService {
|
|
|
379
397
|
* @param options.doNotSwitchPage 删除后是否不切换当前页面(默认 false;删除页面 / 页面片段时为 true 会跳过自动切换到首个剩余页面)
|
|
380
398
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
381
399
|
*/
|
|
382
|
-
async remove(nodeOrNodeList, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription } = {}) {
|
|
400
|
+
async remove(nodeOrNodeList, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
383
401
|
this.captureSelectionBeforeOp();
|
|
384
402
|
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
385
403
|
const removedItems = [];
|
|
@@ -393,7 +411,7 @@ var Editor = class extends BaseService {
|
|
|
393
411
|
};
|
|
394
412
|
const idx = getNodeIndex(curNode.id, parent);
|
|
395
413
|
removedItems.push({
|
|
396
|
-
|
|
414
|
+
oldSchema: cloneDeep$1(toRaw(curNode)),
|
|
397
415
|
parentId: parent.id,
|
|
398
416
|
index: typeof idx === "number" ? idx : -1
|
|
399
417
|
});
|
|
@@ -403,11 +421,16 @@ var Editor = class extends BaseService {
|
|
|
403
421
|
doNotSelect,
|
|
404
422
|
doNotSwitchPage
|
|
405
423
|
})));
|
|
406
|
-
if (removedItems.length > 0 && pageForOp) if (!doNotPushHistory) this.pushOpHistory("remove", {
|
|
424
|
+
if (removedItems.length > 0 && pageForOp) if (!doNotPushHistory) this.pushOpHistory("remove", {
|
|
425
|
+
diff: removedItems,
|
|
426
|
+
pageData: pageForOp,
|
|
427
|
+
historyDescription,
|
|
428
|
+
source: historySource
|
|
429
|
+
});
|
|
407
430
|
else this.selectionBeforeOp = null;
|
|
408
431
|
this.emit("remove", nodes);
|
|
409
432
|
}
|
|
410
|
-
async doUpdate(config, { changeRecords = [] } = {}) {
|
|
433
|
+
async doUpdate(config, { changeRecords = [], historySource } = {}) {
|
|
411
434
|
const root = this.get("root");
|
|
412
435
|
if (!root) throw new Error("root为空");
|
|
413
436
|
if (!config?.id) throw new Error("没有配置或者配置缺少id值");
|
|
@@ -418,7 +441,7 @@ var Editor = class extends BaseService {
|
|
|
418
441
|
newConfig = mergeWith(cloneDeep$1(node), newConfig, editorNodeMergeCustomizer);
|
|
419
442
|
if (!newConfig.type) throw new Error("配置缺少type值");
|
|
420
443
|
if (newConfig.type === NodeType.ROOT) {
|
|
421
|
-
this.set("root", newConfig);
|
|
444
|
+
this.set("root", newConfig, { historySource });
|
|
422
445
|
return {
|
|
423
446
|
oldNode: node,
|
|
424
447
|
newNode: newConfig,
|
|
@@ -464,23 +487,31 @@ var Editor = class extends BaseService {
|
|
|
464
487
|
*/
|
|
465
488
|
async update(config, data = {}) {
|
|
466
489
|
this.captureSelectionBeforeOp();
|
|
467
|
-
const { doNotPushHistory = false, changeRecordList, changeRecords, historyDescription } = data;
|
|
490
|
+
const { doNotPushHistory = false, changeRecordList, changeRecords, historyDescription, historySource } = data;
|
|
468
491
|
const nodes = Array.isArray(config) ? config : [config];
|
|
469
492
|
const updateData = await Promise.all(nodes.map((node, index) => {
|
|
470
493
|
const recordsForNode = changeRecordList ? changeRecordList[index] ?? [] : changeRecords ?? [];
|
|
471
|
-
return this.doUpdate(node, {
|
|
494
|
+
return this.doUpdate(node, {
|
|
495
|
+
changeRecords: recordsForNode,
|
|
496
|
+
historySource
|
|
497
|
+
});
|
|
472
498
|
}));
|
|
473
499
|
if (updateData[0].oldNode?.type !== NodeType.ROOT) {
|
|
474
500
|
if (this.get("nodes").length) if (!doNotPushHistory) {
|
|
475
501
|
const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
|
|
476
|
-
this.pushOpHistory("update", {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
502
|
+
this.pushOpHistory("update", {
|
|
503
|
+
diff: buildUpdateDiff(updateData.map((d) => ({
|
|
504
|
+
oldNode: cloneDeep$1(d.oldNode),
|
|
505
|
+
newNode: cloneDeep$1(d.newNode),
|
|
506
|
+
changeRecords: d.changeRecords?.length ? cloneDeep$1(d.changeRecords) : void 0
|
|
507
|
+
}))),
|
|
508
|
+
pageData: {
|
|
509
|
+
name: pageForOp?.name || "",
|
|
510
|
+
id: pageForOp.id
|
|
511
|
+
},
|
|
512
|
+
historyDescription,
|
|
513
|
+
source: historySource
|
|
514
|
+
});
|
|
484
515
|
} else this.selectionBeforeOp = null;
|
|
485
516
|
}
|
|
486
517
|
this.emit("update", updateData);
|
|
@@ -496,7 +527,7 @@ var Editor = class extends BaseService {
|
|
|
496
527
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
497
528
|
* @returns void
|
|
498
529
|
*/
|
|
499
|
-
async sort(id1, id2, { doNotSelect = false, doNotPushHistory = false } = {}) {
|
|
530
|
+
async sort(id1, id2, { doNotSelect = false, doNotPushHistory = false, historySource } = {}) {
|
|
500
531
|
this.captureSelectionBeforeOp();
|
|
501
532
|
const root = this.get("root");
|
|
502
533
|
if (!root) throw new Error("root为空");
|
|
@@ -508,7 +539,10 @@ var Editor = class extends BaseService {
|
|
|
508
539
|
if (index2 < 0) return;
|
|
509
540
|
const index1 = parent.items.findIndex((node) => `${node.id}` === `${id1}`);
|
|
510
541
|
parent.items.splice(index2, 0, ...parent.items.splice(index1, 1));
|
|
511
|
-
await this.update(parent, {
|
|
542
|
+
await this.update(parent, {
|
|
543
|
+
doNotPushHistory,
|
|
544
|
+
historySource
|
|
545
|
+
});
|
|
512
546
|
if (!doNotSelect) await this.select(node);
|
|
513
547
|
this.get("stage")?.update({
|
|
514
548
|
config: cloneDeep$1(node),
|
|
@@ -544,7 +578,7 @@ var Editor = class extends BaseService {
|
|
|
544
578
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
545
579
|
* @returns 添加后的组件节点配置
|
|
546
580
|
*/
|
|
547
|
-
async paste(position = {}, collectorOptions, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false } = {}) {
|
|
581
|
+
async paste(position = {}, collectorOptions, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
548
582
|
const config = storage_default.getItem(COPY_STORAGE_KEY);
|
|
549
583
|
if (!Array.isArray(config)) return;
|
|
550
584
|
const node = this.get("node");
|
|
@@ -558,7 +592,9 @@ var Editor = class extends BaseService {
|
|
|
558
592
|
return this.add(pasteConfigs, parent, {
|
|
559
593
|
doNotSelect,
|
|
560
594
|
doNotSwitchPage,
|
|
561
|
-
doNotPushHistory
|
|
595
|
+
doNotPushHistory,
|
|
596
|
+
historyDescription,
|
|
597
|
+
historySource
|
|
562
598
|
});
|
|
563
599
|
}
|
|
564
600
|
async doPaste(config, position = {}) {
|
|
@@ -586,11 +622,15 @@ var Editor = class extends BaseService {
|
|
|
586
622
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
587
623
|
* @returns 当前组件节点配置
|
|
588
624
|
*/
|
|
589
|
-
async alignCenter(config, { doNotSelect = false, doNotPushHistory = false } = {}) {
|
|
625
|
+
async alignCenter(config, { doNotSelect = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
590
626
|
const nodes = Array.isArray(config) ? config : [config];
|
|
591
627
|
const stage = this.get("stage");
|
|
592
628
|
const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
|
|
593
|
-
const newNode = await this.update(newNodes, {
|
|
629
|
+
const newNode = await this.update(newNodes, {
|
|
630
|
+
doNotPushHistory,
|
|
631
|
+
historyDescription,
|
|
632
|
+
historySource
|
|
633
|
+
});
|
|
594
634
|
if (!doNotSelect) if (newNodes.length > 1) await stage?.multiSelect(newNodes.map((node) => node.id));
|
|
595
635
|
else await stage?.select(newNodes[0].id);
|
|
596
636
|
return newNode;
|
|
@@ -601,7 +641,7 @@ var Editor = class extends BaseService {
|
|
|
601
641
|
* @param options 可选配置
|
|
602
642
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
603
643
|
*/
|
|
604
|
-
async moveLayer(offset, { doNotPushHistory = false } = {}) {
|
|
644
|
+
async moveLayer(offset, { doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
605
645
|
this.captureSelectionBeforeOp();
|
|
606
646
|
const root = this.get("root");
|
|
607
647
|
if (!root) throw new Error("root为空");
|
|
@@ -626,12 +666,17 @@ var Editor = class extends BaseService {
|
|
|
626
666
|
this.addModifiedNodeId(parent.id);
|
|
627
667
|
if (!doNotPushHistory) {
|
|
628
668
|
const pageForOp = this.getNodeInfo(node.id, false).page;
|
|
629
|
-
this.pushOpHistory("update", {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
669
|
+
this.pushOpHistory("update", {
|
|
670
|
+
diff: buildUpdateDiff([{
|
|
671
|
+
oldNode: oldParent,
|
|
672
|
+
newNode: cloneDeep$1(toRaw(parent))
|
|
673
|
+
}]),
|
|
674
|
+
pageData: {
|
|
675
|
+
name: pageForOp?.name || "",
|
|
676
|
+
id: pageForOp.id
|
|
677
|
+
},
|
|
678
|
+
historyDescription,
|
|
679
|
+
source: historySource
|
|
635
680
|
});
|
|
636
681
|
} else this.selectionBeforeOp = null;
|
|
637
682
|
this.emit("move-layer", offset);
|
|
@@ -650,7 +695,7 @@ var Editor = class extends BaseService {
|
|
|
650
695
|
* @param options.doNotSwitchPage 移动后是否不切换当前页面(默认 false;目标容器位于其它页面时为 true 会跳过自动选中以避免页面切换)
|
|
651
696
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
652
697
|
*/
|
|
653
|
-
async moveToContainer(config, targetId, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false } = {}) {
|
|
698
|
+
async moveToContainer(config, targetId, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
654
699
|
const isBatch = Array.isArray(config);
|
|
655
700
|
const configs = (isBatch ? config : [config]).filter((item) => !(isPage(item) || isPageFragment(item)));
|
|
656
701
|
if (configs.length === 0) throw new Error("没有可移动的节点");
|
|
@@ -698,11 +743,16 @@ var Editor = class extends BaseService {
|
|
|
698
743
|
name: "",
|
|
699
744
|
id: target.id
|
|
700
745
|
};
|
|
701
|
-
this.pushOpHistory("update", {
|
|
746
|
+
this.pushOpHistory("update", {
|
|
747
|
+
diff: buildUpdateDiff(updatedItems),
|
|
748
|
+
pageData: historyPage,
|
|
749
|
+
historyDescription,
|
|
750
|
+
source: historySource
|
|
751
|
+
});
|
|
702
752
|
} else this.selectionBeforeOp = null;
|
|
703
753
|
return isBatch ? newConfigs : newConfigs[0];
|
|
704
754
|
}
|
|
705
|
-
async dragTo(config, targetParent, targetIndex, { doNotPushHistory = false } = {}) {
|
|
755
|
+
async dragTo(config, targetParent, targetIndex, { doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
706
756
|
this.captureSelectionBeforeOp();
|
|
707
757
|
if (!targetParent || !Array.isArray(targetParent.items)) return;
|
|
708
758
|
const configs = Array.isArray(config) ? config : [config];
|
|
@@ -744,9 +794,14 @@ var Editor = class extends BaseService {
|
|
|
744
794
|
}
|
|
745
795
|
if (!doNotPushHistory) {
|
|
746
796
|
const pageForOp = this.getNodeInfo(configs[0].id, false).page;
|
|
747
|
-
this.pushOpHistory("update", {
|
|
748
|
-
|
|
749
|
-
|
|
797
|
+
this.pushOpHistory("update", {
|
|
798
|
+
diff: buildUpdateDiff(updatedItems),
|
|
799
|
+
pageData: {
|
|
800
|
+
name: pageForOp?.name || "",
|
|
801
|
+
id: pageForOp.id
|
|
802
|
+
},
|
|
803
|
+
historyDescription,
|
|
804
|
+
source: historySource
|
|
750
805
|
});
|
|
751
806
|
} else this.selectionBeforeOp = null;
|
|
752
807
|
this.emit("drag-to", {
|
|
@@ -756,6 +811,49 @@ var Editor = class extends BaseService {
|
|
|
756
811
|
});
|
|
757
812
|
}
|
|
758
813
|
/**
|
|
814
|
+
* 下列 *AndGetHistoryId 方法与对应的普通操作(add / remove / update ...)行为完全一致,
|
|
815
|
+
* 唯一区别是返回值为本次写入历史栈的历史记录 uuid({@link StepValue.uuid}),
|
|
816
|
+
* 而非节点 / 节点数组。可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
|
|
817
|
+
*
|
|
818
|
+
* 当本次操作未写入历史(doNotPushHistory 为 true、或操作无实际变更 / 提前返回)时返回 null。
|
|
819
|
+
*/
|
|
820
|
+
/** 等价于 {@link add},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
821
|
+
async addAndGetHistoryId(addNode, parent, options = {}) {
|
|
822
|
+
this.lastPushedHistoryId = null;
|
|
823
|
+
await this.add(addNode, parent, options);
|
|
824
|
+
return this.lastPushedHistoryId;
|
|
825
|
+
}
|
|
826
|
+
/** 等价于 {@link remove},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
827
|
+
async removeAndGetHistoryId(nodeOrNodeList, options = {}) {
|
|
828
|
+
this.lastPushedHistoryId = null;
|
|
829
|
+
await this.remove(nodeOrNodeList, options);
|
|
830
|
+
return this.lastPushedHistoryId;
|
|
831
|
+
}
|
|
832
|
+
/** 等价于 {@link update},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
833
|
+
async updateAndGetHistoryId(config, data = {}) {
|
|
834
|
+
this.lastPushedHistoryId = null;
|
|
835
|
+
await this.update(config, data);
|
|
836
|
+
return this.lastPushedHistoryId;
|
|
837
|
+
}
|
|
838
|
+
/** 等价于 {@link moveLayer},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
839
|
+
async moveLayerAndGetHistoryId(offset, options = {}) {
|
|
840
|
+
this.lastPushedHistoryId = null;
|
|
841
|
+
await this.moveLayer(offset, options);
|
|
842
|
+
return this.lastPushedHistoryId;
|
|
843
|
+
}
|
|
844
|
+
/** 等价于 {@link moveToContainer},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
845
|
+
async moveToContainerAndGetHistoryId(config, targetId, options = {}) {
|
|
846
|
+
this.lastPushedHistoryId = null;
|
|
847
|
+
await this.moveToContainer(config, targetId, options);
|
|
848
|
+
return this.lastPushedHistoryId;
|
|
849
|
+
}
|
|
850
|
+
/** 等价于 {@link dragTo},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
851
|
+
async dragToAndGetHistoryId(config, targetParent, targetIndex, options = {}) {
|
|
852
|
+
this.lastPushedHistoryId = null;
|
|
853
|
+
await this.dragTo(config, targetParent, targetIndex, options);
|
|
854
|
+
return this.lastPushedHistoryId;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
759
857
|
* 撤销当前操作
|
|
760
858
|
* @returns 被撤销的操作
|
|
761
859
|
*/
|
|
@@ -793,7 +891,12 @@ var Editor = class extends BaseService {
|
|
|
793
891
|
const entry = history_default.getPageStepList()[index];
|
|
794
892
|
if (!entry?.applied) return null;
|
|
795
893
|
const { step } = entry;
|
|
894
|
+
if (step.opType === "initial") return null;
|
|
796
895
|
if (!this.get("root")) return null;
|
|
896
|
+
if (step.opType === "update") {
|
|
897
|
+
const items = step.diff ?? [];
|
|
898
|
+
if (!items.length || !items.every((item) => item.changeRecords?.length)) return null;
|
|
899
|
+
}
|
|
797
900
|
let revertedStep = null;
|
|
798
901
|
const captureRevert = (s) => {
|
|
799
902
|
revertedStep = s;
|
|
@@ -803,28 +906,31 @@ var Editor = class extends BaseService {
|
|
|
803
906
|
const opts = {
|
|
804
907
|
doNotSelect: true,
|
|
805
908
|
doNotSwitchPage: true,
|
|
806
|
-
historyDescription
|
|
909
|
+
historyDescription,
|
|
910
|
+
historySource: "rollback"
|
|
807
911
|
};
|
|
808
912
|
try {
|
|
809
913
|
switch (step.opType) {
|
|
810
|
-
case "add":
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
const existing = this.getNodeById(
|
|
914
|
+
case "add":
|
|
915
|
+
for (const { newSchema } of step.diff ?? []) {
|
|
916
|
+
if (!newSchema) continue;
|
|
917
|
+
const existing = this.getNodeById(newSchema.id, false);
|
|
814
918
|
if (existing) await this.remove(existing, opts);
|
|
815
919
|
}
|
|
816
920
|
break;
|
|
817
|
-
}
|
|
818
921
|
case "remove": {
|
|
819
|
-
const sorted = [...step.
|
|
820
|
-
for (const {
|
|
922
|
+
const sorted = [...step.diff ?? []].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
923
|
+
for (const { oldSchema, parentId } of sorted) {
|
|
924
|
+
if (!oldSchema || parentId === void 0) continue;
|
|
821
925
|
const parent = this.getNodeById(parentId, false);
|
|
822
|
-
if (parent) await this.add([cloneDeep$1(
|
|
926
|
+
if (parent) await this.add([cloneDeep$1(oldSchema)], parent, opts);
|
|
823
927
|
}
|
|
824
928
|
break;
|
|
825
929
|
}
|
|
826
930
|
case "update": {
|
|
827
|
-
const configs = (step.
|
|
931
|
+
const configs = (step.diff ?? []).filter((item) => item.oldSchema && item.newSchema).map(({ oldSchema, newSchema, changeRecords }) => {
|
|
932
|
+
const oldNode = oldSchema;
|
|
933
|
+
const newNode = newSchema;
|
|
828
934
|
if (changeRecords?.length) {
|
|
829
935
|
const patch = {
|
|
830
936
|
id: newNode.id,
|
|
@@ -839,7 +945,10 @@ var Editor = class extends BaseService {
|
|
|
839
945
|
}
|
|
840
946
|
return cloneDeep$1(oldNode);
|
|
841
947
|
});
|
|
842
|
-
if (configs.length) await this.update(configs, {
|
|
948
|
+
if (configs.length) await this.update(configs, {
|
|
949
|
+
historyDescription,
|
|
950
|
+
historySource: "rollback"
|
|
951
|
+
});
|
|
843
952
|
break;
|
|
844
953
|
}
|
|
845
954
|
}
|
|
@@ -851,6 +960,19 @@ var Editor = class extends BaseService {
|
|
|
851
960
|
return revertedStep;
|
|
852
961
|
}
|
|
853
962
|
/**
|
|
963
|
+
* 通过历史记录 uuid 回滚当前页面的某条历史步骤,语义与 {@link revertPageStep} 完全一致,
|
|
964
|
+
* 仅入参从 index 改为 uuid({@link StepValue.uuid})。uuid 不随栈内步骤增删而变化,
|
|
965
|
+
* 更适合业务侧持有引用后再回滚(埋点、跨端同步等场景)。
|
|
966
|
+
*
|
|
967
|
+
* @param uuid 目标历史记录的 uuid,通常由 *AndGetHistoryId 方法返回
|
|
968
|
+
* @returns 反向后产生的新 step;找不到对应 uuid / 未应用 / 反向失败时返回 null
|
|
969
|
+
*/
|
|
970
|
+
async revertPageStepById(uuid) {
|
|
971
|
+
const index = history_default.getPageStepIndexByUuid(uuid);
|
|
972
|
+
if (index < 0) return null;
|
|
973
|
+
return this.revertPageStep(index);
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
854
976
|
* 跳转当前页面历史栈到指定游标位置。
|
|
855
977
|
*
|
|
856
978
|
* `targetCursor` 与 `UndoRedo.getCursor()` 同义:表示"已应用步骤数量",
|
|
@@ -873,7 +995,7 @@ var Editor = class extends BaseService {
|
|
|
873
995
|
}
|
|
874
996
|
return cursor;
|
|
875
997
|
}
|
|
876
|
-
async move(left, top, { doNotPushHistory = false } = {}) {
|
|
998
|
+
async move(left, top, { doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
877
999
|
const node = toRaw(this.get("node"));
|
|
878
1000
|
if (!node || isPage(node)) return;
|
|
879
1001
|
const newStyle = calcMoveStyle(node.style || {}, left, top);
|
|
@@ -882,7 +1004,11 @@ var Editor = class extends BaseService {
|
|
|
882
1004
|
id: node.id,
|
|
883
1005
|
type: node.type,
|
|
884
1006
|
style: newStyle
|
|
885
|
-
}, {
|
|
1007
|
+
}, {
|
|
1008
|
+
doNotPushHistory,
|
|
1009
|
+
historyDescription,
|
|
1010
|
+
historySource
|
|
1011
|
+
});
|
|
886
1012
|
}
|
|
887
1013
|
resetState() {
|
|
888
1014
|
this.set("root", null);
|
|
@@ -922,18 +1048,83 @@ var Editor = class extends BaseService {
|
|
|
922
1048
|
if (this.selectionBeforeOp) return;
|
|
923
1049
|
this.selectionBeforeOp = this.get("nodes").map((n) => n.id);
|
|
924
1050
|
}
|
|
925
|
-
|
|
1051
|
+
/**
|
|
1052
|
+
* 比较「上一次 root」与「新 root」的页面 / 页面片,按页面粒度把整体替换拆成历史记录:
|
|
1053
|
+
* - 新旧都存在且内容变化的页面 → 一条 `update`(整页快照替换,无 changeRecords);
|
|
1054
|
+
* - 仅新 root 存在的页面 → 一条 `add`;
|
|
1055
|
+
* - 仅旧 root 存在的页面 → 一条 `remove`。
|
|
1056
|
+
*
|
|
1057
|
+
* 每条记录落到对应页面自己的历史栈(与普通节点操作一致),并标记来源 `source`。
|
|
1058
|
+
* 内容未变化的页面不产生记录,避免重复设置相同 DSL 时产生噪声。
|
|
1059
|
+
*/
|
|
1060
|
+
pushRootDiffHistory(preRoot, nextRoot, source) {
|
|
1061
|
+
const prevPages = preRoot?.items || [];
|
|
1062
|
+
const nextPages = nextRoot?.items || [];
|
|
1063
|
+
const prevMap = new Map(prevPages.map((p) => [`${p.id}`, p]));
|
|
1064
|
+
const nextMap = new Map(nextPages.map((p) => [`${p.id}`, p]));
|
|
1065
|
+
const indexInItems = (root, id) => (root.items ?? []).findIndex((item) => `${item.id}` === `${id}`);
|
|
1066
|
+
nextPages.forEach((nextPage) => {
|
|
1067
|
+
const prevPage = prevMap.get(`${nextPage.id}`);
|
|
1068
|
+
if (!prevPage) this.pushPageDiffStep("add", nextPage, {
|
|
1069
|
+
newSchema: cloneDeep$1(toRaw(nextPage)),
|
|
1070
|
+
parentId: nextRoot.id,
|
|
1071
|
+
index: indexInItems(nextRoot, nextPage.id)
|
|
1072
|
+
}, source);
|
|
1073
|
+
else if (!isEqual(toRaw(prevPage), toRaw(nextPage))) this.pushPageDiffStep("update", nextPage, {
|
|
1074
|
+
oldSchema: cloneDeep$1(toRaw(prevPage)),
|
|
1075
|
+
newSchema: cloneDeep$1(toRaw(nextPage))
|
|
1076
|
+
}, source);
|
|
1077
|
+
});
|
|
1078
|
+
prevPages.forEach((prevPage) => {
|
|
1079
|
+
if (!nextMap.has(`${prevPage.id}`)) this.pushPageDiffStep("remove", prevPage, {
|
|
1080
|
+
oldSchema: cloneDeep$1(toRaw(prevPage)),
|
|
1081
|
+
parentId: preRoot.id,
|
|
1082
|
+
index: indexInItems(preRoot, prevPage.id)
|
|
1083
|
+
}, source);
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* 构造一条页面级「set root」历史记录(不携带选区 / modifiedNodeIds 上下文)并落到该页面自己的栈。
|
|
1088
|
+
*
|
|
1089
|
+
* 连续 set root 替换:若该页栈最新一条已是**同来源**的 set root 记录({@link StepValue.rootStep} 且 `source` 相同),
|
|
1090
|
+
* 则用本次记录**替换**它而非新增,避免源码反复保存 / 外部重设 DSL 时堆积多条 root 记录;
|
|
1091
|
+
* 来源不同则照常新增(initial 基线不是 rootStep,不在此列)。
|
|
1092
|
+
*/
|
|
1093
|
+
pushPageDiffStep(opType, page, diffItem, source) {
|
|
1094
|
+
const step = {
|
|
1095
|
+
uuid: guid(),
|
|
1096
|
+
data: {
|
|
1097
|
+
name: page.name || "",
|
|
1098
|
+
id: page.id
|
|
1099
|
+
},
|
|
1100
|
+
opType,
|
|
1101
|
+
selectedBefore: [],
|
|
1102
|
+
selectedAfter: [],
|
|
1103
|
+
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
1104
|
+
diff: [diffItem],
|
|
1105
|
+
rootStep: true
|
|
1106
|
+
};
|
|
1107
|
+
if (source) step.source = source;
|
|
1108
|
+
const top = history_default.getCurrentPageStep(page.id);
|
|
1109
|
+
if (top?.rootStep && top.source === source) history_default.replaceCurrentPageStep(step, page.id);
|
|
1110
|
+
else history_default.push(step, page.id);
|
|
1111
|
+
}
|
|
1112
|
+
pushOpHistory(opType, { diff, pageData, historyDescription, source }) {
|
|
926
1113
|
const step = {
|
|
1114
|
+
uuid: guid(),
|
|
927
1115
|
data: pageData,
|
|
928
1116
|
opType,
|
|
929
1117
|
selectedBefore: this.selectionBeforeOp ?? [],
|
|
930
1118
|
selectedAfter: this.get("nodes").map((n) => n.id),
|
|
931
1119
|
modifiedNodeIds: new Map(this.get("modifiedNodeIds")),
|
|
932
|
-
|
|
1120
|
+
diff
|
|
933
1121
|
};
|
|
934
1122
|
if (historyDescription) step.historyDescription = historyDescription;
|
|
935
|
-
|
|
1123
|
+
if (source) step.source = source;
|
|
1124
|
+
const historyId = history_default.push(step, pageData.id) ? step.uuid : null;
|
|
1125
|
+
this.lastPushedHistoryId = historyId;
|
|
936
1126
|
this.selectionBeforeOp = null;
|
|
1127
|
+
return historyId;
|
|
937
1128
|
}
|
|
938
1129
|
/**
|
|
939
1130
|
* 应用历史操作(撤销 / 重做)
|
|
@@ -948,6 +1139,7 @@ var Editor = class extends BaseService {
|
|
|
948
1139
|
* @param reverse true = 撤销,false = 重做
|
|
949
1140
|
*/
|
|
950
1141
|
async applyHistoryOp(step, reverse) {
|
|
1142
|
+
if (step.opType === "initial") return;
|
|
951
1143
|
const root = this.get("root");
|
|
952
1144
|
const stage = this.get("stage");
|
|
953
1145
|
if (!root) return;
|
|
@@ -958,56 +1150,59 @@ var Editor = class extends BaseService {
|
|
|
958
1150
|
};
|
|
959
1151
|
switch (step.opType) {
|
|
960
1152
|
case "add": {
|
|
961
|
-
const
|
|
962
|
-
if (reverse) for (const
|
|
963
|
-
|
|
1153
|
+
const items = step.diff ?? [];
|
|
1154
|
+
if (reverse) for (const { newSchema } of items) {
|
|
1155
|
+
if (!newSchema) continue;
|
|
1156
|
+
const existing = this.getNodeById(newSchema.id, false);
|
|
964
1157
|
if (existing) await this.remove(existing, commonOpts);
|
|
965
1158
|
}
|
|
966
1159
|
else {
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
if (parent.items)
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
});
|
|
981
|
-
}
|
|
1160
|
+
const sorted = [...items].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
1161
|
+
for (const { newSchema, parentId, index } of sorted) {
|
|
1162
|
+
if (!newSchema || parentId === void 0) continue;
|
|
1163
|
+
const parent = this.getNodeById(parentId, false);
|
|
1164
|
+
if (parent?.items) {
|
|
1165
|
+
if (typeof index === "number" && index >= 0 && index < parent.items.length) parent.items.splice(index, 0, cloneDeep$1(newSchema));
|
|
1166
|
+
else parent.items.push(cloneDeep$1(newSchema));
|
|
1167
|
+
await stage?.add({
|
|
1168
|
+
config: cloneDeep$1(newSchema),
|
|
1169
|
+
parent: cloneDeep$1(parent),
|
|
1170
|
+
parentId: parent.id,
|
|
1171
|
+
root: cloneDeep$1(root)
|
|
1172
|
+
});
|
|
982
1173
|
}
|
|
983
1174
|
}
|
|
984
1175
|
}
|
|
985
1176
|
break;
|
|
986
1177
|
}
|
|
987
1178
|
case "remove": {
|
|
988
|
-
const items = step.
|
|
1179
|
+
const items = step.diff ?? [];
|
|
989
1180
|
if (reverse) {
|
|
990
|
-
const sorted = [...items].sort((a, b) => a.index - b.index);
|
|
991
|
-
for (const {
|
|
1181
|
+
const sorted = [...items].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
1182
|
+
for (const { oldSchema, parentId, index } of sorted) {
|
|
1183
|
+
if (!oldSchema || parentId === void 0) continue;
|
|
992
1184
|
const parent = this.getNodeById(parentId, false);
|
|
993
1185
|
if (parent?.items) {
|
|
994
|
-
parent.items.splice(index, 0, cloneDeep$1(
|
|
1186
|
+
parent.items.splice(index ?? parent.items.length, 0, cloneDeep$1(oldSchema));
|
|
995
1187
|
await stage?.add({
|
|
996
|
-
config: cloneDeep$1(
|
|
1188
|
+
config: cloneDeep$1(oldSchema),
|
|
997
1189
|
parent: cloneDeep$1(parent),
|
|
998
1190
|
parentId,
|
|
999
1191
|
root: cloneDeep$1(root)
|
|
1000
1192
|
});
|
|
1001
1193
|
}
|
|
1002
1194
|
}
|
|
1003
|
-
} else for (const {
|
|
1004
|
-
|
|
1195
|
+
} else for (const { oldSchema } of items) {
|
|
1196
|
+
if (!oldSchema) continue;
|
|
1197
|
+
const existing = this.getNodeById(oldSchema.id, false);
|
|
1005
1198
|
if (existing) await this.remove(existing, commonOpts);
|
|
1006
1199
|
}
|
|
1007
1200
|
break;
|
|
1008
1201
|
}
|
|
1009
1202
|
case "update": {
|
|
1010
|
-
const configs = (step.
|
|
1203
|
+
const configs = (step.diff ?? []).filter((item) => item.oldSchema && item.newSchema).map(({ oldSchema, newSchema, changeRecords }) => {
|
|
1204
|
+
const oldNode = oldSchema;
|
|
1205
|
+
const newNode = newSchema;
|
|
1011
1206
|
if (changeRecords?.length) {
|
|
1012
1207
|
const sourceForValues = reverse ? oldNode : newNode;
|
|
1013
1208
|
const patch = {
|