> **本文回答**：`mapcadLayer.setMode / toggleMode / getMode / setModeToggleShortcut` —— 编辑 / 浏览双模式切换（已对照 `vjmapext.d.ts` 与运行时核实）。

## 一、真实模式只有两个：`edit` | `browse`

```ts
type MapCadLayerMode = 'edit' | 'browse'
```

- `edit`（默认）：绘图/编辑/夹点全可用。
- `browse`：只读浏览——**不存在 `view`/`admin`/`inspector` 等第三档**。

切到 `browse` 时框架自动做三件事（`setMode` 内部）：

1. `inputManager.cancelCurrentInput()` —— 取消正在进行的命令/输入；
2. `store.clearSelection()` —— 清空选集；
3. 刷新显示级过滤 + `renderPipeline.forceFullRender()`，并发 `mode:changed` 事件。

browse 下的实际约束：

- `gripManager.getActiveGrips()` 直接返回 `[]` → **不显示夹点**；
- 输入管理器 `isBrowseMode()` 为 true → 绘制/编辑命令的输入流程被挡（属性面板里 "Display level (browse mode only)" 类选项也只在这时出现）；
- 实体拾取/框选输入被抑制。

## 二、切换 / 读取

```js
mapcadLayer.setMode('browse');        // 只读
mapcadLayer.setMode('edit');          // 恢复编辑
mapcadLayer.toggleMode();             // edit ↔ browse 往返
const cur = mapcadLayer.getMode();    // 'edit' | 'browse'
```

切换快捷键（默认 UI 有「Mode: {shortcut}」工具条提示）：

```js
mapcadLayer.setModeToggleShortcut('ctrl+e');   // 传 null 取消
```

> 模式切换键就是 `ShortcutMap` 里的 `modeToggle` 动作（默认 `'ctrl+shift+e'`）：`setModeToggleShortcut(k)` 与 `setShortcuts({ modeToggle: k })` 完全等价，`getShortcuts().modeToggle` 可读回（见 [shortcuts](shortcuts.md)）。

## 三、事件

```js
mapcadLayer.eventBus.on('mode:changed', ({ mode }) => {
  console.log('当前模式：', mode);          // payload 是 { mode }，不是 {from,to}
  myToolbar.update(mode === 'edit');        // 你自己的工具栏按它启用/禁用
});
```

## 四、UI 层典型用法

```js
mapcadLayer.eventBus.on('mode:changed', ({ mode }) => {
  const editing = mode === 'edit';
  document.querySelector('#tool-draw').style.display = editing ? '' : 'none';
  document.querySelector('#tool-edit').style.display = editing ? '' : 'none';
});

mapcadLayer.setMode(userHasEditPermission ? 'edit' : 'browse');
```

## 五、没有「按模式过滤命令」注册项

`commandRegistry.register(name, cmdClass, description?)` **只收 3 个参数，没有 `modes` 选项**。要在浏览模式拦命令，两条路：

- 依赖框架自带行为：browse 态输入被抑制，绘图/编辑命令走不下去；
- 自定义命令自己拦：`CommandContext` **没有 `layer` 字段**，在注册处闭包持有 layer 引用再判：

```js
const layer = mapcadLayer;
class GuardedCmd {
  async main(ctx) {   // 实例方法，不能写 static
    if (layer.getMode() === 'browse') return;
    // ...
  }
}
layer.commandRegistry.register('GUARDED', GuardedCmd);
```

## 六、mode 不是权限系统

| 层 | 作用 | 例 |
|---|---|---|
| mode | 前端 UX | 禁按钮 / 禁夹点 / 拦命令输入 |
| 后端权限 | 数据层 | 拒 save / 拒导出 |

**不要依赖 mode 做安全**——控制台 `mapcadLayer.setMode('edit')` 即可绕过；真正的权限必须在服务端校验。

## 七、常见坑

1. **切 browse 后工具栏按钮仍亮**：忘了监听 `mode:changed`；payload 键是 `mode`（新值），没有 `from`/`to`。
2. **以为有 `view`/`admin` 档**：只有 `edit`/`browse` 两值；`setMode('admin')` 不会报错（模式是字符串）但等效于非 browse——语义上不要这么用。
3. **browse 下夹点消失当 bug**：设计如此（`getActiveGrips` 对 browse 返回 `[]`）。
4. **多 MapCadLayer 共用 mode？** 每个 layer 各存各的 `_mode`，互不影响。

## 相关

- 命令系统 → [overview](overview.md)
- 快捷键 → [shortcuts](shortcuts.md)
- 事件 → [event/bus-command-mode](../event/bus-command-mode.md)
