@tmagic/editor 1.8.0-manmanyu.9 → 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 -122
- 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 +16 -8
- 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 +1 -1
- 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 +11 -13
- 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/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 +8 -3
- package/dist/es/services/dataSource.js +3 -0
- package/dist/es/services/dep.js +162 -41
- package/dist/es/services/editor.js +344 -113
- package/dist/es/services/events.js +4 -4
- package/dist/es/services/history.js +17 -1
- 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/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 +12695 -10896
- 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 +1199 -724
- 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
|
*/
|
|
@@ -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}`;
|
|
@@ -239,24 +253,29 @@ var Editor = class extends BaseService {
|
|
|
239
253
|
this.set("stage", null);
|
|
240
254
|
this.set("highlightNode", null);
|
|
241
255
|
}
|
|
242
|
-
async doAdd(node, parent) {
|
|
256
|
+
async doAdd(node, parent, _options = {}) {
|
|
243
257
|
const root = this.get("root");
|
|
244
258
|
if (!root) throw new Error("root为空");
|
|
245
259
|
const curNode = this.get("node");
|
|
246
260
|
const stage = this.get("stage");
|
|
247
261
|
if (!curNode) throw new Error("当前选中节点为空");
|
|
248
|
-
if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && !(
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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
|
+
};
|
|
253
271
|
const layout = await this.getLayout(toRaw(parent), node);
|
|
254
272
|
node.style = getInitPositionStyle(node.style, layout);
|
|
255
273
|
await stage?.add({
|
|
256
274
|
config: cloneDeep$1(node),
|
|
257
275
|
parent: cloneDeep$1(parent),
|
|
258
276
|
parentId: parent.id,
|
|
259
|
-
root: cloneDeep$1(root)
|
|
277
|
+
root: cloneDeep$1(root),
|
|
278
|
+
index: insertIndex
|
|
260
279
|
});
|
|
261
280
|
const newStyle = fixNodePosition(node, parent, stage);
|
|
262
281
|
if (newStyle && (newStyle.top !== node.style.top || newStyle.left !== node.style.left)) {
|
|
@@ -274,14 +293,12 @@ var Editor = class extends BaseService {
|
|
|
274
293
|
* 向指点容器添加组件节点
|
|
275
294
|
* @param addConfig 将要添加的组件节点配置
|
|
276
295
|
* @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
|
|
277
|
-
* @param options
|
|
278
|
-
* @param options.doNotSelect 添加后是否不更新当前选中节点(默认 false,添加后会选中新增的节点)
|
|
279
|
-
* @param options.doNotSwitchPage 添加后是否不切换当前页面(默认 false;新增页面 / 跨页新增时为 true 会跳过会引发页面切换的选中操作)
|
|
280
|
-
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
296
|
+
* @param options 可选配置,见 {@link DslOpOptions}
|
|
281
297
|
* @returns 添加后的节点
|
|
282
298
|
*/
|
|
283
|
-
async add(addNode, parent,
|
|
299
|
+
async add(addNode, parent, options = {}) {
|
|
284
300
|
this.captureSelectionBeforeOp();
|
|
301
|
+
const { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = options;
|
|
285
302
|
const stage = this.get("stage");
|
|
286
303
|
const addNodes = [];
|
|
287
304
|
if (!Array.isArray(addNode)) {
|
|
@@ -289,13 +306,13 @@ var Editor = class extends BaseService {
|
|
|
289
306
|
if (!type) throw new Error("组件类型不能为空");
|
|
290
307
|
addNodes.push({ ...toRaw(await props_default.getPropsValue(type, config)) });
|
|
291
308
|
} else addNodes.push(...addNode);
|
|
292
|
-
const newNodes =
|
|
309
|
+
const newNodes = [];
|
|
310
|
+
for (const node of addNodes) {
|
|
293
311
|
const root = this.get("root");
|
|
294
|
-
|
|
295
|
-
const parentNode = parent ?? getAddParent(node);
|
|
312
|
+
const parentNode = isPageOrFragment(node) && root ? root : parent ?? getAddParent(node);
|
|
296
313
|
if (!parentNode) throw new Error("未找到父元素");
|
|
297
|
-
|
|
298
|
-
}
|
|
314
|
+
newNodes.push(await this.doAdd(node, parentNode, options));
|
|
315
|
+
}
|
|
299
316
|
if (newNodes.length > 1) {
|
|
300
317
|
const wouldSwitchPage = newNodes.some((n) => this.isOnDifferentPage(n));
|
|
301
318
|
if (!doNotSelect && !(doNotSwitchPage && wouldSwitchPage)) {
|
|
@@ -311,7 +328,7 @@ var Editor = class extends BaseService {
|
|
|
311
328
|
else if (isPageFragment(newNodes[0])) this.state.pageFragmentLength += 1;
|
|
312
329
|
else if (!skipSelect) stage?.select(newNodes[0].id);
|
|
313
330
|
}
|
|
314
|
-
if (!(
|
|
331
|
+
if (!isPageOrFragment(newNodes[0])) {
|
|
315
332
|
const pageForOp = this.getNodeInfo(newNodes[0].id, false).page;
|
|
316
333
|
if (!doNotPushHistory) {
|
|
317
334
|
const parentId = (this.getParentById(newNodes[0].id, false) ?? this.get("root")).id;
|
|
@@ -335,6 +352,20 @@ var Editor = class extends BaseService {
|
|
|
335
352
|
} else this.selectionBeforeOp = null;
|
|
336
353
|
}
|
|
337
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
|
+
});
|
|
338
369
|
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
339
370
|
}
|
|
340
371
|
async doRemove(node, { doNotSelect = false, doNotSwitchPage = false } = {}) {
|
|
@@ -344,13 +375,10 @@ var Editor = class extends BaseService {
|
|
|
344
375
|
if (!parent || !curNode) throw new Error("找不要删除的节点");
|
|
345
376
|
const index = getNodeIndex(curNode.id, parent);
|
|
346
377
|
if (typeof index !== "number" || index === -1) throw new Error("找不要删除的节点");
|
|
347
|
-
parent.items?.splice(index, 1);
|
|
348
378
|
const stage = this.get("stage");
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
root: cloneDeep$1(root)
|
|
353
|
-
});
|
|
379
|
+
const currentPage = this.get("page");
|
|
380
|
+
const isDeletingCurrentPage = isPageOrFragment(node) && !!currentPage && `${currentPage.id}` === `${node.id}`;
|
|
381
|
+
parent.items?.splice(index, 1);
|
|
354
382
|
const selectedNodes = this.get("nodes");
|
|
355
383
|
const removedSelectedIndex = selectedNodes.findIndex((n) => `${n.id}` === `${node.id}`);
|
|
356
384
|
if (removedSelectedIndex !== -1) {
|
|
@@ -358,24 +386,29 @@ var Editor = class extends BaseService {
|
|
|
358
386
|
nextSelected.splice(removedSelectedIndex, 1);
|
|
359
387
|
this.set("nodes", nextSelected);
|
|
360
388
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
const selectDefault = async (pages) => {
|
|
366
|
-
if (pages[0]) {
|
|
367
|
-
await this.select(pages[0]);
|
|
368
|
-
stage?.select(pages[0].id);
|
|
369
|
-
} else this.selectRoot();
|
|
389
|
+
const removeData = {
|
|
390
|
+
id: node.id,
|
|
391
|
+
parentId: parent.id,
|
|
392
|
+
root: cloneDeep$1(root)
|
|
370
393
|
};
|
|
371
394
|
const rootItems = root.items || [];
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
this.state.pageFragmentLength -= 1;
|
|
377
|
-
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
|
+
}
|
|
378
410
|
} else {
|
|
411
|
+
stage?.remove(removeData);
|
|
379
412
|
if (!doNotSelect) {
|
|
380
413
|
await this.select(parent);
|
|
381
414
|
stage?.select(parent.id);
|
|
@@ -395,12 +428,17 @@ var Editor = class extends BaseService {
|
|
|
395
428
|
* @param options.doNotSwitchPage 删除后是否不切换当前页面(默认 false;删除页面 / 页面片段时为 true 会跳过自动切换到首个剩余页面)
|
|
396
429
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
397
430
|
*/
|
|
398
|
-
async remove(nodeOrNodeList,
|
|
431
|
+
async remove(nodeOrNodeList, options = {}) {
|
|
432
|
+
const { doNotPushHistory = false, historyDescription, historySource } = options;
|
|
399
433
|
this.captureSelectionBeforeOp();
|
|
400
434
|
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
435
|
+
const changeItems = nodes.map((node) => ({
|
|
436
|
+
node,
|
|
437
|
+
page: this.getPageOfNode(node.id)
|
|
438
|
+
}));
|
|
401
439
|
const removedItems = [];
|
|
402
440
|
let pageForOp = null;
|
|
403
|
-
if (!(
|
|
441
|
+
if (!isPageOrFragment(nodes[0])) for (const n of nodes) {
|
|
404
442
|
const { parent, node: curNode, page } = this.getNodeInfo(n.id, false);
|
|
405
443
|
if (parent && curNode) {
|
|
406
444
|
if (!pageForOp && page) pageForOp = {
|
|
@@ -415,27 +453,39 @@ var Editor = class extends BaseService {
|
|
|
415
453
|
});
|
|
416
454
|
}
|
|
417
455
|
}
|
|
418
|
-
await Promise.all(nodes.map((node) => this.doRemove(node,
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
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
|
+
}
|
|
429
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
|
+
});
|
|
430
479
|
}
|
|
431
|
-
async doUpdate(config,
|
|
480
|
+
async doUpdate(config, data = {}) {
|
|
481
|
+
const { changeRecords = [], historySource, replace = false } = data;
|
|
432
482
|
if (!this.get("root")) throw new Error("root为空");
|
|
433
483
|
if (!config?.id) throw new Error("没有配置或者配置缺少id值");
|
|
434
484
|
const info = this.getNodeInfo(config.id, false);
|
|
435
485
|
if (!info.node) throw new Error(`获取不到id为${config.id}的节点`);
|
|
436
486
|
const node = toRaw(info.node);
|
|
437
|
-
let newConfig = await toggleFixedPosition(toRaw(config), node, info.path, this.getLayout);
|
|
438
|
-
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);
|
|
439
489
|
if (!newConfig.type) throw new Error("配置缺少type值");
|
|
440
490
|
if (newConfig.type === NodeType.ROOT) {
|
|
441
491
|
this.set("root", newConfig, { historySource });
|
|
@@ -450,9 +500,11 @@ var Editor = class extends BaseService {
|
|
|
450
500
|
const parentNodeItems = parent.items;
|
|
451
501
|
const index = getNodeIndex(newConfig.id, parent);
|
|
452
502
|
if (!parentNodeItems || typeof index === "undefined" || index === -1) throw new Error("更新的节点未找到");
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
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
|
+
}
|
|
456
508
|
parentNodeItems[index] = newConfig;
|
|
457
509
|
const selectedNodes = this.get("nodes");
|
|
458
510
|
const targetIndex = selectedNodes.findIndex((nodeItem) => `${nodeItem.id}` === `${newConfig.id}`);
|
|
@@ -460,7 +512,7 @@ var Editor = class extends BaseService {
|
|
|
460
512
|
selectedNodes.splice(targetIndex, 1, newConfig);
|
|
461
513
|
this.set("nodes", [...selectedNodes]);
|
|
462
514
|
}
|
|
463
|
-
if (
|
|
515
|
+
if (isPageOrFragment(newConfig)) {
|
|
464
516
|
const currentPage = this.get("page");
|
|
465
517
|
if (currentPage && `${currentPage.id}` === `${newConfig.id}`) this.set("page", newConfig);
|
|
466
518
|
}
|
|
@@ -475,43 +527,51 @@ var Editor = class extends BaseService {
|
|
|
475
527
|
* 更新节点
|
|
476
528
|
* update后会触发依赖收集,收集完后会掉stage.update方法
|
|
477
529
|
* @param config 新的节点配置,配置中需要有id信息
|
|
478
|
-
* @param data
|
|
479
|
-
* @param data.changeRecords 单节点 form 端变更记录(多节点场景下被忽略,使用 changeRecordList)
|
|
480
|
-
* @param data.changeRecordList 多节点 form 端变更记录列表,按 config 数组同序对应每个节点;优先级高于 changeRecords
|
|
481
|
-
* @param data.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
482
|
-
* @param data.historyDescription 入栈时附带的人类可读描述,用于历史面板展示(不影响 undo/redo 行为)
|
|
530
|
+
* @param data 额外数据,见 {@link UpdateOptions}
|
|
483
531
|
* @returns 更新后的节点配置
|
|
484
532
|
*/
|
|
485
533
|
async update(config, data = {}) {
|
|
486
534
|
this.captureSelectionBeforeOp();
|
|
487
|
-
const { doNotPushHistory = false, changeRecordList, changeRecords, historyDescription, historySource } = data;
|
|
535
|
+
const { doNotPushHistory = false, changeRecordList, changeRecords, historyDescription, historySource, invalidInfo } = data;
|
|
488
536
|
const nodes = Array.isArray(config) ? config : [config];
|
|
489
537
|
const updateData = await Promise.all(nodes.map((node, index) => {
|
|
490
538
|
const recordsForNode = changeRecordList ? changeRecordList[index] ?? [] : changeRecords ?? [];
|
|
491
539
|
return this.doUpdate(node, {
|
|
492
|
-
|
|
493
|
-
|
|
540
|
+
...data,
|
|
541
|
+
changeRecords: recordsForNode
|
|
494
542
|
});
|
|
495
543
|
}));
|
|
544
|
+
this.applyInvalidInfo(config, invalidInfo);
|
|
496
545
|
if (updateData[0].oldNode?.type !== NodeType.ROOT) {
|
|
497
|
-
if (this.get("nodes").length)
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
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
|
+
}
|
|
513
564
|
}
|
|
514
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
|
+
});
|
|
515
575
|
return Array.isArray(config) ? updateData.map((item) => item.newNode) : updateData[0].newNode;
|
|
516
576
|
}
|
|
517
577
|
/**
|
|
@@ -628,8 +688,10 @@ var Editor = class extends BaseService {
|
|
|
628
688
|
historyDescription,
|
|
629
689
|
historySource
|
|
630
690
|
});
|
|
631
|
-
if (!doNotSelect)
|
|
632
|
-
|
|
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
|
+
}
|
|
633
695
|
return newNode;
|
|
634
696
|
}
|
|
635
697
|
/**
|
|
@@ -677,6 +739,16 @@ var Editor = class extends BaseService {
|
|
|
677
739
|
});
|
|
678
740
|
} else this.selectionBeforeOp = null;
|
|
679
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
|
+
});
|
|
680
752
|
}
|
|
681
753
|
/**
|
|
682
754
|
* 移动一个或多个节点到指定容器中。
|
|
@@ -694,7 +766,7 @@ var Editor = class extends BaseService {
|
|
|
694
766
|
*/
|
|
695
767
|
async moveToContainer(config, targetId, { doNotSelect = false, doNotSwitchPage = false, doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
696
768
|
const isBatch = Array.isArray(config);
|
|
697
|
-
const configs = (isBatch ? config : [config]).filter((item) => !(
|
|
769
|
+
const configs = (isBatch ? config : [config]).filter((item) => !isPageOrFragment(item));
|
|
698
770
|
if (configs.length === 0) throw new Error("没有可移动的节点");
|
|
699
771
|
this.captureSelectionBeforeOp();
|
|
700
772
|
const target = this.getNodeById(targetId, false);
|
|
@@ -806,6 +878,17 @@ var Editor = class extends BaseService {
|
|
|
806
878
|
configs,
|
|
807
879
|
targetParent
|
|
808
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
|
+
});
|
|
809
892
|
}
|
|
810
893
|
/**
|
|
811
894
|
* 下列 *AndGetHistoryId 方法与对应的普通操作(add / remove / update ...)行为完全一致,
|
|
@@ -1039,6 +1122,7 @@ var Editor = class extends BaseService {
|
|
|
1039
1122
|
this.set("stage", null);
|
|
1040
1123
|
this.set("highlightNode", null);
|
|
1041
1124
|
this.set("modifiedNodeIds", /* @__PURE__ */ new Map());
|
|
1125
|
+
this.set("invalidNodeIds", /* @__PURE__ */ new Map());
|
|
1042
1126
|
this.set("pageLength", 0);
|
|
1043
1127
|
}
|
|
1044
1128
|
destroy() {
|
|
@@ -1049,6 +1133,51 @@ var Editor = class extends BaseService {
|
|
|
1049
1133
|
resetModifiedNodeId() {
|
|
1050
1134
|
this.get("modifiedNodeIds").clear();
|
|
1051
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
|
+
}
|
|
1052
1181
|
usePlugin(options) {
|
|
1053
1182
|
super.usePlugin(options);
|
|
1054
1183
|
}
|
|
@@ -1061,12 +1190,63 @@ var Editor = class extends BaseService {
|
|
|
1061
1190
|
emit(eventName, ...args) {
|
|
1062
1191
|
return super.emit(eventName, ...args);
|
|
1063
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
|
+
}
|
|
1064
1230
|
addModifiedNodeId(id) {
|
|
1065
1231
|
this.get("modifiedNodeIds").set(id, id);
|
|
1066
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
|
+
}
|
|
1067
1246
|
captureSelectionBeforeOp() {
|
|
1068
1247
|
if (this.selectionBeforeOp) return;
|
|
1069
1248
|
this.selectionBeforeOp = this.get("nodes").map((n) => n.id);
|
|
1249
|
+
this.invalidNodeIdsBeforeOp = new Map(this.get("invalidNodeIds"));
|
|
1070
1250
|
}
|
|
1071
1251
|
/**
|
|
1072
1252
|
* 比较「上一次 root」与「新 root」的页面 / 页面片,按页面粒度把整体替换拆成历史记录:
|
|
@@ -1083,24 +1263,35 @@ var Editor = class extends BaseService {
|
|
|
1083
1263
|
const prevMap = new Map(prevPages.map((p) => [`${p.id}`, p]));
|
|
1084
1264
|
const nextMap = new Map(nextPages.map((p) => [`${p.id}`, p]));
|
|
1085
1265
|
const indexInItems = (root, id) => (root.items ?? []).findIndex((item) => `${item.id}` === `${id}`);
|
|
1266
|
+
const addedPages = [];
|
|
1267
|
+
const removedPages = [];
|
|
1086
1268
|
nextPages.forEach((nextPage) => {
|
|
1087
1269
|
const prevPage = prevMap.get(`${nextPage.id}`);
|
|
1088
|
-
if (!prevPage)
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
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, {
|
|
1094
1278
|
oldSchema: cloneDeep$1(toRaw(prevPage)),
|
|
1095
1279
|
newSchema: cloneDeep$1(toRaw(nextPage))
|
|
1096
1280
|
}, source);
|
|
1097
1281
|
});
|
|
1098
1282
|
prevPages.forEach((prevPage) => {
|
|
1099
|
-
if (!nextMap.has(`${prevPage.id}`))
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
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
|
|
1104
1295
|
});
|
|
1105
1296
|
}
|
|
1106
1297
|
/**
|
|
@@ -1139,7 +1330,9 @@ var Editor = class extends BaseService {
|
|
|
1139
1330
|
extra: {
|
|
1140
1331
|
selectedBefore: this.selectionBeforeOp ?? [],
|
|
1141
1332
|
selectedAfter: this.get("nodes").map((n) => n.id),
|
|
1142
|
-
modifiedNodeIds: new Map(this.get("modifiedNodeIds"))
|
|
1333
|
+
modifiedNodeIds: new Map(this.get("modifiedNodeIds")),
|
|
1334
|
+
invalidNodeIdsBefore: new Map(this.invalidNodeIdsBeforeOp ?? this.get("invalidNodeIds")),
|
|
1335
|
+
invalidNodeIdsAfter: new Map(this.get("invalidNodeIds"))
|
|
1143
1336
|
},
|
|
1144
1337
|
diff
|
|
1145
1338
|
};
|
|
@@ -1148,15 +1341,18 @@ var Editor = class extends BaseService {
|
|
|
1148
1341
|
const historyId = history_default.push("page", step, pageData.id) ? step.uuid : null;
|
|
1149
1342
|
this.lastPushedHistoryId = historyId;
|
|
1150
1343
|
this.selectionBeforeOp = null;
|
|
1344
|
+
this.invalidNodeIdsBeforeOp = null;
|
|
1151
1345
|
return historyId;
|
|
1152
1346
|
}
|
|
1153
1347
|
/**
|
|
1154
1348
|
* 应用历史操作(撤销 / 重做)
|
|
1155
1349
|
*
|
|
1156
|
-
*
|
|
1157
|
-
* `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)。
|
|
1158
1354
|
*
|
|
1159
|
-
*
|
|
1355
|
+
* 注意:这些路径都会发出 add / remove / update / change 事件,业务侧若需要区分"用户操作"与"撤销重做触发",
|
|
1160
1356
|
* 请监听 `history-change` 事件配合判断。
|
|
1161
1357
|
*
|
|
1162
1358
|
* @param step 操作记录
|
|
@@ -1170,7 +1366,8 @@ var Editor = class extends BaseService {
|
|
|
1170
1366
|
const commonOpts = {
|
|
1171
1367
|
doNotSelect: true,
|
|
1172
1368
|
doNotSwitchPage: true,
|
|
1173
|
-
doNotPushHistory: true
|
|
1369
|
+
doNotPushHistory: true,
|
|
1370
|
+
historySource: step.source
|
|
1174
1371
|
};
|
|
1175
1372
|
switch (step.opType) {
|
|
1176
1373
|
case "add": {
|
|
@@ -1182,20 +1379,25 @@ var Editor = class extends BaseService {
|
|
|
1182
1379
|
}
|
|
1183
1380
|
else {
|
|
1184
1381
|
const sorted = [...items].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
1382
|
+
const addedNodes = [];
|
|
1185
1383
|
for (const { newSchema, parentId, index } of sorted) {
|
|
1186
1384
|
if (!newSchema || parentId === void 0) continue;
|
|
1187
1385
|
const parent = this.getNodeById(parentId, false);
|
|
1188
1386
|
if (parent?.items) {
|
|
1189
|
-
|
|
1190
|
-
|
|
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);
|
|
1191
1391
|
await stage?.add({
|
|
1192
1392
|
config: cloneDeep$1(newSchema),
|
|
1193
1393
|
parent: cloneDeep$1(parent),
|
|
1194
1394
|
parentId: parent.id,
|
|
1195
|
-
root: cloneDeep$1(root)
|
|
1395
|
+
root: cloneDeep$1(root),
|
|
1396
|
+
index: insertIndex
|
|
1196
1397
|
});
|
|
1197
1398
|
}
|
|
1198
1399
|
}
|
|
1400
|
+
this.emitHistoryInsertEvents(addedNodes, step.source);
|
|
1199
1401
|
}
|
|
1200
1402
|
break;
|
|
1201
1403
|
}
|
|
@@ -1203,19 +1405,25 @@ var Editor = class extends BaseService {
|
|
|
1203
1405
|
const items = step.diff ?? [];
|
|
1204
1406
|
if (reverse) {
|
|
1205
1407
|
const sorted = [...items].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
1408
|
+
const addedNodes = [];
|
|
1206
1409
|
for (const { oldSchema, parentId, index } of sorted) {
|
|
1207
1410
|
if (!oldSchema || parentId === void 0) continue;
|
|
1208
1411
|
const parent = this.getNodeById(parentId, false);
|
|
1209
1412
|
if (parent?.items) {
|
|
1210
|
-
|
|
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);
|
|
1211
1417
|
await stage?.add({
|
|
1212
1418
|
config: cloneDeep$1(oldSchema),
|
|
1213
1419
|
parent: cloneDeep$1(parent),
|
|
1214
1420
|
parentId,
|
|
1215
|
-
root: cloneDeep$1(root)
|
|
1421
|
+
root: cloneDeep$1(root),
|
|
1422
|
+
index: insertIndex
|
|
1216
1423
|
});
|
|
1217
1424
|
}
|
|
1218
1425
|
}
|
|
1426
|
+
this.emitHistoryInsertEvents(addedNodes, step.source);
|
|
1219
1427
|
} else for (const { oldSchema } of items) {
|
|
1220
1428
|
if (!oldSchema) continue;
|
|
1221
1429
|
const existing = this.getNodeById(oldSchema.id, false);
|
|
@@ -1242,11 +1450,17 @@ var Editor = class extends BaseService {
|
|
|
1242
1450
|
}
|
|
1243
1451
|
return cloneDeep$1(reverse ? oldNode : newNode);
|
|
1244
1452
|
});
|
|
1245
|
-
if (configs.length) await this.update(configs, {
|
|
1453
|
+
if (configs.length) await this.update(configs, {
|
|
1454
|
+
doNotPushHistory: true,
|
|
1455
|
+
historySource: step.source
|
|
1456
|
+
});
|
|
1246
1457
|
break;
|
|
1247
1458
|
}
|
|
1248
1459
|
}
|
|
1249
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"));
|
|
1250
1464
|
const page = toRaw(this.get("page"));
|
|
1251
1465
|
if (page) {
|
|
1252
1466
|
const selectIds = (reverse ? step.extra?.selectedBefore : step.extra?.selectedAfter) ?? [];
|
|
@@ -1263,6 +1477,23 @@ var Editor = class extends BaseService {
|
|
|
1263
1477
|
selectedConfigExceptionHandler(config) {
|
|
1264
1478
|
return resolveSelectedNode(config, (id) => this.getNodeInfo(id), this.state.root?.id);
|
|
1265
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
|
+
}
|
|
1266
1497
|
};
|
|
1267
1498
|
var editor_default = new Editor();
|
|
1268
1499
|
//#endregion
|