唯杰地图 logo唯杰地图
VJMAP
EN

command-events

vjcad/references/event/command-events.md 4.0 KB106 行
原文

本文回答:枚举里有 4 个命令事件,但实际派发的只有 3 个:CommandStarting(前,可取消)/ CommandStarted(后)/ CommandEnded(结束,args {commandName, success, duration})。CommandCancelled 是未派发的保留事件——按 ESC 退出命令同样触发 CommandEnded(success=false 仅表示 main() 抛了异常),"是否被取消"需由命令自身判断。常用于操作日志、自动化、命令钩子。

一、事件清单

事件 说明 可取消
CommandStarting 命令开始前 是
CommandStarted 命令开始后 否
CommandEnded 命令结束(正常完成、ESC 退出、main() 抛异常都触发;success=false 仅表示抛了异常) 否
CommandCancelled ✗ 未派发(枚举保留成员,订阅永不触发) —

MCP 参考:vjcad/doc/event/event-types.md;派发点在 invokeCommandWithOp(只 emit Starting/Started/Ended)。

二、最小用法

import { Engine, CadEvents } from 'vjcad';

Engine.eventManager.on(CadEvents.CommandStarted, (args) => {
  console.log('命令开始:', args.commandName);
});

Engine.eventManager.on(CadEvents.CommandEnded, (args) => {
  // ESC 取消也走这里;success 只区分 main() 是否抛异常
  console.log('命令结束:', args.commandName, args.success, args.duration + 'ms');
});

MCP 参考:vjcad/example/event/04commandevents.js、vjcad/doc/event/event-usage.md。

三、操作日志

Engine.eventManager.on(CadEvents.CommandEnded, (args) => {
  log(`用户执行了命令: ${args.commandName}`, new Date());
});

四、阻止特定命令

const blocked = new Set(['EXPORTDWG', 'PURGE']);

Engine.eventManager.on(CadEvents.CommandStarting, (args) => {
  if (blocked.has(args.commandName)) {
    args.cancel = true;
    alert(`命令 ${args.commandName} 已被禁用`);
  }
});

MCP 参考:vjcad/doc/event/event-usage.md。

五、配合 PLINE / SPLINE 等交互式命令

let activePline = null;

Engine.eventManager.on(CadEvents.CommandStarted, (args) => {
  if (args.commandName === 'PLINE') activePline = null;
});

Engine.eventManager.on(CadEvents.EntityAdded, (args) => {
  if (args.entity.type === 'PLINE') activePline = args.entity;
});

// 正常结束与 ESC 退出都只触发 CommandEnded(CommandCancelled 不派发)
Engine.eventManager.on(CadEvents.CommandEnded, (args) => {
  if (args.commandName === 'PLINE' && activePline) {
    console.log('最终点数:', activePline.bulgePoints.items.length);
  }
  activePline = null;
});

MCP 参考:vjcad/example/event/06plinepoints.js,详见 pline-timing。

六、用 CommandEnded 做"绘图后处理"

如果在 EntityAdded 里改实体属性,会被后续的命令交互再覆盖(PLINE 加点会重置某些字段)。最稳的做法是在 CommandEnded 里改:

Engine.eventManager.on(CadEvents.CommandEnded, (args) => {
  if (args.commandName === 'CIRCLE') {
    const last = Engine.getEntities(e => e.type === 'CIRCLE').slice(-1)[0];
    if (last) {
      last.color = 1;
      last.layer = '装饰层';
      last.setModified();
    }
  }
});

反例

  • 在 CommandStarting 里弹出 confirm():阻塞主线程,所有命令变慢。
  • 不分 Started / Ended,把统计逻辑放在 Started:命令还没执行就被计数。注意 Ended 同样无法区分"完成"和"ESC 取消",要统计完成数需自行判断(如命令前后实体数 / UndoStackChanged)。
  • 订阅 CommandCancelled 处理取消分支:该事件不派发,分支永远不执行。
  • args.commandName 大小写不一致:vjcad 命令名一般是大写('PLINE'、'CIRCLE'),写 'pline' 比较不上。

参考(官方文档 MCP)

  • 文档:vjcad/doc/event/event-types.md、vjcad/doc/event/event-usage.md
  • 示例:vjcad/example/event/04commandevents.js、06plinepoints.js