Files
Nexus/docs/changelog/2026-06-02-editor-refactor-p0.md
T

2.6 KiB
Raw Blame History

Changelog — 编辑器重构 P0

日期: 2026-06-02
模块: 文件编辑器(FileEditorWorkbench + 后端 read/write-file


变更摘要

修复编辑器三个 P0 正确性问题:

  1. 撤销历史串台(M1):改为每个标签页独立持有 Monaco ITextModel,切换时通过 editor.setModel() + saveViewState/restoreViewState 保留光标、折叠、选区,撤销历史互不影响。

  2. EOL 强制 LFM2):read-file 响应新增 eol 字段(LF/CRLF);编辑器内部用 LF-only 做对比,保存时按原始 EOL 还原。CRLF 文件不再被破坏。

  3. 并发写覆盖M3):read-file 新增 mtimeetagsha256hex);write-file 接受可选 etag,写前校验,不一致返回 HTTP 409;前端弹出冲突弹窗(覆盖/放弃)。


动机

  • M1:多标签编辑时,A 文件的撤销会回到 B 文件内容(共享同一 Monaco model 的 setValue 导致)
  • M2:CRLF 脚本/配置保存后被改成 LF,破坏 Windows 批处理等文件
  • M3:并发场景(两个管理员、外部工具)下静默覆盖,数据丢失无提示

涉及文件

文件 变更
server/api/schemas.py FileWrite 加 `etag: str
server/api/sync_v2.py read_file 返回 mtime/etag/eolwrite_file 加 etag 校验(409)和写后更新 etag
frontend/src/utils/filePreload.ts 新增 RemoteFileReadResult 接口,缓存改存完整结果
frontend/src/composables/files/useFilesEditor.ts 新增 OpenFilePayload 接口,editFile/previewFile 适配新返回类型
frontend/src/components/FileEditorWorkbench.vue per-tab model + viewStateEOL 保留;409 冲突弹窗
tests/test_editor_write_conflict.py 11 个 pytest 用例,覆盖 etag 校验逻辑
docs/design/specs/2026-06-02-editor-refactor-design.md 设计文档
docs/design/plans/2026-06-02-editor-refactor.md 技术文档

是否需要迁移/重启

  • 后端:需 supervisorctl restart nexusAPI 响应字段变更)
  • 前端:需重新构建并上传(bundle 变更)
  • 数据库:无 migration

验证方式

  1. python -m ruff check server/api/schemas.py server/api/sync_v2.py → 0 errors
  2. python -m pytest tests/test_editor_write_conflict.py -v → 11 passed
  3. npx vite build → build succeeded, 0 TS errors
  4. 浏览器:打开两个文件 A、B,编辑 B 后切回 A,Ctrl+Z 只撤销 A 的历史
  5. 浏览器:上传 CRLF 文件,编辑后保存,下载验证 CRLF 保留
  6. 浏览器:同一文件两标签保存,后者收到冲突弹窗