Răsfoiți Sursa

docs: 添加史诗010故事010.009-011 - 创建统一文件模块和UI

拆分为三个独立故事:
- 故事010.009: 创建统一文件后端模块 (unified-file-module)
- 故事010.010: 创建统一文件管理UI包 (unified-file-management-ui)
- 故事010.011: 集成统一文件模块到统一广告和租户后台

解决统一广告模块使用多租户文件模块的不一致问题。

🤖 Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 2 săptămâni în urmă
părinte
comite
8b15ff4d2c

+ 93 - 4
docs/prd/epic-010-unified-ad-management.md

@@ -17,6 +17,7 @@
 | 1.10 | 2026-01-03 | 修复故事010.006 E2E测试:50个测试通过,更新测试策略文档 | James (Claude Code) |
 | 1.11 | 2026-01-03 | 添加故事010.007:租户后台UI交互E2E测试 | James (Claude Code) |
 | 1.12 | 2026-01-03 | 添加故事010.008:小程序端广告展示E2E测试 | James (Claude Code) |
+| 1.13 | 2026-01-03 | 添加故事010.009-011:拆分统一文件模块为三个故事 | James (Claude Code) |
 
 ## 史诗目标
 
@@ -333,6 +334,88 @@
 - 多租户数据统一性
 - 错误处理和缓存
 
+### Story 9: 创建统一文件后端模块 📝 待开始
+
+**标题**: 创建统一文件后端模块 (unified-file-module)
+
+**描述**: 当前统一广告模块使用多租户的文件模块(`file-module-mt`),这与统一广告的无租户隔离设计不一致。本故事从单租户的文件模块复制创建统一版本。
+
+**背景说明**:
+- **当前问题**: 统一广告模块 (`unified-advertisements-module`) 使用 `@d8d/core-module-mt/file-module-mt` 的 `FileMt` 实体(有tenant_id)
+- **不一致性**: 统一广告本身是无租户隔离的,但关联的文件却是多租户隔离的
+- **解决方案**: 从 `file-module` 复制创建 `unified-file-module`(无tenant_id)
+
+**任务**:
+- [ ] 创建 `packages/unified-file-module` 包(从 `file-module` 复制并改造)
+- [ ] 定义Entity(无tenant_id字段)
+- [ ] 实现Service层和文件上传逻辑(MinIO)
+- [ ] 实现管理员路由(使用 `tenantAuthMiddleware`)
+- [ ] 编写完整的单元测试和集成测试
+
+**完成日期**: _待定_
+**相关文件**: `docs/stories/010.009.story.md`
+
+**测试覆盖**:
+- 单元测试和集成测试
+- 文件上传测试
+- MinIO集成测试
+- 权限控制测试
+
+### Story 10: 创建统一文件管理UI包 📝 待开始
+
+**标题**: 创建统一文件管理UI包 (unified-file-management-ui)
+
+**描述**: 当前统一广告管理UI使用多租户的文件管理UI(`file-management-ui-mt`),这与统一广告的无租户隔离设计不一致。本故事从单租户的文件管理UI复制创建统一版本。
+
+**背景说明**:
+- **当前问题**: 统一广告管理UI (`unified-advertisement-management-ui`) 使用 `@d8d/file-management-ui-mt` 的 `FileSelector` 组件(多租户)
+- **不一致性**: 统一广告管理UI本身是无租户隔离的,但使用的文件选择器却是多租户版本
+- **解决方案**: 从 `file-management-ui` 复制创建 `unified-file-management-ui`(API指向统一文件模块)
+
+**前置条件**: 故事010.009已完成
+
+**任务**:
+- [ ] 创建 `packages/unified-file-management-ui` 包(从 `file-management-ui` 复制并改造)
+- [ ] 实现文件管理组件(列表、上传、删除)
+- [ ] 实现文件选择器组件(供其他UI包使用)
+- [ ] API客户端指向统一文件模块端点
+- [ ] 编写完整的组件测试和集成测试
+
+**完成日期**: _待定_
+**相关文件**: `docs/stories/010.010.story.md`
+
+**测试覆盖**:
+- 组件测试
+- API集成测试
+- 文件选择器测试
+
+### Story 11: 集成统一文件模块到统一广告和租户后台 📝 待开始
+
+**标题**: 集成统一文件模块到统一广告和租户后台
+
+**描述**: 将统一文件模块集成到统一广告模块、统一广告管理UI、Server包和租户后台。
+
+**前置条件**:
+- 故事010.009已完成:统一文件模块已创建
+- 故事010.010已完成:统一文件管理UI已创建
+
+**任务**:
+- [ ] 统一广告模块更新为使用 `UnifiedFile` 实体(而非 `FileMt`)
+- [ ] 统一广告管理UI更新为使用统一文件选择器(而非多租户版本)
+- [ ] Server包注册统一文件模块路由和实体
+- [ ] 租户后台集成统一文件管理功能
+- [ ] E2E测试验证文件上传和选择器功能
+- [ ] 回归测试确保统一广告模块功能不受影响
+
+**完成日期**: _待定_
+**相关文件**: `docs/stories/010.011.story.md`
+
+**测试覆盖**:
+- 统一广告模块回归测试
+- 统一广告管理UI回归测试
+- Server包集成测试
+- E2E测试
+
 ## 兼容性要求
 
 - [x] 现有广告API端点保持向后兼容(或提供适配层)
