2026-10-26-simple-doclib.md 6.1 KB

简单文档库实施计划

执行方式:使用 subagent-driven-development,前端委派一个独立任务,主代理负责后端、联调和验收。用户已确认 HTML 原型并授权实施;在当前功能分支保留其他未提交改动,不提交或部署无关内容。

Goal: 在门户内实现文件夹、上传、指定人员分享、查看/下载和上传人/超级管理员删除。

Architecture: 复用 FastAPI、门户认证、MySQL 和 MinIO。三张独立业务表存目录、文档、分享关系;文档使用专用私有桶,下载由认证接口代理。左侧树同屏显示“我的文档”“分享给我”,管理员额外显示“全部文档”。旧 Cloudreve 数据和服务保留,门户不再调用旧 SSO。

Tech Stack: Python 3.9 / SQLAlchemy / Pydantic v2 / Vue 3 / Element Plus / Fresh Mint。

已确认的权限与边界

  • 每个用户只能在自己的目录上传,目录可嵌套;文件夹创建者或超级管理员可重命名、删除空目录。
  • 文件可见范围为同租户上传人、指定分享用户、超级管理员;只有上传人/超级管理员可改分享或软删除。分享接收人可见完整目录路径但不获得兄弟文档权限。
  • 本模块按用户明确授权的逐文档 ACL 管理,普通角色部门范围不会自动授予他人私有文档,也不会阻断明确分享;超级管理员身份沿用门户的多角色联合解析。该业务特例记录于 OpenSpec。
  • 文件元信息不返回对象存储地址/密钥。上传分块读取到临时文件,单文件默认 100 MB;下载二进制流,禁止公开链接及匿名读取。
  • 无在线 Office 编辑、版本、审批、自动迁移/停旧服务。

API 合同(统一 success_response,data 解包后)

基础路径 /web/doclib:

type Scope = 'mine' | 'shared' | 'all'
type Person = { id: string; name: string; deptName: string }
type FolderNode = { id: string; name: string; scope: Scope; folderId: string; fullPath: string; ownerId: string; canManage: boolean; count: number; children: FolderNode[] }
type Document = { id: string; name: string; folderId: string; folderPath: string; size: number; contentType: string; ownerId: string; ownerName: string; createTime: string; updateTime: string; canManage: boolean; shares: Person[] }
// GET /tree -> { nodes: FolderNode[]; isSuperAdmin: boolean; maxUploadBytes: number }
// GET /files?scope=mine&folderId=&keyword=&page=1&pageSize=20 -> {list: Document[]; total:number}
// GET /files/{id} -> Document
// POST /folders {name,parentId} -> FolderNode
// PUT /folders/{id} {name} -> FolderNode
// DELETE /folders/{id} -> null
// POST /upload multipart(file,folderId) -> Document,单文件立即上传
// PUT /files/{id}/shares {userIds:string[]} -> Document,空数组撤回全部分享
// POST /files/batch-delete {ids:string[]} -> null,全有权限才执行
// GET /files/{id}/download -> application/octet-stream + attachment
// GET /users?keyword= -> Person[],同租户有效人员,上限100,姓名/账号搜索

Task 1 — 后端与 SQL

Files: backend/app/models/doclib.py, backend/app/schemas/doclib.py, backend/app/services/doclib_service.py, backend/app/services/doclib_storage.py, backend/app/api/doclib.py, backend/app/core/config.py, backend/app/core/doclib_upload_route.py, docs/sql/20261026_simple_doclib.sql, backend/tests/test_doclib.py。

  • 先写 SQLite 会话集成测试:多租户、上传人、接收人、管理员、软删除、撤回分享、空目录、非法跨租户分享、父目录权限;运行并确认功能缺失失败。
  • 实现模型、schema、服务和薄路由;已有 doclib_router 已在两个入口注册,保留旧接口兼容。
  • 存储独立私有桶,上传校验大小/文件名,下载关闭响应连接;新增限额、桶配置和 multipart 排除路径。
  • MySQL 5.7 SQL:UUID VARCHAR(64)、全部公共字段、tenant/scope/file/share 查询索引。
  • 运行 cd backend && venv/bin/python -m pytest tests/test_doclib.py -q。

Task 2 — 门户页面(P04)

Files: web-admin/src/api/doclib.ts, web-admin/src/views/doclib/enter/index.vue 及同目录拆分组件,文档库跳转代码。

  • 对齐 docs/demos/simple-doclib-demo.html 与 web-admin/src/views/system/user/index.vue;原型中的两个根节点及文件夹树同时展示。
  • 接入 API,分页、搜索、列表主列链接打开详情、toolbar 的上传/新建/分享/下载/批量删除。
  • 新建/重命名目录、上传卡片、可搜索分享人选择、文档详情;按钮图标、顶部标签、完整路径与 dark tags。
  • 接收人无删除/分享操作,管理员可管理同租户文档;防重复提交、切换目录清空选择、请求竞态处理。
  • 移除 Cloudreve 跳转拦截,门户内打开 /doclib/enter。
  • 针对 tree/permissions 的最小行为测试,再运行定向 ESLint/Prettier 与 vue-tsc/build。

Task 3 — 集成验收与交付

  • 检查现有审计中间件对二进制下载/上传的内存处理;保留日志但避免整份文档读取进内存。
  • 真实 API 边界测试(认证、crypto、下载、大小限制、拒绝访问),浏览器检查正式 Vue 页。
  • 运行已有相关 auth/data-scope 测试;字段一致性脚本若仓库不存在,记录并人工核对契约。
  • 代码审查(先功能符合、再质量安全)、修复问题、重新验证。
  • 配置与 SQL 部署说明写入 doclib/需求说明.md;仅在确认目标为开发环境后执行开发库新增表,不改旧库。
  • 更新 backend/frontend/root 知识图谱;记录测试结果和未执行的部署步骤。

执行结果

2026-10-26:前后端实现与两阶段审查已完成。修复目录选择缺失、下载超时、分享旧快照竞态、上传失败残留对象及multipart/伪装正文预读问题。后端28测试,前端7测试与隔离浏览器回归通过;生产构建通过。开发库仅新增三表,私有桶和真实上传/匿名拒绝/分享撤回已验证,样例数据软删除。生产未发布,旧服务未停止。工作区保留,未commit,未修改无关功能。