# Story 13.13 代码审查报告 - 订单统计字段显示修复 **审查日期**: 2026-01-15 **审查类型**: 对抗性代码审查 (ADVERSARIAL Senior Developer Code Review) **审查范围**: Story 13.13 - 订单统计字段显示修复 --- ## 审查发现的关键问题 ### 问题 1: 后端路由结构不匹配 RPC 客户端类型 (CRITICAL) **文件**: `allin-packages/order-module/src/routes/order-custom.routes.ts` **问题描述**: - `orderStatsRoute` 定义为扁平路径 `/company-orders/{id}/stats` - Hono RPC 客户端期望嵌套路径结构 `company-orders` → `:id` → `stats` - 导致前端无法通过 `enterpriseOrderClient['company-orders'][':id']['stats']` 访问统计接口 **根本原因**: Hono 的 RPC 客户端使用类型推断生成客户端结构,需要后端路由使用嵌套结构才能正确映射。 **修复方案**: ```typescript // 修复前:扁平路由 const orderStatsRoute = createRoute({ path: '/company-orders/{id}/stats', // 错误:扁平路径 ... }); // 修复后:嵌套路由结构 enterpriseOrderCustomRoutes .route('/company-orders', new OpenAPIHono() .openapi({ ...companyOrdersRoute, path: '' }, async (c) => { ... }) // 列表 .openapi(orderStatsRoute, async (c) => { ... }) // 统计 (path: '/:id/stats') ) ``` **修改的文件**: - `allin-packages/order-module/src/routes/order-custom.routes.ts` (行 856-907, 1399-1487) --- ### 问题 2: 订单统计 API 未被调用 (CRITICAL) **文件**: `mini-ui-packages/yongren-order-management-ui/src/pages/OrderList/OrderList.tsx` **问题描述**: 通过 Playwright MCP 实际测试验证发现: - 企业小程序订单列表页面的所有统计字段显示为 `0/0 0%` - 网络请求监控显示没有调用 `/company-orders/{id}/stats` 接口 - `useOrderStats` hook 静默失败,没有抛出错误 **根本原因**: 与问题 1 相关,由于路由结构不匹配,RPC 客户端无法正确访问统计接口。 **修复方案**: 修复后端路由结构(见问题 1)后,前端需要重新编译以获取更新后的类型定义。 --- ### 问题 3: 前端使用默认值掩盖 API 失败 (MEDIUM) **文件**: `mini-ui-packages/yongren-order-management-ui/src/pages/OrderList/OrderList.tsx` (行 65-67) **问题描述**: ```typescript const checkinStats = statsData?.checkinStats || { current: 0, total: order.actualPeople, percentage: 0 } const salaryVideoStats = statsData?.salaryVideoStats || { current: 0, total: order.actualPeople, percentage: 0 } const taxVideoStats = statsData?.taxVideoStats || { current: 0, total: order.actualPeople, percentage: 0 } ``` 当 API 调用失败时,前端会回退到默认值 `{ current: 0, total: order.actualPeople, percentage: 0 }`,这会掩盖 API 调用的真实问题。 **建议改进**: ```typescript // 添加错误处理和日志记录 const { data: statsData, isLoading: statsLoading, error: statsError } = useOrderStats(order.id); if (statsError) { console.error(`获取订单 ${order.id} 统计数据失败:`, statsError); } // 区分加载状态、错误状态和无数据状态 const checkinStats = statsData?.checkinStats; const showFallback = !statsLoading && !statsData; ``` --- ### 问题 4: E2E 测试凭证不匹配 (MINOR) **文件**: `web/tests/e2e/specs/cross-platform/order-stats-fix.spec.ts` (行 26-27) **问题描述**: ```typescript const TEST_USER_PHONE = '13800001111'; // 错误的手机号 const TEST_USER_PASSWORD = process.env.TEST_ENTERPRISE_PASSWORD || 'password123'; ``` 测试使用的企业账号与实际测试环境不匹配。 **修复方案**: ```typescript const TEST_USER_PHONE = '13800138002'; // 修正为正确的手机号 const TEST_USER_PASSWORD = process.env.TEST_ENTERPRISE_PASSWORD || '123123'; ``` --- ## 后端代码质量分析 ### `order.service.ts` - getOrderStats 方法 (行 1206-1271) **发现的问题**: 1. **时区处理不明确**: ```typescript const monthStart = new Date(year, month - 1, 1); const monthEnd = new Date(year, month, 1); ``` - JavaScript Date 对象使用本地时区 - PostgreSQL `related_time` 字段存储的是 timestamp - 可能导致时区不匹配问题 2. **查询逻辑正确但可优化**: - 使用 `DISTINCT asset.personId` 统计去重人员数是正确的 - 查询按 `relatedTime` 筛选本月数据逻辑正确 - 建议添加时区转换以确保边界准确 --- ## 测试覆盖率分析 ### 单元测试 **状态**: 未发现单元测试覆盖 `getOrderStats` 方法 **建议**: 添加以下测试用例: 1. 测试时区边界情况(月末最后一天) 2. 测试无数据情况 3. 测试部分数据情况(只有部分人员有资产) 4. 测试跨月数据筛选 ### E2E 测试 **文件**: `web/tests/e2e/specs/cross-platform/order-stats-fix.spec.ts` **覆盖率**: 适中 - AC1: 修复硬编码问题 ✓ (但 API 验证不充分) - AC2: 本月打卡统计 ✓ (结构正确) - AC3: 工资视频统计 ✓ (结构正确) - AC4: 个税视频统计 ✓ (结构正确) **改进建议**: 1. 添加 API Mock 测试,验证 RPC 客户端调用正确性 2. 添加错误场景测试(API 失败时的行为) 3. 添加数据准确性测试(验证百分比计算) --- ## 修复后的路由结构 ### 最终实现 ```typescript // allin-packages/order-module/src/routes/order-custom.routes.ts enterpriseOrderCustomRoutes .route('/company-orders', new OpenAPIHono() // GET /company-orders - 企业订单列表 .openapi({ ...companyOrdersRoute, path: '' }, async (c) => { ... }) // GET /company-orders/:id/stats - 订单统计 .openapi(orderStatsRoute, async (c) => { ... }) ) ``` **路径映射**: - `enterpriseOrderClient['company-orders'].$get()` → `/company-orders` - `enterpriseOrderClient['company-orders'][':id']['stats'].$get()` → `/company-orders/:id/stats` --- ## 修复后的代码文件清单 ### 后端文件 1. `allin-packages/order-module/src/routes/order-custom.routes.ts` - 修改 `orderStatsRoute` 路径从 `/company-orders/{id}/stats` 到 `/:id/stats` - 创建嵌套路由结构,将 `companyOrdersRoute` 和 `orderStatsRoute` 放在同一嵌套路由下 - 修改行: 856-907 (路由定义), 1399-1487 (路由注册) ### 前端文件 1. `web/tests/e2e/specs/cross-platform/order-stats-fix.spec.ts` - 修改测试凭证为正确的手机号和密码 - 修改行: 26-27 --- ## 验证步骤 1. **重新编译后端代码** ```bash cd /mnt/code/188-179-template-6 pnpm build ``` 2. **重启开发服务器**(如需要) 3. **验证路由可用性** ```bash curl -X GET 'http://localhost:8080/api/v1/yongren/order/company-orders/1/stats?year=2026&month=1' \ -H 'Authorization: Bearer ' ``` 4. **运行 E2E 测试** ```bash cd web timeout 60 pnpm test:e2e:chromium order-stats-fix ``` 5. **手动验证** - 登录企业小程序 (13800138002 / 123123) - 导航到订单列表页 - 检查网络请求,确认 `/company-orders/:id/stats` 被调用 - 验证统计字段显示实际数据而非硬编码的 0 --- ## 代码审查总结 ### 严重程度分布 - CRITICAL: 2 个 (路由结构不匹配、API 未被调用) - MEDIUM: 1 个 (默认值掩盖错误) - MINOR: 1 个 (测试凭证不匹配) ### 状态 - ✅ 已修复: 路由结构问题 - ✅ 已修复: E2E 测试凭证 - ⚠️ 需要验证: 前端需要重新编译 - 📝 建议改进: 前端错误处理、后端时区处理、单元测试覆盖 ### 下一步行动 1. 重新编译项目以应用类型定义更新 2. 运行 E2E 测试验证修复效果 3. 使用 Playwright MCP 手动验证订单统计字段显示 4. 考虑添加单元测试覆盖 `getOrderStats` 方法