@@ -663,7 +746,7 @@ export const adminUnifiedAdApiRoutes = api.route('/api/v1/admin/unified-advertis
 ## 验收标准
 
 ### 完成定义 (Definition of Done)
-- [ ] 所有故事完成且验收标准满足(Story 7、8 进行中
+- [ ] 所有故事完成且验收标准满足(Story 7、8、9、10、11 待完成
 - [x] 现有功能通过测试验证
 - [x] 集成点正常工作
 - [x] 文档适当更新
@@ -677,15 +760,21 @@ export const adminUnifiedAdApiRoutes = api.route('/api/v1/admin/unified-advertis
 5. [x] 权限控制正确(只有超级管理员可管理)
 6. [ ] 租户后台UI交互E2E测试覆盖完整流程(Story 7)
 7. [ ] 小程序端广告展示E2E测试验证通过(Story 8)
+8. [ ] 统一文件模块创建完成(Story 9)
+9. [ ] 统一文件管理UI创建完成(Story 10)
+10. [ ] 统一文件模块集成到统一广告和租户后台(Story 11)
 
 ### 技术验收
 1. [x] 所有单元测试通过
 2. [x] 集成测试通过
 3. [ ] 租户后台UI交互E2E测试通过(Story 7)
 4. [ ] 小程序端广告展示E2E测试通过(Story 8)
-5. [x] 代码符合项目编码规范
-6. [x] 无TypeScript类型错误
-7. [x] ESLint检查通过
+5. [ ] 统一文件模块测试通过(Story 9)
+6. [ ] 统一文件管理UI测试通过(Story 10)
+7. [ ] 集成和回归测试通过(Story 11)
+8. [x] 代码符合项目编码规范
+9. [x] 无TypeScript类型错误
+10. [x] ESLint检查通过
 
 ## 参考文档
 

+ 233 - 0
docs/stories/010.009.story.md

@@ -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代理填写_

+ 207 - 0
docs/stories/010.010.story.md

@@ -0,0 +1,207 @@
+# Story 010.010: 创建统一文件管理UI包
+
+## Status
+Approved
+
+## Story
+
+**As a** 超级管理员,
+**I want** 一个统一的文件管理UI包,
+**so that** 可以在租户管理后台统一管理所有文件,统一广告管理UI使用统一的文件选择器组件。
+
+## Background
+
+**当前问题**:
+- 统一广告管理UI (`unified-advertisement-management-ui`) 使用 `@d8d/file-management-ui-mt` 的 `FileSelector` 组件(多租户)
+- **不一致性**: 统一广告管理UI本身是无租户隔离的,但使用的文件选择器却是多租户版本
+
+**解决方案**:
+- 参照统一广告管理UI的设计模式,从单租户的 `file-management-ui` 复制创建统一版本
+- 创建 `unified-file-management-ui`(API指向统一文件模块)
+
+## Acceptance Criteria
+
+1. 创建 `packages/unified-file-management-ui` 包,从 `file-management-ui` 复制并改造为指向统一文件模块
+2. 实现文件管理组件(列表、上传、删除)
+3. 实现文件选择器组件(供其他UI包使用)
+4. API客户端指向统一文件模块端点(`/api/v1/admin/unified-files`)
+5. 包含完整的组件测试和集成测试
+
+## Tasks / Subtasks
+
+- [ ] **任务1: 创建UI包结构和配置文件** (AC: 1)
+  - [ ] 创建 `packages/unified-file-management-ui` 目录
+  - [ ] 创建 `package.json`,配置包名为 `@d8d/unified-file-management-ui`
+  - [ ] 创建 `tsconfig.json`
+  - [ ] 创建 `vitest.config.ts`(设置 `fileParallelism: false`,配置别名)
+  - [ ] 创建 `src/` 子目录:`components/`, `api/`, `hooks/`, `types/`, `utils/`
+  - [ ] 创建 `tests/` 子目录:`integration/`, `unit/`
+
+- [ ] **任务2: 创建API客户端** (AC: 4)
+  - [ ] 创建 `src/api/client.ts`,使用 `hc` RPC客户端
+  - [ ] 配置API端点指向 `/api/v1/admin/unified-files`
+  - [ ] 创建类型定义(从RPC推断)
+  - [ ] 创建API方法:`uploadFile`, `getFiles`, `getFile`, `deleteFile`
+
+- [ ] **任务3: 创建React Hooks** (AC: 1)
+  - [ ] 创建 `src/hooks/useUnifiedFiles.ts`(文件列表)
+  - [ ] 创建 `src/hooks/useUnifiedFileUpload.ts`(文件上传)
+  - [ ] 创建 `src/hooks/useUnifiedFileDelete.ts`(文件删除)
+
+- [ ] **任务4: 实现文件管理组件** (AC: 2)
+  - [ ] 创建 `src/components/UnifiedFileList.tsx`(文件列表)
+  - [ ] 创建 `src/components/UnifiedFileUpload.tsx`(文件上传)
+  - [ ] 创建 `src/components/UnifiedFileManagement.tsx`(管理页面主组件)
+
+- [ ] **任务5: 实现文件选择器组件** (AC: 3)
+  - [ ] 创建 `src/components/UnifiedFileSelector.tsx`(文件选择器)
+  - [ ] 支持单选和多选模式
+  - [ ] 支持文件类型过滤
+  - [ ] 支持搜索功能
+  - [ ] 添加 `data-testid` 属性用于测试
+
+- [ ] **任务6: 创建包导出入口** (AC: 1)
+  - [ ] 创建 `src/index.ts`,导出组件、Hooks、API客户端
+  - [ ] 配置 `package.json` 的 `exports` 字段
+
+- [ ] **任务7: 编写组件测试** (AC: 5)
+  - [ ] 创建 `tests/unit/UnifiedFileSelector.test.tsx`
+  - [ ] 创建 `tests/unit/UnifiedFileList.test.tsx`
+  - [ ] 创建 `tests/unit/UnifiedFileUpload.test.tsx`
+
+- [ ] **任务8: 编写集成测试** (AC: 5)
+  - [ ] 创建 `tests/integration/file-selector.integration.test.tsx`
+  - [ ] 创建 `tests/integration/file-upload.integration.test.tsx`
+  - [ ] 创建 `tests/integration/file-management.integration.test.tsx`
+
+- [ ] **任务9: 代码质量检查**
+  - [ ] 运行 `pnpm typecheck` 确保无TypeScript错误
+  - [ ] 运行 `pnpm lint` 确保代码符合规范
+  - [ ] 运行 `pnpm test` 确保所有测试通过
+  - [ ] 运行 `pnpm test:coverage` 确保覆盖率达标
+
+## Dev Notes
+
+### 项目结构信息
+
+**新包位置**:
+```
+packages/unified-file-management-ui/
+├── package.json
+├── tsconfig.json
+├── vitest.config.ts
+├── src/
+│   ├── components/
+│   │   ├── UnifiedFileList.tsx
+│   │   ├── UnifiedFileUpload.tsx
+│   │   ├── UnifiedFileSelector.tsx
+│   │   └── UnifiedFileManagement.tsx
+│   ├── api/
+│   │   └── client.ts
+│   ├── hooks/
+│   │   ├── useUnifiedFiles.ts
+│   │   ├── useUnifiedFileUpload.ts
+│   │   └── useUnifiedFileDelete.ts
+│   ├── types/
+│   │   └── index.ts
+│   ├── utils/
+│   │   └── file-utils.ts
+│   └── index.ts
+└── tests/
+    ├── integration/
+    │   ├── file-selector.integration.test.tsx
+    │   ├── file-upload.integration.test.tsx
+    │   └── file-management.integration.test.tsx
+    └── unit/
+        ├── UnifiedFileSelector.test.tsx
+        ├── UnifiedFileList.test.tsx
+        └── UnifiedFileUpload.test.tsx
+```
+
+**参考模块**:
+- 单租户文件管理UI: `packages/file-management-ui`
+- 统一广告管理UI: `packages/unified-advertisement-management-ui`
+
+### API客户端设计
+
+**RPC客户端使用**:
+```typescript
+import { hc } from '@d8d/shared-ui-components/utils/hc';
+import type { UnifiedFileRoutes } from '@d8d/unified-file-module';
+
+export const unifiedFileClient = hc<UnifiedFileRoutes>('/api/v1/admin/unified-files');
+```
+
+### 组件设计规范
+
+**文件选择器** (`UnifiedFileSelector.tsx`):
+- 使用RPC推断类型(不直接导入schema类型)
+- 添加 `data-testid` 属性用于测试
+- 支持单选和多选模式
+- 支持文件类型过滤
+- 支持搜索功能
+
+### 测试标准
+
+| 测试类型 | 最低要求 | 目标要求 |
+|----------|----------|----------|
+| 单元测试 | 70% | 80% |
+| 集成测试 | 50% | 60% |
+
+### 关键测试要求
+1. **组件测试**: 验证组件渲染正确
+2. **交互测试**: 验证用户交互(上传、删除、选择)
+3. **API集成测试**: 验证API调用正确
+4. **文件选择器测试**: 验证选择器功能(单选、多选、搜索)
+
+## Testing
+
+### 测试文件位置
+- 单元测试: `tests/unit/`
+- 集成测试: `tests/integration/`
+
+### 测试框架
+- **Vitest**: 主要测试运行器
+- **Testing Library**: React组件测试
+- **Happy DOM**: 轻量级DOM环境
+
+### 测试执行命令
+```bash
+# 进入UI包目录
+cd packages/unified-file-management-ui
+
+# 运行所有测试
+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代理填写_

+ 209 - 0
docs/stories/010.011.story.md

@@ -0,0 +1,209 @@
+# Story 010.011: 集成统一文件模块到统一广告和租户后台
+
+## Status
+Approved
+
+## Story
+
+**As a** 超级管理员,
+**I want** 统一文件模块集成到统一广告模块和租户后台,
+**so that** 可以在租户管理后台统一管理所有文件,统一广告模块使用统一文件实体。
+
+## Background
+
+**前置条件**:
+- 故事010.009已完成:统一文件模块 (`unified-file-module`) 已创建
+- 故事010.010已完成:统一文件管理UI (`unified-file-management-ui`) 已创建
+
+**需要完成的集成**:
+1. 统一广告模块更新为使用 `UnifiedFile` 实体(而非 `FileMt`)
+2. 统一广告管理UI更新为使用统一文件选择器(而非多租户版本)
+3. Server包注册统一文件模块路由
+4. 租户后台集成统一文件管理功能
+
+## Acceptance Criteria
+
+1. 统一广告模块更新Entity关联,使用 `UnifiedFile` 替代 `FileMt`
+2. 统一广告管理UI更新依赖,使用 `@d8d/unified-file-management-ui`
+3. Server包注册统一文件模块路由和实体
+4. 租户后台添加文件管理菜单项和路由
+5. 统一广告模块所有测试通过
+6. 统一广告管理UI所有测试通过
+7. E2E测试验证文件上传和选择器功能
+
+## Tasks / Subtasks
+
+- [ ] **任务1: 更新统一广告模块Entity** (AC: 1)
+  - [ ] 修改 `unified-advertisement.entity.ts`,将 `FileMt` 替换为 `UnifiedFile`
+  - [ ] 更新导入语句:`import { UnifiedFile } from '@d8d/unified-file-module'`
+  - [ ] 更新 `@ManyToOne` 关联定义
+  - [ ] 更新 `@JoinColumn` 定义
+
+- [ ] **任务2: 更新统一广告模块依赖** (AC: 1)
+  - [ ] 修改 `package.json`,添加 `@d8d/unified-file-module` 依赖
+  - [ ] 移除或保留 `@d8d/core-module-mt` 依赖(如果其他模块还需要)
+  - [ ] 运行 `pnpm install` 更新依赖
+
+- [ ] **任务3: 更新统一广告模块测试** (AC: 5)
+  - [ ] 更新测试文件中的 `FileMt` 引用为 `UnifiedFile`
+  - [ ] 更新测试数据工厂
+  - [ ] 运行测试验证修改正确
+
+- [ ] **任务4: 更新统一广告管理UI依赖** (AC: 2)
+  - [ ] 修改 `package.json`,添加 `@d8d/unified-file-management-ui` 依赖
+  - [ ] 移除 `@d8d/file-management-ui-mt` 依赖
+  - [ ] 更新 `vitest.config.ts` 别名配置
+  - [ ] 运行 `pnpm install` 更新依赖
+
+- [ ] **任务5: 更新统一广告管理UI组件** (AC: 2)
+  - [ ] 修改 `UnifiedAdvertisementManagement.tsx`,将 `FileSelector` 替换为 `UnifiedFileSelector`
+  - [ ] 更新导入语句
+  - [ ] 更新组件props(如果有差异)
+
+- [ ] **任务6: 更新统一广告管理UI测试** (AC: 6)
+  - [ ] 更新所有测试文件中的mock:`@d8d/file-management-ui-mt` → `@d8d/unified-file-management-ui`
+  - [ ] 更新mock组件名称
+  - [ ] 运行测试验证修改正确
+
+- [ ] **任务7: Server包集成统一文件模块** (AC: 3)
+  - [ ] 在 `packages/server/src/index.ts` 中导入统一文件模块
+  - [ ] 导入 `UnifiedFile` 实体
+  - [ ] 导入统一文件管理员路由
+  - [ ] 注册 `UnifiedFile` 实体到数据源
+  - [ ] 注册管理员路由:`app.route('/api/v1/admin/unified-files', unifiedFileAdminRoutes)`
+
+- [ ] **任务8: 租户后台集成统一文件管理** (AC: 4)
+  - [ ] 在 `web/src/client/tenant/` 添加文件管理路由
+  - [ ] 在 `web/src/client/tenant/` 添加文件管理页面组件
+  - [ ] 添加文件管理菜单项(Files图标)
+  - [ ] 初始化API客户端(指向管理员API)
+
+- [ ] **任务9: 编写E2E测试** (AC: 7)
+  - [ ] 创建 `web/tests/e2e/tenant-file-management.spec.ts`
+  - [ ] 测试文件上传流程
+  - [ ] 测试文件列表显示
+  - [ ] 测试文件删除功能
+  - [ ] 测试文件选择器在广告管理中的使用
+
+- [ ] **任务10: 代码质量检查**
+  - [ ] 运行 `pnpm typecheck` 确保无TypeScript错误
+  - [ ] 运行 `pnpm lint` 确保代码符合规范
+  - [ ] 运行所有测试确保通过
+  - [ ] 更新史诗010文档
+
+## Dev Notes
+
+### 修改的文件清单
+
+**统一广告模块** (`packages/unified-advertisements-module/`):
+- `src/entities/unified-advertisement.entity.ts` - 更新Entity关联
+- `src/entities/index.ts` - 更新导入
+- `package.json` - 添加依赖
+- `tests/**/*.test.ts` - 更新测试
+
+**统一广告管理UI** (`packages/unified-advertisement-management-ui/`):
+- `src/components/UnifiedAdvertisementManagement.tsx` - 更新组件
+- `package.json` - 更新依赖
+- `vitest.config.ts` - 更新别名配置
+- `tests/**/*.test.tsx` - 更新mock
+
+**Server包** (`packages/server/`):
+- `src/index.ts` - 注册路由和实体
+- `package.json` - 添加依赖
+
+**租户后台** (`web/src/client/tenant/`):
+- 添加路由配置
+- 添加页面组件
+- 更新菜单
+
+### Entity关联更新
+
+**更新前**:
+```typescript
+import { FileMt } from '@d8d/core-module-mt/file-module-mt';
+
+@Entity('unified_advertisement')
+export class UnifiedAdvertisement {
+  // ...
+
+  @ManyToOne(() => FileMt, { nullable: true })
+  @JoinColumn({ name: 'image_file_id' })
+  imageFile!: FileMt | null;
+}
+```
+
+**更新后**:
+```typescript
+import { UnifiedFile } from '@d8d/unified-file-module';
+
+@Entity('unified_advertisement')
+export class UnifiedAdvertisement {
+  // ...
+
+  @ManyToOne(() => UnifiedFile, { nullable: true })
+  @JoinColumn({ name: 'image_file_id' })
+  imageFile!: UnifiedFile | null;
+}
+```
+
+### 测试标准
+
+| 测试类型 | 要求 |
+|----------|------|
+| 统一广告模块测试 | 全部通过 |
+| 统一广告管理UI测试 | 全部通过 |
+| Server包集成测试 | 全部通过 |
+| E2E测试 | 全部通过 |
+
+### 关键测试要求
+1. **回归测试**: 确保统一广告模块原有功能不受影响
+2. **关联测试**: 验证 `UnifiedFile` 关联正确
+3. **集成测试**: 验证Server包路由注册正确
+4. **UI测试**: 验证文件选择器在广告管理中正常工作
+5. **E2E测试**: 验证完整的文件管理流程
+
+## Testing
+
+### 测试文件位置
+- E2E测试: `web/tests/e2e/`
+
+### 测试框架
+- **Playwright**: E2E测试
+
+### 测试执行命令
+```bash
+# 统一广告模块测试
+cd packages/unified-advertisements-module
+pnpm test
+
+# 统一广告管理UI测试
+cd packages/unified-advertisement-management-ui
+pnpm test
+
+# E2E测试
+cd web
+pnpm test:e2e:chromium
+```
+
+## 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代理填写_