historyService事件
change
详情: 页面历史记录发生变化(
page类型push/undo/redo成功时触发;与code-block-history-change/data-source-history-change同构)事件回调函数:
(pageId: Id, step: StepValue) => void查看 StepValue 及关联类型定义
ts/** * 页面节点历史记录条目(`diff` 内容为 {@link MNode})。结构已与代码块 / 数据源统一收敛到 * {@link BaseStepValue}:关联 id 见 `data.id`,选区等上下文见 `extra`。 */ export type StepValue = BaseStepValue<MNode, StepExtra>;ts/** * 历史记录条目公共字段,被 {@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; }ts/** * 历史记录的扩展上下文({@link BaseStepValue.extra})。 * 内置字段供 `page` 类型在撤销 / 重做时恢复选区与受影响节点;扩展类型可自由附加其它键。 */ export interface StepExtra { /** 操作前选中的节点 ID,用于撤销后恢复选择状态(page 类型) */ selectedBefore?: Id[]; /** 操作后选中的节点 ID,用于重做后恢复选择状态(page 类型) */ selectedAfter?: Id[]; /** 本次操作涉及的节点 id 集合(page 类型) */ modifiedNodeIds?: Map<Id, Id>; [key: string]: any; }ts/** * 历史记录操作类型: * - `add` / `remove` / `update`:普通可撤销/重做的节点变更; * - `initial`:页面「未修改的初始状态」基线(设置 root 时生成),作为页面栈 index 0 的固定底线 step。 * 该 step 不可被撤销/回滚(cursor 不会低于它),仅用于历史面板底部的初始行展示。 */ export type HistoryOpType = 'add' | 'remove' | 'update' | 'initial';ts/** * 历史记录的「操作途径」——标记本次变更由哪条交互入口触发,仅用于历史面板展示 / 业务埋点, * 不影响 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 & {});tsexport type Id = string | number;tsexport type MNode = MComponent | MContainer | MIteratorContainer | MPage | MApp | MPageFragment;TIP
回调签名已与其它历史类型统一为
(id, step)。当游标处于历史栈边界(已无法继续撤销 / 重做)时undo/redo返回null,此时不会触发该事件。
marker-change
详情: 通过
setMarker为某个历史栈种入initial基线时触发(适用于所有类型)事件回调函数:
(id: Id, marker: StepValue, stepType: HistoryStepType) => void
clear
详情: 调用
clear清空历史栈时触发(适用于所有类型)事件回调函数:
(id: Id | undefined, stepType: HistoryStepType) => voidTIP
id缺省(清空stepType下全部栈)时回调的id为undefined。
code-block-history-change
详情: 代码块历史记录发生变化(
push('codeBlock', step, codeBlockId)/undo('codeBlock', id)/redo('codeBlock', id)成功时触发)事件回调函数:
(codeBlockId: Id, step: CodeBlockStepValue) => void查看 CodeBlockStepValue 及关联类型定义
ts/** * 代码块历史记录条目(`diff` 内容为 {@link CodeBlockContent}),按 `data.id`(codeBlock.id) * 分组保存到 historyState.steps.codeBlock。结构与 {@link StepValue} / {@link DataSourceStepValue} * 一致,仅 `diff` 快照类型不同。 */ export type CodeBlockStepValue = BaseStepValue<CodeBlockContent>;ts/** * 历史记录条目公共字段,被 {@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; }ts/** * 历史记录的「操作途径」——标记本次变更由哪条交互入口触发,仅用于历史面板展示 / 业务埋点, * 不影响 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 & {});tsexport interface CodeBlockContent { /** 代码块名称 */ name: string; /** 代码块内容 */ content: ((...args: any[]) => any) | Function; /** 参数定义 */ params: CodeParam[] | []; /** 注释 */ desc?: string; /** 扩展字段 */ [propName: string]: any; }tsexport type Id = string | number;TIP
- 新增触发的 step 其 diff 项
oldSchema为null - 删除触发的 step 其 diff 项
newSchema为null undo/redo返回null(边界状态)时不会触发该事件
- 新增触发的 step 其 diff 项
data-source-history-change
详情: 数据源历史记录发生变化(
push('dataSource', step, dataSourceId)/undo('dataSource', id)/redo('dataSource', id)成功时触发)事件回调函数:
(dataSourceId: Id, step: DataSourceStepValue) => void查看 DataSourceStepValue 及关联类型定义
ts/** * 数据源历史记录条目(`diff` 内容为 {@link DataSourceSchema}),按 `data.id`(dataSource.id) * 分组保存到 historyState.steps.dataSource。结构与 {@link StepValue} / {@link CodeBlockStepValue} * 一致,仅 `diff` 快照类型不同。 */ export type DataSourceStepValue = BaseStepValue<DataSourceSchema>;ts/** * 历史记录条目公共字段,被 {@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; }ts/** * 历史记录的「操作途径」——标记本次变更由哪条交互入口触发,仅用于历史面板展示 / 业务埋点, * 不影响 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 & {});tsexport type Id = string | number;TIP
- 新增触发的 step 其 diff 项
oldSchema为null - 删除触发的 step 其 diff 项
newSchema为null undo/redo返回null(边界状态)时不会触发该事件
- 新增触发的 step 其 diff 项
mark-saved
详情: 调用
markSaved标记「已保存」记录时触发事件回调函数:
(payload: { kind: 'all' | HistoryStepType; id?: Id }) => voidTIP
markSaved(stepType)(缺省 id)触发时kind为all,无id(此时stepType不生效)markSaved(stepType, id)触发时kind为对应的stepType(page/codeBlock/dataSource/ 扩展),id为目标栈 id
save-to-indexed-db
详情:
saveToIndexedDB把历史记录写入本地 IndexedDB 成功时触发事件回调函数:
(snapshot: PersistedHistoryState) => void查看 PersistedHistoryState 类型定义
ts/** * 历史记录的可持久化快照。由 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; }ts/** * UndoRedo 栈的可序列化快照,用于持久化(如写入 IndexedDB)后再还原。 */ export interface SerializedUndoRedo<T = any> { /** 栈内全部元素(按时间正序,索引 0 为最早一步)。 */ elementList: T[]; /** 游标位置(已应用步骤数量)。 */ listCursor: number; /** 栈容量上限。 */ listMaxSize: number; }
restore-from-indexed-db
详情:
restoreFromIndexedDB从本地 IndexedDB 读取并重建历史记录成功时触发(找不到记录时不触发)事件回调函数:
(snapshot: PersistedHistoryState) => void查看 PersistedHistoryState 类型定义
ts/** * 历史记录的可持久化快照。由 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; }