@tmagic/editor 1.8.0-beta.4 → 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 +1 -1
- package/dist/es/components/ToolButton.vue_vue_type_script_setup_true_lang.js +6 -6
- 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/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +19 -55
- package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +22 -39
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +149 -103
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +32 -8
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +333 -211
- 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 -60
- package/dist/es/layouts/history-list/composables.js +73 -32
- package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +5 -1
- package/dist/es/services/codeBlock.js +85 -37
- package/dist/es/services/dataSource.js +62 -26
- package/dist/es/services/editor.js +243 -100
- package/dist/es/services/history.js +270 -206
- package/dist/es/services/ui.js +3 -0
- package/dist/es/style.css +49 -6
- 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 +49 -6
- package/dist/tmagic-editor.umd.cjs +1799 -905
- package/package.json +7 -7
- package/src/components/CompareForm.vue +3 -1
- package/src/components/ToolButton.vue +2 -2
- package/src/index.ts +1 -0
- package/src/initService.ts +1 -1
- package/src/layouts/Framework.vue +1 -1
- package/src/layouts/history-list/Bucket.vue +34 -71
- package/src/layouts/history-list/BucketTab.vue +46 -54
- package/src/layouts/history-list/GroupRow.vue +146 -111
- package/src/layouts/history-list/HistoryDiffDialog.vue +94 -68
- package/src/layouts/history-list/HistoryListPanel.vue +296 -113
- package/src/layouts/history-list/InitialRow.vue +25 -9
- package/src/layouts/history-list/PageTab.vue +57 -51
- package/src/layouts/history-list/composables.ts +157 -36
- package/src/layouts/page-bar/PageBar.vue +4 -2
- package/src/layouts/sidebar/Sidebar.vue +6 -1
- package/src/services/codeBlock.ts +107 -37
- package/src/services/dataSource.ts +89 -40
- package/src/services/editor.ts +370 -134
- package/src/services/history.ts +305 -203
- package/src/services/ui.ts +7 -0
- package/src/theme/history-list-panel.scss +72 -5
- package/src/theme/page-bar.scss +0 -4
- package/src/type.ts +167 -63
- 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 +783 -291
|
@@ -4917,8 +4917,41 @@
|
|
|
4917
4917
|
};
|
|
4918
4918
|
var props_default = new Props();
|
|
4919
4919
|
//#endregion
|
|
4920
|
+
//#region packages/editor/src/utils/config.ts
|
|
4921
|
+
var $TMAGIC_EDITOR = {};
|
|
4922
|
+
var setEditorConfig = (option) => {
|
|
4923
|
+
$TMAGIC_EDITOR = option;
|
|
4924
|
+
};
|
|
4925
|
+
var getEditorConfig = (key) => $TMAGIC_EDITOR[key];
|
|
4926
|
+
//#endregion
|
|
4920
4927
|
//#region packages/editor/src/utils/undo-redo.ts
|
|
4921
|
-
var UndoRedo = class {
|
|
4928
|
+
var UndoRedo = class UndoRedo {
|
|
4929
|
+
/**
|
|
4930
|
+
* 由 {@link UndoRedo.serialize} 产出的快照重建一个 UndoRedo 实例。
|
|
4931
|
+
* 游标会被夹紧到 [0, length] 区间,避免脏数据导致越界。
|
|
4932
|
+
*
|
|
4933
|
+
* @param options.isSavedStep 可选谓词:若提供,则把游标定位到「最近一条满足该谓词的记录」之后
|
|
4934
|
+
* (即恢复到最近一个已保存点);找不到匹配记录时退回快照中的原游标。
|
|
4935
|
+
*/
|
|
4936
|
+
static fromSerialized(data, options = {}) {
|
|
4937
|
+
const undoRedo = new UndoRedo(data.listMaxSize);
|
|
4938
|
+
const list = Array.isArray(data.elementList) ? data.elementList.map((item) => cloneDeep$1(item)) : [];
|
|
4939
|
+
let cursor = Number.isFinite(data.listCursor) ? data.listCursor : list.length;
|
|
4940
|
+
const overflow = list.length - undoRedo.listMaxSize;
|
|
4941
|
+
if (overflow > 0) {
|
|
4942
|
+
list.splice(0, overflow);
|
|
4943
|
+
cursor -= overflow;
|
|
4944
|
+
}
|
|
4945
|
+
if (options.isSavedStep) {
|
|
4946
|
+
for (let i = list.length - 1; i >= 0; i--) if (options.isSavedStep(list[i])) {
|
|
4947
|
+
cursor = i + 1;
|
|
4948
|
+
break;
|
|
4949
|
+
}
|
|
4950
|
+
}
|
|
4951
|
+
undoRedo.elementList = list;
|
|
4952
|
+
undoRedo.listCursor = Math.max(0, Math.min(cursor, list.length));
|
|
4953
|
+
return undoRedo;
|
|
4954
|
+
}
|
|
4922
4955
|
elementList;
|
|
4923
4956
|
listCursor;
|
|
4924
4957
|
listMaxSize;
|
|
@@ -4928,6 +4961,17 @@
|
|
|
4928
4961
|
this.listCursor = 0;
|
|
4929
4962
|
this.listMaxSize = listMaxSize > minListMaxSize ? listMaxSize : minListMaxSize;
|
|
4930
4963
|
}
|
|
4964
|
+
/**
|
|
4965
|
+
* 导出当前栈的可序列化快照(深克隆,避免外部改动污染内部状态)。
|
|
4966
|
+
* 配合 {@link UndoRedo.fromSerialized} 可在持久化后完整还原撤销/重做栈。
|
|
4967
|
+
*/
|
|
4968
|
+
serialize() {
|
|
4969
|
+
return {
|
|
4970
|
+
elementList: this.elementList.map((item) => cloneDeep$1(item)),
|
|
4971
|
+
listCursor: this.listCursor,
|
|
4972
|
+
listMaxSize: this.listMaxSize
|
|
4973
|
+
};
|
|
4974
|
+
}
|
|
4931
4975
|
pushElement(element) {
|
|
4932
4976
|
this.elementList.splice(this.listCursor, this.elementList.length - this.listCursor, cloneDeep$1(element));
|
|
4933
4977
|
this.listCursor += 1;
|
|
@@ -4960,6 +5004,28 @@
|
|
|
4960
5004
|
return cloneDeep$1(this.elementList[this.listCursor - 1]);
|
|
4961
5005
|
}
|
|
4962
5006
|
/**
|
|
5007
|
+
* 用 `element` 替换当前游标所在元素(cursor - 1),并丢弃其后的重做尾部(与 {@link pushElement} 的丢尾一致),
|
|
5008
|
+
* 游标位置保持不变(元素数量不增)。cursor 为 0(无已应用元素)时不做任何操作并返回 false。
|
|
5009
|
+
* 用于「连续同类记录合并」等就地替换最新一条的场景。
|
|
5010
|
+
*/
|
|
5011
|
+
replaceCurrentElement(element) {
|
|
5012
|
+
if (this.listCursor < 1) return false;
|
|
5013
|
+
this.elementList.splice(this.listCursor - 1, this.elementList.length - (this.listCursor - 1), cloneDeep$1(element));
|
|
5014
|
+
return true;
|
|
5015
|
+
}
|
|
5016
|
+
/**
|
|
5017
|
+
* 对当前游标所在元素(cursor - 1)做就地更新;cursor 为 0(全部已撤销)时不做任何操作。
|
|
5018
|
+
* 用于给「当前步骤」打标记(如标记为已保存)等元数据写入场景。
|
|
5019
|
+
*/
|
|
5020
|
+
updateCurrentElement(updater) {
|
|
5021
|
+
if (this.listCursor < 1) return;
|
|
5022
|
+
updater(this.elementList[this.listCursor - 1]);
|
|
5023
|
+
}
|
|
5024
|
+
/** 对栈内全部元素做就地更新。用于批量清理元数据(如清空所有元素的已保存标记)。 */
|
|
5025
|
+
updateElements(updater) {
|
|
5026
|
+
this.elementList.forEach(updater);
|
|
5027
|
+
}
|
|
5028
|
+
/**
|
|
4963
5029
|
* 返回栈内全部元素的浅克隆数组(按时间顺序,索引 0 为最早一步)。
|
|
4964
5030
|
* 仅用于历史面板等只读展示场景,不应直接修改返回值。
|
|
4965
5031
|
*/
|
|
@@ -4981,172 +5047,317 @@
|
|
|
4981
5047
|
}
|
|
4982
5048
|
};
|
|
4983
5049
|
//#endregion
|
|
4984
|
-
//#region packages/editor/src/
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5050
|
+
//#region packages/editor/src/utils/history.ts
|
|
5051
|
+
/**
|
|
5052
|
+
* 「回滚」生成的新 step 简短描述。代码块 / 数据源共用。
|
|
5053
|
+
* 二者逻辑一致,仅展示名取值字段不同(代码块取 `name`,数据源取 `title`),
|
|
5054
|
+
* 因此通过 `getLabel` 注入取值方式。
|
|
5055
|
+
*
|
|
5056
|
+
* @param id 关联的代码块 / 数据源 id
|
|
5057
|
+
* @param diff 单条变更 diff(缺省视为空)
|
|
5058
|
+
* @param getLabel 从快照取展示名
|
|
5059
|
+
*/
|
|
5060
|
+
var describeRevertStep = (id, { oldSchema, newSchema, changeRecords } = {}, getLabel) => {
|
|
5061
|
+
const labelOf = (schema) => getLabel(schema) || schema.id;
|
|
5062
|
+
if (!oldSchema && newSchema) return `撤回新增 ${labelOf(newSchema) || id}`;
|
|
5063
|
+
if (oldSchema && !newSchema) return `还原已删除的 ${labelOf(oldSchema) || id}`;
|
|
5064
|
+
const label = newSchema && getLabel(newSchema) || oldSchema && getLabel(oldSchema) || `${id}`;
|
|
5065
|
+
const propPath = changeRecords?.[0]?.propPath;
|
|
5066
|
+
return propPath ? `还原 ${label} · ${propPath}` : `还原 ${label}`;
|
|
5067
|
+
};
|
|
5068
|
+
/**
|
|
5069
|
+
* 根据 old/new 是否为 null 推断 opType(与 push 时的约定一致)。
|
|
5070
|
+
*/
|
|
5071
|
+
var detectStackOpType = (oldVal, newVal) => {
|
|
5072
|
+
if (oldVal === null && newVal !== null) return "add";
|
|
5073
|
+
if (oldVal !== null && newVal === null) return "remove";
|
|
5074
|
+
return "update";
|
|
5075
|
+
};
|
|
5076
|
+
/**
|
|
5077
|
+
* 构造一条代码块 / 数据源「按 id 分栈」的历史记录:两者除 payload 字段命名外完全一致。
|
|
5078
|
+
*
|
|
5079
|
+
* - `add`:oldValue = null;`remove`:newValue = null;`update`:两者都有,可带 changeRecords 做局部更新。
|
|
5080
|
+
* - 内容会做 cloneDeep 防止后续被外部引用篡改;opType 依据 old/new 是否为 null 推断。
|
|
5081
|
+
* - 仅负责构造 step 并返回,入栈与事件 emit 由各公共方法(pushCodeBlock / pushDataSource)自行处理。
|
|
5082
|
+
* - 不直接驱动业务 service,调用方负责实际写回。
|
|
5083
|
+
*/
|
|
5084
|
+
var createStackStep = (id, payload) => {
|
|
5085
|
+
if (!id) return null;
|
|
5086
|
+
const oldSchema = payload.oldValue ? cloneDeep$1(payload.oldValue) : null;
|
|
5087
|
+
const newSchema = payload.newValue ? cloneDeep$1(payload.newValue) : null;
|
|
5088
|
+
const changeRecords = payload.changeRecords?.length ? cloneDeep$1(payload.changeRecords) : void 0;
|
|
5089
|
+
const opType = detectStackOpType(payload.oldValue, payload.newValue);
|
|
5090
|
+
return {
|
|
5091
|
+
uuid: (0, _tmagic_utils.guid)(),
|
|
5092
|
+
id,
|
|
5093
|
+
opType,
|
|
5094
|
+
diff: [{
|
|
5095
|
+
...newSchema !== null ? { newSchema } : {},
|
|
5096
|
+
...oldSchema !== null ? { oldSchema } : {},
|
|
5097
|
+
...opType === "update" && changeRecords ? { changeRecords } : {}
|
|
5098
|
+
}],
|
|
5099
|
+
historyDescription: payload.historyDescription,
|
|
5100
|
+
source: payload.source,
|
|
5101
|
+
timestamp: Date.now()
|
|
5102
|
+
};
|
|
5103
|
+
};
|
|
5104
|
+
var markStackSaved = (undoRedo) => {
|
|
5105
|
+
if (!undoRedo) return;
|
|
5106
|
+
undoRedo.updateElements((element) => {
|
|
5107
|
+
element.saved = false;
|
|
5108
|
+
});
|
|
5109
|
+
undoRedo.updateCurrentElement((element) => {
|
|
5110
|
+
element.saved = true;
|
|
5111
|
+
});
|
|
5112
|
+
};
|
|
5113
|
+
/**
|
|
5114
|
+
* 把单个「按 id 分栈」的历史栈(代码块 / 数据源)拆成若干 group:
|
|
5115
|
+
* - 把"新增/删除"独立成组(语义上属于一次性事件,不应与 update 合并);
|
|
5116
|
+
* - 连续 'update' 合并到同一组,组内 steps 顺序就是发生顺序。
|
|
5117
|
+
*
|
|
5118
|
+
* 代码块与数据源除 `kind` 外结构完全一致,统一由本方法处理;`kind` 决定返回的具体分组类型。
|
|
5119
|
+
*/
|
|
5120
|
+
var mergeStackSteps = (kind, id, list, cursor) => {
|
|
5121
|
+
const groups = [];
|
|
5122
|
+
let current = null;
|
|
5123
|
+
const currentIndex = cursor - 1;
|
|
5124
|
+
list.forEach((step, index) => {
|
|
5125
|
+
const { opType } = step;
|
|
5126
|
+
const applied = index < cursor;
|
|
5127
|
+
const isCurrent = index === currentIndex;
|
|
5128
|
+
if (opType === "update" && current?.opType === "update") {
|
|
5129
|
+
current.steps.push({
|
|
5130
|
+
step,
|
|
5131
|
+
index,
|
|
5132
|
+
applied,
|
|
5133
|
+
isCurrent
|
|
5134
|
+
});
|
|
5135
|
+
current.applied = applied;
|
|
5136
|
+
if (isCurrent) current.isCurrent = true;
|
|
5137
|
+
} else {
|
|
5138
|
+
current = {
|
|
5139
|
+
kind,
|
|
5140
|
+
id,
|
|
5141
|
+
opType,
|
|
5142
|
+
steps: [{
|
|
5037
5143
|
step,
|
|
5038
5144
|
index,
|
|
5039
5145
|
applied,
|
|
5040
5146
|
isCurrent
|
|
5041
|
-
}
|
|
5042
|
-
current.applied = applied;
|
|
5043
|
-
if (isCurrent) current.isCurrent = true;
|
|
5044
|
-
} else {
|
|
5045
|
-
current = {
|
|
5046
|
-
kind: "data-source",
|
|
5047
|
-
id: dataSourceId,
|
|
5048
|
-
opType,
|
|
5049
|
-
steps: [{
|
|
5050
|
-
step,
|
|
5051
|
-
index,
|
|
5052
|
-
applied,
|
|
5053
|
-
isCurrent
|
|
5054
|
-
}],
|
|
5055
|
-
applied,
|
|
5056
|
-
isCurrent
|
|
5057
|
-
};
|
|
5058
|
-
groups.push(current);
|
|
5059
|
-
}
|
|
5060
|
-
});
|
|
5061
|
-
return groups;
|
|
5062
|
-
}
|
|
5063
|
-
/**
|
|
5064
|
-
* 根据 old/new 是否为 null 推断 opType(与 push 时的约定一致)。
|
|
5065
|
-
*/
|
|
5066
|
-
static detectOpType(oldVal, newVal) {
|
|
5067
|
-
if (oldVal === null && newVal !== null) return "add";
|
|
5068
|
-
if (oldVal !== null && newVal === null) return "remove";
|
|
5069
|
-
return "update";
|
|
5070
|
-
}
|
|
5071
|
-
/**
|
|
5072
|
-
* 把页面栈拆成若干 group:
|
|
5073
|
-
* - 单节点的 'update' 按 targetId 与相邻同 targetId 的 update 合并到一个 group;
|
|
5074
|
-
* - 'add' / 'remove' 始终独立成组(语义上是结构变更,不应被收纳进单节点修改组);
|
|
5075
|
-
* - 多节点 'update'(如批量改属性)也独立成组(无明确单一目标,避免误合并)。
|
|
5076
|
-
*/
|
|
5077
|
-
static mergePageSteps(pageId, list, cursor) {
|
|
5078
|
-
const groups = [];
|
|
5079
|
-
let current = null;
|
|
5080
|
-
const currentIndex = cursor - 1;
|
|
5081
|
-
list.forEach((step, index) => {
|
|
5082
|
-
const applied = index < cursor;
|
|
5083
|
-
const isCurrent = index === currentIndex;
|
|
5084
|
-
const targetId = History.detectPageTargetId(step);
|
|
5085
|
-
const targetName = History.detectPageTargetName(step);
|
|
5086
|
-
const entry = {
|
|
5087
|
-
step,
|
|
5088
|
-
index,
|
|
5147
|
+
}],
|
|
5089
5148
|
applied,
|
|
5090
5149
|
isCurrent
|
|
5091
5150
|
};
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5151
|
+
groups.push(current);
|
|
5152
|
+
}
|
|
5153
|
+
});
|
|
5154
|
+
return groups;
|
|
5155
|
+
};
|
|
5156
|
+
/**
|
|
5157
|
+
* 把页面栈拆成若干 group:
|
|
5158
|
+
* - 单节点的 'update' 按 targetId 与相邻同 targetId 的 update 合并到一个 group;
|
|
5159
|
+
* - 'add' / 'remove' 始终独立成组(语义上是结构变更,不应被收纳进单节点修改组);
|
|
5160
|
+
* - 多节点 'update'(如批量改属性)也独立成组(无明确单一目标,避免误合并)。
|
|
5161
|
+
*/
|
|
5162
|
+
var mergePageSteps = (pageId, list, cursor) => {
|
|
5163
|
+
const groups = [];
|
|
5164
|
+
let current = null;
|
|
5165
|
+
const currentIndex = cursor - 1;
|
|
5166
|
+
list.forEach((step, index) => {
|
|
5167
|
+
const applied = index < cursor;
|
|
5168
|
+
const isCurrent = index === currentIndex;
|
|
5169
|
+
const targetId = detectPageTargetId(step);
|
|
5170
|
+
const targetName = detectPageTargetName(step);
|
|
5171
|
+
const entry = {
|
|
5172
|
+
step,
|
|
5173
|
+
index,
|
|
5174
|
+
applied,
|
|
5175
|
+
isCurrent
|
|
5176
|
+
};
|
|
5177
|
+
const mergeable = step.opType === "update" && targetId !== void 0;
|
|
5178
|
+
if (mergeable && current?.opType === "update" && current.targetId === targetId) {
|
|
5179
|
+
current.steps.push(entry);
|
|
5180
|
+
current.applied = applied;
|
|
5181
|
+
if (isCurrent) current.isCurrent = true;
|
|
5182
|
+
if (targetName) current.targetName = targetName;
|
|
5183
|
+
} else {
|
|
5184
|
+
current = {
|
|
5185
|
+
kind: "page",
|
|
5186
|
+
pageId,
|
|
5187
|
+
opType: step.opType,
|
|
5188
|
+
targetId: mergeable ? targetId : void 0,
|
|
5189
|
+
targetName,
|
|
5190
|
+
steps: [entry],
|
|
5191
|
+
applied,
|
|
5192
|
+
isCurrent
|
|
5193
|
+
};
|
|
5194
|
+
groups.push(current);
|
|
5195
|
+
}
|
|
5196
|
+
});
|
|
5197
|
+
return groups;
|
|
5198
|
+
};
|
|
5199
|
+
/**
|
|
5200
|
+
* 解析 StepValue 中的"目标节点 id"用于合并:
|
|
5201
|
+
* - 单节点 update:取唯一一项 updatedItems 的节点 id;
|
|
5202
|
+
* - 其它情形(多节点 update / add / remove):返回 undefined,表示不参与合并。
|
|
5203
|
+
*/
|
|
5204
|
+
var detectPageTargetId = (step) => {
|
|
5205
|
+
if (step.opType !== "update") return void 0;
|
|
5206
|
+
const items = step.diff;
|
|
5207
|
+
if (items?.length !== 1) return void 0;
|
|
5208
|
+
return items[0].newSchema?.id ?? items[0].oldSchema?.id;
|
|
5209
|
+
};
|
|
5210
|
+
/** 解析 StepValue 中的目标节点可读名(用于 UI 展示)。 */
|
|
5211
|
+
var detectPageTargetName = (step) => {
|
|
5212
|
+
const items = step.diff;
|
|
5213
|
+
if (step.opType === "update") {
|
|
5214
|
+
if (items?.length === 1) {
|
|
5215
|
+
const node = items[0].newSchema || items[0].oldSchema;
|
|
5216
|
+
return node?.name || node?.type || (node?.id !== void 0 ? `${node.id}` : void 0);
|
|
5217
|
+
}
|
|
5218
|
+
return items?.length ? `${items.length} 个节点` : void 0;
|
|
5113
5219
|
}
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
*/
|
|
5119
|
-
static detectPageTargetId(step) {
|
|
5120
|
-
if (step.opType !== "update") return void 0;
|
|
5121
|
-
const items = step.updatedItems;
|
|
5122
|
-
if (items?.length !== 1) return void 0;
|
|
5123
|
-
return items[0].newNode?.id ?? items[0].oldNode?.id;
|
|
5124
|
-
}
|
|
5125
|
-
/** 解析 StepValue 中的目标节点可读名(用于 UI 展示)。 */
|
|
5126
|
-
static detectPageTargetName(step) {
|
|
5127
|
-
if (step.opType === "update") {
|
|
5128
|
-
const items = step.updatedItems;
|
|
5129
|
-
if (items?.length === 1) {
|
|
5130
|
-
const node = items[0].newNode || items[0].oldNode;
|
|
5131
|
-
return node?.name || node?.type || (node?.id !== void 0 ? `${node.id}` : void 0);
|
|
5132
|
-
}
|
|
5133
|
-
return items?.length ? `${items.length} 个节点` : void 0;
|
|
5220
|
+
if (step.opType === "add") {
|
|
5221
|
+
if (items?.length === 1) {
|
|
5222
|
+
const n = items[0].newSchema;
|
|
5223
|
+
return n?.name || n?.type || `${n?.id}`;
|
|
5134
5224
|
}
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
return
|
|
5225
|
+
return items?.length ? `${items.length} 个节点` : void 0;
|
|
5226
|
+
}
|
|
5227
|
+
if (step.opType === "remove") {
|
|
5228
|
+
if (items?.length === 1) {
|
|
5229
|
+
const n = items[0].oldSchema;
|
|
5230
|
+
return n?.name || n?.type || `${n?.id}`;
|
|
5141
5231
|
}
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5232
|
+
return items?.length ? `${items.length} 个节点` : void 0;
|
|
5233
|
+
}
|
|
5234
|
+
};
|
|
5235
|
+
/** 把 `Record<Id, UndoRedo>` 整体序列化为 `Record<Id, SerializedUndoRedo>`。 */
|
|
5236
|
+
var serializeStacks = (stacks) => {
|
|
5237
|
+
const result = {};
|
|
5238
|
+
Object.entries(stacks).forEach(([id, undoRedo]) => {
|
|
5239
|
+
if (undoRedo) result[id] = undoRedo.serialize();
|
|
5240
|
+
});
|
|
5241
|
+
return result;
|
|
5242
|
+
};
|
|
5243
|
+
/**
|
|
5244
|
+
* 把 `Record<Id, SerializedUndoRedo>` 整体还原为 `Record<Id, UndoRedo>`。
|
|
5245
|
+
* 还原时把每个栈的游标定位到最近一条已保存(`saved === true`)记录之后。
|
|
5246
|
+
*/
|
|
5247
|
+
var deserializeStacks = (stacks = {}) => {
|
|
5248
|
+
const result = {};
|
|
5249
|
+
Object.entries(stacks).forEach(([id, serialized]) => {
|
|
5250
|
+
if (serialized) result[id] = UndoRedo.fromSerialized(serialized, { isSavedStep: (element) => element.saved === true });
|
|
5251
|
+
});
|
|
5252
|
+
return result;
|
|
5253
|
+
};
|
|
5254
|
+
/**
|
|
5255
|
+
* 按 id 从「按 id 分栈」的记录表(代码块 / 数据源)中获取(或创建)对应的 UndoRedo 栈。
|
|
5256
|
+
*/
|
|
5257
|
+
var getOrCreateStack = (stacks, id) => {
|
|
5258
|
+
if (!stacks[id]) stacks[id] = new UndoRedo();
|
|
5259
|
+
return stacks[id];
|
|
5260
|
+
};
|
|
5261
|
+
/**
|
|
5262
|
+
* 撤销下限:当页面栈 index 0 是 `opType: 'initial'` 的基线 step 时为 1(基线不可被撤销),否则为 0。
|
|
5263
|
+
* 用于把 cursor 钉在基线之上,保证 undo / canUndo / goto 都不会越过初始基线。
|
|
5264
|
+
*/
|
|
5265
|
+
var undoFloor = (undoRedo) => {
|
|
5266
|
+
return undoRedo.getElementList()[0]?.opType === "initial" ? 1 : 0;
|
|
5267
|
+
};
|
|
5268
|
+
//#endregion
|
|
5269
|
+
//#region packages/editor/src/utils/indexed-db.ts
|
|
5270
|
+
/**
|
|
5271
|
+
* 一组极简的、基于原生 IndexedDB 的 Promise KV 工具,避免引入额外依赖。
|
|
5272
|
+
* 仅用于浏览器环境;在不支持 IndexedDB 的环境(如 SSR / 部分测试环境)下会 reject。
|
|
5273
|
+
*/
|
|
5274
|
+
/** 是否处于支持 IndexedDB 的环境。 */
|
|
5275
|
+
var isIndexedDBSupported = () => typeof indexedDB !== "undefined" && indexedDB !== null;
|
|
5276
|
+
/**
|
|
5277
|
+
* 打开(必要时升级)数据库,确保目标 objectStore 存在后返回连接。
|
|
5278
|
+
*
|
|
5279
|
+
* 由于 objectStore 只能在 `onupgradeneeded` 内创建,这里先以当前版本打开,
|
|
5280
|
+
* 若发现 store 不存在则关闭连接、以更高版本重开来按需创建,兼容动态 storeName。
|
|
5281
|
+
*/
|
|
5282
|
+
var openIndexedDB = (dbName, storeName) => new Promise((resolve, reject) => {
|
|
5283
|
+
if (!isIndexedDBSupported()) {
|
|
5284
|
+
reject(/* @__PURE__ */ new Error("当前环境不支持 IndexedDB"));
|
|
5285
|
+
return;
|
|
5286
|
+
}
|
|
5287
|
+
const request = indexedDB.open(dbName);
|
|
5288
|
+
request.onupgradeneeded = () => {
|
|
5289
|
+
const db = request.result;
|
|
5290
|
+
if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName);
|
|
5291
|
+
};
|
|
5292
|
+
request.onerror = () => reject(request.error);
|
|
5293
|
+
request.onsuccess = () => {
|
|
5294
|
+
const db = request.result;
|
|
5295
|
+
if (db.objectStoreNames.contains(storeName)) {
|
|
5296
|
+
resolve(db);
|
|
5297
|
+
return;
|
|
5148
5298
|
}
|
|
5299
|
+
const nextVersion = db.version + 1;
|
|
5300
|
+
db.close();
|
|
5301
|
+
const upgradeRequest = indexedDB.open(dbName, nextVersion);
|
|
5302
|
+
upgradeRequest.onupgradeneeded = () => {
|
|
5303
|
+
const upgradeDb = upgradeRequest.result;
|
|
5304
|
+
if (!upgradeDb.objectStoreNames.contains(storeName)) upgradeDb.createObjectStore(storeName);
|
|
5305
|
+
};
|
|
5306
|
+
upgradeRequest.onerror = () => reject(upgradeRequest.error);
|
|
5307
|
+
upgradeRequest.onsuccess = () => resolve(upgradeRequest.result);
|
|
5308
|
+
};
|
|
5309
|
+
});
|
|
5310
|
+
/** 写入(覆盖)一条记录。value 通过结构化克隆存储,支持 Map / Set 等结构。 */
|
|
5311
|
+
var idbSet = async (dbName, storeName, key, value) => {
|
|
5312
|
+
const db = await openIndexedDB(dbName, storeName);
|
|
5313
|
+
try {
|
|
5314
|
+
await new Promise((resolve, reject) => {
|
|
5315
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
5316
|
+
tx.objectStore(storeName).put(value, key);
|
|
5317
|
+
tx.oncomplete = () => resolve();
|
|
5318
|
+
tx.onabort = () => reject(tx.error);
|
|
5319
|
+
tx.onerror = () => reject(tx.error);
|
|
5320
|
+
});
|
|
5321
|
+
} finally {
|
|
5322
|
+
db.close();
|
|
5323
|
+
}
|
|
5324
|
+
};
|
|
5325
|
+
/** 读取一条记录,不存在时返回 undefined。 */
|
|
5326
|
+
var idbGet = async (dbName, storeName, key) => {
|
|
5327
|
+
const db = await openIndexedDB(dbName, storeName);
|
|
5328
|
+
try {
|
|
5329
|
+
return await new Promise((resolve, reject) => {
|
|
5330
|
+
const request = db.transaction(storeName, "readonly").objectStore(storeName).get(key);
|
|
5331
|
+
request.onsuccess = () => resolve(request.result);
|
|
5332
|
+
request.onerror = () => reject(request.error);
|
|
5333
|
+
});
|
|
5334
|
+
} finally {
|
|
5335
|
+
db.close();
|
|
5336
|
+
}
|
|
5337
|
+
};
|
|
5338
|
+
/** 删除一条记录。 */
|
|
5339
|
+
var idbDelete = async (dbName, storeName, key) => {
|
|
5340
|
+
const db = await openIndexedDB(dbName, storeName);
|
|
5341
|
+
try {
|
|
5342
|
+
await new Promise((resolve, reject) => {
|
|
5343
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
5344
|
+
tx.objectStore(storeName).delete(key);
|
|
5345
|
+
tx.oncomplete = () => resolve();
|
|
5346
|
+
tx.onabort = () => reject(tx.error);
|
|
5347
|
+
tx.onerror = () => reject(tx.error);
|
|
5348
|
+
});
|
|
5349
|
+
} finally {
|
|
5350
|
+
db.close();
|
|
5149
5351
|
}
|
|
5352
|
+
};
|
|
5353
|
+
//#endregion
|
|
5354
|
+
//#region packages/editor/src/services/history.ts
|
|
5355
|
+
/** 历史记录持久化快照的默认存储位置与结构版本。 */
|
|
5356
|
+
var DEFAULT_DB_NAME = "tmagic-editor";
|
|
5357
|
+
var DEFAULT_STORE_NAME = "history";
|
|
5358
|
+
var DEFAULT_KEY = "default";
|
|
5359
|
+
var PERSIST_VERSION = 1;
|
|
5360
|
+
var History = class extends BaseService {
|
|
5150
5361
|
state = (0, vue.reactive)({
|
|
5151
5362
|
pageSteps: {},
|
|
5152
5363
|
pageId: void 0,
|
|
@@ -5186,6 +5397,53 @@
|
|
|
5186
5397
|
this.state.dataSourceState = {};
|
|
5187
5398
|
}
|
|
5188
5399
|
/**
|
|
5400
|
+
* 为指定页面 / 页面片种入一条「初始基线」记录(如加载 DSL 时的「初始 / 加载」基线)。
|
|
5401
|
+
*
|
|
5402
|
+
* 该记录是一条 `opType: 'initial'` 的 {@link StepValue},作为页面历史栈 **index 0 的固定底线**:
|
|
5403
|
+
* - 它是一条真实入栈的 step(随栈一起持久化),但被钉为撤销/回滚的下限——cursor 永不低于它,
|
|
5404
|
+
* 因此不会被 undo / goto / revert 触达(详见 {@link undo} / {@link setCanUndoRedo});
|
|
5405
|
+
* - 历史面板把它过滤出分组列表(见 {@link getPageHistoryGroups}),改由底部「初始」行展示。
|
|
5406
|
+
*
|
|
5407
|
+
* 仅当目标页面栈为空时种入(保证 initial 一定位于 index 0);已存在 initial 底线时默认不重复种入,
|
|
5408
|
+
* 传 `force=true` 且栈为空时按新基线种入。
|
|
5409
|
+
*/
|
|
5410
|
+
setPageMarker(pageId, options = {}) {
|
|
5411
|
+
if (pageId === void 0 || pageId === null || `${pageId}` === "") return null;
|
|
5412
|
+
const existing = this.getPageMarker(pageId);
|
|
5413
|
+
if (existing) return existing;
|
|
5414
|
+
const stack = getOrCreateStack(this.state.pageSteps, pageId);
|
|
5415
|
+
if (stack.getLength() > 0) return null;
|
|
5416
|
+
const marker = {
|
|
5417
|
+
uuid: (0, _tmagic_utils.guid)(),
|
|
5418
|
+
opType: "initial",
|
|
5419
|
+
diff: [],
|
|
5420
|
+
data: {
|
|
5421
|
+
name: options.name || "",
|
|
5422
|
+
id: pageId
|
|
5423
|
+
},
|
|
5424
|
+
selectedBefore: [],
|
|
5425
|
+
selectedAfter: [],
|
|
5426
|
+
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
5427
|
+
historyDescription: options.description || "未修改的初始状态",
|
|
5428
|
+
timestamp: Date.now(),
|
|
5429
|
+
...options.source ? { source: options.source } : {}
|
|
5430
|
+
};
|
|
5431
|
+
stack.pushElement(marker);
|
|
5432
|
+
if (`${pageId}` === `${this.state.pageId}`) this.setCanUndoRedo();
|
|
5433
|
+
this.emit("page-marker-change", marker);
|
|
5434
|
+
return marker;
|
|
5435
|
+
}
|
|
5436
|
+
/**
|
|
5437
|
+
* 读取指定页面(缺省当前活动页)的初始基线 step(页面栈 index 0 且 `opType: 'initial'`);
|
|
5438
|
+
* 不存在时返回 undefined。
|
|
5439
|
+
*/
|
|
5440
|
+
getPageMarker(pageId) {
|
|
5441
|
+
const targetPageId = pageId ?? this.state.pageId;
|
|
5442
|
+
if (!targetPageId) return void 0;
|
|
5443
|
+
const first = this.state.pageSteps[targetPageId]?.getElementList()[0];
|
|
5444
|
+
return first?.opType === "initial" ? first : void 0;
|
|
5445
|
+
}
|
|
5446
|
+
/**
|
|
5189
5447
|
* 把一条步骤推入指定页面的栈;不指定 pageId 时落到当前活动页。
|
|
5190
5448
|
*
|
|
5191
5449
|
* 跨页操作(例如 `moveToContainer` 把节点搬到其它页)必须显式传入 `pageId`,
|
|
@@ -5194,11 +5452,31 @@
|
|
|
5194
5452
|
push(state, pageId) {
|
|
5195
5453
|
const undoRedo = this.getUndoRedo(pageId);
|
|
5196
5454
|
if (!undoRedo) return null;
|
|
5455
|
+
if (state.uuid === void 0) state.uuid = (0, _tmagic_utils.guid)();
|
|
5197
5456
|
if (state.timestamp === void 0) state.timestamp = Date.now();
|
|
5198
5457
|
undoRedo.pushElement(state);
|
|
5199
5458
|
if (pageId === void 0 || `${pageId}` === `${this.state.pageId}`) this.emit("change", state);
|
|
5200
5459
|
return state;
|
|
5201
5460
|
}
|
|
5461
|
+
/** 读取指定页面(缺省当前活动页)历史栈当前游标所在的 step(cursor - 1);无则返回 null。 */
|
|
5462
|
+
getCurrentPageStep(pageId) {
|
|
5463
|
+
const targetPageId = pageId ?? this.state.pageId;
|
|
5464
|
+
if (!targetPageId) return null;
|
|
5465
|
+
return this.state.pageSteps[targetPageId]?.getCurrentElement() ?? null;
|
|
5466
|
+
}
|
|
5467
|
+
/**
|
|
5468
|
+
* 用 `state` 替换指定页面栈当前游标所在的 step(并丢弃其后的重做尾部),游标不变。
|
|
5469
|
+
* 用于「连续 set root 记录合并」等就地替换最新一条的场景;替换成功后按需刷新 / 通知。
|
|
5470
|
+
*/
|
|
5471
|
+
replaceCurrentPageStep(state, pageId) {
|
|
5472
|
+
const undoRedo = this.getUndoRedo(pageId);
|
|
5473
|
+
if (!undoRedo) return null;
|
|
5474
|
+
if (state.uuid === void 0) state.uuid = (0, _tmagic_utils.guid)();
|
|
5475
|
+
if (state.timestamp === void 0) state.timestamp = Date.now();
|
|
5476
|
+
if (!undoRedo.replaceCurrentElement(state)) return null;
|
|
5477
|
+
this.emit("change", state);
|
|
5478
|
+
return state;
|
|
5479
|
+
}
|
|
5202
5480
|
/**
|
|
5203
5481
|
* 推入一条代码块变更记录(与页面/节点完全无关),按 `codeBlockId` 维度独立一份 UndoRedo 栈。
|
|
5204
5482
|
*
|
|
@@ -5209,17 +5487,15 @@
|
|
|
5209
5487
|
* - 不直接驱动 codeBlockService,调用方负责实际写回。
|
|
5210
5488
|
*/
|
|
5211
5489
|
pushCodeBlock(codeBlockId, payload) {
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
newContent: payload.newContent ? cloneDeep$1(payload.newContent) : null,
|
|
5217
|
-
changeRecords: payload.changeRecords?.length ? cloneDeep$1(payload.changeRecords) : void 0,
|
|
5490
|
+
const step = createStackStep(codeBlockId, {
|
|
5491
|
+
oldValue: payload.oldContent,
|
|
5492
|
+
newValue: payload.newContent,
|
|
5493
|
+
changeRecords: payload.changeRecords,
|
|
5218
5494
|
historyDescription: payload.historyDescription,
|
|
5219
|
-
source: payload.source
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
this.
|
|
5495
|
+
source: payload.source
|
|
5496
|
+
});
|
|
5497
|
+
if (!step) return null;
|
|
5498
|
+
getOrCreateStack(this.state.codeBlockState, codeBlockId).pushElement(step);
|
|
5223
5499
|
this.emit("code-block-history-change", codeBlockId, step);
|
|
5224
5500
|
return step;
|
|
5225
5501
|
}
|
|
@@ -5228,17 +5504,15 @@
|
|
|
5228
5504
|
* 行为同 pushCodeBlock(新增 oldSchema=null;删除 newSchema=null)。
|
|
5229
5505
|
*/
|
|
5230
5506
|
pushDataSource(dataSourceId, payload) {
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
newSchema: payload.newSchema ? cloneDeep$1(payload.newSchema) : null,
|
|
5236
|
-
changeRecords: payload.changeRecords?.length ? cloneDeep$1(payload.changeRecords) : void 0,
|
|
5507
|
+
const step = createStackStep(dataSourceId, {
|
|
5508
|
+
oldValue: payload.oldSchema,
|
|
5509
|
+
newValue: payload.newSchema,
|
|
5510
|
+
changeRecords: payload.changeRecords,
|
|
5237
5511
|
historyDescription: payload.historyDescription,
|
|
5238
|
-
source: payload.source
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
this.
|
|
5512
|
+
source: payload.source
|
|
5513
|
+
});
|
|
5514
|
+
if (!step) return null;
|
|
5515
|
+
getOrCreateStack(this.state.dataSourceState, dataSourceId).pushElement(step);
|
|
5242
5516
|
this.emit("data-source-history-change", dataSourceId, step);
|
|
5243
5517
|
return step;
|
|
5244
5518
|
}
|
|
@@ -5293,6 +5567,7 @@
|
|
|
5293
5567
|
undo() {
|
|
5294
5568
|
const undoRedo = this.getUndoRedo();
|
|
5295
5569
|
if (!undoRedo) return null;
|
|
5570
|
+
if (undoRedo.getCursor() <= undoFloor(undoRedo)) return null;
|
|
5296
5571
|
const state = undoRedo.undo();
|
|
5297
5572
|
this.emit("change", state);
|
|
5298
5573
|
return state;
|
|
@@ -5310,6 +5585,127 @@
|
|
|
5310
5585
|
this.removeAllPlugins();
|
|
5311
5586
|
}
|
|
5312
5587
|
/**
|
|
5588
|
+
* 清空指定页面(缺省当前活动页)的历史记录栈。
|
|
5589
|
+
* 仅删除撤销/重做记录,不会改动当前 DSL;清空后该页将无法再撤销/重做之前的操作。
|
|
5590
|
+
*/
|
|
5591
|
+
clearPage(pageId) {
|
|
5592
|
+
const targetPageId = pageId ?? this.state.pageId;
|
|
5593
|
+
if (!targetPageId) return;
|
|
5594
|
+
const marker = this.getPageMarker(targetPageId);
|
|
5595
|
+
this.state.pageSteps[targetPageId] = new UndoRedo();
|
|
5596
|
+
if (marker) this.setPageMarker(targetPageId, {
|
|
5597
|
+
name: marker.data?.name,
|
|
5598
|
+
description: marker.historyDescription,
|
|
5599
|
+
source: marker.source
|
|
5600
|
+
});
|
|
5601
|
+
if (`${targetPageId}` === `${this.state.pageId}`) {
|
|
5602
|
+
this.setCanUndoRedo();
|
|
5603
|
+
this.emit("clear-page", null);
|
|
5604
|
+
}
|
|
5605
|
+
}
|
|
5606
|
+
/**
|
|
5607
|
+
* 清空数据源历史记录栈:传入 `dataSourceId` 仅清空该数据源,缺省清空全部数据源。
|
|
5608
|
+
* 仅删除撤销/重做记录,不会改动数据源本身。
|
|
5609
|
+
*/
|
|
5610
|
+
clearDataSource(dataSourceId) {
|
|
5611
|
+
if (dataSourceId !== void 0) delete this.state.dataSourceState[dataSourceId];
|
|
5612
|
+
else this.state.dataSourceState = {};
|
|
5613
|
+
}
|
|
5614
|
+
/**
|
|
5615
|
+
* 清空代码块历史记录栈:传入 `codeBlockId` 仅清空该代码块,缺省清空全部代码块。
|
|
5616
|
+
* 仅删除撤销/重做记录,不会改动代码块本身。
|
|
5617
|
+
*/
|
|
5618
|
+
clearCodeBlock(codeBlockId) {
|
|
5619
|
+
if (codeBlockId !== void 0) delete this.state.codeBlockState[codeBlockId];
|
|
5620
|
+
else this.state.codeBlockState = {};
|
|
5621
|
+
}
|
|
5622
|
+
/**
|
|
5623
|
+
* 标记「整份 DSL 已保存」:把页面 / 代码块 / 数据源所有栈当前游标所在的记录都标为 `saved`。
|
|
5624
|
+
* 适用于「整体落库」场景;若只保存了其中一类,请改用更细粒度的
|
|
5625
|
+
* {@link markPageSaved} / {@link markCodeBlockSaved} / {@link markDataSourceSaved}。
|
|
5626
|
+
*/
|
|
5627
|
+
markSaved() {
|
|
5628
|
+
Object.values(this.state.pageSteps).forEach(markStackSaved);
|
|
5629
|
+
Object.values(this.state.codeBlockState).forEach(markStackSaved);
|
|
5630
|
+
Object.values(this.state.dataSourceState).forEach(markStackSaved);
|
|
5631
|
+
this.emit("mark-saved", { kind: "all" });
|
|
5632
|
+
}
|
|
5633
|
+
/**
|
|
5634
|
+
* 标记指定页面(缺省为当前活动页)的历史栈当前记录为已保存。
|
|
5635
|
+
* 仅影响该页面自己的栈,不波及代码块 / 数据源 / 其它页面。
|
|
5636
|
+
*/
|
|
5637
|
+
markPageSaved(pageId) {
|
|
5638
|
+
const targetPageId = pageId ?? this.state.pageId;
|
|
5639
|
+
if (!targetPageId) return;
|
|
5640
|
+
markStackSaved(this.state.pageSteps[targetPageId]);
|
|
5641
|
+
this.emit("mark-saved", {
|
|
5642
|
+
kind: "page",
|
|
5643
|
+
id: targetPageId
|
|
5644
|
+
});
|
|
5645
|
+
}
|
|
5646
|
+
/** 标记指定代码块的历史栈当前记录为已保存,仅影响该代码块自己的栈。 */
|
|
5647
|
+
markCodeBlockSaved(codeBlockId) {
|
|
5648
|
+
if (!codeBlockId) return;
|
|
5649
|
+
markStackSaved(this.state.codeBlockState[codeBlockId]);
|
|
5650
|
+
this.emit("mark-saved", {
|
|
5651
|
+
kind: "code-block",
|
|
5652
|
+
id: codeBlockId
|
|
5653
|
+
});
|
|
5654
|
+
}
|
|
5655
|
+
/** 标记指定数据源的历史栈当前记录为已保存,仅影响该数据源自己的栈。 */
|
|
5656
|
+
markDataSourceSaved(dataSourceId) {
|
|
5657
|
+
if (!dataSourceId) return;
|
|
5658
|
+
markStackSaved(this.state.dataSourceState[dataSourceId]);
|
|
5659
|
+
this.emit("mark-saved", {
|
|
5660
|
+
kind: "data-source",
|
|
5661
|
+
id: dataSourceId
|
|
5662
|
+
});
|
|
5663
|
+
}
|
|
5664
|
+
/**
|
|
5665
|
+
* 把当前内存中的全部历史栈(页面 / 代码块 / 数据源)序列化后写入本地 IndexedDB。
|
|
5666
|
+
*
|
|
5667
|
+
* - 每个 UndoRedo 栈连同其游标、容量一并保存,恢复后可继续 undo/redo;
|
|
5668
|
+
* - `key` 用于区分不同活动页 / 项目(同一 store 下可保存多份快照),缺省为 `default`;
|
|
5669
|
+
* - 返回写入成功的快照对象,便于调用方记录 savedAt 等信息;
|
|
5670
|
+
* - 不支持 IndexedDB 的环境(如 SSR)会 reject。
|
|
5671
|
+
*/
|
|
5672
|
+
async saveToIndexedDB(options = {}) {
|
|
5673
|
+
const { dbName = DEFAULT_DB_NAME, storeName = DEFAULT_STORE_NAME, key = DEFAULT_KEY, appId } = options;
|
|
5674
|
+
const snapshot = {
|
|
5675
|
+
version: PERSIST_VERSION,
|
|
5676
|
+
pageId: this.state.pageId,
|
|
5677
|
+
pageSteps: serializeStacks(this.state.pageSteps),
|
|
5678
|
+
codeBlockState: serializeStacks(this.state.codeBlockState),
|
|
5679
|
+
dataSourceState: serializeStacks(this.state.dataSourceState),
|
|
5680
|
+
savedAt: Date.now()
|
|
5681
|
+
};
|
|
5682
|
+
await idbSet(this.resolveDbName(dbName, appId), storeName, key, (0, serialize_javascript.default)(snapshot));
|
|
5683
|
+
this.emit("save-to-indexed-db", snapshot);
|
|
5684
|
+
return snapshot;
|
|
5685
|
+
}
|
|
5686
|
+
/**
|
|
5687
|
+
* 从本地 IndexedDB 读取此前保存的历史快照并重建全部撤销/重做栈。
|
|
5688
|
+
*
|
|
5689
|
+
* - 读取到的每个栈都会经 {@link UndoRedo.fromSerialized} 还原(含游标),随后可直接 undo/redo;
|
|
5690
|
+
* - 会整体覆盖当前内存中的历史状态,并把活动页恢复为快照中的 pageId;
|
|
5691
|
+
* - 找不到对应记录时返回 null,且不改动当前状态;
|
|
5692
|
+
* - 不支持 IndexedDB 的环境(如 SSR)会 reject。
|
|
5693
|
+
*/
|
|
5694
|
+
async restoreFromIndexedDB(options = {}) {
|
|
5695
|
+
const { dbName = DEFAULT_DB_NAME, storeName = DEFAULT_STORE_NAME, key = DEFAULT_KEY, appId } = options;
|
|
5696
|
+
const raw = await idbGet(this.resolveDbName(dbName, appId), storeName, key);
|
|
5697
|
+
if (!raw) return null;
|
|
5698
|
+
const snapshot = typeof raw === "string" ? getEditorConfig("parseDSL")(`(${raw})`) : raw;
|
|
5699
|
+
if (!snapshot) return null;
|
|
5700
|
+
this.state.pageSteps = deserializeStacks(snapshot.pageSteps);
|
|
5701
|
+
this.state.codeBlockState = deserializeStacks(snapshot.codeBlockState);
|
|
5702
|
+
this.state.dataSourceState = deserializeStacks(snapshot.dataSourceState);
|
|
5703
|
+
this.state.pageId = snapshot.pageId;
|
|
5704
|
+
this.setCanUndoRedo();
|
|
5705
|
+
this.emit("restore-from-indexed-db", snapshot);
|
|
5706
|
+
return snapshot;
|
|
5707
|
+
}
|
|
5708
|
+
/**
|
|
5313
5709
|
* 取出当前活动页的历史步骤平铺列表(包含已应用 + 已撤销)。
|
|
5314
5710
|
* 列表按时间正序,最早一步在最前面。
|
|
5315
5711
|
* 通常 UI 应使用 `getPageHistoryGroups` 取已合并分组的版本;本方法仅为兼容/调试保留。
|
|
@@ -5340,8 +5736,7 @@
|
|
|
5340
5736
|
if (!undoRedo) return [];
|
|
5341
5737
|
const list = undoRedo.getElementList();
|
|
5342
5738
|
if (!list.length) return [];
|
|
5343
|
-
|
|
5344
|
-
return History.mergePageSteps(targetPageId, list, cursor);
|
|
5739
|
+
return mergePageSteps(targetPageId, list, undoRedo.getCursor()).filter((group) => group.opType !== "initial");
|
|
5345
5740
|
}
|
|
5346
5741
|
/**
|
|
5347
5742
|
* 取出全部代码块的历史栈,按 codeBlockId 分组。
|
|
@@ -5357,7 +5752,7 @@
|
|
|
5357
5752
|
const list = undoRedo.getElementList();
|
|
5358
5753
|
if (!list.length) return;
|
|
5359
5754
|
const cursor = undoRedo.getCursor();
|
|
5360
|
-
groups.push(...
|
|
5755
|
+
groups.push(...mergeStackSteps("code-block", id, list, cursor));
|
|
5361
5756
|
});
|
|
5362
5757
|
return groups;
|
|
5363
5758
|
}
|
|
@@ -5407,6 +5802,44 @@
|
|
|
5407
5802
|
}));
|
|
5408
5803
|
}
|
|
5409
5804
|
/**
|
|
5805
|
+
* 按历史记录 uuid 在指定页面(默认当前活动页)的栈中查找其索引。
|
|
5806
|
+
* 找不到时返回 -1。供「按 uuid 回滚」等需要把 uuid 映射回 index 的场景使用。
|
|
5807
|
+
*/
|
|
5808
|
+
getPageStepIndexByUuid(uuid, pageId) {
|
|
5809
|
+
if (!uuid) return -1;
|
|
5810
|
+
return this.getPageStepList(pageId).findIndex((entry) => entry.step.uuid === uuid);
|
|
5811
|
+
}
|
|
5812
|
+
/**
|
|
5813
|
+
* 按历史记录 uuid 在全部代码块栈中查找其所属 codeBlockId 与索引。
|
|
5814
|
+
* 找不到时返回 null。
|
|
5815
|
+
*/
|
|
5816
|
+
findCodeBlockStepLocationByUuid(uuid) {
|
|
5817
|
+
if (!uuid) return null;
|
|
5818
|
+
for (const id of Object.keys(this.state.codeBlockState)) {
|
|
5819
|
+
const index = this.getCodeBlockStepList(id).findIndex((entry) => entry.step.uuid === uuid);
|
|
5820
|
+
if (index >= 0) return {
|
|
5821
|
+
id,
|
|
5822
|
+
index
|
|
5823
|
+
};
|
|
5824
|
+
}
|
|
5825
|
+
return null;
|
|
5826
|
+
}
|
|
5827
|
+
/**
|
|
5828
|
+
* 按历史记录 uuid 在全部数据源栈中查找其所属 dataSourceId 与索引。
|
|
5829
|
+
* 找不到时返回 null。
|
|
5830
|
+
*/
|
|
5831
|
+
findDataSourceStepLocationByUuid(uuid) {
|
|
5832
|
+
if (!uuid) return null;
|
|
5833
|
+
for (const id of Object.keys(this.state.dataSourceState)) {
|
|
5834
|
+
const index = this.getDataSourceStepList(id).findIndex((entry) => entry.step.uuid === uuid);
|
|
5835
|
+
if (index >= 0) return {
|
|
5836
|
+
id,
|
|
5837
|
+
index
|
|
5838
|
+
};
|
|
5839
|
+
}
|
|
5840
|
+
return null;
|
|
5841
|
+
}
|
|
5842
|
+
/**
|
|
5410
5843
|
* 取出全部数据源的历史栈,按 dataSourceId 分组。同上。
|
|
5411
5844
|
*/
|
|
5412
5845
|
getDataSourceHistoryGroups() {
|
|
@@ -5416,7 +5849,7 @@
|
|
|
5416
5849
|
const list = undoRedo.getElementList();
|
|
5417
5850
|
if (!list.length) return;
|
|
5418
5851
|
const cursor = undoRedo.getCursor();
|
|
5419
|
-
groups.push(...
|
|
5852
|
+
groups.push(...mergeStackSteps("data-source", id, list, cursor));
|
|
5420
5853
|
});
|
|
5421
5854
|
return groups;
|
|
5422
5855
|
}
|
|
@@ -5432,35 +5865,22 @@
|
|
|
5432
5865
|
if (!this.state.pageSteps[targetPageId]) this.state.pageSteps[targetPageId] = new UndoRedo();
|
|
5433
5866
|
return this.state.pageSteps[targetPageId];
|
|
5434
5867
|
}
|
|
5435
|
-
setCanUndoRedo() {
|
|
5436
|
-
const undoRedo = this.getUndoRedo();
|
|
5437
|
-
this.state.canRedo = undoRedo?.canRedo() || false;
|
|
5438
|
-
this.state.canUndo = undoRedo?.canUndo() || false;
|
|
5439
|
-
}
|
|
5440
5868
|
/**
|
|
5441
|
-
*
|
|
5869
|
+
* 把基础 dbName 与当前 DSL(root app)的 id 拼成最终库名,实现不同应用历史隔离。
|
|
5870
|
+
* 取不到 app id(如尚未加载 DSL)时退回基础 dbName。
|
|
5442
5871
|
*/
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
return
|
|
5872
|
+
resolveDbName(dbName, appId) {
|
|
5873
|
+
const resolvedAppId = appId ?? editor_default.get("root")?.id;
|
|
5874
|
+
return resolvedAppId ? `${dbName}-${resolvedAppId}` : dbName;
|
|
5446
5875
|
}
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
if (!this.state.dataSourceState[dataSourceId]) this.state.dataSourceState[dataSourceId] = new UndoRedo();
|
|
5452
|
-
return this.state.dataSourceState[dataSourceId];
|
|
5876
|
+
setCanUndoRedo() {
|
|
5877
|
+
const undoRedo = this.getUndoRedo();
|
|
5878
|
+
this.state.canRedo = undoRedo?.canRedo() || false;
|
|
5879
|
+
this.state.canUndo = undoRedo ? undoRedo.getCursor() > undoFloor(undoRedo) : false;
|
|
5453
5880
|
}
|
|
5454
5881
|
};
|
|
5455
5882
|
var history_default = new History();
|
|
5456
5883
|
//#endregion
|
|
5457
|
-
//#region packages/editor/src/utils/config.ts
|
|
5458
|
-
var $TMAGIC_EDITOR = {};
|
|
5459
|
-
var setEditorConfig = (option) => {
|
|
5460
|
-
$TMAGIC_EDITOR = option;
|
|
5461
|
-
};
|
|
5462
|
-
var getEditorConfig = (key) => $TMAGIC_EDITOR[key];
|
|
5463
|
-
//#endregion
|
|
5464
5884
|
//#region packages/editor/src/services/storage.ts
|
|
5465
5885
|
var Protocol = /* @__PURE__ */ function(Protocol) {
|
|
5466
5886
|
Protocol["OBJECT"] = "object";
|
|
@@ -6010,6 +6430,40 @@
|
|
|
6010
6430
|
aborted: false
|
|
6011
6431
|
};
|
|
6012
6432
|
};
|
|
6433
|
+
/**
|
|
6434
|
+
* 给「回滚」生成的新 step 用的简短描述生成器。
|
|
6435
|
+
* 与 UI 层 `describePageStep` 同义,但避免 service 反向依赖 layouts/,故放在此工具函数中。
|
|
6436
|
+
*/
|
|
6437
|
+
var describeStepForRevert = (step) => {
|
|
6438
|
+
const items = step.diff ?? [];
|
|
6439
|
+
const withId = (node, label) => {
|
|
6440
|
+
const id = node?.id;
|
|
6441
|
+
if (id === void 0 || id === null || `${id}` === "") return label;
|
|
6442
|
+
return label ? `${label}(id: ${id})` : `id: ${id}`;
|
|
6443
|
+
};
|
|
6444
|
+
switch (step.opType) {
|
|
6445
|
+
case "add": {
|
|
6446
|
+
const count = items.length;
|
|
6447
|
+
const node = items[0]?.newSchema;
|
|
6448
|
+
const label = node?.name || node?.type || "";
|
|
6449
|
+
return `撤回新增 ${count} 个节点${count === 1 ? `(${withId(node, label)})` : ""}`;
|
|
6450
|
+
}
|
|
6451
|
+
case "remove": {
|
|
6452
|
+
const count = items.length;
|
|
6453
|
+
const node = items[0]?.oldSchema;
|
|
6454
|
+
const label = node?.name || node?.type || "";
|
|
6455
|
+
return `还原已删除的 ${count} 个节点${count === 1 ? `(${withId(node, label)})` : ""}`;
|
|
6456
|
+
}
|
|
6457
|
+
default:
|
|
6458
|
+
if (items.length === 1) {
|
|
6459
|
+
const { newSchema, oldSchema, changeRecords } = items[0];
|
|
6460
|
+
const target = withId(newSchema || oldSchema, newSchema?.name || newSchema?.type || oldSchema?.name || oldSchema?.type || "");
|
|
6461
|
+
const propPath = changeRecords?.[0]?.propPath;
|
|
6462
|
+
return propPath ? `还原 ${target} · ${propPath}` : `还原 ${target}`;
|
|
6463
|
+
}
|
|
6464
|
+
return `还原 ${items.length} 个节点的修改`;
|
|
6465
|
+
}
|
|
6466
|
+
};
|
|
6013
6467
|
//#endregion
|
|
6014
6468
|
//#region packages/editor/src/utils/operator.ts
|
|
6015
6469
|
/**
|
|
@@ -6078,35 +6532,15 @@
|
|
|
6078
6532
|
//#endregion
|
|
6079
6533
|
//#region packages/editor/src/services/editor.ts
|
|
6080
6534
|
/**
|
|
6081
|
-
*
|
|
6082
|
-
*
|
|
6535
|
+
* 把「变更前后节点快照」列表归一成 update 类型的 {@link StepDiffItem} 列表,供 {@link StepValue.diff} 使用。
|
|
6536
|
+
* `changeRecords` 来自 form 端的 propPath/value 列表,撤销/重做时只对这些 propPath 做局部更新;
|
|
6537
|
+
* 缺省(未传 / 空数组)才退化为整节点替换。
|
|
6083
6538
|
*/
|
|
6084
|
-
var
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
const label = node?.name || node?.type || (node?.id !== void 0 ? `${node.id}` : "");
|
|
6090
|
-
return `撤回新增 ${count} 个节点${count === 1 && label ? `(${label})` : ""}`;
|
|
6091
|
-
}
|
|
6092
|
-
case "remove": {
|
|
6093
|
-
const count = step.removedItems?.length ?? 0;
|
|
6094
|
-
const node = step.removedItems?.[0]?.node;
|
|
6095
|
-
const label = node?.name || node?.type || (node?.id !== void 0 ? `${node.id}` : "");
|
|
6096
|
-
return `还原已删除的 ${count} 个节点${count === 1 && label ? `(${label})` : ""}`;
|
|
6097
|
-
}
|
|
6098
|
-
default: {
|
|
6099
|
-
const items = step.updatedItems ?? [];
|
|
6100
|
-
if (items.length === 1) {
|
|
6101
|
-
const { newNode, oldNode, changeRecords } = items[0];
|
|
6102
|
-
const target = newNode?.name || newNode?.type || oldNode?.name || oldNode?.type || `${newNode?.id ?? ""}`;
|
|
6103
|
-
const propPath = changeRecords?.[0]?.propPath;
|
|
6104
|
-
return propPath ? `还原 ${target} · ${propPath}` : `还原 ${target}`;
|
|
6105
|
-
}
|
|
6106
|
-
return `还原 ${items.length} 个节点的修改`;
|
|
6107
|
-
}
|
|
6108
|
-
}
|
|
6109
|
-
};
|
|
6539
|
+
var buildUpdateDiff = (items) => items.map(({ oldNode, newNode, changeRecords }) => ({
|
|
6540
|
+
oldSchema: oldNode,
|
|
6541
|
+
newSchema: newNode,
|
|
6542
|
+
...changeRecords?.length ? { changeRecords } : {}
|
|
6543
|
+
}));
|
|
6110
6544
|
var Editor = class extends BaseService {
|
|
6111
6545
|
state = (0, vue.reactive)({
|
|
6112
6546
|
root: null,
|
|
@@ -6124,6 +6558,12 @@
|
|
|
6124
6558
|
alwaysMultiSelect: false
|
|
6125
6559
|
});
|
|
6126
6560
|
selectionBeforeOp = null;
|
|
6561
|
+
/**
|
|
6562
|
+
* 最近一次 pushOpHistory 写入的历史记录 uuid。
|
|
6563
|
+
* 供 *AndGetHistoryId 系列方法在调用普通操作后取回本次产生的历史记录 id;
|
|
6564
|
+
* 普通操作不会读取它,调用前由 *AndGetHistoryId 重置为 null。
|
|
6565
|
+
*/
|
|
6566
|
+
lastPushedHistoryId = null;
|
|
6127
6567
|
constructor() {
|
|
6128
6568
|
super(canUsePluginMethods.async.map((methodName) => ({
|
|
6129
6569
|
name: methodName,
|
|
@@ -6138,8 +6578,9 @@
|
|
|
6138
6578
|
* 设置当前指点节点配置
|
|
6139
6579
|
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength
|
|
6140
6580
|
* @param value MNode
|
|
6581
|
+
* @param options.historySource 设置 root 时,本次变更写入历史记录的「操作来源」(仅 name === 'root' 时生效)
|
|
6141
6582
|
*/
|
|
6142
|
-
set(name, value) {
|
|
6583
|
+
set(name, value, options = {}) {
|
|
6143
6584
|
const preValue = this.state[name];
|
|
6144
6585
|
this.state[name] = value;
|
|
6145
6586
|
if (name === "nodes" && Array.isArray(value)) this.set("node", value[0]);
|
|
@@ -6150,6 +6591,13 @@
|
|
|
6150
6591
|
this.state.pageLength = getPageList(app).length || 0;
|
|
6151
6592
|
this.state.pageFragmentLength = getPageFragmentList(app).length || 0;
|
|
6152
6593
|
this.state.stageLoading = this.state.pageLength !== 0;
|
|
6594
|
+
if (preValue && !isEmpty(preValue)) this.pushRootDiffHistory(preValue, app, options.historySource);
|
|
6595
|
+
else app.items?.forEach((pageNode) => {
|
|
6596
|
+
if (pageNode?.id !== void 0 && !history_default.getPageMarker(pageNode.id)) history_default.setPageMarker(pageNode.id, {
|
|
6597
|
+
name: pageNode.name,
|
|
6598
|
+
source: options.historySource
|
|
6599
|
+
});
|
|
6600
|
+
});
|
|
6153
6601
|
} else {
|
|
6154
6602
|
this.state.pageLength = 0;
|
|
6155
6603
|
this.state.pageFragmentLength = 0;
|
|
@@ -6175,7 +6623,23 @@
|
|
|
6175
6623
|
getNodeInfo(id, raw = true) {
|
|
6176
6624
|
let root = this.get("root");
|
|
6177
6625
|
if (raw) root = (0, vue.toRaw)(root);
|
|
6178
|
-
|
|
6626
|
+
if (!root) return {
|
|
6627
|
+
node: null,
|
|
6628
|
+
parent: null,
|
|
6629
|
+
page: null
|
|
6630
|
+
};
|
|
6631
|
+
if (id === root.id) return {
|
|
6632
|
+
node: root,
|
|
6633
|
+
parent: null,
|
|
6634
|
+
page: null
|
|
6635
|
+
};
|
|
6636
|
+
const pageIdStr = `${this.get("page")?.id || ""}`;
|
|
6637
|
+
const currentPageNode = root.items?.find((item) => `${item.id}` === pageIdStr);
|
|
6638
|
+
if (currentPageNode && `${id}` !== pageIdStr) {
|
|
6639
|
+
const info = (0, _tmagic_utils.getNodeInfo)(id, currentPageNode);
|
|
6640
|
+
if (info.node) return info;
|
|
6641
|
+
}
|
|
6642
|
+
return (0, _tmagic_utils.getNodeInfo)(id, root, currentPageNode);
|
|
6179
6643
|
}
|
|
6180
6644
|
/**
|
|
6181
6645
|
* 根据ID获取指点节点配置
|
|
@@ -6368,23 +6832,26 @@
|
|
|
6368
6832
|
}
|
|
6369
6833
|
if (!((0, _tmagic_utils.isPage)(newNodes[0]) || (0, _tmagic_utils.isPageFragment)(newNodes[0]))) {
|
|
6370
6834
|
const pageForOp = this.getNodeInfo(newNodes[0].id, false).page;
|
|
6371
|
-
if (!doNotPushHistory)
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
indexMap: Object.fromEntries(newNodes.map((n) => {
|
|
6835
|
+
if (!doNotPushHistory) {
|
|
6836
|
+
const parentId = (this.getParentById(newNodes[0].id, false) ?? this.get("root")).id;
|
|
6837
|
+
this.pushOpHistory("add", {
|
|
6838
|
+
diff: newNodes.map((n) => {
|
|
6376
6839
|
const p = this.getParentById(n.id, false);
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6840
|
+
const idx = p ? getNodeIndex(n.id, p) : -1;
|
|
6841
|
+
return {
|
|
6842
|
+
newSchema: cloneDeep$1((0, vue.toRaw)(n)),
|
|
6843
|
+
parentId,
|
|
6844
|
+
index: typeof idx === "number" ? idx : -1
|
|
6845
|
+
};
|
|
6846
|
+
}),
|
|
6847
|
+
pageData: {
|
|
6848
|
+
name: pageForOp?.name || "",
|
|
6849
|
+
id: pageForOp.id
|
|
6850
|
+
},
|
|
6851
|
+
historyDescription,
|
|
6852
|
+
source: historySource
|
|
6853
|
+
});
|
|
6854
|
+
} else this.selectionBeforeOp = null;
|
|
6388
6855
|
}
|
|
6389
6856
|
this.emit("add", newNodes);
|
|
6390
6857
|
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
@@ -6464,7 +6931,7 @@
|
|
|
6464
6931
|
};
|
|
6465
6932
|
const idx = getNodeIndex(curNode.id, parent);
|
|
6466
6933
|
removedItems.push({
|
|
6467
|
-
|
|
6934
|
+
oldSchema: cloneDeep$1((0, vue.toRaw)(curNode)),
|
|
6468
6935
|
parentId: parent.id,
|
|
6469
6936
|
index: typeof idx === "number" ? idx : -1
|
|
6470
6937
|
});
|
|
@@ -6475,7 +6942,7 @@
|
|
|
6475
6942
|
doNotSwitchPage
|
|
6476
6943
|
})));
|
|
6477
6944
|
if (removedItems.length > 0 && pageForOp) if (!doNotPushHistory) this.pushOpHistory("remove", {
|
|
6478
|
-
|
|
6945
|
+
diff: removedItems,
|
|
6479
6946
|
pageData: pageForOp,
|
|
6480
6947
|
historyDescription,
|
|
6481
6948
|
source: historySource
|
|
@@ -6483,7 +6950,7 @@
|
|
|
6483
6950
|
else this.selectionBeforeOp = null;
|
|
6484
6951
|
this.emit("remove", nodes);
|
|
6485
6952
|
}
|
|
6486
|
-
async doUpdate(config, { changeRecords = [] } = {}) {
|
|
6953
|
+
async doUpdate(config, { changeRecords = [], historySource } = {}) {
|
|
6487
6954
|
const root = this.get("root");
|
|
6488
6955
|
if (!root) throw new Error("root为空");
|
|
6489
6956
|
if (!config?.id) throw new Error("没有配置或者配置缺少id值");
|
|
@@ -6494,7 +6961,7 @@
|
|
|
6494
6961
|
newConfig = mergeWith(cloneDeep$1(node), newConfig, editorNodeMergeCustomizer);
|
|
6495
6962
|
if (!newConfig.type) throw new Error("配置缺少type值");
|
|
6496
6963
|
if (newConfig.type === _tmagic_core.NodeType.ROOT) {
|
|
6497
|
-
this.set("root", newConfig);
|
|
6964
|
+
this.set("root", newConfig, { historySource });
|
|
6498
6965
|
return {
|
|
6499
6966
|
oldNode: node,
|
|
6500
6967
|
newNode: newConfig,
|
|
@@ -6544,17 +7011,20 @@
|
|
|
6544
7011
|
const nodes = Array.isArray(config) ? config : [config];
|
|
6545
7012
|
const updateData = await Promise.all(nodes.map((node, index) => {
|
|
6546
7013
|
const recordsForNode = changeRecordList ? changeRecordList[index] ?? [] : changeRecords ?? [];
|
|
6547
|
-
return this.doUpdate(node, {
|
|
7014
|
+
return this.doUpdate(node, {
|
|
7015
|
+
changeRecords: recordsForNode,
|
|
7016
|
+
historySource
|
|
7017
|
+
});
|
|
6548
7018
|
}));
|
|
6549
7019
|
if (updateData[0].oldNode?.type !== _tmagic_core.NodeType.ROOT) {
|
|
6550
7020
|
if (this.get("nodes").length) if (!doNotPushHistory) {
|
|
6551
7021
|
const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
|
|
6552
7022
|
this.pushOpHistory("update", {
|
|
6553
|
-
|
|
7023
|
+
diff: buildUpdateDiff(updateData.map((d) => ({
|
|
6554
7024
|
oldNode: cloneDeep$1(d.oldNode),
|
|
6555
|
-
newNode: cloneDeep$1(
|
|
7025
|
+
newNode: cloneDeep$1(d.newNode),
|
|
6556
7026
|
changeRecords: d.changeRecords?.length ? cloneDeep$1(d.changeRecords) : void 0
|
|
6557
|
-
}))
|
|
7027
|
+
}))),
|
|
6558
7028
|
pageData: {
|
|
6559
7029
|
name: pageForOp?.name || "",
|
|
6560
7030
|
id: pageForOp.id
|
|
@@ -6717,10 +7187,10 @@
|
|
|
6717
7187
|
if (!doNotPushHistory) {
|
|
6718
7188
|
const pageForOp = this.getNodeInfo(node.id, false).page;
|
|
6719
7189
|
this.pushOpHistory("update", {
|
|
6720
|
-
|
|
7190
|
+
diff: buildUpdateDiff([{
|
|
6721
7191
|
oldNode: oldParent,
|
|
6722
7192
|
newNode: cloneDeep$1((0, vue.toRaw)(parent))
|
|
6723
|
-
}]
|
|
7193
|
+
}]),
|
|
6724
7194
|
pageData: {
|
|
6725
7195
|
name: pageForOp?.name || "",
|
|
6726
7196
|
id: pageForOp.id
|
|
@@ -6794,7 +7264,7 @@
|
|
|
6794
7264
|
id: target.id
|
|
6795
7265
|
};
|
|
6796
7266
|
this.pushOpHistory("update", {
|
|
6797
|
-
|
|
7267
|
+
diff: buildUpdateDiff(updatedItems),
|
|
6798
7268
|
pageData: historyPage,
|
|
6799
7269
|
historyDescription,
|
|
6800
7270
|
source: historySource
|
|
@@ -6845,7 +7315,7 @@
|
|
|
6845
7315
|
if (!doNotPushHistory) {
|
|
6846
7316
|
const pageForOp = this.getNodeInfo(configs[0].id, false).page;
|
|
6847
7317
|
this.pushOpHistory("update", {
|
|
6848
|
-
|
|
7318
|
+
diff: buildUpdateDiff(updatedItems),
|
|
6849
7319
|
pageData: {
|
|
6850
7320
|
name: pageForOp?.name || "",
|
|
6851
7321
|
id: pageForOp.id
|
|
@@ -6861,6 +7331,49 @@
|
|
|
6861
7331
|
});
|
|
6862
7332
|
}
|
|
6863
7333
|
/**
|
|
7334
|
+
* 下列 *AndGetHistoryId 方法与对应的普通操作(add / remove / update ...)行为完全一致,
|
|
7335
|
+
* 唯一区别是返回值为本次写入历史栈的历史记录 uuid({@link StepValue.uuid}),
|
|
7336
|
+
* 而非节点 / 节点数组。可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
|
|
7337
|
+
*
|
|
7338
|
+
* 当本次操作未写入历史(doNotPushHistory 为 true、或操作无实际变更 / 提前返回)时返回 null。
|
|
7339
|
+
*/
|
|
7340
|
+
/** 等价于 {@link add},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
7341
|
+
async addAndGetHistoryId(addNode, parent, options = {}) {
|
|
7342
|
+
this.lastPushedHistoryId = null;
|
|
7343
|
+
await this.add(addNode, parent, options);
|
|
7344
|
+
return this.lastPushedHistoryId;
|
|
7345
|
+
}
|
|
7346
|
+
/** 等价于 {@link remove},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
7347
|
+
async removeAndGetHistoryId(nodeOrNodeList, options = {}) {
|
|
7348
|
+
this.lastPushedHistoryId = null;
|
|
7349
|
+
await this.remove(nodeOrNodeList, options);
|
|
7350
|
+
return this.lastPushedHistoryId;
|
|
7351
|
+
}
|
|
7352
|
+
/** 等价于 {@link update},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
7353
|
+
async updateAndGetHistoryId(config, data = {}) {
|
|
7354
|
+
this.lastPushedHistoryId = null;
|
|
7355
|
+
await this.update(config, data);
|
|
7356
|
+
return this.lastPushedHistoryId;
|
|
7357
|
+
}
|
|
7358
|
+
/** 等价于 {@link moveLayer},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
7359
|
+
async moveLayerAndGetHistoryId(offset, options = {}) {
|
|
7360
|
+
this.lastPushedHistoryId = null;
|
|
7361
|
+
await this.moveLayer(offset, options);
|
|
7362
|
+
return this.lastPushedHistoryId;
|
|
7363
|
+
}
|
|
7364
|
+
/** 等价于 {@link moveToContainer},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
7365
|
+
async moveToContainerAndGetHistoryId(config, targetId, options = {}) {
|
|
7366
|
+
this.lastPushedHistoryId = null;
|
|
7367
|
+
await this.moveToContainer(config, targetId, options);
|
|
7368
|
+
return this.lastPushedHistoryId;
|
|
7369
|
+
}
|
|
7370
|
+
/** 等价于 {@link dragTo},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
7371
|
+
async dragToAndGetHistoryId(config, targetParent, targetIndex, options = {}) {
|
|
7372
|
+
this.lastPushedHistoryId = null;
|
|
7373
|
+
await this.dragTo(config, targetParent, targetIndex, options);
|
|
7374
|
+
return this.lastPushedHistoryId;
|
|
7375
|
+
}
|
|
7376
|
+
/**
|
|
6864
7377
|
* 撤销当前操作
|
|
6865
7378
|
* @returns 被撤销的操作
|
|
6866
7379
|
*/
|
|
@@ -6898,9 +7411,10 @@
|
|
|
6898
7411
|
const entry = history_default.getPageStepList()[index];
|
|
6899
7412
|
if (!entry?.applied) return null;
|
|
6900
7413
|
const { step } = entry;
|
|
7414
|
+
if (step.opType === "initial") return null;
|
|
6901
7415
|
if (!this.get("root")) return null;
|
|
6902
7416
|
if (step.opType === "update") {
|
|
6903
|
-
const items = step.
|
|
7417
|
+
const items = step.diff ?? [];
|
|
6904
7418
|
if (!items.length || !items.every((item) => item.changeRecords?.length)) return null;
|
|
6905
7419
|
}
|
|
6906
7420
|
let revertedStep = null;
|
|
@@ -6917,24 +7431,26 @@
|
|
|
6917
7431
|
};
|
|
6918
7432
|
try {
|
|
6919
7433
|
switch (step.opType) {
|
|
6920
|
-
case "add":
|
|
6921
|
-
const
|
|
6922
|
-
|
|
6923
|
-
const existing = this.getNodeById(
|
|
7434
|
+
case "add":
|
|
7435
|
+
for (const { newSchema } of step.diff ?? []) {
|
|
7436
|
+
if (!newSchema) continue;
|
|
7437
|
+
const existing = this.getNodeById(newSchema.id, false);
|
|
6924
7438
|
if (existing) await this.remove(existing, opts);
|
|
6925
7439
|
}
|
|
6926
7440
|
break;
|
|
6927
|
-
}
|
|
6928
7441
|
case "remove": {
|
|
6929
|
-
const sorted = [...step.
|
|
6930
|
-
for (const {
|
|
7442
|
+
const sorted = [...step.diff ?? []].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
7443
|
+
for (const { oldSchema, parentId } of sorted) {
|
|
7444
|
+
if (!oldSchema || parentId === void 0) continue;
|
|
6931
7445
|
const parent = this.getNodeById(parentId, false);
|
|
6932
|
-
if (parent) await this.add([cloneDeep$1(
|
|
7446
|
+
if (parent) await this.add([cloneDeep$1(oldSchema)], parent, opts);
|
|
6933
7447
|
}
|
|
6934
7448
|
break;
|
|
6935
7449
|
}
|
|
6936
7450
|
case "update": {
|
|
6937
|
-
const configs = (step.
|
|
7451
|
+
const configs = (step.diff ?? []).filter((item) => item.oldSchema && item.newSchema).map(({ oldSchema, newSchema, changeRecords }) => {
|
|
7452
|
+
const oldNode = oldSchema;
|
|
7453
|
+
const newNode = newSchema;
|
|
6938
7454
|
if (changeRecords?.length) {
|
|
6939
7455
|
const patch = {
|
|
6940
7456
|
id: newNode.id,
|
|
@@ -6964,6 +7480,19 @@
|
|
|
6964
7480
|
return revertedStep;
|
|
6965
7481
|
}
|
|
6966
7482
|
/**
|
|
7483
|
+
* 通过历史记录 uuid 回滚当前页面的某条历史步骤,语义与 {@link revertPageStep} 完全一致,
|
|
7484
|
+
* 仅入参从 index 改为 uuid({@link StepValue.uuid})。uuid 不随栈内步骤增删而变化,
|
|
7485
|
+
* 更适合业务侧持有引用后再回滚(埋点、跨端同步等场景)。
|
|
7486
|
+
*
|
|
7487
|
+
* @param uuid 目标历史记录的 uuid,通常由 *AndGetHistoryId 方法返回
|
|
7488
|
+
* @returns 反向后产生的新 step;找不到对应 uuid / 未应用 / 反向失败时返回 null
|
|
7489
|
+
*/
|
|
7490
|
+
async revertPageStepById(uuid) {
|
|
7491
|
+
const index = history_default.getPageStepIndexByUuid(uuid);
|
|
7492
|
+
if (index < 0) return null;
|
|
7493
|
+
return this.revertPageStep(index);
|
|
7494
|
+
}
|
|
7495
|
+
/**
|
|
6967
7496
|
* 跳转当前页面历史栈到指定游标位置。
|
|
6968
7497
|
*
|
|
6969
7498
|
* `targetCursor` 与 `UndoRedo.getCursor()` 同义:表示"已应用步骤数量",
|
|
@@ -7039,19 +7568,83 @@
|
|
|
7039
7568
|
if (this.selectionBeforeOp) return;
|
|
7040
7569
|
this.selectionBeforeOp = this.get("nodes").map((n) => n.id);
|
|
7041
7570
|
}
|
|
7042
|
-
|
|
7571
|
+
/**
|
|
7572
|
+
* 比较「上一次 root」与「新 root」的页面 / 页面片,按页面粒度把整体替换拆成历史记录:
|
|
7573
|
+
* - 新旧都存在且内容变化的页面 → 一条 `update`(整页快照替换,无 changeRecords);
|
|
7574
|
+
* - 仅新 root 存在的页面 → 一条 `add`;
|
|
7575
|
+
* - 仅旧 root 存在的页面 → 一条 `remove`。
|
|
7576
|
+
*
|
|
7577
|
+
* 每条记录落到对应页面自己的历史栈(与普通节点操作一致),并标记来源 `source`。
|
|
7578
|
+
* 内容未变化的页面不产生记录,避免重复设置相同 DSL 时产生噪声。
|
|
7579
|
+
*/
|
|
7580
|
+
pushRootDiffHistory(preRoot, nextRoot, source) {
|
|
7581
|
+
const prevPages = preRoot?.items || [];
|
|
7582
|
+
const nextPages = nextRoot?.items || [];
|
|
7583
|
+
const prevMap = new Map(prevPages.map((p) => [`${p.id}`, p]));
|
|
7584
|
+
const nextMap = new Map(nextPages.map((p) => [`${p.id}`, p]));
|
|
7585
|
+
const indexInItems = (root, id) => (root.items ?? []).findIndex((item) => `${item.id}` === `${id}`);
|
|
7586
|
+
nextPages.forEach((nextPage) => {
|
|
7587
|
+
const prevPage = prevMap.get(`${nextPage.id}`);
|
|
7588
|
+
if (!prevPage) this.pushPageDiffStep("add", nextPage, {
|
|
7589
|
+
newSchema: cloneDeep$1((0, vue.toRaw)(nextPage)),
|
|
7590
|
+
parentId: nextRoot.id,
|
|
7591
|
+
index: indexInItems(nextRoot, nextPage.id)
|
|
7592
|
+
}, source);
|
|
7593
|
+
else if (!isEqual((0, vue.toRaw)(prevPage), (0, vue.toRaw)(nextPage))) this.pushPageDiffStep("update", nextPage, {
|
|
7594
|
+
oldSchema: cloneDeep$1((0, vue.toRaw)(prevPage)),
|
|
7595
|
+
newSchema: cloneDeep$1((0, vue.toRaw)(nextPage))
|
|
7596
|
+
}, source);
|
|
7597
|
+
});
|
|
7598
|
+
prevPages.forEach((prevPage) => {
|
|
7599
|
+
if (!nextMap.has(`${prevPage.id}`)) this.pushPageDiffStep("remove", prevPage, {
|
|
7600
|
+
oldSchema: cloneDeep$1((0, vue.toRaw)(prevPage)),
|
|
7601
|
+
parentId: preRoot.id,
|
|
7602
|
+
index: indexInItems(preRoot, prevPage.id)
|
|
7603
|
+
}, source);
|
|
7604
|
+
});
|
|
7605
|
+
}
|
|
7606
|
+
/**
|
|
7607
|
+
* 构造一条页面级「set root」历史记录(不携带选区 / modifiedNodeIds 上下文)并落到该页面自己的栈。
|
|
7608
|
+
*
|
|
7609
|
+
* 连续 set root 替换:若该页栈最新一条已是**同来源**的 set root 记录({@link StepValue.rootStep} 且 `source` 相同),
|
|
7610
|
+
* 则用本次记录**替换**它而非新增,避免源码反复保存 / 外部重设 DSL 时堆积多条 root 记录;
|
|
7611
|
+
* 来源不同则照常新增(initial 基线不是 rootStep,不在此列)。
|
|
7612
|
+
*/
|
|
7613
|
+
pushPageDiffStep(opType, page, diffItem, source) {
|
|
7614
|
+
const step = {
|
|
7615
|
+
uuid: (0, _tmagic_utils.guid)(),
|
|
7616
|
+
data: {
|
|
7617
|
+
name: page.name || "",
|
|
7618
|
+
id: page.id
|
|
7619
|
+
},
|
|
7620
|
+
opType,
|
|
7621
|
+
selectedBefore: [],
|
|
7622
|
+
selectedAfter: [],
|
|
7623
|
+
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
7624
|
+
diff: [diffItem],
|
|
7625
|
+
rootStep: true
|
|
7626
|
+
};
|
|
7627
|
+
if (source) step.source = source;
|
|
7628
|
+
const top = history_default.getCurrentPageStep(page.id);
|
|
7629
|
+
if (top?.rootStep && top.source === source) history_default.replaceCurrentPageStep(step, page.id);
|
|
7630
|
+
else history_default.push(step, page.id);
|
|
7631
|
+
}
|
|
7632
|
+
pushOpHistory(opType, { diff, pageData, historyDescription, source }) {
|
|
7043
7633
|
const step = {
|
|
7634
|
+
uuid: (0, _tmagic_utils.guid)(),
|
|
7044
7635
|
data: pageData,
|
|
7045
7636
|
opType,
|
|
7046
7637
|
selectedBefore: this.selectionBeforeOp ?? [],
|
|
7047
7638
|
selectedAfter: this.get("nodes").map((n) => n.id),
|
|
7048
7639
|
modifiedNodeIds: new Map(this.get("modifiedNodeIds")),
|
|
7049
|
-
|
|
7640
|
+
diff
|
|
7050
7641
|
};
|
|
7051
7642
|
if (historyDescription) step.historyDescription = historyDescription;
|
|
7052
7643
|
if (source) step.source = source;
|
|
7053
|
-
history_default.push(step, pageData.id);
|
|
7644
|
+
const historyId = history_default.push(step, pageData.id) ? step.uuid : null;
|
|
7645
|
+
this.lastPushedHistoryId = historyId;
|
|
7054
7646
|
this.selectionBeforeOp = null;
|
|
7647
|
+
return historyId;
|
|
7055
7648
|
}
|
|
7056
7649
|
/**
|
|
7057
7650
|
* 应用历史操作(撤销 / 重做)
|
|
@@ -7066,6 +7659,7 @@
|
|
|
7066
7659
|
* @param reverse true = 撤销,false = 重做
|
|
7067
7660
|
*/
|
|
7068
7661
|
async applyHistoryOp(step, reverse) {
|
|
7662
|
+
if (step.opType === "initial") return;
|
|
7069
7663
|
const root = this.get("root");
|
|
7070
7664
|
const stage = this.get("stage");
|
|
7071
7665
|
if (!root) return;
|
|
@@ -7076,56 +7670,59 @@
|
|
|
7076
7670
|
};
|
|
7077
7671
|
switch (step.opType) {
|
|
7078
7672
|
case "add": {
|
|
7079
|
-
const
|
|
7080
|
-
if (reverse) for (const
|
|
7081
|
-
|
|
7673
|
+
const items = step.diff ?? [];
|
|
7674
|
+
if (reverse) for (const { newSchema } of items) {
|
|
7675
|
+
if (!newSchema) continue;
|
|
7676
|
+
const existing = this.getNodeById(newSchema.id, false);
|
|
7082
7677
|
if (existing) await this.remove(existing, commonOpts);
|
|
7083
7678
|
}
|
|
7084
7679
|
else {
|
|
7085
|
-
const
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
if (parent.items)
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
});
|
|
7099
|
-
}
|
|
7680
|
+
const sorted = [...items].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
7681
|
+
for (const { newSchema, parentId, index } of sorted) {
|
|
7682
|
+
if (!newSchema || parentId === void 0) continue;
|
|
7683
|
+
const parent = this.getNodeById(parentId, false);
|
|
7684
|
+
if (parent?.items) {
|
|
7685
|
+
if (typeof index === "number" && index >= 0 && index < parent.items.length) parent.items.splice(index, 0, cloneDeep$1(newSchema));
|
|
7686
|
+
else parent.items.push(cloneDeep$1(newSchema));
|
|
7687
|
+
await stage?.add({
|
|
7688
|
+
config: cloneDeep$1(newSchema),
|
|
7689
|
+
parent: cloneDeep$1(parent),
|
|
7690
|
+
parentId: parent.id,
|
|
7691
|
+
root: cloneDeep$1(root)
|
|
7692
|
+
});
|
|
7100
7693
|
}
|
|
7101
7694
|
}
|
|
7102
7695
|
}
|
|
7103
7696
|
break;
|
|
7104
7697
|
}
|
|
7105
7698
|
case "remove": {
|
|
7106
|
-
const items = step.
|
|
7699
|
+
const items = step.diff ?? [];
|
|
7107
7700
|
if (reverse) {
|
|
7108
|
-
const sorted = [...items].sort((a, b) => a.index - b.index);
|
|
7109
|
-
for (const {
|
|
7701
|
+
const sorted = [...items].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
|
|
7702
|
+
for (const { oldSchema, parentId, index } of sorted) {
|
|
7703
|
+
if (!oldSchema || parentId === void 0) continue;
|
|
7110
7704
|
const parent = this.getNodeById(parentId, false);
|
|
7111
7705
|
if (parent?.items) {
|
|
7112
|
-
parent.items.splice(index, 0, cloneDeep$1(
|
|
7706
|
+
parent.items.splice(index ?? parent.items.length, 0, cloneDeep$1(oldSchema));
|
|
7113
7707
|
await stage?.add({
|
|
7114
|
-
config: cloneDeep$1(
|
|
7708
|
+
config: cloneDeep$1(oldSchema),
|
|
7115
7709
|
parent: cloneDeep$1(parent),
|
|
7116
7710
|
parentId,
|
|
7117
7711
|
root: cloneDeep$1(root)
|
|
7118
7712
|
});
|
|
7119
7713
|
}
|
|
7120
7714
|
}
|
|
7121
|
-
} else for (const {
|
|
7122
|
-
|
|
7715
|
+
} else for (const { oldSchema } of items) {
|
|
7716
|
+
if (!oldSchema) continue;
|
|
7717
|
+
const existing = this.getNodeById(oldSchema.id, false);
|
|
7123
7718
|
if (existing) await this.remove(existing, commonOpts);
|
|
7124
7719
|
}
|
|
7125
7720
|
break;
|
|
7126
7721
|
}
|
|
7127
7722
|
case "update": {
|
|
7128
|
-
const configs = (step.
|
|
7723
|
+
const configs = (step.diff ?? []).filter((item) => item.oldSchema && item.newSchema).map(({ oldSchema, newSchema, changeRecords }) => {
|
|
7724
|
+
const oldNode = oldSchema;
|
|
7725
|
+
const newNode = newSchema;
|
|
7129
7726
|
if (changeRecords?.length) {
|
|
7130
7727
|
const sourceForValues = reverse ? oldNode : newNode;
|
|
7131
7728
|
const patch = {
|
|
@@ -7206,6 +7803,7 @@
|
|
|
7206
7803
|
showPageListButton: true,
|
|
7207
7804
|
hideSlideBar: false,
|
|
7208
7805
|
sideBarItems: [],
|
|
7806
|
+
sideBarActiveTabName: "",
|
|
7209
7807
|
navMenuRect: {
|
|
7210
7808
|
left: 0,
|
|
7211
7809
|
top: 0,
|
|
@@ -7238,7 +7836,9 @@
|
|
|
7238
7836
|
}
|
|
7239
7837
|
if (name === "showGuides") mask?.showGuides(value);
|
|
7240
7838
|
if (name === "showRule") mask?.showRule(value);
|
|
7839
|
+
const preValue = state[name];
|
|
7241
7840
|
state[name] = value;
|
|
7841
|
+
if (preValue !== value) this.emit("state-change", name, value, preValue);
|
|
7242
7842
|
}
|
|
7243
7843
|
get(name) {
|
|
7244
7844
|
return state[name];
|
|
@@ -8461,7 +9061,7 @@
|
|
|
8461
9061
|
key: 1,
|
|
8462
9062
|
class: "menu-item-text"
|
|
8463
9063
|
};
|
|
8464
|
-
var _hoisted_2$
|
|
9064
|
+
var _hoisted_2$30 = { class: "el-dropdown-link menubar-menu-button" };
|
|
8465
9065
|
var ToolButton_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
8466
9066
|
name: "MEditorToolButton",
|
|
8467
9067
|
__name: "ToolButton",
|
|
@@ -8526,11 +9126,11 @@
|
|
|
8526
9126
|
placement: "bottom-start",
|
|
8527
9127
|
content: __props.data.tooltip
|
|
8528
9128
|
}, {
|
|
8529
|
-
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
|
|
9129
|
+
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), (0, vue.mergeProps)({
|
|
8530
9130
|
size: "small",
|
|
8531
9131
|
link: "",
|
|
8532
9132
|
disabled: disabled.value
|
|
8533
|
-
}, (0, vue.createSlots)({ _: 2 }, [__props.data.icon ? {
|
|
9133
|
+
}, __props.data.buttonProps || {}), (0, vue.createSlots)({ _: 2 }, [__props.data.icon ? {
|
|
8534
9134
|
name: "icon",
|
|
8535
9135
|
fn: (0, vue.withCtx)(() => [(0, vue.createVNode)(Icon_default, { icon: __props.data.icon }, null, 8, ["icon"])]),
|
|
8536
9136
|
key: "0"
|
|
@@ -8538,15 +9138,15 @@
|
|
|
8538
9138
|
name: "default",
|
|
8539
9139
|
fn: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)(__props.data.text), 1)]),
|
|
8540
9140
|
key: "1"
|
|
8541
|
-
} : void 0]),
|
|
9141
|
+
} : void 0]), 1040, ["disabled"])]),
|
|
8542
9142
|
_: 1
|
|
8543
|
-
}, 8, ["content"])) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicButton), {
|
|
9143
|
+
}, 8, ["content"])) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicButton), (0, vue.mergeProps)({
|
|
8544
9144
|
key: 1,
|
|
8545
9145
|
size: "small",
|
|
8546
9146
|
link: "",
|
|
8547
9147
|
disabled: disabled.value,
|
|
8548
9148
|
title: __props.data.text
|
|
8549
|
-
}, (0, vue.createSlots)({ _: 2 }, [__props.data.icon ? {
|
|
9149
|
+
}, __props.data.buttonProps || {}), (0, vue.createSlots)({ _: 2 }, [__props.data.icon ? {
|
|
8550
9150
|
name: "icon",
|
|
8551
9151
|
fn: (0, vue.withCtx)(() => [(0, vue.createVNode)(Icon_default, { icon: __props.data.icon }, null, 8, ["icon"])]),
|
|
8552
9152
|
key: "0"
|
|
@@ -8554,7 +9154,7 @@
|
|
|
8554
9154
|
name: "default",
|
|
8555
9155
|
fn: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)(__props.data.text), 1)]),
|
|
8556
9156
|
key: "1"
|
|
8557
|
-
} : void 0]),
|
|
9157
|
+
} : void 0]), 1040, ["disabled", "title"]))], 64)) : __props.data.type === "dropdown" ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicDropdown), {
|
|
8558
9158
|
key: 3,
|
|
8559
9159
|
trigger: "click",
|
|
8560
9160
|
disabled: disabled.value,
|
|
@@ -8575,7 +9175,7 @@
|
|
|
8575
9175
|
}), 128))]),
|
|
8576
9176
|
_: 1
|
|
8577
9177
|
})) : (0, vue.createCommentVNode)("v-if", true)]),
|
|
8578
|
-
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("span", _hoisted_2$
|
|
9178
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("span", _hoisted_2$30, [(0, vue.createTextVNode)((0, vue.toDisplayString)(__props.data.text), 1), (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicIcon), { class: "el-icon--right" }, {
|
|
8579
9179
|
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_element_plus_icons_vue.ArrowDown))]),
|
|
8580
9180
|
_: 1
|
|
8581
9181
|
})])]),
|
|
@@ -8594,7 +9194,7 @@
|
|
|
8594
9194
|
id: "m-editor-page-bar-add-icon",
|
|
8595
9195
|
class: "m-editor-page-bar-item m-editor-page-bar-item-icon"
|
|
8596
9196
|
};
|
|
8597
|
-
var _hoisted_2$
|
|
9197
|
+
var _hoisted_2$29 = {
|
|
8598
9198
|
key: 1,
|
|
8599
9199
|
style: { "width": "21px" }
|
|
8600
9200
|
};
|
|
@@ -8631,7 +9231,7 @@
|
|
|
8631
9231
|
}
|
|
8632
9232
|
} }, null, 8, ["data"])]),
|
|
8633
9233
|
_: 1
|
|
8634
|
-
})])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$
|
|
9234
|
+
})])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$29));
|
|
8635
9235
|
};
|
|
8636
9236
|
}
|
|
8637
9237
|
});
|
|
@@ -8644,7 +9244,7 @@
|
|
|
8644
9244
|
class: "m-editor-page-bar",
|
|
8645
9245
|
ref: "pageBar"
|
|
8646
9246
|
};
|
|
8647
|
-
var _hoisted_2$
|
|
9247
|
+
var _hoisted_2$28 = {
|
|
8648
9248
|
key: 0,
|
|
8649
9249
|
class: "m-editor-page-bar-items",
|
|
8650
9250
|
ref: "itemsContainer"
|
|
@@ -8736,7 +9336,7 @@
|
|
|
8736
9336
|
return (_ctx, _cache) => {
|
|
8737
9337
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$68, [
|
|
8738
9338
|
(0, vue.renderSlot)(_ctx.$slots, "prepend"),
|
|
8739
|
-
__props.length ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$
|
|
9339
|
+
__props.length ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$28, [(0, vue.renderSlot)(_ctx.$slots, "default")], 512)) : (0, vue.createCommentVNode)("v-if", true),
|
|
8740
9340
|
canScroll.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
8741
9341
|
key: 1,
|
|
8742
9342
|
class: "m-editor-page-bar-item m-editor-page-bar-item-icon m-editor-page-bar-item-left-icon",
|
|
@@ -8761,8 +9361,8 @@
|
|
|
8761
9361
|
id: "m-editor-page-bar-list-icon",
|
|
8762
9362
|
class: "m-editor-page-bar-item m-editor-page-bar-item-icon"
|
|
8763
9363
|
};
|
|
8764
|
-
var _hoisted_2$
|
|
8765
|
-
var _hoisted_3$
|
|
9364
|
+
var _hoisted_2$27 = { class: "page-bar-popover-wrapper" };
|
|
9365
|
+
var _hoisted_3$13 = { class: "page-bar-popover-inner" };
|
|
8766
9366
|
var PageList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
8767
9367
|
name: "MEditorPageList",
|
|
8768
9368
|
__name: "PageList",
|
|
@@ -8786,7 +9386,7 @@
|
|
|
8786
9386
|
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_element_plus_icons_vue.Files))]),
|
|
8787
9387
|
_: 1
|
|
8788
9388
|
})]),
|
|
8789
|
-
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_2$
|
|
9389
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_2$27, [(0, vue.createElementVNode)("div", _hoisted_3$13, [(0, vue.renderSlot)(_ctx.$slots, "page-list-popover", { list: __props.list }, () => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.list, (item, index) => {
|
|
8790
9390
|
return (0, vue.openBlock)(), (0, vue.createBlock)(ToolButton_default, {
|
|
8791
9391
|
data: {
|
|
8792
9392
|
type: "button",
|
|
@@ -8865,9 +9465,9 @@
|
|
|
8865
9465
|
//#endregion
|
|
8866
9466
|
//#region packages/editor/src/layouts/page-bar/PageBar.vue?vue&type=script&setup=true&lang.ts
|
|
8867
9467
|
var _hoisted_1$65 = { class: "m-editor-page-bar-tabs" };
|
|
8868
|
-
var _hoisted_2$
|
|
8869
|
-
var _hoisted_3$
|
|
8870
|
-
var _hoisted_4$
|
|
9468
|
+
var _hoisted_2$26 = ["data-page-id", "onClick"];
|
|
9469
|
+
var _hoisted_3$12 = { class: "m-editor-page-bar-title" };
|
|
9470
|
+
var _hoisted_4$9 = ["title"];
|
|
8871
9471
|
var PageBar_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
8872
9472
|
name: "MEditorPageBar",
|
|
8873
9473
|
__name: "PageBar",
|
|
@@ -8909,7 +9509,8 @@
|
|
|
8909
9509
|
top: 0
|
|
8910
9510
|
});
|
|
8911
9511
|
};
|
|
8912
|
-
const remove = (node) => {
|
|
9512
|
+
const remove = async (node) => {
|
|
9513
|
+
await _tmagic_design.tMagicMessageBox.confirm("确定删除该页面吗?");
|
|
8913
9514
|
editorService.remove(node);
|
|
8914
9515
|
};
|
|
8915
9516
|
const pageBarScrollContainerRef = (0, vue.useTemplateRef)("pageBarScrollContainer");
|
|
@@ -8956,7 +9557,7 @@
|
|
|
8956
9557
|
key: item.id,
|
|
8957
9558
|
"data-page-id": item.id,
|
|
8958
9559
|
onClick: ($event) => switchPage(item.id)
|
|
8959
|
-
}, [(0, vue.createElementVNode)("div", _hoisted_3$
|
|
9560
|
+
}, [(0, vue.createElementVNode)("div", _hoisted_3$12, [(0, vue.renderSlot)(_ctx.$slots, "page-bar-title", { page: item }, () => [(0, vue.createElementVNode)("span", { title: item.name }, (0, vue.toDisplayString)(item.name || item.id), 9, _hoisted_4$9)])]), (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicPopover), {
|
|
8960
9561
|
"popper-class": "page-bar-popover",
|
|
8961
9562
|
placement: "top",
|
|
8962
9563
|
trigger: "hover",
|
|
@@ -8976,10 +9577,11 @@
|
|
|
8976
9577
|
type: "button",
|
|
8977
9578
|
text: "删除",
|
|
8978
9579
|
icon: (0, vue.unref)(_element_plus_icons_vue.Delete),
|
|
9580
|
+
buttonProps: { type: "danger" },
|
|
8979
9581
|
handler: () => remove(item)
|
|
8980
9582
|
} }, null, 8, ["data"])])])]),
|
|
8981
9583
|
_: 2
|
|
8982
|
-
}, 1024)], 10, _hoisted_2$
|
|
9584
|
+
}, 1024)], 10, _hoisted_2$26);
|
|
8983
9585
|
}), 128))]),
|
|
8984
9586
|
_: 3
|
|
8985
9587
|
}, 8, ["page-bar-sort-options", "length"])]);
|
|
@@ -8992,7 +9594,7 @@
|
|
|
8992
9594
|
//#endregion
|
|
8993
9595
|
//#region packages/editor/src/layouts/AddPageBox.vue?vue&type=script&setup=true&lang.ts
|
|
8994
9596
|
var _hoisted_1$64 = { class: "m-editor-empty-panel" };
|
|
8995
|
-
var _hoisted_2$
|
|
9597
|
+
var _hoisted_2$25 = { class: "m-editor-empty-content" };
|
|
8996
9598
|
var AddPageBox_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
8997
9599
|
name: "MEditorAddPageBox",
|
|
8998
9600
|
__name: "AddPageBox",
|
|
@@ -9009,7 +9611,7 @@
|
|
|
9009
9611
|
});
|
|
9010
9612
|
};
|
|
9011
9613
|
return (_ctx, _cache) => {
|
|
9012
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$64, [(0, vue.createElementVNode)("div", _hoisted_2$
|
|
9614
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$64, [(0, vue.createElementVNode)("div", _hoisted_2$25, [(0, vue.createElementVNode)("div", {
|
|
9013
9615
|
class: "m-editor-empty-button",
|
|
9014
9616
|
onClick: _cache[0] || (_cache[0] = ($event) => clickHandler((0, vue.unref)(_tmagic_core.NodeType).PAGE))
|
|
9015
9617
|
}, [(0, vue.createElementVNode)("div", null, [(0, vue.createVNode)(Icon_default, { icon: (0, vue.unref)(_element_plus_icons_vue.Plus) }, null, 8, ["icon"])]), _cache[2] || (_cache[2] = (0, vue.createElementVNode)("p", null, "新增页面", -1))]), !__props.disabledPageFragment ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
@@ -9026,7 +9628,7 @@
|
|
|
9026
9628
|
//#endregion
|
|
9027
9629
|
//#region packages/editor/src/layouts/CodeEditor.vue?vue&type=script&setup=true&lang.ts
|
|
9028
9630
|
var _hoisted_1$63 = { class: "magic-code-editor" };
|
|
9029
|
-
var _hoisted_2$
|
|
9631
|
+
var _hoisted_2$24 = {
|
|
9030
9632
|
ref: "codeEditor",
|
|
9031
9633
|
class: "magic-code-editor-content"
|
|
9032
9634
|
};
|
|
@@ -9281,7 +9883,7 @@
|
|
|
9281
9883
|
}, {
|
|
9282
9884
|
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(Icon_default, { icon: (0, vue.unref)(_element_plus_icons_vue.FullScreen) }, null, 8, ["icon"])]),
|
|
9283
9885
|
_: 1
|
|
9284
|
-
})) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createElementVNode)("div", _hoisted_2$
|
|
9886
|
+
})) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createElementVNode)("div", _hoisted_2$24, null, 512)], 6)], 8, ["disabled"]))]);
|
|
9285
9887
|
};
|
|
9286
9888
|
}
|
|
9287
9889
|
});
|
|
@@ -9348,7 +9950,7 @@
|
|
|
9348
9950
|
const saveCode = (value) => {
|
|
9349
9951
|
try {
|
|
9350
9952
|
const parseDSL = getEditorConfig("parseDSL");
|
|
9351
|
-
editorService.set("root", parseDSL(value));
|
|
9953
|
+
editorService.set("root", parseDSL(value), { historySource: "root-code" });
|
|
9352
9954
|
} catch (e) {
|
|
9353
9955
|
console.error(e);
|
|
9354
9956
|
}
|
|
@@ -9422,6 +10024,8 @@
|
|
|
9422
10024
|
var Framework_default = Framework_vue_vue_type_script_setup_true_lang_default;
|
|
9423
10025
|
//#endregion
|
|
9424
10026
|
//#region packages/editor/src/layouts/history-list/composables.ts
|
|
10027
|
+
/** 合并组默认展开;仅当 expanded[key] === false 时为收起。 */
|
|
10028
|
+
var isHistoryGroupExpanded = (expanded, key) => expanded[key] !== false;
|
|
9425
10029
|
/**
|
|
9426
10030
|
* 历史记录面板共享逻辑:
|
|
9427
10031
|
* - 暴露三类历史的聚合数据(页面 / 数据源 / 代码块);
|
|
@@ -9435,10 +10039,11 @@
|
|
|
9435
10039
|
/**
|
|
9436
10040
|
* 折叠状态:key 形如 `pg-${组内首步 index}` / `ds-${id}-${组内首步 index}` / `cb-${id}-${组内首步 index}`。
|
|
9437
10041
|
* 用组内首步的稳定 index(而非展示位置)作为 key,确保历史数据更新后已展开的分组状态保持不变。
|
|
10042
|
+
* 合并组默认展开;仅当值为 `false` 时表示收起。
|
|
9438
10043
|
*/
|
|
9439
10044
|
const expanded = (0, vue.reactive)({});
|
|
9440
10045
|
const toggleGroup = (key) => {
|
|
9441
|
-
expanded[key] =
|
|
10046
|
+
expanded[key] = expanded[key] === false;
|
|
9442
10047
|
};
|
|
9443
10048
|
const pageGroups = (0, vue.computed)(() => historyService.getPageHistoryGroups());
|
|
9444
10049
|
const dataSourceGroups = (0, vue.computed)(() => historyService.getDataSourceHistoryGroups());
|
|
@@ -9500,6 +10105,7 @@
|
|
|
9500
10105
|
"component-panel": "组件面板",
|
|
9501
10106
|
props: "配置面板",
|
|
9502
10107
|
code: "源码",
|
|
10108
|
+
"root-code": "DSL源码",
|
|
9503
10109
|
"stage-contextmenu": "画布菜单",
|
|
9504
10110
|
"tree-contextmenu": "树菜单",
|
|
9505
10111
|
toolbar: "工具栏",
|
|
@@ -9507,6 +10113,8 @@
|
|
|
9507
10113
|
rollback: "回滚",
|
|
9508
10114
|
api: "接口",
|
|
9509
10115
|
ai: "AI",
|
|
10116
|
+
initial: "初始值",
|
|
10117
|
+
sync: "同步",
|
|
9510
10118
|
unknown: "未知"
|
|
9511
10119
|
};
|
|
9512
10120
|
/** 操作途径文案:用于历史面板展示「画布 / 树面板 / 配置面板…」标签。 */
|
|
@@ -9515,6 +10123,37 @@
|
|
|
9515
10123
|
};
|
|
9516
10124
|
/** 取一组历史步骤里最后一步(最近一次)的操作途径,用于组头部展示。 */
|
|
9517
10125
|
var groupSource = (group) => group.steps[group.steps.length - 1]?.step.source;
|
|
10126
|
+
/**
|
|
10127
|
+
* 把一个历史分组(页面 / bucket)派生为 GroupRow 直接消费的视图模型 {@link HistoryRowGroup}。
|
|
10128
|
+
* 统一了原先 PageTab / Bucket 各自内联的 sub-steps 映射逻辑:描述、可差异、可回滚、时间、途径
|
|
10129
|
+
* 全部在此一次性算好,组件层只负责渲染。
|
|
10130
|
+
*/
|
|
10131
|
+
var toRowGroup = (group, key, descriptor) => {
|
|
10132
|
+
const { describeGroup, describeStep, isStepDiffable, isStepRevertable } = descriptor;
|
|
10133
|
+
const timestamp = groupTimestamp(group);
|
|
10134
|
+
return {
|
|
10135
|
+
key,
|
|
10136
|
+
applied: group.applied,
|
|
10137
|
+
isCurrent: Boolean(group.isCurrent),
|
|
10138
|
+
opType: group.opType,
|
|
10139
|
+
desc: describeGroup(group),
|
|
10140
|
+
source: groupSource(group),
|
|
10141
|
+
time: formatHistoryTime(timestamp),
|
|
10142
|
+
timeTitle: formatHistoryFullTime(timestamp),
|
|
10143
|
+
subSteps: group.steps.map((s) => ({
|
|
10144
|
+
index: s.index,
|
|
10145
|
+
applied: s.applied,
|
|
10146
|
+
isCurrent: s.isCurrent,
|
|
10147
|
+
saved: s.step.saved,
|
|
10148
|
+
desc: describeStep(s.step),
|
|
10149
|
+
diffable: isStepDiffable ? isStepDiffable(s.step) : false,
|
|
10150
|
+
revertable: s.applied && (isStepRevertable ? isStepRevertable(s.step) : true),
|
|
10151
|
+
source: s.step.source,
|
|
10152
|
+
time: formatHistoryTime(s.step.timestamp),
|
|
10153
|
+
timeTitle: formatHistoryFullTime(s.step.timestamp)
|
|
10154
|
+
}))
|
|
10155
|
+
};
|
|
10156
|
+
};
|
|
9518
10157
|
var nameOf = (node) => node?.name || node?.type || `${node?.id ?? ""}`;
|
|
9519
10158
|
/**
|
|
9520
10159
|
* 默认描述里展示「名称 (id: xxx)」,便于区分同名实体。
|
|
@@ -9533,24 +10172,24 @@
|
|
|
9533
10172
|
var describePageStep = (step) => {
|
|
9534
10173
|
if (step.historyDescription) return step.historyDescription;
|
|
9535
10174
|
const { opType } = step;
|
|
10175
|
+
const items = step.diff ?? [];
|
|
9536
10176
|
if (opType === "add") {
|
|
9537
|
-
const count =
|
|
9538
|
-
const node =
|
|
10177
|
+
const count = items.length;
|
|
10178
|
+
const node = items[0]?.newSchema;
|
|
9539
10179
|
return `新增 ${count} 个节点${count === 1 && node ? `(${labelWithId(nameOf(node), node.id)})` : ""}`;
|
|
9540
10180
|
}
|
|
9541
10181
|
if (opType === "remove") {
|
|
9542
|
-
const count =
|
|
9543
|
-
const node =
|
|
10182
|
+
const count = items.length;
|
|
10183
|
+
const node = items[0]?.oldSchema;
|
|
9544
10184
|
return `删除 ${count} 个节点${count === 1 && node ? `(${labelWithId(nameOf(node), node.id)})` : ""}`;
|
|
9545
10185
|
}
|
|
9546
|
-
|
|
9547
|
-
if (
|
|
9548
|
-
|
|
9549
|
-
const { newNode, changeRecords } = updated[0];
|
|
10186
|
+
if (!items.length) return "修改节点";
|
|
10187
|
+
if (items.length === 1) {
|
|
10188
|
+
const { newSchema, changeRecords } = items[0];
|
|
9550
10189
|
const propPath = changeRecords?.[0]?.propPath;
|
|
9551
|
-
return `修改 ${labelWithId(nameOf(
|
|
10190
|
+
return `修改 ${labelWithId(nameOf(newSchema), newSchema?.id)}${propPath ? ` · ${propPath}` : ""}`;
|
|
9552
10191
|
}
|
|
9553
|
-
return `修改 ${
|
|
10192
|
+
return `修改 ${items.length} 个节点`;
|
|
9554
10193
|
};
|
|
9555
10194
|
/**
|
|
9556
10195
|
* 合并组的展示文案:
|
|
@@ -9564,7 +10203,7 @@
|
|
|
9564
10203
|
if (group.steps.length === 1) return describePageStep(group.steps[0].step);
|
|
9565
10204
|
const paths = /* @__PURE__ */ new Set();
|
|
9566
10205
|
group.steps.forEach((s) => {
|
|
9567
|
-
s.step.
|
|
10206
|
+
s.step.diff?.[0]?.changeRecords?.forEach((r) => r.propPath && paths.add(r.propPath));
|
|
9568
10207
|
});
|
|
9569
10208
|
const pathList = Array.from(paths).slice(0, 3).join(", ");
|
|
9570
10209
|
const target = labelWithId(group.targetName ?? (group.targetId !== void 0 ? `${group.targetId}` : "节点"), group.targetId);
|
|
@@ -9572,10 +10211,11 @@
|
|
|
9572
10211
|
};
|
|
9573
10212
|
var describeDataSourceStep = (step) => {
|
|
9574
10213
|
if (step.historyDescription) return step.historyDescription;
|
|
9575
|
-
|
|
9576
|
-
if (
|
|
9577
|
-
|
|
9578
|
-
const
|
|
10214
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
10215
|
+
if (!oldSchema && newSchema) return `创建 ${labelWithId(newSchema.title, newSchema.id ?? step.id)}`;
|
|
10216
|
+
if (!newSchema && oldSchema) return `删除 ${labelWithId(oldSchema.title, oldSchema.id ?? step.id)}`;
|
|
10217
|
+
const propPath = changeRecords?.[0]?.propPath;
|
|
10218
|
+
const title = labelWithId(newSchema?.title || oldSchema?.title, step.id);
|
|
9579
10219
|
return propPath ? `修改 ${title} · ${propPath}` : `修改 ${title}`;
|
|
9580
10220
|
};
|
|
9581
10221
|
var describeDataSourceGroup = (group) => {
|
|
@@ -9584,18 +10224,19 @@
|
|
|
9584
10224
|
if (group.steps.length === 1) return describeDataSourceStep(group.steps[0].step);
|
|
9585
10225
|
const paths = /* @__PURE__ */ new Set();
|
|
9586
10226
|
group.steps.forEach((s) => {
|
|
9587
|
-
s.step.changeRecords?.forEach((r) => r.propPath && paths.add(r.propPath));
|
|
10227
|
+
s.step.diff?.[0]?.changeRecords?.forEach((r) => r.propPath && paths.add(r.propPath));
|
|
9588
10228
|
});
|
|
9589
10229
|
const pathList = Array.from(paths).slice(0, 3).join(", ");
|
|
9590
|
-
const target = labelWithId(group.steps[group.steps.length - 1].step.newSchema?.title || group.steps[0].step.oldSchema?.title, group.id);
|
|
10230
|
+
const target = labelWithId(group.steps[group.steps.length - 1].step.diff?.[0]?.newSchema?.title || group.steps[0].step.diff?.[0]?.oldSchema?.title, group.id);
|
|
9591
10231
|
return pathList ? `修改 ${target} · ${pathList}${paths.size > 3 ? "…" : ""}` : `修改 ${target}`;
|
|
9592
10232
|
};
|
|
9593
10233
|
var describeCodeBlockStep = (step) => {
|
|
9594
10234
|
if (step.historyDescription) return step.historyDescription;
|
|
9595
|
-
|
|
9596
|
-
if (
|
|
9597
|
-
|
|
9598
|
-
const
|
|
10235
|
+
const { oldSchema: oldContent, newSchema: newContent, changeRecords } = step.diff?.[0] ?? {};
|
|
10236
|
+
if (!oldContent && newContent) return `创建 ${labelWithId(newContent.name, newContent.id ?? step.id)}`;
|
|
10237
|
+
if (!newContent && oldContent) return `删除 ${labelWithId(oldContent.name, oldContent.id ?? step.id)}`;
|
|
10238
|
+
const propPath = changeRecords?.[0]?.propPath;
|
|
10239
|
+
const title = labelWithId(newContent?.name || oldContent?.name, step.id);
|
|
9599
10240
|
return propPath ? `修改 ${title} · ${propPath}` : `修改 ${title}`;
|
|
9600
10241
|
};
|
|
9601
10242
|
var describeCodeBlockGroup = (group) => {
|
|
@@ -9604,10 +10245,10 @@
|
|
|
9604
10245
|
if (group.steps.length === 1) return describeCodeBlockStep(group.steps[0].step);
|
|
9605
10246
|
const paths = /* @__PURE__ */ new Set();
|
|
9606
10247
|
group.steps.forEach((s) => {
|
|
9607
|
-
s.step.changeRecords?.forEach((r) => r.propPath && paths.add(r.propPath));
|
|
10248
|
+
s.step.diff?.[0]?.changeRecords?.forEach((r) => r.propPath && paths.add(r.propPath));
|
|
9608
10249
|
});
|
|
9609
10250
|
const pathList = Array.from(paths).slice(0, 3).join(", ");
|
|
9610
|
-
const target = labelWithId(group.steps[group.steps.length - 1].step.
|
|
10251
|
+
const target = labelWithId(group.steps[group.steps.length - 1].step.diff?.[0]?.newSchema?.name || group.steps[0].step.diff?.[0]?.oldSchema?.name, group.id);
|
|
9611
10252
|
return pathList ? `修改 ${target} · ${pathList}${paths.size > 3 ? "…" : ""}` : `修改 ${target}`;
|
|
9612
10253
|
};
|
|
9613
10254
|
/**
|
|
@@ -9618,136 +10259,176 @@
|
|
|
9618
10259
|
*/
|
|
9619
10260
|
var isPageStepRevertable = (step) => {
|
|
9620
10261
|
if (step.opType !== "update") return true;
|
|
9621
|
-
const items = step.
|
|
10262
|
+
const items = step.diff ?? [];
|
|
9622
10263
|
if (!items.length) return false;
|
|
9623
10264
|
return items.every((item) => Boolean(item.changeRecords?.length));
|
|
9624
10265
|
};
|
|
9625
10266
|
/**
|
|
9626
10267
|
* 数据源 step 是否支持「回滚」:
|
|
9627
|
-
* -
|
|
10268
|
+
* - 新增(无 oldSchema)/ 删除(无 newSchema):不依赖 changeRecords,始终可回滚;
|
|
9628
10269
|
* - 更新(前后 schema 都存在):必须有 changeRecords 才支持局部反向 patch,否则不支持回滚。
|
|
9629
10270
|
*/
|
|
9630
10271
|
var isDataSourceStepRevertable = (step) => {
|
|
9631
|
-
|
|
9632
|
-
|
|
10272
|
+
const item = step.diff?.[0];
|
|
10273
|
+
if (!item?.oldSchema || !item?.newSchema) return true;
|
|
10274
|
+
return Boolean(item.changeRecords?.length);
|
|
9633
10275
|
};
|
|
9634
10276
|
/**
|
|
9635
10277
|
* 代码块 step 是否支持「回滚」:
|
|
9636
|
-
* -
|
|
10278
|
+
* - 新增(无 oldSchema)/ 删除(无 newSchema):不依赖 changeRecords,始终可回滚;
|
|
9637
10279
|
* - 更新(前后 content 都存在):必须有 changeRecords 才支持局部反向 patch,否则不支持回滚。
|
|
9638
10280
|
*/
|
|
9639
10281
|
var isCodeBlockStepRevertable = (step) => {
|
|
9640
|
-
|
|
9641
|
-
|
|
10282
|
+
const item = step.diff?.[0];
|
|
10283
|
+
if (!item?.oldSchema || !item?.newSchema) return true;
|
|
10284
|
+
return Boolean(item.changeRecords?.length);
|
|
9642
10285
|
};
|
|
9643
10286
|
//#endregion
|
|
9644
10287
|
//#region packages/editor/src/layouts/history-list/GroupRow.vue?vue&type=script&setup=true&lang.ts
|
|
9645
10288
|
var _hoisted_1$61 = ["title"];
|
|
9646
|
-
var _hoisted_2$
|
|
9647
|
-
var _hoisted_3$
|
|
9648
|
-
var _hoisted_4$
|
|
9649
|
-
|
|
9650
|
-
|
|
9651
|
-
|
|
10289
|
+
var _hoisted_2$23 = ["title"];
|
|
10290
|
+
var _hoisted_3$11 = { class: "m-editor-history-list-item-desc" };
|
|
10291
|
+
var _hoisted_4$8 = {
|
|
10292
|
+
key: 0,
|
|
10293
|
+
class: "m-editor-history-list-item-saved",
|
|
10294
|
+
title: "该记录为最近一次保存的状态"
|
|
10295
|
+
};
|
|
10296
|
+
var _hoisted_5$3 = {
|
|
10297
|
+
key: 1,
|
|
10298
|
+
class: "m-editor-history-list-item-actions"
|
|
10299
|
+
};
|
|
10300
|
+
var _hoisted_6$3 = ["title"];
|
|
10301
|
+
var _hoisted_7$1 = ["title"];
|
|
10302
|
+
var _hoisted_8 = {
|
|
10303
|
+
key: 4,
|
|
9652
10304
|
class: "m-editor-history-list-item-merge"
|
|
9653
10305
|
};
|
|
9654
|
-
var
|
|
10306
|
+
var _hoisted_9 = {
|
|
9655
10307
|
key: 0,
|
|
9656
10308
|
class: "m-editor-history-list-substeps"
|
|
9657
10309
|
};
|
|
9658
|
-
var
|
|
9659
|
-
var
|
|
9660
|
-
var
|
|
9661
|
-
var
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
10310
|
+
var _hoisted_10 = ["title", "onClick"];
|
|
10311
|
+
var _hoisted_11 = { class: "m-editor-history-list-item-index" };
|
|
10312
|
+
var _hoisted_12 = { class: "m-editor-history-list-substep-desc" };
|
|
10313
|
+
var _hoisted_13 = {
|
|
10314
|
+
key: 0,
|
|
10315
|
+
class: "m-editor-history-list-item-saved",
|
|
10316
|
+
title: "该记录为最近一次保存的状态"
|
|
10317
|
+
};
|
|
10318
|
+
var _hoisted_14 = {
|
|
10319
|
+
key: 1,
|
|
10320
|
+
class: "m-editor-history-list-item-actions"
|
|
10321
|
+
};
|
|
9665
10322
|
var _hoisted_15 = ["onClick"];
|
|
10323
|
+
var _hoisted_16 = ["onClick"];
|
|
10324
|
+
var _hoisted_17 = ["onClick"];
|
|
10325
|
+
var _hoisted_18 = ["title"];
|
|
10326
|
+
var _hoisted_19 = ["title"];
|
|
9666
10327
|
var GroupRow_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
9667
10328
|
name: "MEditorHistoryListGroupRow",
|
|
9668
10329
|
__name: "GroupRow",
|
|
9669
10330
|
props: {
|
|
9670
|
-
|
|
9671
|
-
applied: { type: Boolean },
|
|
9672
|
-
merged: { type: Boolean },
|
|
9673
|
-
opType: {},
|
|
9674
|
-
desc: {},
|
|
9675
|
-
source: {},
|
|
9676
|
-
time: {},
|
|
9677
|
-
timeTitle: {},
|
|
9678
|
-
stepCount: {},
|
|
9679
|
-
subSteps: {},
|
|
10331
|
+
group: {},
|
|
9680
10332
|
expanded: { type: Boolean },
|
|
9681
|
-
isCurrent: {
|
|
9682
|
-
type: Boolean,
|
|
9683
|
-
default: false
|
|
9684
|
-
},
|
|
9685
10333
|
gotoEnabled: {
|
|
9686
10334
|
type: Boolean,
|
|
9687
10335
|
default: true
|
|
10336
|
+
},
|
|
10337
|
+
selectEnabled: {
|
|
10338
|
+
type: Boolean,
|
|
10339
|
+
default: false
|
|
9688
10340
|
}
|
|
9689
10341
|
},
|
|
9690
10342
|
emits: [
|
|
9691
10343
|
"toggle",
|
|
9692
10344
|
"goto",
|
|
9693
10345
|
"diff-step",
|
|
9694
|
-
"revert-step"
|
|
10346
|
+
"revert-step",
|
|
10347
|
+
"select"
|
|
9695
10348
|
],
|
|
9696
10349
|
setup(__props, { emit: __emit }) {
|
|
9697
10350
|
const props = __props;
|
|
9698
10351
|
const emit = __emit;
|
|
10352
|
+
/** 子步数大于 1 即为合并组:决定是否展示合并标记与可展开的子步列表。 */
|
|
10353
|
+
const merged = (0, vue.computed)(() => props.group.subSteps.length > 1);
|
|
10354
|
+
/** 组内 step 总数,仅在合并组时显示为 "合并 N 步"。 */
|
|
10355
|
+
const stepCount = (0, vue.computed)(() => props.group.subSteps.length);
|
|
9699
10356
|
/**
|
|
9700
|
-
*
|
|
9701
|
-
*
|
|
10357
|
+
* 头部可点击的场景:
|
|
10358
|
+
* - 合并组:点击切换展开 / 收起;
|
|
10359
|
+
* - 开启 `selectEnabled`(页面 tab):点击选中对应节点。
|
|
10360
|
+
* 单步组的跳转仍由头部的「回到」按钮触发。
|
|
9702
10361
|
*/
|
|
9703
|
-
const isHeadClickable = (0, vue.computed)(() => props.
|
|
10362
|
+
const isHeadClickable = (0, vue.computed)(() => merged.value || props.selectEnabled);
|
|
9704
10363
|
const headTitle = (0, vue.computed)(() => {
|
|
9705
|
-
if (
|
|
9706
|
-
|
|
10364
|
+
if (merged.value) {
|
|
10365
|
+
const expandHint = props.expanded ? "点击收起子步" : "点击展开子步";
|
|
10366
|
+
return props.selectEnabled ? `${expandHint}(并选中该节点)` : expandHint;
|
|
10367
|
+
}
|
|
10368
|
+
if (props.selectEnabled) return "点击选中该节点";
|
|
10369
|
+
if (props.group.isCurrent) return "当前所在记录";
|
|
9707
10370
|
return "";
|
|
9708
10371
|
});
|
|
9709
10372
|
/**
|
|
9710
|
-
*
|
|
10373
|
+
* 头部点击行为:
|
|
10374
|
+
* - 开启 selectEnabled 时,发出 select(携带组内首步 index,上层据此选中节点);
|
|
10375
|
+
* - 合并组同时切换展开 / 收起。
|
|
9711
10376
|
*/
|
|
9712
10377
|
const onHeadClick = () => {
|
|
9713
|
-
if (props.
|
|
10378
|
+
if (props.selectEnabled && props.group.subSteps.length) emit("select", props.group.subSteps[0].index);
|
|
10379
|
+
if (merged.value) emit("toggle", props.group.key);
|
|
9714
10380
|
};
|
|
9715
10381
|
const onGotoClick = (index) => {
|
|
9716
10382
|
if (!props.gotoEnabled) return;
|
|
9717
10383
|
emit("goto", index);
|
|
9718
10384
|
};
|
|
10385
|
+
/** 点击子步行:开启 selectEnabled 时选中该子步对应的节点。 */
|
|
10386
|
+
const onSubStepClick = (index) => {
|
|
10387
|
+
if (!props.selectEnabled) return;
|
|
10388
|
+
emit("select", index);
|
|
10389
|
+
};
|
|
9719
10390
|
const subStepTitle = (s) => {
|
|
10391
|
+
if (props.selectEnabled) return "点击选中该节点";
|
|
9720
10392
|
if (s.isCurrent) return "当前所在记录";
|
|
9721
10393
|
return "";
|
|
9722
10394
|
};
|
|
10395
|
+
/**
|
|
10396
|
+
* 头部是否展示「已保存」标记:
|
|
10397
|
+
* - 单步组:取该唯一子步的 saved;
|
|
10398
|
+
* - 合并组:组内任一子步为已保存即在头部提示(具体落在哪一步可展开查看)。
|
|
10399
|
+
*/
|
|
10400
|
+
const headSaved = (0, vue.computed)(() => merged.value ? props.group.subSteps.some((s) => s.saved) : Boolean(props.group.subSteps[0]?.saved));
|
|
9723
10401
|
/** 单步组头部是否展示"查看差异"入口:要求该唯一子步本身可对比。 */
|
|
9724
|
-
const headDiffable = (0, vue.computed)(() => !
|
|
10402
|
+
const headDiffable = (0, vue.computed)(() => !merged.value && Boolean(props.group.subSteps[0]?.diffable));
|
|
9725
10403
|
/** 单步组头部是否展示"回滚"入口:要求该唯一子步本身可回滚(已应用)。 */
|
|
9726
|
-
const headRevertable = (0, vue.computed)(() => !
|
|
10404
|
+
const headRevertable = (0, vue.computed)(() => !merged.value && Boolean(props.group.subSteps[0]?.revertable));
|
|
10405
|
+
/** 单步组头部是否展示"回到"入口:可跳转、非当前、且存在唯一子步。 */
|
|
10406
|
+
const canHeadGoto = (0, vue.computed)(() => !merged.value && props.gotoEnabled && !props.group.isCurrent && props.group.subSteps.length > 0);
|
|
9727
10407
|
/**
|
|
9728
10408
|
* 合并组展开后的子步渲染顺序:与外层分组列表保持一致——倒序展示(最新的子步在最上方)。
|
|
9729
10409
|
* 外层 page tab / bucket 都已对 groups 做了 reverse,子步沿用同样的视觉规则更直观。
|
|
9730
10410
|
* 注意:仅用于渲染,原 `subSteps` 保持时间正序,`headIndexLabel` 等基于首尾索引的展示语义不变。
|
|
9731
10411
|
*/
|
|
9732
|
-
const subStepsDisplay = (0, vue.computed)(() => props.subSteps.slice().reverse());
|
|
10412
|
+
const subStepsDisplay = (0, vue.computed)(() => props.group.subSteps.slice().reverse());
|
|
9733
10413
|
/**
|
|
9734
10414
|
* 头部索引展示:
|
|
9735
|
-
* -
|
|
10415
|
+
* - 单步组(非合并):显示该唯一 step 的编号,如 `#5`;
|
|
9736
10416
|
* - 合并组:显示组内 step 的编号范围,如 `#3-#7`(首尾相同则退化为 `#5`)。
|
|
9737
10417
|
*
|
|
9738
10418
|
* 这里展示的是 step.index + 1(与子步列表 `#{{ s.index + 1 }}` 保持一致),从 1 起编号更符合直觉。
|
|
9739
10419
|
*/
|
|
9740
10420
|
const headIndexLabel = (0, vue.computed)(() => {
|
|
9741
|
-
const list = props.subSteps;
|
|
10421
|
+
const list = props.group.subSteps;
|
|
9742
10422
|
if (!list.length) return "";
|
|
9743
10423
|
const first = list[0].index + 1;
|
|
9744
10424
|
const last = list[list.length - 1].index + 1;
|
|
9745
|
-
if (!
|
|
10425
|
+
if (!merged.value || first === last) return `#${first}`;
|
|
9746
10426
|
return `#${first}-#${last}`;
|
|
9747
10427
|
});
|
|
9748
10428
|
const headIndexTitle = (0, vue.computed)(() => {
|
|
9749
|
-
|
|
9750
|
-
|
|
10429
|
+
const list = props.group.subSteps;
|
|
10430
|
+
if (!merged.value) return `历史步骤编号 #${list[0]?.index + 1}`;
|
|
10431
|
+
return `合并了第 ${list[0]?.index + 1} 至第 ${list[list.length - 1]?.index + 1} 共 ${list.length} 条历史步骤`;
|
|
9751
10432
|
});
|
|
9752
10433
|
const onDiffClick = (index) => {
|
|
9753
10434
|
emit("diff-step", index);
|
|
@@ -9757,9 +10438,9 @@
|
|
|
9757
10438
|
};
|
|
9758
10439
|
return (_ctx, _cache) => {
|
|
9759
10440
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("li", { class: (0, vue.normalizeClass)(["m-editor-history-list-item m-editor-history-list-group", {
|
|
9760
|
-
"is-undone": !__props.applied,
|
|
9761
|
-
"is-merged":
|
|
9762
|
-
"is-current": __props.isCurrent
|
|
10441
|
+
"is-undone": !__props.group.applied,
|
|
10442
|
+
"is-merged": merged.value,
|
|
10443
|
+
"is-current": __props.group.isCurrent
|
|
9763
10444
|
}]) }, [(0, vue.createElementVNode)("div", {
|
|
9764
10445
|
class: (0, vue.normalizeClass)(["m-editor-history-list-group-head", { "is-clickable": isHeadClickable.value }]),
|
|
9765
10446
|
title: headTitle.value,
|
|
@@ -9768,82 +10449,90 @@
|
|
|
9768
10449
|
(0, vue.createElementVNode)("span", {
|
|
9769
10450
|
class: "m-editor-history-list-item-index",
|
|
9770
10451
|
title: headIndexTitle.value
|
|
9771
|
-
}, (0, vue.toDisplayString)(headIndexLabel.value), 9, _hoisted_2$
|
|
9772
|
-
(0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["m-editor-history-list-item-op", `op-${__props.opType}`]) }, (0, vue.toDisplayString)((0, vue.unref)(opLabel)(__props.opType)), 3),
|
|
9773
|
-
(0, vue.createElementVNode)("span", _hoisted_3$
|
|
9774
|
-
|
|
9775
|
-
|
|
10452
|
+
}, (0, vue.toDisplayString)(headIndexLabel.value), 9, _hoisted_2$23),
|
|
10453
|
+
(0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["m-editor-history-list-item-op", `op-${__props.group.opType}`]) }, (0, vue.toDisplayString)((0, vue.unref)(opLabel)(__props.group.opType)), 3),
|
|
10454
|
+
(0, vue.createElementVNode)("span", _hoisted_3$11, (0, vue.toDisplayString)(__props.group.desc), 1),
|
|
10455
|
+
headSaved.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_4$8, "已保存")) : (0, vue.createCommentVNode)("v-if", true),
|
|
10456
|
+
!merged.value && (headRevertable.value || headDiffable.value || canHeadGoto.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_5$3, [
|
|
10457
|
+
headRevertable.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10458
|
+
key: 0,
|
|
10459
|
+
class: "m-editor-history-list-item-revert",
|
|
10460
|
+
title: "将该步骤的修改作为一次新操作反向应用(不影响后续历史)",
|
|
10461
|
+
onClick: _cache[0] || (_cache[0] = (0, vue.withModifiers)(($event) => onRevertClick(__props.group.subSteps[0].index), ["stop"]))
|
|
10462
|
+
}, "回滚")) : (0, vue.createCommentVNode)("v-if", true),
|
|
10463
|
+
canHeadGoto.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10464
|
+
key: 1,
|
|
10465
|
+
class: "m-editor-history-list-item-goto",
|
|
10466
|
+
title: "回到该记录",
|
|
10467
|
+
onClick: _cache[1] || (_cache[1] = (0, vue.withModifiers)(($event) => onGotoClick(__props.group.subSteps[0].index), ["stop"]))
|
|
10468
|
+
}, "回到")) : (0, vue.createCommentVNode)("v-if", true),
|
|
10469
|
+
headDiffable.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10470
|
+
key: 2,
|
|
10471
|
+
class: "m-editor-history-list-item-diff",
|
|
10472
|
+
title: "查看修改差异",
|
|
10473
|
+
onClick: _cache[2] || (_cache[2] = (0, vue.withModifiers)(($event) => onDiffClick(__props.group.subSteps[0].index), ["stop"]))
|
|
10474
|
+
}, "查看差异")) : (0, vue.createCommentVNode)("v-if", true)
|
|
10475
|
+
])) : (0, vue.createCommentVNode)("v-if", true),
|
|
10476
|
+
!merged.value && (0, vue.unref)(sourceLabel)(__props.group.source) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10477
|
+
key: 2,
|
|
9776
10478
|
class: "m-editor-history-list-item-source",
|
|
9777
|
-
title: `操作途径:${(0, vue.unref)(sourceLabel)(__props.source)}`
|
|
9778
|
-
}, (0, vue.toDisplayString)((0, vue.unref)(sourceLabel)(__props.source)), 9,
|
|
9779
|
-
!
|
|
9780
|
-
key: 1,
|
|
9781
|
-
class: "m-editor-history-list-item-time",
|
|
9782
|
-
title: __props.timeTitle || __props.time
|
|
9783
|
-
}, (0, vue.toDisplayString)(__props.time), 9, _hoisted_5$3)) : (0, vue.createCommentVNode)("v-if", true),
|
|
9784
|
-
__props.merged ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_6$3, "合并 " + (0, vue.toDisplayString)(__props.stepCount) + " 步", 1)) : (0, vue.createCommentVNode)("v-if", true),
|
|
9785
|
-
!__props.merged && headRevertable.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10479
|
+
title: `操作途径:${(0, vue.unref)(sourceLabel)(__props.group.source)}`
|
|
10480
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(sourceLabel)(__props.group.source)), 9, _hoisted_6$3)) : (0, vue.createCommentVNode)("v-if", true),
|
|
10481
|
+
!merged.value && __props.group.time ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
9786
10482
|
key: 3,
|
|
9787
|
-
class: "m-editor-history-list-item-
|
|
9788
|
-
title:
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
key: 4,
|
|
9793
|
-
class: "m-editor-history-list-item-goto",
|
|
9794
|
-
title: "回到该记录",
|
|
9795
|
-
onClick: _cache[1] || (_cache[1] = (0, vue.withModifiers)(($event) => onGotoClick(__props.subSteps[0].index), ["stop"]))
|
|
9796
|
-
}, "回到")) : (0, vue.createCommentVNode)("v-if", true),
|
|
9797
|
-
!__props.merged && headDiffable.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10483
|
+
class: "m-editor-history-list-item-time",
|
|
10484
|
+
title: __props.group.timeTitle || __props.group.time
|
|
10485
|
+
}, (0, vue.toDisplayString)(__props.group.time), 9, _hoisted_7$1)) : (0, vue.createCommentVNode)("v-if", true),
|
|
10486
|
+
merged.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8, "合并 " + (0, vue.toDisplayString)(stepCount.value) + " 步", 1)) : (0, vue.createCommentVNode)("v-if", true),
|
|
10487
|
+
merged.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
9798
10488
|
key: 5,
|
|
9799
|
-
class: "m-editor-history-list-item-diff",
|
|
9800
|
-
title: "查看修改差异",
|
|
9801
|
-
onClick: _cache[2] || (_cache[2] = (0, vue.withModifiers)(($event) => onDiffClick(__props.subSteps[0].index), ["stop"]))
|
|
9802
|
-
}, "查看差异")) : (0, vue.createCommentVNode)("v-if", true),
|
|
9803
|
-
__props.merged ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
9804
|
-
key: 6,
|
|
9805
10489
|
class: (0, vue.normalizeClass)(["m-editor-history-list-group-toggle", { "is-expanded": __props.expanded }])
|
|
9806
10490
|
}, "▾", 2)) : (0, vue.createCommentVNode)("v-if", true)
|
|
9807
|
-
], 10, _hoisted_1$61),
|
|
10491
|
+
], 10, _hoisted_1$61), merged.value && __props.expanded ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("ul", _hoisted_9, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(subStepsDisplay.value, (s) => {
|
|
9808
10492
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("li", {
|
|
9809
10493
|
key: s.index,
|
|
9810
10494
|
class: (0, vue.normalizeClass)({
|
|
9811
10495
|
"is-undone": !s.applied,
|
|
9812
|
-
"is-current": s.isCurrent
|
|
10496
|
+
"is-current": s.isCurrent,
|
|
10497
|
+
"is-clickable": __props.selectEnabled
|
|
9813
10498
|
}),
|
|
9814
|
-
title: subStepTitle(s)
|
|
10499
|
+
title: subStepTitle(s),
|
|
10500
|
+
onClick: ($event) => onSubStepClick(s.index)
|
|
9815
10501
|
}, [
|
|
9816
|
-
(0, vue.createElementVNode)("span",
|
|
9817
|
-
(0, vue.createElementVNode)("span",
|
|
10502
|
+
(0, vue.createElementVNode)("span", _hoisted_11, "#" + (0, vue.toDisplayString)(s.index + 1), 1),
|
|
10503
|
+
(0, vue.createElementVNode)("span", _hoisted_12, (0, vue.toDisplayString)(s.desc), 1),
|
|
10504
|
+
s.saved ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_13, "已保存")) : (0, vue.createCommentVNode)("v-if", true),
|
|
10505
|
+
s.revertable || s.diffable || __props.gotoEnabled && !s.isCurrent ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_14, [
|
|
10506
|
+
s.revertable ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10507
|
+
key: 0,
|
|
10508
|
+
class: "m-editor-history-list-item-revert",
|
|
10509
|
+
title: "将该步骤的修改作为一次新操作反向应用(不影响后续历史)",
|
|
10510
|
+
onClick: (0, vue.withModifiers)(($event) => onRevertClick(s.index), ["stop"])
|
|
10511
|
+
}, "回滚", 8, _hoisted_15)) : (0, vue.createCommentVNode)("v-if", true),
|
|
10512
|
+
__props.gotoEnabled && !s.isCurrent ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10513
|
+
key: 1,
|
|
10514
|
+
class: "m-editor-history-list-item-goto",
|
|
10515
|
+
title: "回到该记录",
|
|
10516
|
+
onClick: (0, vue.withModifiers)(($event) => onGotoClick(s.index), ["stop"])
|
|
10517
|
+
}, "回到", 8, _hoisted_16)) : (0, vue.createCommentVNode)("v-if", true),
|
|
10518
|
+
s.diffable ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10519
|
+
key: 2,
|
|
10520
|
+
class: "m-editor-history-list-item-diff",
|
|
10521
|
+
title: "查看修改差异",
|
|
10522
|
+
onClick: (0, vue.withModifiers)(($event) => onDiffClick(s.index), ["stop"])
|
|
10523
|
+
}, "查看差异", 8, _hoisted_17)) : (0, vue.createCommentVNode)("v-if", true)
|
|
10524
|
+
])) : (0, vue.createCommentVNode)("v-if", true),
|
|
9818
10525
|
(0, vue.unref)(sourceLabel)(s.source) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
9819
|
-
key:
|
|
10526
|
+
key: 2,
|
|
9820
10527
|
class: "m-editor-history-list-item-source",
|
|
9821
10528
|
title: `操作途径:${(0, vue.unref)(sourceLabel)(s.source)}`
|
|
9822
|
-
}, (0, vue.toDisplayString)((0, vue.unref)(sourceLabel)(s.source)), 9,
|
|
10529
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(sourceLabel)(s.source)), 9, _hoisted_18)) : (0, vue.createCommentVNode)("v-if", true),
|
|
9823
10530
|
s.time ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
9824
|
-
key:
|
|
10531
|
+
key: 3,
|
|
9825
10532
|
class: "m-editor-history-list-item-time",
|
|
9826
10533
|
title: s.timeTitle || s.time
|
|
9827
|
-
}, (0, vue.toDisplayString)(s.time), 9,
|
|
9828
|
-
|
|
9829
|
-
key: 2,
|
|
9830
|
-
class: "m-editor-history-list-item-revert",
|
|
9831
|
-
title: "将该步骤的修改作为一次新操作反向应用(不影响后续历史)",
|
|
9832
|
-
onClick: (0, vue.withModifiers)(($event) => onRevertClick(s.index), ["stop"])
|
|
9833
|
-
}, "回滚", 8, _hoisted_13)) : (0, vue.createCommentVNode)("v-if", true),
|
|
9834
|
-
__props.gotoEnabled && !s.isCurrent ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
9835
|
-
key: 3,
|
|
9836
|
-
class: "m-editor-history-list-item-goto",
|
|
9837
|
-
title: "回到该记录",
|
|
9838
|
-
onClick: (0, vue.withModifiers)(($event) => onGotoClick(s.index), ["stop"])
|
|
9839
|
-
}, "回到", 8, _hoisted_14)) : (0, vue.createCommentVNode)("v-if", true),
|
|
9840
|
-
s.diffable ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
9841
|
-
key: 4,
|
|
9842
|
-
class: "m-editor-history-list-item-diff",
|
|
9843
|
-
title: "查看修改差异",
|
|
9844
|
-
onClick: (0, vue.withModifiers)(($event) => onDiffClick(s.index), ["stop"])
|
|
9845
|
-
}, "查看差异", 8, _hoisted_15)) : (0, vue.createCommentVNode)("v-if", true)
|
|
9846
|
-
], 10, _hoisted_8);
|
|
10534
|
+
}, (0, vue.toDisplayString)(s.time), 9, _hoisted_19)) : (0, vue.createCommentVNode)("v-if", true)
|
|
10535
|
+
], 10, _hoisted_10);
|
|
9847
10536
|
}), 128))])) : (0, vue.createCommentVNode)("v-if", true)], 2);
|
|
9848
10537
|
};
|
|
9849
10538
|
}
|
|
@@ -9854,6 +10543,12 @@
|
|
|
9854
10543
|
//#endregion
|
|
9855
10544
|
//#region packages/editor/src/layouts/history-list/InitialRow.vue?vue&type=script&setup=true&lang.ts
|
|
9856
10545
|
var _hoisted_1$60 = ["title"];
|
|
10546
|
+
var _hoisted_2$22 = { class: "m-editor-history-list-item-desc" };
|
|
10547
|
+
var _hoisted_3$10 = {
|
|
10548
|
+
key: 0,
|
|
10549
|
+
class: "m-editor-history-list-item-actions"
|
|
10550
|
+
};
|
|
10551
|
+
var _hoisted_4$7 = ["title"];
|
|
9857
10552
|
var InitialRow_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
9858
10553
|
name: "MEditorHistoryListInitialRow",
|
|
9859
10554
|
__name: "InitialRow",
|
|
@@ -9862,7 +10557,8 @@
|
|
|
9862
10557
|
gotoEnabled: {
|
|
9863
10558
|
type: Boolean,
|
|
9864
10559
|
default: true
|
|
9865
|
-
}
|
|
10560
|
+
},
|
|
10561
|
+
marker: { default: void 0 }
|
|
9866
10562
|
},
|
|
9867
10563
|
emits: ["goto-initial"],
|
|
9868
10564
|
setup(__props, { emit: __emit }) {
|
|
@@ -9870,10 +10566,19 @@
|
|
|
9870
10566
|
* 「初始状态」记录行:渲染于历史列表底部,作为整个栈的"零点"。
|
|
9871
10567
|
* - 点击该行会把对应栈撤销到 cursor === 0(即没有任何已应用步骤),等同于回到所有修改之前。
|
|
9872
10568
|
* - 当对应栈本身已处于 cursor === 0 时(isCurrent=true),用户已在初始状态,点击不再触发动作。
|
|
10569
|
+
* - 当上层传入 `marker`(设置 root 时为该页生成的「未修改的初始状态」标记)时,
|
|
10570
|
+
* 用标记的文案与时间渲染本行;标记不进入撤销/重做栈,仅作为该页基线展示。
|
|
9873
10571
|
*
|
|
9874
10572
|
* 该行不是真实 step,仅作为 UI 入口;上层负责把"点击"翻译为 `service.goto*(0)`。
|
|
9875
10573
|
*/
|
|
9876
10574
|
const props = __props;
|
|
10575
|
+
const desc = (0, vue.computed)(() => props.marker?.historyDescription || "未修改的初始状态");
|
|
10576
|
+
const time = (0, vue.computed)(() => formatHistoryTime(props.marker?.timestamp));
|
|
10577
|
+
const timeTitle = (0, vue.computed)(() => formatHistoryFullTime(props.marker?.timestamp));
|
|
10578
|
+
const rowTitle = (0, vue.computed)(() => {
|
|
10579
|
+
const base = props.marker?.historyDescription || "未修改的初始状态";
|
|
10580
|
+
return props.isCurrent ? `当前已回到${base}` : `点击回到${base}`;
|
|
10581
|
+
});
|
|
9877
10582
|
const emit = __emit;
|
|
9878
10583
|
const onClick = () => {
|
|
9879
10584
|
if (props.isCurrent) return;
|
|
@@ -9885,20 +10590,24 @@
|
|
|
9885
10590
|
"is-current": __props.isCurrent,
|
|
9886
10591
|
"is-clickable": !__props.isCurrent
|
|
9887
10592
|
}]),
|
|
9888
|
-
title:
|
|
10593
|
+
title: rowTitle.value
|
|
9889
10594
|
}, [
|
|
9890
10595
|
_cache[0] || (_cache[0] = (0, vue.createElementVNode)("span", {
|
|
9891
10596
|
class: "m-editor-history-list-item-index",
|
|
9892
10597
|
title: "历史步骤编号 #0(未修改的初始状态)"
|
|
9893
10598
|
}, "#0", -1)),
|
|
9894
10599
|
_cache[1] || (_cache[1] = (0, vue.createElementVNode)("span", { class: "m-editor-history-list-item-op op-initial" }, "初始", -1)),
|
|
9895
|
-
|
|
9896
|
-
__props.gotoEnabled && !__props.isCurrent ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
9897
|
-
key: 0,
|
|
10600
|
+
(0, vue.createElementVNode)("span", _hoisted_2$22, (0, vue.toDisplayString)(desc.value), 1),
|
|
10601
|
+
__props.gotoEnabled && !__props.isCurrent ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_3$10, [(0, vue.createElementVNode)("span", {
|
|
9898
10602
|
class: "m-editor-history-list-item-goto",
|
|
9899
10603
|
title: "回到该记录",
|
|
9900
10604
|
onClick: (0, vue.withModifiers)(onClick, ["stop"])
|
|
9901
|
-
}, "回到")) : (0, vue.createCommentVNode)("v-if", true)
|
|
10605
|
+
}, "回到")])) : (0, vue.createCommentVNode)("v-if", true),
|
|
10606
|
+
time.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
10607
|
+
key: 1,
|
|
10608
|
+
class: "m-editor-history-list-item-time",
|
|
10609
|
+
title: timeTitle.value
|
|
10610
|
+
}, (0, vue.toDisplayString)(time.value), 9, _hoisted_4$7)) : (0, vue.createCommentVNode)("v-if", true)
|
|
9902
10611
|
], 10, _hoisted_1$60);
|
|
9903
10612
|
};
|
|
9904
10613
|
}
|
|
@@ -9909,30 +10618,17 @@
|
|
|
9909
10618
|
//#endregion
|
|
9910
10619
|
//#region packages/editor/src/layouts/history-list/Bucket.vue?vue&type=script&setup=true&lang.ts
|
|
9911
10620
|
var _hoisted_1$59 = { class: "m-editor-history-list-bucket" };
|
|
9912
|
-
var _hoisted_2$
|
|
9913
|
-
var _hoisted_3$
|
|
10621
|
+
var _hoisted_2$21 = { class: "m-editor-history-list-bucket-title" };
|
|
10622
|
+
var _hoisted_3$9 = { class: "m-editor-history-list-bucket-count" };
|
|
9914
10623
|
var _hoisted_4$6 = { class: "m-editor-history-list-ul" };
|
|
9915
10624
|
var Bucket_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
9916
10625
|
name: "MEditorHistoryListBucket",
|
|
9917
10626
|
__name: "Bucket",
|
|
9918
10627
|
props: {
|
|
9919
|
-
|
|
10628
|
+
config: {},
|
|
9920
10629
|
bucketId: {},
|
|
9921
|
-
prefix: {},
|
|
9922
|
-
showInitial: {
|
|
9923
|
-
type: Boolean,
|
|
9924
|
-
default: true
|
|
9925
|
-
},
|
|
9926
10630
|
groups: {},
|
|
9927
|
-
|
|
9928
|
-
describeStep: {},
|
|
9929
|
-
isStepDiffable: {},
|
|
9930
|
-
isStepRevertable: {},
|
|
9931
|
-
expanded: {},
|
|
9932
|
-
gotoEnabled: {
|
|
9933
|
-
type: Boolean,
|
|
9934
|
-
default: true
|
|
9935
|
-
}
|
|
10631
|
+
expanded: {}
|
|
9936
10632
|
},
|
|
9937
10633
|
emits: [
|
|
9938
10634
|
"toggle",
|
|
@@ -9943,65 +10639,42 @@
|
|
|
9943
10639
|
],
|
|
9944
10640
|
setup(__props) {
|
|
9945
10641
|
const props = __props;
|
|
10642
|
+
/**
|
|
10643
|
+
* 子项 / 折叠状态 key:`${prefix}-${bucketId}-${组内首步 index}`。
|
|
10644
|
+
* 以稳定的 step 索引(而非展示位置)标识分组,历史数据更新后已展开的分组状态仍能正确保持。
|
|
10645
|
+
*/
|
|
10646
|
+
const rowKey = (group) => `${props.config.prefix}-${props.bucketId}-${group.steps[0]?.index}`;
|
|
10647
|
+
/** 把原始分组派生为 GroupRow 直接消费的视图模型。 */
|
|
10648
|
+
const toRow = (group) => toRowGroup(group, rowKey(group), props.config);
|
|
9946
10649
|
/** 该 bucket 是否处于初始状态(栈 cursor=0),等价于全部 group 都未 applied。 */
|
|
9947
10650
|
const isInitial = (0, vue.computed)(() => props.groups.length > 0 && props.groups.every((g) => !g.applied));
|
|
9948
10651
|
return (_ctx, _cache) => {
|
|
9949
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$59, [(0, vue.createElementVNode)("div", _hoisted_2$
|
|
9950
|
-
(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.title), 1),
|
|
10652
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$59, [(0, vue.createElementVNode)("div", _hoisted_2$21, [
|
|
10653
|
+
(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.config.title), 1),
|
|
9951
10654
|
(0, vue.createElementVNode)("code", null, (0, vue.toDisplayString)(String(__props.bucketId)), 1),
|
|
9952
|
-
(0, vue.createElementVNode)("span", _hoisted_3$
|
|
10655
|
+
(0, vue.createElementVNode)("span", _hoisted_3$9, (0, vue.toDisplayString)(__props.groups.length) + " 组", 1)
|
|
9953
10656
|
]), (0, vue.createElementVNode)("ul", _hoisted_4$6, [
|
|
9954
10657
|
((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.groups, (group) => {
|
|
9955
10658
|
return (0, vue.openBlock)(), (0, vue.createBlock)(GroupRow_default, {
|
|
9956
|
-
key:
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
"op-type": group.opType,
|
|
9961
|
-
desc: __props.describeGroup(group),
|
|
9962
|
-
source: (0, vue.unref)(groupSource)(group),
|
|
9963
|
-
time: (0, vue.unref)(formatHistoryTime)((0, vue.unref)(groupTimestamp)(group)),
|
|
9964
|
-
"time-title": (0, vue.unref)(formatHistoryFullTime)((0, vue.unref)(groupTimestamp)(group)),
|
|
9965
|
-
"step-count": group.steps.length,
|
|
9966
|
-
"sub-steps": group.steps.map((s) => ({
|
|
9967
|
-
index: s.index,
|
|
9968
|
-
applied: s.applied,
|
|
9969
|
-
isCurrent: s.isCurrent,
|
|
9970
|
-
desc: __props.describeStep(s.step),
|
|
9971
|
-
diffable: __props.isStepDiffable ? __props.isStepDiffable(s.step) : false,
|
|
9972
|
-
revertable: s.applied && (__props.isStepRevertable ? __props.isStepRevertable(s.step) : true),
|
|
9973
|
-
source: s.step.source,
|
|
9974
|
-
time: (0, vue.unref)(formatHistoryTime)(s.step.timestamp),
|
|
9975
|
-
timeTitle: (0, vue.unref)(formatHistoryFullTime)(s.step.timestamp)
|
|
9976
|
-
})),
|
|
9977
|
-
"is-current": group.isCurrent,
|
|
9978
|
-
expanded: !!__props.expanded[`${__props.prefix}-${__props.bucketId}-${group.steps[0]?.index}`],
|
|
9979
|
-
"goto-enabled": __props.gotoEnabled,
|
|
10659
|
+
key: rowKey(group),
|
|
10660
|
+
group: toRow(group),
|
|
10661
|
+
expanded: (0, vue.unref)(isHistoryGroupExpanded)(__props.expanded, rowKey(group)),
|
|
10662
|
+
"goto-enabled": __props.config.gotoEnabled,
|
|
9980
10663
|
onToggle: _cache[0] || (_cache[0] = (key) => _ctx.$emit("toggle", key)),
|
|
9981
10664
|
onGoto: _cache[1] || (_cache[1] = (index) => _ctx.$emit("goto", __props.bucketId, index)),
|
|
9982
10665
|
onDiffStep: _cache[2] || (_cache[2] = (index) => _ctx.$emit("diff-step", __props.bucketId, index)),
|
|
9983
10666
|
onRevertStep: _cache[3] || (_cache[3] = (index) => _ctx.$emit("revert-step", __props.bucketId, index))
|
|
9984
10667
|
}, null, 8, [
|
|
9985
|
-
"group
|
|
9986
|
-
"applied",
|
|
9987
|
-
"merged",
|
|
9988
|
-
"op-type",
|
|
9989
|
-
"desc",
|
|
9990
|
-
"source",
|
|
9991
|
-
"time",
|
|
9992
|
-
"time-title",
|
|
9993
|
-
"step-count",
|
|
9994
|
-
"sub-steps",
|
|
9995
|
-
"is-current",
|
|
10668
|
+
"group",
|
|
9996
10669
|
"expanded",
|
|
9997
10670
|
"goto-enabled"
|
|
9998
10671
|
]);
|
|
9999
10672
|
}), 128)),
|
|
10000
|
-
(0, vue.createCommentVNode)("\n 初始状态项:永远位于该 bucket 列表底部(同样按倒序展示,最底部 = 最早状态)。\n 当 bucket 内所有 group 都未 applied 时即为当前位置。\n showInitial=false 时不展示(用于没有\"撤销到初始状态\"语义的自定义历史,如业务模块历史)。\n "),
|
|
10001
|
-
__props.showInitial !== false ? ((0, vue.openBlock)(), (0, vue.createBlock)(InitialRow_default, {
|
|
10673
|
+
(0, vue.createCommentVNode)("\n 初始状态项:永远位于该 bucket 列表底部(同样按倒序展示,最底部 = 最早状态)。\n 当 bucket 内所有 group 都未 applied 时即为当前位置。\n config.showInitial=false 时不展示(用于没有\"撤销到初始状态\"语义的自定义历史,如业务模块历史)。\n "),
|
|
10674
|
+
__props.config.showInitial !== false ? ((0, vue.openBlock)(), (0, vue.createBlock)(InitialRow_default, {
|
|
10002
10675
|
key: 0,
|
|
10003
10676
|
"is-current": isInitial.value,
|
|
10004
|
-
"goto-enabled": __props.gotoEnabled,
|
|
10677
|
+
"goto-enabled": __props.config.gotoEnabled,
|
|
10005
10678
|
onGotoInitial: _cache[4] || (_cache[4] = ($event) => _ctx.$emit("goto-initial", __props.bucketId))
|
|
10006
10679
|
}, null, 8, ["is-current", "goto-enabled"])) : (0, vue.createCommentVNode)("v-if", true)
|
|
10007
10680
|
])]);
|
|
@@ -10017,69 +10690,52 @@
|
|
|
10017
10690
|
key: 0,
|
|
10018
10691
|
class: "m-editor-history-list-empty"
|
|
10019
10692
|
};
|
|
10693
|
+
var _hoisted_2$20 = { class: "m-editor-history-list-toolbar" };
|
|
10694
|
+
var _hoisted_3$8 = ["title"];
|
|
10020
10695
|
var BucketTab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
10021
10696
|
name: "MEditorHistoryListBucketTab",
|
|
10022
10697
|
__name: "BucketTab",
|
|
10023
10698
|
props: {
|
|
10024
|
-
|
|
10025
|
-
prefix: {},
|
|
10699
|
+
config: {},
|
|
10026
10700
|
buckets: {},
|
|
10027
|
-
|
|
10028
|
-
describeStep: {},
|
|
10029
|
-
isStepDiffable: {},
|
|
10030
|
-
isStepRevertable: {},
|
|
10031
|
-
expanded: {},
|
|
10032
|
-
gotoEnabled: {
|
|
10033
|
-
type: Boolean,
|
|
10034
|
-
default: true
|
|
10035
|
-
}
|
|
10701
|
+
expanded: {}
|
|
10036
10702
|
},
|
|
10037
10703
|
emits: [
|
|
10038
10704
|
"toggle",
|
|
10039
10705
|
"goto",
|
|
10040
10706
|
"goto-initial",
|
|
10041
10707
|
"diff-step",
|
|
10042
|
-
"revert-step"
|
|
10708
|
+
"revert-step",
|
|
10709
|
+
"clear"
|
|
10043
10710
|
],
|
|
10044
10711
|
setup(__props) {
|
|
10045
10712
|
return (_ctx, _cache) => {
|
|
10046
|
-
return !__props.buckets.length ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$58, "暂无操作记录")) : ((0, vue.openBlock)(), (0, vue.
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10713
|
+
return !__props.buckets.length ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$58, "暂无操作记录")) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [(0, vue.createElementVNode)("div", _hoisted_2$20, [(0, vue.createElementVNode)("span", {
|
|
10714
|
+
class: "m-editor-history-list-clear",
|
|
10715
|
+
title: `清空${__props.config.title}的历史记录`,
|
|
10716
|
+
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("clear"))
|
|
10717
|
+
}, "清空", 8, _hoisted_3$8)]), (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicScrollbar), { "max-height": "360px" }, {
|
|
10050
10718
|
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.buckets, (bucket) => {
|
|
10051
10719
|
return (0, vue.openBlock)(), (0, vue.createBlock)(Bucket_default, {
|
|
10052
|
-
key: `${__props.prefix}-${bucket.id}`,
|
|
10053
|
-
|
|
10720
|
+
key: `${__props.config.prefix}-${bucket.id}`,
|
|
10721
|
+
config: __props.config,
|
|
10054
10722
|
"bucket-id": bucket.id,
|
|
10055
|
-
prefix: __props.prefix,
|
|
10056
10723
|
groups: bucket.groups,
|
|
10057
|
-
"describe-group": __props.describeGroup,
|
|
10058
|
-
"describe-step": __props.describeStep,
|
|
10059
|
-
"is-step-diffable": __props.isStepDiffable,
|
|
10060
|
-
"is-step-revertable": __props.isStepRevertable,
|
|
10061
10724
|
expanded: __props.expanded,
|
|
10062
|
-
"
|
|
10063
|
-
|
|
10064
|
-
|
|
10065
|
-
|
|
10066
|
-
|
|
10067
|
-
onRevertStep: _cache[4] || (_cache[4] = (id, index) => _ctx.$emit("revert-step", id, index))
|
|
10725
|
+
onToggle: _cache[1] || (_cache[1] = (key) => _ctx.$emit("toggle", key)),
|
|
10726
|
+
onGoto: _cache[2] || (_cache[2] = (id, index) => _ctx.$emit("goto", id, index)),
|
|
10727
|
+
onGotoInitial: _cache[3] || (_cache[3] = (id) => _ctx.$emit("goto-initial", id)),
|
|
10728
|
+
onDiffStep: _cache[4] || (_cache[4] = (id, index) => _ctx.$emit("diff-step", id, index)),
|
|
10729
|
+
onRevertStep: _cache[5] || (_cache[5] = (id, index) => _ctx.$emit("revert-step", id, index))
|
|
10068
10730
|
}, null, 8, [
|
|
10069
|
-
"
|
|
10731
|
+
"config",
|
|
10070
10732
|
"bucket-id",
|
|
10071
|
-
"prefix",
|
|
10072
10733
|
"groups",
|
|
10073
|
-
"
|
|
10074
|
-
"describe-step",
|
|
10075
|
-
"is-step-diffable",
|
|
10076
|
-
"is-step-revertable",
|
|
10077
|
-
"expanded",
|
|
10078
|
-
"goto-enabled"
|
|
10734
|
+
"expanded"
|
|
10079
10735
|
]);
|
|
10080
10736
|
}), 128))]),
|
|
10081
10737
|
_: 1
|
|
10082
|
-
}));
|
|
10738
|
+
})], 64));
|
|
10083
10739
|
};
|
|
10084
10740
|
}
|
|
10085
10741
|
});
|
|
@@ -10184,7 +10840,7 @@
|
|
|
10184
10840
|
switch (props.category) {
|
|
10185
10841
|
case "node":
|
|
10186
10842
|
if (!props.type) return [];
|
|
10187
|
-
return removeStyleDisplayConfig(await propsService.getPropsConfig(props.type));
|
|
10843
|
+
return removeStyleDisplayConfig(await propsService.getPropsConfig(props.type, { node: props.value }));
|
|
10188
10844
|
case "data-source": return dataSourceService.getFormConfig(props.type || "base");
|
|
10189
10845
|
case "code-block": return getCodeBlockFormConfig({
|
|
10190
10846
|
paramColConfig: codeBlockService.getParamsColConfig(),
|
|
@@ -10277,7 +10933,7 @@
|
|
|
10277
10933
|
key: 0,
|
|
10278
10934
|
class: "m-editor-history-diff-dialog-notice"
|
|
10279
10935
|
};
|
|
10280
|
-
var _hoisted_3$
|
|
10936
|
+
var _hoisted_3$7 = { class: "m-editor-history-diff-dialog-header" };
|
|
10281
10937
|
var _hoisted_4$5 = { class: "m-editor-history-diff-dialog-target" };
|
|
10282
10938
|
var _hoisted_5$2 = { class: "m-editor-history-diff-dialog-controls" };
|
|
10283
10939
|
var _hoisted_6$2 = { class: "m-editor-history-diff-dialog-legend" };
|
|
@@ -10292,6 +10948,7 @@
|
|
|
10292
10948
|
extendState: {},
|
|
10293
10949
|
loadConfig: {},
|
|
10294
10950
|
width: { default: "900px" },
|
|
10951
|
+
isConfirm: { type: Boolean },
|
|
10295
10952
|
onConfirm: {},
|
|
10296
10953
|
selfDiffFieldTypes: {}
|
|
10297
10954
|
},
|
|
@@ -10346,9 +11003,12 @@
|
|
|
10346
11003
|
if (mode.value !== "current" || !payload.value) return false;
|
|
10347
11004
|
return isEqual(payload.value.value, payload.value.currentValue);
|
|
10348
11005
|
});
|
|
11006
|
+
/** confirm() 的 resolve,仅在「等待用户确认回滚」期间存在 */
|
|
11007
|
+
let confirmResolve = null;
|
|
10349
11008
|
const onConfirmClick = () => {
|
|
10350
|
-
|
|
10351
|
-
|
|
11009
|
+
props.onConfirm?.();
|
|
11010
|
+
confirmResolve?.(true);
|
|
11011
|
+
confirmResolve = null;
|
|
10352
11012
|
visible.value = false;
|
|
10353
11013
|
};
|
|
10354
11014
|
const targetText = (0, vue.computed)(() => {
|
|
@@ -10370,21 +11030,41 @@
|
|
|
10370
11030
|
viewMode.value = "form";
|
|
10371
11031
|
visible.value = true;
|
|
10372
11032
|
};
|
|
11033
|
+
/**
|
|
11034
|
+
* 以 Promise 形式打开确认回滚弹窗:
|
|
11035
|
+
* - 用户点击「确定回滚」时 resolve(true);
|
|
11036
|
+
* - 取消 / 关闭 / 按 Esc 等其他方式关闭弹窗时 resolve(false)。
|
|
11037
|
+
*
|
|
11038
|
+
* 同一时刻只允许一个待确认流程,重复调用会先 resolve(false) 掉上一个。
|
|
11039
|
+
*/
|
|
11040
|
+
const confirm = (p) => {
|
|
11041
|
+
confirmResolve?.(false);
|
|
11042
|
+
confirmResolve = null;
|
|
11043
|
+
return new Promise((resolve) => {
|
|
11044
|
+
confirmResolve = resolve;
|
|
11045
|
+
open(p);
|
|
11046
|
+
});
|
|
11047
|
+
};
|
|
10373
11048
|
const close = () => {
|
|
10374
11049
|
visible.value = false;
|
|
10375
11050
|
};
|
|
10376
11051
|
(0, vue.watch)(visible, (v) => {
|
|
10377
|
-
if (!v)
|
|
11052
|
+
if (!v) {
|
|
11053
|
+
payload.value = null;
|
|
11054
|
+
confirmResolve?.(false);
|
|
11055
|
+
confirmResolve = null;
|
|
11056
|
+
}
|
|
10378
11057
|
});
|
|
10379
11058
|
const onClose = () => {
|
|
10380
11059
|
emit("close");
|
|
10381
11060
|
};
|
|
10382
11061
|
__expose({
|
|
10383
11062
|
open,
|
|
11063
|
+
confirm,
|
|
10384
11064
|
close
|
|
10385
11065
|
});
|
|
10386
11066
|
return (_ctx, _cache) => {
|
|
10387
|
-
return (0, vue.openBlock)(), (0, vue.createBlock)(
|
|
11067
|
+
return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicDialog), {
|
|
10388
11068
|
modelValue: visible.value,
|
|
10389
11069
|
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => visible.value = $event),
|
|
10390
11070
|
class: "m-editor-history-diff-dialog",
|
|
@@ -10395,7 +11075,7 @@
|
|
|
10395
11075
|
width: __props.width,
|
|
10396
11076
|
onClose
|
|
10397
11077
|
}, {
|
|
10398
|
-
footer: (0, vue.withCtx)(() => [__props.
|
|
11078
|
+
footer: (0, vue.withCtx)(() => [__props.isConfirm ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
|
|
10399
11079
|
size: "small",
|
|
10400
11080
|
onClick: _cache[2] || (_cache[2] = ($event) => visible.value = false)
|
|
10401
11081
|
}, {
|
|
@@ -10416,9 +11096,9 @@
|
|
|
10416
11096
|
default: (0, vue.withCtx)(() => [..._cache[12] || (_cache[12] = [(0, vue.createTextVNode)("关闭", -1)])]),
|
|
10417
11097
|
_: 1
|
|
10418
11098
|
}))]),
|
|
10419
|
-
default: (0, vue.withCtx)(() => [payload.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$57, [
|
|
11099
|
+
default: (0, vue.withCtx)(() => [payload.value && visible.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$57, [
|
|
10420
11100
|
__props.onConfirm ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$19, "仅回滚有差异的字段")) : (0, vue.createCommentVNode)("v-if", true),
|
|
10421
|
-
(0, vue.createElementVNode)("div", _hoisted_3$
|
|
11101
|
+
(0, vue.createElementVNode)("div", _hoisted_3$7, [(0, vue.createElementVNode)("span", _hoisted_4$5, (0, vue.toDisplayString)(targetText.value), 1), (0, vue.createElementVNode)("div", _hoisted_5$2, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicRadioGroup), {
|
|
10422
11102
|
modelValue: viewMode.value,
|
|
10423
11103
|
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => viewMode.value = $event),
|
|
10424
11104
|
size: "small",
|
|
@@ -10504,7 +11184,7 @@
|
|
|
10504
11184
|
"modelValue",
|
|
10505
11185
|
"title",
|
|
10506
11186
|
"width"
|
|
10507
|
-
])
|
|
11187
|
+
]);
|
|
10508
11188
|
};
|
|
10509
11189
|
}
|
|
10510
11190
|
});
|
|
@@ -10517,99 +11197,86 @@
|
|
|
10517
11197
|
key: 0,
|
|
10518
11198
|
class: "m-editor-history-list-empty"
|
|
10519
11199
|
};
|
|
10520
|
-
var _hoisted_2$18 = {
|
|
11200
|
+
var _hoisted_2$18 = {
|
|
11201
|
+
key: 0,
|
|
11202
|
+
class: "m-editor-history-list-toolbar"
|
|
11203
|
+
};
|
|
11204
|
+
var _hoisted_3$6 = { class: "m-editor-history-list-ul" };
|
|
10521
11205
|
var PageTab_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
10522
11206
|
name: "MEditorHistoryListPageTab",
|
|
10523
11207
|
__name: "PageTab",
|
|
10524
11208
|
props: {
|
|
10525
11209
|
list: {},
|
|
10526
|
-
expanded: {}
|
|
11210
|
+
expanded: {},
|
|
11211
|
+
marker: {}
|
|
10527
11212
|
},
|
|
10528
11213
|
emits: [
|
|
10529
11214
|
"toggle",
|
|
10530
11215
|
"goto",
|
|
10531
11216
|
"goto-initial",
|
|
10532
11217
|
"diff-step",
|
|
10533
|
-
"revert-step"
|
|
11218
|
+
"revert-step",
|
|
11219
|
+
"select",
|
|
11220
|
+
"clear"
|
|
10534
11221
|
],
|
|
10535
11222
|
setup(__props) {
|
|
10536
11223
|
const props = __props;
|
|
10537
11224
|
/**
|
|
10538
11225
|
* 当前 step 是否可查看差异:
|
|
10539
11226
|
* - 仅 update 操作;
|
|
10540
|
-
* - 单节点更新(
|
|
11227
|
+
* - 单节点更新(diff.length === 1),且 oldSchema / newSchema 都存在。
|
|
10541
11228
|
* 多节点更新难以选定单一对比目标,统一不展示差异入口。
|
|
10542
11229
|
*/
|
|
10543
11230
|
const isPageStepDiffable = (step) => {
|
|
10544
11231
|
if (step.opType !== "update") return false;
|
|
10545
|
-
const items = step.
|
|
11232
|
+
const items = step.diff ?? [];
|
|
10546
11233
|
if (items.length !== 1) return false;
|
|
10547
|
-
return Boolean(items[0]?.
|
|
11234
|
+
return Boolean(items[0]?.oldSchema && items[0]?.newSchema);
|
|
10548
11235
|
};
|
|
11236
|
+
/** 页面历史的描述 / 可操作性判定集合,注入给统一的 `toRowGroup`。 */
|
|
11237
|
+
const descriptor = {
|
|
11238
|
+
describeGroup: describePageGroup,
|
|
11239
|
+
describeStep: describePageStep,
|
|
11240
|
+
isStepDiffable: isPageStepDiffable,
|
|
11241
|
+
isStepRevertable: isPageStepRevertable
|
|
11242
|
+
};
|
|
11243
|
+
const rowKey = (group) => `pg-${group.steps[0]?.index}`;
|
|
11244
|
+
const toRow = (group) => toRowGroup(group, rowKey(group), descriptor);
|
|
10549
11245
|
/**
|
|
10550
11246
|
* 是否处于"初始状态"——即对应页面历史栈 cursor===0:
|
|
10551
|
-
* 当 list 中所有 group 的 applied 都为 false
|
|
10552
|
-
*
|
|
11247
|
+
* 当 list 中所有 group 的 applied 都为 false 时即为该状态(空列表 `every` 返回 true,
|
|
11248
|
+
* 即仅有 marker、无任何操作记录时也视为处于初始状态)。
|
|
10553
11249
|
*/
|
|
10554
|
-
const isInitial = (0, vue.computed)(() => props.list.
|
|
11250
|
+
const isInitial = (0, vue.computed)(() => props.list.every((g) => !g.applied));
|
|
10555
11251
|
return (_ctx, _cache) => {
|
|
10556
|
-
return !__props.list.length ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$56, "暂无操作记录")) : ((0, vue.openBlock)(), (0, vue.
|
|
10557
|
-
|
|
10558
|
-
|
|
10559
|
-
|
|
10560
|
-
|
|
11252
|
+
return !__props.list.length && !__props.marker ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$56, "暂无操作记录")) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [__props.list.length ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$18, [(0, vue.createElementVNode)("span", {
|
|
11253
|
+
class: "m-editor-history-list-clear",
|
|
11254
|
+
title: "清空当前页面的历史记录",
|
|
11255
|
+
onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("clear"))
|
|
11256
|
+
}, "清空")])) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicScrollbar), { "max-height": "360px" }, {
|
|
11257
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("ul", _hoisted_3$6, [
|
|
10561
11258
|
((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.list, (group) => {
|
|
10562
11259
|
return (0, vue.openBlock)(), (0, vue.createBlock)(GroupRow_default, {
|
|
10563
|
-
key:
|
|
10564
|
-
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
"
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
"sub-steps": group.steps.map((s) => ({
|
|
10574
|
-
index: s.index,
|
|
10575
|
-
applied: s.applied,
|
|
10576
|
-
isCurrent: s.isCurrent,
|
|
10577
|
-
desc: (0, vue.unref)(describePageStep)(s.step),
|
|
10578
|
-
diffable: isPageStepDiffable(s.step),
|
|
10579
|
-
revertable: s.applied && (0, vue.unref)(isPageStepRevertable)(s.step),
|
|
10580
|
-
source: s.step.source,
|
|
10581
|
-
time: (0, vue.unref)(formatHistoryTime)(s.step.timestamp),
|
|
10582
|
-
timeTitle: (0, vue.unref)(formatHistoryFullTime)(s.step.timestamp)
|
|
10583
|
-
})),
|
|
10584
|
-
"is-current": group.isCurrent,
|
|
10585
|
-
expanded: !!__props.expanded[`pg-${group.steps[0]?.index}`],
|
|
10586
|
-
onToggle: _cache[0] || (_cache[0] = (key) => _ctx.$emit("toggle", key)),
|
|
10587
|
-
onGoto: _cache[1] || (_cache[1] = (index) => _ctx.$emit("goto", index)),
|
|
10588
|
-
onDiffStep: _cache[2] || (_cache[2] = (index) => _ctx.$emit("diff-step", index)),
|
|
10589
|
-
onRevertStep: _cache[3] || (_cache[3] = (index) => _ctx.$emit("revert-step", index))
|
|
10590
|
-
}, null, 8, [
|
|
10591
|
-
"group-key",
|
|
10592
|
-
"applied",
|
|
10593
|
-
"merged",
|
|
10594
|
-
"op-type",
|
|
10595
|
-
"desc",
|
|
10596
|
-
"source",
|
|
10597
|
-
"time",
|
|
10598
|
-
"time-title",
|
|
10599
|
-
"step-count",
|
|
10600
|
-
"sub-steps",
|
|
10601
|
-
"is-current",
|
|
10602
|
-
"expanded"
|
|
10603
|
-
]);
|
|
11260
|
+
key: rowKey(group),
|
|
11261
|
+
group: toRow(group),
|
|
11262
|
+
expanded: (0, vue.unref)(isHistoryGroupExpanded)(__props.expanded, rowKey(group)),
|
|
11263
|
+
"select-enabled": true,
|
|
11264
|
+
onToggle: _cache[1] || (_cache[1] = (key) => _ctx.$emit("toggle", key)),
|
|
11265
|
+
onGoto: _cache[2] || (_cache[2] = (index) => _ctx.$emit("goto", index)),
|
|
11266
|
+
onDiffStep: _cache[3] || (_cache[3] = (index) => _ctx.$emit("diff-step", index)),
|
|
11267
|
+
onRevertStep: _cache[4] || (_cache[4] = (index) => _ctx.$emit("revert-step", index)),
|
|
11268
|
+
onSelect: _cache[5] || (_cache[5] = (index) => _ctx.$emit("select", index))
|
|
11269
|
+
}, null, 8, ["group", "expanded"]);
|
|
10604
11270
|
}), 128)),
|
|
10605
|
-
(0, vue.createCommentVNode)("\n 初始状态项:永远位于列表底部(页面 tab 倒序展示,最底部=最早),\n 作为\"未修改\"零点。当所有 group 都未 applied 时它即为当前位置。\n "),
|
|
11271
|
+
(0, vue.createCommentVNode)("\n 初始状态项:永远位于列表底部(页面 tab 倒序展示,最底部=最早),\n 作为\"未修改\"零点。当所有 group 都未 applied 时它即为当前位置。\n 设置 root 时生成的「未修改的初始状态」标记(marker)会作为该行的文案与时间来源。\n "),
|
|
10606
11272
|
(0, vue.createVNode)(InitialRow_default, {
|
|
10607
11273
|
"is-current": isInitial.value,
|
|
10608
|
-
|
|
10609
|
-
|
|
11274
|
+
marker: __props.marker,
|
|
11275
|
+
onGotoInitial: _cache[6] || (_cache[6] = ($event) => _ctx.$emit("goto-initial"))
|
|
11276
|
+
}, null, 8, ["is-current", "marker"])
|
|
10610
11277
|
])]),
|
|
10611
11278
|
_: 1
|
|
10612
|
-
}));
|
|
11279
|
+
})], 64));
|
|
10613
11280
|
};
|
|
10614
11281
|
}
|
|
10615
11282
|
});
|
|
@@ -10619,6 +11286,12 @@
|
|
|
10619
11286
|
//#endregion
|
|
10620
11287
|
//#region packages/editor/src/layouts/history-list/HistoryListPanel.vue?vue&type=script&setup=true&lang.ts
|
|
10621
11288
|
var _hoisted_1$55 = { class: "m-editor-history-list" };
|
|
11289
|
+
/**
|
|
11290
|
+
* 构造差异弹窗入参:仅 update(前后值都存在)可对比。
|
|
11291
|
+
* - 页面(无 id):在全部分组中按 index 定位 step,目标 id 取自快照;
|
|
11292
|
+
* - 数据源 / 代码块(带 id):先匹配分组 id 再按 index 定位。
|
|
11293
|
+
* 无可对比内容(多节点 / add / remove)或定位不到时返回 null。
|
|
11294
|
+
*/
|
|
10622
11295
|
var HistoryListPanel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
10623
11296
|
name: "MEditorHistoryListPanel",
|
|
10624
11297
|
__name: "HistoryListPanel",
|
|
@@ -10647,7 +11320,10 @@
|
|
|
10647
11320
|
const ClockIcon = (0, vue.markRaw)(_element_plus_icons_vue.Clock);
|
|
10648
11321
|
const CloseIcon = (0, vue.markRaw)(_element_plus_icons_vue.Close);
|
|
10649
11322
|
const activeTab = (0, vue.ref)("page");
|
|
10650
|
-
/**
|
|
11323
|
+
/**
|
|
11324
|
+
* 面板显隐受控:reference 图标点击切换,右上角关闭按钮置为 false。
|
|
11325
|
+
* 点击面板以外区域的自动收起由 TMagicPopover 通过 v-model:visible 回写完成。
|
|
11326
|
+
*/
|
|
10651
11327
|
const visible = (0, vue.ref)(false);
|
|
10652
11328
|
const tabPaneComponent = (0, _tmagic_design.getDesignConfig)("components")?.tabPane;
|
|
10653
11329
|
/**
|
|
@@ -10657,7 +11333,7 @@
|
|
|
10657
11333
|
const extraTabs = (0, vue.inject)("historyListExtraTabs", []);
|
|
10658
11334
|
/** label 支持字符串或函数,函数形式便于展示动态数量等内容。 */
|
|
10659
11335
|
const resolveTabLabel = (tab) => typeof tab.label === "function" ? tab.label() : tab.label;
|
|
10660
|
-
const { editorService, dataSourceService, codeBlockService, historyService, propsService } = useServices();
|
|
11336
|
+
const { editorService, dataSourceService, codeBlockService, historyService, propsService, stageOverlayService } = useServices();
|
|
10661
11337
|
/**
|
|
10662
11338
|
* 数据源 / 代码块功能可被业务方通过 `disabledDataSource` / `disabledCodeBlock` 禁用,
|
|
10663
11339
|
* 禁用后对应的历史记录 tab 不再展示。若当前激活的 tab 恰好被禁用,则回退到「页面」tab。
|
|
@@ -10674,15 +11350,60 @@
|
|
|
10674
11350
|
*/
|
|
10675
11351
|
const extendFormState = (0, vue.inject)("extendFormState", void 0);
|
|
10676
11352
|
const { expanded, toggleGroup, pageGroups, dataSourceGroups, codeBlockGroups, pageGroupsDisplay, dataSourceGroupsByTarget, codeBlockGroupsByTarget } = useHistoryList();
|
|
11353
|
+
/**
|
|
11354
|
+
* 当前活动页的「加载/初始」标记记录(设置 root 时生成),透传给 PageTab 的底部初始行展示。
|
|
11355
|
+
* 基于 historyService 的 reactive state 派生,活动页切换或标记写入后自动刷新。
|
|
11356
|
+
*/
|
|
11357
|
+
const pageMarker = (0, vue.computed)(() => historyService.getPageMarker());
|
|
10677
11358
|
/** 数据源 step 仅 update(前后 schema 都存在)时可查看差异。 */
|
|
10678
|
-
const isDataSourceStepDiffable = (step) => Boolean(step.oldSchema && step.newSchema);
|
|
11359
|
+
const isDataSourceStepDiffable = (step) => Boolean(step.diff?.[0]?.oldSchema && step.diff?.[0]?.newSchema);
|
|
10679
11360
|
/** 代码块 step 仅 update(前后 content 都存在)时可查看差异。 */
|
|
10680
|
-
const isCodeBlockStepDiffable = (step) => Boolean(step.
|
|
11361
|
+
const isCodeBlockStepDiffable = (step) => Boolean(step.diff?.[0]?.oldSchema && step.diff?.[0]?.newSchema);
|
|
11362
|
+
/**
|
|
11363
|
+
* 数据源 / 代码块两类 bucket 历史的整体渲染配置:把 title / prefix 与各自的描述、
|
|
11364
|
+
* 可差异、可回滚判定收敛为单一对象整体注入 BucketTab,组件内部按需读取。
|
|
11365
|
+
*/
|
|
11366
|
+
const dataSourceConfig = {
|
|
11367
|
+
title: "数据源",
|
|
11368
|
+
prefix: "ds",
|
|
11369
|
+
describeGroup: describeDataSourceGroup,
|
|
11370
|
+
describeStep: describeDataSourceStep,
|
|
11371
|
+
isStepDiffable: isDataSourceStepDiffable,
|
|
11372
|
+
isStepRevertable: isDataSourceStepRevertable
|
|
11373
|
+
};
|
|
11374
|
+
const codeBlockConfig = {
|
|
11375
|
+
title: "代码块",
|
|
11376
|
+
prefix: "cb",
|
|
11377
|
+
describeGroup: describeCodeBlockGroup,
|
|
11378
|
+
describeStep: describeCodeBlockStep,
|
|
11379
|
+
isStepDiffable: isCodeBlockStepDiffable,
|
|
11380
|
+
isStepRevertable: isCodeBlockStepRevertable
|
|
11381
|
+
};
|
|
10681
11382
|
/** 把"目标 step 索引"翻译成"目标 cursor"(已应用步骤数量)。 */
|
|
10682
11383
|
const indexToCursor = (index) => index + 1;
|
|
10683
11384
|
const onPageGoto = (index) => {
|
|
10684
11385
|
editorService.gotoPageStep(indexToCursor(index));
|
|
10685
11386
|
};
|
|
11387
|
+
/**
|
|
11388
|
+
* 点击页面历史记录行:选中该记录对应的画布节点。
|
|
11389
|
+
* - 从目标 step 的 diff 中取节点 id(优先 newSchema,回退 oldSchema),按出现顺序找到第一个当前仍存在的节点;
|
|
11390
|
+
* - 与图层树点击选中一致:editorService.select + 画布 / overlay 画布 select 三者联动;
|
|
11391
|
+
* - 该 step 涉及的节点都已不存在(如删除记录、被撤销的新增)时给出提示,不做选中。
|
|
11392
|
+
*/
|
|
11393
|
+
const onPageSelect = async (index) => {
|
|
11394
|
+
const step = historyService.getPageStepList()[index]?.step;
|
|
11395
|
+
if (!step) return;
|
|
11396
|
+
const targetId = (step.diff ?? []).map((item) => item.newSchema?.id ?? item.oldSchema?.id).find((id) => id !== void 0 && id !== null && editorService.getNodeById(id, false));
|
|
11397
|
+
if (targetId === void 0 || targetId === null) {
|
|
11398
|
+
_tmagic_design.tMagicMessage.warning("该记录对应的节点已不存在,无法选中");
|
|
11399
|
+
return;
|
|
11400
|
+
}
|
|
11401
|
+
const node = editorService.getNodeById(targetId, false);
|
|
11402
|
+
if (!node) return;
|
|
11403
|
+
await editorService.select(node);
|
|
11404
|
+
editorService.get("stage")?.select(targetId);
|
|
11405
|
+
stageOverlayService.get("stage")?.select(targetId);
|
|
11406
|
+
};
|
|
10686
11407
|
const onDataSourceGoto = (id, index) => {
|
|
10687
11408
|
dataSourceService.goto(id, indexToCursor(index));
|
|
10688
11409
|
};
|
|
@@ -10703,71 +11424,53 @@
|
|
|
10703
11424
|
codeBlockService.goto(id, 0);
|
|
10704
11425
|
};
|
|
10705
11426
|
const diffDialogRef = (0, vue.useTemplateRef)("diffDialog");
|
|
11427
|
+
const confirmDialogRef = (0, vue.useTemplateRef)("confirmDialog");
|
|
10706
11428
|
/**
|
|
10707
|
-
*
|
|
10708
|
-
*
|
|
10709
|
-
* `currentValue` 取自 editorService 中该节点当前实际值,用于支持「与当前对比」。
|
|
10710
|
-
* 无可对比内容(如多节点 / add / remove)时返回 null。
|
|
11429
|
+
* 三类历史(页面 / 数据源 / 代码块)差异弹窗入参的构造差异,收敛为一份配置:
|
|
11430
|
+
* 仅「分组来源、当前值读取、类型 / 展示名提取」不同,定位 step、校验前后值、组装 payload 的流程共用。
|
|
10711
11431
|
*/
|
|
10712
|
-
const
|
|
10713
|
-
const
|
|
10714
|
-
|
|
10715
|
-
const
|
|
10716
|
-
if (!
|
|
10717
|
-
const
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
const
|
|
10721
|
-
const
|
|
11432
|
+
const buildDiffPayload = (source, index, id) => {
|
|
11433
|
+
for (const group of source.groups()) {
|
|
11434
|
+
if (id !== void 0 && group.id !== id) continue;
|
|
11435
|
+
const step = group.steps.find((s) => s.index === index)?.step;
|
|
11436
|
+
if (!step) continue;
|
|
11437
|
+
const oldSchema = step.diff?.[0]?.oldSchema;
|
|
11438
|
+
const newSchema = step.diff?.[0]?.newSchema;
|
|
11439
|
+
if (!oldSchema || !newSchema) return null;
|
|
11440
|
+
const targetId = id ?? newSchema.id ?? oldSchema.id;
|
|
11441
|
+
const type = source.resolveType?.(newSchema, oldSchema);
|
|
10722
11442
|
return {
|
|
10723
|
-
category:
|
|
10724
|
-
type,
|
|
10725
|
-
lastValue:
|
|
10726
|
-
value:
|
|
10727
|
-
currentValue:
|
|
10728
|
-
targetLabel:
|
|
10729
|
-
id:
|
|
11443
|
+
category: source.category,
|
|
11444
|
+
...type !== void 0 ? { type } : {},
|
|
11445
|
+
lastValue: oldSchema,
|
|
11446
|
+
value: newSchema,
|
|
11447
|
+
currentValue: (targetId !== void 0 ? source.getCurrent(targetId) : null) || null,
|
|
11448
|
+
targetLabel: source.resolveLabel(newSchema, oldSchema, targetId),
|
|
11449
|
+
id: targetId
|
|
10730
11450
|
};
|
|
10731
11451
|
}
|
|
10732
11452
|
return null;
|
|
10733
11453
|
};
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
}
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
value: newSchema,
|
|
10755
|
-
currentValue: currentSchema || null,
|
|
10756
|
-
targetLabel: newSchema.title || oldSchema.title || `${id}`,
|
|
10757
|
-
id
|
|
10758
|
-
};
|
|
10759
|
-
});
|
|
10760
|
-
const buildCodeBlockDiffPayload = (id, index) => findGroupStep(historyService.getCodeBlockHistoryGroups(), id, index, ({ oldContent, newContent }) => {
|
|
10761
|
-
if (!oldContent || !newContent) return null;
|
|
10762
|
-
return {
|
|
10763
|
-
category: "code-block",
|
|
10764
|
-
lastValue: oldContent,
|
|
10765
|
-
value: newContent,
|
|
10766
|
-
currentValue: codeBlockService.getCodeContentById(id) || null,
|
|
10767
|
-
targetLabel: newContent.name || oldContent.name || `${id}`,
|
|
10768
|
-
id
|
|
10769
|
-
};
|
|
10770
|
-
});
|
|
11454
|
+
const buildPageDiffPayload = (index) => buildDiffPayload({
|
|
11455
|
+
category: "node",
|
|
11456
|
+
groups: () => historyService.getPageHistoryGroups(),
|
|
11457
|
+
getCurrent: (id) => editorService.getNodeById(id),
|
|
11458
|
+
resolveType: (n, o) => n.type || o.type || "",
|
|
11459
|
+
resolveLabel: (n, o) => n.name || o.name || n.type || o.type || ""
|
|
11460
|
+
}, index);
|
|
11461
|
+
const buildDataSourceDiffPayload = (id, index) => buildDiffPayload({
|
|
11462
|
+
category: "data-source",
|
|
11463
|
+
groups: () => historyService.getDataSourceHistoryGroups(),
|
|
11464
|
+
getCurrent: (id) => dataSourceService.getDataSourceById(`${id}`),
|
|
11465
|
+
resolveType: (n, o) => n.type || o.type || "base",
|
|
11466
|
+
resolveLabel: (n, o, id) => n.title || o.title || `${id}`
|
|
11467
|
+
}, index, id);
|
|
11468
|
+
const buildCodeBlockDiffPayload = (id, index) => buildDiffPayload({
|
|
11469
|
+
category: "code-block",
|
|
11470
|
+
groups: () => historyService.getCodeBlockHistoryGroups(),
|
|
11471
|
+
getCurrent: (id) => codeBlockService.getCodeContentById(id),
|
|
11472
|
+
resolveLabel: (n, o, id) => n.name || o.name || `${id}`
|
|
11473
|
+
}, index, id);
|
|
10771
11474
|
const onPageDiff = (index) => {
|
|
10772
11475
|
const payload = buildPageDiffPayload(index);
|
|
10773
11476
|
if (payload) diffDialogRef.value?.open(payload);
|
|
@@ -10780,173 +11483,259 @@
|
|
|
10780
11483
|
const payload = buildCodeBlockDiffPayload(id, index);
|
|
10781
11484
|
if (payload) diffDialogRef.value?.open(payload);
|
|
10782
11485
|
};
|
|
10783
|
-
const onConfirmRevert = (0, vue.shallowRef)();
|
|
10784
11486
|
/**
|
|
10785
|
-
*
|
|
11487
|
+
* 「回滚」统一入口:把目标历史步骤的修改作为一次新操作反向应用(类 git revert),
|
|
10786
11488
|
* 不破坏原有栈结构。各 service 内部完成反向 + 入栈,并自带描述用于面板展示。
|
|
10787
11489
|
*
|
|
10788
|
-
*
|
|
10789
|
-
*
|
|
11490
|
+
* 交互:
|
|
11491
|
+
* - 可差异对比的步骤(单节点 / 单实体 update):弹出差异弹窗供用户确认,点「确定回滚」再执行;
|
|
11492
|
+
* - 无法对比的步骤(add / remove / 多节点更新,payload 为 null):弹出普通二次确认框,确认后执行。
|
|
11493
|
+
*
|
|
11494
|
+
* 页面 / 数据源 / 代码块三类回滚仅「差异入参构造」与「实际 revert 调用」不同,
|
|
11495
|
+
* 由调用方分别传入 payload 与 revert,公共的弹窗 / 确认流程在此收敛。
|
|
11496
|
+
*/
|
|
11497
|
+
const runRevert = (payload) => {
|
|
11498
|
+
if (payload && confirmDialogRef.value) return confirmDialogRef.value.confirm(payload);
|
|
11499
|
+
return confirmRevert();
|
|
11500
|
+
};
|
|
11501
|
+
/**
|
|
11502
|
+
* 回滚前置校验:若该历史步骤回滚所依赖的目标数据已被删除,则无法回滚。
|
|
11503
|
+
* - update(把旧值写回):被修改的目标必须仍存在;
|
|
11504
|
+
* - 页面 remove(还原被删节点):被删节点的原父容器必须仍存在,否则无处插回;
|
|
11505
|
+
* add(回滚即删除)即使目标已不在,也已达成「删除」目的,不视为失败。
|
|
11506
|
+
*
|
|
11507
|
+
* 命中时弹出「回滚失败」提示并返回 true,调用方据此中止本次回滚。
|
|
10790
11508
|
*/
|
|
11509
|
+
const isPageRevertTargetMissing = (index) => {
|
|
11510
|
+
const step = historyService.getPageStepList()[index]?.step;
|
|
11511
|
+
if (!step) return false;
|
|
11512
|
+
if (step.opType === "update") return (step.diff ?? []).some((item) => {
|
|
11513
|
+
const id = item.newSchema?.id ?? item.oldSchema?.id;
|
|
11514
|
+
return id !== void 0 && !editorService.getNodeById(id, false);
|
|
11515
|
+
});
|
|
11516
|
+
if (step.opType === "remove") return (step.diff ?? []).some((item) => item.parentId !== void 0 && !editorService.getNodeById(item.parentId, false));
|
|
11517
|
+
return false;
|
|
11518
|
+
};
|
|
11519
|
+
/** 数据源 update 步骤回滚时,对应数据源必须仍存在(已删除则无处写回旧值)。 */
|
|
11520
|
+
const isDataSourceRevertTargetMissing = (id, index) => {
|
|
11521
|
+
const step = historyService.getDataSourceStepList(id)[index]?.step;
|
|
11522
|
+
return Boolean(step && step.opType === "update" && !dataSourceService.getDataSourceById(`${id}`));
|
|
11523
|
+
};
|
|
11524
|
+
/** 代码块 update 步骤回滚时,对应代码块必须仍存在(已删除则无处写回旧值)。 */
|
|
11525
|
+
const isCodeBlockRevertTargetMissing = (id, index) => {
|
|
11526
|
+
const step = historyService.getCodeBlockStepList(id)[index]?.step;
|
|
11527
|
+
return Boolean(step && step.opType === "update" && !codeBlockService.getCodeContentById(id));
|
|
11528
|
+
};
|
|
11529
|
+
/** 目标数据已被删除、无法回滚时的统一提示。 */
|
|
11530
|
+
const showRevertTargetMissing = () => {
|
|
11531
|
+
_tmagic_design.tMagicMessage.error("回滚失败:该记录对应的数据已被删除");
|
|
11532
|
+
};
|
|
10791
11533
|
const onPageRevert = (index) => {
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
11534
|
+
if (isPageRevertTargetMissing(index)) {
|
|
11535
|
+
showRevertTargetMissing();
|
|
11536
|
+
return Promise.resolve(null);
|
|
11537
|
+
}
|
|
11538
|
+
return runRevert(buildPageDiffPayload(index)).then((result) => result ? editorService.revertPageStep(index) : null);
|
|
10796
11539
|
};
|
|
10797
11540
|
const onDataSourceRevert = (id, index) => {
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
11541
|
+
if (isDataSourceRevertTargetMissing(id, index)) {
|
|
11542
|
+
showRevertTargetMissing();
|
|
11543
|
+
return Promise.resolve(null);
|
|
11544
|
+
}
|
|
11545
|
+
return runRevert(buildDataSourceDiffPayload(id, index)).then((result) => result ? dataSourceService.revert(id, index) : null);
|
|
10802
11546
|
};
|
|
10803
11547
|
const onCodeBlockRevert = (id, index) => {
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
11548
|
+
if (isCodeBlockRevertTargetMissing(id, index)) {
|
|
11549
|
+
showRevertTargetMissing();
|
|
11550
|
+
return Promise.resolve(null);
|
|
11551
|
+
}
|
|
11552
|
+
return runRevert(buildCodeBlockDiffPayload(id, index)).then((result) => result ? codeBlockService.revert(id, index) : null);
|
|
11553
|
+
};
|
|
11554
|
+
/**
|
|
11555
|
+
* 「回滚」二次确认:新增 / 删除 / 多节点更新等无法做差异对比的步骤,
|
|
11556
|
+
* 不弹差异弹窗,改用一个普通确认框替代「确定回滚」按钮,避免点击后无任何提示直接执行。
|
|
11557
|
+
* 用户取消时返回 false,调用方据此中止回滚。
|
|
11558
|
+
*/
|
|
11559
|
+
const confirmRevert = () => confirmDialog("确定回滚该步骤吗?回滚会将该操作作为一条新记录反向应用(新增将被删除、删除将被还原),不影响后续历史记录。");
|
|
11560
|
+
/**
|
|
11561
|
+
* 通用二次确认弹窗:清空历史 / 无法差异对比的回滚等会改变状态的操作,先弹出确认框,
|
|
11562
|
+
* 用户点击「确定」返回 true,取消(confirm reject)时返回 false 并静默忽略。
|
|
11563
|
+
*/
|
|
11564
|
+
const confirmDialog = async (message) => {
|
|
11565
|
+
try {
|
|
11566
|
+
await _tmagic_design.tMagicMessageBox.confirm(message, "提示", {
|
|
11567
|
+
confirmButtonText: "确定",
|
|
11568
|
+
cancelButtonText: "取消",
|
|
11569
|
+
type: "warning"
|
|
11570
|
+
});
|
|
11571
|
+
return true;
|
|
11572
|
+
} catch (e) {
|
|
11573
|
+
return false;
|
|
11574
|
+
}
|
|
11575
|
+
};
|
|
11576
|
+
/**
|
|
11577
|
+
* 把内存中(已清空对应类别后的)历史状态重新写回 IndexedDB,
|
|
11578
|
+
* 使本地持久化的那份与内存保持一致——即「连同本地保存的一并删除」。
|
|
11579
|
+
* 不支持 IndexedDB 或写入失败时静默忽略(内存清空已生效)。
|
|
11580
|
+
*/
|
|
11581
|
+
const syncIndexedDB = async () => {
|
|
11582
|
+
try {
|
|
11583
|
+
await historyService.saveToIndexedDB();
|
|
11584
|
+
} catch (e) {}
|
|
11585
|
+
};
|
|
11586
|
+
const onPageClear = async () => {
|
|
11587
|
+
if (await confirmDialog("确定清空当前页面的历史记录吗?清空后将无法撤销/重做之前的操作,本地保存的记录也会一并删除。")) {
|
|
11588
|
+
historyService.clearPage();
|
|
11589
|
+
await syncIndexedDB();
|
|
11590
|
+
}
|
|
10808
11591
|
};
|
|
10809
|
-
const
|
|
10810
|
-
|
|
11592
|
+
const onDataSourceClear = async () => {
|
|
11593
|
+
if (await confirmDialog("确定清空数据源的历史记录吗?清空后将无法撤销/重做之前的操作,本地保存的记录也会一并删除。")) {
|
|
11594
|
+
historyService.clearDataSource();
|
|
11595
|
+
await syncIndexedDB();
|
|
11596
|
+
}
|
|
11597
|
+
};
|
|
11598
|
+
const onCodeBlockClear = async () => {
|
|
11599
|
+
if (await confirmDialog("确定清空代码块的历史记录吗?清空后将无法撤销/重做之前的操作,本地保存的记录也会一并删除。")) {
|
|
11600
|
+
historyService.clearCodeBlock();
|
|
11601
|
+
await syncIndexedDB();
|
|
11602
|
+
}
|
|
10811
11603
|
};
|
|
10812
11604
|
return (_ctx, _cache) => {
|
|
10813
|
-
return (0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, null, [
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
trigger: "click",
|
|
10817
|
-
visible: visible.value,
|
|
10818
|
-
width: 660
|
|
10819
|
-
}, {
|
|
10820
|
-
reference: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
|
|
10821
|
-
effect: "dark",
|
|
11605
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, null, [
|
|
11606
|
+
(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicPopover), {
|
|
11607
|
+
"popper-class": "m-editor-history-list-popover",
|
|
10822
11608
|
placement: "bottom",
|
|
10823
|
-
|
|
11609
|
+
trigger: "click",
|
|
11610
|
+
visible: visible.value,
|
|
11611
|
+
"onUpdate:visible": _cache[3] || (_cache[3] = ($event) => visible.value = $event),
|
|
11612
|
+
width: 660
|
|
10824
11613
|
}, {
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
11614
|
+
reference: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
|
|
11615
|
+
effect: "dark",
|
|
11616
|
+
placement: "bottom",
|
|
11617
|
+
content: "历史记录"
|
|
10829
11618
|
}, {
|
|
10830
|
-
|
|
11619
|
+
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
|
|
11620
|
+
size: "small",
|
|
11621
|
+
link: "",
|
|
11622
|
+
onClick: _cache[2] || (_cache[2] = ($event) => visible.value = !visible.value)
|
|
11623
|
+
}, {
|
|
11624
|
+
icon: (0, vue.withCtx)(() => [(0, vue.createVNode)(Icon_default, { icon: (0, vue.unref)(ClockIcon) }, null, 8, ["icon"])]),
|
|
11625
|
+
_: 1
|
|
11626
|
+
})]),
|
|
10831
11627
|
_: 1
|
|
10832
11628
|
})]),
|
|
10833
|
-
|
|
10834
|
-
|
|
10835
|
-
|
|
10836
|
-
|
|
10837
|
-
placement: "top",
|
|
10838
|
-
content: "关闭"
|
|
10839
|
-
}, {
|
|
10840
|
-
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
|
|
10841
|
-
class: "m-editor-history-list-close",
|
|
10842
|
-
size: "small",
|
|
10843
|
-
link: "",
|
|
10844
|
-
onClick: _cache[0] || (_cache[0] = ($event) => visible.value = false)
|
|
11629
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_1$55, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
|
|
11630
|
+
effect: "dark",
|
|
11631
|
+
placement: "top",
|
|
11632
|
+
content: "关闭"
|
|
10845
11633
|
}, {
|
|
10846
|
-
|
|
10847
|
-
|
|
10848
|
-
|
|
10849
|
-
|
|
10850
|
-
|
|
10851
|
-
|
|
10852
|
-
|
|
10853
|
-
class: "m-editor-history-list-tabs"
|
|
10854
|
-
}, {
|
|
10855
|
-
default: (0, vue.withCtx)(() => [
|
|
10856
|
-
((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(tabPaneComponent)?.component || "el-tab-pane"), (0, vue.normalizeProps)((0, vue.guardReactiveProps)((0, vue.unref)(tabPaneComponent)?.props({
|
|
10857
|
-
name: "page",
|
|
10858
|
-
label: `页面 (${(0, vue.unref)(pageGroups).length})`
|
|
10859
|
-
}) || {})), {
|
|
10860
|
-
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(PageTab_default, {
|
|
10861
|
-
list: (0, vue.unref)(pageGroupsDisplay),
|
|
10862
|
-
expanded: (0, vue.unref)(expanded),
|
|
10863
|
-
onToggle: (0, vue.unref)(toggleGroup),
|
|
10864
|
-
onGoto: onPageGoto,
|
|
10865
|
-
onGotoInitial: onPageGotoInitial,
|
|
10866
|
-
onDiffStep: onPageDiff,
|
|
10867
|
-
onRevertStep: onPageRevert
|
|
10868
|
-
}, null, 8, [
|
|
10869
|
-
"list",
|
|
10870
|
-
"expanded",
|
|
10871
|
-
"onToggle"
|
|
10872
|
-
])]),
|
|
10873
|
-
_: 1
|
|
10874
|
-
}, 16)),
|
|
10875
|
-
!disabledDataSource.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(tabPaneComponent)?.component || "el-tab-pane"), (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 0 }, (0, vue.unref)(tabPaneComponent)?.props({
|
|
10876
|
-
name: "data-source",
|
|
10877
|
-
label: `数据源 (${(0, vue.unref)(dataSourceGroups).length})`
|
|
10878
|
-
}) || {})), {
|
|
10879
|
-
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(BucketTab_default, {
|
|
10880
|
-
title: "数据源",
|
|
10881
|
-
prefix: "ds",
|
|
10882
|
-
buckets: (0, vue.unref)(dataSourceGroupsByTarget),
|
|
10883
|
-
expanded: (0, vue.unref)(expanded),
|
|
10884
|
-
"describe-group": (0, vue.unref)(describeDataSourceGroup),
|
|
10885
|
-
"describe-step": (0, vue.unref)(describeDataSourceStep),
|
|
10886
|
-
"is-step-diffable": isDataSourceStepDiffable,
|
|
10887
|
-
"is-step-revertable": (0, vue.unref)(isDataSourceStepRevertable),
|
|
10888
|
-
onToggle: (0, vue.unref)(toggleGroup),
|
|
10889
|
-
onGoto: onDataSourceGoto,
|
|
10890
|
-
onGotoInitial: onDataSourceGotoInitial,
|
|
10891
|
-
onDiffStep: onDataSourceDiff,
|
|
10892
|
-
onRevertStep: onDataSourceRevert
|
|
10893
|
-
}, null, 8, [
|
|
10894
|
-
"buckets",
|
|
10895
|
-
"expanded",
|
|
10896
|
-
"describe-group",
|
|
10897
|
-
"describe-step",
|
|
10898
|
-
"is-step-revertable",
|
|
10899
|
-
"onToggle"
|
|
10900
|
-
])]),
|
|
10901
|
-
_: 1
|
|
10902
|
-
}, 16)) : (0, vue.createCommentVNode)("v-if", true),
|
|
10903
|
-
!disabledCodeBlock.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(tabPaneComponent)?.component || "el-tab-pane"), (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 1 }, (0, vue.unref)(tabPaneComponent)?.props({
|
|
10904
|
-
name: "code-block",
|
|
10905
|
-
label: `代码块 (${(0, vue.unref)(codeBlockGroups).length})`
|
|
10906
|
-
}) || {})), {
|
|
10907
|
-
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(BucketTab_default, {
|
|
10908
|
-
title: "代码块",
|
|
10909
|
-
prefix: "cb",
|
|
10910
|
-
buckets: (0, vue.unref)(codeBlockGroupsByTarget),
|
|
10911
|
-
expanded: (0, vue.unref)(expanded),
|
|
10912
|
-
"describe-group": (0, vue.unref)(describeCodeBlockGroup),
|
|
10913
|
-
"describe-step": (0, vue.unref)(describeCodeBlockStep),
|
|
10914
|
-
"is-step-diffable": isCodeBlockStepDiffable,
|
|
10915
|
-
"is-step-revertable": (0, vue.unref)(isCodeBlockStepRevertable),
|
|
10916
|
-
onToggle: (0, vue.unref)(toggleGroup),
|
|
10917
|
-
onGoto: onCodeBlockGoto,
|
|
10918
|
-
onGotoInitial: onCodeBlockGotoInitial,
|
|
10919
|
-
onDiffStep: onCodeBlockDiff,
|
|
10920
|
-
onRevertStep: onCodeBlockRevert
|
|
10921
|
-
}, null, 8, [
|
|
10922
|
-
"buckets",
|
|
10923
|
-
"expanded",
|
|
10924
|
-
"describe-group",
|
|
10925
|
-
"describe-step",
|
|
10926
|
-
"is-step-revertable",
|
|
10927
|
-
"onToggle"
|
|
10928
|
-
])]),
|
|
11634
|
+
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
|
|
11635
|
+
class: "m-editor-history-list-close",
|
|
11636
|
+
size: "small",
|
|
11637
|
+
link: "",
|
|
11638
|
+
onClick: _cache[0] || (_cache[0] = ($event) => visible.value = false)
|
|
11639
|
+
}, {
|
|
11640
|
+
icon: (0, vue.withCtx)(() => [(0, vue.createVNode)(Icon_default, { icon: (0, vue.unref)(CloseIcon) }, null, 8, ["icon"])]),
|
|
10929
11641
|
_: 1
|
|
10930
|
-
}
|
|
10931
|
-
|
|
10932
|
-
|
|
10933
|
-
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
|
|
10937
|
-
|
|
10938
|
-
|
|
10939
|
-
|
|
10940
|
-
|
|
11642
|
+
})]),
|
|
11643
|
+
_: 1
|
|
11644
|
+
}), (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicTabs), {
|
|
11645
|
+
modelValue: activeTab.value,
|
|
11646
|
+
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => activeTab.value = $event),
|
|
11647
|
+
class: "m-editor-history-list-tabs"
|
|
11648
|
+
}, {
|
|
11649
|
+
default: (0, vue.withCtx)(() => [
|
|
11650
|
+
((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(tabPaneComponent)?.component || "el-tab-pane"), (0, vue.normalizeProps)((0, vue.guardReactiveProps)((0, vue.unref)(tabPaneComponent)?.props({
|
|
11651
|
+
name: "page",
|
|
11652
|
+
label: `页面 (${(0, vue.unref)(pageGroups).length})`
|
|
11653
|
+
}) || {})), {
|
|
11654
|
+
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(PageTab_default, {
|
|
11655
|
+
list: (0, vue.unref)(pageGroupsDisplay),
|
|
11656
|
+
expanded: (0, vue.unref)(expanded),
|
|
11657
|
+
marker: pageMarker.value,
|
|
11658
|
+
onToggle: (0, vue.unref)(toggleGroup),
|
|
11659
|
+
onGoto: onPageGoto,
|
|
11660
|
+
onGotoInitial: onPageGotoInitial,
|
|
11661
|
+
onDiffStep: onPageDiff,
|
|
11662
|
+
onRevertStep: onPageRevert,
|
|
11663
|
+
onSelect: onPageSelect,
|
|
11664
|
+
onClear: onPageClear
|
|
11665
|
+
}, null, 8, [
|
|
11666
|
+
"list",
|
|
11667
|
+
"expanded",
|
|
11668
|
+
"marker",
|
|
11669
|
+
"onToggle"
|
|
11670
|
+
])]),
|
|
11671
|
+
_: 1
|
|
11672
|
+
}, 16)),
|
|
11673
|
+
!disabledDataSource.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(tabPaneComponent)?.component || "el-tab-pane"), (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 0 }, (0, vue.unref)(tabPaneComponent)?.props({
|
|
11674
|
+
name: "data-source",
|
|
11675
|
+
label: `数据源 (${(0, vue.unref)(dataSourceGroups).length})`
|
|
11676
|
+
}) || {})), {
|
|
11677
|
+
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(BucketTab_default, {
|
|
11678
|
+
config: dataSourceConfig,
|
|
11679
|
+
buckets: (0, vue.unref)(dataSourceGroupsByTarget),
|
|
11680
|
+
expanded: (0, vue.unref)(expanded),
|
|
11681
|
+
onToggle: (0, vue.unref)(toggleGroup),
|
|
11682
|
+
onGoto: onDataSourceGoto,
|
|
11683
|
+
onGotoInitial: onDataSourceGotoInitial,
|
|
11684
|
+
onDiffStep: onDataSourceDiff,
|
|
11685
|
+
onRevertStep: onDataSourceRevert,
|
|
11686
|
+
onClear: onDataSourceClear
|
|
11687
|
+
}, null, 8, [
|
|
11688
|
+
"buckets",
|
|
11689
|
+
"expanded",
|
|
11690
|
+
"onToggle"
|
|
11691
|
+
])]),
|
|
11692
|
+
_: 1
|
|
11693
|
+
}, 16)) : (0, vue.createCommentVNode)("v-if", true),
|
|
11694
|
+
!disabledCodeBlock.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(tabPaneComponent)?.component || "el-tab-pane"), (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 1 }, (0, vue.unref)(tabPaneComponent)?.props({
|
|
11695
|
+
name: "code-block",
|
|
11696
|
+
label: `代码块 (${(0, vue.unref)(codeBlockGroups).length})`
|
|
11697
|
+
}) || {})), {
|
|
11698
|
+
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(BucketTab_default, {
|
|
11699
|
+
config: codeBlockConfig,
|
|
11700
|
+
buckets: (0, vue.unref)(codeBlockGroupsByTarget),
|
|
11701
|
+
expanded: (0, vue.unref)(expanded),
|
|
11702
|
+
onToggle: (0, vue.unref)(toggleGroup),
|
|
11703
|
+
onGoto: onCodeBlockGoto,
|
|
11704
|
+
onGotoInitial: onCodeBlockGotoInitial,
|
|
11705
|
+
onDiffStep: onCodeBlockDiff,
|
|
11706
|
+
onRevertStep: onCodeBlockRevert,
|
|
11707
|
+
onClear: onCodeBlockClear
|
|
11708
|
+
}, null, 8, [
|
|
11709
|
+
"buckets",
|
|
11710
|
+
"expanded",
|
|
11711
|
+
"onToggle"
|
|
11712
|
+
])]),
|
|
11713
|
+
_: 1
|
|
11714
|
+
}, 16)) : (0, vue.createCommentVNode)("v-if", true),
|
|
11715
|
+
((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)((0, vue.unref)(extraTabs), (tab) => {
|
|
11716
|
+
return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(tabPaneComponent)?.component || "el-tab-pane"), (0, vue.mergeProps)({ key: tab.name }, { ref_for: true }, (0, vue.unref)(tabPaneComponent)?.props({
|
|
11717
|
+
name: tab.name,
|
|
11718
|
+
label: resolveTabLabel(tab)
|
|
11719
|
+
}) || {}), {
|
|
11720
|
+
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tab.component), (0, vue.mergeProps)({ ref_for: true }, tab.props || {}, (0, vue.toHandlers)(tab.listeners || {})), null, 16))]),
|
|
11721
|
+
_: 2
|
|
11722
|
+
}, 1040);
|
|
11723
|
+
}), 128))
|
|
11724
|
+
]),
|
|
11725
|
+
_: 1
|
|
11726
|
+
}, 8, ["modelValue"])])]),
|
|
10941
11727
|
_: 1
|
|
10942
|
-
}, 8, ["
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
"extend-state"
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
11728
|
+
}, 8, ["visible"]),
|
|
11729
|
+
(0, vue.createVNode)(HistoryDiffDialog_default, {
|
|
11730
|
+
ref: "diffDialog",
|
|
11731
|
+
"extend-state": (0, vue.unref)(extendFormState)
|
|
11732
|
+
}, null, 8, ["extend-state"]),
|
|
11733
|
+
(0, vue.createVNode)(HistoryDiffDialog_default, {
|
|
11734
|
+
ref: "confirmDialog",
|
|
11735
|
+
"is-confirm": true,
|
|
11736
|
+
"extend-state": (0, vue.unref)(extendFormState)
|
|
11737
|
+
}, null, 8, ["extend-state"])
|
|
11738
|
+
], 64);
|
|
10950
11739
|
};
|
|
10951
11740
|
}
|
|
10952
11741
|
});
|
|
@@ -14242,7 +15031,11 @@
|
|
|
14242
15031
|
});
|
|
14243
15032
|
}
|
|
14244
15033
|
}, { immediate: true });
|
|
14245
|
-
const activeTabName = (0, vue.
|
|
15034
|
+
const activeTabName = (0, vue.computed)({
|
|
15035
|
+
get: () => uiService.get("sideBarActiveTabName"),
|
|
15036
|
+
set: (value) => uiService.set("sideBarActiveTabName", value)
|
|
15037
|
+
});
|
|
15038
|
+
uiService.set("sideBarActiveTabName", props.data?.status || "");
|
|
14246
15039
|
const getItemConfig = (data) => {
|
|
14247
15040
|
const map = {
|
|
14248
15041
|
[SideItemKey.COMPONENT_LIST]: {
|
|
@@ -15436,17 +16229,6 @@
|
|
|
15436
16229
|
],
|
|
15437
16230
|
sync: ["setCodeDslByIdSync"]
|
|
15438
16231
|
};
|
|
15439
|
-
/**
|
|
15440
|
-
* 「回滚」生成的新 step 简短描述。仅 service 层使用。
|
|
15441
|
-
*/
|
|
15442
|
-
var describeRevertCodeBlockStep = (step) => {
|
|
15443
|
-
const { oldContent, newContent, changeRecords, id } = step;
|
|
15444
|
-
if (oldContent === null && newContent) return `撤回新增 ${newContent.name || newContent.id || id}`;
|
|
15445
|
-
if (oldContent && newContent === null) return `还原已删除的 ${oldContent.name || oldContent.id || id}`;
|
|
15446
|
-
const name = newContent?.name || oldContent?.name || `${id}`;
|
|
15447
|
-
const propPath = changeRecords?.[0]?.propPath;
|
|
15448
|
-
return propPath ? `还原 ${name} · ${propPath}` : `还原 ${name}`;
|
|
15449
|
-
};
|
|
15450
16232
|
var CodeBlock = class extends BaseService {
|
|
15451
16233
|
state = (0, vue.reactive)({
|
|
15452
16234
|
codeDsl: null,
|
|
@@ -15455,6 +16237,16 @@
|
|
|
15455
16237
|
undeletableList: [],
|
|
15456
16238
|
paramsColConfig: void 0
|
|
15457
16239
|
});
|
|
16240
|
+
/**
|
|
16241
|
+
* 最近一次写入历史栈的代码块历史记录 uuid(单条写入场景:新增 / 更新)。
|
|
16242
|
+
* 供 setCodeDslById(Sync)AndGetHistoryId 取回,普通方法不读取它。
|
|
16243
|
+
*/
|
|
16244
|
+
lastPushedHistoryId = null;
|
|
16245
|
+
/**
|
|
16246
|
+
* deleteCodeDslByIds 一次删除多个代码块时,按写入顺序收集的历史记录 uuid 列表。
|
|
16247
|
+
* 在 deleteCodeDslByIds 入口处重置,供 deleteCodeDslByIdsAndGetHistoryId 取回。
|
|
16248
|
+
*/
|
|
16249
|
+
lastDeletedHistoryIds = [];
|
|
15458
16250
|
constructor() {
|
|
15459
16251
|
super([...canUsePluginMethods$4.async.map((methodName) => ({
|
|
15460
16252
|
name: methodName,
|
|
@@ -15537,13 +16329,13 @@
|
|
|
15537
16329
|
...codeConfigProcessed
|
|
15538
16330
|
};
|
|
15539
16331
|
const newContent = cloneDeep$1(codeDsl[id]);
|
|
15540
|
-
if (!doNotPushHistory) history_default.pushCodeBlock(id, {
|
|
16332
|
+
if (!doNotPushHistory) this.lastPushedHistoryId = history_default.pushCodeBlock(id, {
|
|
15541
16333
|
oldContent,
|
|
15542
16334
|
newContent,
|
|
15543
16335
|
changeRecords,
|
|
15544
16336
|
historyDescription,
|
|
15545
16337
|
source: historySource
|
|
15546
|
-
});
|
|
16338
|
+
})?.uuid ?? null;
|
|
15547
16339
|
this.emit("addOrUpdate", id, codeDsl[id]);
|
|
15548
16340
|
}
|
|
15549
16341
|
/**
|
|
@@ -15626,18 +16418,50 @@
|
|
|
15626
16418
|
async deleteCodeDslByIds(codeIds, { doNotPushHistory = false, historyDescription, historySource } = {}) {
|
|
15627
16419
|
const currentDsl = await this.getCodeDsl();
|
|
15628
16420
|
if (!currentDsl) return;
|
|
16421
|
+
this.lastDeletedHistoryIds = [];
|
|
15629
16422
|
codeIds.forEach((id) => {
|
|
15630
16423
|
const oldContent = currentDsl[id] ? cloneDeep$1(currentDsl[id]) : null;
|
|
15631
16424
|
delete currentDsl[id];
|
|
15632
|
-
if (oldContent && !doNotPushHistory)
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
|
|
15637
|
-
|
|
16425
|
+
if (oldContent && !doNotPushHistory) {
|
|
16426
|
+
const uuid = history_default.pushCodeBlock(id, {
|
|
16427
|
+
oldContent,
|
|
16428
|
+
newContent: null,
|
|
16429
|
+
historyDescription,
|
|
16430
|
+
source: historySource
|
|
16431
|
+
})?.uuid;
|
|
16432
|
+
if (uuid) this.lastDeletedHistoryIds.push(uuid);
|
|
16433
|
+
}
|
|
15638
16434
|
this.emit("remove", id);
|
|
15639
16435
|
});
|
|
15640
16436
|
}
|
|
16437
|
+
/**
|
|
16438
|
+
* 下列 *AndGetHistoryId 方法与对应的写入方法行为完全一致,
|
|
16439
|
+
* 唯一区别是返回值为本次写入历史栈的历史记录 uuid({@link CodeBlockStepValue.uuid}),
|
|
16440
|
+
* 可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
|
|
16441
|
+
*
|
|
16442
|
+
* 当本次操作未写入历史(doNotPushHistory 为 true、或无对应记录)时:单条写入返回 null,批量删除返回空数组。
|
|
16443
|
+
*/
|
|
16444
|
+
/** 等价于 {@link setCodeDslById},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
16445
|
+
async setCodeDslByIdAndGetHistoryId(id, codeConfig, options = {}) {
|
|
16446
|
+
this.lastPushedHistoryId = null;
|
|
16447
|
+
await this.setCodeDslById(id, codeConfig, options);
|
|
16448
|
+
return this.lastPushedHistoryId;
|
|
16449
|
+
}
|
|
16450
|
+
/** 等价于 {@link setCodeDslByIdSync},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
16451
|
+
setCodeDslByIdSyncAndGetHistoryId(id, codeConfig, force = true, options = {}) {
|
|
16452
|
+
this.lastPushedHistoryId = null;
|
|
16453
|
+
this.setCodeDslByIdSync(id, codeConfig, force, options);
|
|
16454
|
+
return this.lastPushedHistoryId;
|
|
16455
|
+
}
|
|
16456
|
+
/**
|
|
16457
|
+
* 等价于 {@link deleteCodeDslByIds},但返回本次写入的全部历史记录 uuid(按删除顺序)。
|
|
16458
|
+
* 一次删除多个代码块会产生多条历史记录,因此返回数组;未写入任何历史时返回空数组。
|
|
16459
|
+
*/
|
|
16460
|
+
async deleteCodeDslByIdsAndGetHistoryId(codeIds, options = {}) {
|
|
16461
|
+
this.lastDeletedHistoryIds = [];
|
|
16462
|
+
await this.deleteCodeDslByIds(codeIds, options);
|
|
16463
|
+
return [...this.lastDeletedHistoryIds];
|
|
16464
|
+
}
|
|
15641
16465
|
setParamsColConfig(config) {
|
|
15642
16466
|
this.state.paramsColConfig = config;
|
|
15643
16467
|
}
|
|
@@ -15713,11 +16537,25 @@
|
|
|
15713
16537
|
async revert(id, index) {
|
|
15714
16538
|
const entry = history_default.getCodeBlockStepList(id)[index];
|
|
15715
16539
|
if (!entry?.applied) return null;
|
|
15716
|
-
|
|
15717
|
-
|
|
16540
|
+
const { oldSchema, newSchema, changeRecords } = entry.step.diff?.[0] ?? {};
|
|
16541
|
+
if (oldSchema && newSchema && !changeRecords?.length) return null;
|
|
16542
|
+
const description = `回滚 #${index + 1}: ${describeRevertStep(entry.step.id, entry.step.diff?.[0], (s) => s.name)}`;
|
|
15718
16543
|
return await this.applyRevertStep(entry.step, description);
|
|
15719
16544
|
}
|
|
15720
16545
|
/**
|
|
16546
|
+
* 通过历史记录 uuid 回滚某条代码块历史步骤,语义同 {@link revert},
|
|
16547
|
+
* 仅无需调用方再传 codeBlockId 与 index:内部会按 uuid({@link CodeBlockStepValue.uuid})
|
|
16548
|
+
* 在全部代码块栈中定位对应步骤后再回滚。
|
|
16549
|
+
*
|
|
16550
|
+
* @param uuid 目标历史记录的 uuid,通常由 {@link setCodeDslByIdAndGetHistoryId} 等方法返回
|
|
16551
|
+
* @returns 反向后产生的新 step;找不到对应 uuid / 未应用时返回 null
|
|
16552
|
+
*/
|
|
16553
|
+
async revertById(uuid) {
|
|
16554
|
+
const location = history_default.findCodeBlockStepLocationByUuid(uuid);
|
|
16555
|
+
if (!location) return null;
|
|
16556
|
+
return await this.revert(location.id, location.index);
|
|
16557
|
+
}
|
|
16558
|
+
/**
|
|
15721
16559
|
* 生成代码块唯一id
|
|
15722
16560
|
* @returns {Id} 代码块唯一id
|
|
15723
16561
|
*/
|
|
@@ -15782,22 +16620,23 @@
|
|
|
15782
16620
|
* 差异仅在于通过公开的 setCodeDslByIdSync / deleteCodeDslByIds 触发 push。
|
|
15783
16621
|
*/
|
|
15784
16622
|
async applyRevertStep(step, historyDescription) {
|
|
15785
|
-
const { id
|
|
15786
|
-
|
|
16623
|
+
const { id } = step;
|
|
16624
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
16625
|
+
if (!oldSchema && newSchema) {
|
|
15787
16626
|
await this.deleteCodeDslByIds([id], {
|
|
15788
16627
|
historyDescription,
|
|
15789
16628
|
historySource: "rollback"
|
|
15790
16629
|
});
|
|
15791
16630
|
return history_default.getCodeBlockStepList(id).slice(-1)[0]?.step ?? null;
|
|
15792
16631
|
}
|
|
15793
|
-
if (
|
|
15794
|
-
this.setCodeDslByIdSync(id, cloneDeep$1(
|
|
16632
|
+
if (oldSchema && !newSchema) {
|
|
16633
|
+
this.setCodeDslByIdSync(id, cloneDeep$1(oldSchema), true, {
|
|
15795
16634
|
historyDescription,
|
|
15796
16635
|
historySource: "rollback"
|
|
15797
16636
|
});
|
|
15798
16637
|
return history_default.getCodeBlockStepList(id).slice(-1)[0]?.step ?? null;
|
|
15799
16638
|
}
|
|
15800
|
-
if (!
|
|
16639
|
+
if (!oldSchema || !newSchema) return null;
|
|
15801
16640
|
if (changeRecords?.length) {
|
|
15802
16641
|
const current = this.getCodeContentById(id);
|
|
15803
16642
|
if (!current) return null;
|
|
@@ -15808,17 +16647,17 @@
|
|
|
15808
16647
|
fallbackToFullReplace = true;
|
|
15809
16648
|
break;
|
|
15810
16649
|
}
|
|
15811
|
-
const value = cloneDeep$1((0, _tmagic_utils.getValueByKeyPath)(record.propPath,
|
|
16650
|
+
const value = cloneDeep$1((0, _tmagic_utils.getValueByKeyPath)(record.propPath, oldSchema));
|
|
15812
16651
|
(0, _tmagic_utils.setValueByKeyPath)(record.propPath, value, patched);
|
|
15813
16652
|
}
|
|
15814
|
-
this.setCodeDslByIdSync(id, fallbackToFullReplace ? cloneDeep$1(
|
|
16653
|
+
this.setCodeDslByIdSync(id, fallbackToFullReplace ? cloneDeep$1(oldSchema) : patched, true, {
|
|
15815
16654
|
changeRecords,
|
|
15816
16655
|
historyDescription,
|
|
15817
16656
|
historySource: "rollback"
|
|
15818
16657
|
});
|
|
15819
16658
|
return history_default.getCodeBlockStepList(id).slice(-1)[0]?.step ?? null;
|
|
15820
16659
|
}
|
|
15821
|
-
this.setCodeDslByIdSync(id, cloneDeep$1(
|
|
16660
|
+
this.setCodeDslByIdSync(id, cloneDeep$1(oldSchema), true, {
|
|
15822
16661
|
historyDescription,
|
|
15823
16662
|
historySource: "rollback"
|
|
15824
16663
|
});
|
|
@@ -15839,19 +16678,20 @@
|
|
|
15839
16678
|
* @param reverse true=撤销,false=重做
|
|
15840
16679
|
*/
|
|
15841
16680
|
async applyHistoryStep(step, reverse) {
|
|
15842
|
-
const { id
|
|
15843
|
-
|
|
16681
|
+
const { id } = step;
|
|
16682
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
16683
|
+
if (!oldSchema && newSchema) {
|
|
15844
16684
|
if (reverse) await this.deleteCodeDslByIds([id], { doNotPushHistory: true });
|
|
15845
|
-
else this.setCodeDslByIdSync(id, cloneDeep$1(
|
|
16685
|
+
else this.setCodeDslByIdSync(id, cloneDeep$1(newSchema), true, { doNotPushHistory: true });
|
|
15846
16686
|
return;
|
|
15847
16687
|
}
|
|
15848
|
-
if (
|
|
15849
|
-
if (reverse) this.setCodeDslByIdSync(id, cloneDeep$1(
|
|
16688
|
+
if (oldSchema && !newSchema) {
|
|
16689
|
+
if (reverse) this.setCodeDslByIdSync(id, cloneDeep$1(oldSchema), true, { doNotPushHistory: true });
|
|
15850
16690
|
else await this.deleteCodeDslByIds([id], { doNotPushHistory: true });
|
|
15851
16691
|
return;
|
|
15852
16692
|
}
|
|
15853
|
-
if (!
|
|
15854
|
-
const sourceForValues = reverse ?
|
|
16693
|
+
if (!oldSchema || !newSchema) return;
|
|
16694
|
+
const sourceForValues = reverse ? oldSchema : newSchema;
|
|
15855
16695
|
if (changeRecords?.length) {
|
|
15856
16696
|
const current = this.getCodeContentById(id);
|
|
15857
16697
|
if (!current) return;
|
|
@@ -15920,18 +16760,6 @@
|
|
|
15920
16760
|
"createId"
|
|
15921
16761
|
]
|
|
15922
16762
|
};
|
|
15923
|
-
/**
|
|
15924
|
-
* 「回滚」生成的新 step 简短描述。
|
|
15925
|
-
* 仅在 service 层使用,避免依赖 UI 层 composables。
|
|
15926
|
-
*/
|
|
15927
|
-
var describeRevertDataSourceStep = (step) => {
|
|
15928
|
-
const { oldSchema, newSchema, changeRecords, id } = step;
|
|
15929
|
-
if (oldSchema === null && newSchema) return `撤回新增 ${newSchema.title || newSchema.id || id}`;
|
|
15930
|
-
if (oldSchema && newSchema === null) return `还原已删除的 ${oldSchema.title || oldSchema.id || id}`;
|
|
15931
|
-
const title = newSchema?.title || oldSchema?.title || `${id}`;
|
|
15932
|
-
const propPath = changeRecords?.[0]?.propPath;
|
|
15933
|
-
return propPath ? `还原 ${title} · ${propPath}` : `还原 ${title}`;
|
|
15934
|
-
};
|
|
15935
16763
|
var DataSource = class extends BaseService {
|
|
15936
16764
|
state = (0, vue.reactive)({
|
|
15937
16765
|
datasourceTypeList: [],
|
|
@@ -15942,6 +16770,12 @@
|
|
|
15942
16770
|
events: {},
|
|
15943
16771
|
methods: {}
|
|
15944
16772
|
});
|
|
16773
|
+
/**
|
|
16774
|
+
* 最近一次写入历史栈的数据源历史记录 uuid。
|
|
16775
|
+
* 供 *AndGetHistoryId 系列方法在调用 add / update / remove 后取回本次产生的历史记录 id;
|
|
16776
|
+
* 普通方法不读取它,调用前由 *AndGetHistoryId 重置为 null。
|
|
16777
|
+
*/
|
|
16778
|
+
lastPushedHistoryId = null;
|
|
15945
16779
|
constructor() {
|
|
15946
16780
|
super(canUsePluginMethods$3.sync.map((methodName) => ({
|
|
15947
16781
|
name: methodName,
|
|
@@ -15991,12 +16825,12 @@
|
|
|
15991
16825
|
id: config.id && !this.getDataSourceById(config.id) ? config.id : this.createId()
|
|
15992
16826
|
};
|
|
15993
16827
|
this.get("dataSources").push(newConfig);
|
|
15994
|
-
if (!doNotPushHistory) history_default.pushDataSource(newConfig.id, {
|
|
16828
|
+
if (!doNotPushHistory) this.lastPushedHistoryId = history_default.pushDataSource(newConfig.id, {
|
|
15995
16829
|
oldSchema: null,
|
|
15996
16830
|
newSchema: newConfig,
|
|
15997
16831
|
historyDescription,
|
|
15998
16832
|
source: historySource
|
|
15999
|
-
});
|
|
16833
|
+
})?.uuid ?? null;
|
|
16000
16834
|
this.emit("add", newConfig);
|
|
16001
16835
|
return newConfig;
|
|
16002
16836
|
}
|
|
@@ -16014,13 +16848,13 @@
|
|
|
16014
16848
|
const oldConfig = dataSources[index];
|
|
16015
16849
|
const newConfig = cloneDeep$1(config);
|
|
16016
16850
|
dataSources[index] = newConfig;
|
|
16017
|
-
if (!doNotPushHistory) history_default.pushDataSource(newConfig.id, {
|
|
16851
|
+
if (!doNotPushHistory) this.lastPushedHistoryId = history_default.pushDataSource(newConfig.id, {
|
|
16018
16852
|
oldSchema: oldConfig ? cloneDeep$1(oldConfig) : null,
|
|
16019
16853
|
newSchema: newConfig,
|
|
16020
16854
|
changeRecords,
|
|
16021
16855
|
historyDescription,
|
|
16022
16856
|
source: historySource
|
|
16023
|
-
});
|
|
16857
|
+
})?.uuid ?? null;
|
|
16024
16858
|
this.emit("update", newConfig, {
|
|
16025
16859
|
oldConfig,
|
|
16026
16860
|
changeRecords
|
|
@@ -16039,15 +16873,40 @@
|
|
|
16039
16873
|
const index = dataSources.findIndex((ds) => ds.id === id);
|
|
16040
16874
|
const oldConfig = index !== -1 ? dataSources[index] : null;
|
|
16041
16875
|
dataSources.splice(index, 1);
|
|
16042
|
-
if (oldConfig && !doNotPushHistory) history_default.pushDataSource(id, {
|
|
16876
|
+
if (oldConfig && !doNotPushHistory) this.lastPushedHistoryId = history_default.pushDataSource(id, {
|
|
16043
16877
|
oldSchema: cloneDeep$1(oldConfig),
|
|
16044
16878
|
newSchema: null,
|
|
16045
16879
|
historyDescription,
|
|
16046
16880
|
source: historySource
|
|
16047
|
-
});
|
|
16881
|
+
})?.uuid ?? null;
|
|
16048
16882
|
this.emit("remove", id);
|
|
16049
16883
|
}
|
|
16050
16884
|
/**
|
|
16885
|
+
* 下列 *AndGetHistoryId 方法与对应的 add / update / remove 行为完全一致,
|
|
16886
|
+
* 唯一区别是返回值为本次写入历史栈的历史记录 uuid({@link DataSourceStepValue.uuid}),
|
|
16887
|
+
* 而非数据源配置。可用于精确引用 / 定位该条历史记录(埋点、revert、跨端同步等)。
|
|
16888
|
+
*
|
|
16889
|
+
* 当本次操作未写入历史(doNotPushHistory 为 true、或无对应记录)时返回 null。
|
|
16890
|
+
*/
|
|
16891
|
+
/** 等价于 {@link add},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
16892
|
+
addAndGetHistoryId(config, options = {}) {
|
|
16893
|
+
this.lastPushedHistoryId = null;
|
|
16894
|
+
this.add(config, options);
|
|
16895
|
+
return this.lastPushedHistoryId;
|
|
16896
|
+
}
|
|
16897
|
+
/** 等价于 {@link update},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
16898
|
+
updateAndGetHistoryId(config, options = {}) {
|
|
16899
|
+
this.lastPushedHistoryId = null;
|
|
16900
|
+
this.update(config, options);
|
|
16901
|
+
return this.lastPushedHistoryId;
|
|
16902
|
+
}
|
|
16903
|
+
/** 等价于 {@link remove},但返回本次写入历史记录的 uuid(未入栈时返回 null)。 */
|
|
16904
|
+
removeAndGetHistoryId(id, options = {}) {
|
|
16905
|
+
this.lastPushedHistoryId = null;
|
|
16906
|
+
this.remove(id, options);
|
|
16907
|
+
return this.lastPushedHistoryId;
|
|
16908
|
+
}
|
|
16909
|
+
/**
|
|
16051
16910
|
* 撤销指定数据源的最近一次变更。
|
|
16052
16911
|
*
|
|
16053
16912
|
* 内部走 add / update / remove,因此会自动触发 dataSourceService 的事件,
|
|
@@ -16115,10 +16974,24 @@
|
|
|
16115
16974
|
revert(id, index) {
|
|
16116
16975
|
const entry = history_default.getDataSourceStepList(id)[index];
|
|
16117
16976
|
if (!entry?.applied) return null;
|
|
16118
|
-
|
|
16119
|
-
|
|
16977
|
+
const { oldSchema, newSchema, changeRecords } = entry.step.diff?.[0] ?? {};
|
|
16978
|
+
if (oldSchema && newSchema && !changeRecords?.length) return null;
|
|
16979
|
+
const description = `回滚 #${index + 1}: ${describeRevertStep(entry.step.id, entry.step.diff?.[0], (s) => s.title)}`;
|
|
16120
16980
|
return this.applyRevertStep(entry.step, description);
|
|
16121
16981
|
}
|
|
16982
|
+
/**
|
|
16983
|
+
* 通过历史记录 uuid 回滚某条数据源历史步骤,语义同 {@link revert},
|
|
16984
|
+
* 仅无需调用方再传 dataSourceId 与 index:内部会按 uuid({@link DataSourceStepValue.uuid})
|
|
16985
|
+
* 在全部数据源栈中定位对应步骤后再回滚。
|
|
16986
|
+
*
|
|
16987
|
+
* @param uuid 目标历史记录的 uuid,通常由 {@link addAndGetHistoryId} 等方法返回
|
|
16988
|
+
* @returns 反向后产生的新 step;找不到对应 uuid / 未应用时返回 null
|
|
16989
|
+
*/
|
|
16990
|
+
revertById(uuid) {
|
|
16991
|
+
const location = history_default.findDataSourceStepLocationByUuid(uuid);
|
|
16992
|
+
if (!location) return null;
|
|
16993
|
+
return this.revert(location.id, location.index);
|
|
16994
|
+
}
|
|
16122
16995
|
createId() {
|
|
16123
16996
|
return `ds_${(0, _tmagic_utils.guid)()}`;
|
|
16124
16997
|
}
|
|
@@ -16177,15 +17050,16 @@
|
|
|
16177
17050
|
* 同构,差异仅在于走对应的公共 add / update / remove 而不是带 doNotPushHistory 的版本。
|
|
16178
17051
|
*/
|
|
16179
17052
|
applyRevertStep(step, historyDescription) {
|
|
16180
|
-
const { id
|
|
16181
|
-
|
|
17053
|
+
const { id } = step;
|
|
17054
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
17055
|
+
if (!oldSchema && newSchema) {
|
|
16182
17056
|
this.remove(`${id}`, {
|
|
16183
17057
|
historyDescription,
|
|
16184
17058
|
historySource: "rollback"
|
|
16185
17059
|
});
|
|
16186
17060
|
return history_default.getDataSourceStepList(id).slice(-1)[0]?.step ?? null;
|
|
16187
17061
|
}
|
|
16188
|
-
if (oldSchema && newSchema
|
|
17062
|
+
if (oldSchema && !newSchema) {
|
|
16189
17063
|
this.add(cloneDeep$1(oldSchema), {
|
|
16190
17064
|
historyDescription,
|
|
16191
17065
|
historySource: "rollback"
|
|
@@ -16234,13 +17108,14 @@
|
|
|
16234
17108
|
* @param reverse true=撤销,false=重做
|
|
16235
17109
|
*/
|
|
16236
17110
|
applyHistoryStep(step, reverse) {
|
|
16237
|
-
const { id
|
|
16238
|
-
|
|
17111
|
+
const { id } = step;
|
|
17112
|
+
const { oldSchema, newSchema, changeRecords } = step.diff?.[0] ?? {};
|
|
17113
|
+
if (!oldSchema && newSchema) {
|
|
16239
17114
|
if (reverse) this.remove(`${id}`, { doNotPushHistory: true });
|
|
16240
17115
|
else this.add(cloneDeep$1(newSchema), { doNotPushHistory: true });
|
|
16241
17116
|
return;
|
|
16242
17117
|
}
|
|
16243
|
-
if (oldSchema && newSchema
|
|
17118
|
+
if (oldSchema && !newSchema) {
|
|
16244
17119
|
if (reverse) this.add(cloneDeep$1(oldSchema), { doNotPushHistory: true });
|
|
16245
17120
|
else this.remove(`${id}`, { doNotPushHistory: true });
|
|
16246
17121
|
return;
|
|
@@ -16891,7 +17766,7 @@
|
|
|
16891
17766
|
//#region packages/editor/src/initService.ts
|
|
16892
17767
|
var initServiceState = (props, { editorService, historyService, componentListService, propsService, eventsService, uiService, codeBlockService, keybindingService, dataSourceService, depService }) => {
|
|
16893
17768
|
(0, vue.watch)(() => props.modelValue, (modelValue) => {
|
|
16894
|
-
editorService.set("root", modelValue || null);
|
|
17769
|
+
editorService.set("root", modelValue || null, { historySource: "initial" });
|
|
16895
17770
|
}, { immediate: true });
|
|
16896
17771
|
(0, vue.watch)(() => props.disabledMultiSelect, (disabledMultiSelect) => {
|
|
16897
17772
|
editorService.set("disabledMultiSelect", disabledMultiSelect || false);
|
|
@@ -22166,6 +23041,7 @@
|
|
|
22166
23041
|
exports.H_GUIDE_LINE_STORAGE_KEY = H_GUIDE_LINE_STORAGE_KEY;
|
|
22167
23042
|
exports.HistoryDiffDialog = HistoryDiffDialog_default;
|
|
22168
23043
|
exports.HistoryListBucket = Bucket_default;
|
|
23044
|
+
exports.HistoryListBucketTab = BucketTab_default;
|
|
22169
23045
|
exports.Icon = Icon_default;
|
|
22170
23046
|
exports.IdleTask = IdleTask;
|
|
22171
23047
|
exports.KeyBindingCommand = KeyBindingCommand;
|
|
@@ -22215,17 +23091,24 @@
|
|
|
22215
23091
|
exports.classifyDragSources = classifyDragSources;
|
|
22216
23092
|
exports.codeBlockService = codeBlock_default;
|
|
22217
23093
|
exports.collectRelatedNodes = collectRelatedNodes;
|
|
23094
|
+
exports.createStackStep = createStackStep;
|
|
22218
23095
|
exports.dataSourceService = dataSource_default;
|
|
22219
23096
|
exports.debug = debug;
|
|
22220
23097
|
exports.default = plugin_default;
|
|
22221
23098
|
exports.defaultIsExpandable = defaultIsExpandable;
|
|
22222
23099
|
exports.depService = dep_default;
|
|
23100
|
+
exports.describeRevertStep = describeRevertStep;
|
|
23101
|
+
exports.describeStepForRevert = describeStepForRevert;
|
|
23102
|
+
exports.deserializeStacks = deserializeStacks;
|
|
22223
23103
|
Object.defineProperty(exports, "designPlugin", {
|
|
22224
23104
|
enumerable: true,
|
|
22225
23105
|
get: function() {
|
|
22226
23106
|
return _tmagic_design.default;
|
|
22227
23107
|
}
|
|
22228
23108
|
});
|
|
23109
|
+
exports.detectPageTargetId = detectPageTargetId;
|
|
23110
|
+
exports.detectPageTargetName = detectPageTargetName;
|
|
23111
|
+
exports.detectStackOpType = detectStackOpType;
|
|
22229
23112
|
exports.displayTabConfig = displayTabConfig;
|
|
22230
23113
|
exports.editorNodeMergeCustomizer = editorNodeMergeCustomizer;
|
|
22231
23114
|
exports.editorService = editor_default;
|
|
@@ -22256,21 +23139,31 @@
|
|
|
22256
23139
|
exports.getGuideLineFromCache = getGuideLineFromCache;
|
|
22257
23140
|
exports.getInitPositionStyle = getInitPositionStyle;
|
|
22258
23141
|
exports.getNodeIndex = getNodeIndex;
|
|
23142
|
+
exports.getOrCreateStack = getOrCreateStack;
|
|
22259
23143
|
exports.getPageFragmentList = getPageFragmentList;
|
|
22260
23144
|
exports.getPageList = getPageList;
|
|
22261
23145
|
exports.getPageNameList = getPageNameList;
|
|
22262
23146
|
exports.getPositionInContainer = getPositionInContainer;
|
|
22263
23147
|
exports.getRelativeStyle = getRelativeStyle;
|
|
22264
23148
|
exports.historyService = history_default;
|
|
23149
|
+
exports.idbDelete = idbDelete;
|
|
23150
|
+
exports.idbGet = idbGet;
|
|
23151
|
+
exports.idbSet = idbSet;
|
|
22265
23152
|
exports.info = info;
|
|
22266
23153
|
exports.isIncludeDataSource = isIncludeDataSource;
|
|
23154
|
+
exports.isIndexedDBSupported = isIndexedDBSupported;
|
|
22267
23155
|
exports.loadMonaco = monaco_editor_default;
|
|
22268
23156
|
exports.log = log;
|
|
23157
|
+
exports.markStackSaved = markStackSaved;
|
|
23158
|
+
exports.mergePageSteps = mergePageSteps;
|
|
23159
|
+
exports.mergeStackSteps = mergeStackSteps;
|
|
22269
23160
|
exports.moveItemsInContainer = moveItemsInContainer;
|
|
22270
23161
|
exports.numberOptions = numberOptions;
|
|
23162
|
+
exports.openIndexedDB = openIndexedDB;
|
|
22271
23163
|
exports.propsService = props_default;
|
|
22272
23164
|
exports.resolveSelectedNode = resolveSelectedNode;
|
|
22273
23165
|
exports.serializeConfig = serializeConfig;
|
|
23166
|
+
exports.serializeStacks = serializeStacks;
|
|
22274
23167
|
exports.setChildrenLayout = setChildrenLayout;
|
|
22275
23168
|
exports.setEditorConfig = setEditorConfig;
|
|
22276
23169
|
exports.setLayout = setLayout;
|
|
@@ -22285,6 +23178,7 @@
|
|
|
22285
23178
|
});
|
|
22286
23179
|
exports.toggleFixedPosition = toggleFixedPosition;
|
|
22287
23180
|
exports.uiService = ui_default;
|
|
23181
|
+
exports.undoFloor = undoFloor;
|
|
22288
23182
|
exports.updateStatus = updateStatus;
|
|
22289
23183
|
exports.useCodeBlockEdit = useCodeBlockEdit;
|
|
22290
23184
|
exports.useEditorContentHeight = useEditorContentHeight;
|