import{ax as i,z as a,A as n,b5 as l}from"./chunks/framework.DRScawWW.js";const y=JSON.parse('{"title":"historyService事件","description":"","frontmatter":{},"headers":[],"relativePath":"api/editor/historyServiceEvents.md","filePath":"api/editor/historyServiceEvents.md"}'),h={name:"api/editor/historyServiceEvents.md"};function k(p,s,t,e,d,r){return n(),a("div",null,[...s[0]||(s[0]=[l(`
详情: 页面历史记录发生变化(page 类型 push / undo / redo 成功时触发;与 code-block-history-change / data-source-history-change 同构)
事件回调函数: (pageId: Id, step: StepValue) => void
/**
* 页面节点历史记录条目(\`diff\` 内容为 {@link MNode})。结构已与代码块 / 数据源统一收敛到
* {@link BaseStepValue}:关联 id 见 \`data.id\`,选区等上下文见 \`extra\`。
*/
export type StepValue = BaseStepValue<MNode, StepExtra>;/**
* 历史记录条目公共字段,被 {@link StepValue} / {@link CodeBlockStepValue} / {@link DataSourceStepValue} 复用。
*
* 泛型 \`T\` 为 \`diff\` 中变化内容的快照类型(页面节点 \`MNode\` / 代码块 \`CodeBlockContent\` / 数据源 \`DataSourceSchema\`)。
*/
export interface BaseStepValue<T = unknown, U extends Record<string, any> = {}> {
/**
* 历史记录唯一标识(uuid)。入栈时自动写入(若调用方未指定),
* 用于精确定位 / 引用某一条历史记录(如 revert、埋点、跨端同步等)。
* 注意与 \`data.id\`(关联的页面 / 代码块 / 数据源 id)区分。
*/
uuid: string;
/**
* 关联目标信息:\`id\` 为关联的页面 / 代码块 / 数据源等资源 id(也是历史栈的分组 key),
* \`name\` 为展示名。所有历史类型统一携带。
*/
data: { name: string; id: Id };
/** 操作类型:新增 / 删除 / 更新(三类历史记录统一携带)。 */
opType: HistoryOpType;
/**
* 本次变更的内容(统一 diff 表达),每项见 {@link StepDiffItem}。
* 页面节点(add/remove 多节点、update 多节点)会有多项,代码块 / 数据源通常只有一项。
*/
diff: StepDiffItem<T>[];
/**
* 调用方可选传入的人类可读描述(如「调整按钮颜色」),用于历史面板展示。
* 不影响 undo/redo 行为;缺省时面板会根据节点 / propPath 自动生成描述。
*/
historyDescription?: string;
/**
* 操作途径:标记本次变更由哪条交互入口触发,取值见 {@link HistoryOpSource}
* (画布 / 树面板 / 组件面板 / 配置面板 / 源码编辑器 / 右键菜单 / 工具栏 / 快捷键 / 回滚 / 接口 等)。
* 仅用于历史面板展示与业务埋点,不影响 undo/redo 行为;缺省时面板视为「未知」。
*/
source?: HistoryOpSource;
/**
* 入栈时间戳(毫秒)。入栈时自动写入(若调用方未指定),仅用于历史面板展示。
*/
timestamp?: number;
/**
* 是否为「已保存」记录:DSL 落库(如保存到后端 / 本地)时由 historyService.markSaved 标记。
* 同一栈内任意时刻最多只有一条记录为 true;从 IndexedDB 恢复时游标会被定位到最近一条已保存记录之后。
*/
saved?: boolean;
/**
* 是否为「整体设置 root」(set root)产生的记录(由 {@link Editor.pushRootDiffHistory} 写入)。
* 用于「连续 set root 合并」:当某页栈最新一条已是 root 记录时,下一条 set root 会替换它而非新增,
* 避免源码反复保存 / 外部重设 DSL 时堆积多条 root 记录。
*/
rootStep?: boolean;
/** 操作人 */
operator?: string;
/** 扩展信息 */
extra?: U;
}/**
* 历史记录的扩展上下文({@link BaseStepValue.extra})。
* 内置字段供 \`page\` 类型在撤销 / 重做时恢复选区与受影响节点;扩展类型可自由附加其它键。
*/
export interface StepExtra {
/** 操作前选中的节点 ID,用于撤销后恢复选择状态(page 类型) */
selectedBefore?: Id[];
/** 操作后选中的节点 ID,用于重做后恢复选择状态(page 类型) */
selectedAfter?: Id[];
/** 本次操作涉及的节点 id 集合(page 类型) */
modifiedNodeIds?: Map<Id, Id>;
[key: string]: any;
}/**
* 历史记录操作类型:
* - \`add\` / \`remove\` / \`update\`:普通可撤销/重做的节点变更;
* - \`initial\`:页面「未修改的初始状态」基线(设置 root 时生成),作为页面栈 index 0 的固定底线 step。
* 该 step 不可被撤销/回滚(cursor 不会低于它),仅用于历史面板底部的初始行展示。
*/
export type HistoryOpType = 'add' | 'remove' | 'update' | 'initial';/**
* 历史记录的「操作途径」——标记本次变更由哪条交互入口触发,仅用于历史面板展示 / 业务埋点,
* 不影响 undo/redo 行为。缺省(未传)时 UI 视为「未知」。
*
* - \`stage\`:画布(拖拽 / 缩放 / 排序等舞台直接操作)
* - \`tree\`:树形面板(图层 / 数据源 / 代码块等树形结构里的拖拽 / 菜单操作)
* - \`component-panel\`:组件面板(左侧组件列表点击 / 拖拽新增组件)
* - \`props\`:配置面板表单(属性表单字段编辑)
* - \`code\`:源码编辑器(配置面板「源码」面板里直接编辑 JSON/代码后保存)
* - \`stage-contextmenu\`:画布右键菜单(舞台上节点的右键上下文菜单)
* - \`tree-contextmenu\`:树面板右键菜单(图层 / 数据源 / 代码块等树形列表上的右键上下文菜单)
* - \`toolbar\`:工具栏菜单(顶部导航工具栏按钮)
* - \`shortcut\`:键盘快捷键
* - \`rollback\`:历史回滚(历史面板里对某条历史「回滚」,反向应用为一条新记录,类 git revert)
* - \`api\`:代码 / 接口调用(程序化触发)
* - \`ai\`:AI 生成 / 智能助手触发的变更
* - \`unknown\`:未知来源
*
* 通过 \`(string & {})\` 允许业务侧扩展自定义途径字符串,同时保留内置值的自动补全。
*/
export type HistoryOpSource =
| 'initial'
| 'stage'
| 'tree'
| 'component-panel'
| 'props'
| 'code'
| 'root-code'
| 'stage-contextmenu'
| 'tree-contextmenu'
| 'toolbar'
| 'shortcut'
| 'rollback'
| 'api'
| 'ai'
// 同步
| 'sync'
| 'unknown'
| (string & {});export type Id = string | number;export type MNode = MComponent | MContainer | MIteratorContainer | MPage | MApp | MPageFragment;TIP
回调签名已与其它历史类型统一为 (id, step)。当游标处于历史栈边界(已无法继续撤销 / 重做)时 undo / redo 返回 null,此时不会触发该事件。
详情: 通过 setMarker 为某个历史栈种入 initial 基线时触发(适用于所有类型)
事件回调函数: (id: Id, marker: StepValue, stepType: HistoryStepType) => void
详情: 调用 clear 清空历史栈时触发(适用于所有类型)
事件回调函数: (id: Id | undefined, stepType: HistoryStepType) => void
TIP
id 缺省(清空 stepType 下全部栈)时回调的 id 为 undefined。
详情: 代码块历史记录发生变化(push('codeBlock', step, codeBlockId) / undo('codeBlock', id) / redo('codeBlock', id) 成功时触发)
事件回调函数: (codeBlockId: Id, step: CodeBlockStepValue) => void
/**
* 代码块历史记录条目(\`diff\` 内容为 {@link CodeBlockContent}),按 \`data.id\`(codeBlock.id)
* 分组保存到 historyState.steps.codeBlock。结构与 {@link StepValue} / {@link DataSourceStepValue}
* 一致,仅 \`diff\` 快照类型不同。
*/
export type CodeBlockStepValue = BaseStepValue<CodeBlockContent>;/**
* 历史记录条目公共字段,被 {@link StepValue} / {@link CodeBlockStepValue} / {@link DataSourceStepValue} 复用。
*
* 泛型 \`T\` 为 \`diff\` 中变化内容的快照类型(页面节点 \`MNode\` / 代码块 \`CodeBlockContent\` / 数据源 \`DataSourceSchema\`)。
*/
export interface BaseStepValue<T = unknown, U extends Record<string, any> = {}> {
/**
* 历史记录唯一标识(uuid)。入栈时自动写入(若调用方未指定),
* 用于精确定位 / 引用某一条历史记录(如 revert、埋点、跨端同步等)。
* 注意与 \`data.id\`(关联的页面 / 代码块 / 数据源 id)区分。
*/
uuid: string;
/**
* 关联目标信息:\`id\` 为关联的页面 / 代码块 / 数据源等资源 id(也是历史栈的分组 key),
* \`name\` 为展示名。所有历史类型统一携带。
*/
data: { name: string; id: Id };
/** 操作类型:新增 / 删除 / 更新(三类历史记录统一携带)。 */
opType: HistoryOpType;
/**
* 本次变更的内容(统一 diff 表达),每项见 {@link StepDiffItem}。
* 页面节点(add/remove 多节点、update 多节点)会有多项,代码块 / 数据源通常只有一项。
*/
diff: StepDiffItem<T>[];
/**
* 调用方可选传入的人类可读描述(如「调整按钮颜色」),用于历史面板展示。
* 不影响 undo/redo 行为;缺省时面板会根据节点 / propPath 自动生成描述。
*/
historyDescription?: string;
/**
* 操作途径:标记本次变更由哪条交互入口触发,取值见 {@link HistoryOpSource}
* (画布 / 树面板 / 组件面板 / 配置面板 / 源码编辑器 / 右键菜单 / 工具栏 / 快捷键 / 回滚 / 接口 等)。
* 仅用于历史面板展示与业务埋点,不影响 undo/redo 行为;缺省时面板视为「未知」。
*/
source?: HistoryOpSource;
/**
* 入栈时间戳(毫秒)。入栈时自动写入(若调用方未指定),仅用于历史面板展示。
*/
timestamp?: number;
/**
* 是否为「已保存」记录:DSL 落库(如保存到后端 / 本地)时由 historyService.markSaved 标记。
* 同一栈内任意时刻最多只有一条记录为 true;从 IndexedDB 恢复时游标会被定位到最近一条已保存记录之后。
*/
saved?: boolean;
/**
* 是否为「整体设置 root」(set root)产生的记录(由 {@link Editor.pushRootDiffHistory} 写入)。
* 用于「连续 set root 合并」:当某页栈最新一条已是 root 记录时,下一条 set root 会替换它而非新增,
* 避免源码反复保存 / 外部重设 DSL 时堆积多条 root 记录。
*/
rootStep?: boolean;
/** 操作人 */
operator?: string;
/** 扩展信息 */
extra?: U;
}/**
* 历史记录的「操作途径」——标记本次变更由哪条交互入口触发,仅用于历史面板展示 / 业务埋点,
* 不影响 undo/redo 行为。缺省(未传)时 UI 视为「未知」。
*
* - \`stage\`:画布(拖拽 / 缩放 / 排序等舞台直接操作)
* - \`tree\`:树形面板(图层 / 数据源 / 代码块等树形结构里的拖拽 / 菜单操作)
* - \`component-panel\`:组件面板(左侧组件列表点击 / 拖拽新增组件)
* - \`props\`:配置面板表单(属性表单字段编辑)
* - \`code\`:源码编辑器(配置面板「源码」面板里直接编辑 JSON/代码后保存)
* - \`stage-contextmenu\`:画布右键菜单(舞台上节点的右键上下文菜单)
* - \`tree-contextmenu\`:树面板右键菜单(图层 / 数据源 / 代码块等树形列表上的右键上下文菜单)
* - \`toolbar\`:工具栏菜单(顶部导航工具栏按钮)
* - \`shortcut\`:键盘快捷键
* - \`rollback\`:历史回滚(历史面板里对某条历史「回滚」,反向应用为一条新记录,类 git revert)
* - \`api\`:代码 / 接口调用(程序化触发)
* - \`ai\`:AI 生成 / 智能助手触发的变更
* - \`unknown\`:未知来源
*
* 通过 \`(string & {})\` 允许业务侧扩展自定义途径字符串,同时保留内置值的自动补全。
*/
export type HistoryOpSource =
| 'initial'
| 'stage'
| 'tree'
| 'component-panel'
| 'props'
| 'code'
| 'root-code'
| 'stage-contextmenu'
| 'tree-contextmenu'
| 'toolbar'
| 'shortcut'
| 'rollback'
| 'api'
| 'ai'
// 同步
| 'sync'
| 'unknown'
| (string & {});export interface CodeBlockContent {
/** 代码块名称 */
name: string;
/** 代码块内容 */
content: ((...args: any[]) => any) | Function;
/** 参数定义 */
params: CodeParam[] | [];
/** 注释 */
desc?: string;
/** 扩展字段 */
[propName: string]: any;
}export type Id = string | number;TIP
oldSchema 为 nullnewSchema 为 nullundo / redo 返回 null(边界状态)时不会触发该事件详情: 数据源历史记录发生变化(push('dataSource', step, dataSourceId) / undo('dataSource', id) / redo('dataSource', id) 成功时触发)
事件回调函数: (dataSourceId: Id, step: DataSourceStepValue) => void
/**
* 数据源历史记录条目(\`diff\` 内容为 {@link DataSourceSchema}),按 \`data.id\`(dataSource.id)
* 分组保存到 historyState.steps.dataSource。结构与 {@link StepValue} / {@link CodeBlockStepValue}
* 一致,仅 \`diff\` 快照类型不同。
*/
export type DataSourceStepValue = BaseStepValue<DataSourceSchema>;/**
* 历史记录条目公共字段,被 {@link StepValue} / {@link CodeBlockStepValue} / {@link DataSourceStepValue} 复用。
*
* 泛型 \`T\` 为 \`diff\` 中变化内容的快照类型(页面节点 \`MNode\` / 代码块 \`CodeBlockContent\` / 数据源 \`DataSourceSchema\`)。
*/
export interface BaseStepValue<T = unknown, U extends Record<string, any> = {}> {
/**
* 历史记录唯一标识(uuid)。入栈时自动写入(若调用方未指定),
* 用于精确定位 / 引用某一条历史记录(如 revert、埋点、跨端同步等)。
* 注意与 \`data.id\`(关联的页面 / 代码块 / 数据源 id)区分。
*/
uuid: string;
/**
* 关联目标信息:\`id\` 为关联的页面 / 代码块 / 数据源等资源 id(也是历史栈的分组 key),
* \`name\` 为展示名。所有历史类型统一携带。
*/
data: { name: string; id: Id };
/** 操作类型:新增 / 删除 / 更新(三类历史记录统一携带)。 */
opType: HistoryOpType;
/**
* 本次变更的内容(统一 diff 表达),每项见 {@link StepDiffItem}。
* 页面节点(add/remove 多节点、update 多节点)会有多项,代码块 / 数据源通常只有一项。
*/
diff: StepDiffItem<T>[];
/**
* 调用方可选传入的人类可读描述(如「调整按钮颜色」),用于历史面板展示。
* 不影响 undo/redo 行为;缺省时面板会根据节点 / propPath 自动生成描述。
*/
historyDescription?: string;
/**
* 操作途径:标记本次变更由哪条交互入口触发,取值见 {@link HistoryOpSource}
* (画布 / 树面板 / 组件面板 / 配置面板 / 源码编辑器 / 右键菜单 / 工具栏 / 快捷键 / 回滚 / 接口 等)。
* 仅用于历史面板展示与业务埋点,不影响 undo/redo 行为;缺省时面板视为「未知」。
*/
source?: HistoryOpSource;
/**
* 入栈时间戳(毫秒)。入栈时自动写入(若调用方未指定),仅用于历史面板展示。
*/
timestamp?: number;
/**
* 是否为「已保存」记录:DSL 落库(如保存到后端 / 本地)时由 historyService.markSaved 标记。
* 同一栈内任意时刻最多只有一条记录为 true;从 IndexedDB 恢复时游标会被定位到最近一条已保存记录之后。
*/
saved?: boolean;
/**
* 是否为「整体设置 root」(set root)产生的记录(由 {@link Editor.pushRootDiffHistory} 写入)。
* 用于「连续 set root 合并」:当某页栈最新一条已是 root 记录时,下一条 set root 会替换它而非新增,
* 避免源码反复保存 / 外部重设 DSL 时堆积多条 root 记录。
*/
rootStep?: boolean;
/** 操作人 */
operator?: string;
/** 扩展信息 */
extra?: U;
}/**
* 历史记录的「操作途径」——标记本次变更由哪条交互入口触发,仅用于历史面板展示 / 业务埋点,
* 不影响 undo/redo 行为。缺省(未传)时 UI 视为「未知」。
*
* - \`stage\`:画布(拖拽 / 缩放 / 排序等舞台直接操作)
* - \`tree\`:树形面板(图层 / 数据源 / 代码块等树形结构里的拖拽 / 菜单操作)
* - \`component-panel\`:组件面板(左侧组件列表点击 / 拖拽新增组件)
* - \`props\`:配置面板表单(属性表单字段编辑)
* - \`code\`:源码编辑器(配置面板「源码」面板里直接编辑 JSON/代码后保存)
* - \`stage-contextmenu\`:画布右键菜单(舞台上节点的右键上下文菜单)
* - \`tree-contextmenu\`:树面板右键菜单(图层 / 数据源 / 代码块等树形列表上的右键上下文菜单)
* - \`toolbar\`:工具栏菜单(顶部导航工具栏按钮)
* - \`shortcut\`:键盘快捷键
* - \`rollback\`:历史回滚(历史面板里对某条历史「回滚」,反向应用为一条新记录,类 git revert)
* - \`api\`:代码 / 接口调用(程序化触发)
* - \`ai\`:AI 生成 / 智能助手触发的变更
* - \`unknown\`:未知来源
*
* 通过 \`(string & {})\` 允许业务侧扩展自定义途径字符串,同时保留内置值的自动补全。
*/
export type HistoryOpSource =
| 'initial'
| 'stage'
| 'tree'
| 'component-panel'
| 'props'
| 'code'
| 'root-code'
| 'stage-contextmenu'
| 'tree-contextmenu'
| 'toolbar'
| 'shortcut'
| 'rollback'
| 'api'
| 'ai'
// 同步
| 'sync'
| 'unknown'
| (string & {});export type Id = string | number;TIP
oldSchema 为 nullnewSchema 为 nullundo / redo 返回 null(边界状态)时不会触发该事件详情: 调用 markSaved 标记「已保存」记录时触发
事件回调函数: (payload: { kind: 'all' | HistoryStepType; id?: Id }) => void
TIP
markSaved(stepType)(缺省 id)触发时 kind 为 all,无 id(此时 stepType 不生效)markSaved(stepType, id) 触发时 kind 为对应的 stepType(page / codeBlock / dataSource / 扩展),id 为目标栈 id详情: saveToIndexedDB 把历史记录写入本地 IndexedDB 成功时触发
事件回调函数: (snapshot: PersistedHistoryState) => void
/**
* 历史记录的可持久化快照。由 historyService.saveToIndexedDB 写入 IndexedDB,
* 再由 historyService.restoreFromIndexedDB 读出并重建各 UndoRedo 栈。
*/
export interface PersistedHistoryState {
/** 快照结构版本号,便于后续兼容升级。 */
version: number;
/**
* 全部历史栈的序列化快照,按「类型 -> id」两级分组,与 {@link HistorySteps} 对应。
* 内置 \`page\` / \`codeBlock\` / \`dataSource\`,并包含业务注册的扩展类型。
*/
steps: {
page: Record<Id, SerializedUndoRedo<StepValue>>;
codeBlock: Record<Id, SerializedUndoRedo<CodeBlockStepValue>>;
dataSource: Record<Id, SerializedUndoRedo<DataSourceStepValue>>;
[stepType: string]: Record<Id, SerializedUndoRedo<any>>;
};
/** 保存时间戳(毫秒)。 */
savedAt: number;
}/**
* UndoRedo 栈的可序列化快照,用于持久化(如写入 IndexedDB)后再还原。
*/
export interface SerializedUndoRedo<T = any> {
/** 栈内全部元素(按时间正序,索引 0 为最早一步)。 */
elementList: T[];
/** 游标位置(已应用步骤数量)。 */
listCursor: number;
/** 栈容量上限。 */
listMaxSize: number;
}详情: restoreFromIndexedDB 从本地 IndexedDB 读取并重建历史记录成功时触发(找不到记录时不触发)
事件回调函数: (snapshot: PersistedHistoryState) => void
/**
* 历史记录的可持久化快照。由 historyService.saveToIndexedDB 写入 IndexedDB,
* 再由 historyService.restoreFromIndexedDB 读出并重建各 UndoRedo 栈。
*/
export interface PersistedHistoryState {
/** 快照结构版本号,便于后续兼容升级。 */
version: number;
/**
* 全部历史栈的序列化快照,按「类型 -> id」两级分组,与 {@link HistorySteps} 对应。
* 内置 \`page\` / \`codeBlock\` / \`dataSource\`,并包含业务注册的扩展类型。
*/
steps: {
page: Record<Id, SerializedUndoRedo<StepValue>>;
codeBlock: Record<Id, SerializedUndoRedo<CodeBlockStepValue>>;
dataSource: Record<Id, SerializedUndoRedo<DataSourceStepValue>>;
[stepType: string]: Record<Id, SerializedUndoRedo<any>>;
};
/** 保存时间戳(毫秒)。 */
savedAt: number;
}