# resource tab 连续打开多个预览后卡住

## 现象

- 在文档页 resource tab 内连续打开多个 PDF 时，第 4 个 PDF 必现卡住。
- 卡住时 tab 标题已经切换，但 iframe 仍停在 `about:blank` 或空 body，PDF canvas 数量为 0。
- 单独打开 `/pdf-preview` 页面、或独立页面中复用单个 iframe 连续切换 PDF，均不能复现。
- PDF 改成 tab 内 canvas 渲染后，第 4 个 PDF 可打开，但继续打开第 5 个仍会卡住；表格预览第 4 个仍会卡住。

## 根因

根因不是具体 PDF 文件，也不是页数懒加载策略，而是 resource tab 为每个本地资源预览都常驻一个 `/api/local-folder/events` EventSource。连续打开多个 PDF / Office 预览后，隐藏 tab 的 EventSource 仍占用浏览器同源连接槽，新的 Office iframe 或 PDF 文件读取请求会被排队，表现为空白预览。

## 修复

- resource tab 内的 PDF 改为直接使用 pdf.js 渲染 canvas，不再通过 iframe 打开 `/pdf-preview`。
- 关闭或替换 PDF resource tab 时销毁 pdf.js document，释放渲染资源。
- resource tab 的本地文件监听改为 active-only：只保留当前激活资源 tab 的 EventSource，切换 tab 或回到页面 tab 时关闭其它资源 tab 的监听。
- 移除 `/pdf-preview` 内此前排查用的懒加载、占位页和多页预渲染逻辑，保留 2x 起步渲染清晰度。
- `dev:hot` 默认把 loopback bind 修正为 `0.0.0.0:<port>`，避免外网访问不到 3000。

## 验证

- 真实浏览器连续打开以下 4 个 PDF：
  - `patent/WO2024170760A1_Camellia_oleifera_tea_oil_concentrate.pdf`
  - `standard/T_CAIFCCI_106-2026_cosmetic_ingredient_camellia_oleifera_seed_oil.pdf`
  - `literature/Ouyang_2024_Frontiers_aged_Camellia_oleifera_oil_AD.pdf`
  - `literature/Leclere_2025_OCL_Tea_oil_concentrate.pdf`
- 第 4 个 PDF 结果：`canvasCount=15`，`iframeCount=0`，`status=15 / 15`，浏览器错误 0。
- 真实浏览器连续打开 5 个 DHA PDF，第 5 个 `Sun2022_DHA_Maillard_Kinetics.pdf` 结果：`canvasCount=8`，`status=8 / 8`，浏览器错误 0。
- 真实浏览器连续打开 5 个 XLSX 预览，第 4/5 个均 `status=完成`，`tableCount=1`，浏览器错误 0。
- `node --check rust/crates/mnote-web/browser/document-resource-tab-runtime.js`
- `node scripts/task-dev-hot-plan-test.js`
- `cargo test -p mnote-web --manifest-path rust/Cargo.toml pdf_preview_page_does_not_render_visible_toolbar`
- `cargo test -p mnote-web --manifest-path rust/Cargo.toml document_shell_returns_page_aggregate_snapshot`
- `cargo build -p mnote-web --manifest-path rust/Cargo.toml`
