Przeglądaj źródła

docs(story): 创建故事012.005 - 视频管理API扩展

- 创建故事012.005文档,状态为Approved
- 实现企业维度视频查询、批量下载和视频状态管理API

🤖 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 1 tydzień temu
rodzic
commit
cf1ca03886
1 zmienionych plików z 231 dodań i 0 usunięć
  1. 231 0
      docs/stories/012.005.story.md

+ 231 - 0
docs/stories/012.005.story.md

@@ -0,0 +1,231 @@
+# 故事 012.005:视频管理API扩展
+
+## 状态
+Approved
+
+## 故事
+**作为**企业用户,
+**我希望**能够查询企业关联的所有视频并支持批量下载,
+**以便**更好地管理员工工作视频,提高视频管理效率。
+
+**史诗上下文**:此故事是史诗012(用人方小程序API补充与数据库扩展)的第5个故事,为企业用户提供企业维度的视频查询和批量下载功能,完善用人方小程序的视频管理能力。
+
+## 验收标准
+从史诗文件复制的验收标准编号列表
+
+1. [ ] 企业维度视频查询接口返回企业关联的所有视频,支持按视频类型过滤
+2. [ ] 批量下载功能支持按企业或个人维度下载多个视频文件(返回文件URL列表)
+3. [ ] 视频状态管理功能完整(如实现状态字段)
+4. [ ] 视频查询性能优化,添加必要的数据索引
+5. [ ] 所有接口通过单元测试和集成测试
+
+## 任务 / 子任务
+将故事分解为实施所需的具体任务和子任务。
+在相关处引用适用的验收标准编号。
+
+- [ ] 任务1:企业维度视频查询API实现(order-module扩展)(AC:1,4)
+  - [ ] 在`allin-packages/order-module/src/routes/order-custom.routes.ts`中添加企业维度视频查询路由:
+    - [ ] `GET /order/company-videos` - 企业维度视频查询接口(支持按企业ID过滤、按视频类型过滤、分页、排序)
+  - [ ] 在`allin-packages/order-module/src/services/order.service.ts`中添加企业维度视频查询服务方法:
+    - [ ] `getCompanyVideos(companyId: number, filters: VideoFilters): Promise<VideoListResult>` - 企业维度视频查询
+    - [ ] 实现企业数据隔离:通过`employment_order.company_id` → `order_person_asset`关联链过滤视频
+  - [ ] 在`allin-packages/order-module/src/schemas/order.schema.ts`中添加对应的Zod Schema验证:
+    - [ ] `CompanyVideosQuerySchema` - 企业视频查询参数schema(companyId、assetType、page、pageSize、sort等)
+    - [ ] `CompanyVideoResponseSchema` - 企业视频响应schema(包含文件详情、订单信息等)
+  - [ ] 更新`allin-packages/order-module/src/routes/index.ts`导出新的路由
+
+- [ ] 任务2:批量下载功能实现(AC:2)
+  - [ ] 在`allin-packages/order-module/src/routes/order-custom.routes.ts`中添加批量下载路由:
+    - [ ] `POST /order/batch-download` - 批量下载接口(支持企业维度或个人维度视频批量下载)
+  - [ ] 在`allin-packages/order-module/src/services/order.service.ts`中添加批量下载服务方法:
+    - [ ] `batchDownloadVideos(companyId: number, filters: BatchDownloadFilters): Promise<BatchDownloadResult>` - 批量下载文件
+    - [ ] 返回文件URL列表或生成临时打包文件(基于file-module的预签名URL功能)
+  - [ ] 在`allin-packages/order-module/src/schemas/order.schema.ts`中添加对应的Zod Schema验证:
+    - [ ] `BatchDownloadRequestSchema` - 批量下载请求schema(下载范围:企业/个人、视频类型过滤、文件ID列表等)
+    - [ ] `BatchDownloadResponseSchema` - 批量下载响应schema(文件URL列表、临时打包文件URL等)
+
+- [ ] 任务3:视频状态管理增强(AC:3)
+  - [ ] 数据库schema扩展:在`order_person_asset`表添加`status`字段(枚举类型,默认值`pending`):
+    - [ ] 枚举值:`pending`(待审核)、`verified`(已验证)、`rejected`(已拒绝)
+    - [ ] 类型:`varchar(20)`,可为空,默认值`'pending'`
+  - [ ] 更新TypeORM实体定义`allin-packages/order-module/src/entities/order-person-asset.entity.ts`:
+    - [ ] 添加`status`字段定义,使用`AssetStatus`枚举类型
+    - [ ] 更新实体注释说明
+  - [ ] 在`allin-packages/order-module/src/schemas/order.schema.ts`中添加视频状态相关Schema:
+    - [ ] `AssetStatus`枚举定义
+    - [ ] `UpdateAssetStatusSchema` - 更新视频状态请求schema
+  - [ ] 在`allin-packages/order-module/src/routes/order-custom.routes.ts`中添加视频状态管理路由:
+    - [ ] `PUT /order/videos/{id}/status` - 更新视频审核状态接口
+  - [ ] 在`allin-packages/order-module/src/services/order.service.ts`中添加视频状态管理服务方法:
+    - [ ] `updateVideoStatus(assetId: number, status: AssetStatus): Promise<OrderPersonAsset>` - 更新视频状态
+
+- [ ] 任务4:性能优化与数据库索引(AC:4)
+  - [ ] 分析企业维度视频查询性能瓶颈,添加针对性的数据库索引:
+    - [ ] `order_person_asset.asset_type`索引(视频类型过滤优化)
+    - [ ] `order_person_asset.related_time`索引(按时间排序优化)
+    - [ ] 复合索引:`order_person_asset(order_id, person_id, asset_type)`(关联查询优化)
+  - [ ] 优化复杂查询:使用TypeORM QueryBuilder实现高效的企业维度视频查询(通过`employment_order`表关联过滤)
+  - [ ] 考虑大数据量下的分页策略和查询缓存机制
+  - [ ] 评估并实现物化视图(如需要),用于高频视频查询的结果缓存
+
+- [ ] 任务5:测试实现(AC:5)
+  - [ ] **企业维度视频查询测试**:
+    - [ ] 在`allin-packages/order-module/tests/integration/order.integration.test.ts`中添加企业维度视频查询接口的集成测试
+    - [ ] 测试企业维度视频查询的正确性(mock `order_person_asset`和`employment_order`表数据)
+    - [ ] 测试按视频类型过滤功能(`asset_type` = `salary_video`、`tax_video`、`checkin_video`、`work_video`)
+    - [ ] 测试企业数据隔离:不同企业用户只能访问自己企业的视频数据
+    - [ ] 测试分页和排序功能
+  - [ ] **批量下载功能测试**:
+    - [ ] 测试企业维度批量下载功能(返回文件URL列表)
+    - [ ] 测试个人维度批量下载功能(基于personId过滤)
+    - [ ] 测试批量下载请求参数验证(文件ID列表、视频类型过滤等)
+    - [ ] 验证文件URL有效性(通过file-module的预签名URL功能)
+  - [ ] **视频状态管理测试**:
+    - [ ] 测试视频状态更新接口(pending → verified,pending → rejected等)
+    - [ ] 测试状态字段默认值(新创建的视频资产status应为`pending`)
+    - [ ] 测试状态更新权限验证(只有授权用户可更新视频状态)
+  - [ ] **性能测试**:
+    - [ ] 建立企业维度视频查询性能基准,测试大数据量(1000+视频记录)下的响应时间
+    - [ ] 验证数据库索引优化效果
+    - [ ] 测试批量下载查询性能
+
+## 开发笔记
+仅填充从docs文件夹中的实际工件提取的相关信息,与此故事相关:
+
+### 先前故事洞察
+基于故事012.001-012.004的已完成实施:
+1. **故事012.001**:数据库schema扩展已完成,`order_person_asset`表的`asset_type`枚举已扩展支持视频类型(`salary_video`、`tax_video`、`checkin_video`、`work_video`)
+2. **故事012.002**:企业用户认证API已实现,提供企业用户认证中间件`enterpriseAuthMiddleware`
+3. **故事012.003**:人才扩展API已实现个人维度视频查询接口`GET /disability-person/{id}/videos`
+   - **职责划分**:故事012.003专注于**个人维度视频查询**(查询特定残疾人员的关联视频)
+   - **与本故事关系**:故事012.005专注于**企业维度视频查询**(查询企业关联的所有视频),两者职责互补不重叠
+4. **故事012.004**:订单统计与数据统计API已实现,提供企业数据隔离实现模式参考(通过`employment_order.company_id`关联过滤)
+5. **故事012.008**:路由路径规范修复已完成,确保API路径前缀`/api/v1/yongren`在server包统一注册
+
+### 数据模型
+基于现有实体定义和故事012.001的数据库schema扩展:
+
+**OrderPersonAsset实体**(allin-packages/order-module/src/entities/order-person-asset.entity.ts):
+- 用于视频管理:`asset_type`枚举值已扩展支持视频类型(`salary_video`、`tax_video`、`checkin_video`、`work_video`)
+- `asset_file_type`字段:`video`表示视频文件
+- 关联关系:通过`order_id`关联`employment_order`表(包含`company_id`字段)
+- 文件关联:通过`file_id`关联`files`表(file-module)
+- **新增字段**:`status`(视频审核状态,枚举:`pending`、`verified`、`rejected`)
+
+**EmploymentOrder实体**(allin-packages/order-module/src/entities/employment-order.entity.ts):
+- 用于企业数据隔离:包含`company_id`字段(用人单位ID)
+- 关联关系:`employment_order` → `order_person_asset`(通过`order_id`关联)
+
+**File实体**(packages/file-module/src/entities/file.entity.ts):
+- 用于文件下载:提供`fullUrl`预签名URL访问
+- MinIO存储:文件存储在MinIO对象存储中
+
+### API规范
+**API路径约定**:
+所有新增API必须遵循`/api/v1/yongren`前缀约定,路由在模块包内不应包含此前缀,前缀在server包注册时统一添加。
+
+**企业维度视频查询API接口设计**(order-module扩展):
+1. 企业维度视频查询:`GET /order/company-videos`(企业维度,支持视频类型过滤、分页、排序)
+   - 查询参数:`companyId`(可选,从认证用户获取)、`assetType`(视频类型过滤)、`page`、`pageSize`、`sortBy`、`sortOrder`
+   - 响应:视频列表(包含文件详情、订单信息、人员信息等)
+
+**批量下载API接口设计**:
+1. 批量下载:`POST /order/batch-download`(支持企业维度或个人维度批量下载)
+   - 请求参数:`downloadScope`(`company`或`person`)、`companyId`、`personId`、`assetTypes`(视频类型数组)、`fileIds`(文件ID数组)
+   - 响应:文件URL列表或临时打包文件URL
+
+**视频状态管理API接口设计**:
+1. 更新视频审核状态:`PUT /order/videos/{id}/status`(更新视频审核状态)
+   - 请求参数:`status`(`pending`、`verified`、`rejected`)
+   - 响应:更新后的视频资产信息
+
+**认证要求**:
+- 所有接口需要企业用户权限验证
+- 使用故事012.002实现的`enterpriseAuthMiddleware`中间件
+- 企业用户只能访问自己关联的企业数据(通过`company_id`验证)
+
+**企业数据隔离实现细节**:
+- 在服务层实现企业数据过滤:所有查询必须包含`company_id`条件(从认证用户的`company_id`字段获取)
+- 对于企业维度视频查询:通过`employment_order.company_id`过滤(`employment_order` → `order_person_asset`关联链)
+- 对于批量下载:下载范围限定在企业关联的视频数据
+
+### 组件规范
+不适用(后端API故事)。
+
+### 文件位置
+基于项目结构和后端模块包规范:
+
+**订单模块位置**:
+- `allin-packages/order-module/src/routes/order-custom.routes.ts` - 路由文件位置(新增企业维度视频查询、批量下载、视频状态管理路由)
+- `allin-packages/order-module/src/services/order.service.ts` - 服务层文件位置(新增企业维度视频查询、批量下载、视频状态管理服务方法)
+- `allin-packages/order-module/src/schemas/order.schema.ts` - Schema验证文件位置(新增视频查询、批量下载、状态管理相关Schema)
+- `allin-packages/order-module/src/entities/order-person-asset.entity.ts` - 实体文件位置(新增`status`字段)
+- `allin-packages/order-module/tests/integration/order.integration.test.ts` - 集成测试位置(新增测试用例)
+
+**文件模块位置**(用于批量下载):
+- `packages/file-module/src/services/file.service.ts` - 文件服务(提供预签名URL生成功能)
+- `packages/file-module/src/entities/file.entity.ts` - 文件实体(`fullUrl`预签名URL属性)
+
+### 技术约束
+- **API路径规范**:模块包内路由不应包含`/api/v1/yongren`前缀,前缀在server包统一注册 [史诗012文档](docs/prd/epic-012-api-supplement-for-employer-mini-program.md#故事012-08)
+- **企业数据隔离**:企业用户只能访问自己关联的企业数据,通过`company_id`验证
+- **性能要求**:视频查询需要优化,大数据量下响应时间应可接受
+- **数据库兼容性**:使用PostgreSQL 17,TypeORM 0.3.25 [技术栈文档](docs/architecture/tech-stack.md)
+- **文件下载安全性**:批量下载应使用预签名URL,避免直接文件系统访问
+- **状态字段设计**:`status`字段应为可为空字段,确保向后兼容(现有记录status为NULL)
+- **枚举值定义**:`AssetStatus`枚举应在schema中定义,供前端使用
+- **编码模式例外**:企业维度视频查询优先使用TypeORM QueryBuilder,复杂关联查询可使用JOIN优化性能
+
+### 项目结构说明
+- Monorepo结构,`allin-packages/`用于业务模块
+- 订单模块(order-module)已存在,本次为功能扩展
+- 模块间通过依赖注入和TypeORM关联关系进行数据访问
+- 文件下载依赖file-module的预签名URL功能
+
+### 测试
+列出开发者需要遵循的相关测试标准:
+
+#### 测试文件位置
+- 单元测试:`allin-packages/order-module/tests/unit/**/*.test.ts`
+- 集成测试:`allin-packages/order-module/tests/integration/order.integration.test.ts`
+
+#### 测试标准
+- 测试框架:Vitest
+- 数据库测试:使用测试数据库和事务回滚
+- 覆盖率要求:单元测试 ≥ 80%,集成测试 ≥ 60%
+
+#### 测试框架和模式
+- **单元测试**:测试服务层逻辑、视频查询逻辑、状态管理逻辑
+- **集成测试**:测试API端点、数据库查询、企业数据隔离
+- **性能测试**:验证视频查询响应时间
+- **安全测试**:验证企业数据隔离,防止跨企业数据访问
+
+#### 此故事的特定测试要求
+1. **企业数据隔离测试**:验证企业用户只能访问自己企业的视频数据
+2. **视频查询准确性测试**:验证企业维度视频查询结果与数据库实际数据一致
+3. **视频类型过滤测试**:测试按`asset_type`视频类型过滤功能
+4. **批量下载功能测试**:验证批量下载返回正确的文件URL列表
+5. **视频状态管理测试**:测试视频审核状态更新流程
+6. **性能基准测试**:建立企业维度视频查询性能基准,确保响应时间可接受
+7. **边缘情况测试**:测试空数据查询、无效企业ID处理、部分字段缺失时的优雅处理
+
+## 变更日志
+跟踪对此故事文档所做的更改
+
+| 日期 | 版本 | 描述 | 作者 |
+|------|------|------|------|
+| 2025-12-17 | 1.0 | 初始故事创建 | Bob(Scrum Master) |
+
+## 开发代理记录
+此部分由开发代理在实施过程中填充
+
+### 使用的代理模型
+
+### 调试日志引用
+
+### 完成笔记列表
+
+### 文件列表
+
+## QA结果
+来自QA代理对已完成故事实施的QA审查结果