# 2026-06-02 文件编辑器双击打开卡死修复（Monaco markRaw）

## 变更摘要

`FileEditorWorkbench.vue` 中每个编辑器 tab 持有的 Monaco `model` 与 `viewState` 现用 `markRaw()` 包裹，阻止 Vue 对其建立响应式代理。

## 动机

用户反馈：在 `/app/#/files` 双击打开文件编辑器时，Firefox 弹出「此网页拖慢了您的 Firefox。可停止此页面，恢复浏览速度」并卡死。

根因：`tabs` 是 `ref<EditorTabState[]>`，而每个 `EditorTabState` 直接持有 Monaco 的 `ITextModel`（`model`）和 `ICodeEditorViewState`（`viewState`）。当 tab 被 `push` 进响应式数组时，Vue 的 reactivity 会**深度遍历并代理 Monaco model 的整个内部对象图**——其中包含大量内部状态与循环引用，一次性代理化在主线程上同步执行，导致页面冻结、浏览器报「网页拖慢」。

## 修复

用 Vue 的 `markRaw()` 将 Monaco 对象标记为「永不代理」，使其在响应式数组中保持原始对象：

- `openFile`：`monaco.editor.createModel(...)` → `markRaw(...)`
- `mountEditor`：懒建 model → `markRaw(...)`
- `switchToTab`：兜底懒建 model → `markRaw(...)`
- `persistEditorToActiveTab`：`editor.saveViewState()` → 非空时 `markRaw(...)`，否则 `null`

tab 的其它字段（`name`/`modified`/`path` 等）仍保持响应式，UI 行为不变。

## 涉及文件

- `frontend/src/components/FileEditorWorkbench.vue`

## 是否需迁移/重启

- 无需 DB 迁移。仅前端构建产物变更，需重新 `vite build` + 上传 `web/app` + `supervisorctl restart nexus`。

## 验证方式

1. 构建前端无类型/lint 错误。
2. 浏览器打开 `/app/#/files`，选服务器进入目录，双击文件打开编辑器：不再出现「网页拖慢」警告，打开瞬时完成。
3. 编辑、切换 tab、保存、关闭流程正常（viewState 滚动/光标位置仍正确恢复）。

## 回滚方式

移除 `markRaw` 包裹并删除 `markRaw` 导入即可恢复原状态（不建议，会复现卡死）。
