# Story 010.004: 修复路由参数类型规范问题 ## 元数据 | 字段 | 值 | |------|-----| | **史诗** | Epic 010: 统一广告管理系统 | | **状态** | Ready for Review | | **优先级** | 中 | | **故事类型** | 修复 (Bug Fix) | | **工作量** | 1小时 | | **负责人** | - | | **创建日期** | 2026-01-03 | ## 故事描述 ### 问题描述 统一广告模块 (`unified-advertisements-module`) 的路由定义中缺少 `params` schema 定义,导致 RPC 客户端推断出的 `:id` 参数类型为 `string`,而不是 `number`。这违反了后端模块开发规范,需要在路由 schema 中添加 `params` 定义,使用 `z.coerce.number()` 进行类型转换。 ### 问题影响 - 前端 UI 包需要手动将 number 转换为 string(`String(id)`) - RPC 客户端类型推断不准确 - 不符合 `createCrudRoutes` 的开发规范 ### 根本原因 故事 010.001 实施时,路由定义使用的是手动方式而非 `createCrudRoutes`,没有在 schema 中定义 `request.params`,导致 Hono RPC 客户端无法正确推断参数类型。 ## 验收标准 ### 功能验收 - [x] 所有管理员路由(广告、广告类型)的 `/:id` 操作都包含 `params` schema 定义 - [x] `params` 使用 `z.coerce.number()` 进行类型转换 - [x] RPC 客户端能正确推断 `:id` 参数为 `number` 类型 - [x] 集成测试全部通过 ### 技术验收 - [x] 路由 schema 符合后端模块开发规范 - [x] 前端 UI 包无需手动转换类型(可直接传递 number) - [x] 代码通过类型检查 ## 任务清单 ### 任务1: 修复管理员广告路由 params 定义 - [x] 修改 `unified-advertisements.admin.routes.ts` - [x] 为 `getRoute` 添加 `request.params` 定义 - [x] 为 `updateRoute` 添加 `request.params` 定义 - [x] 为 `deleteRoute` 添加 `request.params` 定义 ### 任务2: 修复管理员广告类型路由 params 定义 - [x] 修改 `unified-advertisement-types.admin.routes.ts` - [x] 为 `getRoute` 添加 `request.params` 定义 - [x] 为 `updateRoute` 添加 `request.params` 定义 - [x] 为 `deleteRoute` 添加 `request.params` 定义 ### 任务3: 更新 UI 包移除类型转换 - [x] 修改 `unified-advertisement-management-ui` 组件 - [x] 移除 `String(id)` 类型转换 - [x] 验证类型检查通过 ### 任务4: 更新集成测试 - [x] 更新集成测试中的 mock 数据类型 - [x] 验证所有测试通过 ## 开发笔记 ### 修复参考 对比项目 `createCrudRoutes` 的正确实现方式: **正确示例** (createCrudRoutes): ```typescript const getRouteDef = createRoute({ method: 'get', path: '/{id}', middleware, request: { params: z.object({ id: z.coerce.number().openapi({ param: { name: 'id', in: 'path' }, example: 1, description: '资源ID' }) }) }, // ... }); ``` **错误示例** (修复前的 unified-advertisements-module): ```typescript const getRoute = createRoute({ method: 'get', path: '/:id', middleware: [tenantAuthMiddleware] as const, // ❌ 缺少 request.params 定义 responses: { /* ... */ } }); ``` **正确示例** (修复后): ```typescript const getRoute = createRoute({ method: 'get', path: '/:id', middleware: [tenantAuthMiddleware] as const, request: { params: z.object({ id: z.coerce.number().openapi({ param: { name: 'id', in: 'path' }, example: 1, description: '广告ID' }) }) }, responses: { /* ... */ } }); ``` ### 修改文件清单 #### 后端模块文件 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` #### 前端 UI 文件 3. `packages/unified-advertisement-management-ui/src/components/UnifiedAdvertisementManagement.tsx` 4. `packages/unified-advertisement-management-ui/src/components/UnifiedAdvertisementTypeManagement.tsx` #### 测试文件 5. `packages/unified-advertisements-module/tests/integration/unified-advertisements.integration.test.ts` ### 关键变更说明 **后端变更**: - 在每个带 `:id` 的路由中添加 `request.params` 定义 - 使用 `z.coerce.number()` 将字符串参数转换为数字 **前端变更**: - 移除 `String(id)` 类型转换,直接传递 number 类型 ### 测试验证 ```bash # 后端模块测试 pnpm --filter @d8d/unified-advertisements-module test # 前端 UI 包类型检查 pnpm --filter @d8d/unified-advertisement-management-ui typecheck ``` ## 完成备注 ### 实施总结 已成功修复统一广告模块的路由参数类型规范问题。所有 `/:id` 路由现在都正确包含 `request.params` 定义,使用 `z.coerce.number()` 进行类型转换。 ### 修改文件 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-advertisement-management-ui/src/components/UnifiedAdvertisementManagement.tsx` 4. `packages/unified-advertisement-management-ui/src/components/UnifiedAdvertisementTypeManagement.tsx` ### 测试结果 - ✅ 后端模块集成测试: 57/57 通过 - ✅ 后端模块类型检查: 通过 ### 开发代理 - **Agent**: James (dev) - **模型**: d8d-model - **完成日期**: 2026-01-03 ## 相关文档 - [后端模块包开发规范](../architecture/backend-module-package-standards.md) - [史诗 010: 统一广告管理系统](../prd/epic-010-unified-ad-management.md) - [故事 010.001: 创建统一广告模块](010.001.story.md) - [故事 010.002: 创建统一广告管理UI包](010.002.story.md) - [故事 010.003: 修复路由路径规范问题](010.003.story.md)