@tmagic/editor 1.8.0-beta.3 → 1.8.0-beta.5
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/components/CompareForm.vue_vue_type_script_setup_true_lang.js +15 -1
- package/dist/es/components/ToolButton.vue_vue_type_script_setup_true_lang.js +6 -6
- package/dist/es/hooks/use-code-block-edit.js +6 -3
- package/dist/es/hooks/use-data-source-edit.js +5 -2
- package/dist/es/hooks/use-stage.js +6 -3
- package/dist/es/index.js +6 -3
- package/dist/es/initService.js +1 -1
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/NavMenu.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 +19 -51
- package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +22 -36
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +152 -93
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +36 -10
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +334 -208
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +28 -7
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +47 -57
- package/dist/es/layouts/history-list/composables.js +118 -25
- package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +5 -1
- package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +5 -1
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
- 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 +5 -5
- package/dist/es/layouts/sidebar/layer/LayerNodeTool.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 +1 -1
- package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/es/services/codeBlock.js +105 -42
- package/dist/es/services/dataSource.js +85 -35
- package/dist/es/services/editor.js +317 -122
- package/dist/es/services/history.js +270 -204
- package/dist/es/services/keybinding.js +3 -3
- package/dist/es/services/ui.js +3 -0
- package/dist/es/style.css +65 -10
- package/dist/es/utils/content-menu.js +17 -9
- package/dist/es/utils/editor.js +35 -1
- package/dist/es/utils/history.js +223 -0
- package/dist/es/utils/indexed-db.js +86 -0
- package/dist/es/utils/undo-redo.js +60 -1
- package/dist/style.css +65 -10
- package/dist/tmagic-editor.umd.cjs +2047 -954
- package/package.json +7 -7
- package/src/components/CompareForm.vue +21 -1
- package/src/components/ToolButton.vue +2 -2
- package/src/hooks/use-code-block-edit.ts +4 -3
- package/src/hooks/use-data-source-edit.ts +2 -2
- package/src/hooks/use-stage.ts +3 -3
- package/src/index.ts +1 -0
- package/src/initService.ts +1 -1
- package/src/layouts/Framework.vue +1 -1
- package/src/layouts/NavMenu.vue +1 -1
- package/src/layouts/history-list/Bucket.vue +34 -67
- package/src/layouts/history-list/BucketTab.vue +46 -51
- package/src/layouts/history-list/GroupRow.vue +150 -98
- package/src/layouts/history-list/HistoryDiffDialog.vue +96 -69
- package/src/layouts/history-list/HistoryListPanel.vue +298 -111
- package/src/layouts/history-list/InitialRow.vue +25 -9
- package/src/layouts/history-list/PageTab.vue +58 -48
- package/src/layouts/history-list/composables.ts +210 -29
- 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 +6 -1
- 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/DataSourceListPanel.vue +1 -1
- 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/workspace/viewer/Stage.vue +1 -1
- package/src/layouts/workspace/viewer/ViewerMenu.vue +8 -8
- package/src/services/codeBlock.ts +129 -35
- package/src/services/dataSource.ts +105 -34
- package/src/services/editor.ts +470 -157
- package/src/services/history.ts +312 -203
- package/src/services/keybinding.ts +3 -3
- package/src/services/ui.ts +7 -0
- package/src/theme/history-list-panel.scss +87 -6
- package/src/theme/page-bar.scss +0 -4
- package/src/theme/props-panel.scss +3 -3
- package/src/type.ts +221 -61
- package/src/utils/content-menu.ts +18 -9
- package/src/utils/editor.ts +41 -1
- package/src/utils/history.ts +298 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/indexed-db.ts +122 -0
- package/src/utils/undo-redo.ts +88 -0
- package/types/index.d.ts +871 -308
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
} from '@editor/type';
|
|
20
20
|
import { getFormConfig, getFormValue } from '@editor/utils/data-source';
|
|
21
21
|
import { COPY_DS_STORAGE_KEY } from '@editor/utils/editor';
|
|
22
|
+
import { describeRevertStep } from '@editor/utils/history';
|
|
22
23
|
|
|
23
24
|
import BaseService from './BaseService';
|
|
24
25
|
|
|
@@ -54,19 +55,6 @@ const canUsePluginMethods = {
|
|
|
54
55
|
|
|
55
56
|
type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
|
|
56
57
|
|
|
57
|
-
/**
|
|
58
|
-
* 「回滚」生成的新 step 简短描述。
|
|
59
|
-
* 仅在 service 层使用,避免依赖 UI 层 composables。
|
|
60
|
-
*/
|
|
61
|
-
const describeRevertDataSourceStep = (step: DataSourceStepValue): string => {
|
|
62
|
-
const { oldSchema, newSchema, changeRecords, id } = step;
|
|
63
|
-
if (oldSchema === null && newSchema) return `撤回新增 ${newSchema.title || newSchema.id || id}`;
|
|
64
|
-
if (oldSchema && newSchema === null) return `还原已删除的 ${oldSchema.title || oldSchema.id || id}`;
|
|
65
|
-
const title = newSchema?.title || oldSchema?.title || `${id}`;
|
|
66
|
-
const propPath = changeRecords?.[0]?.propPath;
|
|
67
|
-
return propPath ? `还原 ${title} · ${propPath}` : `还原 ${title}`;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
58
|
class DataSource extends BaseService {
|
|
71
59
|
private state = reactive<State>({
|
|
72
60
|
datasourceTypeList: [],
|
|
@@ -78,6 +66,13 @@ class DataSource extends BaseService {
|
|
|
78
66
|
methods: {},
|
|
79
67
|
});
|
|
80
68
|
|
|
69
|
+
/**
|
|
70
|
+
* 最近一次写入历史栈的数据源历史记录 uuid。
|
|
71
|
+
* 供 *AndGetHistoryId 系列方法在调用 add / update / remove 后取回本次产生的历史记录 id;
|
|
72
|
+
* 普通方法不读取它,调用前由 *AndGetHistoryId 重置为 null。
|
|
73
|
+
*/
|
|
74
|
+
private lastPushedHistoryId: string | null = null;
|
|
75
|
+
|
|
81
76
|
constructor() {
|
|
82
77
|
super(canUsePluginMethods.sync.map((methodName) => ({ name: methodName, isAsync: false })));
|
|
83
78
|
}
|
|
@@ -129,7 +124,10 @@ class DataSource extends BaseService {
|
|
|
129
124
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
130
125
|
* @param options.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
|
|
131
126
|
*/
|
|
132
|
-
public add(
|
|
127
|
+
public add(
|
|
128
|
+
config: DataSourceSchema,
|
|
129
|
+
{ doNotPushHistory = false, historyDescription, historySource }: HistoryOpOptions = {},
|
|
130
|
+
) {
|
|
133
131
|
const newConfig = {
|
|
134
132
|
...config,
|
|
135
133
|
id: config.id && !this.getDataSourceById(config.id) ? config.id : this.createId(),
|
|
@@ -138,7 +136,13 @@ class DataSource extends BaseService {
|
|
|
138
136
|
this.get('dataSources').push(newConfig);
|
|
139
137
|
|
|
140
138
|
if (!doNotPushHistory) {
|
|
141
|
-
|
|
139
|
+
this.lastPushedHistoryId =
|
|
140
|
+
historyService.pushDataSource(newConfig.id, {
|
|
141
|
+
oldSchema: null,
|
|
142
|
+
newSchema: newConfig,
|
|
143
|
+
historyDescription,
|
|
144
|
+
source: historySource,
|
|
145
|
+
})?.uuid ?? null;
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
this.emit('add', newConfig);
|
|
@@ -156,7 +160,12 @@ class DataSource extends BaseService {
|
|
|
156
160
|
*/
|
|
157
161
|
public update(
|
|
158
162
|
config: DataSourceSchema,
|
|
159
|
-
{
|
|
163
|
+
{
|
|
164
|
+
changeRecords = [],
|
|
165
|
+
doNotPushHistory = false,
|
|
166
|
+
historyDescription,
|
|
167
|
+
historySource,
|
|
168
|
+
}: HistoryOpOptionsWithChangeRecords = {},
|
|
160
169
|
) {
|
|
161
170
|
const dataSources = this.get('dataSources');
|
|
162
171
|
|
|
@@ -168,12 +177,14 @@ class DataSource extends BaseService {
|
|
|
168
177
|
dataSources[index] = newConfig;
|
|
169
178
|
|
|
170
179
|
if (!doNotPushHistory) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
this.lastPushedHistoryId =
|
|
181
|
+
historyService.pushDataSource(newConfig.id, {
|
|
182
|
+
oldSchema: oldConfig ? cloneDeep(oldConfig) : null,
|
|
183
|
+
newSchema: newConfig,
|
|
184
|
+
changeRecords,
|
|
185
|
+
historyDescription,
|
|
186
|
+
source: historySource,
|
|
187
|
+
})?.uuid ?? null;
|
|
177
188
|
}
|
|
178
189
|
|
|
179
190
|
this.emit('update', newConfig, {
|
|
@@ -191,19 +202,59 @@ class DataSource extends BaseService {
|
|
|
191
202
|
* @param options.doNotPushHistory 是否不写入历史记录(默认 false)
|
|
192
203
|
* @param options.historyDescription 入栈时附带的人类可读描述,用于历史面板展示
|
|
193
204
|
*/
|
|
194
|
-
public remove(id: string, { doNotPushHistory = false, historyDescription }: HistoryOpOptions = {}) {
|
|
205
|
+
public remove(id: string, { doNotPushHistory = false, historyDescription, historySource }: HistoryOpOptions = {}) {
|
|
195
206
|
const dataSources = this.get('dataSources');
|
|
196
207
|
const index = dataSources.findIndex((ds) => ds.id === id);
|
|
197
208
|
const oldConfig = index !== -1 ? dataSources[index] : null;
|
|
198
209
|
dataSources.splice(index, 1);
|
|
199
210
|
|
|
200
211
|
if (oldConfig && !doNotPushHistory) {
|
|
201
|
-
|
|
212
|
+
this.lastPushedHistoryId =
|
|
213
|
+
historyService.pushDataSource(id, {
|
|
214
|
+
oldSchema: cloneDeep(oldConfig),
|
|
215
|
+
newSchema: null,
|
|
216
|
+
historyDescription,
|
|
217
|
+
source: historySource,
|
|
218
|
+
})?.uuid ?? null;
|
|
202
219
|
}
|
|
203
220
|
|
|
204
221
|
this.emit('remove', id);
|
|
205
222
|
}
|
|
206
223
|
|
|
224
|
+
// #region AndGetHistoryId
|
|
225
|
+
/**
|
|
226
|
+
* 下列 *AndGetHistoryId 方法与对应的 add / update / remove 行为完全一致,
|
|
227
|
+
* 唯一区别是返回值为本次写入历史栈的历史记录 uuid({@link DataSourceStepValue.uuid}),
|
|
228
|
+
* 而非数据源配置。可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
|
|
229
|
+
*
|
|
230
|
+
* 当本次操作未写入历史(doNotPushHistory 为 true、或无对应记录)时返回 null。
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
/** 等价于 {@link add},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
234
|
+
public addAndGetHistoryId(config: DataSourceSchema, options: HistoryOpOptions = {}): string | null {
|
|
235
|
+
this.lastPushedHistoryId = null;
|
|
236
|
+
this.add(config, options);
|
|
237
|
+
return this.lastPushedHistoryId;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** 等价于 {@link update},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
241
|
+
public updateAndGetHistoryId(
|
|
242
|
+
config: DataSourceSchema,
|
|
243
|
+
options: HistoryOpOptionsWithChangeRecords = {},
|
|
244
|
+
): string | null {
|
|
245
|
+
this.lastPushedHistoryId = null;
|
|
246
|
+
this.update(config, options);
|
|
247
|
+
return this.lastPushedHistoryId;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** 等价于 {@link remove},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
251
|
+
public removeAndGetHistoryId(id: string, options: HistoryOpOptions = {}): string | null {
|
|
252
|
+
this.lastPushedHistoryId = null;
|
|
253
|
+
this.remove(id, options);
|
|
254
|
+
return this.lastPushedHistoryId;
|
|
255
|
+
}
|
|
256
|
+
// #endregion AndGetHistoryId
|
|
257
|
+
|
|
207
258
|
/**
|
|
208
259
|
* 撤销指定数据源的最近一次变更。
|
|
209
260
|
*
|
|
@@ -278,10 +329,27 @@ class DataSource extends BaseService {
|
|
|
278
329
|
const list = historyService.getDataSourceStepList(id);
|
|
279
330
|
const entry = list[index];
|
|
280
331
|
if (!entry?.applied) return null;
|
|
281
|
-
|
|
332
|
+
// 更新类步骤(前后 schema 都存在)必须带 changeRecords 才支持回滚,否则只能整 schema 替换,会冲掉后续无关变更。
|
|
333
|
+
const { oldSchema, newSchema, changeRecords } = entry.step.diff?.[0] ?? {};
|
|
334
|
+
if (oldSchema && newSchema && !changeRecords?.length) return null;
|
|
335
|
+
const description = `回滚 #${index + 1}: ${describeRevertStep<DataSourceSchema>(entry.step.id, entry.step.diff?.[0], (s) => s.title)}`;
|
|
282
336
|
return this.applyRevertStep(entry.step, description);
|
|
283
337
|
}
|
|
284
338
|
|
|
339
|
+
/**
|
|
340
|
+
* 通过历史记录 uuid 回滚某条数据源历史步骤,语义同 {@link revert},
|
|
341
|
+
* 仅无需调用方再传 dataSourceId 与 index:内部会按 uuid({@link DataSourceStepValue.uuid})
|
|
342
|
+
* 在全部数据源栈中定位对应步骤后再回滚。
|
|
343
|
+
*
|
|
344
|
+
* @param uuid 目标历史记录的 uuid,通常由 {@link addAndGetHistoryId} 等方法返回
|
|
345
|
+
* @returns 反向后产生的新 step;找不到对应 uuid / 未应用时返回 null
|
|
346
|
+
*/
|
|
347
|
+
public revertById(uuid: string): DataSourceStepValue | null {
|
|
348
|
+
const location = historyService.findDataSourceStepLocationByUuid(uuid);
|
|
349
|
+
if (!location) return null;
|
|
350
|
+
return this.revert(location.id, location.index);
|
|
351
|
+
}
|
|
352
|
+
|
|
285
353
|
public createId(): string {
|
|
286
354
|
return `ds_${guid()}`;
|
|
287
355
|
}
|
|
@@ -362,17 +430,18 @@ class DataSource extends BaseService {
|
|
|
362
430
|
* 同构,差异仅在于走对应的公共 add / update / remove 而不是带 doNotPushHistory 的版本。
|
|
363
431
|
*/
|
|
364
432
|
private applyRevertStep(step: DataSourceStepValue, historyDescription: string): DataSourceStepValue | null {
|
|
365
|
-
const { id
|
|
433
|
+
const { id } = step;
|
|
434
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
366
435
|
|
|
367
436
|
// 原本是新增 → revert 即删除
|
|
368
|
-
if (oldSchema
|
|
369
|
-
this.remove(`${id}`, { historyDescription });
|
|
437
|
+
if (!oldSchema && newSchema) {
|
|
438
|
+
this.remove(`${id}`, { historyDescription, historySource: 'rollback' });
|
|
370
439
|
return historyService.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
|
|
371
440
|
}
|
|
372
441
|
|
|
373
442
|
// 原本是删除 → revert 即重新加回
|
|
374
|
-
if (oldSchema && newSchema
|
|
375
|
-
this.add(cloneDeep(oldSchema), { historyDescription });
|
|
443
|
+
if (oldSchema && !newSchema) {
|
|
444
|
+
this.add(cloneDeep(oldSchema), { historyDescription, historySource: 'rollback' });
|
|
376
445
|
return historyService.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
|
|
377
446
|
}
|
|
378
447
|
|
|
@@ -395,11 +464,12 @@ class DataSource extends BaseService {
|
|
|
395
464
|
this.update(fallbackToFullReplace ? cloneDeep(oldSchema) : patched, {
|
|
396
465
|
changeRecords,
|
|
397
466
|
historyDescription,
|
|
467
|
+
historySource: 'rollback',
|
|
398
468
|
});
|
|
399
469
|
return historyService.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
|
|
400
470
|
}
|
|
401
471
|
|
|
402
|
-
this.update(cloneDeep(oldSchema), { historyDescription });
|
|
472
|
+
this.update(cloneDeep(oldSchema), { historyDescription, historySource: 'rollback' });
|
|
403
473
|
return historyService.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
|
|
404
474
|
}
|
|
405
475
|
|
|
@@ -418,10 +488,11 @@ class DataSource extends BaseService {
|
|
|
418
488
|
* @param reverse true=撤销,false=重做
|
|
419
489
|
*/
|
|
420
490
|
private applyHistoryStep(step: DataSourceStepValue, reverse: boolean): void {
|
|
421
|
-
const { id
|
|
491
|
+
const { id } = step;
|
|
492
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
422
493
|
|
|
423
494
|
// 新增 / 删除:直接 add 或 remove,不走 patch 逻辑
|
|
424
|
-
if (oldSchema
|
|
495
|
+
if (!oldSchema && newSchema) {
|
|
425
496
|
if (reverse) {
|
|
426
497
|
this.remove(`${id}`, { doNotPushHistory: true });
|
|
427
498
|
} else {
|
|
@@ -430,7 +501,7 @@ class DataSource extends BaseService {
|
|
|
430
501
|
return;
|
|
431
502
|
}
|
|
432
503
|
|
|
433
|
-
if (oldSchema && newSchema
|
|
504
|
+
if (oldSchema && !newSchema) {
|
|
434
505
|
if (reverse) {
|
|
435
506
|
this.add(cloneDeep(oldSchema), { doNotPushHistory: true });
|
|
436
507
|
} else {
|