@tmagic/editor 1.8.0-beta.5 → 1.8.0-beta.6

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.
Files changed (42) hide show
  1. package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +4 -1
  2. package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +8 -2
  3. package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +25 -8
  4. package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +6 -4
  5. package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +25 -12
  6. package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +27 -5
  7. package/dist/es/index.js +2 -2
  8. package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +2 -2
  9. package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +12 -4
  10. package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +16 -3
  11. package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +23 -1
  12. package/dist/es/services/codeBlock.js +30 -19
  13. package/dist/es/services/dataSource.js +29 -21
  14. package/dist/es/services/editor.js +52 -33
  15. package/dist/es/services/history.js +10 -15
  16. package/dist/es/style.css +4 -1
  17. package/dist/es/utils/data-source/index.js +2 -0
  18. package/dist/es/utils/editor.js +68 -48
  19. package/dist/es/utils/history.js +42 -33
  20. package/dist/style.css +4 -1
  21. package/dist/tmagic-editor.umd.cjs +376 -206
  22. package/package.json +7 -7
  23. package/src/fields/CodeSelectCol.vue +7 -1
  24. package/src/fields/DataSourceFieldSelect/FieldSelect.vue +16 -2
  25. package/src/fields/DataSourceFields.vue +37 -8
  26. package/src/fields/DataSourceMethodSelect.vue +9 -4
  27. package/src/fields/DataSourceMethods.vue +42 -21
  28. package/src/fields/StyleSetter/components/Border.vue +15 -6
  29. package/src/layouts/history-list/HistoryListPanel.vue +2 -2
  30. package/src/layouts/history-list/InitialRow.vue +3 -0
  31. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +30 -2
  32. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +26 -1
  33. package/src/services/codeBlock.ts +28 -22
  34. package/src/services/dataSource.ts +29 -24
  35. package/src/services/editor.ts +41 -37
  36. package/src/services/history.ts +14 -19
  37. package/src/theme/style-setter/border.scss +4 -1
  38. package/src/type.ts +16 -1
  39. package/src/utils/data-source/index.ts +2 -0
  40. package/src/utils/editor.ts +125 -59
  41. package/src/utils/history.ts +46 -36
  42. package/types/index.d.ts +87 -68
@@ -13,13 +13,14 @@ import storageService, { Protocol } from '@editor/services/storage';
13
13
  import type {
14
14
  DataSourceStepValue,
15
15
  DatasourceTypeOption,
16
+ DslOpWithHistoryIdsResult,
16
17
  HistoryOpOptions,
17
18
  HistoryOpOptionsWithChangeRecords,
18
19
  SyncHookPlugin,
19
20
  } from '@editor/type';
20
21
  import { getFormConfig, getFormValue } from '@editor/utils/data-source';
21
22
  import { COPY_DS_STORAGE_KEY } from '@editor/utils/editor';
22
- import { describeRevertStep } from '@editor/utils/history';
23
+ import { describeRevertStep, getLastPushedHistoryIds } from '@editor/utils/history';
23
24
 
24
25
  import BaseService from './BaseService';
25
26
 
