@tmagic/editor 1.8.0-manmanyu.8 → 1.8.0
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/Editor.vue_vue_type_script_setup_true_lang.js +22 -13
- package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +10 -5
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +7 -6
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +21 -119
- package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +21 -5
- package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +62 -16
- package/dist/es/components/Icon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/Resizer.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/components/ScrollBar.js +0 -1
- package/dist/es/components/ScrollBar.vue_vue_type_script_setup_true_lang.js +5 -4
- package/dist/es/components/ScrollViewer.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/SearchInput.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/SplitView.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/ToolButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/Tree.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/TreeNode.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/ViewForm.js +5 -0
- package/dist/es/components/ViewForm.vue_vue_type_script_setup_true_lang.js +56 -0
- package/dist/es/editorProps.js +7 -1
- package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +30 -113
- package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +7 -19
- package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +7 -6
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +12 -4
- package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +9 -20
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +2 -2
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +5 -3
- package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +9 -4
- package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +10 -110
- package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +52 -363
- package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/PageFragmentSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +3 -6
- package/dist/es/fields/StyleSetter/components/BackgroundPosition.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +4 -35
- package/dist/es/fields/StyleSetter/components/Box.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/fields/StyleSetter/configs.js +663 -0
- package/dist/es/fields/StyleSetter/icons/align-items/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/FlexEnd.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/FlexStart.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceAround.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceBetween.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/NoRepeat.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/Repeat.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatX.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatY.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Block.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Flex.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Inline.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/InlineBlock.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/None.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/Column.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/ColumnReverse.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/Row.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/RowReverse.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexEnd.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexStart.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceAround.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceBetween.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Left.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Right.js +1 -1
- package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +29 -106
- package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +8 -11
- package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +30 -89
- package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +29 -297
- package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +29 -82
- package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +8 -24
- package/dist/es/fields/UISelect.js +0 -1
- package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/configs/codeSelect.js +98 -0
- package/dist/es/fields/configs/displayConds.js +158 -0
- package/dist/es/fields/configs/eventSelect.js +225 -0
- package/dist/es/fields/configs/stickyAddButton.js +21 -0
- package/dist/es/fields/headless-validation.js +139 -0
- package/dist/es/headless.js +2 -0
- package/dist/es/hooks/use-code-block-edit.js +4 -2
- package/dist/es/hooks/use-compare-form.js +101 -0
- package/dist/es/hooks/use-form-context.js +29 -0
- package/dist/es/hooks/use-stage.js +1 -0
- package/dist/es/icons/CenterIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/icons/CodeIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/icons/DatasourceIcon.js +1 -1
- package/dist/es/icons/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/index.js +17 -9
- package/dist/es/initService.js +52 -16
- package/dist/es/layouts/AddPageBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +26 -10
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +11 -8
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/NavMenuColumn.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 +1 -1
- package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +8 -5
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +26 -10
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +36 -28
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/composables.js +1 -1
- package/dist/es/layouts/history-list/useHistoryList.js +4 -4
- package/dist/es/layouts/history-list/useHistoryRevert.js +38 -33
- package/dist/es/layouts/page-bar/AddButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageBarScrollContainer.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/Search.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +50 -20
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +53 -35
- package/dist/es/layouts/props-panel/use-style-panel.js +3 -2
- package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +21 -36
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/es/layouts/sidebar/code-block/useContentMenu.js +19 -4
- package/dist/es/layouts/sidebar/data-source/DataSourceAddButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +9 -4
- package/dist/es/layouts/sidebar/data-source/DataSourceList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/es/layouts/sidebar/data-source/useContentMenu.js +19 -4
- package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/sidebar/layer/LayerNodeContent.js +5 -0
- package/dist/es/layouts/sidebar/layer/LayerNodeContent.vue_vue_type_script_setup_true_lang.js +46 -0
- package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +6 -4
- package/dist/es/layouts/sidebar/layer/use-click.js +3 -3
- package/dist/es/layouts/sidebar/layer/use-drag.js +11 -10
- package/dist/es/layouts/sidebar/layer/use-node-status.js +2 -2
- package/dist/es/layouts/workspace/Breadcrumb.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/Workspace.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/viewer/NodeListMenu.vue_vue_type_script_setup_true_lang.js +9 -3
- package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +55 -9
- package/dist/es/layouts/workspace/viewer/StageOverlay.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/plugin.js +35 -23
- package/dist/es/services/codeBlock.js +40 -31
- package/dist/es/services/dataSource.js +46 -34
- package/dist/es/services/dep.js +162 -41
- package/dist/es/services/editor.js +373 -137
- package/dist/es/services/events.js +4 -4
- package/dist/es/services/history.js +275 -392
- package/dist/es/services/keybinding.js +3 -3
- package/dist/es/services/props.js +2 -1
- package/dist/es/services/storage.js +2 -2
- package/dist/es/services/ui.js +7 -2
- package/dist/es/style.css +277 -114
- package/dist/es/utils/code-block.js +14 -7
- package/dist/es/utils/config.js +4 -1
- package/dist/es/utils/const.js +2 -2
- package/dist/es/utils/content-menu.js +2 -2
- package/dist/es/utils/data-source/index.js +34 -12
- package/dist/es/utils/dep/collect-worker-client.js +154 -0
- package/dist/es/utils/dep/idle-task.js +70 -22
- package/dist/es/utils/dep/worker.js +1 -1
- package/dist/es/utils/editor.js +4 -2
- package/dist/es/utils/event.js +135 -0
- package/dist/es/utils/history.js +35 -47
- package/dist/es/utils/monaco-editor.js +22 -6
- package/dist/es/utils/operator.js +2 -2
- package/dist/es/utils/props.js +50 -106
- package/dist/es/utils/type-match-rules.js +356 -0
- package/dist/style.css +277 -114
- package/dist/themes/magic-admin.css +978 -175
- package/dist/tmagic-editor-headless.umd.cjs +10880 -0
- package/dist/tmagic-editor.umd.cjs +13047 -11363
- package/package.json +18 -13
- package/src/Editor.vue +23 -6
- package/src/components/CodeBlockEditor.vue +3 -0
- package/src/components/CodeParams.vue +10 -4
- package/src/components/CompareForm.vue +20 -190
- package/src/components/ContentMenu.vue +34 -6
- package/src/components/FloatingBox.vue +71 -7
- package/src/components/ScrollBar.vue +0 -67
- package/src/components/ViewForm.vue +54 -0
- package/src/editorProps.ts +23 -10
- package/src/fields/Code.vue +1 -1
- package/src/fields/CodeSelect.vue +20 -113
- package/src/fields/CodeSelectCol.vue +1 -1
- package/src/fields/CondOpSelect.vue +5 -26
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +2 -2
- package/src/fields/DataSourceFieldSelect/Index.vue +4 -1
- package/src/fields/DataSourceFields.vue +5 -1
- package/src/fields/DataSourceInput.vue +10 -28
- package/src/fields/DataSourceMethodSelect.vue +1 -1
- package/src/fields/DataSourceMethods.vue +6 -2
- package/src/fields/DataSourceMocks.vue +3 -0
- package/src/fields/DataSourceSelect.vue +1 -1
- package/src/fields/DisplayConds.vue +17 -139
- package/src/fields/EventSelect.vue +29 -416
- package/src/fields/KeyValue.vue +1 -1
- package/src/fields/StyleSetter/Index.vue +2 -8
- package/src/fields/StyleSetter/components/Border.vue +4 -38
- package/src/fields/StyleSetter/components/Box.vue +1 -1
- package/src/fields/StyleSetter/components/Position.vue +1 -1
- package/src/fields/StyleSetter/configs.ts +690 -0
- package/src/fields/StyleSetter/pro/Background.vue +9 -64
- package/src/fields/StyleSetter/pro/Border.vue +5 -16
- package/src/fields/StyleSetter/pro/Font.vue +11 -71
- package/src/fields/StyleSetter/pro/Layout.vue +10 -230
- package/src/fields/StyleSetter/pro/Position.vue +11 -82
- package/src/fields/StyleSetter/pro/Transform.vue +6 -34
- package/src/fields/UISelect.vue +0 -12
- package/src/fields/configs/codeSelect.ts +127 -0
- package/src/fields/configs/displayConds.ts +184 -0
- package/src/fields/configs/eventSelect.ts +309 -0
- package/src/fields/configs/stickyAddButton.ts +32 -0
- package/src/fields/headless-validation.ts +177 -0
- package/src/headless.ts +33 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-compare-form.ts +166 -0
- package/src/hooks/use-form-context.ts +56 -0
- package/src/hooks/use-stage.ts +1 -0
- package/src/index.ts +9 -0
- package/src/initService.ts +73 -18
- package/src/layouts/CodeEditor.vue +32 -6
- package/src/layouts/Framework.vue +7 -6
- package/src/layouts/history-list/BucketTab.vue +2 -2
- package/src/layouts/history-list/HistoryDiffDialog.vue +33 -15
- package/src/layouts/history-list/HistoryListPanel.vue +16 -18
- package/src/layouts/history-list/useHistoryRevert.ts +57 -41
- package/src/layouts/props-panel/FormPanel.vue +75 -20
- package/src/layouts/props-panel/PropsPanel.vue +81 -30
- package/src/layouts/props-panel/use-style-panel.ts +4 -3
- package/src/layouts/sidebar/ComponentListPanel.vue +6 -2
- package/src/layouts/sidebar/Sidebar.vue +5 -3
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +5 -2
- package/src/layouts/sidebar/code-block/useContentMenu.ts +14 -2
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +3 -0
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +3 -3
- package/src/layouts/sidebar/data-source/useContentMenu.ts +14 -2
- package/src/layouts/sidebar/layer/LayerMenu.vue +2 -2
- package/src/layouts/sidebar/layer/LayerNodeContent.vue +57 -0
- package/src/layouts/sidebar/layer/LayerPanel.vue +5 -2
- package/src/layouts/sidebar/layer/use-click.ts +3 -3
- package/src/layouts/sidebar/layer/use-node-status.ts +2 -2
- package/src/layouts/workspace/viewer/NodeListMenu.vue +4 -1
- package/src/layouts/workspace/viewer/Stage.vue +80 -10
- package/src/layouts/workspace/viewer/ViewerMenu.vue +7 -7
- package/src/plugin.ts +35 -25
- package/src/services/codeBlock.ts +4 -0
- package/src/services/dataSource.ts +3 -0
- package/src/services/dep.ts +292 -47
- package/src/services/editor.ts +383 -120
- package/src/services/events.ts +8 -7
- package/src/services/history.ts +22 -1
- package/src/services/keybinding.ts +3 -3
- package/src/services/ui.ts +26 -5
- package/src/theme/code-block.scss +0 -37
- package/src/theme/display-conds.scss +4 -0
- package/src/theme/event.scss +25 -33
- package/src/theme/floating-box.scss +9 -1
- package/src/theme/framework.scss +4 -1
- package/src/theme/layer-node-content.scss +14 -0
- package/src/theme/nav-menu.scss +5 -1
- package/src/theme/props-panel.scss +17 -3
- package/src/theme/scroll-bar.scss +64 -0
- package/src/theme/theme.scss +3 -0
- package/src/theme/themes/magic-admin/index.scss +109 -9
- package/src/theme/ui-select.scss +9 -0
- package/src/type.ts +216 -6
- package/src/utils/code-block.ts +1 -0
- package/src/utils/config.ts +9 -1
- package/src/utils/const.ts +3 -3
- package/src/utils/content-menu.ts +2 -2
- package/src/utils/data-source/index.ts +31 -12
- package/src/utils/dep/collect-worker-client.ts +215 -0
- package/src/utils/dep/idle-task.ts +104 -35
- package/src/utils/dep/worker.ts +113 -9
- package/src/utils/event.ts +237 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/monaco-editor.ts +27 -0
- package/src/utils/operator.ts +2 -2
- package/src/utils/props.ts +61 -122
- package/src/utils/type-match-rules.ts +697 -0
- package/types/headless.d.ts +17 -0
- package/types/index.d.ts +1494 -978
- package/src/fields/StyleSetter/icons/align-items/index copy.ts +0 -5
|
@@ -7,11 +7,13 @@ import storage_default, { Protocol } from "./storage.js";
|
|
|
7
7
|
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";
|
|
8
8
|
import { beforePaste, getAddParent } from "../utils/operator.js";
|
|
9
9
|
import { isFixed } from "@tmagic/stage";
|
|
10
|
-
import { getNodeInfo, getNodePath, getValueByKeyPath, guid, isPage, isPageFragment, setValueByKeyPath } from "@tmagic/utils";
|
|
10
|
+
import { getNodeInfo, getNodePath, getValueByKeyPath, guid, isPage, isPageFragment, isPageOrFragment, setValueByKeyPath, traverseNode } from "@tmagic/utils";
|
|
11
11
|
import { NodeType } from "@tmagic/core";
|
|
12
|
-
import { reactive, toRaw } from "vue";
|
|
12
|
+
import { nextTick, reactive, toRaw } from "vue";
|
|
13
13
|
import { cloneDeep as cloneDeep$1, isEmpty, isEqual, isObject, mergeWith, uniq } from "lodash-es";
|
|
14
14
|
//#region packages/editor/src/services/editor.ts
|
|
15
|
+
/** 历史插回时把记录的下标收敛到 [0, length],越界(含未记录)一律追加到末尾 */
|
|
16
|
+
var clampIndex = (index, length) => typeof index === "number" && index >= 0 && index <= length ? index : length;
|
|
15
17
|
/**
|
|
16
18
|
* 把「变更前后节点快照」列表归一成 update 类型的 {@link StepDiffItem} 列表,供 {@link StepValue.diff} 使用。
|
|
17
19
|
* `changeRecords` 来自 form 端的 propPath/value 列表,撤销/重做时只对这些 propPath 做局部更新;
|
|
@@ -33,6 +35,7 @@ var Editor = class extends BaseService {
|
|
|
33
35
|
stageLoading: true,
|
|
34
36
|
highlightNode: null,
|
|
35
37
|
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
38
|
+
invalidNodeIds: /* @__PURE__ */ new Map(),
|
|
36
39
|
pageLength: 0,
|
|
37
40
|
pageFragmentLength: 0,
|
|
38
41
|
disabledMultiSelect: false,
|
|
@@ -40,11 +43,21 @@ var Editor = class extends BaseService {
|
|
|
40
43
|
});
|
|
41
44
|
selectionBeforeOp = null;
|
|
42
45
|
/**
|
|
46
|
+
* 操作前的节点校验错误快照,与 selectionBeforeOp 同时在 captureSelectionBeforeOp 中捕获,
|
|
47
|
+
* 供 pushOpHistory 写入 step.extra.invalidNodeIdsBefore,用于撤销时还原到「操作前」的错误状态。
|
|
48
|
+
*/
|
|
49
|
+
invalidNodeIdsBeforeOp = null;
|
|
50
|
+
/**
|
|
43
51
|
* 最近一次 pushOpHistory 写入的历史记录 uuid。
|
|
44
52
|
* 供 *AndGetHistoryId 系列方法在调用普通操作后取回本次产生的历史记录 id;
|
|
45
53
|
* 普通操作不会读取它,调用前由 *AndGetHistoryId 重置为 null。
|
|
46
54
|
*/
|
|
47
55
|
lastPushedHistoryId = null;
|
|
56
|
+
/**
|
|
57
|
+
* 上一次 doAdd 的插入记忆:nodeId 为插入的节点,selectedId 为当时的选中节点。
|
|
58
|
+
* 仅在选中节点未变化时复用(连续 add / doNotSelect / 批量粘贴),选中变化后自动失效,无需手动清理。
|
|
59
|
+
*/
|
|
60
|
+
lastAdded = null;
|
|
48
61
|
constructor() {
|
|
49
62
|
super(canUsePluginMethods.async.map((methodName) => ({
|
|
50
63
|
name: methodName,
|
|
@@ -57,7 +70,7 @@ var Editor = class extends BaseService {
|
|
|
57
70
|
}
|
|
58
71
|
/**
|
|
59
72
|
* 设置当前指点节点配置
|
|
60
|
-
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength
|
|
73
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'invalidNodeIds' | 'pageLength' | 'pageFragmentLength
|
|
61
74
|
* @param value MNode
|
|
62
75
|
* @param options.historySource 设置 root 时,本次变更写入历史记录的「操作来源」(仅 name === 'root' 时生效)
|
|
63
76
|
*/
|
|
@@ -74,7 +87,7 @@ var Editor = class extends BaseService {
|
|
|
74
87
|
this.state.stageLoading = this.state.pageLength !== 0;
|
|
75
88
|
if (preValue && !isEmpty(preValue)) this.pushRootDiffHistory(preValue, app, options.historySource);
|
|
76
89
|
else app.items?.forEach((pageNode) => {
|
|
77
|
-
if (pageNode?.id !== void 0 && !history_default.
|
|
90
|
+
if (pageNode?.id !== void 0 && !history_default.getMarker("page", pageNode.id)) history_default.setMarker("page", pageNode.id, {
|
|
78
91
|
name: pageNode.name,
|
|
79
92
|
source: options.historySource
|
|
80
93
|
});
|
|
@@ -85,11 +98,12 @@ var Editor = class extends BaseService {
|
|
|
85
98
|
this.state.stageLoading = false;
|
|
86
99
|
}
|
|
87
100
|
this.emit("root-change", value, preValue, options);
|
|
101
|
+
this.pruneInvalidNodeIds();
|
|
88
102
|
}
|
|
89
103
|
}
|
|
90
104
|
/**
|
|
91
105
|
* 获取当前指点节点配置
|
|
92
|
-
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength'
|
|
106
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'invalidNodeIds' | 'pageLength' | 'pageFragmentLength'
|
|
93
107
|
* @returns MNode
|
|
94
108
|
*/
|
|
95
109
|
get(name) {
|
|
@@ -152,7 +166,7 @@ var Editor = class extends BaseService {
|
|
|
152
166
|
isOnDifferentPage(node) {
|
|
153
167
|
const currentPageId = this.get("page")?.id;
|
|
154
168
|
if (currentPageId === void 0 || currentPageId === null) return false;
|
|
155
|
-
if (
|
|
169
|
+
if (isPageOrFragment(node)) return `${node.id}` !== `${currentPageId}`;
|
|
156
170
|
const nodePage = this.getNodeInfo(node.id, false).page;
|
|
157
171
|
if (!nodePage) return false;
|
|
158
172
|
return `${nodePage.id}` !== `${currentPageId}`;
|
|
@@ -176,8 +190,6 @@ var Editor = class extends BaseService {
|
|
|
176
190
|
this.set("nodes", node ? [node] : []);
|
|
177
191
|
this.set("page", page);
|
|
178
192
|
this.set("parent", parent);
|
|
179
|
-
if (page) history_default.changePage(toRaw(page));
|
|
180
|
-
else history_default.resetState();
|
|
181
193
|
if (node?.id) this.get("stage")?.renderer?.runtime?.getApp?.()?.page?.emit("editor:select", {
|
|
182
194
|
node,
|
|
183
195
|
page,
|
|
@@ -241,24 +253,29 @@ var Editor = class extends BaseService {
|
|
|
241
253
|
this.set("stage", null);
|
|
242
254
|
this.set("highlightNode", null);
|
|
243
255
|
}
|
|
244
|
-
async doAdd(node, parent) {
|
|
256
|
+
async doAdd(node, parent, _options = {}) {
|
|
245
257
|
const root = this.get("root");
|
|
246
258
|
if (!root) throw new Error("root为空");
|
|
247
259
|
const curNode = this.get("node");
|
|
248
260
|
const stage = this.get("stage");
|
|
249
261
|
if (!curNode) throw new Error("当前选中节点为空");
|
|
250
|
-
if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && !(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
262
|
+
if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && !isPageOrFragment(node)) throw new Error("app下不能添加组件");
|
|
263
|
+
const anchorId = this.lastAdded?.selectedId === curNode.id ? this.lastAdded.nodeId : curNode.id;
|
|
264
|
+
const anchorIndex = isPageOrFragment(node) ? -1 : Math.max(getNodeIndex(anchorId, parent), getNodeIndex(curNode.id, parent));
|
|
265
|
+
const insertIndex = anchorIndex < 0 ? parent.items.length : anchorIndex + 1;
|
|
266
|
+
parent.items.splice(insertIndex, 0, node);
|
|
267
|
+
this.lastAdded = {
|
|
268
|
+
selectedId: curNode.id,
|
|
269
|
+
nodeId: node.id
|
|
270
|
+
};
|
|
255
271
|
const layout = await this.getLayout(toRaw(parent), node);
|
|
256
272
|
node.style = getInitPositionStyle(node.style, layout);
|
|
257
273
|
await stage?.add({
|
|
258
274
|
config: cloneDeep$1(node),
|
|
259
275
|
parent: cloneDeep$1(parent),
|
|
260
276
|
parentId: parent.id,
|
|
261
|
-
root: cloneDeep$1(root)
|
|
277
|
+
root: cloneDeep$1(root),
|
|
278
|
+
index: insertIndex
|
|
262
279
|
});
|
|
263
280
|
const newStyle = fixNodePosition(node, parent, stage);
|
|
264
281
|
if (newStyle && (newStyle.top !== node.style.top || newStyle.left !== node.style.left)) {
|
|
@@ -276,14 +293,12 @@ var Editor = class extends BaseService {
|
|
|
276
293
|
* 向指点容器添加组件节点
|
|
277
294
|
* @param addConfig 将要添加的组件节点配置
|
|
278
295
|
* @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
|
|
279
|
-
* @param options
|
|
280
|
-
* @param options.doNotSelect 添加后是否不更新当前选中节点(默认 false,添加后会选中新增的节点)
|
|
281
|
-
* @param options.doNotSwitchPage 添加后是否不切换当前页面(默认 false;新增页面 / 跨页新增时为 true 会跳过会引发页面切换的选中操作)
|
|
282
|
-
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
296
|
+
* @param options 可选配置,见 {@link DslOpOptions}
|
|
283
297
|
* @returns 添加后的节点
|
|
284
298
|
*/
|
|
285
|
-
async add(addNode, parent,
|
|
299
|
+
async add(addNode, parent, options = {}) {
|
|
286
300
|
this.captureSelectionBeforeOp();
|
|
301
|
+
const { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = options;
|
|
287
302
|
const stage = this.get("stage");
|
|
288
303
|
const addNodes = [];
|
|
289
304
|
if (!Array.isArray(addNode)) {
|
|
@@ -291,13 +306,13 @@ var Editor = class extends BaseService {
|
|
|
291
306
|
if (!type) throw new Error("组件类型不能为空");
|
|
292
307
|
addNodes.push({ ...toRaw(await props_default.getPropsValue(type, config)) });
|
|
293
308
|
} else addNodes.push(...addNode);
|
|
294
|
-
const newNodes =
|
|
309
|
+
const newNodes = [];
|
|
310
|
+
for (const node of addNodes) {
|
|
295
311
|
const root = this.get("root");
|
|
296
|
-
|
|
297
|
-
const parentNode = parent ?? getAddParent(node);
|
|
312
|
+
const parentNode = isPageOrFragment(node) && root ? root : parent ?? getAddParent(node);
|
|
298
313
|
if (!parentNode) throw new Error("未找到父元素");
|
|
299
|
-
|
|
300
|
-
}
|
|
314
|
+
newNodes.push(await this.doAdd(node, parentNode, options));
|
|
315
|
+
}
|
|
301
316
|
if (newNodes.length > 1) {
|
|
302
317
|
const wouldSwitchPage = newNodes.some((n) => this.isOnDifferentPage(n));
|
|
303
318
|
if (!doNotSelect && !(doNotSwitchPage && wouldSwitchPage)) {
|
|
@@ -313,7 +328,7 @@ var Editor = class extends BaseService {
|
|
|
313
328
|
else if (isPageFragment(newNodes[0])) this.state.pageFragmentLength += 1;
|
|
314
329
|
else if (!skipSelect) stage?.select(newNodes[0].id);
|
|
315
330
|
}
|
|
316
|
-
if (!(
|
|
331
|
+
if (!isPageOrFragment(newNodes[0])) {
|
|
317
332
|
const pageForOp = this.getNodeInfo(newNodes[0].id, false).page;
|
|
318
333
|
if (!doNotPushHistory) {
|
|
319
334
|
const parentId = (this.getParentById(newNodes[0].id, false) ?? this.get("root")).id;
|
|
@@ -337,6 +352,20 @@ var Editor = class extends BaseService {
|
|
|
337
352
|
} else this.selectionBeforeOp = null;
|
|
338
353
|
}
|
|
339
354
|
this.emit("add", newNodes);
|
|
355
|
+
this.emit("change", {
|
|
356
|
+
type: "add",
|
|
357
|
+
data: newNodes.map((node) => ({
|
|
358
|
+
node,
|
|
359
|
+
page: this.getPageOfNode(node.id)
|
|
360
|
+
})),
|
|
361
|
+
historySource,
|
|
362
|
+
doNotPushHistory
|
|
363
|
+
});
|
|
364
|
+
const addedPages = newNodes.filter((node) => isPageOrFragment(node));
|
|
365
|
+
if (addedPages.length) history_default.notifyPageStructureChange({
|
|
366
|
+
add: addedPages,
|
|
367
|
+
remove: []
|
|
368
|
+
});
|
|
340
369
|
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
341
370
|
}
|
|
342
371
|
async doRemove(node, { doNotSelect = false, doNotSwitchPage = false } = {}) {
|
|
@@ -346,13 +375,10 @@ var Editor = class extends BaseService {
|
|
|
346
375
|
if (!parent || !curNode) throw new Error("找不要删除的节点");
|
|
347
376
|
const index = getNodeIndex(curNode.id, parent);
|
|
348
377
|
if (typeof index !== "number" || index === -1) throw new Error("找不要删除的节点");
|
|
349
|
-
parent.items?.splice(index, 1);
|
|
350
378
|
const stage = this.get("stage");
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
root: cloneDeep$1(root)
|
|
355
|
-
});
|
|
379
|
+
const currentPage = this.get("page");
|
|
380
|
+
const isDeletingCurrentPage = isPageOrFragment(node) && !!currentPage && `${currentPage.id}` === `${node.id}`;
|
|
381
|
+
parent.items?.splice(index, 1);
|
|
356
382
|
const selectedNodes = this.get("nodes");
|
|
357
383
|
const removedSelectedIndex = selectedNodes.findIndex((n) => `${n.id}` === `${node.id}`);
|
|
358
384
|
if (removedSelectedIndex !== -1) {
|
|
@@ -360,27 +386,29 @@ var Editor = class extends BaseService {
|
|
|
360
386
|
nextSelected.splice(removedSelectedIndex, 1);
|
|
361
387
|
this.set("nodes", nextSelected);
|
|
362
388
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const selectDefault = async (pages) => {
|
|
368
|
-
if (pages[0]) {
|
|
369
|
-
await this.select(pages[0]);
|
|
370
|
-
stage?.select(pages[0].id);
|
|
371
|
-
} else {
|
|
372
|
-
this.selectRoot();
|
|
373
|
-
history_default.resetPage();
|
|
374
|
-
}
|
|
389
|
+
const removeData = {
|
|
390
|
+
id: node.id,
|
|
391
|
+
parentId: parent.id,
|
|
392
|
+
root: cloneDeep$1(root)
|
|
375
393
|
};
|
|
376
394
|
const rootItems = root.items || [];
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
this.state.pageFragmentLength -= 1;
|
|
382
|
-
if (
|
|
395
|
+
const shouldReselect = isDeletingCurrentPage && !doNotSelect && !doNotSwitchPage;
|
|
396
|
+
const shouldSwitchPage = shouldReselect && rootItems.length > 0;
|
|
397
|
+
if (isPageOrFragment(node)) {
|
|
398
|
+
if (isPage(node)) this.state.pageLength -= 1;
|
|
399
|
+
else this.state.pageFragmentLength -= 1;
|
|
400
|
+
if (shouldSwitchPage) {
|
|
401
|
+
await this.select(rootItems[0]);
|
|
402
|
+
stage?.select(rootItems[0].id);
|
|
403
|
+
await nextTick();
|
|
404
|
+
stage?.remove(removeData);
|
|
405
|
+
} else {
|
|
406
|
+
stage?.remove(removeData);
|
|
407
|
+
if (shouldReselect) this.selectRoot();
|
|
408
|
+
else if (isDeletingCurrentPage) this.set("page", null);
|
|
409
|
+
}
|
|
383
410
|
} else {
|
|
411
|
+
stage?.remove(removeData);
|
|
384
412
|
if (!doNotSelect) {
|
|
385
413
|
await this.select(parent);
|
|
386
414
|
stage?.select(parent.id);
|
|
@@ -400,12 +428,17 @@ var Editor = class extends BaseService {
|
|
|
400
428
|
* @param options.doNotSwitchPage 删除后是否不切换当前页面(默认 false;删除页面 / 页面片段时为 true 会跳过自动切换到首个剩余页面)
|
|
401
429
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
402
430
|
*/
|
|
403
|
-
async remove(nodeOrNodeList,
|
|
431
|
+
async remove(nodeOrNodeList, options = {}) {
|
|
432
|
+
const { doNotPushHistory = false, historyDescription, historySource } = options;
|
|
404
433
|
this.captureSelectionBeforeOp();
|
|
405
434
|
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
435
|
+
const changeItems = nodes.map((node) => ({
|
|
436
|
+
node,
|
|
437
|
+
page: this.getPageOfNode(node.id)
|
|
438
|
+
}));
|
|
406
439
|
const removedItems = [];
|
|
407
440
|
let pageForOp = null;
|
|
408
|
-
if (!(
|
|
441
|
+
if (!isPageOrFragment(nodes[0])) for (const n of nodes) {
|
|
409
442
|
const { parent, node: curNode, page } = this.getNodeInfo(n.id, false);
|
|
410
443
|
if (parent && curNode) {
|
|
411
444
|
if (!pageForOp && page) pageForOp = {
|
|
@@ -420,27 +453,39 @@ var Editor = class extends BaseService {
|
|
|
420
453
|
});
|
|
421
454
|
}
|
|
422
455
|
}
|
|
423
|
-
await Promise.all(nodes.map((node) => this.doRemove(node,
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
456
|
+
await Promise.all(nodes.map((node) => this.doRemove(node, options)));
|
|
457
|
+
this.removeInvalidNodesBySubtree(nodes);
|
|
458
|
+
if (removedItems.length > 0 && pageForOp) {
|
|
459
|
+
if (!doNotPushHistory) this.pushOpHistory("remove", {
|
|
460
|
+
diff: removedItems,
|
|
461
|
+
pageData: pageForOp,
|
|
462
|
+
historyDescription,
|
|
463
|
+
source: historySource
|
|
464
|
+
});
|
|
465
|
+
else this.selectionBeforeOp = null;
|
|
466
|
+
}
|
|
434
467
|
this.emit("remove", nodes);
|
|
468
|
+
this.emit("change", {
|
|
469
|
+
type: "remove",
|
|
470
|
+
data: changeItems,
|
|
471
|
+
historySource,
|
|
472
|
+
doNotPushHistory
|
|
473
|
+
});
|
|
474
|
+
const removedPages = nodes.filter((node) => isPageOrFragment(node));
|
|
475
|
+
if (removedPages.length) history_default.notifyPageStructureChange({
|
|
476
|
+
add: [],
|
|
477
|
+
remove: removedPages
|
|
478
|
+
});
|
|
435
479
|
}
|
|
436
|
-
async doUpdate(config,
|
|
480
|
+
async doUpdate(config, data = {}) {
|
|
481
|
+
const { changeRecords = [], historySource, replace = false } = data;
|
|
437
482
|
if (!this.get("root")) throw new Error("root为空");
|
|
438
483
|
if (!config?.id) throw new Error("没有配置或者配置缺少id值");
|
|
439
484
|
const info = this.getNodeInfo(config.id, false);
|
|
440
485
|
if (!info.node) throw new Error(`获取不到id为${config.id}的节点`);
|
|
441
486
|
const node = toRaw(info.node);
|
|
442
|
-
let newConfig = await toggleFixedPosition(toRaw(config), node, info.path, this.getLayout);
|
|
443
|
-
newConfig = mergeWith(cloneDeep$1(node), newConfig, editorNodeMergeCustomizer);
|
|
487
|
+
let newConfig = replace ? cloneDeep$1(toRaw(config)) : await toggleFixedPosition(toRaw(config), node, info.path, this.getLayout);
|
|
488
|
+
if (!replace) newConfig = mergeWith(cloneDeep$1(node), newConfig, editorNodeMergeCustomizer);
|
|
444
489
|
if (!newConfig.type) throw new Error("配置缺少type值");
|
|
445
490
|
if (newConfig.type === NodeType.ROOT) {
|
|
446
491
|
this.set("root", newConfig, { historySource });
|
|
@@ -455,9 +500,11 @@ var Editor = class extends BaseService {
|
|
|
455
500
|
const parentNodeItems = parent.items;
|
|
456
501
|
const index = getNodeIndex(newConfig.id, parent);
|
|
457
502
|
if (!parentNodeItems || typeof index === "undefined" || index === -1) throw new Error("更新的节点未找到");
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
503
|
+
if (!replace) {
|
|
504
|
+
const newLayout = await this.getLayout(newConfig);
|
|
505
|
+
const layout = await this.getLayout(node);
|
|
506
|
+
if (Array.isArray(newConfig.items) && newLayout !== layout) newConfig = setChildrenLayout(newConfig, newLayout);
|
|
507
|
+
}
|
|
461
508
|
parentNodeItems[index] = newConfig;
|
|
462
509
|
const selectedNodes = this.get("nodes");
|
|
463
510
|
const targetIndex = selectedNodes.findIndex((nodeItem) => `${nodeItem.id}` === `${newConfig.id}`);
|
|
@@ -465,7 +512,7 @@ var Editor = class extends BaseService {
|
|
|
465
512
|
selectedNodes.splice(targetIndex, 1, newConfig);
|
|
466
513
|
this.set("nodes", [...selectedNodes]);
|
|
467
514
|
}
|
|
468
|
-
if (
|
|
515
|
+
if (isPageOrFragment(newConfig)) {
|
|
469
516
|
const currentPage = this.get("page");
|
|
470
517
|
if (currentPage && `${currentPage.id}` === `${newConfig.id}`) this.set("page", newConfig);
|
|
471
518
|
}
|
|
@@ -480,43 +527,51 @@ var Editor = class extends BaseService {
|
|
|
480
527
|
* 更新节点
|
|
481
528
|
* update后会触发依赖收集,收集完后会掉stage.update方法
|
|
482
529
|
* @param config 新的节点配置,配置中需要有id信息
|
|
483
|
-
* @param data
|
|
484
|
-
* @param data.changeRecords 单节点 form 端变更记录(多节点场景下被忽略,使用 changeRecordList)
|
|
485
|
-
* @param data.changeRecordList 多节点 form 端变更记录列表,按 config 数组同序对应每个节点;优先级高于 changeRecords
|
|
486
|
-
* @param data.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
487
|
-
* @param data.historyDescription 入栈时附带的人类可读描述,用于历史面板展示(不影响 undo/redo 行为)
|
|
530
|
+
* @param data 额外数据,见 {@link UpdateOptions}
|
|
488
531
|
* @returns 更新后的节点配置
|
|
489
532
|
*/
|
|
490
533
|
async update(config, data = {}) {
|
|
491
534
|
this.captureSelectionBeforeOp();
|
|
492
|
-
const { doNotPushHistory = false, changeRecordList, changeRecords, historyDescription, historySource } = data;
|
|
535
|
+
const { doNotPushHistory = false, changeRecordList, changeRecords, historyDescription, historySource, invalidInfo } = data;
|
|
493
536
|
const nodes = Array.isArray(config) ? config : [config];
|
|
494
537
|
const updateData = await Promise.all(nodes.map((node, index) => {
|
|
495
538
|
const recordsForNode = changeRecordList ? changeRecordList[index] ?? [] : changeRecords ?? [];
|
|
496
539
|
return this.doUpdate(node, {
|
|
497
|
-
|
|
498
|
-
|
|
540
|
+
...data,
|
|
541
|
+
changeRecords: recordsForNode
|
|
499
542
|
});
|
|
500
543
|
}));
|
|
544
|
+
this.applyInvalidInfo(config, invalidInfo);
|
|
501
545
|
if (updateData[0].oldNode?.type !== NodeType.ROOT) {
|
|
502
|
-
if (this.get("nodes").length)
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
546
|
+
if (this.get("nodes").length) {
|
|
547
|
+
if (!doNotPushHistory) {
|
|
548
|
+
const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
|
|
549
|
+
this.pushOpHistory("update", {
|
|
550
|
+
diff: buildUpdateDiff(updateData.map((d) => ({
|
|
551
|
+
oldNode: cloneDeep$1(d.oldNode),
|
|
552
|
+
newNode: cloneDeep$1(d.newNode),
|
|
553
|
+
changeRecords: d.changeRecords?.length ? cloneDeep$1(d.changeRecords) : void 0
|
|
554
|
+
}))),
|
|
555
|
+
pageData: {
|
|
556
|
+
name: pageForOp?.name || "",
|
|
557
|
+
id: pageForOp.id
|
|
558
|
+
},
|
|
559
|
+
historyDescription,
|
|
560
|
+
source: historySource
|
|
561
|
+
});
|
|
562
|
+
} else this.selectionBeforeOp = null;
|
|
563
|
+
}
|
|
518
564
|
}
|
|
519
565
|
this.emit("update", updateData);
|
|
566
|
+
this.emit("change", {
|
|
567
|
+
type: "update",
|
|
568
|
+
data: updateData.map((node) => ({
|
|
569
|
+
node,
|
|
570
|
+
page: this.getPageOfNode(node.newNode.id)
|
|
571
|
+
})),
|
|
572
|
+
historySource,
|
|
573
|
+
doNotPushHistory
|
|
574
|
+
});
|
|
520
575
|
return Array.isArray(config) ? updateData.map((item) => item.newNode) : updateData[0].newNode;
|
|
521
576
|
}
|
|
522
577
|
/**
|
|
@@ -633,8 +688,10 @@ var Editor = class extends BaseService {
|
|
|
633
688
|
historyDescription,
|
|
634
689
|
historySource
|
|
635
690
|
});
|
|
636
|
-
if (!doNotSelect)
|
|
637
|
-
|
|
691
|
+
if (!doNotSelect) {
|
|
692
|
+
if (newNodes.length > 1) await stage?.multiSelect(newNodes.map((node) => node.id));
|
|
693
|
+
else await stage?.select(newNodes[0].id);
|
|
694
|
+
}
|
|
638
695
|
return newNode;
|
|
639
696
|
}
|
|
640
697
|
/**
|
|
@@ -682,6 +739,16 @@ var Editor = class extends BaseService {
|
|
|
682
739
|
});
|
|
683
740
|
} else this.selectionBeforeOp = null;
|
|
684
741
|
this.emit("move-layer", offset);
|
|
742
|
+
this.emit("change", {
|
|
743
|
+
type: "move-layer",
|
|
744
|
+
data: [{
|
|
745
|
+
node,
|
|
746
|
+
page: this.getPageOfNode(node.id)
|
|
747
|
+
}],
|
|
748
|
+
offset,
|
|
749
|
+
historySource,
|
|
750
|
+
doNotPushHistory
|
|
751
|
+
});
|
|
685
752
|
}
|
|
686
753
|
/**
|
|
687
754
|
* 移动一个或多个节点到指定容器中。
|
|
@@ -699,7 +766,7 @@ var Editor = class extends BaseService {
|
|
|
699
766
|
*/
|
|
700
767
|
async moveToContainer(config, targetId, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
701
768
|
const isBatch = Array.isArray(config);
|
|
702
|
-
const configs = (isBatch ? config : [config]).filter((item) => !(
|
|
769
|
+
const configs = (isBatch ? config : [config]).filter((item) => !isPageOrFragment(item));
|
|
703
770
|
if (configs.length === 0) throw new Error("没有可移动的节点");
|
|
704
771
|
this.captureSelectionBeforeOp();
|
|
705
772
|
const target = this.getNodeById(targetId, false);
|
|
@@ -811,6 +878,17 @@ var Editor = class extends BaseService {
|
|
|
811
878
|
configs,
|
|
812
879
|
targetParent
|
|
813
880
|
});
|
|
881
|
+
this.emit("change", {
|
|
882
|
+
type: "drag-to",
|
|
883
|
+
data: configs.map((node) => ({
|
|
884
|
+
node,
|
|
885
|
+
page: this.getPageOfNode(node.id)
|
|
886
|
+
})),
|
|
887
|
+
targetIndex,
|
|
888
|
+
targetParent,
|
|
889
|
+
historySource,
|
|
890
|
+
doNotPushHistory
|
|
891
|
+
});
|
|
814
892
|
}
|
|
815
893
|
/**
|
|
816
894
|
* 下列 *AndGetHistoryId 方法与对应的普通操作(add / remove / update ...)行为完全一致,
|
|
@@ -875,7 +953,9 @@ var Editor = class extends BaseService {
|
|
|
875
953
|
* @returns 被撤销的操作
|
|
876
954
|
*/
|
|
877
955
|
async undo() {
|
|
878
|
-
const
|
|
956
|
+
const pageId = this.get("page")?.id;
|
|
957
|
+
if (pageId === void 0) return null;
|
|
958
|
+
const value = history_default.undo("page", pageId);
|
|
879
959
|
if (value) await this.applyHistoryOp(value, true);
|
|
880
960
|
return value;
|
|
881
961
|
}
|
|
@@ -884,7 +964,9 @@ var Editor = class extends BaseService {
|
|
|
884
964
|
* @returns 被恢复的操作
|
|
885
965
|
*/
|
|
886
966
|
async redo() {
|
|
887
|
-
const
|
|
967
|
+
const pageId = this.get("page")?.id;
|
|
968
|
+
if (pageId === void 0) return null;
|
|
969
|
+
const value = history_default.redo("page", pageId);
|
|
888
970
|
if (value) await this.applyHistoryOp(value, false);
|
|
889
971
|
return value;
|
|
890
972
|
}
|
|
@@ -905,7 +987,7 @@ var Editor = class extends BaseService {
|
|
|
905
987
|
* @returns 反向后产生的新 step;目标不存在 / 未应用 / 反向失败时返回 null
|
|
906
988
|
*/
|
|
907
989
|
async revertPageStep(index) {
|
|
908
|
-
const entry = history_default.
|
|
990
|
+
const entry = history_default.getStepList("page", this.get("page")?.id)[index];
|
|
909
991
|
if (!entry?.applied) return null;
|
|
910
992
|
const { step } = entry;
|
|
911
993
|
if (step.opType === "initial") return null;
|
|
@@ -915,7 +997,7 @@ var Editor = class extends BaseService {
|
|
|
915
997
|
if (!items.length || !items.every((item) => item.changeRecords?.length)) return null;
|
|
916
998
|
}
|
|
917
999
|
let revertedStep = null;
|
|
918
|
-
const captureRevert = (s) => {
|
|
1000
|
+
const captureRevert = (_pageId, s) => {
|
|
919
1001
|
revertedStep = s;
|
|
920
1002
|
};
|
|
921
1003
|
history_default.once("change", captureRevert);
|
|
@@ -985,9 +1067,10 @@ var Editor = class extends BaseService {
|
|
|
985
1067
|
*/
|
|
986
1068
|
async revertPageStepById(uuids) {
|
|
987
1069
|
const results = [];
|
|
1070
|
+
const pageId = this.get("page")?.id;
|
|
988
1071
|
for (const uuid of uuids) {
|
|
989
|
-
const
|
|
990
|
-
results.push(
|
|
1072
|
+
const location = history_default.findStepLocationByUuid("page", uuid, pageId);
|
|
1073
|
+
results.push(!location ? null : await this.revertPageStep(location.index));
|
|
991
1074
|
}
|
|
992
1075
|
return results;
|
|
993
1076
|
}
|
|
@@ -1001,8 +1084,9 @@ var Editor = class extends BaseService {
|
|
|
1001
1084
|
* @returns 实际移动到的最终游标位置
|
|
1002
1085
|
*/
|
|
1003
1086
|
async gotoPageStep(targetCursor) {
|
|
1004
|
-
|
|
1005
|
-
|
|
1087
|
+
const pageId = this.get("page")?.id;
|
|
1088
|
+
let cursor = history_default.getCursor("page", pageId);
|
|
1089
|
+
const { length } = history_default.getStepList("page", pageId);
|
|
1006
1090
|
const target = Math.max(0, Math.min(targetCursor, length));
|
|
1007
1091
|
while (cursor > target) {
|
|
1008
1092
|
if (!await this.undo()) break;
|
|
@@ -1038,6 +1122,7 @@ var Editor = class extends BaseService {
|
|
|
1038
1122
|
this.set("stage", null);
|
|
1039
1123
|
this.set("highlightNode", null);
|
|
1040
1124
|
this.set("modifiedNodeIds", /* @__PURE__ */ new Map());
|
|
1125
|
+
this.set("invalidNodeIds", /* @__PURE__ */ new Map());
|
|
1041
1126
|
this.set("pageLength", 0);
|
|
1042
1127
|
}
|
|
1043
1128
|
destroy() {
|
|
@@ -1048,6 +1133,51 @@ var Editor = class extends BaseService {
|
|
|
1048
1133
|
resetModifiedNodeId() {
|
|
1049
1134
|
this.get("modifiedNodeIds").clear();
|
|
1050
1135
|
}
|
|
1136
|
+
/**
|
|
1137
|
+
* 记录(或覆盖)某个节点在指定来源(属性表单 / 样式表单)上的校验错误信息。
|
|
1138
|
+
* @param id 节点 id
|
|
1139
|
+
* @param source 错误来源:'props'(属性表单)| 'style'(样式表单)
|
|
1140
|
+
* @param message 错误文案(可能是包含 <br> 的 HTML)
|
|
1141
|
+
*/
|
|
1142
|
+
setInvalidNode(id, source, message) {
|
|
1143
|
+
const map = this.get("invalidNodeIds");
|
|
1144
|
+
const info = { ...map.get(id) || {} };
|
|
1145
|
+
info[source] = message;
|
|
1146
|
+
map.set(id, info);
|
|
1147
|
+
this.emit("invalid-node-change", map);
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* 删除节点的校验错误记录。
|
|
1151
|
+
* @param id 节点 id
|
|
1152
|
+
* @param source 指定来源则仅删除该来源;不传则删除该节点全部来源的错误
|
|
1153
|
+
*/
|
|
1154
|
+
deleteInvalidNode(id, source) {
|
|
1155
|
+
const map = this.get("invalidNodeIds");
|
|
1156
|
+
if (!map.has(id)) return;
|
|
1157
|
+
if (!source) map.delete(id);
|
|
1158
|
+
else {
|
|
1159
|
+
const info = { ...map.get(id) || {} };
|
|
1160
|
+
delete info[source];
|
|
1161
|
+
if (info.props || info.style) map.set(id, info);
|
|
1162
|
+
else map.delete(id);
|
|
1163
|
+
}
|
|
1164
|
+
this.emit("invalid-node-change", map);
|
|
1165
|
+
}
|
|
1166
|
+
/** 获取当前存在校验错误的节点错误 Map(key 为节点 id) */
|
|
1167
|
+
getInvalidNodeIds() {
|
|
1168
|
+
return this.get("invalidNodeIds");
|
|
1169
|
+
}
|
|
1170
|
+
/** 获取指定节点的校验错误信息 */
|
|
1171
|
+
getInvalidNodeInfo(id) {
|
|
1172
|
+
return this.get("invalidNodeIds").get(id);
|
|
1173
|
+
}
|
|
1174
|
+
/** 清空全部校验错误记录 */
|
|
1175
|
+
resetInvalidNodeId() {
|
|
1176
|
+
const map = this.get("invalidNodeIds");
|
|
1177
|
+
if (map.size === 0) return;
|
|
1178
|
+
map.clear();
|
|
1179
|
+
this.emit("invalid-node-change", map);
|
|
1180
|
+
}
|
|
1051
1181
|
usePlugin(options) {
|
|
1052
1182
|
super.usePlugin(options);
|
|
1053
1183
|
}
|
|
@@ -1060,12 +1190,63 @@ var Editor = class extends BaseService {
|
|
|
1060
1190
|
emit(eventName, ...args) {
|
|
1061
1191
|
return super.emit(eventName, ...args);
|
|
1062
1192
|
}
|
|
1193
|
+
/**
|
|
1194
|
+
* 应用一次属性面板提交携带的校验错误信息(在写入历史记录之前调用,使历史快照与本次变更对齐)。
|
|
1195
|
+
* - invalidInfo 为空(调用方未携带):认为本次更新对应的节点已无校验错误,清除其全部来源的错误;
|
|
1196
|
+
* - error 非空则记录错误,为空则清除对应来源的错误。
|
|
1197
|
+
*/
|
|
1198
|
+
applyInvalidInfo(config, invalidInfo) {
|
|
1199
|
+
if (!invalidInfo) {
|
|
1200
|
+
(Array.isArray(config) ? config : [config]).map((node) => node.id).filter((id) => id !== void 0).forEach((id) => this.deleteInvalidNode(id));
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
const { id, source, error } = invalidInfo;
|
|
1204
|
+
if (error) this.setInvalidNode(id, source, error);
|
|
1205
|
+
else this.deleteInvalidNode(id, source);
|
|
1206
|
+
}
|
|
1207
|
+
/** 删除被移除节点(含其子树)的校验错误记录,避免残留误报 */
|
|
1208
|
+
removeInvalidNodesBySubtree(nodes) {
|
|
1209
|
+
const map = this.get("invalidNodeIds");
|
|
1210
|
+
if (map.size === 0) return;
|
|
1211
|
+
let changed = false;
|
|
1212
|
+
nodes.forEach((node) => {
|
|
1213
|
+
traverseNode(node, (n) => {
|
|
1214
|
+
if (n.id !== void 0 && map.delete(n.id)) changed = true;
|
|
1215
|
+
});
|
|
1216
|
+
});
|
|
1217
|
+
if (changed) this.emit("invalid-node-change", map);
|
|
1218
|
+
}
|
|
1219
|
+
/** 清理不在当前 DSL 中的失效节点错误记录(用于整体替换 root 后) */
|
|
1220
|
+
pruneInvalidNodeIds() {
|
|
1221
|
+
const map = this.get("invalidNodeIds");
|
|
1222
|
+
if (map.size === 0) return;
|
|
1223
|
+
let changed = false;
|
|
1224
|
+
for (const id of [...map.keys()]) if (!this.getNodeById(id, false)) {
|
|
1225
|
+
map.delete(id);
|
|
1226
|
+
changed = true;
|
|
1227
|
+
}
|
|
1228
|
+
if (changed) this.emit("invalid-node-change", map);
|
|
1229
|
+
}
|
|
1063
1230
|
addModifiedNodeId(id) {
|
|
1064
1231
|
this.get("modifiedNodeIds").set(id, id);
|
|
1065
1232
|
}
|
|
1233
|
+
/**
|
|
1234
|
+
* 获取指定节点所属的页面 / 页面片:
|
|
1235
|
+
* - 普通节点返回其所在的 page;
|
|
1236
|
+
* - 节点本身就是 page / pageFragment 时返回它自己;
|
|
1237
|
+
* - 找不到时返回 null。
|
|
1238
|
+
* 供 `change` 事件携带「变更节点对应的 page」(而非编辑器当前选中页)。
|
|
1239
|
+
*/
|
|
1240
|
+
getPageOfNode(id) {
|
|
1241
|
+
const { node, page } = this.getNodeInfo(id, false);
|
|
1242
|
+
if (page) return page;
|
|
1243
|
+
if (node && isPageOrFragment(node)) return node;
|
|
1244
|
+
return null;
|
|
1245
|
+
}
|
|
1066
1246
|
captureSelectionBeforeOp() {
|
|
1067
1247
|
if (this.selectionBeforeOp) return;
|
|
1068
1248
|
this.selectionBeforeOp = this.get("nodes").map((n) => n.id);
|
|
1249
|
+
this.invalidNodeIdsBeforeOp = new Map(this.get("invalidNodeIds"));
|
|
1069
1250
|
}
|
|
1070
1251
|
/**
|
|
1071
1252
|
* 比较「上一次 root」与「新 root」的页面 / 页面片,按页面粒度把整体替换拆成历史记录:
|
|
@@ -1082,24 +1263,35 @@ var Editor = class extends BaseService {
|
|
|
1082
1263
|
const prevMap = new Map(prevPages.map((p) => [`${p.id}`, p]));
|
|
1083
1264
|
const nextMap = new Map(nextPages.map((p) => [`${p.id}`, p]));
|
|
1084
1265
|
const indexInItems = (root, id) => (root.items ?? []).findIndex((item) => `${item.id}` === `${id}`);
|
|
1266
|
+
const addedPages = [];
|
|
1267
|
+
const removedPages = [];
|
|
1085
1268
|
nextPages.forEach((nextPage) => {
|
|
1086
1269
|
const prevPage = prevMap.get(`${nextPage.id}`);
|
|
1087
|
-
if (!prevPage)
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1270
|
+
if (!prevPage) {
|
|
1271
|
+
this.pushPageDiffStep("add", nextPage, {
|
|
1272
|
+
newSchema: cloneDeep$1(toRaw(nextPage)),
|
|
1273
|
+
parentId: nextRoot.id,
|
|
1274
|
+
index: indexInItems(nextRoot, nextPage.id)
|
|
1275
|
+
}, source);
|
|
1276
|
+
addedPages.push(nextPage);
|
|
1277
|
+
} else if (!isEqual(toRaw(prevPage), toRaw(nextPage))) this.pushPageDiffStep("update", nextPage, {
|
|
1093
1278
|
oldSchema: cloneDeep$1(toRaw(prevPage)),
|
|
1094
1279
|
newSchema: cloneDeep$1(toRaw(nextPage))
|
|
1095
1280
|
}, source);
|
|
1096
1281
|
});
|
|
1097
1282
|
prevPages.forEach((prevPage) => {
|
|
1098
|
-
if (!nextMap.has(`${prevPage.id}`))
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1283
|
+
if (!nextMap.has(`${prevPage.id}`)) {
|
|
1284
|
+
this.pushPageDiffStep("remove", prevPage, {
|
|
1285
|
+
oldSchema: cloneDeep$1(toRaw(prevPage)),
|
|
1286
|
+
parentId: preRoot.id,
|
|
1287
|
+
index: indexInItems(preRoot, prevPage.id)
|
|
1288
|
+
}, source);
|
|
1289
|
+
removedPages.push(prevPage);
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
if (addedPages.length || removedPages.length) history_default.notifyPageStructureChange({
|
|
1293
|
+
add: addedPages,
|
|
1294
|
+
remove: removedPages
|
|
1103
1295
|
});
|
|
1104
1296
|
}
|
|
1105
1297
|
/**
|
|
@@ -1117,41 +1309,50 @@ var Editor = class extends BaseService {
|
|
|
1117
1309
|
id: page.id
|
|
1118
1310
|
},
|
|
1119
1311
|
opType,
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1312
|
+
extra: {
|
|
1313
|
+
selectedBefore: [],
|
|
1314
|
+
selectedAfter: [],
|
|
1315
|
+
modifiedNodeIds: /* @__PURE__ */ new Map()
|
|
1316
|
+
},
|
|
1123
1317
|
diff: [diffItem],
|
|
1124
1318
|
rootStep: true
|
|
1125
1319
|
};
|
|
1126
1320
|
if (source) step.source = source;
|
|
1127
1321
|
const top = history_default.getCurrentPageStep(page.id);
|
|
1128
|
-
if (top?.rootStep && top.source === source) history_default.
|
|
1129
|
-
else history_default.push(step, page.id);
|
|
1322
|
+
if (top?.rootStep && top.source === source) history_default.replaceCurrentStep("page", step, page.id);
|
|
1323
|
+
else history_default.push("page", step, page.id);
|
|
1130
1324
|
}
|
|
1131
1325
|
pushOpHistory(opType, { diff, pageData, historyDescription, source }) {
|
|
1132
1326
|
const step = {
|
|
1133
1327
|
uuid: guid(),
|
|
1134
1328
|
data: pageData,
|
|
1135
1329
|
opType,
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1330
|
+
extra: {
|
|
1331
|
+
selectedBefore: this.selectionBeforeOp ?? [],
|
|
1332
|
+
selectedAfter: this.get("nodes").map((n) => n.id),
|
|
1333
|
+
modifiedNodeIds: new Map(this.get("modifiedNodeIds")),
|
|
1334
|
+
invalidNodeIdsBefore: new Map(this.invalidNodeIdsBeforeOp ?? this.get("invalidNodeIds")),
|
|
1335
|
+
invalidNodeIdsAfter: new Map(this.get("invalidNodeIds"))
|
|
1336
|
+
},
|
|
1139
1337
|
diff
|
|
1140
1338
|
};
|
|
1141
1339
|
if (historyDescription) step.historyDescription = historyDescription;
|
|
1142
1340
|
if (source) step.source = source;
|
|
1143
|
-
const historyId = history_default.push(step, pageData.id) ? step.uuid : null;
|
|
1341
|
+
const historyId = history_default.push("page", step, pageData.id) ? step.uuid : null;
|
|
1144
1342
|
this.lastPushedHistoryId = historyId;
|
|
1145
1343
|
this.selectionBeforeOp = null;
|
|
1344
|
+
this.invalidNodeIdsBeforeOp = null;
|
|
1146
1345
|
return historyId;
|
|
1147
1346
|
}
|
|
1148
1347
|
/**
|
|
1149
1348
|
* 应用历史操作(撤销 / 重做)
|
|
1150
1349
|
*
|
|
1151
|
-
*
|
|
1152
|
-
* `doNotSelect / doNotSwitchPage`
|
|
1350
|
+
* 删除 / 更新类修改走 `editor.remove / update`,并通过 `doNotPushHistory` 阻止再次入栈、
|
|
1351
|
+
* `doNotSelect / doNotSwitchPage` 让选区由方法末尾的统一逻辑兜底;
|
|
1352
|
+
* 「重新插回节点」(撤销 remove / 重做 add)需按 step 记录的 parentId / index 精确还原,
|
|
1353
|
+
* 不走 this.add,由手工 splice + stage.add 完成后补发等价的 add / change 事件(见 emitHistoryInsertEvents)。
|
|
1153
1354
|
*
|
|
1154
|
-
*
|
|
1355
|
+
* 注意:这些路径都会发出 add / remove / update / change 事件,业务侧若需要区分"用户操作"与"撤销重做触发",
|
|
1155
1356
|
* 请监听 `history-change` 事件配合判断。
|
|
1156
1357
|
*
|
|
1157
1358
|
* @param step 操作记录
|
|
@@ -1165,7 +1366,8 @@ var Editor = class extends BaseService {
|
|
|
1165
1366
|
const commonOpts = {
|
|
1166
1367
|
doNotSelect: true,
|
|
1167
1368
|
doNotSwitchPage: true,
|
|
1168
|
-
doNotPushHistory: true
|
|
1369
|
+
doNotPushHistory: true,
|
|
1370
|
+
historySource: step.source
|
|
1169
1371
|
};
|
|
1170
1372
|
switch (step.opType) {
|
|
1171
1373
|
case "add": {
|
|
@@ -1177,20 +1379,25 @@ var Editor = class extends BaseService {
|
|
|
1177
1379
|
}
|
|
1178
1380
|
else {
|
|
1179
1381
|
const sorted = [...items].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
1382
|
+
const addedNodes = [];
|
|
1180
1383
|
for (const { newSchema, parentId, index } of sorted) {
|
|
1181
1384
|
if (!newSchema || parentId === void 0) continue;
|
|
1182
1385
|
const parent = this.getNodeById(parentId, false);
|
|
1183
1386
|
if (parent?.items) {
|
|
1184
|
-
|
|
1185
|
-
|
|
1387
|
+
const addedNode = cloneDeep$1(newSchema);
|
|
1388
|
+
const insertIndex = clampIndex(index, parent.items.length);
|
|
1389
|
+
parent.items.splice(insertIndex, 0, addedNode);
|
|
1390
|
+
addedNodes.push(addedNode);
|
|
1186
1391
|
await stage?.add({
|
|
1187
1392
|
config: cloneDeep$1(newSchema),
|
|
1188
1393
|
parent: cloneDeep$1(parent),
|
|
1189
1394
|
parentId: parent.id,
|
|
1190
|
-
root: cloneDeep$1(root)
|
|
1395
|
+
root: cloneDeep$1(root),
|
|
1396
|
+
index: insertIndex
|
|
1191
1397
|
});
|
|
1192
1398
|
}
|
|
1193
1399
|
}
|
|
1400
|
+
this.emitHistoryInsertEvents(addedNodes, step.source);
|
|
1194
1401
|
}
|
|
1195
1402
|
break;
|
|
1196
1403
|
}
|
|
@@ -1198,19 +1405,25 @@ var Editor = class extends BaseService {
|
|
|
1198
1405
|
const items = step.diff ?? [];
|
|
1199
1406
|
if (reverse) {
|
|
1200
1407
|
const sorted = [...items].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
1408
|
+
const addedNodes = [];
|
|
1201
1409
|
for (const { oldSchema, parentId, index } of sorted) {
|
|
1202
1410
|
if (!oldSchema || parentId === void 0) continue;
|
|
1203
1411
|
const parent = this.getNodeById(parentId, false);
|
|
1204
1412
|
if (parent?.items) {
|
|
1205
|
-
|
|
1413
|
+
const addedNode = cloneDeep$1(oldSchema);
|
|
1414
|
+
const insertIndex = clampIndex(index, parent.items.length);
|
|
1415
|
+
parent.items.splice(insertIndex, 0, addedNode);
|
|
1416
|
+
addedNodes.push(addedNode);
|
|
1206
1417
|
await stage?.add({
|
|
1207
1418
|
config: cloneDeep$1(oldSchema),
|
|
1208
1419
|
parent: cloneDeep$1(parent),
|
|
1209
1420
|
parentId,
|
|
1210
|
-
root: cloneDeep$1(root)
|
|
1421
|
+
root: cloneDeep$1(root),
|
|
1422
|
+
index: insertIndex
|
|
1211
1423
|
});
|
|
1212
1424
|
}
|
|
1213
1425
|
}
|
|
1426
|
+
this.emitHistoryInsertEvents(addedNodes, step.source);
|
|
1214
1427
|
} else for (const { oldSchema } of items) {
|
|
1215
1428
|
if (!oldSchema) continue;
|
|
1216
1429
|
const existing = this.getNodeById(oldSchema.id, false);
|
|
@@ -1237,14 +1450,20 @@ var Editor = class extends BaseService {
|
|
|
1237
1450
|
}
|
|
1238
1451
|
return cloneDeep$1(reverse ? oldNode : newNode);
|
|
1239
1452
|
});
|
|
1240
|
-
if (configs.length) await this.update(configs, {
|
|
1453
|
+
if (configs.length) await this.update(configs, {
|
|
1454
|
+
doNotPushHistory: true,
|
|
1455
|
+
historySource: step.source
|
|
1456
|
+
});
|
|
1241
1457
|
break;
|
|
1242
1458
|
}
|
|
1243
1459
|
}
|
|
1244
|
-
this.set("modifiedNodeIds", step.modifiedNodeIds);
|
|
1460
|
+
this.set("modifiedNodeIds", step.extra?.modifiedNodeIds ?? /* @__PURE__ */ new Map());
|
|
1461
|
+
const invalidToRestore = (reverse ? step.extra?.invalidNodeIdsBefore : step.extra?.invalidNodeIdsAfter) ?? /* @__PURE__ */ new Map();
|
|
1462
|
+
this.set("invalidNodeIds", new Map(invalidToRestore));
|
|
1463
|
+
this.emit("invalid-node-change", this.get("invalidNodeIds"));
|
|
1245
1464
|
const page = toRaw(this.get("page"));
|
|
1246
1465
|
if (page) {
|
|
1247
|
-
const selectIds = reverse ? step.selectedBefore : step.selectedAfter;
|
|
1466
|
+
const selectIds = (reverse ? step.extra?.selectedBefore : step.extra?.selectedAfter) ?? [];
|
|
1248
1467
|
setTimeout(() => {
|
|
1249
1468
|
if (!selectIds.length) return;
|
|
1250
1469
|
if (selectIds.length > 1) {
|
|
@@ -1258,6 +1477,23 @@ var Editor = class extends BaseService {
|
|
|
1258
1477
|
selectedConfigExceptionHandler(config) {
|
|
1259
1478
|
return resolveSelectedNode(config, (id) => this.getNodeInfo(id), this.state.root?.id);
|
|
1260
1479
|
}
|
|
1480
|
+
/**
|
|
1481
|
+
* 撤销 remove / 重做 add 通过手工 splice 按 step 记录的 parentId / index 精确还原节点(不走 this.add,原因见调用处注释),
|
|
1482
|
+
* 这里补齐与 this.add 等价的 add / change 事件,保证撤销/重做路径的事件行为与正向操作一致。
|
|
1483
|
+
*/
|
|
1484
|
+
emitHistoryInsertEvents(nodes, source) {
|
|
1485
|
+
if (!nodes.length) return;
|
|
1486
|
+
this.emit("add", nodes);
|
|
1487
|
+
this.emit("change", {
|
|
1488
|
+
type: "add",
|
|
1489
|
+
data: nodes.map((node) => ({
|
|
1490
|
+
node,
|
|
1491
|
+
page: this.getPageOfNode(node.id)
|
|
1492
|
+
})),
|
|
1493
|
+
historySource: source,
|
|
1494
|
+
doNotPushHistory: true
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1261
1497
|
};
|
|
1262
1498
|
var editor_default = new Editor();
|
|
1263
1499
|
//#endregion
|