@tmagic/editor 1.8.0-manmanyu.8 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +22 -13
- package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +10 -5
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +7 -6
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +21 -119
- package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +21 -5
- package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +62 -16
- package/dist/es/components/Icon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/Resizer.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/components/ScrollBar.js +0 -1
- package/dist/es/components/ScrollBar.vue_vue_type_script_setup_true_lang.js +5 -4
- package/dist/es/components/ScrollViewer.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/SearchInput.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/SplitView.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/ToolButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/Tree.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/TreeNode.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/ViewForm.js +5 -0
- package/dist/es/components/ViewForm.vue_vue_type_script_setup_true_lang.js +56 -0
- package/dist/es/editorProps.js +7 -1
- package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +30 -113
- package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +7 -19
- package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +7 -6
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +12 -4
- package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +9 -20
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +2 -2
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +5 -3
- package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +9 -4
- package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +10 -110
- package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +52 -363
- package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/PageFragmentSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +3 -6
- package/dist/es/fields/StyleSetter/components/BackgroundPosition.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +4 -35
- package/dist/es/fields/StyleSetter/components/Box.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/fields/StyleSetter/configs.js +663 -0
- package/dist/es/fields/StyleSetter/icons/align-items/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/FlexEnd.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/FlexStart.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceAround.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceBetween.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/NoRepeat.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/Repeat.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatX.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatY.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Block.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Flex.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Inline.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/InlineBlock.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/None.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/Column.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/ColumnReverse.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/Row.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/RowReverse.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexEnd.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexStart.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceAround.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceBetween.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Left.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Right.js +1 -1
- package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +29 -106
- package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +8 -11
- package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +30 -89
- package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +29 -297
- package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +29 -82
- package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +8 -24
- package/dist/es/fields/UISelect.js +0 -1
- package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/configs/codeSelect.js +98 -0
- package/dist/es/fields/configs/displayConds.js +158 -0
- package/dist/es/fields/configs/eventSelect.js +225 -0
- package/dist/es/fields/configs/stickyAddButton.js +21 -0
- package/dist/es/fields/headless-validation.js +139 -0
- package/dist/es/headless.js +2 -0
- package/dist/es/hooks/use-code-block-edit.js +4 -2
- package/dist/es/hooks/use-compare-form.js +101 -0
- package/dist/es/hooks/use-form-context.js +29 -0
- package/dist/es/hooks/use-stage.js +1 -0
- package/dist/es/icons/CenterIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/icons/CodeIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/icons/DatasourceIcon.js +1 -1
- package/dist/es/icons/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/index.js +17 -9
- package/dist/es/initService.js +52 -16
- package/dist/es/layouts/AddPageBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +26 -10
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +11 -8
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/NavMenuColumn.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +8 -5
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +26 -10
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +36 -28
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/composables.js +1 -1
- package/dist/es/layouts/history-list/useHistoryList.js +4 -4
- package/dist/es/layouts/history-list/useHistoryRevert.js +38 -33
- package/dist/es/layouts/page-bar/AddButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageBarScrollContainer.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/Search.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +50 -20
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +53 -35
- package/dist/es/layouts/props-panel/use-style-panel.js +3 -2
- package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +21 -36
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/es/layouts/sidebar/code-block/useContentMenu.js +19 -4
- package/dist/es/layouts/sidebar/data-source/DataSourceAddButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +9 -4
- package/dist/es/layouts/sidebar/data-source/DataSourceList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/es/layouts/sidebar/data-source/useContentMenu.js +19 -4
- package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/sidebar/layer/LayerNodeContent.js +5 -0
- package/dist/es/layouts/sidebar/layer/LayerNodeContent.vue_vue_type_script_setup_true_lang.js +46 -0
- package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +6 -4
- package/dist/es/layouts/sidebar/layer/use-click.js +3 -3
- package/dist/es/layouts/sidebar/layer/use-drag.js +11 -10
- package/dist/es/layouts/sidebar/layer/use-node-status.js +2 -2
- package/dist/es/layouts/workspace/Breadcrumb.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/Workspace.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/viewer/NodeListMenu.vue_vue_type_script_setup_true_lang.js +9 -3
- package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +55 -9
- package/dist/es/layouts/workspace/viewer/StageOverlay.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/es/plugin.js +35 -23
- package/dist/es/services/codeBlock.js +40 -31
- package/dist/es/services/dataSource.js +46 -34
- package/dist/es/services/dep.js +162 -41
- package/dist/es/services/editor.js +373 -137
- package/dist/es/services/events.js +4 -4
- package/dist/es/services/history.js +275 -392
- package/dist/es/services/keybinding.js +3 -3
- package/dist/es/services/props.js +2 -1
- package/dist/es/services/storage.js +2 -2
- package/dist/es/services/ui.js +7 -2
- package/dist/es/style.css +277 -114
- package/dist/es/utils/code-block.js +14 -7
- package/dist/es/utils/config.js +4 -1
- package/dist/es/utils/const.js +2 -2
- package/dist/es/utils/content-menu.js +2 -2
- package/dist/es/utils/data-source/index.js +34 -12
- package/dist/es/utils/dep/collect-worker-client.js +154 -0
- package/dist/es/utils/dep/idle-task.js +70 -22
- package/dist/es/utils/dep/worker.js +1 -1
- package/dist/es/utils/editor.js +4 -2
- package/dist/es/utils/event.js +135 -0
- package/dist/es/utils/history.js +35 -47
- package/dist/es/utils/monaco-editor.js +22 -6
- package/dist/es/utils/operator.js +2 -2
- package/dist/es/utils/props.js +50 -106
- package/dist/es/utils/type-match-rules.js +356 -0
- package/dist/style.css +277 -114
- package/dist/themes/magic-admin.css +978 -175
- package/dist/tmagic-editor-headless.umd.cjs +10880 -0
- package/dist/tmagic-editor.umd.cjs +13047 -11363
- package/package.json +18 -13
- package/src/Editor.vue +23 -6
- package/src/components/CodeBlockEditor.vue +3 -0
- package/src/components/CodeParams.vue +10 -4
- package/src/components/CompareForm.vue +20 -190
- package/src/components/ContentMenu.vue +34 -6
- package/src/components/FloatingBox.vue +71 -7
- package/src/components/ScrollBar.vue +0 -67
- package/src/components/ViewForm.vue +54 -0
- package/src/editorProps.ts +23 -10
- package/src/fields/Code.vue +1 -1
- package/src/fields/CodeSelect.vue +20 -113
- package/src/fields/CodeSelectCol.vue +1 -1
- package/src/fields/CondOpSelect.vue +5 -26
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +2 -2
- package/src/fields/DataSourceFieldSelect/Index.vue +4 -1
- package/src/fields/DataSourceFields.vue +5 -1
- package/src/fields/DataSourceInput.vue +10 -28
- package/src/fields/DataSourceMethodSelect.vue +1 -1
- package/src/fields/DataSourceMethods.vue +6 -2
- package/src/fields/DataSourceMocks.vue +3 -0
- package/src/fields/DataSourceSelect.vue +1 -1
- package/src/fields/DisplayConds.vue +17 -139
- package/src/fields/EventSelect.vue +29 -416
- package/src/fields/KeyValue.vue +1 -1
- package/src/fields/StyleSetter/Index.vue +2 -8
- package/src/fields/StyleSetter/components/Border.vue +4 -38
- package/src/fields/StyleSetter/components/Box.vue +1 -1
- package/src/fields/StyleSetter/components/Position.vue +1 -1
- package/src/fields/StyleSetter/configs.ts +690 -0
- package/src/fields/StyleSetter/pro/Background.vue +9 -64
- package/src/fields/StyleSetter/pro/Border.vue +5 -16
- package/src/fields/StyleSetter/pro/Font.vue +11 -71
- package/src/fields/StyleSetter/pro/Layout.vue +10 -230
- package/src/fields/StyleSetter/pro/Position.vue +11 -82
- package/src/fields/StyleSetter/pro/Transform.vue +6 -34
- package/src/fields/UISelect.vue +0 -12
- package/src/fields/configs/codeSelect.ts +127 -0
- package/src/fields/configs/displayConds.ts +184 -0
- package/src/fields/configs/eventSelect.ts +309 -0
- package/src/fields/configs/stickyAddButton.ts +32 -0
- package/src/fields/headless-validation.ts +177 -0
- package/src/headless.ts +33 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-compare-form.ts +166 -0
- package/src/hooks/use-form-context.ts +56 -0
- package/src/hooks/use-stage.ts +1 -0
- package/src/index.ts +9 -0
- package/src/initService.ts +73 -18
- package/src/layouts/CodeEditor.vue +32 -6
- package/src/layouts/Framework.vue +7 -6
- package/src/layouts/history-list/BucketTab.vue +2 -2
- package/src/layouts/history-list/HistoryDiffDialog.vue +33 -15
- package/src/layouts/history-list/HistoryListPanel.vue +16 -18
- package/src/layouts/history-list/useHistoryRevert.ts +57 -41
- package/src/layouts/props-panel/FormPanel.vue +75 -20
- package/src/layouts/props-panel/PropsPanel.vue +81 -30
- package/src/layouts/props-panel/use-style-panel.ts +4 -3
- package/src/layouts/sidebar/ComponentListPanel.vue +6 -2
- package/src/layouts/sidebar/Sidebar.vue +5 -3
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +5 -2
- package/src/layouts/sidebar/code-block/useContentMenu.ts +14 -2
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +3 -0
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +3 -3
- package/src/layouts/sidebar/data-source/useContentMenu.ts +14 -2
- package/src/layouts/sidebar/layer/LayerMenu.vue +2 -2
- package/src/layouts/sidebar/layer/LayerNodeContent.vue +57 -0
- package/src/layouts/sidebar/layer/LayerPanel.vue +5 -2
- package/src/layouts/sidebar/layer/use-click.ts +3 -3
- package/src/layouts/sidebar/layer/use-node-status.ts +2 -2
- package/src/layouts/workspace/viewer/NodeListMenu.vue +4 -1
- package/src/layouts/workspace/viewer/Stage.vue +80 -10
- package/src/layouts/workspace/viewer/ViewerMenu.vue +7 -7
- package/src/plugin.ts +35 -25
- package/src/services/codeBlock.ts +4 -0
- package/src/services/dataSource.ts +3 -0
- package/src/services/dep.ts +292 -47
- package/src/services/editor.ts +383 -120
- package/src/services/events.ts +8 -7
- package/src/services/history.ts +22 -1
- package/src/services/keybinding.ts +3 -3
- package/src/services/ui.ts +26 -5
- package/src/theme/code-block.scss +0 -37
- package/src/theme/display-conds.scss +4 -0
- package/src/theme/event.scss +25 -33
- package/src/theme/floating-box.scss +9 -1
- package/src/theme/framework.scss +4 -1
- package/src/theme/layer-node-content.scss +14 -0
- package/src/theme/nav-menu.scss +5 -1
- package/src/theme/props-panel.scss +17 -3
- package/src/theme/scroll-bar.scss +64 -0
- package/src/theme/theme.scss +3 -0
- package/src/theme/themes/magic-admin/index.scss +109 -9
- package/src/theme/ui-select.scss +9 -0
- package/src/type.ts +216 -6
- package/src/utils/code-block.ts +1 -0
- package/src/utils/config.ts +9 -1
- package/src/utils/const.ts +3 -3
- package/src/utils/content-menu.ts +2 -2
- package/src/utils/data-source/index.ts +31 -12
- package/src/utils/dep/collect-worker-client.ts +215 -0
- package/src/utils/dep/idle-task.ts +104 -35
- package/src/utils/dep/worker.ts +113 -9
- package/src/utils/event.ts +237 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/monaco-editor.ts +27 -0
- package/src/utils/operator.ts +2 -2
- package/src/utils/props.ts +61 -122
- package/src/utils/type-match-rules.ts +697 -0
- package/types/headless.d.ts +17 -0
- package/types/index.d.ts +1494 -978
- package/src/fields/StyleSetter/icons/align-items/index copy.ts +0 -5
|
@@ -59,6 +59,7 @@ const buildDiffPayload = (source: DiffPayloadSource, index: number, id?: string
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
interface MountedDiffDialog {
|
|
62
|
+
app: ReturnType<typeof createApp>;
|
|
62
63
|
instance: {
|
|
63
64
|
open: (_payload: DiffDialogPayload) => void;
|
|
64
65
|
confirm: (_payload: DiffDialogPayload) => Promise<boolean>;
|
|
@@ -73,9 +74,9 @@ interface MountedDiffDialog {
|
|
|
73
74
|
* 弹窗组件动态 import,避免拖累其它消费者。供「确认回滚」与「查看差异」两种交互共用。
|
|
74
75
|
*/
|
|
75
76
|
const mountHistoryDiffDialog = async (
|
|
76
|
-
options: Pick<UseHistoryRevertOptions, 'appContext'
|
|
77
|
+
options: Pick<UseHistoryRevertOptions, 'appContext'> &
|
|
77
78
|
CustomDiffFormOptions & {
|
|
78
|
-
services
|
|
79
|
+
services?: Services;
|
|
79
80
|
isConfirm?: boolean;
|
|
80
81
|
onClose?: () => void;
|
|
81
82
|
},
|
|
@@ -89,9 +90,10 @@ const mountHistoryDiffDialog = async (
|
|
|
89
90
|
const app = createApp(historyDiffDialog, {
|
|
90
91
|
services: options.services,
|
|
91
92
|
isConfirm: options.isConfirm,
|
|
92
|
-
extendState: options.extendState,
|
|
93
93
|
loadConfig: options.loadConfig,
|
|
94
94
|
selfDiffFieldTypes: options.selfDiffFieldTypes,
|
|
95
|
+
width: options.width,
|
|
96
|
+
size: options.size ?? options.services?.uiService?.get('propsPanelSize'),
|
|
95
97
|
onClose: options.onClose,
|
|
96
98
|
});
|
|
97
99
|
if (options.appContext) {
|
|
@@ -111,7 +113,7 @@ const mountHistoryDiffDialog = async (
|
|
|
111
113
|
}, 300);
|
|
112
114
|
};
|
|
113
115
|
|
|
114
|
-
return { instance, destroy };
|
|
116
|
+
return { app, instance, destroy };
|
|
115
117
|
};
|
|
116
118
|
|
|
117
119
|
/**
|
|
@@ -121,9 +123,9 @@ const mountHistoryDiffDialog = async (
|
|
|
121
123
|
*/
|
|
122
124
|
const confirmRevertWithDiffDialog = async (
|
|
123
125
|
payload: DiffDialogPayload,
|
|
124
|
-
options: Pick<UseHistoryRevertOptions, 'appContext'
|
|
126
|
+
options: Pick<UseHistoryRevertOptions, 'appContext'> &
|
|
125
127
|
CustomDiffFormOptions & {
|
|
126
|
-
services
|
|
128
|
+
services?: Services;
|
|
127
129
|
},
|
|
128
130
|
): Promise<boolean> => {
|
|
129
131
|
const { instance, destroy } = await mountHistoryDiffDialog({
|
|
@@ -143,9 +145,9 @@ const confirmRevertWithDiffDialog = async (
|
|
|
143
145
|
*/
|
|
144
146
|
const viewHistoryDiffDialog = async (
|
|
145
147
|
payload: DiffDialogPayload,
|
|
146
|
-
options: Pick<UseHistoryRevertOptions, 'appContext'
|
|
148
|
+
options: Pick<UseHistoryRevertOptions, 'appContext'> &
|
|
147
149
|
CustomDiffFormOptions & {
|
|
148
|
-
services
|
|
150
|
+
services?: Services;
|
|
149
151
|
},
|
|
150
152
|
): Promise<void> => {
|
|
151
153
|
// onClose 在用户关闭弹窗时才触发,此时 handle.destroy 早已赋值。
|
|
@@ -182,19 +184,15 @@ const viewHistoryDiffDialog = async (
|
|
|
182
184
|
* ```ts
|
|
183
185
|
* import { useHistoryRevert } from '@tmagic/editor';
|
|
184
186
|
*
|
|
185
|
-
* const { onPageRevert, onPageDiff } = useHistoryRevert(editorRef.value); // editorRef.value 即 Editor 暴露的 services
|
|
187
|
+
* const { onPageRevert, onPageDiff } = useHistoryRevert({}, editorRef.value); // editorRef.value 即 Editor 暴露的 services
|
|
186
188
|
* await onPageRevert(index); // 弹出差异 / 二次确认弹窗后回滚
|
|
187
189
|
* onPageDiff(index); // 弹出只读差异弹窗查看前后值差异
|
|
188
190
|
* ```
|
|
189
191
|
*/
|
|
190
|
-
export const useHistoryRevert = (
|
|
191
|
-
services: Pick<Services, 'editorService' | 'dataSourceService' | 'codeBlockService' | 'historyService'>,
|
|
192
|
-
options: UseHistoryRevertOptions = {},
|
|
193
|
-
) => {
|
|
194
|
-
const { editorService, dataSourceService, codeBlockService, historyService } = services;
|
|
192
|
+
export const useHistoryRevert = (options: UseHistoryRevertOptions = {}, services?: Services) => {
|
|
195
193
|
// 自动捕获调用方所在组件的 appContext(在 setup 中调用时),业务方亦可显式覆盖。
|
|
196
194
|
const appContext = options.appContext ?? getCurrentInstance()?.appContext ?? null;
|
|
197
|
-
const {
|
|
195
|
+
const { dialogWidth } = options;
|
|
198
196
|
|
|
199
197
|
/** 目标数据已被删除、无法回滚时的统一提示。 */
|
|
200
198
|
const showRevertTargetMissing = () => {
|
|
@@ -206,10 +204,7 @@ export const useHistoryRevert = (
|
|
|
206
204
|
* 不弹差异弹窗,改用一个普通确认框替代「确定回滚」按钮,避免点击后无任何提示直接执行。
|
|
207
205
|
* 用户取消时返回 false,调用方据此中止回滚。
|
|
208
206
|
*/
|
|
209
|
-
const confirmRevert = (): Promise<boolean> =>
|
|
210
|
-
confirmHistoryAction(
|
|
211
|
-
'确定回滚该步骤吗?回滚会将该操作作为一条新记录反向应用(新增将被删除、删除将被还原),不影响后续历史记录。',
|
|
212
|
-
);
|
|
207
|
+
const confirmRevert = (): Promise<boolean> => confirmHistoryAction('确定回滚该步骤吗?');
|
|
213
208
|
|
|
214
209
|
/**
|
|
215
210
|
* 「回滚」统一确认入口:可差异对比的步骤动态挂载 HistoryDiffDialog 走差异确认弹窗,
|
|
@@ -218,7 +213,13 @@ export const useHistoryRevert = (
|
|
|
218
213
|
*/
|
|
219
214
|
const runRevert = (payload: DiffDialogPayload | null, extra?: CustomDiffFormOptions): Promise<boolean> => {
|
|
220
215
|
if (payload) {
|
|
221
|
-
return confirmRevertWithDiffDialog(payload, {
|
|
216
|
+
return confirmRevertWithDiffDialog(payload, {
|
|
217
|
+
appContext,
|
|
218
|
+
services,
|
|
219
|
+
...extra,
|
|
220
|
+
width: extra?.width ?? dialogWidth,
|
|
221
|
+
size: extra?.size,
|
|
222
|
+
});
|
|
222
223
|
}
|
|
223
224
|
return confirmRevert();
|
|
224
225
|
};
|
|
@@ -227,8 +228,8 @@ export const useHistoryRevert = (
|
|
|
227
228
|
buildDiffPayload(
|
|
228
229
|
{
|
|
229
230
|
category: 'node',
|
|
230
|
-
groups: () => historyService.getHistoryGroups('page', editorService.get('page')?.id),
|
|
231
|
-
getCurrent: (id) => editorService.getNodeById(id) as Record<string, any> | null,
|
|
231
|
+
groups: () => services?.historyService.getHistoryGroups('page', services?.editorService.get('page')?.id) ?? [],
|
|
232
|
+
getCurrent: (id) => services?.editorService.getNodeById(id) as Record<string, any> | null,
|
|
232
233
|
resolveType: (n, o) => n.type || o.type || '',
|
|
233
234
|
resolveLabel: (n, o) => n.name || o.name || n.type || o.type || '',
|
|
234
235
|
},
|
|
@@ -239,8 +240,8 @@ export const useHistoryRevert = (
|
|
|
239
240
|
buildDiffPayload(
|
|
240
241
|
{
|
|
241
242
|
category: 'data-source',
|
|
242
|
-
groups: () => historyService.getHistoryGroups('dataSource'),
|
|
243
|
-
getCurrent: (id) => dataSourceService.getDataSourceById(`${id}`) as Record<string, any> | null,
|
|
243
|
+
groups: () => services?.historyService.getHistoryGroups('dataSource') ?? [],
|
|
244
|
+
getCurrent: (id) => services?.dataSourceService.getDataSourceById(`${id}`) as Record<string, any> | null,
|
|
244
245
|
resolveType: (n, o) => n.type || o.type || 'base',
|
|
245
246
|
resolveLabel: (n, o, id) => n.title || o.title || `${id}`,
|
|
246
247
|
},
|
|
@@ -252,8 +253,8 @@ export const useHistoryRevert = (
|
|
|
252
253
|
buildDiffPayload(
|
|
253
254
|
{
|
|
254
255
|
category: 'code-block',
|
|
255
|
-
groups: () => historyService.getHistoryGroups('codeBlock'),
|
|
256
|
-
getCurrent: (id) => codeBlockService.getCodeContentById(id) as Record<string, any> | null,
|
|
256
|
+
groups: () => services?.historyService.getHistoryGroups('codeBlock') ?? [],
|
|
257
|
+
getCurrent: (id) => services?.codeBlockService.getCodeContentById(id) as Record<string, any> | null,
|
|
257
258
|
resolveLabel: (n, o, id) => n.name || o.name || `${id}`,
|
|
258
259
|
},
|
|
259
260
|
index,
|
|
@@ -267,17 +268,17 @@ export const useHistoryRevert = (
|
|
|
267
268
|
* add(回滚即删除)即使目标已不在,也已达成「删除」目的,不视为失败。
|
|
268
269
|
*/
|
|
269
270
|
const isPageRevertTargetMissing = (index: number): boolean => {
|
|
270
|
-
const step = historyService.getStepList('page', editorService.get('page')?.id)[index]?.step;
|
|
271
|
+
const step = services?.historyService.getStepList('page', services?.editorService.get('page')?.id)[index]?.step;
|
|
271
272
|
if (!step) return false;
|
|
272
273
|
if (step.opType === 'update') {
|
|
273
274
|
return (step.diff ?? []).some((item) => {
|
|
274
275
|
const id = item.newSchema?.id ?? item.oldSchema?.id;
|
|
275
|
-
return id !== undefined && !editorService.getNodeById(id, false);
|
|
276
|
+
return id !== undefined && !services?.editorService.getNodeById(id, false);
|
|
276
277
|
});
|
|
277
278
|
}
|
|
278
279
|
if (step.opType === 'remove') {
|
|
279
280
|
return (step.diff ?? []).some(
|
|
280
|
-
(item) => item.parentId !== undefined && !editorService.getNodeById(item.parentId, false),
|
|
281
|
+
(item) => item.parentId !== undefined && !services?.editorService.getNodeById(item.parentId, false),
|
|
281
282
|
);
|
|
282
283
|
}
|
|
283
284
|
return false;
|
|
@@ -285,14 +286,14 @@ export const useHistoryRevert = (
|
|
|
285
286
|
|
|
286
287
|
/** 数据源 update 步骤回滚时,对应数据源必须仍存在(已删除则无处写回旧值)。 */
|
|
287
288
|
const isDataSourceRevertTargetMissing = (id: string | number, index: number): boolean => {
|
|
288
|
-
const step = historyService.getStepList('dataSource', id)[index]?.step;
|
|
289
|
-
return Boolean(step?.opType === 'update' && !dataSourceService.getDataSourceById(`${id}`));
|
|
289
|
+
const step = services?.historyService.getStepList('dataSource', id)[index]?.step;
|
|
290
|
+
return Boolean(step?.opType === 'update' && !services?.dataSourceService.getDataSourceById(`${id}`));
|
|
290
291
|
};
|
|
291
292
|
|
|
292
293
|
/** 代码块 update 步骤回滚时,对应代码块必须仍存在(已删除则无处写回旧值)。 */
|
|
293
294
|
const isCodeBlockRevertTargetMissing = (id: string | number, index: number): boolean => {
|
|
294
|
-
const step = historyService.getStepList('codeBlock', id)[index]?.step;
|
|
295
|
-
return Boolean(step?.opType === 'update' && !codeBlockService.getCodeContentById(id));
|
|
295
|
+
const step = services?.historyService.getStepList('codeBlock', id)[index]?.step;
|
|
296
|
+
return Boolean(step?.opType === 'update' && !services?.codeBlockService.getCodeContentById(id));
|
|
296
297
|
};
|
|
297
298
|
|
|
298
299
|
const onPageRevert = (index: number) => {
|
|
@@ -300,8 +301,8 @@ export const useHistoryRevert = (
|
|
|
300
301
|
showRevertTargetMissing();
|
|
301
302
|
return Promise.resolve(null);
|
|
302
303
|
}
|
|
303
|
-
return runRevert(buildPageDiffPayload(index)).then((result) =>
|
|
304
|
-
result ? editorService.revertPageStep(index) : null,
|
|
304
|
+
return runRevert(buildPageDiffPayload(index), {}).then((result) =>
|
|
305
|
+
result ? services?.editorService.revertPageStep(index) : null,
|
|
305
306
|
);
|
|
306
307
|
};
|
|
307
308
|
|
|
@@ -311,7 +312,7 @@ export const useHistoryRevert = (
|
|
|
311
312
|
return Promise.resolve(null);
|
|
312
313
|
}
|
|
313
314
|
return runRevert(buildDataSourceDiffPayload(id, index)).then((result) =>
|
|
314
|
-
result ? dataSourceService.revert(id, index) : null,
|
|
315
|
+
result ? services?.dataSourceService.revert(id, index) : null,
|
|
315
316
|
);
|
|
316
317
|
};
|
|
317
318
|
|
|
@@ -321,7 +322,7 @@ export const useHistoryRevert = (
|
|
|
321
322
|
return Promise.resolve(null);
|
|
322
323
|
}
|
|
323
324
|
return runRevert(buildCodeBlockDiffPayload(id, index)).then((result) =>
|
|
324
|
-
result ? codeBlockService.revert(id, index) : null,
|
|
325
|
+
result ? services?.codeBlockService.revert(id, index) : null,
|
|
325
326
|
);
|
|
326
327
|
};
|
|
327
328
|
|
|
@@ -331,17 +332,23 @@ export const useHistoryRevert = (
|
|
|
331
332
|
*/
|
|
332
333
|
const onPageDiff = (index: number): Promise<void> | void => {
|
|
333
334
|
const payload = buildPageDiffPayload(index);
|
|
334
|
-
if (payload)
|
|
335
|
+
if (payload) {
|
|
336
|
+
return viewHistoryDiffDialog(payload, {
|
|
337
|
+
appContext,
|
|
338
|
+
services,
|
|
339
|
+
width: dialogWidth,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
335
342
|
};
|
|
336
343
|
|
|
337
344
|
const onDataSourceDiff = (id: string | number, index: number): Promise<void> | void => {
|
|
338
345
|
const payload = buildDataSourceDiffPayload(id, index);
|
|
339
|
-
if (payload) return viewHistoryDiffDialog(payload, { appContext,
|
|
346
|
+
if (payload) return viewHistoryDiffDialog(payload, { appContext, services, width: dialogWidth });
|
|
340
347
|
};
|
|
341
348
|
|
|
342
349
|
const onCodeBlockDiff = (id: string | number, index: number): Promise<void> | void => {
|
|
343
350
|
const payload = buildCodeBlockDiffPayload(id, index);
|
|
344
|
-
if (payload) return viewHistoryDiffDialog(payload, { appContext,
|
|
351
|
+
if (payload) return viewHistoryDiffDialog(payload, { appContext, services, width: dialogWidth });
|
|
345
352
|
};
|
|
346
353
|
|
|
347
354
|
/**
|
|
@@ -368,6 +375,8 @@ export const useHistoryRevert = (
|
|
|
368
375
|
const confirmed = await runRevert(revertOptions.diffPayload ?? null, {
|
|
369
376
|
loadConfig: revertOptions.loadConfig,
|
|
370
377
|
selfDiffFieldTypes: revertOptions.selfDiffFieldTypes,
|
|
378
|
+
width: revertOptions.width,
|
|
379
|
+
size: revertOptions.size,
|
|
371
380
|
});
|
|
372
381
|
if (!confirmed) return null;
|
|
373
382
|
return await revertOptions.revert();
|
|
@@ -378,7 +387,14 @@ export const useHistoryRevert = (
|
|
|
378
387
|
* 可透传 `loadConfig` / `selfDiffFieldTypes`。payload 为 null(不可对比)时静默返回。
|
|
379
388
|
*/
|
|
380
389
|
const viewDiff = (payload: DiffDialogPayload | null, extra?: CustomDiffFormOptions): Promise<void> | void => {
|
|
381
|
-
if (payload)
|
|
390
|
+
if (payload)
|
|
391
|
+
return viewHistoryDiffDialog(payload, {
|
|
392
|
+
appContext,
|
|
393
|
+
services,
|
|
394
|
+
...extra,
|
|
395
|
+
width: extra?.width ?? dialogWidth,
|
|
396
|
+
size: extra?.size,
|
|
397
|
+
});
|
|
382
398
|
};
|
|
383
399
|
|
|
384
400
|
return {
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
:size="propsPanelSize"
|
|
13
13
|
:init-values="values"
|
|
14
14
|
:config="config"
|
|
15
|
-
:
|
|
15
|
+
:type-match-valid="true"
|
|
16
|
+
:context="formContext"
|
|
17
|
+
:validate-on-init="true"
|
|
16
18
|
@change="submit"
|
|
17
19
|
@error="errorHandler"
|
|
18
20
|
></MForm>
|
|
@@ -43,15 +45,18 @@
|
|
|
43
45
|
</template>
|
|
44
46
|
|
|
45
47
|
<script setup lang="ts">
|
|
46
|
-
import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, useTemplateRef
|
|
48
|
+
import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, useTemplateRef } from 'vue';
|
|
47
49
|
import { Document as DocumentIcon } from '@element-plus/icons-vue';
|
|
48
50
|
|
|
49
|
-
import { TMagicButton, TMagicScrollbar } from '@tmagic/design';
|
|
50
|
-
import type { ContainerChangeEventData, FormConfig,
|
|
51
|
-
import { MForm } from '@tmagic/form';
|
|
51
|
+
import { TMagicButton, tMagicMessage, TMagicScrollbar } from '@tmagic/design';
|
|
52
|
+
import type { ContainerChangeEventData, FormConfig, FormValue } from '@tmagic/form';
|
|
53
|
+
import { MForm, validateForm } from '@tmagic/form';
|
|
54
|
+
import { filterXSS } from '@tmagic/utils';
|
|
52
55
|
|
|
53
56
|
import MIcon from '@editor/components/Icon.vue';
|
|
57
|
+
import { ENABLE_PROPS_FORM_VALIDATE } from '@editor/editorProps';
|
|
54
58
|
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
|
|
59
|
+
import { useEditorFormContext } from '@editor/hooks/use-form-context';
|
|
55
60
|
import { useServices } from '@editor/hooks/use-services';
|
|
56
61
|
|
|
57
62
|
import CodeEditor from '../CodeEditor.vue';
|
|
@@ -70,36 +75,31 @@ const props = defineProps<{
|
|
|
70
75
|
disabledShowSrc?: boolean;
|
|
71
76
|
labelWidth?: string;
|
|
72
77
|
codeValueKey?: string;
|
|
73
|
-
labelPosition?:
|
|
74
|
-
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
78
|
+
labelPosition?: 'top' | 'left' | 'right';
|
|
75
79
|
}>();
|
|
76
80
|
|
|
77
81
|
const emit = defineEmits<{
|
|
78
|
-
submit: [values: any, eventData?: ContainerChangeEventData];
|
|
82
|
+
submit: [values: any, eventData?: ContainerChangeEventData, error?: any];
|
|
79
83
|
'submit-error': [e: any];
|
|
80
84
|
'form-error': [e: any];
|
|
81
85
|
mounted: [internalInstance: any];
|
|
82
86
|
unmounted: [];
|
|
83
87
|
}>();
|
|
84
88
|
|
|
89
|
+
const enablePropsFormValidate = inject(ENABLE_PROPS_FORM_VALIDATE, false);
|
|
90
|
+
|
|
85
91
|
const services = useServices();
|
|
86
|
-
const {
|
|
92
|
+
const { uiService } = services;
|
|
87
93
|
|
|
88
94
|
const codeOptions = inject('codeOptions', {});
|
|
89
95
|
|
|
90
96
|
const showSrc = ref(false);
|
|
91
97
|
const propsPanelSize = computed(() => uiService.get('propsPanelSize') || 'small');
|
|
92
98
|
const { height: editorContentHeight } = useEditorContentHeight();
|
|
93
|
-
const stage = computed(() => editorService.get('stage'));
|
|
94
99
|
|
|
95
|
-
const
|
|
100
|
+
const formContext = useEditorFormContext(() => services);
|
|
96
101
|
|
|
97
|
-
|
|
98
|
-
if (configFormRef.value) {
|
|
99
|
-
configFormRef.value.formState.stage = stage.value;
|
|
100
|
-
configFormRef.value.formState.services = services;
|
|
101
|
-
}
|
|
102
|
-
});
|
|
102
|
+
const configFormRef = useTemplateRef<InstanceType<typeof MForm>>('configForm');
|
|
103
103
|
|
|
104
104
|
const internalInstance = getCurrentInstance();
|
|
105
105
|
onMounted(() => {
|
|
@@ -113,9 +113,16 @@ onUnmounted(() => {
|
|
|
113
113
|
const submit = async (v: FormValue, eventData: ContainerChangeEventData) => {
|
|
114
114
|
try {
|
|
115
115
|
const values = await configFormRef.value?.submitForm();
|
|
116
|
+
// 校验成功:正常更新节点(第三个参数 error 为空,表示清除该来源的错误记录)
|
|
116
117
|
emit('submit', values, eventData);
|
|
117
118
|
} catch (e: any) {
|
|
118
|
-
|
|
119
|
+
if (enablePropsFormValidate) {
|
|
120
|
+
// 启用校验联动:校验失败时仍以当前表单值更新节点,并把错误信息一并抛给上层记录
|
|
121
|
+
emit('submit', v, eventData, e);
|
|
122
|
+
} else {
|
|
123
|
+
// 未启用:保持原行为,校验失败丢弃本次改动
|
|
124
|
+
emit('submit-error', e);
|
|
125
|
+
}
|
|
119
126
|
}
|
|
120
127
|
};
|
|
121
128
|
|
|
@@ -123,8 +130,56 @@ const errorHandler = (e: any) => {
|
|
|
123
130
|
emit('form-error', e);
|
|
124
131
|
};
|
|
125
132
|
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
/**
|
|
134
|
+
* 将校验错误文案安全地转为用于弹窗展示的 HTML。
|
|
135
|
+
*
|
|
136
|
+
* 文案形如 `字段 -> 主文案\n\n建议`,多条以结构性 `<br>` 拼接。为在保留换行排版的同时
|
|
137
|
+
* 避免 `${value}`/字段名中可能夹带的 HTML 造成 XSS:先按结构性 `<br>` 拆分,对每段做 HTML
|
|
138
|
+
* 转义后再把段内换行 `\n` 替换为 `<br>`,最后用 `<br>` 拼回。
|
|
139
|
+
*/
|
|
140
|
+
const formatValidateErrorHtml = (error: string): string =>
|
|
141
|
+
error
|
|
142
|
+
.split(/<br\s*\/?>/i)
|
|
143
|
+
.map((segment) => filterXSS(segment).replaceAll('\n', '<br>'))
|
|
144
|
+
.join('<br>');
|
|
145
|
+
|
|
146
|
+
const saveCode = async (values: any) => {
|
|
147
|
+
const newValues = props.codeValueKey ? { [props.codeValueKey]: values } : values;
|
|
148
|
+
|
|
149
|
+
if (!enablePropsFormValidate) {
|
|
150
|
+
// 未启用校验联动:保持原行为,直接提交源码保存的值
|
|
151
|
+
emit('submit', newValues);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 启用校验联动:源码编辑器保存的值未经过表单交互,这里对最新配置做一次无渲染的静默校验
|
|
156
|
+
// (不挂载任何组件,也不影响页面上正在展示的表单),并将校验结果(错误信息)随提交
|
|
157
|
+
// 一并抛给上层记录,使源码保存的错误状态与表单编辑保持一致。
|
|
158
|
+
//
|
|
159
|
+
// 配置里的 display / rules 回调会从 formState 上读 services,因此必须带上 context。
|
|
160
|
+
try {
|
|
161
|
+
const error = await validateForm({
|
|
162
|
+
config: props.config,
|
|
163
|
+
typeMatchValid: true,
|
|
164
|
+
initValues: newValues,
|
|
165
|
+
context: formContext.value,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (error) {
|
|
169
|
+
tMagicMessage({
|
|
170
|
+
type: 'error',
|
|
171
|
+
message: formatValidateErrorHtml(error),
|
|
172
|
+
dangerouslyUseHTMLString: true,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
emit('submit', newValues, undefined, error ? new Error(error) : undefined);
|
|
177
|
+
} catch (e: any) {
|
|
178
|
+
console.error('validateForm error', e);
|
|
179
|
+
// 嵌套配置 / initValue 等机制故障不得当成「校验通过」,
|
|
180
|
+
// 把 error 交给上层记录,同时仍提交源码,避免阻塞保存。
|
|
181
|
+
emit('submit', newValues, undefined, e instanceof Error ? e : new Error(String(e)));
|
|
182
|
+
}
|
|
128
183
|
};
|
|
129
184
|
|
|
130
185
|
defineExpose({ configForm: configFormRef, submit });
|
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
:config="curFormConfig"
|
|
9
9
|
:values="values"
|
|
10
10
|
:disabledShowSrc="disabledShowSrc"
|
|
11
|
-
|
|
12
|
-
@submit="submit"
|
|
11
|
+
@submit="(v, eventData, error) => submit(v, eventData, error, 'props')"
|
|
13
12
|
@submit-error="errorHandler"
|
|
14
13
|
@form-error="errorHandler"
|
|
15
14
|
@mounted="mountedHandler"
|
|
@@ -26,8 +25,7 @@
|
|
|
26
25
|
:config="styleFormConfig"
|
|
27
26
|
:values="values"
|
|
28
27
|
:disabledShowSrc="disabledShowSrc"
|
|
29
|
-
|
|
30
|
-
@submit="submit"
|
|
28
|
+
@submit="(v, eventData, error) => submit(v, eventData, error, 'style')"
|
|
31
29
|
@submit-error="errorHandler"
|
|
32
30
|
@form-error="errorHandler"
|
|
33
31
|
>
|
|
@@ -55,20 +53,21 @@
|
|
|
55
53
|
</template>
|
|
56
54
|
|
|
57
55
|
<script lang="ts" setup>
|
|
58
|
-
import { computed, onBeforeUnmount, onMounted, ref, useTemplateRef, watch, watchEffect } from 'vue';
|
|
56
|
+
import { computed, inject, onBeforeUnmount, onMounted, ref, useTemplateRef, watch, watchEffect } from 'vue';
|
|
59
57
|
import { Close, Sugar } from '@element-plus/icons-vue';
|
|
60
58
|
import type { OnDrag } from 'gesto';
|
|
61
59
|
|
|
62
60
|
import { type MNode } from '@tmagic/core';
|
|
63
61
|
import { TMagicButton } from '@tmagic/design';
|
|
64
|
-
import type { ContainerChangeEventData,
|
|
62
|
+
import type { ContainerChangeEventData, FormValue } from '@tmagic/form';
|
|
65
63
|
import { setValueByKeyPath } from '@tmagic/utils';
|
|
66
64
|
|
|
67
65
|
import MIcon from '@editor/components/Icon.vue';
|
|
68
66
|
import Resizer from '@editor/components/Resizer.vue';
|
|
67
|
+
import { ENABLE_PROPS_FORM_VALIDATE } from '@editor/editorProps';
|
|
69
68
|
import { useServices } from '@editor/hooks/use-services';
|
|
70
69
|
import { Protocol } from '@editor/services/storage';
|
|
71
|
-
import type { PropsPanelSlots } from '@editor/type';
|
|
70
|
+
import type { NodeInvalidSource, PropsPanelSlots } from '@editor/type';
|
|
72
71
|
import { styleTabConfig } from '@editor/utils';
|
|
73
72
|
import { PROPS_PANEL_WIDTH_STORAGE_KEY } from '@editor/utils/const';
|
|
74
73
|
|
|
@@ -83,7 +82,6 @@ defineOptions({
|
|
|
83
82
|
|
|
84
83
|
defineProps<{
|
|
85
84
|
disabledShowSrc?: boolean;
|
|
86
|
-
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
87
85
|
}>();
|
|
88
86
|
|
|
89
87
|
const emit = defineEmits<{
|
|
@@ -95,6 +93,8 @@ const emit = defineEmits<{
|
|
|
95
93
|
|
|
96
94
|
const { editorService, uiService, propsService, storageService } = useServices();
|
|
97
95
|
|
|
96
|
+
const enablePropsFormValidate = inject(ENABLE_PROPS_FORM_VALIDATE, false);
|
|
97
|
+
|
|
98
98
|
const values = ref<FormValue>({});
|
|
99
99
|
// ts类型应该是FormConfig, 但是打包时会出错,所以暂时用any
|
|
100
100
|
const curFormConfig = ref<any>([]);
|
|
@@ -108,14 +108,31 @@ const styleFormConfig = [
|
|
|
108
108
|
},
|
|
109
109
|
];
|
|
110
110
|
|
|
111
|
+
// 用单调递增序号标记每次 init 调用,只让"最新一次"的 await 结果落到 ref 上。
|
|
112
|
+
// 避免节点快速切换时多个 init 并发 + 解析顺序错乱导致 stale config 覆盖最新选中节点,
|
|
113
|
+
// 以及组件已卸载 / FormPanel 正在 remount 的中间态下写 ref 触发 Vue setRef 把 __vnode
|
|
114
|
+
// 设到 null 上的报错(TypeError: Cannot set properties of null (setting '__vnode'))。
|
|
115
|
+
let initSeq = 0;
|
|
116
|
+
let mounted = true;
|
|
117
|
+
|
|
111
118
|
const init = async () => {
|
|
119
|
+
initSeq += 1;
|
|
120
|
+
const seq = initSeq;
|
|
121
|
+
|
|
112
122
|
if (!node.value) {
|
|
123
|
+
if (seq !== initSeq || !mounted) return;
|
|
113
124
|
curFormConfig.value = [];
|
|
114
125
|
return;
|
|
115
126
|
}
|
|
116
127
|
|
|
117
128
|
const type = node.value.type || (node.value.items ? 'container' : 'text');
|
|
118
|
-
|
|
129
|
+
const config = await propsService.getPropsConfig(type, { node: node.value });
|
|
130
|
+
|
|
131
|
+
// 期间被新一次 init 取代 / 组件已卸载,丢弃本次结果
|
|
132
|
+
if (seq !== initSeq || !mounted) return;
|
|
133
|
+
if (!node.value) return;
|
|
134
|
+
|
|
135
|
+
curFormConfig.value = config;
|
|
119
136
|
values.value = node.value;
|
|
120
137
|
};
|
|
121
138
|
|
|
@@ -123,39 +140,73 @@ watchEffect(init);
|
|
|
123
140
|
propsService.on('props-configs-change', init);
|
|
124
141
|
|
|
125
142
|
onBeforeUnmount(() => {
|
|
143
|
+
mounted = false;
|
|
126
144
|
propsService.off('props-configs-change', init);
|
|
127
145
|
});
|
|
128
146
|
|
|
129
|
-
const submit = async (
|
|
147
|
+
const submit = async (
|
|
148
|
+
v: MNode,
|
|
149
|
+
eventData?: ContainerChangeEventData,
|
|
150
|
+
error?: any,
|
|
151
|
+
source: NodeInvalidSource = 'props',
|
|
152
|
+
) => {
|
|
130
153
|
try {
|
|
131
154
|
if (!v.id) {
|
|
132
155
|
v.id = values.value.id;
|
|
133
156
|
}
|
|
134
157
|
|
|
135
|
-
const newValue: MNode = {
|
|
136
|
-
...v,
|
|
137
|
-
style: {},
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
if (v.style) {
|
|
141
|
-
Object.entries(v.style).forEach(([key, value]) => {
|
|
142
|
-
if (value !== '' && newValue.style) {
|
|
143
|
-
newValue.style[key] = value;
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
eventData?.changeRecords?.forEach((record) => {
|
|
148
|
-
if (record.propPath?.startsWith('style') && record.value === '') {
|
|
149
|
-
setValueByKeyPath(record.propPath, record.value, newValue);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
158
|
// 区分操作途径:表单字段编辑(MForm @change)会带上 eventData(含 changeRecords);
|
|
155
159
|
// 源码编辑器(CodeEditor @save → saveCode)保存时不带 eventData,据此标记为「源码编辑器」。
|
|
156
160
|
const historySource = eventData ? 'props' : 'code';
|
|
161
|
+
// 源码编辑统一走整节点 replace,避免 merge 保留已删除字段。
|
|
162
|
+
const replace = historySource === 'code';
|
|
163
|
+
|
|
164
|
+
let newValue: MNode;
|
|
165
|
+
|
|
166
|
+
if (replace) {
|
|
167
|
+
if (source === 'style') {
|
|
168
|
+
// 样式面板源码仅提交 { style }:先把新 style 替换到原节点上,再整节点覆盖。
|
|
169
|
+
newValue = {
|
|
170
|
+
...values.value,
|
|
171
|
+
id: v.id || values.value.id,
|
|
172
|
+
style: { ...(v.style || {}) },
|
|
173
|
+
};
|
|
174
|
+
} else {
|
|
175
|
+
// 属性面板源码提交完整节点 DSL
|
|
176
|
+
newValue = { ...v };
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
newValue = {
|
|
180
|
+
...v,
|
|
181
|
+
style: {},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
if (v.style) {
|
|
185
|
+
// 空字符串样式值表示「清除该样式」,需保留才能在 doUpdate 的 mergeWith 中覆盖旧值。
|
|
186
|
+
// 表单编辑:先过滤掉空字符串(避免表单默认空值污染 DSL),
|
|
187
|
+
// 再按 changeRecords 恢复被主动清空的字段。
|
|
188
|
+
Object.entries(v.style).forEach(([key, value]) => {
|
|
189
|
+
if (value !== '' && newValue.style) {
|
|
190
|
+
newValue.style[key] = value;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
eventData?.changeRecords?.forEach((record) => {
|
|
195
|
+
if (record.propPath?.startsWith('style') && record.value === '') {
|
|
196
|
+
setValueByKeyPath(record.propPath, record.value, newValue);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
157
201
|
|
|
158
|
-
editorService.update(newValue, {
|
|
202
|
+
editorService.update(newValue, {
|
|
203
|
+
changeRecords: eventData?.changeRecords,
|
|
204
|
+
historySource,
|
|
205
|
+
replace,
|
|
206
|
+
// 启用校验联动时,仅校验失败(error 存在)才把错误信息随更新传入 editorService 记录;
|
|
207
|
+
// 其余情况(含表单校验成功、CodeEditor 源码保存)不携带 invalidInfo,由 editorService 在执行 update 时统一清除该节点错误。
|
|
208
|
+
...(enablePropsFormValidate && error ? { invalidInfo: { id: newValue.id, source, error: error?.message } } : {}),
|
|
209
|
+
});
|
|
159
210
|
} catch (e: any) {
|
|
160
211
|
emit('submit-error', e);
|
|
161
212
|
}
|
|
@@ -2,7 +2,7 @@ import { computed, type Ref, watch } from 'vue';
|
|
|
2
2
|
|
|
3
3
|
import { Protocol } from '@editor/services/storage';
|
|
4
4
|
import { Services } from '@editor/type';
|
|
5
|
-
import {
|
|
5
|
+
import { RIGHT_COLUMN_WIDTH_STORAGE_KEY } from '@editor/utils/const';
|
|
6
6
|
|
|
7
7
|
export const useStylePanel = (
|
|
8
8
|
{ uiService, storageService }: Pick<Services, 'uiService' | 'storageService'>,
|
|
@@ -47,8 +47,9 @@ export const useStylePanel = (
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
if (columnWidth.center < 0) {
|
|
50
|
-
|
|
51
|
-
columnWidth.
|
|
50
|
+
const minCenterColumnWidth = uiService.get('minCenterColumnWidth');
|
|
51
|
+
columnWidth.right = columnWidth.right + columnWidth.center - minCenterColumnWidth;
|
|
52
|
+
columnWidth.center = minCenterColumnWidth;
|
|
52
53
|
|
|
53
54
|
propsPanelWidth.value = columnWidth.right / 2;
|
|
54
55
|
}
|
|
@@ -71,7 +71,11 @@ const stage = computed(() => editorService.get('stage'));
|
|
|
71
71
|
const list = computed<ComponentGroup[]>(() =>
|
|
72
72
|
componentListService.getList().map((group: ComponentGroup) => ({
|
|
73
73
|
...group,
|
|
74
|
-
items: group.items.filter((item: ComponentItem) =>
|
|
74
|
+
items: group.items.filter((item: ComponentItem) =>
|
|
75
|
+
`${item.text || ''}${item.desc || ''}${item.type}`
|
|
76
|
+
.toLocaleLowerCase()
|
|
77
|
+
.includes(searchText.value.toLocaleLowerCase()),
|
|
78
|
+
),
|
|
75
79
|
})),
|
|
76
80
|
);
|
|
77
81
|
|
|
@@ -145,6 +149,6 @@ const dragHandler = (e: DragEvent) => {
|
|
|
145
149
|
|
|
146
150
|
if (timeout || !stage.value) return;
|
|
147
151
|
|
|
148
|
-
timeout = stage.value.delayedMarkContainer(e);
|
|
152
|
+
timeout = stage.value.delayedMarkContainer(e, [], true);
|
|
149
153
|
};
|
|
150
154
|
</script>
|