@@ -224,34 +225,37 @@ class DataSource extends BaseService {
224
225
  // #region AndGetHistoryId
225
226
  /**
226
227
  * 下列 *AndGetHistoryId 方法与对应的 add / update / remove 行为完全一致,
227
- * 唯一区别是返回值为本次写入历史栈的历史记录 uuid{@link DataSourceStepValue.uuid}),
228
- * 而非数据源配置。可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
228
+ * 返回值在 {@link DslOpWithHistoryIdsResult} 中同时包含原操作结果与本次写入历史栈的 uuid 列表({@link DataSourceStepValue.uuid}),
229
+ * 可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
229
230
  *
230
- * 当本次操作未写入历史(doNotPushHistory 为 true、或无对应记录)时返回 null。
231
+ * 当本次操作未写入历史(doNotPushHistory 为 true、或无对应记录)时 historyIds 为 `[]`。
231
232
  */
232
233
 
233
- /** 等价于 {@link add},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
234
- public addAndGetHistoryId(config: DataSourceSchema, options: HistoryOpOptions = {}): string | null {
234
+ /** 等价于 {@link add},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
235
+ public addAndGetHistoryId(
236
+ config: DataSourceSchema,
237
+ options: HistoryOpOptions = {},
238
+ ): DslOpWithHistoryIdsResult<DataSourceSchema> {
235
239
  this.lastPushedHistoryId = null;
236
- this.add(config, options);
237
- return this.lastPushedHistoryId;
240
+ const result = this.add(config, options);
241
+ return { result, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
238
242
  }
239
243
 
240
- /** 等价于 {@link update},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
244
+ /** 等价于 {@link update},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
241
245
  public updateAndGetHistoryId(
242
246
  config: DataSourceSchema,
243
247
  options: HistoryOpOptionsWithChangeRecords = {},
244
- ): string | null {
248
+ ): DslOpWithHistoryIdsResult<DataSourceSchema> {
245
249
  this.lastPushedHistoryId = null;
246
- this.update(config, options);
247
- return this.lastPushedHistoryId;
250
+ const result = this.update(config, options);
251
+ return { result, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
248
252
  }
249
253
 
250
- /** 等价于 {@link remove},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
251
- public removeAndGetHistoryId(id: string, options: HistoryOpOptions = {}): string | null {
254
+ /** 等价于 {@link remove},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
255
+ public removeAndGetHistoryId(id: string, options: HistoryOpOptions = {}): DslOpWithHistoryIdsResult<void> {
252
256
  this.lastPushedHistoryId = null;
253
257
  this.remove(id, options);
254
- return this.lastPushedHistoryId;
258
+ return { result: undefined, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
255
259
  }
256
260
  // #endregion AndGetHistoryId
257
261
 
@@ -337,17 +341,18 @@ class DataSource extends BaseService {
337
341
  }
338
342
 
339
343
  /**
340
- * 通过历史记录 uuid 回滚某条数据源历史步骤,语义同 {@link revert},
341
- * 仅无需调用方再传 dataSourceId 与 index:内部会按 uuid({@link DataSourceStepValue.uuid})
342
- * 在全部数据源栈中定位对应步骤后再回滚。
344
+ * 通过历史记录 uuid 回滚数据源历史步骤,语义同 {@link revert},
345
+ * 仅无需调用方再传 dataSourceId 与 index:内部会按 uuid 在全部数据源栈中定位对应步骤后再回滚。
346
+ * 按数组顺序依次回滚,返回与入参同序的结果列表(某项失败时为 `null`)。
343
347
  *
344
- * @param uuid 目标历史记录的 uuid,通常由 {@link addAndGetHistoryId} 等方法返回
345
- * @returns 反向后产生的新 step;找不到对应 uuid / 未应用时返回 null
348
+ * @param uuids 目标历史记录的 uuid 列表,通常由 {@link addAndGetHistoryId} 等方法返回的 `historyIds`
346
349
  */
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);
350
+ public revertById(uuids: string[]): (DataSourceStepValue | null)[] {
351
+ return uuids.map((uuid) => {
352
+ const location = historyService.findDataSourceStepLocationByUuid(uuid);
353
+ if (!location) return null;
354
+ return this.revert(location.id, location.index);
355
+ });
351
356
  }
352
357
 
353
358
  public createId(): string {
@@ -42,6 +42,7 @@ import type {
42
42
  AsyncHookPlugin,
43
43
  AsyncMethodName,
44
44
  DslOpOptions,
45
+ DslOpWithHistoryIdsResult,
45
46
  EditorEvents,
46
47
  EditorNodeInfo,
47
48
  HistoryOpSource,
@@ -73,6 +74,7 @@ import {
73
74
  setLayout,
74
75
  toggleFixedPosition,
75
76
  } from '@editor/utils/editor';
77
+ import { getLastPushedHistoryIds } from '@editor/utils/history';
76
78
  import { beforePaste, getAddParent } from '@editor/utils/operator';
77
79
 
78
80
  type MoveItem = { node: MNode; parent: MContainer; pageForOp: { name: string; id: Id } | null };
@@ -177,7 +179,7 @@ class Editor extends BaseService {
177
179
  this.state.stageLoading = false;
178
180
  }
179
181
 
180
- this.emit('root-change', value as StoreState['root'], preValue as StoreState['root']);
182
+ this.emit('root-change', value as StoreState['root'], preValue as StoreState['root'], options);
181
183
  }
182
184
  }
183
185
 
@@ -203,11 +205,11 @@ class Editor extends BaseService {
203
205
  }
204
206
 
205
207
  if (!root) {
206
- return { node: null, parent: null, page: null };
208
+ return { node: null, parent: null, page: null, path: [] };
207
209
  }
208
210
 
