execute-command
本文回答:
mapcadLayer.executeCommand/commandRegistry.repeatLast/lastCommandName—— 启动 / 重复 / 取消命令。
一、基本调用
mapcadLayer.executeCommand('LINE'); // 启动
mapcadLayer.executeCommand('DRAWORDER', { action: 'back' }); // 带选项(内置命令仅 TEXTEDIT/INSERT/DRAWORDER 读 opts)
返回 Promise<void>。命令启动后异步等待用户输入;不需要 await,也可以 await 等结束。
二、带选项
选项被 main(ctx, opts) 的第二个参数接收:
mapcadLayer.executeCommand('TEXTEDIT', { entity: someTextEnt }); // 跳过"选择实体"步骤
mapcadLayer.executeCommand('INSERT', { blockName: '灯具' });
mapcadLayer.executeCommand('DRAWORDER', { action: 'front' });
⚠️ 绝大多数内置命令不读 opts——v1.0.1 中只有 TEXTEDIT(opts.entity)、INSERT(opts.blockName)、DRAWORDER(opts.action)三个消费它;executeCommand('TEXT', { text, height }) 这类写法会被静默忽略。opts 主要给自定义命令用。
三、重复上一条
mapcadLayer.commandRegistry.repeatLast();
const last = mapcadLayer.commandRegistry.lastCommandName;
// → 'LINE'
键盘:repeatCommand 快捷键默认是 null(未绑定)——回车默认是 confirm 动作不是 repeat。要回车重复上一条:mapcadLayer.setShortcuts({ repeatCommand: 'enter' })(会顶掉 confirm 的回车)。
四、取消命令
mapcadLayer.inputManager.cancelCurrentInput();
对应的 getPoint / getSelections / ... Promise 会以 status: 'cancel' resolve,main 函数自然流程结束。
按 Esc 默认触发 cancel。右键行为分输入类型(右键只处理点输入与实体输入两种状态):getPoint 等待中右键 = cancel;getEntity({ multiple: true })(MOVE/COPY/ERASE 等内置编辑命令的选集步骤)等待中右键 = 确认当前选择(返回 OK + 已选实体,等同回车),单选 getEntity 右键 = cancel;getSelections 等待中右键无反应——用回车/空格,或单击空白处结束选择。
五、错误处理
await mapcadLayer.executeCommand('UNKNOWN_CMD');
// 不抛异常:console 输出警告 `[vjmapext] Unknown command: UNKNOWN_CMD`,直接 return
注意:命令名不存在不会 throw(warn + return,Promise 正常 resolve)。想兜底:
const names = mapcadLayer.commandRegistry.getAll().map(c => c.name);
if (!names.includes('MYCMD')) console.error('命令未注册');
main抛异常 → 也被吞掉:console.error('[vjmapext] Command XXX error:', err),Promise 照样 resolve;finally 里会endTransaction+ 清理_activeCommand,command:ended照发(实采)。command:ended的 payload 只有{ name },成功/取消/异常一律在 finally 里发出,无法据此判断结果;要结果请在main里自行 try/catch、eventBus.emit业务事件,或配合entity:added统计产出。- 失败的命令不进历史(实采):
lastCommandName只在main正常结束时更新;main抛错后repeatLast()重放的是上一条成功的命令。 - browse 模式静默空转(实采):
setMode('browse')下executeCommand/repeatLastCommand直接resolve()——不执行、不报错、不发command:started。批量脚本里若误留 browse 态,命令全部静默跳过。
六、查看所有已注册命令
// 低级 API
for (const cmd of mapcadLayer.commandRegistry.getAll()) {
console.log(cmd.name, cmd.description);
}
或结合 getShortcuts()(返回动作→键位映射,见 shortcuts):
const shortcuts = mapcadLayer.getShortcuts();
// { undo: 'ctrl+z', cancel: 'escape', ... }
七、命令互斥
同一时刻只能有一条命令在执行。启动新命令会:
- 取消旧命令(
cancelCurrentInput); - 清除旧命令残留的预览 / 高亮;
- 启动新命令。
这是特性不是 bug:工具栏切换时不必手动清理。
八、延迟 / 定时启动
setTimeout(() => mapcadLayer.executeCommand('LINE'), 100);
常见用途:UI 面板弹出后再启动对应绘图命令,避免 UI 动画吃掉第一次 click。
九、组合调用
await mapcadLayer.executeCommand('LINE'); // 等画完一条线
await mapcadLayer.executeCommand('CIRCLE'); // 再画圆
// 注意:中间用户有可能取消;上面 await 只是等 command 的流程结束,并不等价于"成功"
十、常见坑
- await 里等不到用户输入:命令内部有用户交互,
executeCommand不返回"用户确定";command:ended(payload 只有{ name })也只说明"结束了",成功与否要靠entity:added或命令自己 emit 的业务事件判断。 - 不能并发:两次
executeCommand并发时,第二次会取消第一次。 - 空闲按回车没触发:需要
mapcadLayer.getMapContainer()?.focus()聚焦容器。 - 右键菜单多次执行 LINE:注意菜单回调里的
executeCommand会重复启动命令,取消当前再启动新的。
相关
- 内置绘图 → builtin-draw
- 输入模块 → input-manager
- 事件 → event/bus-command-mode