@tmagic/editor 1.8.0-beta.1 → 1.8.0-beta.11
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 +31 -5
- package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +21 -113
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +7 -1
- package/dist/es/components/CompareForm.js +5 -0
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +196 -0
- package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +2 -2
- 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.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/editorProps.js +2 -0
- package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +20 -4
- package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +3 -6
- package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +19 -3
- package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +42 -8
- package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +14 -6
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +41 -16
- package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +9 -5
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +40 -19
- package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +17 -9
- package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +59 -12
- package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +12 -7
- 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 +1 -1
- 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 +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/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 +1 -1
- package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +9 -6
- package/dist/es/hooks/use-code-block-edit.js +7 -4
- package/dist/es/hooks/use-data-source-edit.js +5 -2
- package/dist/es/hooks/use-stage.js +22 -10
- 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/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/index.js +14 -3
- package/dist/es/initService.js +7 -7
- 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 +7 -6
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +14 -9
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +12 -4
- package/dist/es/layouts/NavMenuColumn.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/Bucket.js +5 -0
- package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +71 -0
- 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.js +5 -0
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +269 -0
- package/dist/es/layouts/history-list/HistoryDiffDialog.js +5 -0
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +294 -0
- package/dist/es/layouts/history-list/HistoryListPanel.js +5 -0
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +327 -0
- package/dist/es/layouts/history-list/InitialRow.js +5 -0
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +83 -0
- package/dist/es/layouts/history-list/PageTab.js +5 -0
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +95 -0
- package/dist/es/layouts/history-list/composables.js +184 -0
- package/dist/es/layouts/history-list/useHistoryList.js +56 -0
- package/dist/es/layouts/history-list/useHistoryRevert.js +313 -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 +1 -1
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +6 -2
- package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +8 -4
- 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 +2 -2
- package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
- 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 +19 -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 +25 -3
- package/dist/es/layouts/sidebar/data-source/useContentMenu.js +1 -1
- package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +6 -6
- 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 +1 -1
- package/dist/es/layouts/sidebar/layer/use-node-status.js +1 -1
- 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 +1 -1
- 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 +9 -9
- package/dist/es/services/BaseService.js +31 -68
- package/dist/es/services/codeBlock.js +286 -8
- package/dist/es/services/componentList.js +2 -2
- package/dist/es/services/dataSource.js +287 -8
- package/dist/es/services/dep.js +21 -9
- package/dist/es/services/editor.js +655 -194
- package/dist/es/services/events.js +2 -2
- package/dist/es/services/history.js +390 -47
- package/dist/es/services/keybinding.js +5 -5
- package/dist/es/services/props.js +8 -8
- package/dist/es/services/stageOverlay.js +2 -2
- package/dist/es/services/storage.js +2 -2
- package/dist/es/services/ui.js +5 -2
- package/dist/es/style.css +456 -8
- package/dist/es/utils/code-block.js +122 -0
- package/dist/es/utils/content-menu.js +19 -12
- package/dist/es/utils/data-source/index.js +2 -0
- package/dist/es/utils/dep/worker.js +1 -1
- package/dist/es/utils/editor.js +105 -51
- package/dist/es/utils/history.js +220 -0
- package/dist/es/utils/indexed-db.js +86 -0
- package/dist/es/utils/undo-redo.js +80 -1
- package/dist/style.css +456 -8
- package/dist/tmagic-editor.umd.cjs +11149 -6646
- package/package.json +8 -8
- package/src/Editor.vue +25 -1
- package/src/components/CodeBlockEditor.vue +20 -109
- package/src/components/CodeParams.vue +6 -0
- package/src/components/CompareForm.vue +277 -0
- package/src/components/ToolButton.vue +2 -2
- package/src/editorProps.ts +9 -0
- package/src/fields/Code.vue +19 -3
- package/src/fields/CodeLink.vue +2 -5
- package/src/fields/CodeSelect.vue +17 -1
- package/src/fields/CodeSelectCol.vue +37 -3
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +23 -3
- package/src/fields/DataSourceFieldSelect/Index.vue +2 -2
- package/src/fields/DataSourceFields.vue +48 -10
- package/src/fields/DataSourceInput.vue +3 -3
- package/src/fields/DataSourceMethodSelect.vue +12 -4
- package/src/fields/DataSourceMethods.vue +55 -24
- package/src/fields/DataSourceMocks.vue +13 -3
- package/src/fields/DataSourceSelect.vue +4 -1
- package/src/fields/EventSelect.vue +57 -8
- package/src/fields/KeyValue.vue +17 -4
- package/src/fields/StyleSetter/components/Border.vue +15 -6
- package/src/fields/UISelect.vue +5 -2
- package/src/hooks/use-code-block-edit.ts +9 -5
- package/src/hooks/use-data-source-edit.ts +2 -2
- package/src/hooks/use-stage.ts +26 -9
- package/src/index.ts +8 -0
- package/src/initService.ts +1 -1
- package/src/layouts/CodeEditor.vue +17 -5
- package/src/layouts/Framework.vue +11 -6
- package/src/layouts/NavMenu.vue +12 -3
- package/src/layouts/history-list/Bucket.vue +91 -0
- package/src/layouts/history-list/BucketTab.vue +72 -0
- package/src/layouts/history-list/GroupRow.vue +304 -0
- package/src/layouts/history-list/HistoryDiffDialog.vue +281 -0
- package/src/layouts/history-list/HistoryListPanel.vue +367 -0
- package/src/layouts/history-list/InitialRow.vue +71 -0
- package/src/layouts/history-list/PageTab.vue +118 -0
- package/src/layouts/history-list/composables.ts +309 -0
- package/src/layouts/history-list/useHistoryList.ts +60 -0
- package/src/layouts/history-list/useHistoryRevert.ts +421 -0
- package/src/layouts/page-bar/PageBar.vue +4 -2
- package/src/layouts/props-panel/PropsPanel.vue +5 -1
- package/src/layouts/sidebar/ComponentListPanel.vue +9 -5
- package/src/layouts/sidebar/Sidebar.vue +8 -3
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -1
- package/src/layouts/sidebar/code-block/useContentMenu.ts +1 -1
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +31 -2
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +27 -2
- package/src/layouts/sidebar/data-source/useContentMenu.ts +1 -1
- package/src/layouts/sidebar/layer/LayerMenu.vue +19 -11
- package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
- package/src/layouts/sidebar/layer/use-node-status.ts +9 -6
- package/src/layouts/workspace/viewer/Stage.vue +1 -1
- package/src/layouts/workspace/viewer/ViewerMenu.vue +8 -8
- package/src/services/BaseService.ts +35 -86
- package/src/services/codeBlock.ts +361 -5
- package/src/services/dataSource.ts +336 -6
- package/src/services/dep.ts +32 -9
- package/src/services/editor.ts +834 -194
- package/src/services/history.ts +509 -49
- package/src/services/keybinding.ts +3 -3
- package/src/services/props.ts +2 -2
- package/src/services/ui.ts +7 -0
- package/src/theme/history-list-panel.scss +557 -0
- package/src/theme/page-bar.scss +0 -4
- package/src/theme/props-panel.scss +3 -3
- package/src/theme/style-setter/border.scss +4 -1
- package/src/theme/theme.scss +1 -0
- package/src/type.ts +613 -31
- package/src/utils/code-block.ts +150 -0
- package/src/utils/content-menu.ts +25 -13
- package/src/utils/data-source/index.ts +2 -0
- package/src/utils/dep/worker.ts +5 -3
- package/src/utils/editor.ts +166 -60
- package/src/utils/history.ts +286 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/indexed-db.ts +122 -0
- package/src/utils/undo-redo.ts +111 -0
- package/types/index.d.ts +3197 -896
- package/dist/es/utils/compose.js +0 -44
- package/dist/es/utils/editor-history.js +0 -100
- package/src/utils/compose.ts +0 -52
- package/src/utils/editor-history.ts +0 -138
|
@@ -23,13 +23,23 @@ import type { Writable } from 'type-fest';
|
|
|
23
23
|
import type { CodeBlockContent, CodeBlockDSL, Id, MNode, TargetOptions } from '@tmagic/core';
|
|
24
24
|
import { Target, Watcher } from '@tmagic/core';
|
|
25
25
|
import type { TableColumnConfig } from '@tmagic/form';
|
|
26
|
+
import { getValueByKeyPath, setValueByKeyPath } from '@tmagic/utils';
|
|
26
27
|
|
|
27
28
|
import editorService from '@editor/services/editor';
|
|
29
|
+
import historyService from '@editor/services/history';
|
|
28
30
|
import storageService, { Protocol } from '@editor/services/storage';
|
|
29
|
-
import type {
|
|
31
|
+
import type {
|
|
32
|
+
AsyncHookPlugin,
|
|
33
|
+
CodeBlockStepValue,
|
|
34
|
+
CodeState,
|
|
35
|
+
DslOpWithHistoryIdsResult,
|
|
36
|
+
HistoryOpOptions,
|
|
37
|
+
HistoryOpOptionsWithChangeRecords,
|
|
38
|
+
} from '@editor/type';
|
|
30
39
|
import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
|
|
31
40
|
import { getEditorConfig } from '@editor/utils/config';
|
|
32
41
|
import { COPY_CODE_STORAGE_KEY } from '@editor/utils/editor';
|
|
42
|
+
import { createStackStep, describeRevertStep, getLastPushedHistoryIds } from '@editor/utils/history';
|
|
33
43
|
|
|
34
44
|
import BaseService from './BaseService';
|
|
35
45
|
|
|
@@ -49,6 +59,17 @@ class CodeBlock extends BaseService {
|
|
|
49
59
|
paramsColConfig: undefined,
|
|
50
60
|
});
|
|
51
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
|
+
|
|
52
73
|
constructor() {
|
|
53
74
|
super([
|
|
54
75
|
...canUsePluginMethods.async.map((methodName) => ({ name: methodName, isAsync: true })),
|
|
@@ -64,6 +85,7 @@ class CodeBlock extends BaseService {
|
|
|
64
85
|
public async setCodeDsl(codeDsl: CodeBlockDSL): Promise<void> {
|
|
65
86
|
this.state.codeDsl = codeDsl;
|
|
66
87
|
this.emit('code-dsl-change', this.state.codeDsl);
|
|
88
|
+
this.emit('change', this.state.codeDsl);
|
|
67
89
|
}
|
|
68
90
|
|
|
69
91
|
/**
|
|
@@ -92,10 +114,27 @@ class CodeBlock extends BaseService {
|
|
|
92
114
|
* 设置代码块ID和代码内容到源dsl
|
|
93
115
|
* @param {Id} id 代码块id
|
|
94
116
|
* @param {CodeBlockContent} codeConfig 代码块内容配置信息
|
|
117
|
+
* @param options 可选配置
|
|
118
|
+
* @param options.changeRecords form 端 propPath/value 列表,用于历史记录的精细化撤销/重做
|
|
119
|
+
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
95
120
|
* @returns {void}
|
|
96
121
|
*/
|
|
97
|
-
public async setCodeDslById(
|
|
98
|
-
|
|
122
|
+
public async setCodeDslById(
|
|
123
|
+
id: Id,
|
|
124
|
+
codeConfig: Partial<CodeBlockContent>,
|
|
125
|
+
{
|
|
126
|
+
changeRecords,
|
|
127
|
+
doNotPushHistory = false,
|
|
128
|
+
historyDescription,
|
|
129
|
+
historySource,
|
|
130
|
+
}: HistoryOpOptionsWithChangeRecords = {},
|
|
131
|
+
): Promise<void> {
|
|
132
|
+
this.setCodeDslByIdSync(id, codeConfig, true, {
|
|
133
|
+
changeRecords,
|
|
134
|
+
doNotPushHistory,
|
|
135
|
+
historyDescription,
|
|
136
|
+
historySource,
|
|
137
|
+
});
|
|
99
138
|
}
|
|
100
139
|
|
|
101
140
|
/**
|
|
@@ -104,9 +143,23 @@ class CodeBlock extends BaseService {
|
|
|
104
143
|
* @param {Id} id 代码块id
|
|
105
144
|
* @param {CodeBlockContent} codeConfig 代码块内容配置信息
|
|
106
145
|
* @param {boolean} force 是否强制写入,默认true
|
|
146
|
+
* @param options 可选配置
|
|
147
|
+
* @param options.changeRecords form 端 propPath/value 列表,用于历史记录的精细化撤销/重做
|
|
148
|
+
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
149
|
+
* @param options.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
|
|
107
150
|
* @returns {void}
|
|
108
151
|
*/
|
|
109
|
-
public setCodeDslByIdSync(
|
|
152
|
+
public setCodeDslByIdSync(
|
|
153
|
+
id: Id,
|
|
154
|
+
codeConfig: Partial<CodeBlockContent>,
|
|
155
|
+
force = true,
|
|
156
|
+
{
|
|
157
|
+
changeRecords,
|
|
158
|
+
doNotPushHistory = false,
|
|
159
|
+
historyDescription,
|
|
160
|
+
historySource,
|
|
161
|
+
}: HistoryOpOptionsWithChangeRecords = {},
|
|
162
|
+
): void {
|
|
110
163
|
const codeDsl = this.getCodeDsl();
|
|
111
164
|
|
|
112
165
|
if (!codeDsl) {
|
|
@@ -123,6 +176,9 @@ class CodeBlock extends BaseService {
|
|
|
123
176
|
}
|
|
124
177
|
}
|
|
125
178
|
|
|
179
|
+
// 历史记录:在写入前快照旧内容,区分新增/更新
|
|
180
|
+
const oldContent: CodeBlockContent | null = codeDsl[id] ? cloneDeep(codeDsl[id]) : null;
|
|
181
|
+
|
|
126
182
|
const existContent = codeDsl[id] || {};
|
|
127
183
|
|
|
128
184
|
codeDsl[id] = {
|
|
@@ -130,7 +186,21 @@ class CodeBlock extends BaseService {
|
|
|
130
186
|
...codeConfigProcessed,
|
|
131
187
|
};
|
|
132
188
|
|
|
189
|
+
const newContent = cloneDeep(codeDsl[id]);
|
|
190
|
+
|
|
191
|
+
if (!doNotPushHistory) {
|
|
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;
|
|
200
|
+
}
|
|
201
|
+
|
|
133
202
|
this.emit('addOrUpdate', id, codeDsl[id]);
|
|
203
|
+
this.emit('change', this.getCodeDsl());
|
|
134
204
|
}
|
|
135
205
|
|
|
136
206
|
/**
|
|
@@ -218,19 +288,88 @@ class CodeBlock extends BaseService {
|
|
|
218
288
|
/**
|
|
219
289
|
* 在dsl数据源中删除指定id的代码块
|
|
220
290
|
* @param {Id[]} codeIds 需要删除的代码块id数组
|
|
291
|
+
* @param options 可选配置
|
|
292
|
+
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
221
293
|
*/
|
|
222
|
-
public async deleteCodeDslByIds(
|
|
294
|
+
public async deleteCodeDslByIds(
|
|
295
|
+
codeIds: Id[],
|
|
296
|
+
{ doNotPushHistory = false, historyDescription, historySource }: HistoryOpOptions = {},
|
|
297
|
+
): Promise<void> {
|
|
223
298
|
const currentDsl = await this.getCodeDsl();
|
|
224
299
|
|
|
225
300
|
if (!currentDsl) return;
|
|
226
301
|
|
|
302
|
+
this.lastDeletedHistoryIds = [];
|
|
303
|
+
|
|
227
304
|
codeIds.forEach((id) => {
|
|
305
|
+
// 历史记录:删除前快照内容;不存在的 id 直接跳过历史推入
|
|
306
|
+
const oldValue: CodeBlockContent | null = currentDsl[id] ? cloneDeep(currentDsl[id]) : null;
|
|
307
|
+
|
|
228
308
|
delete currentDsl[id];
|
|
229
309
|
|
|
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);
|
|
319
|
+
}
|
|
320
|
+
|
|
230
321
|
this.emit('remove', id);
|
|
231
322
|
});
|
|
323
|
+
|
|
324
|
+
this.emit('change', this.getCodeDsl());
|
|
232
325
|
}
|
|
233
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] };
|
|
370
|
+
}
|
|
371
|
+
// #endregion AndGetHistoryId
|
|
372
|
+
|
|
234
373
|
public setParamsColConfig(config: TableColumnConfig): void {
|
|
235
374
|
this.state.paramsColConfig = config;
|
|
236
375
|
}
|
|
@@ -239,6 +378,107 @@ class CodeBlock extends BaseService {
|
|
|
239
378
|
return this.state.paramsColConfig;
|
|
240
379
|
}
|
|
241
380
|
|
|
381
|
+
/**
|
|
382
|
+
* 撤销指定代码块的最近一次变更。
|
|
383
|
+
*
|
|
384
|
+
* 内部走 setCodeDslByIdSync / deleteCodeDslByIds,因此会自动触发 codeBlockService 的
|
|
385
|
+
* `addOrUpdate` / `remove` 事件,由 initService 中的 handler 重新维护 dep target
|
|
386
|
+
* (DepTargetType.CODE_BLOCK 的 add / remove)。所有写回都带 `doNotPushHistory: true`,
|
|
387
|
+
* 确保不会在历史栈里产生新的记录。
|
|
388
|
+
*
|
|
389
|
+
* @param id 代码块 id
|
|
390
|
+
* @returns 撤销的 step;栈不存在或已无可撤销时返回 null
|
|
391
|
+
*/
|
|
392
|
+
public async undo(id: Id): Promise<CodeBlockStepValue | null> {
|
|
393
|
+
const step = historyService.undo('codeBlock', id);
|
|
394
|
+
if (!step) return null;
|
|
395
|
+
await this.applyHistoryStep(step, true);
|
|
396
|
+
return step;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* 重做指定代码块的下一次变更。
|
|
401
|
+
* @param id 代码块 id
|
|
402
|
+
* @returns 重做的 step;栈不存在或已无可重做时返回 null
|
|
403
|
+
*/
|
|
404
|
+
public async redo(id: Id): Promise<CodeBlockStepValue | null> {
|
|
405
|
+
const step = historyService.redo('codeBlock', id);
|
|
406
|
+
if (!step) return null;
|
|
407
|
+
await this.applyHistoryStep(step, false);
|
|
408
|
+
return step;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** 是否可对指定代码块撤销。 */
|
|
412
|
+
public canUndo(id: Id): boolean {
|
|
413
|
+
return historyService.canUndo('codeBlock', id);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/** 是否可对指定代码块重做。 */
|
|
417
|
+
public canRedo(id: Id): boolean {
|
|
418
|
+
return historyService.canRedo('codeBlock', id);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* 跳转指定代码块的历史栈到目标游标。语义同 editor.gotoPageStep。
|
|
423
|
+
*
|
|
424
|
+
* @param id 代码块 id
|
|
425
|
+
* @param targetCursor 目标游标位置(已应用步骤数量)
|
|
426
|
+
* @returns 实际移动到的最终游标位置
|
|
427
|
+
*/
|
|
428
|
+
public async goto(id: Id, targetCursor: number): Promise<number> {
|
|
429
|
+
let cursor = historyService.getCursor('codeBlock', id);
|
|
430
|
+
const target = Math.max(0, targetCursor);
|
|
431
|
+
while (cursor > target) {
|
|
432
|
+
const step = await this.undo(id);
|
|
433
|
+
if (!step) break;
|
|
434
|
+
cursor -= 1;
|
|
435
|
+
}
|
|
436
|
+
while (cursor < target) {
|
|
437
|
+
const step = await this.redo(id);
|
|
438
|
+
if (!step) break;
|
|
439
|
+
cursor += 1;
|
|
440
|
+
}
|
|
441
|
+
return cursor;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* 「回滚」指定代码块历史步骤(类 git revert 语义):
|
|
446
|
+
* - 不动原始栈结构(不移动 cursor、不丢弃任何步骤);
|
|
447
|
+
* - 把目标 step 的修改**反向应用**一次,并作为**新步骤**追加到栈顶;
|
|
448
|
+
* - 仅对已应用的步骤生效。
|
|
449
|
+
*
|
|
450
|
+
* @param id 代码块 id
|
|
451
|
+
* @param index 目标 step 在该栈中的索引(0 为最早),通常由历史面板传入
|
|
452
|
+
* @returns 反向后产生的新 step;目标不存在 / 未应用时返回 null
|
|
453
|
+
*/
|
|
454
|
+
public async revert(id: Id, index: number): Promise<CodeBlockStepValue | null> {
|
|
455
|
+
const list = historyService.getStepList('codeBlock', id);
|
|
456
|
+
const entry = list[index];
|
|
457
|
+
if (!entry?.applied) return null;
|
|
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)}`;
|
|
463
|
+
return await this.applyRevertStep(entry.step, description);
|
|
464
|
+
}
|
|
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
|
+
|
|
242
482
|
/**
|
|
243
483
|
* 生成代码块唯一id
|
|
244
484
|
* @returns {Id} 代码块唯一id
|
|
@@ -320,6 +560,122 @@ class CodeBlock extends BaseService {
|
|
|
320
560
|
public usePlugin(options: AsyncHookPlugin<AsyncMethodName, CodeBlock>): void {
|
|
321
561
|
super.usePlugin(options);
|
|
322
562
|
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* 反向应用一个 step 并以新 step 入栈。逻辑与 applyHistoryStep(reverse=true) 同构,
|
|
566
|
+
* 差异仅在于通过公开的 setCodeDslByIdSync / deleteCodeDslByIds 触发 push。
|
|
567
|
+
*/
|
|
568
|
+
private async applyRevertStep(
|
|
569
|
+
step: CodeBlockStepValue,
|
|
570
|
+
historyDescription: string,
|
|
571
|
+
): Promise<CodeBlockStepValue | null> {
|
|
572
|
+
const { id } = step.data;
|
|
573
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
574
|
+
|
|
575
|
+
// 原本是新增 → revert 即删除
|
|
576
|
+
if (!oldSchema && newSchema) {
|
|
577
|
+
await this.deleteCodeDslByIds([id], { historyDescription, historySource: 'rollback' });
|
|
578
|
+
return historyService.getStepList('codeBlock', id).slice(-1)[0]?.step ?? null;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// 原本是删除 → revert 即写回
|
|
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;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (!oldSchema || !newSchema) return null;
|
|
588
|
+
|
|
589
|
+
// 原本是更新 → 把 oldContent 写回;优先按 changeRecords 局部 patch
|
|
590
|
+
if (changeRecords?.length) {
|
|
591
|
+
const current = this.getCodeContentById(id);
|
|
592
|
+
if (!current) return null;
|
|
593
|
+
const patched = cloneDeep(current) as CodeBlockContent;
|
|
594
|
+
let fallbackToFullReplace = false;
|
|
595
|
+
for (const record of changeRecords) {
|
|
596
|
+
if (!record.propPath) {
|
|
597
|
+
fallbackToFullReplace = true;
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
const value = cloneDeep(getValueByKeyPath(record.propPath, oldSchema));
|
|
601
|
+
setValueByKeyPath(record.propPath, value, patched);
|
|
602
|
+
}
|
|
603
|
+
this.setCodeDslByIdSync(id, fallbackToFullReplace ? cloneDeep(oldSchema) : patched, true, {
|
|
604
|
+
changeRecords,
|
|
605
|
+
historyDescription,
|
|
606
|
+
historySource: 'rollback',
|
|
607
|
+
});
|
|
608
|
+
return historyService.getStepList('codeBlock', id).slice(-1)[0]?.step ?? null;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
this.setCodeDslByIdSync(id, cloneDeep(oldSchema), true, { historyDescription, historySource: 'rollback' });
|
|
612
|
+
return historyService.getStepList('codeBlock', id).slice(-1)[0]?.step ?? null;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* 把一条历史 step 应用到当前代码块服务上。
|
|
617
|
+
*
|
|
618
|
+
* 复用现有的 setCodeDslByIdSync / deleteCodeDslByIds,目的是借助它们发出的事件
|
|
619
|
+
* 触发 initService 中的 dep target 维护(CODE_BLOCK 的 add / remove)。
|
|
620
|
+
* 所有写回都带 `doNotPushHistory: true`,确保不会在历史栈里产生新的记录。
|
|
621
|
+
*
|
|
622
|
+
* - oldContent=null, newContent≠null:原始为新增 → undo 删除;redo 再次 setCodeDslByIdSync
|
|
623
|
+
* - oldContent≠null, newContent=null:原始为删除 → undo 还原写入;redo 再次删除
|
|
624
|
+
* - 两侧都有:原始为更新 → 按 changeRecords 局部 patch;缺省退化为整内容替换
|
|
625
|
+
*
|
|
626
|
+
* @param step 历史 step
|
|
627
|
+
* @param reverse true=撤销,false=重做
|
|
628
|
+
*/
|
|
629
|
+
private async applyHistoryStep(step: CodeBlockStepValue, reverse: boolean): Promise<void> {
|
|
630
|
+
const { id } = step.data;
|
|
631
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
632
|
+
|
|
633
|
+
// 新增 / 删除:直接 set 或 delete,不走 patch 逻辑
|
|
634
|
+
if (!oldSchema && newSchema) {
|
|
635
|
+
if (reverse) {
|
|
636
|
+
await this.deleteCodeDslByIds([id], { doNotPushHistory: true });
|
|
637
|
+
} else {
|
|
638
|
+
this.setCodeDslByIdSync(id, cloneDeep(newSchema), true, { doNotPushHistory: true });
|
|
639
|
+
}
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
if (oldSchema && !newSchema) {
|
|
644
|
+
if (reverse) {
|
|
645
|
+
this.setCodeDslByIdSync(id, cloneDeep(oldSchema), true, { doNotPushHistory: true });
|
|
646
|
+
} else {
|
|
647
|
+
await this.deleteCodeDslByIds([id], { doNotPushHistory: true });
|
|
648
|
+
}
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
if (!oldSchema || !newSchema) return;
|
|
653
|
+
|
|
654
|
+
// 更新场景:优先按 changeRecords 局部 patch;缺省退化为整内容替换
|
|
655
|
+
const sourceForValues = reverse ? oldSchema : newSchema;
|
|
656
|
+
|
|
657
|
+
if (changeRecords?.length) {
|
|
658
|
+
const current = this.getCodeContentById(id);
|
|
659
|
+
if (!current) return;
|
|
660
|
+
const patched = cloneDeep(current) as CodeBlockContent;
|
|
661
|
+
let fallbackToFullReplace = false;
|
|
662
|
+
for (const record of changeRecords) {
|
|
663
|
+
if (!record.propPath) {
|
|
664
|
+
fallbackToFullReplace = true;
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
const value = cloneDeep(getValueByKeyPath(record.propPath, sourceForValues));
|
|
668
|
+
setValueByKeyPath(record.propPath, value, patched);
|
|
669
|
+
}
|
|
670
|
+
this.setCodeDslByIdSync(id, fallbackToFullReplace ? cloneDeep(sourceForValues) : patched, true, {
|
|
671
|
+
changeRecords,
|
|
672
|
+
doNotPushHistory: true,
|
|
673
|
+
});
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
this.setCodeDslByIdSync(id, cloneDeep(sourceForValues), true, { doNotPushHistory: true });
|
|
678
|
+
}
|
|
323
679
|
}
|
|
324
680
|
|
|
325
681
|
export type CodeBlockService = CodeBlock;
|