description
本文回答:操作描述 = 给撤销组附加一段文本,会显示在 撤销 / 重做 按钮 tooltip、历史下拉、命令行消息上。三种传值方式:① 字符串简写
'修改颜色';② 完整UndoDescriptor{ category, i18nKey?, resolvedText?, sourceCommand? };③ 不传 → 在命令上下文里自动从Engine.editor.currentCommandName推导。监听CadEvents.UndoStackChanged拿"下一步撤销/重做"的标签。
一、UndoDescriptor 结构
interface UndoDescriptor {
i18nKey?: string; // 国际化 key
params?: Record<string, string | number>; // i18n 参数(预留)
resolvedText?: string; // 已解析文本(最高优先级)
category: 'edit' | 'view' | 'system'; // 必填,分类
sourceCommand?: string; // 来源命令名
}
type UndoCategory = 'edit' | 'view' | 'system';
MCP 参考:vjcad/doc/undo/undo-redo.md。
二、三种传值
// 方式 1:字符串简写 = { category: 'edit', resolvedText: str }
Engine.startUndoRecord('修改颜色');
// 方式 2:i18n key(推荐多语言)
Engine.startUndoRecord({
category: 'edit',
i18nKey: 'undo.modify.color'
});
// 方式 3:明确来源命令
Engine.startUndoRecord({
category: 'edit',
sourceCommand: 'MYCMD'
});
// 方式 4:在命令上下文里不传 → 自动推导
class MyCommand {
async main() {
Engine.startUndoRecord(); // 自动 = 命令的 description / name
try { /* ... */ } finally { Engine.endUndoRecord(); }
}
}
MCP 参考:vjcad/doc/undo/undo-redo.md、vjcad/example/undo/04description.js。
三、解析优先级
显示 label 时按以下顺序查找:
resolvedText— 直接使用i18nKey— 通过t()翻译sourceCommand— 命令名兜底- 通用文案 — "撤销" / "重做"
MCP 参考:vjcad/doc/undo/undo-redo.md。
四、自动推导(命令上下文)
不传 description 时,系统按以下顺序推导:
Engine.editor.currentCommandName- 从
CommandRegistry查找命令定义 - 用
CommandDefinition.description或CommandDefinition.name当resolvedText
适用:通过 editor.executerWithOp() 执行的命令(Editor 上是 executerWithOp/invokeCommandWithOp——executeCommand 是 PluginContext 的方法,不是 Editor 的);不适用:属性面板、对话框等非命令上下文(必须显式传 description)。
MCP 参考:vjcad/doc/undo/undo-redo.md。
五、查询撤销 / 重做历史
const u = Engine.undoManager;
const undoHistory = u.getUndoHistory();
console.log('共有', undoHistory.length, '步可撤销');
undoHistory.forEach((item, i) => {
const desc = item.description;
const label = desc?.resolvedText || desc?.i18nKey || '(无描述)';
console.log(`${i + 1}. ${label} 分组=${item.isGroup}`);
});
// 重做历史
const redoHistory = u.getRedoHistory();
// 步数
const undoCount = u.getUndoCount();
const redoCount = u.getRedoCount();
// 最后一次撤销 / 重做的描述
console.log(u.lastUndoDescription);
console.log(u.lastRedoDescription);
UndoHistoryItem 结构:
interface UndoHistoryItem {
description?: UndoDescriptor;
index: number; // 在历史栈中的索引
isGroup: boolean; // 是否为分组操作
}
MCP 参考:vjcad/doc/undo/undo-redo.md、vjcad/example/undo/04description.js。
六、按名称撤销 / 重做
u.undoSteps('绘制直线'); // 撤销到最近一次匹配(含),无匹配则不执行
u.redoSteps('绘制圆'); // 同理
u.undoSteps('不存在的'); // 返回 0,不执行
u.undoSteps(3, { silent: true }); // 静默:只抑制逐步的 UndoStackChanged(结束仍派发一次);UndoManager 本就不写命令行
MCP 参考:vjcad/example/undo/04description.js。
七、监听撤销栈变更(UI 必备)
import { CadEventManager, CadEvents } from 'vjcad';
CadEventManager.getInstance().on(CadEvents.UndoStackChanged, (args) => {
console.log('撤销步数:', args.undoCount);
console.log('重做步数:', args.redoCount);
console.log('下一步撤销:', args.nextUndoLabel);
console.log('下一步重做:', args.nextRedoLabel);
});
事件参数:
interface UndoStackChangedEventArgs {
document: any;
undoCount: number;
redoCount: number;
nextUndoLabel?: string; // 已翻译
nextRedoLabel?: string; // 已翻译
}
MCP 参考:vjcad/doc/undo/undo-redo.md、vjcad/example/undo/04description.js。
八、操作分类(category)
| 值 | 用途 | UI 展示 |
|---|---|---|
edit |
编辑操作(绘图、改属性) | 历史面板主列表 |
view |
视图操作(缩放、平移、UCS) | 历史面板折叠组 |
system |
系统操作(预留) | — |
MCP 参考:vjcad/doc/undo/undo-redo.md。
反例
- 不传 description 但又不在命令上下文(属性面板、对话框):UI 显示 "撤销" 兜底文案,看不出做了什么。
- 用
i18nKey但 i18n 字典里没注册:fallback 显示 key 本身(不友好)。 - 把不可撤销的视图操作也挂
category: 'edit':会污染编辑历史面板。
参考(官方文档 MCP)
- 文档:
vjcad/doc/undo/undo-redo.md - 示例:
vjcad/example/undo/04description.js