|
@@ -0,0 +1,233 @@
|
|
|
|
|
+# Story 010.009: 创建统一文件后端模块
|
|
|
|
|
+
|
|
|
|
|
+## Status
|
|
|
|
|
+Approved
|
|
|
|
|
+
|
|
|
|
|
+## 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
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务1: 创建包结构和配置文件** (AC: 1)
|
|
|
|
|
+ - [ ] 创建 `packages/unified-file-module` 目录
|
|
|
|
|
+ - [ ] 创建 `package.json`,配置包名为 `@d8d/unified-file-module`
|
|
|
|
|
+ - [ ] 创建 `tsconfig.json`
|
|
|
|
|
+ - [ ] 创建 `vitest.config.ts`(设置 `fileParallelism: false`)
|
|
|
|
|
+ - [ ] 创建 `src/` 子目录:`entities/`, `services/`, `routes/`, `schemas/`
|
|
|
|
|
+ - [ ] 创建 `tests/` 子目录:`integration/`, `unit/`, `utils/`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务2: 定义Entity(无tenant_id字段)** (AC: 2)
|
|
|
|
|
+ - [ ] 创建 `src/entities/unified-file.entity.ts`,参考 `file-module` 但移除 `tenant_id` 字段
|
|
|
|
|
+ - [ ] 确保字段包含:`id`, `fileName`, `filePath`, `fileSize`, `mimeType`, `status`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy`
|
|
|
|
|
+ - [ ] 添加 `@Index` 索引(status, createdAt等)
|
|
|
|
|
+ - [ ] 创建 `src/entities/index.ts` 导出Entity
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务3: 实现Service层** (AC: 1)
|
|
|
|
|
+ - [ ] 创建 `src/services/unified-file.service.ts`,继承 `GenericCrudService`
|
|
|
|
|
+ - [ ] 覆盖 `create`、`update`、`delete` 方法(使用 `override` 关键字)
|
|
|
|
|
+ - [ ] 实现软删除逻辑(设置 `status=0`)
|
|
|
|
|
+ - [ ] 实现文件上传逻辑(调用MinIO)
|
|
|
|
|
+ - [ ] 创建 `src/services/index.ts` 导出Service
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务4: 定义Schema** (AC: 1)
|
|
|
|
|
+ - [ ] 创建 `src/schemas/unified-file.schema.ts`,使用 Zod + OpenAPI装饰器
|
|
|
|
|
+ - [ ] 使用 `z.coerce.date<Date>()` 和 `z.coerce.number<number>()` 泛型语法
|
|
|
|
|
+ - [ ] 定义 `CreateUnifiedFileDto`、`UpdateUnifiedFileDto`、`UnifiedFileListResponseSchema`
|
|
|
|
|
+ - [ ] 不导出推断类型(`z.infer`),类型由RPC自动推断
|
|
|
|
|
+ - [ ] 创建 `src/schemas/index.ts` 导出Schema
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务5: 实现管理员路由** (AC: 3)
|
|
|
|
|
+ - [ ] 创建 `src/routes/admin/unified-files.admin.routes.ts`
|
|
|
|
|
+ - [ ] 使用 `OpenAPIHono` 和 `AuthContext` 泛型
|
|
|
|
|
+ - [ ] 使用 `createRoute` 定义路由,包含请求/响应Schema
|
|
|
|
|
+ - [ ] 应用 `tenantAuthMiddleware` 中间件(只有超级管理员可访问)
|
|
|
|
|
+ - [ ] 自定义路由使用 `parseWithAwait` 验证响应数据
|
|
|
|
|
+ - [ ] 使用 `createZodErrorResponse` 处理Zod错误
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务6: 实现文件上传处理** (AC: 4)
|
|
|
|
|
+ - [ ] 实现MinIO文件上传逻辑
|
|
|
|
|
+ - [ ] 实现文件验证(大小、类型)
|
|
|
|
|
+ - [ ] 实现文件删除(MinIO + 数据库)
|
|
|
|
|
+ - [ ] 实现文件URL生成
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务7: 创建包导出入口** (AC: 1)
|
|
|
|
|
+ - [ ] 创建 `src/index.ts`,导出Entities、Services、Routes、Schemas
|
|
|
|
|
+ - [ ] 配置 `package.json` 的 `exports` 字段
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务8: 编写单元测试** (AC: 5)
|
|
|
|
|
+ - [ ] 创建 `tests/utils/test-data-factory.ts`
|
|
|
|
|
+ - [ ] 创建Service层单元测试
|
|
|
|
|
+ - [ ] 创建Schema验证测试
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务9: 编写集成测试** (AC: 5)
|
|
|
|
|
+ - [ ] 创建 `tests/integration/unified-files.integration.test.ts`
|
|
|
|
|
+ - [ ] 测试管理员CRUD操作(验证 `tenantAuthMiddleware` 权限)
|
|
|
|
|
+ - [ ] 测试文件上传功能
|
|
|
|
|
+ - [ ] 测试文件删除功能
|
|
|
|
|
+ - [ ] 测试MinIO集成
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **任务10: 代码质量检查**
|
|
|
|
|
+ - [ ] 运行 `pnpm typecheck` 确保无TypeScript错误
|
|
|
|
|
+ - [ ] 运行 `pnpm lint` 确保代码符合规范
|
|
|
|
|
+ - [ ] 运行 `pnpm test` 确保所有测试通过
|
|
|
|
|
+ - [ ] 运行 `pnpm test:coverage` 确保覆盖率达标
|
|
|
|
|
+
|
|
|
|
|
+## 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 # 上传文件
|
|
|
|
|
+GET /api/v1/admin/unified-files # 文件列表
|
|
|
|
|
+GET /api/v1/admin/unified-files/:id # 获取文件详情
|
|
|
|
|
+DELETE /api/v1/admin/unified-files/:id # 删除文件
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 中间件使用规范
|
|
|
|
|
+
|
|
|
|
|
+**管理员路由**:
|
|
|
|
|
+- 使用 `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) |
|
|
|
|
|
+
|
|
|
|
|
+## Dev Agent Record
|
|
|
|
|
+
|
|
|
|
|
+### Agent Model Used
|
|
|
|
|
+_待开发时填写_
|
|
|
|
|
+
|
|
|
|
|
+### Debug Log References
|
|
|
|
|
+_待开发时填写_
|
|
|
|
|
+
|
|
|
|
|
+### Completion Notes List
|
|
|
|
|
+_待开发时填写_
|
|
|
|
|
+
|
|
|
|
|
+### File List
|
|
|
|
|
+_待开发时填写_
|
|
|
|
|
+
|
|
|
|
|
+## QA Results
|
|
|
|
|
+_待QA代理填写_
|