Răsfoiți Sursa

docs: 添加人才端本月出勤数据修复技术规格

完成 BMM Quick-Spec 工作流,统一首页、更多页面、考勤记录页的
本月出勤数据源,使用 generateMockAttendanceData 函数。

- 问题:三个页面显示的出勤天数不一致(29/28/22天)
- 解决方案:统一使用 generateMockAttendanceData 作为数据源
- 范围:修复首页硬编码值和更多页面本地 mock 数据
- 状态:ready-for-dev,包含 8 个任务和 3 条验收标准

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

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 1 zi în urmă
părinte
comite
4406be9cc7

+ 241 - 0
_bmad-output/implementation-artifacts/tech-spec-talent-attendance-data-fix.md

@@ -0,0 +1,241 @@
+---
+title: '修复人才端本月出勤数据不一致'
+slug: 'talent-attendance-data-fix'
+created: '2026-03-08T23:05:14+00:00'
+status: 'ready-for-dev'
+stepsCompleted: [1, 2, 3, 4]
+tech_stack: ['React', 'TypeScript', 'Taro 4.1', 'React Query', 'Hono RPC Client']
+files_to_modify: [
+  'mini-talent/src/pages/index/index.tsx',
+  'mini-talent/src/pages/settings/index.tsx'
+]
+code_patterns: ['Mock数据函数', 'React hooks', 'useState初始化模式', '同步函数调用']
+test_patterns: ['Vitest', 'React Testing Library', 'Jest']
+---
+
+# Tech-Spec: 修复人才端本月出勤数据不一致
+
+**Created:** 2026-03-08T23:05:14+00:00
+
+## Overview
+
+### Problem Statement
+
+人才端首页、更多页面、考勤记录页的"本月出勤"数据来源不同,显示值不一致:
+
+| 位置 | 当前值 | 数据来源 |
+|------|--------|----------|
+| 首页 (`pages/index/index.tsx`) | 29天 | 硬编码 |
+| 更多页面 (`pages/settings/index.tsx`) | 28天 (mock) / 0天 (API) | 各自的 mock 数据 |
+| 考勤记录页 (`pages/attendance/index.tsx`) | 22天 | `generateMockAttendanceData` |
+
+这种不一致会导致用户体验混乱,不同页面显示的出勤天数不同。
+
+### Solution
+
+统一使用 `generateMockAttendanceData` 函数作为所有页面的统计数据源:
+
+1. 首页:移除硬编码值 `29`,改为调用 `generateMockAttendanceData` 获取 `normalDays`
+2. 更多页面:移除本地 mock 数据,改为调用 `generateMockAttendanceData` 获取 `normalDays`
+3. 保持考勤记录页不变(已正确使用 `generateMockAttendanceData`)
+
+### Scope
+
+**In Scope:**
+- 修复首页 (`mini-talent/src/pages/index/index.tsx`) 的本月出勤硬编码值
+- 修复更多页面 (`mini-talent/src/pages/settings/index.tsx`) 的 mock 数据
+- 统一使用 `generateMockAttendanceData` 函数获取统计数据
+
+**Out of Scope:**
+- 连接真实 API(继续使用 Mock 数据)
+- 修改其他统计数据(薪资、累计出勤等)
+- 修改考勤记录页(已正确实现)
+
+## Context for Development
+
+### Codebase Patterns
+
+**Mock 数据函数 (`generateMockAttendanceData`):**
+- 位置:`mini-talent/src/utils/mockAttendanceData.ts`
+- 签名:`function generateMockAttendanceData(year: number, month: number): { stats: AttendanceStats, records: AttendanceRecord[] }`
+- 返回值:`{ stats: { normalDays: 22, attendanceRate: 100, lateCount: 0, earlyLeaveCount: 0, absentCount: 0 }, records: [...] }`
+- 使用方式:直接同步调用,无需 React Query
+
+**首页当前模式:**
+- 位置:`mini-talent/src/pages/index/index.tsx` 第 223 行
+- 当前代码:`<Text className="text-white text-2xl font-bold">29</Text>`
+- 需要修改:导入 `generateMockAttendanceData` 并调用获取 `normalDays`
+
+**更多页面当前模式:**
+- 位置:`mini-talent/src/pages/settings/index.tsx` 第 185-217 行
+- 当前代码:使用本地 mock 数据 `thisMonthAttendance: 28`
+- 需要修改:调用 `generateMockAttendanceData` 获取 `normalDays`
+
+**考勤记录页正确模式:**
+- 位置:`mini-talent/src/pages/attendance/index.tsx` 第 19-25 行
+- 导入:`import { generateMockAttendanceData, getCurrentYearMonth } from '../../utils/mockAttendanceData'`
+- 使用:`const { stats } = generateMockAttendanceData(year, month).stats`
+
+### Files to Reference
+
+| File | 行号 | 用途 |
+| ---- | ---- | ---- |
+| `mini-talent/src/utils/mockAttendanceData.ts` | 全部 | Mock 数据生成函数,统一的统计数据源 |
+| `mini-talent/src/types/attendance.ts` | 全部 | 考勤相关类型定义 (`AttendanceStats`, `AttendanceRecord`) |
+| `mini-talent/src/pages/index/index.tsx` | 223 | 首页,硬编码显示 29 天(需修改) |
+| `mini-talent/src/pages/settings/index.tsx` | 185-217 | 更多页面,本地 mock 数据(需修改) |
+| `mini-talent/src/pages/attendance/index.tsx` | 19-47 | 考勤记录页,正确实现示例(参考) |
+
+### Technical Decisions
+
+**实现策略:**
+1. 首页:在组件内直接调用 `generateMockAttendanceData`,不使用 useState(因为是纯函数)
+2. 更多页面:在组件内直接调用 `generateMockAttendanceData`,替换本地 mock 数据
+3. 使用 `getCurrentYearMonth()` 获取当前年月,传入 `generateMockAttendanceData`
+
+**代码模式:**
+```typescript
+// 导入
+import { generateMockAttendanceData, getCurrentYearMonth } from '../../utils/mockAttendanceData'
+
+// 在组件内调用
+const { year, month } = getCurrentYearMonth()
+const { stats } = generateMockAttendanceData(year, month)
+
+// 使用 stats.normalDays 显示出勤天数
+```
+
+## Implementation Plan
+
+### Tasks
+
+#### Task 1: 修复首页本月出勤硬编码值
+
+- [ ] **Task 1.1:** 在首页添加 `generateMockAttendanceData` 导入
+  - File: `mini-talent/src/pages/index/index.tsx`
+  - Action: 在文件顶部导入区域添加:
+    ```typescript
+    import { generateMockAttendanceData, getCurrentYearMonth } from '../../utils/mockAttendanceData'
+    ```
+  - Notes: 参考考勤记录页的导入方式(第 19-25 行)
+
+- [ ] **Task 1.2:** 在首页组件中调用 Mock 数据函数
+  - File: `mini-talent/src/pages/index/index.tsx`
+  - Action: 在 `Dashboard` 组件内部,添加以下代码:
+    ```typescript
+    // 获取当前月份考勤统计数据
+    const { stats: attendanceStats } = (() => {
+      const { year, month } = getCurrentYearMonth()
+      return generateMockAttendanceData(year, month)
+    })()
+    ```
+  - Notes: 使用 `attendanceStats` 变量名避免类型冲突,IIFE 确保只在组件渲染时计算一次
+
+- [ ] **Task 1.3:** 替换首页所有硬编码的统计数据
+  - File: `mini-talent/src/pages/index/index.tsx`
+  - Action: 找到第 223-232 行的硬编码值,将:
+    ```typescript
+    <Text className="text-white text-2xl font-bold">29</Text>      {/* 本月出勤 */}
+    <Text className="text-white text-2xl font-bold">0</Text>       {/* 异常记录 */}
+    <Text className="text-white text-2xl font-bold">¥4,800</Text>  {/* 本月薪资 */}
+    ```
+    替换为:
+    ```typescript
+    <Text className="text-white text-2xl font-bold">{stats.normalDays}</Text>      {/* 本月出勤 */}
+    <Text className="text-white text-2xl font-bold">{stats.lateCount + stats.earlyLeaveCount + stats.absentCount}</Text>  {/* 异常记录 */}
+    <Text className="text-white text-2xl font-bold">¥4,800</Text>  {/* 本月薪资保持不变 */}
+    ```
+  - Notes: 使用 `attendanceStats` 变量名避免与 `stats` 类型冲突
+
+#### Task 2: 修复更多页面本地 Mock 数据
+
+- [ ] **Task 2.1:** 在更多页面添加 `generateMockAttendanceData` 导入
+  - File: `mini-talent/src/pages/settings/index.tsx`
+  - Action: 在文件顶部导入区域添加:
+    ```typescript
+    import { generateMockAttendanceData, getCurrentYearMonth } from '../../utils/mockAttendanceData'
+    ```
+
+- [ ] **Task 2.2:** 替换更多页面的本地 Mock 数据
+  - File: `mini-talent/src/pages/settings/index.tsx`
+  - Action: 修改 `displayProfile` 的计算逻辑,将:
+    ```typescript
+    stats: {
+      thisMonthAttendance: 0,
+      totalAttendance: 0,
+      thisMonthSalary: 0
+    }
+    ```
+    替换为:
+    ```typescript
+    stats: (() => {
+      const { year, month } = getCurrentYearMonth()
+      const { stats } = generateMockAttendanceData(year, month)
+      return {
+        thisMonthAttendance: stats.normalDays,
+        totalAttendance: stats.normalDays, // 累计出勤暂时显示本月值
+        thisMonthSalary: 4800 // 薪资保持不变
+      }
+    })()
+    ```
+  - Notes: 累计出勤与本月保持一致,后续可从 API 获取真实累计数据
+
+- [ ] **Task 2.3:** 保留 mockProfile 作为后备数据源
+  - File: `mini-talent/src/pages/settings/index.tsx`
+  - Action: 保留 `mockProfile` 定义作为 API 返回空数据时的后备选项
+  - Notes: 确保 API 失败时页面仍有数据显示
+
+### Acceptance Criteria
+
+#### AC 1: 首页显示正确的出勤天数
+
+- **Given** 用户已登录人才小程序首页,且 `generateMockAttendanceData` 返回正常数据
+- **When** 页面加载完成
+- **Then** 首页"本月出勤"显示 `attendanceStats.normalDays`(当前为 22 天)
+- **And** "异常记录"显示 `attendanceStats.lateCount + attendanceStats.earlyLeaveCount + attendanceStats.absentCount`(当前为 0)
+- **And** "本月薪资"显示 ¥4,800(保持不变)
+
+#### AC 2: 更多页面显示正确的出勤天数
+
+- **Given** 用户已登录人才小程序并点击底部"更多"标签
+- **When** 更多页面加载完成
+- **Then** 更多页面"本月出勤"显示 `stats.normalDays`(当前为 22 天)
+- **And** "累计出勤"显示 `stats.normalDays`(与本月一致,非 *6 计算)
+- **And** "本月薪资"显示 ¥4,800(保持不变)
+
+#### AC 3: 所有页面出勤数据一致
+
+- **Given** 用户在人才小程序的首页、更多页面、考勤记录页之间切换
+- **When** 查看所有页面的出勤天数
+- **Then** 三个页面显示的"本月出勤"均为 22 天
+- **And** 数据来源统一为 `generateMockAttendanceData` 函数
+
+## Additional Context
+
+### Dependencies
+
+- 无新增依赖
+- 依赖现有的 `generateMockAttendanceData` 函数
+
+### Testing Strategy
+
+1. 首页验证:打开人才小程序首页,确认"本月出勤"显示 22 天
+2. 更多页面验证:点击底部"更多"标签,确认"本月出勤"显示 22 天
+3. 一致性验证:首页、更多页面、考勤记录页的出勤天数均为 22 天
+
+### Notes
+
+- 当前 mock 数据固定返回 `normalDays: 22`, `lateCount: 0`, `earlyLeaveCount: 0`, `absentCount: 0`
+- 如后续需要动态计算,可修改 `generateMockAttendanceData` 函数
+- `getCurrentYearMonth()` 使用本地时区,与考勤记录页保持一致
+
+### 回滚计划
+
+如果修改导致页面显示异常或错误:
+1. 使用 `git checkout` 恢复修改的文件:
+   ```bash
+   git checkout mini-talent/src/pages/index/index.tsx
+   git checkout mini-talent/src/pages/settings/index.tsx
+   ```
+2. 重启开发服务器:`pnpm run dev`
+3. 刷新页面验证恢复正常