209
211
  if (id === root.id) {
210
- return { node: root, parent: null, page: null };
212
+ return { node: root, parent: null, page: null, path: [] };
211
213
  }
212
214
 
213
215
  // 大多数查找的目标都在当前页面内,优先在当前页面子树中查找以避免对整棵树做全量遍历。
@@ -693,7 +695,7 @@ class Editor extends BaseService {
693
695
 
694
696
  const node = toRaw(info.node);
695
697
 
696
- let newConfig = await toggleFixedPosition(toRaw(config), node, root, this.getLayout);
698
+ let newConfig = await toggleFixedPosition(toRaw(config), node, info.path, this.getLayout);
697
699
 
698
700
  newConfig = mergeWith(cloneDeep(node), newConfig, editorNodeMergeCustomizer);
699
701
 
@@ -1236,34 +1238,34 @@ class Editor extends BaseService {
1236
1238
  // #region AndGetHistoryId
1237
1239
  /**
1238
1240
  * 下列 *AndGetHistoryId 方法与对应的普通操作(add / remove / update ...)行为完全一致,
1239
- * 唯一区别是返回值为本次写入历史栈的历史记录 uuid{@link StepValue.uuid}),
1240
- * 而非节点 / 节点数组。可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
1241
+ * 返回值在 {@link DslOpWithHistoryIdsResult} 中同时包含原操作结果与本次写入历史栈的 uuid 列表({@link StepValue.uuid}),
1242
+ * 可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
1241
1243
  *
1242
- * 当本次操作未写入历史(doNotPushHistory 为 true、或操作无实际变更 / 提前返回)时返回 null。
1244
+ * 当本次操作未写入历史(doNotPushHistory 为 true、或操作无实际变更 / 提前返回)时 historyIds 为 `[]`。
1243
1245
  */
1244
1246
 
1245
- /** 等价于 {@link add},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
1247
+ /** 等价于 {@link add},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
1246
1248
  public async addAndGetHistoryId(
1247
1249
  addNode: AddMNode | MNode[],
1248
1250
  parent?: MContainer | null,
1249
1251
  options: DslOpOptions = {},
1250
- ): Promise<string | null> {
1252
+ ): Promise<DslOpWithHistoryIdsResult<MNode | MNode[]>> {
1251
1253
  this.lastPushedHistoryId = null;
1252
- await this.add(addNode, parent, options);
1253
- return this.lastPushedHistoryId;
1254
+ const result = await this.add(addNode, parent, options);
1255
+ return { result, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
1254
1256
  }
1255
1257
 
1256
- /** 等价于 {@link remove},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
1258
+ /** 等价于 {@link remove},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
1257
1259
  public async removeAndGetHistoryId(
1258
1260
  nodeOrNodeList: MNode | MNode[],
1259
1261
  options: DslOpOptions = {},
1260
- ): Promise<string | null> {
1262
+ ): Promise<DslOpWithHistoryIdsResult<void>> {
1261
1263
  this.lastPushedHistoryId = null;
1262
1264
  await this.remove(nodeOrNodeList, options);
1263
- return this.lastPushedHistoryId;
1265
+ return { result: undefined, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
1264
1266
  }
1265
1267
 
1266
- /** 等价于 {@link update},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
1268
+ /** 等价于 {@link update},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
1267
1269
  public async updateAndGetHistoryId(
1268
1270
  config: MNode | MNode[],
1269
1271
  data: {
@@ -1273,43 +1275,43 @@ class Editor extends BaseService {
1273
1275
  historyDescription?: string;
1274
1276
  historySource?: HistoryOpSource;
1275
1277
  } = {},
1276
- ): Promise<string | null> {
1278
+ ): Promise<DslOpWithHistoryIdsResult<MNode | MNode[]>> {
1277
1279
  this.lastPushedHistoryId = null;
1278
- await this.update(config, data);
1279
- return this.lastPushedHistoryId;
1280
+ const result = await this.update(config, data);
1281
+ return { result, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
1280
1282
  }
1281
1283
 
1282
- /** 等价于 {@link moveLayer},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
1284
+ /** 等价于 {@link moveLayer},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
1283
1285
  public async moveLayerAndGetHistoryId(
1284
1286
  offset: number | LayerOffset,
1285
1287
  options: DslOpOptions = {},
1286
- ): Promise<string | null> {
1288
+ ): Promise<DslOpWithHistoryIdsResult<void>> {
1287
1289
  this.lastPushedHistoryId = null;
1288
1290
  await this.moveLayer(offset, options);
1289
- return this.lastPushedHistoryId;
1291
+ return { result: undefined, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
1290
1292
  }
1291
1293
 
1292
- /** 等价于 {@link moveToContainer},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
1294
+ /** 等价于 {@link moveToContainer},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
1293
1295
  public async moveToContainerAndGetHistoryId(
1294
1296
  config: MNode | MNode[],
1295
1297
  targetId: Id,
1296
1298
  options: DslOpOptions = {},
1297
- ): Promise<string | null> {
1299
+ ): Promise<DslOpWithHistoryIdsResult<MNode | MNode[]>> {
1298
1300
  this.lastPushedHistoryId = null;
1299
- await this.moveToContainer(config, targetId, options);
1300
- return this.lastPushedHistoryId;
1301
+ const result = await this.moveToContainer(config, targetId, options);
1302
+ return { result, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
1301
1303
  }
1302
1304
 
1303
- /** 等价于 {@link dragTo},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
1305
+ /** 等价于 {@link dragTo},并额外返回本次写入历史记录的 uuid 列表(未入栈时 historyIds 为 `[]`)。 */
1304
1306
  public async dragToAndGetHistoryId(
1305
1307
  config: MNode | MNode[],
1306
1308
  targetParent: MContainer,
1307
1309
  targetIndex: number,
1308
1310
  options: DslOpOptions = {},
1309
- ): Promise<string | null> {
1311
+ ): Promise<DslOpWithHistoryIdsResult<void>> {
1310
1312
  this.lastPushedHistoryId = null;
1311
1313
  await this.dragTo(config, targetParent, targetIndex, options);
1312
- return this.lastPushedHistoryId;
1314
+ return { result: undefined, historyIds: getLastPushedHistoryIds(this.lastPushedHistoryId) };
1313
1315
  }
1314
1316
  // #endregion AndGetHistoryId
1315
1317
 
@@ -1451,17 +1453,19 @@ class Editor extends BaseService {
1451
1453
  }
1452
1454
 
1453
1455
  /**
1454
- * 通过历史记录 uuid 回滚当前页面的某条历史步骤,语义与 {@link revertPageStep} 完全一致,
1455
- * 仅入参从 index 改为 uuid{@link StepValue.uuid})。uuid 不随栈内步骤增删而变化,
1456
- * 更适合业务侧持有引用后再回滚(埋点、跨端同步等场景)。
1456
+ * 通过历史记录 uuid 回滚当前页面的历史步骤,语义与 {@link revertPageStep} 完全一致,
1457
+ * 仅入参从 index 改为 uuid 列表({@link StepValue.uuid})。按数组顺序依次回滚,
1458
+ * 返回与入参同序的结果列表(某项失败时为 `null`)。
1457
1459
  *
1458
- * @param uuid 目标历史记录的 uuid,通常由 *AndGetHistoryId 方法返回
1459
- * @returns 反向后产生的新 step;找不到对应 uuid / 未应用 / 反向失败时返回 null
1460
+ * @param uuids 目标历史记录的 uuid 列表,通常由 *AndGetHistoryId 方法返回的 `historyIds`
1460
1461
  */
1461
- public async revertPageStepById(uuid: string): Promise<StepValue | null> {
1462
- const index = historyService.getPageStepIndexByUuid(uuid);
1463
- if (index < 0) return null;
1464
- return this.revertPageStep(index);
1462
+ public async revertPageStepById(uuids: string[]): Promise<(StepValue | null)[]> {
1463
+ const results: (StepValue | null)[] = [];
1464
+ for (const uuid of uuids) {
1465
+ const index = historyService.getPageStepIndexByUuid(uuid);
1466
+ results.push(index < 0 ? null : await this.revertPageStep(index));
1467
+ }
1468
+ return results;
1465
1469
  }
1466
1470
 
1467
1471
  /**
@@ -17,7 +17,6 @@
17
17
  */
18
18
 
19
19
  import { reactive } from 'vue';
20
- import serialize from 'serialize-javascript';
21
20
 
22
21
  import type { CodeBlockContent, DataSourceSchema, Id, MPage, MPageFragment } from '@tmagic/core';
23
22
  import type { ChangeRecord } from '@tmagic/form';
@@ -57,7 +56,8 @@ import editorService from './editor';
57
56
  const DEFAULT_DB_NAME = 'tmagic-editor';
58
57
  const DEFAULT_STORE_NAME = 'history';
59
58
  const DEFAULT_KEY: IDBValidKey = 'default';
60
- const PERSIST_VERSION = 1;
59
+ // v2:仅把每条 step 的 diff 序列化成字符串,其余字段交给 IndexedDB 结构化克隆原生存储(见 saveToIndexedDB)。
60
+ const PERSIST_VERSION = 2;
61
61
 
62
62
  class History extends BaseService {
63
63
  public state = reactive<HistoryState>({
@@ -442,6 +442,8 @@ class History extends BaseService {
442
442
  public async saveToIndexedDB(options: HistoryPersistOptions = {}): Promise<PersistedHistoryState> {
443
443
  const { dbName = DEFAULT_DB_NAME, storeName = DEFAULT_STORE_NAME, key = DEFAULT_KEY, appId } = options;
444
444
 
445
+ // serializeStacks 会在序列化各栈时只把每条 step 的 diff(可能含函数)序列化成字符串,其余字段原样保留,
446
+ // 因此整份快照可直接按对象写入 IndexedDB(结构化克隆),避免序列化整份快照的开销;读取时再用 parseDSL 还原 diff。
445
447
  const snapshot: PersistedHistoryState = {
446
448
  version: PERSIST_VERSION,
447
449
  pageId: this.state.pageId,
@@ -451,9 +453,7 @@ class History extends BaseService {
451
453
  savedAt: Date.now(),
452
454
  };
453
455
 
454
- // 历史记录里可能包含函数(如代码块内容 / 节点事件 / 数据源方法),IndexedDB 的结构化克隆无法写入函数,
455
- // 因此用 serialize-javascript 序列化成字符串后再写入(支持函数 / Map 等),读取时用 parseDSL 还原。
456
- await idbSet(this.resolveDbName(dbName, appId), storeName, key, serialize(snapshot));
456
+ await idbSet(this.resolveDbName(dbName, appId), storeName, key, snapshot);
457
457
  this.emit('save-to-indexed-db', snapshot);
458
458
  return snapshot;
459
459
  }
@@ -469,16 +469,14 @@ class History extends BaseService {
469
469
  public async restoreFromIndexedDB(options: HistoryPersistOptions = {}): Promise<PersistedHistoryState | null> {
470
470
  const { dbName = DEFAULT_DB_NAME, storeName = DEFAULT_STORE_NAME, key = DEFAULT_KEY, appId } = options;
471
471
 
472
- const raw = await idbGet<string | PersistedHistoryState>(this.resolveDbName(dbName, appId), storeName, key);
473
- if (!raw) return null;
474
-
475
- // 新版以序列化字符串存储(含函数),用 parseDSL 还原;兼容历史上以对象形式存入的旧数据。
476
- const snapshot = (typeof raw === 'string' ? getEditorConfig('parseDSL')(`(${raw})`) : raw) as PersistedHistoryState;
472
+ const snapshot = await idbGet<PersistedHistoryState>(this.resolveDbName(dbName, appId), storeName, key);
477
473
  if (!snapshot) return null;
478
474
 
479
- this.state.pageSteps = deserializeStacks(snapshot.pageSteps);
480
- this.state.codeBlockState = deserializeStacks(snapshot.codeBlockState);
481
- this.state.dataSourceState = deserializeStacks(snapshot.dataSourceState);
475
+ // step 的 diff 以序列化字符串存储(含函数),由 deserializeStacks 逐条用 parseDSL 还原。
476
+ const parseDSL = getEditorConfig('parseDSL');
477
+ this.state.pageSteps = deserializeStacks(snapshot.pageSteps, parseDSL);
478
+ this.state.codeBlockState = deserializeStacks(snapshot.codeBlockState, parseDSL);
479
+ this.state.dataSourceState = deserializeStacks(snapshot.dataSourceState, parseDSL);
482
480
  // initial 基线作为页面栈 index 0 的 step 随 pageSteps 一并还原,无需单独恢复。
483
481
  this.state.pageId = snapshot.pageId;
484
482
 
@@ -526,11 +524,8 @@ class History extends BaseService {
526
524
  }
527
525
 
528
526
  /**
529
- * 取出全部代码块的历史栈,按 codeBlockId 分组。
530
- * 同一栈内相邻、同 opType 且作用于同一 id 的多步会被合并为一个 group:
531
- * - 这正是"代码块/数据源各自按 id 分栈"的天然表现,再叠加"连续修改同目标的相邻步骤合并展示"。
532
- * - 合并后 group 暴露子步骤数组,UI 可展开查看每一步的 changeRecords。
533
- * - applied 字段:组内最后一步是否处于已应用段。
527
+ * 取出全部代码块的历史栈,按 codeBlockId 分桶展示。
528
+ * 同一栈内每条操作记录独立成组,不做相邻 update 合并。
534
529
  */
535
530
  public getCodeBlockHistoryGroups(): CodeBlockHistoryGroup[] {
536
531
  const groups: CodeBlockHistoryGroup[] = [];
@@ -622,7 +617,7 @@ class History extends BaseService {
622
617
  }
623
618
 
624
619
  /**
625
- * 取出全部数据源的历史栈,按 dataSourceId 分组。同上。
620
+ * 取出全部数据源的历史栈,按 dataSourceId 分桶展示。同上,每条操作独立成组。
626
621
  */
627
622
  public getDataSourceHistoryGroups(): DataSourceHistoryGroup[] {
628
623
  const groups: DataSourceHistoryGroup[] = [];
@@ -24,9 +24,12 @@
24
24
  & + .border-icon {
25
25
  margin-left: 8px;
26
26
  }
27
+ &.configured {
28
+ border-color: var(--el-color-success, var(--td-success-color, #2ba471));
29
+ }
27
30
  &.active {
28
31
  border-width: 1px;
29
- border-color: var(--el-color-primary);
32
+ border-color: var(--el-color-primary, var(--td-brand-color, #0052d9));
30
33
  }
31
34
  &.border-icon-top {
32
35
  border-top-width: 2px;
package/src/type.ts CHANGED
@@ -335,6 +335,7 @@ export interface EditorNodeInfo {
335
335
  node: MNode | null;
336
336
  parent: MContainer | null;
337
337
  page: MPage | MPageFragment | null;
338
+ path: MNode[];
338
339
  }
339
340
  // #endregion EditorNodeInfo
340
341
 
@@ -736,6 +737,14 @@ export type HistoryOpSource =
736
737
  | (string & {});
737
738
  // #endregion HistoryOpSource
738
739
 
740
+ // #region DslOpWithHistoryIdsResult
741
+ /** *AndGetHistoryId 系列方法返回值:原操作结果 + 本次写入历史记录的 uuid 列表(未入栈时为 `[]`)。 */
742
+ export type DslOpWithHistoryIdsResult<T> = {
743
+ result: T;
744
+ historyIds: string[];
745
+ };
746
+ // #endregion DslOpWithHistoryIdsResult
747
+
739
748
  // #region StepDiffItem
740
749
  /**
741
750
  * 单条变更的 diff 描述,统一表达「页面节点 / 代码块 / 数据源」的变化内容,
@@ -1147,6 +1156,8 @@ export type SyncHookPlugin<
1147
1156
 
1148
1157
  export interface EventBusEvent {
1149
1158
  'edit-data-source': [id: string];
1159
+ 'edit-data-source-method': [id: string, methodName: string];
1160
+ 'edit-data-source-field': [id: string, fieldPath: string[]];
1150
1161
  'remove-data-source': [id: string];
1151
1162
  'edit-code': [id: string];
1152
1163
  }
@@ -1180,7 +1191,11 @@ export type CustomContentMenuFunction = (
1180
1191
  ) => (MenuButton | MenuComponent)[];
1181
1192
 
1182
1193
  export interface EditorEvents {
1183
- 'root-change': [value: StoreState['root'], preValue?: StoreState['root']];
1194
+ 'root-change': [
1195
+ value: StoreState['root'],
1196
+ preValue?: StoreState['root'],
1197
+ options?: { historySource?: HistoryOpSource },
1198
+ ];
1184
1199
  select: [node: MNode | null];
1185
1200
  add: [nodes: MNode[]];
1186
1201
  remove: [nodes: MNode[]];
@@ -10,6 +10,7 @@ const dataSourceFormConfig: TabConfig = {
10
10
  items: [
11
11
  {
12
12
  title: '数据定义',
13
+ status: 'fields',
13
14
  items: [
14
15
  {
15
16
  name: 'fields',
@@ -20,6 +21,7 @@ const dataSourceFormConfig: TabConfig = {
20
21
  },
21
22
  {
22
23
  title: '方法定义',
24
+ status: 'methods',
23
25
  items: [
24
26
  {
25
27
  name: 'methods',