@tmagic/editor 1.7.6 → 1.7.8-beta.1
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/LICENSE +235 -164
- package/dist/es/Editor.js +5 -0
- package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +214 -0
- package/dist/es/_virtual/_plugin-vue_export-helper.js +8 -0
- package/dist/es/components/CodeBlockEditor.js +5 -0
- package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +337 -0
- package/dist/es/components/CodeParams.js +5 -0
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +63 -0
- package/dist/es/components/ContentMenu.js +5 -0
- package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +160 -0
- package/dist/es/components/FloatingBox.js +5 -0
- package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +161 -0
- package/dist/es/components/Icon.js +5 -0
- package/dist/es/components/Icon.vue_vue_type_script_setup_true_lang.js +39 -0
- package/dist/es/components/Resizer.js +5 -0
- package/dist/es/components/Resizer.vue_vue_type_script_setup_true_lang.js +20 -0
- package/dist/es/components/ScrollBar.js +6 -0
- package/dist/es/components/ScrollBar.vue_vue_type_script_setup_true_lang.js +72 -0
- package/dist/es/components/ScrollViewer.js +5 -0
- package/dist/es/components/ScrollViewer.vue_vue_type_script_setup_true_lang.js +104 -0
- package/dist/es/components/SearchInput.js +5 -0
- package/dist/es/components/SearchInput.vue_vue_type_script_setup_true_lang.js +40 -0
- package/dist/es/components/SplitView.js +5 -0
- package/dist/es/components/SplitView.vue_vue_type_script_setup_true_lang.js +135 -0
- package/dist/es/components/ToolButton.js +5 -0
- package/dist/es/components/ToolButton.vue_vue_type_script_setup_true_lang.js +131 -0
- package/dist/es/components/Tree.js +5 -0
- package/dist/es/components/Tree.vue_vue_type_script_setup_true_lang.js +60 -0
- package/dist/es/components/TreeNode.js +5 -0
- package/dist/es/components/TreeNode.vue_vue_type_script_setup_true_lang.js +126 -0
- package/dist/es/editorProps.js +34 -0
- package/dist/es/fields/Code.js +5 -0
- package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/es/fields/CodeLink.js +5 -0
- package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +69 -0
- package/dist/es/fields/CodeSelect.js +5 -0
- package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +116 -0
- package/dist/es/fields/CodeSelectCol.js +5 -0
- package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +145 -0
- package/dist/es/fields/CondOpSelect.js +5 -0
- package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +81 -0
- package/dist/es/fields/DataSourceFieldSelect/FieldSelect.js +5 -0
- package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +158 -0
- package/dist/es/fields/DataSourceFieldSelect/Index.js +5 -0
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +155 -0
- package/dist/es/fields/DataSourceFields.js +5 -0
- package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +390 -0
- package/dist/es/fields/DataSourceInput.js +5 -0
- package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +268 -0
- package/dist/es/fields/DataSourceMethodSelect.js +5 -0
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +144 -0
- package/dist/es/fields/DataSourceMethods.js +5 -0
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +148 -0
- package/dist/es/fields/DataSourceMocks.js +5 -0
- package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +259 -0
- package/dist/es/fields/DataSourceSelect.js +5 -0
- package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +101 -0
- package/dist/es/fields/DisplayConds.js +5 -0
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +156 -0
- package/dist/es/fields/EventSelect.js +5 -0
- package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +338 -0
- package/dist/es/fields/KeyValue.js +5 -0
- package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +158 -0
- package/dist/es/fields/PageFragmentSelect.js +5 -0
- package/dist/es/fields/PageFragmentSelect.vue_vue_type_script_setup_true_lang.js +81 -0
- package/dist/es/fields/StyleSetter/Index.js +5 -0
- package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +92 -0
- package/dist/es/fields/StyleSetter/components/BackgroundPosition.js +5 -0
- package/dist/es/fields/StyleSetter/components/BackgroundPosition.vue_vue_type_script_setup_true_lang.js +96 -0
- package/dist/es/fields/StyleSetter/components/Border.js +5 -0
- package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +100 -0
- package/dist/es/fields/StyleSetter/components/Box.js +5 -0
- package/dist/es/fields/StyleSetter/components/Box.vue_vue_type_script_setup_true_lang.js +81 -0
- package/dist/es/fields/StyleSetter/icons/background-repeat/NoRepeat.js +17 -0
- package/dist/es/fields/StyleSetter/icons/background-repeat/Repeat.js +14 -0
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatX.js +17 -0
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatY.js +17 -0
- package/dist/es/fields/StyleSetter/icons/display/Block.js +14 -0
- package/dist/es/fields/StyleSetter/icons/display/Flex.js +14 -0
- package/dist/es/fields/StyleSetter/icons/display/Inline.js +14 -0
- package/dist/es/fields/StyleSetter/icons/display/InlineBlock.js +14 -0
- package/dist/es/fields/StyleSetter/icons/display/None.js +14 -0
- package/dist/es/fields/StyleSetter/icons/flex-direction/Column.js +14 -0
- package/dist/es/fields/StyleSetter/icons/flex-direction/ColumnReverse.js +14 -0
- package/dist/es/fields/StyleSetter/icons/flex-direction/Row.js +14 -0
- package/dist/es/fields/StyleSetter/icons/flex-direction/RowReverse.js +14 -0
- package/dist/es/fields/StyleSetter/icons/justify-content/Center.js +14 -0
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexEnd.js +14 -0
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexStart.js +14 -0
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceAround.js +14 -0
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceBetween.js +14 -0
- package/dist/es/fields/StyleSetter/icons/text-align/Center.js +14 -0
- package/dist/es/fields/StyleSetter/icons/text-align/Left.js +14 -0
- package/dist/es/fields/StyleSetter/icons/text-align/Right.js +14 -0
- package/dist/es/fields/StyleSetter/pro/Background.js +5 -0
- package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +114 -0
- package/dist/es/fields/StyleSetter/pro/Border.js +5 -0
- package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +50 -0
- package/dist/es/fields/StyleSetter/pro/Font.js +5 -0
- package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +98 -0
- package/dist/es/fields/StyleSetter/pro/Layout.js +5 -0
- package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +287 -0
- package/dist/es/fields/StyleSetter/pro/Position.js +5 -0
- package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +95 -0
- package/dist/es/fields/UISelect.js +6 -0
- package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +161 -0
- package/dist/es/hooks/use-code-block-edit.js +54 -0
- package/dist/es/hooks/use-data-source-edit.js +29 -0
- package/dist/es/hooks/use-editor-content-height.js +17 -0
- package/dist/es/hooks/use-filter.js +35 -0
- package/dist/es/hooks/use-float-box.js +76 -0
- package/dist/es/hooks/use-getso.js +28 -0
- package/dist/es/hooks/use-next-float-box-position.js +27 -0
- package/dist/es/hooks/use-node-status.js +28 -0
- package/dist/es/hooks/use-services.js +9 -0
- package/dist/es/hooks/use-stage.js +107 -0
- package/dist/es/hooks/use-window-rect.js +19 -0
- package/dist/es/icons/CenterIcon.js +5 -0
- package/dist/es/icons/CenterIcon.vue_vue_type_script_setup_true_lang.js +40 -0
- package/dist/es/icons/CodeIcon.js +5 -0
- package/dist/es/icons/CodeIcon.vue_vue_type_script_setup_true_lang.js +19 -0
- package/dist/es/icons/FolderMinusIcon.js +5 -0
- package/dist/es/icons/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +27 -0
- package/dist/es/index.js +79 -0
- package/dist/es/initService.js +392 -0
- package/dist/es/layouts/AddPageBox.js +5 -0
- package/dist/es/layouts/AddPageBox.vue_vue_type_script_setup_true_lang.js +38 -0
- package/dist/es/layouts/CodeEditor.js +5 -0
- package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +270 -0
- package/dist/es/layouts/Framework.js +5 -0
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +134 -0
- package/dist/es/layouts/NavMenu.js +5 -0
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +181 -0
- package/dist/es/layouts/page-bar/AddButton.js +5 -0
- package/dist/es/layouts/page-bar/AddButton.vue_vue_type_script_setup_true_lang.js +57 -0
- package/dist/es/layouts/page-bar/PageBar.js +5 -0
- package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +135 -0
- package/dist/es/layouts/page-bar/PageBarScrollContainer.js +5 -0
- package/dist/es/layouts/page-bar/PageBarScrollContainer.vue_vue_type_script_setup_true_lang.js +119 -0
- package/dist/es/layouts/page-bar/PageList.js +5 -0
- package/dist/es/layouts/page-bar/PageList.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/es/layouts/page-bar/Search.js +5 -0
- package/dist/es/layouts/page-bar/Search.vue_vue_type_script_setup_true_lang.js +60 -0
- package/dist/es/layouts/props-panel/FormPanel.js +5 -0
- package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +129 -0
- package/dist/es/layouts/props-panel/PropsPanel.js +5 -0
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +179 -0
- package/dist/es/layouts/props-panel/use-style-panel.js +40 -0
- package/dist/es/layouts/sidebar/ComponentListPanel.js +5 -0
- package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +121 -0
- package/dist/es/layouts/sidebar/Sidebar.js +5 -0
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +314 -0
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.js +5 -0
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +161 -0
- package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.js +5 -0
- package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +113 -0
- package/dist/es/layouts/sidebar/code-block/useContentMenu.js +60 -0
- package/dist/es/layouts/sidebar/data-source/DataSourceAddButton.js +5 -0
- package/dist/es/layouts/sidebar/data-source/DataSourceAddButton.vue_vue_type_script_setup_true_lang.js +44 -0
- package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.js +5 -0
- package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +103 -0
- package/dist/es/layouts/sidebar/data-source/DataSourceList.js +5 -0
- package/dist/es/layouts/sidebar/data-source/DataSourceList.vue_vue_type_script_setup_true_lang.js +162 -0
- package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.js +5 -0
- package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +133 -0
- package/dist/es/layouts/sidebar/data-source/useContentMenu.js +59 -0
- package/dist/es/layouts/sidebar/layer/LayerMenu.js +5 -0
- package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +90 -0
- package/dist/es/layouts/sidebar/layer/LayerNodeTool.js +5 -0
- package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/es/layouts/sidebar/layer/LayerPanel.js +5 -0
- package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +99 -0
- package/dist/es/layouts/sidebar/layer/use-click.js +68 -0
- package/dist/es/layouts/sidebar/layer/use-drag.js +118 -0
- package/dist/es/layouts/sidebar/layer/use-keybinding.js +36 -0
- package/dist/es/layouts/sidebar/layer/use-node-status.js +75 -0
- package/dist/es/layouts/workspace/Breadcrumb.js +5 -0
- package/dist/es/layouts/workspace/Breadcrumb.vue_vue_type_script_setup_true_lang.js +39 -0
- package/dist/es/layouts/workspace/Workspace.js +5 -0
- package/dist/es/layouts/workspace/Workspace.vue_vue_type_script_setup_true_lang.js +43 -0
- package/dist/es/layouts/workspace/viewer/NodeListMenu.js +5 -0
- package/dist/es/layouts/workspace/viewer/NodeListMenu.vue_vue_type_script_setup_true_lang.js +88 -0
- package/dist/es/layouts/workspace/viewer/Stage.js +5 -0
- package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +206 -0
- package/dist/es/layouts/workspace/viewer/StageOverlay.js +5 -0
- package/dist/es/layouts/workspace/viewer/StageOverlay.vue_vue_type_script_setup_true_lang.js +89 -0
- package/dist/es/layouts/workspace/viewer/ViewerMenu.js +5 -0
- package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +132 -0
- package/dist/es/plugin.js +61 -0
- package/dist/es/services/BaseService.js +148 -0
- package/dist/es/services/codeBlock.js +251 -0
- package/dist/es/services/componentList.js +29 -0
- package/dist/es/services/dataSource.js +157 -0
- package/dist/es/services/dep.js +173 -0
- package/dist/es/services/editor.js +752 -0
- package/dist/es/services/events.js +64 -0
- package/dist/es/services/history.js +84 -0
- package/dist/es/services/keybinding.js +182 -0
- package/dist/es/services/props.js +215 -0
- package/dist/es/services/stageOverlay.js +161 -0
- package/dist/es/services/storage.js +127 -0
- package/dist/es/services/ui.js +112 -0
- package/dist/es/style.css +1937 -0
- package/dist/es/type.js +90 -0
- package/dist/es/utils/compose.js +44 -0
- package/dist/es/utils/config.js +8 -0
- package/dist/es/utils/const.js +15 -0
- package/dist/es/utils/content-menu.js +76 -0
- package/dist/es/utils/data-source/formConfigs/base.js +28 -0
- package/dist/es/utils/data-source/formConfigs/http.js +74 -0
- package/dist/es/utils/data-source/index.js +201 -0
- package/dist/es/utils/dep/idle-task.js +76 -0
- package/dist/es/utils/dep/worker.js +19 -0
- package/dist/es/utils/editor.js +261 -0
- package/dist/es/utils/keybinding-config.js +106 -0
- package/dist/es/utils/logger.js +18 -0
- package/dist/es/utils/monaco-editor.js +13 -0
- package/dist/es/utils/operator.js +73 -0
- package/dist/es/utils/props.js +232 -0
- package/dist/es/utils/scroll-viewer.js +115 -0
- package/dist/es/utils/tree.js +11 -0
- package/dist/es/utils/undo-redo.js +43 -0
- package/dist/style.css +10 -10
- package/dist/tmagic-editor.umd.cjs +18427 -21980
- package/package.json +17 -13
- package/src/fields/CodeLink.vue +2 -2
- package/src/fields/DataSourceFieldSelect/Index.vue +10 -2
- package/src/fields/EventSelect.vue +6 -5
- package/src/index.ts +1 -73
- package/src/layouts/CodeEditor.vue +15 -8
- package/src/layouts/Framework.vue +1 -1
- package/src/plugin.ts +92 -0
- package/src/type.ts +6 -7
- package/src/utils/index.ts +1 -0
- package/src/utils/monaco-editor.ts +13 -6
- package/src/utils/props.ts +2 -0
- package/types/index.d.ts +3388 -3342
- package/dist/tmagic-editor.js +0 -17037
|
@@ -0,0 +1,752 @@
|
|
|
1
|
+
import { LayerOffset, Layout } from "../type.js";
|
|
2
|
+
import BaseService_default from "./BaseService.js";
|
|
3
|
+
import props_default from "./props.js";
|
|
4
|
+
import history_default from "./history.js";
|
|
5
|
+
import storage_default, { Protocol } from "./storage.js";
|
|
6
|
+
import { COPY_STORAGE_KEY, Fixed2Other, change2Fixed, fixNodePosition, getInitPositionStyle, getNodeIndex, getPageFragmentList, getPageList, moveItemsInContainer, setChildrenLayout, setLayout } from "../utils/editor.js";
|
|
7
|
+
import { beforePaste, getAddParent } from "../utils/operator.js";
|
|
8
|
+
import { isFixed } from "@tmagic/stage";
|
|
9
|
+
import { calcValueByFontsize, getElById, getNodeInfo, getNodePath, isNumber, isPage, isPageFragment, isPop } from "@tmagic/utils";
|
|
10
|
+
import { NodeType, Target, Watcher } from "@tmagic/core";
|
|
11
|
+
import { reactive, toRaw } from "vue";
|
|
12
|
+
import { cloneDeep, get, isObject, mergeWith, uniq } from "lodash-es";
|
|
13
|
+
//#region packages/editor/src/services/editor.ts
|
|
14
|
+
var canUsePluginMethods = {
|
|
15
|
+
async: [
|
|
16
|
+
"getLayout",
|
|
17
|
+
"highlight",
|
|
18
|
+
"select",
|
|
19
|
+
"multiSelect",
|
|
20
|
+
"doAdd",
|
|
21
|
+
"add",
|
|
22
|
+
"doRemove",
|
|
23
|
+
"remove",
|
|
24
|
+
"doUpdate",
|
|
25
|
+
"update",
|
|
26
|
+
"sort",
|
|
27
|
+
"copy",
|
|
28
|
+
"paste",
|
|
29
|
+
"doPaste",
|
|
30
|
+
"doAlignCenter",
|
|
31
|
+
"alignCenter",
|
|
32
|
+
"moveLayer",
|
|
33
|
+
"moveToContainer",
|
|
34
|
+
"dragTo",
|
|
35
|
+
"undo",
|
|
36
|
+
"redo",
|
|
37
|
+
"move"
|
|
38
|
+
],
|
|
39
|
+
sync: []
|
|
40
|
+
};
|
|
41
|
+
var Editor = class extends BaseService_default {
|
|
42
|
+
state = reactive({
|
|
43
|
+
root: null,
|
|
44
|
+
page: null,
|
|
45
|
+
parent: null,
|
|
46
|
+
node: null,
|
|
47
|
+
nodes: [],
|
|
48
|
+
stage: null,
|
|
49
|
+
stageLoading: true,
|
|
50
|
+
highlightNode: null,
|
|
51
|
+
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
52
|
+
pageLength: 0,
|
|
53
|
+
pageFragmentLength: 0,
|
|
54
|
+
disabledMultiSelect: false
|
|
55
|
+
});
|
|
56
|
+
isHistoryStateChange = false;
|
|
57
|
+
constructor() {
|
|
58
|
+
super(canUsePluginMethods.async.map((methodName) => ({
|
|
59
|
+
name: methodName,
|
|
60
|
+
isAsync: true
|
|
61
|
+
})), [
|
|
62
|
+
"select",
|
|
63
|
+
"update",
|
|
64
|
+
"moveLayer"
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 设置当前指点节点配置
|
|
69
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength
|
|
70
|
+
* @param value MNode
|
|
71
|
+
*/
|
|
72
|
+
set(name, value) {
|
|
73
|
+
const preValue = this.state[name];
|
|
74
|
+
this.state[name] = value;
|
|
75
|
+
if (name === "nodes" && Array.isArray(value)) this.set("node", value[0]);
|
|
76
|
+
if (name === "root") {
|
|
77
|
+
if (Array.isArray(value)) throw new Error("root 不能为数组");
|
|
78
|
+
if (value && isObject(value)) {
|
|
79
|
+
const app = value;
|
|
80
|
+
this.state.pageLength = getPageList(app).length || 0;
|
|
81
|
+
this.state.pageFragmentLength = getPageFragmentList(app).length || 0;
|
|
82
|
+
this.state.stageLoading = this.state.pageLength !== 0;
|
|
83
|
+
} else {
|
|
84
|
+
this.state.pageLength = 0;
|
|
85
|
+
this.state.pageFragmentLength = 0;
|
|
86
|
+
this.state.stageLoading = false;
|
|
87
|
+
}
|
|
88
|
+
this.emit("root-change", value, preValue);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 获取当前指点节点配置
|
|
93
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength'
|
|
94
|
+
* @returns MNode
|
|
95
|
+
*/
|
|
96
|
+
get(name) {
|
|
97
|
+
return this.state[name];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 根据id获取组件、组件的父组件以及组件所属的页面节点
|
|
101
|
+
* @param {number | string} id 组件id
|
|
102
|
+
* @param {boolean} raw 是否使用toRaw
|
|
103
|
+
* @returns {EditorNodeInfo}
|
|
104
|
+
*/
|
|
105
|
+
getNodeInfo(id, raw = true) {
|
|
106
|
+
let root = this.get("root");
|
|
107
|
+
if (raw) root = toRaw(root);
|
|
108
|
+
return getNodeInfo(id, root);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 根据ID获取指点节点配置
|
|
112
|
+
* @param id 组件ID
|
|
113
|
+
* @param {boolean} raw 是否使用toRaw
|
|
114
|
+
* @returns 组件节点配置
|
|
115
|
+
*/
|
|
116
|
+
getNodeById(id, raw = true) {
|
|
117
|
+
const { node } = this.getNodeInfo(id, raw);
|
|
118
|
+
return node;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 根据ID获取指点节点的父节点配置
|
|
122
|
+
* @param id 组件ID
|
|
123
|
+
* @param {boolean} raw 是否使用toRaw
|
|
124
|
+
* @returns 指点组件的父节点配置
|
|
125
|
+
*/
|
|
126
|
+
getParentById(id, raw = true) {
|
|
127
|
+
const { parent } = this.getNodeInfo(id, raw);
|
|
128
|
+
return parent;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* 只有容器拥有布局
|
|
132
|
+
*/
|
|
133
|
+
async getLayout(parent, node) {
|
|
134
|
+
if (node && typeof node !== "function" && isFixed(node.style || {})) return Layout.FIXED;
|
|
135
|
+
if (parent.layout) return parent.layout;
|
|
136
|
+
if (!parent.style?.position) return Layout.RELATIVE;
|
|
137
|
+
return Layout.ABSOLUTE;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 选中指定节点(将指定节点设置成当前选中状态)
|
|
141
|
+
* @param config 指定节点配置或者ID
|
|
142
|
+
* @returns 当前选中的节点配置
|
|
143
|
+
*/
|
|
144
|
+
async select(config) {
|
|
145
|
+
const { node, page, parent } = this.selectedConfigExceptionHandler(config);
|
|
146
|
+
this.set("nodes", node ? [node] : []);
|
|
147
|
+
this.set("page", page);
|
|
148
|
+
this.set("parent", parent);
|
|
149
|
+
if (page) history_default.changePage(toRaw(page));
|
|
150
|
+
else history_default.resetState();
|
|
151
|
+
if (node?.id) this.get("stage")?.renderer?.runtime?.getApp?.()?.page?.emit("editor:select", {
|
|
152
|
+
node,
|
|
153
|
+
page,
|
|
154
|
+
parent
|
|
155
|
+
}, getNodePath(node.id, this.get("root")?.items));
|
|
156
|
+
this.emit("select", node);
|
|
157
|
+
return node;
|
|
158
|
+
}
|
|
159
|
+
async selectNextNode() {
|
|
160
|
+
const node = toRaw(this.get("node"));
|
|
161
|
+
if (!node || isPage(node) || node.type === NodeType.ROOT) return node;
|
|
162
|
+
const parent = toRaw(this.getParentById(node.id));
|
|
163
|
+
if (!parent) return node;
|
|
164
|
+
const index = getNodeIndex(node.id, parent);
|
|
165
|
+
const nextNode = parent.items[index + 1] || parent.items[0];
|
|
166
|
+
await this.select(nextNode);
|
|
167
|
+
this.get("stage")?.select(nextNode.id);
|
|
168
|
+
return nextNode;
|
|
169
|
+
}
|
|
170
|
+
async selectNextPage() {
|
|
171
|
+
const root = toRaw(this.get("root"));
|
|
172
|
+
const page = toRaw(this.get("page"));
|
|
173
|
+
if (!page) throw new Error("page不能为空");
|
|
174
|
+
if (!root) throw new Error("root不能为空");
|
|
175
|
+
const index = getNodeIndex(page.id, root);
|
|
176
|
+
const nextPage = root.items[index + 1] || root.items[0];
|
|
177
|
+
await this.select(nextPage);
|
|
178
|
+
this.get("stage")?.select(nextPage.id);
|
|
179
|
+
return nextPage;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* 高亮指定节点
|
|
183
|
+
* @param config 指定节点配置或者ID
|
|
184
|
+
* @returns 当前高亮的节点配置
|
|
185
|
+
*/
|
|
186
|
+
highlight(config) {
|
|
187
|
+
const { node } = this.selectedConfigExceptionHandler(config);
|
|
188
|
+
if (this.get("highlightNode") === node) return;
|
|
189
|
+
this.set("highlightNode", node);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* 多选
|
|
193
|
+
* @param ids 指定节点ID
|
|
194
|
+
* @returns 加入多选的节点配置
|
|
195
|
+
*/
|
|
196
|
+
multiSelect(ids) {
|
|
197
|
+
const nodes = [];
|
|
198
|
+
uniq(ids).forEach((id) => {
|
|
199
|
+
const { node } = this.getNodeInfo(id);
|
|
200
|
+
if (!node) return;
|
|
201
|
+
nodes.push(node);
|
|
202
|
+
});
|
|
203
|
+
this.set("nodes", nodes);
|
|
204
|
+
}
|
|
205
|
+
selectRoot() {
|
|
206
|
+
const root = this.get("root");
|
|
207
|
+
if (!root) return;
|
|
208
|
+
this.set("nodes", [root]);
|
|
209
|
+
this.set("parent", null);
|
|
210
|
+
this.set("page", null);
|
|
211
|
+
this.set("stage", null);
|
|
212
|
+
this.set("highlightNode", null);
|
|
213
|
+
}
|
|
214
|
+
async doAdd(node, parent) {
|
|
215
|
+
const root = this.get("root");
|
|
216
|
+
if (!root) throw new Error("root为空");
|
|
217
|
+
const curNode = this.get("node");
|
|
218
|
+
const stage = this.get("stage");
|
|
219
|
+
if (!curNode) throw new Error("当前选中节点为空");
|
|
220
|
+
if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && !(isPage(node) || isPageFragment(node))) throw new Error("app下不能添加组件");
|
|
221
|
+
if (parent.id !== curNode.id && !(isPage(node) || isPageFragment(node))) {
|
|
222
|
+
const index = parent.items.indexOf(curNode);
|
|
223
|
+
parent.items?.splice(index + 1, 0, node);
|
|
224
|
+
} else parent.items?.push(node);
|
|
225
|
+
const layout = await this.getLayout(toRaw(parent), node);
|
|
226
|
+
node.style = getInitPositionStyle(node.style, layout);
|
|
227
|
+
await stage?.add({
|
|
228
|
+
config: cloneDeep(node),
|
|
229
|
+
parent: cloneDeep(parent),
|
|
230
|
+
parentId: parent.id,
|
|
231
|
+
root: cloneDeep(root)
|
|
232
|
+
});
|
|
233
|
+
const newStyle = fixNodePosition(node, parent, stage);
|
|
234
|
+
if (newStyle && (newStyle.top !== node.style.top || newStyle.left !== node.style.left)) {
|
|
235
|
+
node.style = newStyle;
|
|
236
|
+
await stage?.update({
|
|
237
|
+
config: cloneDeep(node),
|
|
238
|
+
parentId: parent.id,
|
|
239
|
+
root: cloneDeep(root)
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
this.addModifiedNodeId(node.id);
|
|
243
|
+
return node;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* 向指点容器添加组件节点
|
|
247
|
+
* @param addConfig 将要添加的组件节点配置
|
|
248
|
+
* @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
|
|
249
|
+
* @returns 添加后的节点
|
|
250
|
+
*/
|
|
251
|
+
async add(addNode, parent) {
|
|
252
|
+
const stage = this.get("stage");
|
|
253
|
+
const addNodes = [];
|
|
254
|
+
if (!Array.isArray(addNode)) {
|
|
255
|
+
const { type, inputEvent, ...config } = addNode;
|
|
256
|
+
if (!type) throw new Error("组件类型不能为空");
|
|
257
|
+
addNodes.push({ ...toRaw(await props_default.getPropsValue(type, config)) });
|
|
258
|
+
} else addNodes.push(...addNode);
|
|
259
|
+
const newNodes = await Promise.all(addNodes.map((node) => {
|
|
260
|
+
const root = this.get("root");
|
|
261
|
+
if ((isPage(node) || isPageFragment(node)) && root) return this.doAdd(node, root);
|
|
262
|
+
const parentNode = parent && typeof parent !== "function" ? parent : getAddParent(node);
|
|
263
|
+
if (!parentNode) throw new Error("未找到父元素");
|
|
264
|
+
return this.doAdd(node, parentNode);
|
|
265
|
+
}));
|
|
266
|
+
if (newNodes.length > 1) {
|
|
267
|
+
const newNodeIds = newNodes.map((node) => node.id);
|
|
268
|
+
stage?.multiSelect(newNodeIds);
|
|
269
|
+
await this.multiSelect(newNodeIds);
|
|
270
|
+
} else {
|
|
271
|
+
await this.select(newNodes[0]);
|
|
272
|
+
if (isPage(newNodes[0])) this.state.pageLength += 1;
|
|
273
|
+
else if (isPageFragment(newNodes[0])) this.state.pageFragmentLength += 1;
|
|
274
|
+
else stage?.select(newNodes[0].id);
|
|
275
|
+
}
|
|
276
|
+
if (!(isPage(newNodes[0]) || isPageFragment(newNodes[0]))) this.pushHistoryState();
|
|
277
|
+
this.emit("add", newNodes);
|
|
278
|
+
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
279
|
+
}
|
|
280
|
+
async doRemove(node) {
|
|
281
|
+
const root = this.get("root");
|
|
282
|
+
if (!root) throw new Error("root不能为空");
|
|
283
|
+
const { parent, node: curNode } = this.getNodeInfo(node.id, false);
|
|
284
|
+
if (!parent || !curNode) throw new Error("找不要删除的节点");
|
|
285
|
+
const index = getNodeIndex(curNode.id, parent);
|
|
286
|
+
if (typeof index !== "number" || index === -1) throw new Error("找不要删除的节点");
|
|
287
|
+
parent.items?.splice(index, 1);
|
|
288
|
+
const stage = this.get("stage");
|
|
289
|
+
stage?.remove({
|
|
290
|
+
id: node.id,
|
|
291
|
+
parentId: parent.id,
|
|
292
|
+
root: cloneDeep(root)
|
|
293
|
+
});
|
|
294
|
+
const selectDefault = async (pages) => {
|
|
295
|
+
if (pages[0]) {
|
|
296
|
+
await this.select(pages[0]);
|
|
297
|
+
stage?.select(pages[0].id);
|
|
298
|
+
} else {
|
|
299
|
+
this.selectRoot();
|
|
300
|
+
history_default.resetPage();
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
const rootItems = root.items || [];
|
|
304
|
+
if (isPage(node)) {
|
|
305
|
+
this.state.pageLength -= 1;
|
|
306
|
+
await selectDefault(rootItems);
|
|
307
|
+
} else if (isPageFragment(node)) {
|
|
308
|
+
this.state.pageFragmentLength -= 1;
|
|
309
|
+
await selectDefault(rootItems);
|
|
310
|
+
} else {
|
|
311
|
+
await this.select(parent);
|
|
312
|
+
stage?.select(parent.id);
|
|
313
|
+
this.addModifiedNodeId(parent.id);
|
|
314
|
+
}
|
|
315
|
+
if (!rootItems.length) {
|
|
316
|
+
this.resetModifiedNodeId();
|
|
317
|
+
history_default.reset();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* 删除组件
|
|
322
|
+
* @param {Object} node
|
|
323
|
+
*/
|
|
324
|
+
async remove(nodeOrNodeList) {
|
|
325
|
+
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
326
|
+
await Promise.all(nodes.map((node) => this.doRemove(node)));
|
|
327
|
+
if (!(isPage(nodes[0]) || isPageFragment(nodes[0]))) this.pushHistoryState();
|
|
328
|
+
this.emit("remove", nodes);
|
|
329
|
+
}
|
|
330
|
+
async doUpdate(config, { changeRecords = [] } = {}) {
|
|
331
|
+
const root = this.get("root");
|
|
332
|
+
if (!root) throw new Error("root为空");
|
|
333
|
+
if (!config?.id) throw new Error("没有配置或者配置缺少id值");
|
|
334
|
+
const info = this.getNodeInfo(config.id, false);
|
|
335
|
+
if (!info.node) throw new Error(`获取不到id为${config.id}的节点`);
|
|
336
|
+
const node = toRaw(info.node);
|
|
337
|
+
let newConfig = await this.toggleFixedPosition(toRaw(config), node, root);
|
|
338
|
+
newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue, key, object, source) => {
|
|
339
|
+
if (typeof srcValue === "undefined" && Object.hasOwn(source, key)) return "";
|
|
340
|
+
if (isObject(srcValue) && Array.isArray(objValue)) return srcValue;
|
|
341
|
+
if (Array.isArray(srcValue)) return srcValue;
|
|
342
|
+
});
|
|
343
|
+
if (!newConfig.type) throw new Error("配置缺少type值");
|
|
344
|
+
if (newConfig.type === NodeType.ROOT) {
|
|
345
|
+
this.set("root", newConfig);
|
|
346
|
+
return {
|
|
347
|
+
oldNode: node,
|
|
348
|
+
newNode: newConfig,
|
|
349
|
+
changeRecords
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const { parent } = info;
|
|
353
|
+
if (!parent) throw new Error("获取不到父级节点");
|
|
354
|
+
const parentNodeItems = parent.items;
|
|
355
|
+
const index = getNodeIndex(newConfig.id, parent);
|
|
356
|
+
if (!parentNodeItems || typeof index === "undefined" || index === -1) throw new Error("更新的节点未找到");
|
|
357
|
+
const newLayout = await this.getLayout(newConfig);
|
|
358
|
+
const layout = await this.getLayout(node);
|
|
359
|
+
if (Array.isArray(newConfig.items) && newLayout !== layout) newConfig = setChildrenLayout(newConfig, newLayout);
|
|
360
|
+
parentNodeItems[index] = newConfig;
|
|
361
|
+
const nodes = this.get("nodes");
|
|
362
|
+
const targetIndex = nodes.findIndex((nodeItem) => `${nodeItem.id}` === `${newConfig.id}`);
|
|
363
|
+
nodes.splice(targetIndex, 1, newConfig);
|
|
364
|
+
this.set("nodes", [...nodes]);
|
|
365
|
+
if (isPage(newConfig) || isPageFragment(newConfig)) this.set("page", newConfig);
|
|
366
|
+
this.addModifiedNodeId(newConfig.id);
|
|
367
|
+
return {
|
|
368
|
+
oldNode: node,
|
|
369
|
+
newNode: newConfig,
|
|
370
|
+
changeRecords
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* 更新节点
|
|
375
|
+
* update后会触发依赖收集,收集完后会掉stage.update方法
|
|
376
|
+
* @param config 新的节点配置,配置中需要有id信息
|
|
377
|
+
* @returns 更新后的节点配置
|
|
378
|
+
*/
|
|
379
|
+
async update(config, data = {}) {
|
|
380
|
+
const nodes = Array.isArray(config) ? config : [config];
|
|
381
|
+
const updateData = await Promise.all(nodes.map((node) => this.doUpdate(node, data)));
|
|
382
|
+
if (updateData[0].oldNode?.type !== NodeType.ROOT) this.pushHistoryState();
|
|
383
|
+
this.emit("update", updateData);
|
|
384
|
+
return Array.isArray(config) ? updateData.map((item) => item.newNode) : updateData[0].newNode;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* 将id为id1的组件移动到id为id2的组件位置上,例如:[1,2,3,4] -> sort(1,3) -> [2,1,3,4]
|
|
388
|
+
* @param id1 组件ID
|
|
389
|
+
* @param id2 组件ID
|
|
390
|
+
* @returns void
|
|
391
|
+
*/
|
|
392
|
+
async sort(id1, id2) {
|
|
393
|
+
const root = this.get("root");
|
|
394
|
+
if (!root) throw new Error("root为空");
|
|
395
|
+
const node = this.get("node");
|
|
396
|
+
if (!node) throw new Error("当前节点为空");
|
|
397
|
+
const parent = cloneDeep(toRaw(this.get("parent")));
|
|
398
|
+
if (!parent) throw new Error("父节点为空");
|
|
399
|
+
const index2 = parent.items.findIndex((node) => `${node.id}` === `${id2}`);
|
|
400
|
+
if (index2 < 0) return;
|
|
401
|
+
const index1 = parent.items.findIndex((node) => `${node.id}` === `${id1}`);
|
|
402
|
+
parent.items.splice(index2, 0, ...parent.items.splice(index1, 1));
|
|
403
|
+
await this.update(parent);
|
|
404
|
+
await this.select(node);
|
|
405
|
+
this.get("stage")?.update({
|
|
406
|
+
config: cloneDeep(node),
|
|
407
|
+
parentId: parent.id,
|
|
408
|
+
root: cloneDeep(root)
|
|
409
|
+
});
|
|
410
|
+
this.addModifiedNodeId(parent.id);
|
|
411
|
+
this.pushHistoryState();
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* 将组件节点配置存储到localStorage中
|
|
415
|
+
* @param config 组件节点配置
|
|
416
|
+
* @returns
|
|
417
|
+
*/
|
|
418
|
+
copy(config) {
|
|
419
|
+
storage_default.setItem(COPY_STORAGE_KEY, Array.isArray(config) ? config : [config], { protocol: Protocol.OBJECT });
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* 复制时会带上组件关联的依赖
|
|
423
|
+
* @param config 组件节点配置
|
|
424
|
+
* @returns
|
|
425
|
+
*/
|
|
426
|
+
copyWithRelated(config, collectorOptions) {
|
|
427
|
+
const copyNodes = Array.isArray(config) ? config : [config];
|
|
428
|
+
if (collectorOptions && typeof collectorOptions.isTarget === "function") {
|
|
429
|
+
const customTarget = new Target({ ...collectorOptions });
|
|
430
|
+
const coperWatcher = new Watcher();
|
|
431
|
+
coperWatcher.addTarget(customTarget);
|
|
432
|
+
coperWatcher.collect(copyNodes, {}, true, collectorOptions.type);
|
|
433
|
+
Object.keys(customTarget.deps).forEach((nodeId) => {
|
|
434
|
+
const node = this.getNodeById(nodeId);
|
|
435
|
+
if (!node) return;
|
|
436
|
+
customTarget.deps[nodeId].keys.forEach((key) => {
|
|
437
|
+
const relateNodeId = get(node, key);
|
|
438
|
+
if (!copyNodes.find((node) => node.id === relateNodeId)) {
|
|
439
|
+
const relateNode = this.getNodeById(relateNodeId);
|
|
440
|
+
if (relateNode) copyNodes.push(relateNode);
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
storage_default.setItem(COPY_STORAGE_KEY, copyNodes, { protocol: Protocol.OBJECT });
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* 从localStorage中获取节点,然后添加到当前容器中
|
|
449
|
+
* @param position 粘贴的坐标
|
|
450
|
+
* @returns 添加后的组件节点配置
|
|
451
|
+
*/
|
|
452
|
+
async paste(position = {}, collectorOptions) {
|
|
453
|
+
const config = storage_default.getItem(COPY_STORAGE_KEY);
|
|
454
|
+
if (!Array.isArray(config)) return;
|
|
455
|
+
const node = this.get("node");
|
|
456
|
+
let parent = null;
|
|
457
|
+
if (config.length === 1 && config[0].id === node?.id) {
|
|
458
|
+
parent = this.get("parent");
|
|
459
|
+
if (parent?.type === NodeType.ROOT) parent = this.get("page");
|
|
460
|
+
}
|
|
461
|
+
const pasteConfigs = await this.doPaste(config, position);
|
|
462
|
+
if (collectorOptions && typeof collectorOptions.isTarget === "function") props_default.replaceRelateId(config, pasteConfigs, collectorOptions);
|
|
463
|
+
return this.add(pasteConfigs, parent);
|
|
464
|
+
}
|
|
465
|
+
async doPaste(config, position = {}) {
|
|
466
|
+
props_default.clearRelateId();
|
|
467
|
+
const doc = this.get("stage")?.renderer?.contentWindow?.document;
|
|
468
|
+
return beforePaste(position, cloneDeep(config), doc);
|
|
469
|
+
}
|
|
470
|
+
async doAlignCenter(config) {
|
|
471
|
+
const parent = this.getParentById(config.id);
|
|
472
|
+
if (!parent) throw new Error("找不到父节点");
|
|
473
|
+
const node = cloneDeep(toRaw(config));
|
|
474
|
+
const layout = await this.getLayout(parent, node);
|
|
475
|
+
if (layout === Layout.RELATIVE) return config;
|
|
476
|
+
if (!node.style) return config;
|
|
477
|
+
const doc = this.get("stage")?.renderer?.contentWindow?.document;
|
|
478
|
+
if (doc) {
|
|
479
|
+
const el = getElById()(doc, node.id);
|
|
480
|
+
const parentEl = layout === Layout.FIXED ? doc.body : el?.offsetParent;
|
|
481
|
+
if (parentEl && el) {
|
|
482
|
+
node.style.left = calcValueByFontsize(doc, (parentEl.clientWidth - el.clientWidth) / 2);
|
|
483
|
+
node.style.right = "";
|
|
484
|
+
}
|
|
485
|
+
} else if (parent.style && isNumber(parent.style?.width) && isNumber(node.style?.width)) {
|
|
486
|
+
node.style.left = (parent.style.width - node.style.width) / 2;
|
|
487
|
+
node.style.right = "";
|
|
488
|
+
}
|
|
489
|
+
return node;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* 将指点节点设置居中
|
|
493
|
+
* @param config 组件节点配置
|
|
494
|
+
* @returns 当前组件节点配置
|
|
495
|
+
*/
|
|
496
|
+
async alignCenter(config) {
|
|
497
|
+
const nodes = Array.isArray(config) ? config : [config];
|
|
498
|
+
const stage = this.get("stage");
|
|
499
|
+
const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
|
|
500
|
+
const newNode = await this.update(newNodes);
|
|
501
|
+
if (newNodes.length > 1) await stage?.multiSelect(newNodes.map((node) => node.id));
|
|
502
|
+
else await stage?.select(newNodes[0].id);
|
|
503
|
+
return newNode;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* 移动当前选中节点位置
|
|
507
|
+
* @param offset 偏移量
|
|
508
|
+
*/
|
|
509
|
+
async moveLayer(offset) {
|
|
510
|
+
const root = this.get("root");
|
|
511
|
+
if (!root) throw new Error("root为空");
|
|
512
|
+
const parent = this.get("parent");
|
|
513
|
+
if (!parent) throw new Error("父节点为空");
|
|
514
|
+
const node = this.get("node");
|
|
515
|
+
if (!node) throw new Error("当前节点为空");
|
|
516
|
+
const brothers = parent.items || [];
|
|
517
|
+
const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
|
|
518
|
+
const isRelative = await this.getLayout(parent, node) === Layout.RELATIVE;
|
|
519
|
+
let offsetIndex;
|
|
520
|
+
if (offset === LayerOffset.TOP) offsetIndex = isRelative ? 0 : brothers.length;
|
|
521
|
+
else if (offset === LayerOffset.BOTTOM) offsetIndex = isRelative ? brothers.length : 0;
|
|
522
|
+
else offsetIndex = index + (isRelative ? -offset : offset);
|
|
523
|
+
if (offsetIndex > 0 && offsetIndex > brothers.length || offsetIndex < 0) return;
|
|
524
|
+
brothers.splice(index, 1);
|
|
525
|
+
brothers.splice(offsetIndex, 0, node);
|
|
526
|
+
const grandparent = this.getParentById(parent.id);
|
|
527
|
+
this.get("stage")?.update({
|
|
528
|
+
config: cloneDeep(toRaw(parent)),
|
|
529
|
+
parentId: grandparent?.id,
|
|
530
|
+
root: cloneDeep(root)
|
|
531
|
+
});
|
|
532
|
+
this.addModifiedNodeId(parent.id);
|
|
533
|
+
this.pushHistoryState();
|
|
534
|
+
this.emit("move-layer", offset);
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* 移动到指定容器中
|
|
538
|
+
* @param config 需要移动的节点
|
|
539
|
+
* @param targetId 容器ID
|
|
540
|
+
*/
|
|
541
|
+
async moveToContainer(config, targetId) {
|
|
542
|
+
const root = this.get("root");
|
|
543
|
+
const { node, parent } = this.getNodeInfo(config.id, false);
|
|
544
|
+
const target = this.getNodeById(targetId, false);
|
|
545
|
+
const stage = this.get("stage");
|
|
546
|
+
if (root && node && parent && stage) {
|
|
547
|
+
const index = getNodeIndex(node.id, parent);
|
|
548
|
+
parent.items?.splice(index, 1);
|
|
549
|
+
await stage.remove({
|
|
550
|
+
id: node.id,
|
|
551
|
+
parentId: parent.id,
|
|
552
|
+
root: cloneDeep(root)
|
|
553
|
+
});
|
|
554
|
+
const layout = await this.getLayout(target);
|
|
555
|
+
const newConfig = mergeWith(cloneDeep(node), config, (_objValue, srcValue) => {
|
|
556
|
+
if (Array.isArray(srcValue)) return srcValue;
|
|
557
|
+
});
|
|
558
|
+
newConfig.style = getInitPositionStyle(newConfig.style, layout);
|
|
559
|
+
target.items.push(newConfig);
|
|
560
|
+
await stage.select(targetId);
|
|
561
|
+
const targetParent = this.getParentById(target.id);
|
|
562
|
+
await stage.update({
|
|
563
|
+
config: cloneDeep(target),
|
|
564
|
+
parentId: targetParent?.id,
|
|
565
|
+
root: cloneDeep(root)
|
|
566
|
+
});
|
|
567
|
+
await this.select(newConfig);
|
|
568
|
+
stage.select(newConfig.id);
|
|
569
|
+
this.addModifiedNodeId(target.id);
|
|
570
|
+
this.addModifiedNodeId(parent.id);
|
|
571
|
+
this.pushHistoryState();
|
|
572
|
+
return newConfig;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
async dragTo(config, targetParent, targetIndex) {
|
|
576
|
+
if (!targetParent || !Array.isArray(targetParent.items)) return;
|
|
577
|
+
const configs = Array.isArray(config) ? config : [config];
|
|
578
|
+
const sourceIndicesInTargetParent = [];
|
|
579
|
+
const sourceOutTargetParent = [];
|
|
580
|
+
const newLayout = await this.getLayout(targetParent);
|
|
581
|
+
forConfigs: for (const config of configs) {
|
|
582
|
+
const { parent, node: curNode } = this.getNodeInfo(config.id, false);
|
|
583
|
+
if (!parent || !curNode) continue;
|
|
584
|
+
const path = getNodePath(curNode.id, parent.items);
|
|
585
|
+
for (const node of path) if (targetParent.id === node.id) continue forConfigs;
|
|
586
|
+
const index = getNodeIndex(curNode.id, parent);
|
|
587
|
+
if (parent.id === targetParent.id) {
|
|
588
|
+
if (typeof index !== "number" || index === -1) return;
|
|
589
|
+
sourceIndicesInTargetParent.push(index);
|
|
590
|
+
} else {
|
|
591
|
+
if (newLayout !== await this.getLayout(parent)) setLayout(config, newLayout);
|
|
592
|
+
parent.items?.splice(index, 1);
|
|
593
|
+
sourceOutTargetParent.push(config);
|
|
594
|
+
this.addModifiedNodeId(parent.id);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
moveItemsInContainer(sourceIndicesInTargetParent, targetParent, targetIndex);
|
|
598
|
+
sourceOutTargetParent.forEach((config, index) => {
|
|
599
|
+
targetParent.items?.splice(targetIndex + index, 0, config);
|
|
600
|
+
this.addModifiedNodeId(config.id);
|
|
601
|
+
});
|
|
602
|
+
const page = this.get("page");
|
|
603
|
+
const root = this.get("root");
|
|
604
|
+
const stage = this.get("stage");
|
|
605
|
+
if (stage && page && root) stage.update({
|
|
606
|
+
config: cloneDeep(page),
|
|
607
|
+
parentId: root.id,
|
|
608
|
+
root: cloneDeep(root)
|
|
609
|
+
});
|
|
610
|
+
this.pushHistoryState();
|
|
611
|
+
this.emit("drag-to", {
|
|
612
|
+
targetIndex,
|
|
613
|
+
configs,
|
|
614
|
+
targetParent
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* 撤销当前操作
|
|
619
|
+
* @returns 上一次数据
|
|
620
|
+
*/
|
|
621
|
+
async undo() {
|
|
622
|
+
const value = history_default.undo();
|
|
623
|
+
await this.changeHistoryState(value);
|
|
624
|
+
return value;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* 恢复到下一步
|
|
628
|
+
* @returns 下一步数据
|
|
629
|
+
*/
|
|
630
|
+
async redo() {
|
|
631
|
+
const value = history_default.redo();
|
|
632
|
+
await this.changeHistoryState(value);
|
|
633
|
+
return value;
|
|
634
|
+
}
|
|
635
|
+
async move(left, top) {
|
|
636
|
+
const node = toRaw(this.get("node"));
|
|
637
|
+
if (!node || isPage(node)) return;
|
|
638
|
+
const { style, id, type } = node;
|
|
639
|
+
if (!style || !["absolute", "fixed"].includes(style.position)) return;
|
|
640
|
+
const update = (style) => this.update({
|
|
641
|
+
id,
|
|
642
|
+
type,
|
|
643
|
+
style
|
|
644
|
+
});
|
|
645
|
+
if (top) {
|
|
646
|
+
if (isNumber(style.top)) update({
|
|
647
|
+
...style,
|
|
648
|
+
top: Number(style.top) + Number(top),
|
|
649
|
+
bottom: ""
|
|
650
|
+
});
|
|
651
|
+
else if (isNumber(style.bottom)) update({
|
|
652
|
+
...style,
|
|
653
|
+
bottom: Number(style.bottom) - Number(top),
|
|
654
|
+
top: ""
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
if (left) {
|
|
658
|
+
if (isNumber(style.left)) update({
|
|
659
|
+
...style,
|
|
660
|
+
left: Number(style.left) + Number(left),
|
|
661
|
+
right: ""
|
|
662
|
+
});
|
|
663
|
+
else if (isNumber(style.right)) update({
|
|
664
|
+
...style,
|
|
665
|
+
right: Number(style.right) - Number(left),
|
|
666
|
+
left: ""
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
resetState() {
|
|
671
|
+
this.set("root", null);
|
|
672
|
+
this.set("node", null);
|
|
673
|
+
this.set("nodes", []);
|
|
674
|
+
this.set("page", null);
|
|
675
|
+
this.set("parent", null);
|
|
676
|
+
this.set("stage", null);
|
|
677
|
+
this.set("highlightNode", null);
|
|
678
|
+
this.set("modifiedNodeIds", /* @__PURE__ */ new Map());
|
|
679
|
+
this.set("pageLength", 0);
|
|
680
|
+
}
|
|
681
|
+
destroy() {
|
|
682
|
+
this.removeAllListeners();
|
|
683
|
+
this.resetState();
|
|
684
|
+
this.removeAllPlugins();
|
|
685
|
+
}
|
|
686
|
+
resetModifiedNodeId() {
|
|
687
|
+
this.get("modifiedNodeIds").clear();
|
|
688
|
+
}
|
|
689
|
+
usePlugin(options) {
|
|
690
|
+
super.usePlugin(options);
|
|
691
|
+
}
|
|
692
|
+
on(eventName, listener) {
|
|
693
|
+
return super.on(eventName, listener);
|
|
694
|
+
}
|
|
695
|
+
once(eventName, listener) {
|
|
696
|
+
return super.once(eventName, listener);
|
|
697
|
+
}
|
|
698
|
+
emit(eventName, ...args) {
|
|
699
|
+
return super.emit(eventName, ...args);
|
|
700
|
+
}
|
|
701
|
+
addModifiedNodeId(id) {
|
|
702
|
+
if (!this.isHistoryStateChange) this.get("modifiedNodeIds").set(id, id);
|
|
703
|
+
}
|
|
704
|
+
pushHistoryState() {
|
|
705
|
+
const curNode = cloneDeep(toRaw(this.get("node")));
|
|
706
|
+
const page = this.get("page");
|
|
707
|
+
if (!this.isHistoryStateChange && curNode && page) history_default.push({
|
|
708
|
+
data: cloneDeep(toRaw(page)),
|
|
709
|
+
modifiedNodeIds: this.get("modifiedNodeIds"),
|
|
710
|
+
nodeId: curNode.id
|
|
711
|
+
});
|
|
712
|
+
this.isHistoryStateChange = false;
|
|
713
|
+
}
|
|
714
|
+
async changeHistoryState(value) {
|
|
715
|
+
if (!value) return;
|
|
716
|
+
this.isHistoryStateChange = true;
|
|
717
|
+
await this.update(value.data);
|
|
718
|
+
this.set("modifiedNodeIds", value.modifiedNodeIds);
|
|
719
|
+
setTimeout(() => {
|
|
720
|
+
if (!value.nodeId) return;
|
|
721
|
+
this.select(value.nodeId).then(() => {
|
|
722
|
+
this.get("stage")?.select(value.nodeId);
|
|
723
|
+
});
|
|
724
|
+
}, 0);
|
|
725
|
+
this.emit("history-change", value.data);
|
|
726
|
+
}
|
|
727
|
+
async toggleFixedPosition(dist, src, root) {
|
|
728
|
+
const newConfig = cloneDeep(dist);
|
|
729
|
+
if (!isPop(src) && newConfig.style?.position) {
|
|
730
|
+
if (isFixed(newConfig.style) && !isFixed(src.style || {})) newConfig.style = change2Fixed(newConfig, root);
|
|
731
|
+
else if (!isFixed(newConfig.style) && isFixed(src.style || {})) newConfig.style = await Fixed2Other(newConfig, root, this.getLayout);
|
|
732
|
+
}
|
|
733
|
+
return newConfig;
|
|
734
|
+
}
|
|
735
|
+
selectedConfigExceptionHandler(config) {
|
|
736
|
+
let id;
|
|
737
|
+
if (typeof config === "string" || typeof config === "number") id = config;
|
|
738
|
+
else id = config.id;
|
|
739
|
+
if (!id) throw new Error("没有ID,无法选中");
|
|
740
|
+
const { node, parent, page } = this.getNodeInfo(id);
|
|
741
|
+
if (!node) throw new Error("获取不到组件信息");
|
|
742
|
+
if (node.id === this.state.root?.id) throw new Error("不能选根节点");
|
|
743
|
+
return {
|
|
744
|
+
node,
|
|
745
|
+
parent,
|
|
746
|
+
page
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
var editor_default = new Editor();
|
|
751
|
+
//#endregion
|
|
752
|
+
export { editor_default as default };
|