Documents 看上去只是一个文件列表加右侧预览,但企业版前端真正难的地方,是它要把“链接打开某个文档”“恢复某个选中状态”“显示右侧信息面板”“批量执行动作”统一成一套状态流。
主要参考:
enterprise/documents/static/src/core/router.jsenterprise/documents/static/src/core/document_service.jsenterprise/documents/static/src/views/documents_controller_mixin.js
一、Documents 的 URL 不是普通 action URL,而是带 access_token 的深链接
router.js 对 /odoo/documents/<access_token> 做了专门处理,甚至在点击阶段就阻止通用 router 把它误判成普通 action。stateToUrl() 也会优先把当前状态序列化为 access_token 形式的 URL。
这说明 Documents 的核心导航单位不是“当前 action id”,而是“当前聚焦的文档或文件夹 token”。对于分享、门户进入、内部跳转来说,这比传统 action URL 更稳定。
二、DocumentService 把“首次进入状态”提升为系统级 initData
服务初始化时会解析 documents_init_open_preview、documents_init_document_id、documents_init_user_folder_id,并把它们存入 _initData。也就是说,“第一次应该选中谁、要不要直接开预览、默认定位哪个文件夹”都不是某个组件私自决定,而是服务级状态。
这让 Documents 可以在不同入口下保持一致体验:
- 从 token 链接进来
- 从门户进来
- 从内部 action 跳过来
- 从分享链接还原到特定文档
三、初始选中与预览恢复,是 controller 主动完成的
DocumentsControllerMixin.openInitialPreview() 会在视图加载完成后,尝试找到首次应恢复的记录,并决定要不要直接触发预览。这里的设计很巧:数据先加载,记录再恢复,最后才决定是否开 preview。
如果反过来先开预览,你就会遇到记录还没进 model、界面打不开或打开错文档的问题。
四、动作菜单的复杂度,来自它要理解当前 selection 语义
controller mixin 里的菜单不是静态按钮集合,而是会根据:
- 是否单选 / 多选
- 当前是否在垃圾桶
- 当前用户是否内部用户
- 目标记录是否可编辑
- 选中对象是否为 request / folder / file
动态决定显示 rename、move、shortcut、version、share、download 等动作。
这说明 Documents 前端不是“列表 + 按钮”,而是一套基于当前 selection 语义实时计算可操作性的状态机。
五、右侧面板和 URL 更新是联动的
DocumentService 还负责维护 focused record、previewed document、right panel visible,以及根据当前聚焦对象更新 URL 中的 access token。这样用户刷新页面、复制链接或返回历史记录时,状态都更可恢复。
这在文档类应用里很重要,因为用户常常会通过“把当前文件发给别人”来交流,而不是只在当前会话里看一下就算了。
六、结论
Documents 前端的真正价值,在于它把token 深链接、初始化状态、预览恢复、动作菜单与右侧面板合成了一套可恢复的文档工作流。
所以它不是简单的文件预览页,而是一种偏工作台化的企业版文档前端。
DISCUSSION
评论区