# Story 010.012: 统一广告模块响应格式规范化 ## Status Ready for Review ## Story **As a** 开发者, **I want** 统一广告模块的API响应格式与项目规范(`shared-crud`)保持一致, **so that** 前端UI可以使用统一的数据处理模式,确保系统架构的一致性和可维护性。 ## Acceptance Criteria 1. 列表查询响应格式修改为标准格式:`{ data: [...], pagination: { total, current, pageSize } }` 2. 单项查询(get/create/update)响应格式修改为直接返回资源对象:`{ id, ... }` 3. 删除操作响应修改为 `204 No Content`(空响应) 4. 统一广告管理UI适配新的响应格式 5. 所有相关测试通过(模块测试、UI测试、集成测试) 6. API文档/Schema定义更新为新的响应格式 ## Tasks / Subtasks - [x] **任务1: 修改管理员广告路由响应格式** (AC: 1, 2, 3) - [x] 修改 `packages/unified-advertisements-module/src/routes/admin/unified-advertisements.admin.routes.ts` - [x] 列表响应:移除 `code`, `message`,将 `data.list` 改为 `data`(数组),将分页信息移到 `pagination` 对象,`page` 改为 `current` - [x] GET单项响应:移除 `code`, `message`,直接返回验证后的资源对象 - [x] CREATE响应:返回201状态码,直接返回资源对象 - [x] UPDATE响应:返回200状态码,直接返回资源对象 - [x] DELETE响应:返回204状态码,空响应(`c.body(null, 204)`) - [x] **任务2: 修改管理员广告类型路由响应格式** (AC: 1, 2, 3) - [x] 修改 `packages/unified-advertisements-module/src/routes/admin/unified-advertisement-types.admin.routes.ts` - [x] 应用与任务1相同的响应格式修改 - [x] **任务3: 修改用户端广告路由响应格式** (AC: 1, 2, 3) - [x] 修改 `packages/unified-advertisements-module/src/routes/unified-advertisements.crud.routes.ts` - [x] 列表响应:应用标准格式(注意:这是只读路由,只有GET操作) - [x] GET单项响应:直接返回资源对象 - [x] **任务4: 修改用户端广告类型路由响应格式** (AC: 1, 2, 3) - [x] 修改 `packages/unified-advertisements-module/src/routes/unified-advertisement-types.crud.routes.ts` - [x] 列表响应:应用标准格式 - [x] 修改 `packages/unified-advertisements-module/src/routes/unified-advertisement-types.routes.ts` 使用链式写法 - [x] **任务5: 更新路由Schema定义** (AC: 6) - [x] 修改所有路由的 `responses.openapi` schema定义以匹配新格式 - [x] 列表响应schema:`{ data: z.array(schema), pagination: { total, current, pageSize } }` - [x] 单项响应schema:直接使用资源schema(不包装) - [x] 删除响应schema:`204 No Content` - [x] **任务6: 适配统一广告管理UI** (AC: 4) - [x] 修改组件数据处理逻辑:适配新的响应格式(`response.data` 直接是数组,`response.pagination` 包含分页信息) - [x] 更新单项数据处理:适配直接返回资源对象的格式 - [x] 更新类型定义文件 `src/types/index.ts` - [x] 更新 `UnifiedAdvertisementTypeSelector.tsx` 中的数据访问 - [x] **任务7: 更新UI测试Mock数据** (AC: 5) - [x] 修改 `packages/unified-advertisement-management-ui/tests/` 中的mock响应格式 - [x] **任务8: 更新后端集成测试** (AC: 5) - [x] 修改 `packages/unified-advertisements-module/tests/integration/` 中的测试断言 - [x] 验证列表响应包含 `data` 数组和 `pagination` 对象 - [x] 验证单项响应直接返回资源对象 - [x] 验证删除返回204状态码 - [x] **任务9: 更新Server包集成测试** (AC: 5) - [x] 检查 `packages/server/tests/integration/` 中涉及统一广告的测试 - [x] 更新测试断言以匹配新的响应格式 - [x] 验证测试通过 - [x] **任务10: 类型检查和代码质量** (AC: 5) - [x] 运行 `pnpm typecheck` 确保无TypeScript类型错误 - [x] 运行所有相关测试并确保通过 (57/57 tests passed) ## Dev Notes ### 问题说明 **当前响应格式(不符合规范)** [Source: packages/unified-advertisements-module/src/routes/admin/unified-advertisements.admin.routes.ts]: ```typescript // 列表响应 - 当前格式 { code: 200, message: 'success', data: { list: [...], // ← 嵌套在 list 中 total: 100, page: 1, // ← 使用 page 而非 current pageSize: 10 } } // 单项响应 - 当前格式 { code: 200, message: 'success', data: { id: 1, ... } // ← 嵌套在 data 中 } // 删除响应 - 当前格式 { code: 200, message: 'Advertisement deleted successfully' // ← 有内容 } ``` **标准响应格式(generic-crud.routes.ts)** [Source: packages/shared-crud/src/routes/generic-crud.routes.ts]: ```typescript // 列表响应 - 标准格式 { data: [...], // ← 数组直接在根级别 pagination: { total: 100, current: 1, // ← 使用 current pageSize: 10 } } // 单项响应 - 标准格式 { id: 1, name: "..." } // ← 直接返回资源对象 // 删除响应 - 标准格式 204 No Content // ← 空响应 ``` ### 需要修改的文件清单 **后端路由文件**: 1. `packages/unified-advertisements-module/src/routes/admin/unified-advertisements.admin.routes.ts` 2. `packages/unified-advertisements-module/src/routes/admin/unified-advertisement-types.admin.routes.ts` 3. `packages/unified-advertisements-module/src/routes/unified-advertisements.crud.routes.ts` 4. `packages/unified-advertisements-module/src/routes/unified-advertisement-types.crud.routes.ts` **前端UI文件**: 1. `packages/unified-advertisement-management-ui/src/hooks/useAdvertisementManagement.ts` 2. `packages/unified-advertisement-management-ui/src/hooks/useAdTypeManagement.ts` 3. `packages/unified-advertisement-management-ui/tests/` 中的所有测试文件 **测试文件**: 1. `packages/unified-advertisements-module/tests/integration/` 中的所有集成测试 2. `packages/server/tests/integration/` 中涉及统一广告的测试(如有) ### 相关标准规范 **后端模块开发规范** [Source: docs/architecture/backend-module-package-standards.md]: - 使用 `OpenAPIHono` 定义路由 - 使用 `createRoute` 定义路由schema - 响应格式应与 `shared-crud` 保持一致 **编码标准** [Source: docs/architecture/coding-standards.md]: - 自定义路由必须使用 `parseWithAwait` 验证响应数据 - 使用 `z.coerce.date()` 和 `z.coerce.number()`(Zod 4.0需要泛型参数) ### 前一故事关键要点 **来自故事 010.011(集成统一文件模块)**: - 统一广告模块已完成迁移到 `UnifiedFile` 实体 - 统一广告管理UI已集成统一文件选择器 - 测试覆盖:57/57 模块测试通过,51/51 UI测试通过 - 关联查询:`relations: ['imageFile', 'advertisementType']` **来自故事 010.003(路由路径规范问题)**: - 模块内路由使用相对路径(如 `/` 和 `/:id`) - Server包注册时添加完整前缀(如 `/api/v1/admin/unified-advertisements`) ### API端点参考 **管理员广告API**: - `GET /api/v1/admin/unified-advertisements` - 列表(需修改响应格式) - `GET /api/v1/admin/unified-advertisements/:id` - 单项(需修改响应格式) - `POST /api/v1/admin/unified-advertisements` - 创建(需修改响应格式) - `PUT /api/v1/admin/unified-advertisements/:id` - 更新(需修改响应格式) - `DELETE /api/v1/admin/unified-advertisements/:id` - 删除(需修改响应格式) **管理员广告类型API**: - `GET /api/v1/admin/unified-advertisement-types` - 列表(需修改响应格式) - `GET /api/v1/admin/unified-advertisement-types/:id` - 单项(需修改响应格式) - `POST /api/v1/admin/unified-advertisement-types` - 创建(需修改响应格式) - `PUT /api/v1/admin/unified-advertisement-types/:id` - 更新(需修改响应格式) - `DELETE /api/v1/admin/unified-advertisement-types/:id` - 删除(需修改响应格式) **用户展示API**(只读): - `GET /api/v1/advertisements` - 列表(需修改响应格式) - `GET /api/v1/advertisements/:id` - 单项(需修改响应格式) - `GET /api/v1/advertisement-types` - 列表(需修改响应格式) ### Testing **测试文件位置** [Source: docs/architecture/testing-strategy.md]: - 后端模块测试:`packages/{module-name}/tests/` - UI包测试:`packages/{ui-name}/tests/` - Server集成测试:`packages/server/tests/integration/` **测试框架**: - 后端:Vitest + hono/testing - UI:Vitest + Testing Library **测试要求**: - 更新所有涉及响应格式的测试断言 - 验证新响应格式的正确性 - 确保测试覆盖率不低于修改前水平 ## Change Log | Date | Version | Description | Author | |------|---------|-------------|--------| | 2026-01-04 | 1.0 | 初始创建故事 | James (Dev Agent) | ## Dev Agent Record ### Agent Model Used Claude (d8d-model) via Happy CLI ### Debug Log References - 发现测试使用的是 `unified-advertisement-types.routes.ts` 而非 `unified-advertisement-types.crud.routes.ts` - 发现 `unified-advertisement-types.routes.ts` 使用非链式写法,需规范化 - 发现 `.routes.ts` 和 `.crud.routes.ts` 文件冗余问题 ### Completion Notes List - 所有响应格式已按 `shared-crud` 标准规范化 - 列表响应:`{ data: [...], pagination: { total, current, pageSize } }` - 单项响应:直接返回资源对象 `{ id, ... }` - 删除响应:`204 No Content` - 57/57 后端测试通过 - TypeScript 类型检查通过 - 统一广告管理UI已适配新格式 - **代码清理**:删除冗余的 `unified-advertisement-types.routes.ts`,统一使用 `.crud.routes.ts` 命名规范 ### File List **修改的源文件**: - `packages/unified-advertisements-module/src/routes/admin/unified-advertisements.admin.routes.ts` - `packages/unified-advertisements-module/src/routes/admin/unified-advertisement-types.admin.routes.ts` - `packages/unified-advertisements-module/src/routes/unified-advertisements.crud.routes.ts` - `packages/unified-advertisements-module/src/routes/unified-advertisement-types.crud.routes.ts` - `packages/unified-advertisements-module/src/routes/index.ts` - `packages/unified-advertisement-management-ui/src/components/UnifiedAdvertisementManagement.tsx` - `packages/unified-advertisement-management-ui/src/components/UnifiedAdvertisementTypeManagement.tsx` - `packages/unified-advertisement-management-ui/src/components/UnifiedAdvertisementTypeSelector.tsx` - `packages/unified-advertisement-management-ui/src/types/index.ts` - `packages/unified-advertisement-management-ui/src/index.ts` **删除的文件**: - `packages/unified-advertisements-module/src/routes/unified-advertisement-types.routes.ts` (冗余文件) **修改的测试文件**: - `packages/unified-advertisements-module/tests/integration/unified-advertisements.integration.test.ts` - `packages/server/tests/integration/unified-advertisement-auth.integration.test.ts` ## QA Results _待QA评审时填写_