`1️⃣ 前端请求流程

  用户点击预览  
      ↓  
  CollaboraViewer.tsx (组件)  
      ↓  
  fetch('/api/collabora/view?fileId=xxx&mode=view&userId=xxx&userName=xxx')  
      ↓  
  后端 API: app/api/collabora/view/route.ts  
      ↓  
  返回配置 { iframeUrl, accessToken, wopiSrc, ... }  
      ↓  
  前端渲染 

  2️⃣ Collabora 加载文档流程

  浏览器加载 iframe  
      ↓  
  Collabora 服务器 ([http://172.16.0.81:9980](http://172.16.0.81:9980))  
      ↓  
  Collabora 解析 URL 中的 WOPISrc 和 access_token  
      ↓  
  Collabora 调用: GET {WOPISrc}?access_token=xxx  
      实际: GET [http://172.16.0.78:3000/api/collabora/wopi/files/contracts/xxx.docx?access_token=xxx](http://172.16.0.78:3000/api/collabora/wopi/files/contracts/xxx.docx?access_token=xxx)  
      ↓  
  后端 WOPI 端点: app/api/collabora/wopi/files/[...fileId]/route.ts  
      - 验证 JWT token  
      - 返回 CheckFileInfo (文件元数据)  
      ↓  
  Collabora 再次调用: GET {WOPISrc}/contents?access_token=xxx  
      ↓  
  后端 WOPI 端点检测到 /contents 后缀  
      - 从 MinIO 读取文件内容  
      - 返回文件二进制数据  
      ↓  
  Collabora 在 iframe 中渲染文档

  3️⃣ 保存文档流程（编辑模式）

  用户编辑文档 → 点击保存/关闭  
      ↓  
  Collabora 调用: POST {WOPISrc}/contents?access_token=xxx  
      请求体: 编辑后的文档二进制数据  
      ↓  
  后端 WOPI 端点 POST 处理器  
      - 验证 token 和权限  
      - 将文档保存到 MinIO（覆盖原文件）  
      ↓  
  返回 200 OK  
      ↓  
  Collabora 显示保存成功

