@tmagic/editor 1.8.0-beta.2 → 1.8.0-beta.21
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 +43 -9
- package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +8 -4
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +22 -98
- package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +32 -9
- package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +68 -17
- 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 +1 -1
- package/dist/es/components/ScrollBar.js +0 -1
- package/dist/es/components/ScrollBar.vue_vue_type_script_setup_true_lang.js +1 -1
- 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 +7 -7
- 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 +58 -0
- package/dist/es/editorProps.js +9 -1
- package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +16 -5
- package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +81 -44
- package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +10 -3
- 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 +13 -6
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +11 -8
- package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +39 -12
- package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +11 -20
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +11 -6
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +30 -14
- package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +11 -4
- package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +38 -6
- package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +156 -155
- package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/PageFragmentSelect.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +8 -10
- package/dist/es/fields/StyleSetter/components/BackgroundPosition.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +28 -6
- package/dist/es/fields/StyleSetter/components/Box.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/Center.js +31 -0
- package/dist/es/fields/StyleSetter/icons/align-items/FlexEnd.js +31 -0
- package/dist/es/fields/StyleSetter/icons/align-items/FlexStart.js +31 -0
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceAround.js +50 -0
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceBetween.js +50 -0
- package/dist/es/fields/StyleSetter/icons/background-repeat/NoRepeat.js +7 -7
- package/dist/es/fields/StyleSetter/icons/background-repeat/Repeat.js +6 -3
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatX.js +29 -6
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatY.js +32 -6
- 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 +11 -3
- package/dist/es/fields/StyleSetter/icons/flex-direction/ColumnReverse.js +11 -3
- package/dist/es/fields/StyleSetter/icons/flex-direction/Row.js +11 -3
- package/dist/es/fields/StyleSetter/icons/flex-direction/RowReverse.js +11 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/Center.js +17 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexEnd.js +19 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexStart.js +19 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceAround.js +37 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceBetween.js +33 -3
- 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 +56 -30
- package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +7 -4
- package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +35 -26
- package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +76 -48
- package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +29 -23
- package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +7 -4
- package/dist/es/fields/UISelect.js +0 -1
- package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/hooks/use-code-block-edit.js +6 -3
- package/dist/es/hooks/use-compare-form.js +119 -0
- package/dist/es/hooks/use-data-source-edit.js +5 -2
- package/dist/es/hooks/use-stage.js +9 -4
- 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 +17 -0
- package/dist/es/icons/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/index.js +24 -10
- package/dist/es/initService.js +19 -13
- 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 +24 -12
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +25 -18
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +4 -4
- 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 +25 -38
- package/dist/es/layouts/history-list/BucketTab.js +5 -0
- package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +62 -0
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +177 -88
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +139 -37
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +164 -107
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +44 -9
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +49 -53
- package/dist/es/layouts/history-list/composables.js +138 -108
- package/dist/es/layouts/history-list/useHistoryList.js +56 -0
- package/dist/es/layouts/history-list/useHistoryRevert.js +317 -0
- 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 +5 -3
- 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 -7
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +33 -13
- 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 +26 -38
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +4 -4
- 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 +23 -6
- 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 +27 -5
- 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 +8 -8
- 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 +2 -2
- package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/layouts/sidebar/layer/use-click.js +3 -3
- 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 +2 -2
- 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 +16 -16
- package/dist/es/plugin.js +5 -2
- package/dist/es/services/codeBlock.js +137 -56
- package/dist/es/services/dataSource.js +122 -52
- package/dist/es/services/dep.js +162 -41
- package/dist/es/services/editor.js +613 -179
- package/dist/es/services/events.js +2 -2
- package/dist/es/services/history.js +350 -386
- package/dist/es/services/keybinding.js +6 -6
- package/dist/es/services/props.js +3 -2
- package/dist/es/services/storage.js +2 -2
- package/dist/es/services/ui.js +10 -2
- package/dist/es/style.css +549 -113
- package/dist/es/utils/config.js +4 -1
- package/dist/es/utils/const.js +2 -2
- package/dist/es/utils/content-menu.js +19 -11
- package/dist/es/utils/data-source/index.js +34 -11
- package/dist/es/utils/dep/collect-worker-client.js +114 -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 +103 -49
- package/dist/es/utils/event.js +135 -0
- package/dist/es/utils/history.js +220 -0
- package/dist/es/utils/indexed-db.js +86 -0
- package/dist/es/utils/monaco-editor.js +22 -6
- package/dist/es/utils/operator.js +2 -2
- package/dist/es/utils/props.js +114 -33
- package/dist/es/utils/type-match-rules.js +367 -0
- package/dist/es/utils/undo-redo.js +60 -1
- package/dist/style.css +549 -113
- package/dist/themes/magic-admin.css +3028 -0
- package/dist/tmagic-editor.umd.cjs +14403 -10121
- package/package.json +8 -8
- package/src/Editor.vue +43 -2
- package/src/components/CodeBlockEditor.vue +3 -0
- package/src/components/CompareForm.vue +18 -146
- package/src/components/ContentMenu.vue +44 -8
- package/src/components/FloatingBox.vue +84 -9
- package/src/components/ScrollBar.vue +0 -67
- package/src/components/ToolButton.vue +2 -2
- package/src/components/ViewForm.vue +55 -0
- package/src/editorProps.ts +30 -0
- package/src/fields/Code.vue +10 -2
- package/src/fields/CodeLink.vue +2 -5
- package/src/fields/CodeSelect.vue +54 -40
- package/src/fields/CodeSelectCol.vue +8 -1
- package/src/fields/CondOpSelect.vue +2 -24
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +16 -2
- package/src/fields/DataSourceFieldSelect/Index.vue +14 -5
- package/src/fields/DataSourceFields.vue +42 -8
- package/src/fields/DataSourceInput.vue +10 -28
- package/src/fields/DataSourceMethodSelect.vue +9 -4
- package/src/fields/DataSourceMethods.vue +42 -21
- package/src/fields/DataSourceMocks.vue +3 -0
- package/src/fields/DisplayConds.vue +18 -1
- package/src/fields/EventSelect.vue +152 -166
- package/src/fields/StyleSetter/Index.vue +3 -12
- package/src/fields/StyleSetter/components/Border.vue +15 -6
- package/src/fields/StyleSetter/icons/align-items/Center.vue +19 -0
- package/src/fields/StyleSetter/icons/align-items/FlexEnd.vue +19 -0
- package/src/fields/StyleSetter/icons/align-items/FlexStart.vue +19 -0
- package/src/fields/StyleSetter/icons/align-items/SpaceAround.vue +34 -0
- package/src/fields/StyleSetter/icons/align-items/SpaceBetween.vue +34 -0
- package/src/fields/StyleSetter/icons/align-items/index.ts +5 -0
- package/src/fields/StyleSetter/icons/background-repeat/NoRepeat.vue +20 -4
- package/src/fields/StyleSetter/icons/background-repeat/Repeat.vue +10 -28
- package/src/fields/StyleSetter/icons/background-repeat/RepeatX.vue +4 -5
- package/src/fields/StyleSetter/icons/background-repeat/RepeatY.vue +4 -5
- package/src/fields/StyleSetter/icons/flex-direction/Column.vue +4 -3
- package/src/fields/StyleSetter/icons/flex-direction/ColumnReverse.vue +4 -3
- package/src/fields/StyleSetter/icons/flex-direction/Row.vue +4 -3
- package/src/fields/StyleSetter/icons/flex-direction/RowReverse.vue +4 -3
- package/src/fields/StyleSetter/icons/justify-content/Center.vue +5 -2
- package/src/fields/StyleSetter/icons/justify-content/FlexEnd.vue +15 -2
- package/src/fields/StyleSetter/icons/justify-content/FlexStart.vue +15 -2
- package/src/fields/StyleSetter/icons/justify-content/SpaceAround.vue +28 -3
- package/src/fields/StyleSetter/icons/justify-content/SpaceBetween.vue +28 -2
- package/src/fields/StyleSetter/pro/Background.vue +99 -55
- package/src/fields/StyleSetter/pro/Border.vue +9 -11
- package/src/fields/StyleSetter/pro/Font.vue +66 -64
- package/src/fields/StyleSetter/pro/Layout.vue +211 -139
- package/src/fields/StyleSetter/pro/Position.vue +69 -67
- package/src/fields/StyleSetter/pro/Transform.vue +23 -25
- package/src/fields/UISelect.vue +0 -12
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-code-block-edit.ts +4 -3
- package/src/hooks/use-compare-form.ts +187 -0
- package/src/hooks/use-data-source-edit.ts +2 -2
- package/src/hooks/use-stage.ts +5 -3
- package/src/icons/DatasourceIcon.vue +7 -0
- package/src/index.ts +12 -0
- package/src/initService.ts +26 -16
- package/src/layouts/CodeEditor.vue +34 -11
- package/src/layouts/Framework.vue +15 -8
- package/src/layouts/NavMenu.vue +3 -3
- package/src/layouts/history-list/Bucket.vue +33 -41
- package/src/layouts/history-list/BucketTab.vue +72 -0
- package/src/layouts/history-list/GroupRow.vue +190 -93
- package/src/layouts/history-list/HistoryDiffDialog.vue +169 -90
- package/src/layouts/history-list/HistoryListPanel.vue +191 -95
- package/src/layouts/history-list/InitialRow.vue +38 -8
- package/src/layouts/history-list/PageTab.vue +67 -43
- package/src/layouts/history-list/composables.ts +239 -125
- package/src/layouts/history-list/useHistoryList.ts +60 -0
- package/src/layouts/history-list/useHistoryRevert.ts +425 -0
- package/src/layouts/page-bar/PageBar.vue +4 -2
- package/src/layouts/props-panel/FormPanel.vue +72 -6
- package/src/layouts/props-panel/PropsPanel.vue +62 -18
- package/src/layouts/props-panel/use-style-panel.ts +4 -3
- package/src/layouts/sidebar/ComponentListPanel.vue +10 -6
- package/src/layouts/sidebar/Sidebar.vue +13 -6
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
- 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 +34 -2
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +29 -4
- package/src/layouts/sidebar/data-source/useContentMenu.ts +14 -2
- package/src/layouts/sidebar/layer/LayerMenu.vue +21 -13
- package/src/layouts/sidebar/layer/LayerNodeContent.vue +57 -0
- package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
- package/src/layouts/sidebar/layer/LayerPanel.vue +4 -1
- 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 +1 -1
- package/src/layouts/workspace/viewer/ViewerMenu.vue +15 -15
- package/src/plugin.ts +6 -3
- package/src/services/codeBlock.ts +152 -47
- package/src/services/dataSource.ts +120 -41
- package/src/services/dep.ts +292 -47
- package/src/services/editor.ts +820 -224
- package/src/services/events.ts +3 -3
- package/src/services/history.ts +449 -412
- package/src/services/keybinding.ts +6 -6
- package/src/services/ui.ts +33 -5
- package/src/theme/code-block.scss +37 -0
- package/src/theme/common/var.scss +1 -1
- package/src/theme/component-list-panel.scss +2 -2
- package/src/theme/data-source-field.scss +4 -0
- package/src/theme/display-conds.scss +11 -0
- package/src/theme/event.scss +70 -1
- package/src/theme/floating-box.scss +9 -1
- package/src/theme/framework.scss +4 -1
- package/src/theme/history-list-panel.scss +157 -23
- package/src/theme/layer-node-content.scss +14 -0
- package/src/theme/nav-menu.scss +5 -1
- package/src/theme/page-bar.scss +0 -4
- package/src/theme/props-panel.scss +5 -4
- package/src/theme/scroll-bar.scss +64 -0
- package/src/theme/style-setter/border.scss +17 -5
- package/src/theme/theme.scss +4 -0
- package/src/theme/themes/magic-admin/index.scss +214 -0
- package/src/theme/ui-select.scss +9 -0
- package/src/type.ts +668 -124
- package/src/utils/config.ts +9 -1
- package/src/utils/const.ts +3 -2
- package/src/utils/content-menu.ts +20 -11
- package/src/utils/data-source/index.ts +32 -12
- package/src/utils/dep/collect-worker-client.ts +149 -0
- package/src/utils/dep/idle-task.ts +104 -35
- package/src/utils/dep/worker.ts +113 -9
- package/src/utils/editor.ts +166 -60
- package/src/utils/event.ts +237 -0
- package/src/utils/history.ts +286 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/indexed-db.ts +122 -0
- package/src/utils/monaco-editor.ts +27 -0
- package/src/utils/operator.ts +2 -2
- package/src/utils/props.ts +114 -11
- package/src/utils/type-match-rules.ts +684 -0
- package/src/utils/undo-redo.ts +88 -0
- package/types/index.d.ts +1990 -517
- package/dist/es/layouts/history-list/CodeBlockTab.js +0 -5
- package/dist/es/layouts/history-list/CodeBlockTab.vue_vue_type_script_setup_true_lang.js +0 -62
- package/dist/es/layouts/history-list/DataSourceTab.js +0 -5
- package/dist/es/layouts/history-list/DataSourceTab.vue_vue_type_script_setup_true_lang.js +0 -62
- package/src/layouts/history-list/CodeBlockTab.vue +0 -61
- package/src/layouts/history-list/DataSourceTab.vue +0 -61
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span class="m-editor-layer-node-content" :class="{ 'is-invalid': hasError }">
|
|
3
|
+
<span class="m-editor-layer-node-label">{{ label }}</span>
|
|
4
|
+
<TMagicTooltip v-if="hasError" placement="top">
|
|
5
|
+
<template #content>
|
|
6
|
+
<span v-html="errorMessage"></span>
|
|
7
|
+
</template>
|
|
8
|
+
<MIcon class="m-editor-layer-node-error-icon" :icon="WarningFilled"></MIcon>
|
|
9
|
+
</TMagicTooltip>
|
|
10
|
+
</span>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { computed } from 'vue';
|
|
15
|
+
import { WarningFilled } from '@element-plus/icons-vue';
|
|
16
|
+
|
|
17
|
+
import { stripValidateSuggestion, TMagicTooltip } from '@tmagic/design';
|
|
18
|
+
|
|
19
|
+
import MIcon from '@editor/components/Icon.vue';
|
|
20
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
21
|
+
import type { TreeNodeData } from '@editor/type';
|
|
22
|
+
|
|
23
|
+
defineOptions({
|
|
24
|
+
name: 'MEditorLayerNodeContent',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const props = defineProps<{
|
|
28
|
+
data: TreeNodeData;
|
|
29
|
+
}>();
|
|
30
|
+
|
|
31
|
+
const { editorService } = useServices();
|
|
32
|
+
|
|
33
|
+
const label = computed(() => `${props.data.name} (${props.data.id})`);
|
|
34
|
+
|
|
35
|
+
/** 读取集中存储的校验错误状态,建立响应式依赖 */
|
|
36
|
+
const invalidInfo = computed(() => editorService.get('invalidNodeIds').get(props.data.id));
|
|
37
|
+
|
|
38
|
+
const hasError = computed(() => Boolean(invalidInfo.value?.props || invalidInfo.value?.style));
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 去掉单条校验文案中的「修改建议」部分。
|
|
42
|
+
*
|
|
43
|
+
* 错误文案可能是多条错误以 `<br>` 拼接的 HTML,每条本身形如 `主文案\n\n建议`。
|
|
44
|
+
* 组件树 tooltip 仅展示错误描述,不展示修改建议(建议仅在错误汇总面板展示),
|
|
45
|
+
* 故先按 `<br>` 拆分,每段用 `stripValidateSuggestion` 截断建议后再拼回。
|
|
46
|
+
*/
|
|
47
|
+
const stripSuggestion = (text?: string): string =>
|
|
48
|
+
String(text ?? '')
|
|
49
|
+
.split(/<br\s*\/?>/i)
|
|
50
|
+
.map((segment) => stripValidateSuggestion(segment))
|
|
51
|
+
.join('<br>');
|
|
52
|
+
|
|
53
|
+
/** 合并属性表单与样式表单的错误文案(去掉建议,本身可能仍是含 <br> 的 HTML) */
|
|
54
|
+
const errorMessage = computed(() =>
|
|
55
|
+
[stripSuggestion(invalidInfo.value?.props), stripSuggestion(invalidInfo.value?.style)].filter(Boolean).join('<br>'),
|
|
56
|
+
);
|
|
57
|
+
</script>
|
|
@@ -25,9 +25,12 @@ const props = defineProps<{
|
|
|
25
25
|
const { editorService } = useServices();
|
|
26
26
|
|
|
27
27
|
const setNodeVisible = (visible: boolean) => {
|
|
28
|
-
editorService.update(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
editorService.update(
|
|
29
|
+
{
|
|
30
|
+
id: props.data.id,
|
|
31
|
+
visible,
|
|
32
|
+
},
|
|
33
|
+
{ historySource: 'tree' },
|
|
34
|
+
);
|
|
32
35
|
};
|
|
33
36
|
</script>
|
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
</template>
|
|
34
34
|
|
|
35
35
|
<template #tree-node-label="{ data: nodeData }">
|
|
36
|
-
<slot name="layer-node-label" :data="nodeData"
|
|
36
|
+
<slot name="layer-node-label" :data="nodeData">
|
|
37
|
+
<LayerNodeContent :data="nodeData"></LayerNodeContent>
|
|
38
|
+
</slot>
|
|
37
39
|
</template>
|
|
38
40
|
</Tree>
|
|
39
41
|
|
|
@@ -69,6 +71,7 @@ import type {
|
|
|
69
71
|
} from '@editor/type';
|
|
70
72
|
|
|
71
73
|
import LayerMenu from './LayerMenu.vue';
|
|
74
|
+
import LayerNodeContent from './LayerNodeContent.vue';
|
|
72
75
|
import LayerNodeTool from './LayerNodeTool.vue';
|
|
73
76
|
import { useClick } from './use-click';
|
|
74
77
|
import { useDrag } from './use-drag';
|
|
@@ -2,7 +2,7 @@ import { computed, type ComputedRef, nextTick, type Ref, type ShallowRef } from
|
|
|
2
2
|
import { throttle } from 'lodash-es';
|
|
3
3
|
|
|
4
4
|
import { Id, MNode } from '@tmagic/core';
|
|
5
|
-
import { getElById,
|
|
5
|
+
import { getElById, isPageOrFragment } from '@tmagic/utils';
|
|
6
6
|
|
|
7
7
|
import type { LayerNodeStatus, Services, TreeNodeData } from '@editor/type';
|
|
8
8
|
import { UI_SELECT_MODE_EVENT_NAME } from '@editor/utils/const';
|
|
@@ -36,7 +36,7 @@ export const useClick = (
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
const multiSelect = async (data: MNode) => {
|
|
39
|
-
if (
|
|
39
|
+
if (isPageOrFragment(data)) {
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -50,7 +50,7 @@ export const useClick = (
|
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
if (
|
|
53
|
+
if (isPageOrFragment(node)) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { computed, onBeforeUnmount, ref, watch } from 'vue';
|
|
2
2
|
|
|
3
3
|
import type { Id, MApp, MNode, MPage, MPageFragment } from '@tmagic/core';
|
|
4
|
-
import { getNodePath,
|
|
4
|
+
import { getNodePath, isPageOrFragment, traverseNode } from '@tmagic/utils';
|
|
5
5
|
|
|
6
6
|
import type { LayerNodeStatus, Services } from '@editor/type';
|
|
7
7
|
import { updateStatus } from '@editor/utils/tree';
|
|
@@ -136,7 +136,7 @@ export const useNodeStatus = ({ editorService }: Services) => {
|
|
|
136
136
|
|
|
137
137
|
const addHandler = (newNodes: MNode[]) => {
|
|
138
138
|
newNodes.forEach((node) => {
|
|
139
|
-
if (
|
|
139
|
+
if (isPageOrFragment(node)) return;
|
|
140
140
|
|
|
141
141
|
traverseNode(node, (node: MNode) => {
|
|
142
142
|
nodeStatusMap.value?.set(node.id, {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
ref="box"
|
|
9
9
|
v-model:visible="visible"
|
|
10
10
|
title="当前位置下的组件"
|
|
11
|
+
:framework-width="frameworkWidth"
|
|
11
12
|
:position="menuPosition"
|
|
12
13
|
>
|
|
13
14
|
<template #body>
|
|
@@ -36,7 +37,9 @@ import { useNodeStatus } from '@editor/layouts/sidebar/layer/use-node-status';
|
|
|
36
37
|
import type { TreeNodeData } from '@editor/type';
|
|
37
38
|
|
|
38
39
|
const services = useServices();
|
|
39
|
-
const { editorService } = services;
|
|
40
|
+
const { editorService, uiService } = services;
|
|
41
|
+
|
|
42
|
+
const frameworkWidth = computed(() => uiService.get('frameworkRect')?.width || 0);
|
|
40
43
|
|
|
41
44
|
const visible = ref(false);
|
|
42
45
|
const buttonVisible = ref(false);
|
|
@@ -7,7 +7,7 @@ import { computed, markRaw, ref, useTemplateRef, watch } from 'vue';
|
|
|
7
7
|
import { Bottom, Top } from '@element-plus/icons-vue';
|
|
8
8
|
|
|
9
9
|
import { NodeType } from '@tmagic/core';
|
|
10
|
-
import {
|
|
10
|
+
import { isPageOrFragment } from '@tmagic/utils';
|
|
11
11
|
|
|
12
12
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
13
13
|
import { useServices } from '@editor/hooks/use-services';
|
|
@@ -49,62 +49,62 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
|
49
49
|
display: () => canCenter.value,
|
|
50
50
|
handler: () => {
|
|
51
51
|
if (!nodes.value) return;
|
|
52
|
-
editorService.alignCenter(nodes.value);
|
|
52
|
+
editorService.alignCenter(nodes.value, { historySource: 'stage-contextmenu' });
|
|
53
53
|
},
|
|
54
54
|
},
|
|
55
55
|
useCopyMenu(),
|
|
56
|
-
usePasteMenu(menuRef),
|
|
56
|
+
usePasteMenu('stage-contextmenu', menuRef),
|
|
57
57
|
{
|
|
58
58
|
type: 'divider',
|
|
59
59
|
direction: 'horizontal',
|
|
60
60
|
display: () => {
|
|
61
61
|
if (!node.value) return false;
|
|
62
|
-
return !
|
|
62
|
+
return !isPageOrFragment(node.value);
|
|
63
63
|
},
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
type: 'button',
|
|
67
67
|
text: '上移一层',
|
|
68
68
|
icon: markRaw(Top),
|
|
69
|
-
display: () => !
|
|
69
|
+
display: () => !isPageOrFragment(node.value) && !props.isMultiSelect,
|
|
70
70
|
handler: () => {
|
|
71
|
-
editorService.moveLayer(1);
|
|
71
|
+
editorService.moveLayer(1, { historySource: 'stage-contextmenu' });
|
|
72
72
|
},
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
type: 'button',
|
|
76
76
|
text: '下移一层',
|
|
77
77
|
icon: markRaw(Bottom),
|
|
78
|
-
display: () => !
|
|
78
|
+
display: () => !isPageOrFragment(node.value) && !props.isMultiSelect,
|
|
79
79
|
handler: () => {
|
|
80
|
-
editorService.moveLayer(-1);
|
|
80
|
+
editorService.moveLayer(-1, { historySource: 'stage-contextmenu' });
|
|
81
81
|
},
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
type: 'button',
|
|
85
85
|
text: '置顶',
|
|
86
86
|
icon: markRaw(Top),
|
|
87
|
-
display: () => !
|
|
87
|
+
display: () => !isPageOrFragment(node.value) && !props.isMultiSelect,
|
|
88
88
|
handler: () => {
|
|
89
|
-
editorService.moveLayer(LayerOffset.TOP);
|
|
89
|
+
editorService.moveLayer(LayerOffset.TOP, { historySource: 'stage-contextmenu' });
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
type: 'button',
|
|
94
94
|
text: '置底',
|
|
95
95
|
icon: markRaw(Bottom),
|
|
96
|
-
display: () => !
|
|
96
|
+
display: () => !isPageOrFragment(node.value) && !props.isMultiSelect,
|
|
97
97
|
handler: () => {
|
|
98
|
-
editorService.moveLayer(LayerOffset.BOTTOM);
|
|
98
|
+
editorService.moveLayer(LayerOffset.BOTTOM, { historySource: 'stage-contextmenu' });
|
|
99
99
|
},
|
|
100
100
|
},
|
|
101
|
-
useMoveToMenu(services),
|
|
101
|
+
useMoveToMenu(services, 'stage-contextmenu'),
|
|
102
102
|
{
|
|
103
103
|
type: 'divider',
|
|
104
104
|
direction: 'horizontal',
|
|
105
|
-
display: () => !
|
|
105
|
+
display: () => !isPageOrFragment(node.value) && !props.isMultiSelect,
|
|
106
106
|
},
|
|
107
|
-
useDeleteMenu(),
|
|
107
|
+
useDeleteMenu('stage-contextmenu'),
|
|
108
108
|
{
|
|
109
109
|
type: 'divider',
|
|
110
110
|
direction: 'horizontal',
|
package/src/plugin.ts
CHANGED
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import type
|
|
19
|
+
import { type App } from 'vue';
|
|
20
20
|
|
|
21
21
|
import type { DesignPluginOptions } from '@tmagic/design';
|
|
22
22
|
import designPlugin from '@tmagic/design';
|
|
23
23
|
import type { FormInstallOptions } from '@tmagic/form';
|
|
24
|
-
import formPlugin from '@tmagic/form';
|
|
24
|
+
import formPlugin, { registerTypeMatchRules } from '@tmagic/form';
|
|
25
25
|
import tablePlugin from '@tmagic/table';
|
|
26
26
|
|
|
27
27
|
import Code from './fields/Code.vue';
|
|
@@ -44,6 +44,7 @@ import StyleSetter from './fields/StyleSetter/Index.vue';
|
|
|
44
44
|
import uiSelect from './fields/UISelect.vue';
|
|
45
45
|
import CodeEditor from './layouts/CodeEditor.vue';
|
|
46
46
|
import { setEditorConfig } from './utils/config';
|
|
47
|
+
import { editorTypeMatchRules } from './utils/type-match-rules';
|
|
47
48
|
import Editor from './Editor.vue';
|
|
48
49
|
import type { EditorInstallOptions } from './type';
|
|
49
50
|
|
|
@@ -55,6 +56,8 @@ const defaultInstallOpt: EditorInstallOptions = {
|
|
|
55
56
|
customCreateMonacoEditor: (monaco, codeEditorEl, options) => monaco.editor.create(codeEditorEl, options),
|
|
56
57
|
customCreateMonacoDiffEditor: (monaco, codeEditorEl, options) =>
|
|
57
58
|
monaco.editor.createDiffEditor(codeEditorEl, options),
|
|
59
|
+
|
|
60
|
+
flat: false,
|
|
58
61
|
};
|
|
59
62
|
|
|
60
63
|
export default {
|
|
@@ -64,10 +67,10 @@ export default {
|
|
|
64
67
|
app.use(designPlugin, opt || {});
|
|
65
68
|
app.use(formPlugin, opt || {});
|
|
66
69
|
app.use(tablePlugin);
|
|
70
|
+
registerTypeMatchRules(editorTypeMatchRules);
|
|
67
71
|
|
|
68
72
|
app.config.globalProperties.$TMAGIC_EDITOR = option;
|
|
69
73
|
setEditorConfig(option);
|
|
70
|
-
|
|
71
74
|
app.component(`${Editor.name || 'MEditor'}`, Editor);
|
|
72
75
|
app.component('magic-code-editor', CodeEditor);
|
|
73
76
|
app.component('m-fields-ui-select', uiSelect);
|
|
@@ -32,12 +32,14 @@ import type {
|
|
|
32
32
|
AsyncHookPlugin,
|
|
33
33
|
CodeBlockStepValue,
|
|
34
34
|
CodeState,
|
|
35
|
+
DslOpWithHistoryIdsResult,
|
|
35
36
|
HistoryOpOptions,
|
|
36
37
|
HistoryOpOptionsWithChangeRecords,
|
|
37
38
|
} from '@editor/type';
|
|
38
39
|
import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
|
|
39
40
|
import { getEditorConfig } from '@editor/utils/config';
|
|
40
41
|
import { COPY_CODE_STORAGE_KEY } from '@editor/utils/editor';
|
|
42
|
+
import { createStackStep, describeRevertStep, getLastPushedHistoryIds } from '@editor/utils/history';
|
|
41
43
|
|
|
42
44
|
import BaseService from './BaseService';
|
|
43
45
|
|
|
@@ -48,18 +50,6 @@ const canUsePluginMethods = {
|
|
|
48
50
|
|
|
49
51
|
type AsyncMethodName = Writable<(typeof canUsePluginMethods)['async']>;
|
|
50
52
|
|
|
51
|
-
/**
|
|
52
|
-
* 「回滚」生成的新 step 简短描述。仅 service 层使用。
|
|
53
|
-
*/
|
|
54
|
-
const describeRevertCodeBlockStep = (step: CodeBlockStepValue): string => {
|
|
55
|
-
const { oldContent, newContent, changeRecords, id } = step;
|
|
56
|
-
if (oldContent === null && newContent) return `撤回新增 ${newContent.name || newContent.id || id}`;
|
|
57
|
-
if (oldContent && newContent === null) return `还原已删除的 ${oldContent.name || oldContent.id || id}`;
|
|
58
|
-
const name = newContent?.name || oldContent?.name || `${id}`;
|
|
59
|
-
const propPath = changeRecords?.[0]?.propPath;
|
|
60
|
-
return propPath ? `还原 ${name} · ${propPath}` : `还原 ${name}`;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
53
|
class CodeBlock extends BaseService {
|
|
64
54
|
private state = reactive<CodeState>({
|
|
65
55
|
codeDsl: null,
|
|
@@ -69,6 +59,17 @@ class CodeBlock extends BaseService {
|
|
|
69
59
|
paramsColConfig: undefined,
|
|
70
60
|
});
|
|
71
61
|
|
|
62
|
+
/**
|
|
63
|
+
* 最近一次写入历史栈的代码块历史记录 uuid(单条写入场景:新增 / 更新)。
|
|
64
|
+
* 供 setCodeDslById(Sync)AndGetHistoryId 取回,普通方法不读取它。
|
|
65
|
+
*/
|
|
66
|
+
private lastPushedHistoryId: string | null = null;
|
|
67
|
+
/**
|
|
68
|
+
* deleteCodeDslByIds 一次删除多个代码块时,按写入顺序收集的历史记录 uuid 列表。
|
|
69
|
+
* 在 deleteCodeDslByIds 入口处重置,供 deleteCodeDslByIdsAndGetHistoryId 取回。
|
|
70
|
+
*/
|
|
71
|
+
private lastDeletedHistoryIds: string[] = [];
|
|
72
|
+
|
|
72
73
|
constructor() {
|
|
73
74
|
super([
|
|
74
75
|
...canUsePluginMethods.async.map((methodName) => ({ name: methodName, isAsync: true })),
|
|
@@ -84,6 +85,7 @@ class CodeBlock extends BaseService {
|
|
|
84
85
|
public async setCodeDsl(codeDsl: CodeBlockDSL): Promise<void> {
|
|
85
86
|
this.state.codeDsl = codeDsl;
|
|
86
87
|
this.emit('code-dsl-change', this.state.codeDsl);
|
|
88
|
+
this.emit('change', this.state.codeDsl);
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
/**
|
|
@@ -120,9 +122,19 @@ class CodeBlock extends BaseService {
|
|
|
120
122
|
public async setCodeDslById(
|
|
121
123
|
id: Id,
|
|
122
124
|
codeConfig: Partial<CodeBlockContent>,
|
|
123
|
-
{
|
|
125
|
+
{
|
|
126
|
+
changeRecords,
|
|
127
|
+
doNotPushHistory = false,
|
|
128
|
+
historyDescription,
|
|
129
|
+
historySource,
|
|
130
|
+
}: HistoryOpOptionsWithChangeRecords = {},
|
|
124
131
|
): Promise<void> {
|
|
125
|
-
this.setCodeDslByIdSync(id, codeConfig, true, {
|
|
132
|
+
this.setCodeDslByIdSync(id, codeConfig, true, {
|
|
133
|
+
changeRecords,
|
|
134
|
+
doNotPushHistory,
|
|
135
|
+
historyDescription,
|
|
136
|
+
historySource,
|
|
137
|
+
});
|
|
126
138
|
}
|
|
127
139
|
|
|
128
140
|
/**
|
|
@@ -141,7 +153,12 @@ class CodeBlock extends BaseService {
|
|
|
141
153
|
id: Id,
|
|
142
154
|
codeConfig: Partial<CodeBlockContent>,
|
|
143
155
|
force = true,
|
|
144
|
-
{
|
|
156
|
+
{
|
|
157
|
+
changeRecords,
|
|
158
|
+
doNotPushHistory = false,
|
|
159
|
+
historyDescription,
|
|
160
|
+
historySource,
|
|
161
|
+
}: HistoryOpOptionsWithChangeRecords = {},
|
|
145
162
|
): void {
|
|
146
163
|
const codeDsl = this.getCodeDsl();
|
|
147
164
|
|
|
@@ -172,10 +189,18 @@ class CodeBlock extends BaseService {
|
|
|
172
189
|
const newContent = cloneDeep(codeDsl[id]);
|
|
173
190
|
|
|
174
191
|
if (!doNotPushHistory) {
|
|
175
|
-
|
|
192
|
+
const step = createStackStep<CodeBlockContent, CodeBlockStepValue>(id, {
|
|
193
|
+
oldValue: oldContent,
|
|
194
|
+
newValue: newContent,
|
|
195
|
+
changeRecords,
|
|
196
|
+
historyDescription,
|
|
197
|
+
source: historySource,
|
|
198
|
+
});
|
|
199
|
+
this.lastPushedHistoryId = (step ? historyService.push('codeBlock', step, id) : null)?.uuid ?? null;
|
|
176
200
|
}
|
|
177
201
|
|
|
178
202
|
this.emit('addOrUpdate', id, codeDsl[id]);
|
|
203
|
+
this.emit('change', this.getCodeDsl());
|
|
179
204
|
}
|
|
180
205
|
|
|
181
206
|
/**
|
|
@@ -268,25 +293,82 @@ class CodeBlock extends BaseService {
|
|
|
268
293
|
*/
|
|
269
294
|
public async deleteCodeDslByIds(
|
|
270
295
|
codeIds: Id[],
|
|
271
|
-
{ doNotPushHistory = false, historyDescription }: HistoryOpOptions = {},
|
|
296
|
+
{ doNotPushHistory = false, historyDescription, historySource }: HistoryOpOptions = {},
|
|
272
297
|
): Promise<void> {
|
|
273
298
|
const currentDsl = await this.getCodeDsl();
|
|
274
299
|
|
|
275
300
|
if (!currentDsl) return;
|
|
276
301
|
|
|
302
|
+
this.lastDeletedHistoryIds = [];
|
|
303
|
+
|
|
277
304
|
codeIds.forEach((id) => {
|
|
278
305
|
// 历史记录:删除前快照内容;不存在的 id 直接跳过历史推入
|
|
279
|
-
const
|
|
306
|
+
const oldValue: CodeBlockContent | null = currentDsl[id] ? cloneDeep(currentDsl[id]) : null;
|
|
280
307
|
|
|
281
308
|
delete currentDsl[id];
|
|
282
309
|
|
|
283
|
-
if (
|
|
284
|
-
|
|
310
|
+
if (oldValue && !doNotPushHistory) {
|
|
311
|
+
const step = createStackStep<CodeBlockContent, CodeBlockStepValue>(id, {
|
|
312
|
+
oldValue,
|
|
313
|
+
newValue: null,
|
|
314
|
+
historyDescription,
|
|
315
|
+
source: historySource,
|
|
316
|
+
});
|
|
317
|
+
const uuid = step ? historyService.push('codeBlock', step, id)?.uuid : undefined;
|
|
318
|
+
if (uuid) this.lastDeletedHistoryIds.push(uuid);
|
|
285
319
|
}
|
|
286
320
|
|
|
287
321
|
this.emit('remove', id);
|
|
288
322
|
});
|
|
323
|
+
|
|
324
|
+
this.emit('change', this.getCodeDsl());
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// #region AndGetHistoryId
|
|
328
|
+
/**
|
|
329
|
+
* 下列 *AndGetHistoryId 方法与对应的写入方法行为完全一致,
|
|
330
|
+
* 返回值在 {@link DslOpWithHistoryIdsResult} 中同时包含原操作结果与本次写入的历史 uuid 列表,
|
|
331
|
+
* 可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
|
|
332
|
+
*
|
|
333
|
+
* 当本次操作未写入历史(doNotPushHistory 为 true、或无对应记录)时 historyIds 为 `[]`。
|
|
334
|
+
*/
|
|
335
|
+
|
|
336
|
+
/** 等价于 {@link setCodeDslById},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
|
|
337
|
+
public async setCodeDslByIdAndGetHistoryId(
|
|
338
|
+
id: Id,
|
|
339
|
+
codeConfig: Partial<CodeBlockContent>,
|
|
340
|
+
options: HistoryOpOptionsWithChangeRecords = {},
|
|
341
|
+
): Promise<DslOpWithHistoryIdsResult<void>> {
|
|
342
|
+
this.lastPushedHistoryId = null;
|
|
343
|
+
await this.setCodeDslById(id, codeConfig, options);
|
|
344
|
+
return { result: undefined, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/** 等价于 {@link setCodeDslByIdSync},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
|
|
348
|
+
public setCodeDslByIdSyncAndGetHistoryId(
|
|
349
|
+
id: Id,
|
|
350
|
+
codeConfig: Partial<CodeBlockContent>,
|
|
351
|
+
force = true,
|
|
352
|
+
options: HistoryOpOptionsWithChangeRecords = {},
|
|
353
|
+
): DslOpWithHistoryIdsResult<void> {
|
|
354
|
+
this.lastPushedHistoryId = null;
|
|
355
|
+
this.setCodeDslByIdSync(id, codeConfig, force, options);
|
|
356
|
+
return { result: undefined, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* 等价于 {@link deleteCodeDslByIds},并额外返回本次写入的全部历史记录 uuid(按删除顺序)。
|
|
361
|
+
* 一次删除多个代码块会产生多条历史记录;未写入任何历史时 historyIds 为 `[]`。
|
|
362
|
+
*/
|
|
363
|
+
public async deleteCodeDslByIdsAndGetHistoryId(
|
|
364
|
+
codeIds: Id[],
|
|
365
|
+
options: HistoryOpOptions = {},
|
|
366
|
+
): Promise<DslOpWithHistoryIdsResult<void>> {
|
|
367
|
+
this.lastDeletedHistoryIds = [];
|
|
368
|
+
await this.deleteCodeDslByIds(codeIds, options);
|
|
369
|
+
return { result: undefined, historyIds: [...this.lastDeletedHistoryIds] };
|
|
289
370
|
}
|
|
371
|
+
// #endregion AndGetHistoryId
|
|
290
372
|
|
|
291
373
|
public setParamsColConfig(config: TableColumnConfig): void {
|
|
292
374
|
this.state.paramsColConfig = config;
|
|
@@ -308,7 +390,7 @@ class CodeBlock extends BaseService {
|
|
|
308
390
|
* @returns 撤销的 step;栈不存在或已无可撤销时返回 null
|
|
309
391
|
*/
|
|
310
392
|
public async undo(id: Id): Promise<CodeBlockStepValue | null> {
|
|
311
|
-
const step = historyService.
|
|
393
|
+
const step = historyService.undo('codeBlock', id);
|
|
312
394
|
if (!step) return null;
|
|
313
395
|
await this.applyHistoryStep(step, true);
|
|
314
396
|
return step;
|
|
@@ -320,7 +402,7 @@ class CodeBlock extends BaseService {
|
|
|
320
402
|
* @returns 重做的 step;栈不存在或已无可重做时返回 null
|
|
321
403
|
*/
|
|
322
404
|
public async redo(id: Id): Promise<CodeBlockStepValue | null> {
|
|
323
|
-
const step = historyService.
|
|
405
|
+
const step = historyService.redo('codeBlock', id);
|
|
324
406
|
if (!step) return null;
|
|
325
407
|
await this.applyHistoryStep(step, false);
|
|
326
408
|
return step;
|
|
@@ -328,12 +410,12 @@ class CodeBlock extends BaseService {
|
|
|
328
410
|
|
|
329
411
|
/** 是否可对指定代码块撤销。 */
|
|
330
412
|
public canUndo(id: Id): boolean {
|
|
331
|
-
return historyService.
|
|
413
|
+
return historyService.canUndo('codeBlock', id);
|
|
332
414
|
}
|
|
333
415
|
|
|
334
416
|
/** 是否可对指定代码块重做。 */
|
|
335
417
|
public canRedo(id: Id): boolean {
|
|
336
|
-
return historyService.
|
|
418
|
+
return historyService.canRedo('codeBlock', id);
|
|
337
419
|
}
|
|
338
420
|
|
|
339
421
|
/**
|
|
@@ -344,7 +426,7 @@ class CodeBlock extends BaseService {
|
|
|
344
426
|
* @returns 实际移动到的最终游标位置
|
|
345
427
|
*/
|
|
346
428
|
public async goto(id: Id, targetCursor: number): Promise<number> {
|
|
347
|
-
let cursor = historyService.
|
|
429
|
+
let cursor = historyService.getCursor('codeBlock', id);
|
|
348
430
|
const target = Math.max(0, targetCursor);
|
|
349
431
|
while (cursor > target) {
|
|
350
432
|
const step = await this.undo(id);
|
|
@@ -370,13 +452,33 @@ class CodeBlock extends BaseService {
|
|
|
370
452
|
* @returns 反向后产生的新 step;目标不存在 / 未应用时返回 null
|
|
371
453
|
*/
|
|
372
454
|
public async revert(id: Id, index: number): Promise<CodeBlockStepValue | null> {
|
|
373
|
-
const list = historyService.
|
|
455
|
+
const list = historyService.getStepList('codeBlock', id);
|
|
374
456
|
const entry = list[index];
|
|
375
457
|
if (!entry?.applied) return null;
|
|
376
|
-
|
|
458
|
+
// 更新类步骤(前后 content 都存在)必须带 changeRecords 才支持回滚,否则只能整内容替换,会冲掉后续无关变更。
|
|
459
|
+
const { oldSchema, newSchema, changeRecords } = entry.step.diff?.[0] ?? {};
|
|
460
|
+
|
|
461
|
+
if (oldSchema && newSchema && !changeRecords?.length) return null;
|
|
462
|
+
const description = `回滚 #${index + 1}: ${describeRevertStep<CodeBlockContent>(entry.step.data.id, entry.step.diff?.[0], (s) => s.name)}`;
|
|
377
463
|
return await this.applyRevertStep(entry.step, description);
|
|
378
464
|
}
|
|
379
465
|
|
|
466
|
+
/**
|
|
467
|
+
* 通过历史记录 uuid 回滚代码块历史步骤,语义同 {@link revert},
|
|
468
|
+
* 仅无需调用方再传 codeBlockId 与 index:内部会按 uuid 在全部代码块栈中定位对应步骤后再回滚。
|
|
469
|
+
* 按数组顺序依次回滚,返回与入参同序的结果列表(某项失败时为 `null`)。
|
|
470
|
+
*
|
|
471
|
+
* @param uuids 目标历史记录的 uuid 列表,通常由 {@link setCodeDslByIdAndGetHistoryId} 等方法返回的 `historyIds`
|
|
472
|
+
*/
|
|
473
|
+
public async revertById(uuids: string[]): Promise<(CodeBlockStepValue | null)[]> {
|
|
474
|
+
const results: (CodeBlockStepValue | null)[] = [];
|
|
475
|
+
for (const uuid of uuids) {
|
|
476
|
+
const location = historyService.findStepLocationByUuid('codeBlock', uuid);
|
|
477
|
+
results.push(location ? await this.revert(location.id, location.index) : null);
|
|
478
|
+
}
|
|
479
|
+
return results;
|
|
480
|
+
}
|
|
481
|
+
|
|
380
482
|
/**
|
|
381
483
|
* 生成代码块唯一id
|
|
382
484
|
* @returns {Id} 代码块唯一id
|
|
@@ -467,21 +569,22 @@ class CodeBlock extends BaseService {
|
|
|
467
569
|
step: CodeBlockStepValue,
|
|
468
570
|
historyDescription: string,
|
|
469
571
|
): Promise<CodeBlockStepValue | null> {
|
|
470
|
-
const { id
|
|
572
|
+
const { id } = step.data;
|
|
573
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
471
574
|
|
|
472
575
|
// 原本是新增 → revert 即删除
|
|
473
|
-
if (
|
|
474
|
-
await this.deleteCodeDslByIds([id], { historyDescription });
|
|
475
|
-
return historyService.
|
|
576
|
+
if (!oldSchema && newSchema) {
|
|
577
|
+
await this.deleteCodeDslByIds([id], { historyDescription, historySource: 'rollback' });
|
|
578
|
+
return historyService.getStepList('codeBlock', id).slice(-1)[0]?.step ?? null;
|
|
476
579
|
}
|
|
477
580
|
|
|
478
581
|
// 原本是删除 → revert 即写回
|
|
479
|
-
if (
|
|
480
|
-
this.setCodeDslByIdSync(id, cloneDeep(
|
|
481
|
-
return historyService.
|
|
582
|
+
if (oldSchema && !newSchema) {
|
|
583
|
+
this.setCodeDslByIdSync(id, cloneDeep(oldSchema), true, { historyDescription, historySource: 'rollback' });
|
|
584
|
+
return historyService.getStepList('codeBlock', id).slice(-1)[0]?.step ?? null;
|
|
482
585
|
}
|
|
483
586
|
|
|
484
|
-
if (!
|
|
587
|
+
if (!oldSchema || !newSchema) return null;
|
|
485
588
|
|
|
486
589
|
// 原本是更新 → 把 oldContent 写回;优先按 changeRecords 局部 patch
|
|
487
590
|
if (changeRecords?.length) {
|
|
@@ -494,18 +597,19 @@ class CodeBlock extends BaseService {
|
|
|
494
597
|
fallbackToFullReplace = true;
|
|
495
598
|
break;
|
|
496
599
|
}
|
|
497
|
-
const value = cloneDeep(getValueByKeyPath(record.propPath,
|
|
600
|
+
const value = cloneDeep(getValueByKeyPath(record.propPath, oldSchema));
|
|
498
601
|
setValueByKeyPath(record.propPath, value, patched);
|
|
499
602
|
}
|
|
500
|
-
this.setCodeDslByIdSync(id, fallbackToFullReplace ? cloneDeep(
|
|
603
|
+
this.setCodeDslByIdSync(id, fallbackToFullReplace ? cloneDeep(oldSchema) : patched, true, {
|
|
501
604
|
changeRecords,
|
|
502
605
|
historyDescription,
|
|
606
|
+
historySource: 'rollback',
|
|
503
607
|
});
|
|
504
|
-
return historyService.
|
|
608
|
+
return historyService.getStepList('codeBlock', id).slice(-1)[0]?.step ?? null;
|
|
505
609
|
}
|
|
506
610
|
|
|
507
|
-
this.setCodeDslByIdSync(id, cloneDeep(
|
|
508
|
-
return historyService.
|
|
611
|
+
this.setCodeDslByIdSync(id, cloneDeep(oldSchema), true, { historyDescription, historySource: 'rollback' });
|
|
612
|
+
return historyService.getStepList('codeBlock', id).slice(-1)[0]?.step ?? null;
|
|
509
613
|
}
|
|
510
614
|
|
|
511
615
|
/**
|
|
@@ -523,31 +627,32 @@ class CodeBlock extends BaseService {
|
|
|
523
627
|
* @param reverse true=撤销,false=重做
|
|
524
628
|
*/
|
|
525
629
|
private async applyHistoryStep(step: CodeBlockStepValue, reverse: boolean): Promise<void> {
|
|
526
|
-
const { id
|
|
630
|
+
const { id } = step.data;
|
|
631
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
527
632
|
|
|
528
633
|
// 新增 / 删除:直接 set 或 delete,不走 patch 逻辑
|
|
529
|
-
if (
|
|
634
|
+
if (!oldSchema && newSchema) {
|
|
530
635
|
if (reverse) {
|
|
531
636
|
await this.deleteCodeDslByIds([id], { doNotPushHistory: true });
|
|
532
637
|
} else {
|
|
533
|
-
this.setCodeDslByIdSync(id, cloneDeep(
|
|
638
|
+
this.setCodeDslByIdSync(id, cloneDeep(newSchema), true, { doNotPushHistory: true });
|
|
534
639
|
}
|
|
535
640
|
return;
|
|
536
641
|
}
|
|
537
642
|
|
|
538
|
-
if (
|
|
643
|
+
if (oldSchema && !newSchema) {
|
|
539
644
|
if (reverse) {
|
|
540
|
-
this.setCodeDslByIdSync(id, cloneDeep(
|
|
645
|
+
this.setCodeDslByIdSync(id, cloneDeep(oldSchema), true, { doNotPushHistory: true });
|
|
541
646
|
} else {
|
|
542
647
|
await this.deleteCodeDslByIds([id], { doNotPushHistory: true });
|
|
543
648
|
}
|
|
544
649
|
return;
|
|
545
650
|
}
|
|
546
651
|
|
|
547
|
-
if (!
|
|
652
|
+
if (!oldSchema || !newSchema) return;
|
|
548
653
|
|
|
549
654
|
// 更新场景:优先按 changeRecords 局部 patch;缺省退化为整内容替换
|
|
550
|
-
const sourceForValues = reverse ?
|
|
655
|
+
const sourceForValues = reverse ? oldSchema : newSchema;
|
|
551
656
|
|
|
552
657
|
if (changeRecords?.length) {
|
|
553
658
|
const current = this.getCodeContentById(id);
|