# 导出功能复核与开发指引(2026-04-24) ## 1. 文档目的 本文件用于后续迭代开发时快速理解“用户数据导出”功能的当前实现状态、行为边界与已知风险,避免重复摸索。 --- ## 2. 复核范围 本次复核覆盖: - 后端 API:创建 / 列表 / 下载 / 删除 - 服务层:任务状态机、任务删除与目录清理、导出执行流程 - 导出产物:`data/`、`files/`、`manifest.json` - 前端导出中心交互:创建、刷新、下载、删除、重新导出 - 关键测试可执行性 --- ## 3. 关键代码位置 - API - `server/api/me/export/request.post.ts` - `server/api/me/export/tasks.get.ts` - `server/api/me/export/tasks/[id]/download.get.ts` - `server/api/me/export/tasks/[id].delete.ts` - 服务层 - `server/service/export/jobs.ts` - `server/service/export/run.ts` - `server/service/export/build-data.ts` - `server/service/export/build-files.ts` - `server/service/export/build-manifest.ts` - 前端 - `app/pages/me/export/index.vue` - `app/types/export.ts` - 测试 - `server/service/export/jobs.test.ts` - `server/service/export/build-manifest.test.ts` - `server/utils/me-export-request-body.test.ts` --- ## 4. 当前功能状态(复核结论) ### 4.1 已实现并可用 - **任务生命周期** - 支持 `queued -> running -> succeeded/failed/expired` - 同一用户存在 `queued/running` 任务时,禁止再次创建(409) - **导出产物构建** - 导出目录结构: - `manifest.json` - `data/*.json` - `files/*` - `manifest` 包含: - `schemaVersion` - `exportedAt/exportCutoffAt` - `maskPolicy` - `stats` - `checksums.data/files` - **下载完整包** - 下载接口返回完整压缩包(`tar.gz`) - 通过 `tar -czf -` 流式返回,不落地额外压缩文件 - **任务列表自愈** - 刷新任务列表时会检查已完成任务的导出文件可用性 - 缺失/过期会自动标记为 `expired` 并写入错误信息 - **任务删除** - `DELETE /api/me/export/tasks/:id` - 非 `running` 任务可删 - 删除时尝试清理对应 `.tmp/exports` 目录,并做路径边界保护 - **前端交互** - 支持创建、刷新、下载、删除 - `expired` 任务显示“重新导出”按钮 --- ## 5. 实测结果(本地复核) 执行命令: ```bash bun test server/service/export/jobs.test.ts bun test server/service/export/build-manifest.test.ts bun test server/utils/me-export-request-body.test.ts ``` 结果: - `server/service/export/jobs.test.ts`:通过(12 pass) - `server/service/export/build-manifest.test.ts`:通过(1 pass) - `server/utils/me-export-request-body.test.ts`:失败(`Cannot find package 'h3'`) --- ## 6. 已知问题与风险 ### R1(中):`me-export-request-body` 单测依赖问题 - 现象:测试环境无法解析 `h3`,导致 `server/utils/me-export-request-body.test.ts` 失败。 - 影响:该 util 的单测在当前环境不稳定,CI/新开发机可能复现。 - 建议: - 方案 A:`me-export-request-body.ts` 改为抛项目通用错误对象(`{ statusCode, statusMessage }`),不直接依赖 `h3`。 - 方案 B:明确把 `h3` 作为可解析依赖并固定版本,确保测试环境一致。 ### R2(中):下载包格式依赖系统 `tar` - 当前下载使用子进程 `tar` 打包,依赖运行环境存在 `tar` 命令。 - 建议: - 在部署文档里明确依赖项; - 或改为 Node 库打包,避免系统命令依赖。 ### R3(中):下载失败时状态修正为 `expired` 的语义边界 - 当前将“文件缺失/打包失败/过期”统一落到 `expired`。 - 建议: - 若需更细粒度运维排障,可新增状态或错误码区分(如 `EXPORT_MISSING`、`EXPORT_PACKAGE_FAILED`)。 --- ## 7. 对外接口行为(当前版本) ### 7.1 创建任务 - `POST /api/me/export/request` - body:`{ "maskPolicy": "masked" | "raw" }`(可省略,默认 `masked`) - 返回:`taskId`, `status` ### 7.2 获取任务列表 - `GET /api/me/export/tasks` - 返回当前用户任务 - 返回前会自动做“已完成任务文件存在性检查”,必要时改为 `expired` ### 7.3 下载任务产物 - `GET /api/me/export/tasks/:id/download` - 仅允许下载本人且 `succeeded` 的任务 - 返回完整 `tar.gz` 包 - 常见错误: - `409`:任务未完成 - `410`:任务过期或文件丢失(并同步标记为 `expired`) ### 7.4 删除任务 - `DELETE /api/me/export/tasks/:id` - 仅允许删除本人任务 - `running` 任务返回 `409` --- ## 8. 后续开发建议(按优先级) 1. **修复 R1**:先解决 `h3` 解析导致的单测不稳定。 2. **补 API 级测试**:增加 `request/tasks/download/delete` 的集成测试。 3. **下载格式可配置**:支持 `zip`(前端兼容性更好)或可选 `tar.gz/zip`。 4. **导出清理任务**:增加后台任务,定期清理已过期目录与旧任务数据。 5. **更细状态与错误码**:提高运维可观测性。 --- ## 9. 最终结论 - **功能可用性**:通过(可用于后续开发迭代) - **工程稳定性**:有条件通过(需优先修复 R1)