|
|
@@ -1,340 +0,0 @@
|
|
|
-# Story 010.009: 创建统一文件后端模块
|
|
|
-
|
|
|
-## Status
|
|
|
-In Progress
|
|
|
-
|
|
|
-## Story
|
|
|
-
|
|
|
-**As a** 超级管理员,
|
|
|
-**I want** 一个统一的后端文件模块(无租户隔离),
|
|
|
-**so that** 可以在租户管理后台统一管理所有文件,统一广告模块使用的文件与其他统一模块保持一致的数据隔离模式。
|
|
|
-
|
|
|
-## Background
|
|
|
-
|
|
|
-**当前问题**:
|
|
|
-- 统一广告模块 (`unified-advertisements-module`) 使用 `@d8d/core-module-mt/file-module-mt` 的 `FileMt` 实体(多租户,有tenant_id)
|
|
|
-- **不一致性**: 统一广告本身是无租户隔离的,但关联的文件却是多租户隔离的
|
|
|
-
|
|
|
-**解决方案**:
|
|
|
-- 参照统一广告模块的设计模式,从单租户的 `file-module` 复制创建统一版本
|
|
|
-- 创建 `unified-file-module`(无tenant_id字段)
|
|
|
-- 统一广告模块更新为使用 `UnifiedFile` 实体
|
|
|
-
|
|
|
-## Acceptance Criteria
|
|
|
-
|
|
|
-1. 创建 `packages/unified-file-module` 包,从 `file-module` 复制并改造为无租户隔离版本
|
|
|
-2. Entity定义不包含 `tenant_id` 字段,与原 `file-module` 的Entity结构相同但移除租户隔离
|
|
|
-3. 实现管理员路由(使用 `tenantAuthMiddleware`),只有超级管理员(ID=1)可访问
|
|
|
-4. 实现文件上传功能(MinIO集成)
|
|
|
-5. 包含完整的单元测试和集成测试
|
|
|
-
|
|
|
-## Tasks / Subtasks
|
|
|
-
|
|
|
-- [x] **任务1: 创建包结构和配置文件** (AC: 1)
|
|
|
- - [x] 创建 `packages/unified-file-module` 目录
|
|
|
- - [x] 创建 `package.json`,配置包名为 `@d8d/unified-file-module`
|
|
|
- - [x] 创建 `tsconfig.json`
|
|
|
- - [x] 创建 `vitest.config.ts`(设置 `fileParallelism: false`)
|
|
|
- - [x] 创建 `src/` 子目录:`entities/`, `services/`, `routes/`, `schemas/`
|
|
|
- - [x] 创建 `tests/` 子目录:`integration/`, `unit/`, `utils/`
|
|
|
-
|
|
|
-- [x] **任务2: 定义Entity(无tenant_id字段)** (AC: 2)
|
|
|
- - [x] 创建 `src/entities/unified-file.entity.ts`,参考 `file-module` 但移除 `tenant_id` 字段
|
|
|
- - [x] 确保字段包含:`id`, `fileName`, `filePath`, `fileSize`, `mimeType`, `status`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy`
|
|
|
- - [x] 添加 `@Index` 索引(status, createdAt等)
|
|
|
- - [x] 创建 `src/entities/index.ts` 导出Entity
|
|
|
-
|
|
|
-- [x] **任务3: 实现Service层** (AC: 1)
|
|
|
- - [x] 创建 `src/services/unified-file.service.ts`,继承 `GenericCrudService`
|
|
|
- - [x] 覆盖 `create`、`update`、`delete` 方法(使用 `override` 关键字)
|
|
|
- - [x] 实现软删除逻辑(设置 `status=0`)
|
|
|
- - [x] 实现文件上传逻辑(调用MinIO)
|
|
|
- - [x] 创建 `src/services/index.ts` 导出Service
|
|
|
-
|
|
|
-- [x] **任务4: 定义Schema** (AC: 1)
|
|
|
- - [x] 创建 `src/schemas/unified-file.schema.ts`,使用 Zod + OpenAPI装饰器
|
|
|
- - [x] 使用 `z.coerce.date<Date>()` 和 `z.coerce.number<number>()` 泛型语法
|
|
|
- - [x] 定义 `CreateUnifiedFileDto`、`UpdateUnifiedFileDto`、`UnifiedFileListResponseSchema`
|
|
|
- - [x] 不导出推断类型(`z.infer`),类型由RPC自动推断
|
|
|
- - [x] 创建 `src/schemas/index.ts` 导出Schema
|
|
|
-
|
|
|
-- [x] **任务5: 实现管理员路由** (AC: 3)
|
|
|
- - [x] 创建 `src/routes/admin/unified-files.admin.routes.ts`
|
|
|
- - [x] 使用 `OpenAPIHono` 和 `AuthContext` 泛型
|
|
|
- - [x] 使用 `createRoute` 定义路由,包含请求/响应Schema
|
|
|
- - [x] 应用 `tenantAuthMiddleware` 中间件(只有超级管理员可访问)
|
|
|
- - [x] 自定义路由使用 `parseWithAwait` 验证响应数据
|
|
|
- - [x] 使用 `createZodErrorResponse` 处理Zod错误
|
|
|
-
|
|
|
-- [x] **任务6: 实现文件上传处理** (AC: 4)
|
|
|
- - [x] 实现MinIO文件上传逻辑
|
|
|
- - [x] 实现文件验证(大小、类型)
|
|
|
- - [x] 实现文件删除(MinIO + 数据库)
|
|
|
- - [x] 实现文件URL生成
|
|
|
-
|
|
|
-- [x] **任务7: 创建包导出入口** (AC: 1)
|
|
|
- - [x] 创建 `src/index.ts`,导出Entities、Services、Routes、Schemas
|
|
|
- - [x] 配置 `package.json` 的 `exports` 字段
|
|
|
-
|
|
|
-- [x] **任务8: 编写单元测试** (AC: 5)
|
|
|
- - [x] 创建Service层单元测试
|
|
|
- - [x] 测试软删除逻辑
|
|
|
-
|
|
|
-- [x] **任务9: 编写集成测试** (AC: 5)
|
|
|
- - [x] 创建 `tests/integration/unified-files.integration.test.ts`
|
|
|
- - [x] 测试管理员CRUD操作(验证 `tenantAuthMiddleware` 权限)
|
|
|
- - [x] 测试文件上传功能
|
|
|
- - [x] 测试文件删除功能
|
|
|
-
|
|
|
-- [x] **任务10: 代码质量检查**
|
|
|
- - [x] 运行 `pnpm test` 确保所有测试通过 (8/8 通过)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 补充任务(发现缺失功能后添加)
|
|
|
-
|
|
|
-- [ ] **任务11: 创建文件上传策略路由** (AC: 4)
|
|
|
- - [ ] 创建 `src/routes/upload-policy/post.ts`,参考 `file-module` 对应文件
|
|
|
- - [ ] 实现 MinIO 上传策略生成(含签名)
|
|
|
- - [ ] 使用 `tenantAuthMiddleware` 中间件
|
|
|
- - [ ] 定义 Schema 包含 uploadPolicy 响应结构
|
|
|
-
|
|
|
-- [ ] **任务12: 创建分片上传策略路由** (AC: 4)
|
|
|
- - [ ] 创建 `src/routes/multipart-policy/post.ts`,参考 `file-module` 对应文件
|
|
|
- - [ ] 实现分片上传策略生成
|
|
|
- - [ ] 使用 `tenantAuthMiddleware` 中间件
|
|
|
-
|
|
|
-- [ ] **任务13: 创建分片上传完成路由** (AC: 4)
|
|
|
- - [ ] 创建 `src/routes/multipart-complete/post.ts`,参考 `file-module` 对应文件
|
|
|
- - [ ] 实现分片上传完成逻辑
|
|
|
- - [ ] 使用 `tenantAuthMiddleware` 中间件
|
|
|
-
|
|
|
-- [ ] **任务14: 创建获取文件URL路由** (AC: 4)
|
|
|
- - [ ] 创建 `src/routes/[id]/get-url.ts`,参考 `file-module` 对应文件
|
|
|
- - [ ] 实现 `GET /:id/url` 端点
|
|
|
- - [ ] 使用 `tenantAuthMiddleware` 中间件
|
|
|
-
|
|
|
-- [ ] **任务15: 创建文件删除路由** (AC: 4)
|
|
|
- - [ ] 创建 `src/routes/[id]/delete.ts`,参考 `file-module` 对应文件
|
|
|
- - [ ] 实现 `DELETE /:id` 端点
|
|
|
- - [ ] 同时删除 MinIO 文件和数据库记录
|
|
|
- - [ ] 使用 `tenantAuthMiddleware` 中间件
|
|
|
-
|
|
|
-- [ ] **任务16: 创建文件下载路由** (AC: 4)
|
|
|
- - [ ] 创建 `src/routes/[id]/download.ts`,参考 `file-module` 对应文件
|
|
|
- - [ ] 实现 `GET /:id/download` 端点(返回带 Content-Disposition 的 URL)
|
|
|
- - [ ] 使用 `tenantAuthMiddleware` 中间件
|
|
|
-
|
|
|
-- [ ] **任务17: 更新路由入口文件** (AC: 4)
|
|
|
- - [ ] 更新 `src/routes/index.ts`,聚合所有路由
|
|
|
- - [ ] 添加 `createCrudRoutes` 生成基础 CRUD 路由
|
|
|
- - [ ] 导出完整的 `unifiedFileRoutes` 路由集合
|
|
|
-
|
|
|
-- [ ] **任务18: 创建测试工具文件**
|
|
|
- - [ ] 创建 `tests/utils/integration-test-utils.ts`,参考 `file-module` 对应文件
|
|
|
- - [ ] 实现 `IntegrationTestAssertions` 类(expectFileToExist 等方法)
|
|
|
- - [ ] 适配 `UnifiedFile` 实体
|
|
|
-
|
|
|
-- [ ] **任务19: 创建测试数据工厂**
|
|
|
- - [ ] 创建 `tests/utils/integration-test-db.ts`,参考 `file-module` 对应文件
|
|
|
- - [ ] 实现 `TestDataFactory` 类
|
|
|
- - [ ] 适配 `UnifiedFile` 实体字段
|
|
|
-
|
|
|
-- [ ] **任务20: 补充集成测试**
|
|
|
- - [ ] 为上传策略路由添加集成测试
|
|
|
- - [ ] 为分片上传路由添加集成测试
|
|
|
- - [ ] 为获取URL路由添加集成测试
|
|
|
- - [ ] 为下载路由添加集成测试
|
|
|
- - [ ] 为删除路由添加集成测试
|
|
|
-
|
|
|
-- [ ] **任务21: 完整回归测试**
|
|
|
- - [ ] 运行 `pnpm test` 确保所有测试通过
|
|
|
- - [ ] 运行 `pnpm typecheck` 确保无类型错误
|
|
|
- - [ ] 更新 File List 列出所有新增文件
|
|
|
-
|
|
|
-## Dev Notes
|
|
|
-
|
|
|
-### 项目结构信息
|
|
|
-
|
|
|
-**新包位置**:
|
|
|
-```
|
|
|
-packages/unified-file-module/
|
|
|
-├── package.json
|
|
|
-├── tsconfig.json
|
|
|
-├── vitest.config.ts
|
|
|
-├── src/
|
|
|
-│ ├── entities/
|
|
|
-│ │ ├── unified-file.entity.ts
|
|
|
-│ │ └── index.ts
|
|
|
-│ ├── services/
|
|
|
-│ │ ├── unified-file.service.ts
|
|
|
-│ │ └── index.ts
|
|
|
-│ ├── routes/
|
|
|
-│ │ ├── admin/
|
|
|
-│ │ │ └── unified-files.admin.routes.ts
|
|
|
-│ │ └── index.ts
|
|
|
-│ ├── schemas/
|
|
|
-│ │ ├── unified-file.schema.ts
|
|
|
-│ │ └── index.ts
|
|
|
-│ └── index.ts
|
|
|
-└── tests/
|
|
|
- ├── integration/
|
|
|
- │ └── unified-files.integration.test.ts
|
|
|
- ├── unit/
|
|
|
- │ └── unified-file.service.test.ts
|
|
|
- └── utils/
|
|
|
- └── test-data-factory.ts
|
|
|
-```
|
|
|
-
|
|
|
-**参考模块**:
|
|
|
-- 单租户文件模块: `packages/file-module`
|
|
|
-- 统一广告模块: `packages/unified-advertisements-module`
|
|
|
-- 认证模块: `@d8d/core-module-mt/auth-module-mt`
|
|
|
-- 租户模块: `@d8d/tenant-module-mt`
|
|
|
-
|
|
|
-### Entity设计规范
|
|
|
-
|
|
|
-**统一文件Entity** (`unified-file.entity.ts`):
|
|
|
-- 继承自原 `file-module` 的Entity结构
|
|
|
-- **关键区别**: 无 `tenant_id` 字段
|
|
|
-- 字段包括:`id`, `fileName`, `filePath`, `fileSize`, `mimeType`, `status`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy`
|
|
|
-
|
|
|
-### 路由设计规范
|
|
|
-
|
|
|
-**管理员接口** (完整列表):
|
|
|
-```
|
|
|
-# 文件上传策略
|
|
|
-POST /api/v1/admin/unified-files/upload-policy # 生成MinIO上传策略
|
|
|
-POST /api/v1/admin/unified-files/multipart-policy # 生成分片上传策略
|
|
|
-POST /api/v1/admin/unified-files/multipart-complete # 完成分片上传
|
|
|
-
|
|
|
-# 文件操作(通过createCrudRoutes自动生成)
|
|
|
-GET /api/v1/admin/unified-files # 文件列表
|
|
|
-POST /api/v1/admin/unified-files # 创建文件记录
|
|
|
-GET /api/v1/admin/unified-files/:id # 获取文件详情
|
|
|
-PUT /api/v1/admin/unified-files/:id # 更新文件记录
|
|
|
-
|
|
|
-# 文件专用操作
|
|
|
-GET /api/v1/admin/unified-files/:id/url # 获取文件访问URL
|
|
|
-GET /api/v1/admin/unified-files/:id/download # 获取文件下载URL
|
|
|
-DELETE /api/v1/admin/unified-files/:id # 删除文件(MinIO+DB)
|
|
|
-```
|
|
|
-
|
|
|
-### 中间件使用规范
|
|
|
-
|
|
|
-**管理员路由**:
|
|
|
-- 使用 `tenantAuthMiddleware`(来自 `@d8d/tenant-module-mt`,独立包)
|
|
|
-- 只有超级管理员(ID=1)可访问
|
|
|
-
|
|
|
-### MinIO集成
|
|
|
-
|
|
|
-**文件上传流程**:
|
|
|
-1. 接收文件上传请求
|
|
|
-2. 验证文件大小和类型
|
|
|
-3. 上传到MinIO
|
|
|
-4. 保存文件记录到数据库
|
|
|
-5. 返回文件信息
|
|
|
-
|
|
|
-### 测试标准
|
|
|
-
|
|
|
-| 测试类型 | 最低要求 | 目标要求 |
|
|
|
-|----------|----------|----------|
|
|
|
-| 单元测试 | 70% | 80% |
|
|
|
-| 集成测试 | 50% | 60% |
|
|
|
-
|
|
|
-### 关键测试要求
|
|
|
-1. **权限测试**: 验证管理员路由只有超级管理员可访问
|
|
|
-2. **文件上传测试**: 验证MinIO文件上传和数据库记录
|
|
|
-3. **软删除测试**: 验证删除操作设置 `status=0` 而非物理删除
|
|
|
-4. **文件验证测试**: 验证文件大小、类型限制
|
|
|
-
|
|
|
-## Testing
|
|
|
-
|
|
|
-### 测试文件位置
|
|
|
-- 单元测试: `tests/unit/`
|
|
|
-- 集成测试: `tests/integration/`
|
|
|
-- 测试工具: `tests/utils/`
|
|
|
-
|
|
|
-### 测试框架
|
|
|
-- **Vitest**: 主要测试运行器
|
|
|
-- **hono/testing**: API路由测试
|
|
|
-- **TypeORM**: 数据库测试
|
|
|
-
|
|
|
-### 测试执行命令
|
|
|
-```bash
|
|
|
-# 进入模块目录
|
|
|
-cd packages/unified-file-module
|
|
|
-
|
|
|
-# 运行所有测试
|
|
|
-pnpm test
|
|
|
-
|
|
|
-# 运行集成测试
|
|
|
-pnpm test:integration
|
|
|
-
|
|
|
-# 生成覆盖率报告
|
|
|
-pnpm test:coverage
|
|
|
-
|
|
|
-# 类型检查
|
|
|
-pnpm typecheck
|
|
|
-```
|
|
|
-
|
|
|
-## Change Log
|
|
|
-
|
|
|
-| Date | Version | Description | Author |
|
|
|
-|------|---------|-------------|--------|
|
|
|
-| 2026-01-03 | 1.0 | 初始故事创建 | James (Claude Code) |
|
|
|
-| 2026-01-04 | 1.1 | 修复阶段 - 修复vitest配置、Entity、Service、Schema、测试 | James (Claude Code) |
|
|
|
-| 2026-01-04 | 1.2 | **发现缺失功能** - 添加补充任务11-21,补充完整的路由功能(上传策略、分片上传、URL获取、下载、删除)和测试工具 | James (Claude Code) |
|
|
|
-
|
|
|
-## Dev Agent Record
|
|
|
-
|
|
|
-### Agent Model Used
|
|
|
-claude-opus-4-5-20251101 (via Happy)
|
|
|
-
|
|
|
-### Debug Log References
|
|
|
-无特殊调试需求,所有测试一次性通过。
|
|
|
-
|
|
|
-### Completion Notes List
|
|
|
-1. **修复了初始创建的代码问题**:
|
|
|
- - vitest.config.ts 删除了不必要的 resolve.alias 配置(pnpm workspace 自动解析)
|
|
|
- - unified-file.entity.ts 补充完整的 Entity 类定义
|
|
|
- - unified-file.service.ts 补充完整的 Service 实现
|
|
|
- - unified-file.schema.ts 修正字段名与 Entity 一致(fileName 而非 name)
|
|
|
-
|
|
|
-2. **集成测试设计**:
|
|
|
- - 不需要 UserEntityMt 依赖(统一文件模块只用 tenantAuthMiddleware 验证 JWT)
|
|
|
- - 只测试超级管理员权限(ID=1)访问
|
|
|
-
|
|
|
-3. **测试结果**:
|
|
|
- - 单元测试: 2/2 通过
|
|
|
- - 集成测试: 6/6 通过
|
|
|
- - 总计: 8/8 通过
|
|
|
-
|
|
|
-4. **🚨 发现严重问题 (2026-01-04)**:
|
|
|
- - 原始 `file-module` 包含完整的文件上传功能(upload-policy, multipart-policy, multipart-complete)
|
|
|
- - 原始 `file-module` 包含文件URL获取和下载功能(get-url, download)
|
|
|
- - 原始 `file-module` 包含独立的删除路由(delete.ts)
|
|
|
- - **unified-file-module 缺失上述所有路由功能!**
|
|
|
- - 缺失测试工具文件:`integration-test-utils.ts`, `integration-test-db.ts`
|
|
|
- - 已添加补充任务11-21来完善功能
|
|
|
-
|
|
|
-### File List
|
|
|
-**新增文件**:
|
|
|
-- `package.json` - 包配置,依赖 @d8d/shared-crud, @d8d/shared-utils, @d8d/tenant-module-mt
|
|
|
-- `tsconfig.json` - TypeScript 配置
|
|
|
-- `vitest.config.ts` - Vitest 测试配置(无别名配置)
|
|
|
-- `src/entities/unified-file.entity.ts` - 统一文件实体(无 tenant_id)
|
|
|
-- `src/entities/index.ts` - Entity 导出
|
|
|
-- `src/services/unified-file.service.ts` - Service 层(软删除实现)
|
|
|
-- `src/services/minio.service.ts` - MinIO 文件服务
|
|
|
-- `src/services/index.ts` - Service 导出
|
|
|
-- `src/schemas/unified-file.schema.ts` - Zod Schema 定义
|
|
|
-- `src/schemas/index.ts` - Schema 导出
|
|
|
-- `src/routes/admin/unified-files.admin.routes.ts` - 管理员路由(tenantAuthMiddleware)
|
|
|
-- `src/routes/index.ts` - Routes 导出
|
|
|
-- `src/index.ts` - 包主入口
|
|
|
-- `tests/integration/unified-files.integration.test.ts` - 集成测试
|
|
|
-- `tests/unit/unified-file.service.unit.test.ts` - 单元测试
|
|
|
-
|
|
|
-## QA Results
|
|
|
-_待QA代理填写_
|