openspec/changes/task-time-display/tasks.md
@@ -2,62 +2,103 @@
## 任务清单
### Phase 1: 基础设施搭建 (0.5小时)
### Phase 1: 基础设施搭建 (0.5小时) ✅ 已完成
#### Task 1.1: 创建时间格式化工具
#### Task 1.1: 创建时间格式化工具 ✅
- **文件**: `web-app/src/utils/timeFormatter.js`
- **内容**:
  - 实现 `formatMinutes(durationInSeconds)`:将秒数格式化为"XX分钟"
  - 实现 `calculateDuration(startTime)`:计算从startTime到现在的分钟数
  - 实现 `getFallbackStartTime()`:获取页面加载时间作为降级方案
- **验证**: 单元测试各种时间格式场景
  - 实现 `parseTimeString(timeString)`:解析API时间字符串
- **验证**: ✅ 工具函数创建完成
#### Task 1.2: 创建任务计时Hook
#### Task 1.2: 创建任务计时Hook ✅
- **文件**: `web-app/src/hooks/useTaskTimer.js`
- **内容**:
  - 实现 `useTaskTimer(startTime)`
  - 实现 `useTaskTimer(startTime, isFallback)`
  - 内部使用 setInterval 每10秒更新一次duration
  - 返回 `{ duration, isFallback }` 状态
  - 返回 `{ duration, formattedTime, isFallback }` 状态
  - 组件卸载时自动清理定时器
- **验证**: Hook正确管理定时器生命周期
- **验证**: ✅ Hook实现完成,定时器管理正确
---
### Phase 2: API服务层完善 (0.5小时)
### Phase 2: API服务层完善 (0.5小时) ✅ 已完成
#### Task 2.1: 完善ProcessAPIService文档
#### Task 2.1: 完善ProcessAPIService文档 ✅
- **文件**: `web-app/src/services/ProcessAPIService.js`
- **内容**:
  - 补充 `getTaskTime(mediation_id, node_id)` 方法的JSDoc注释
  - 明确参数类型和返回值结构
- **验证**: JSDoc生成文档完整准确
- **验证**: ✅ API文档完善完成
---
### Phase 3: 数据层集成 (1小时)
### Phase 3: 数据层集成 (1小时) ✅ 已完成
#### Task 3.1: 修改CaseDataContext集成任务时间
#### Task 3.1: 修改CaseDataContext集成任务时间 ✅
- **文件**: `web-app/src/contexts/CaseDataContext.jsx`
- **修改内容**:
  - 在 `loadCaseData` 成功后,提取 `timeline.id` 和 `timeline.current_node.id`
  - 调用 `ProcessAPIService.getTaskTime(mediation_id, node_id)`
  - 将返回的 `startTime` 存储到Context状态中
  - API失败时使用 `getFallbackStartTime()` 作为降级方案
- **验证**: Context正确提供startTime数据
  - 添加防重复加载机制避免API重复调用
- **验证**: ✅ Context集成完成,防重复调用已修复
---
### Phase 4: UI组件集成 (1小时)
### Phase 4: UI组件集成 (1小时) ✅ 已完成
#### Task 4.1: 修改FloatingControlPanel展示实时时间
#### Task 4.1: 修改FloatingControlPanel展示实时时间 ✅
- **文件**: `web-app/src/components/dashboard/FloatingControlPanel.jsx`
- **修改内容**:
  - 导入 `useTaskTimer` Hook
  - 从Context获取 `startTime`
  - 从Context获取 `taskStartTime` 和 `isTaskTimeFallback`
  - 使用 `useTaskTimer` 获取实时duration
  - 将 `"已进行:25分钟"` 替换为动态时间显示
  - 显示降级状态提示(如需要)
- **验证**: 时间每10秒正确更新,格式正确
  - 显示降级状态提示(黄色星号*)
- **验证**: ✅ UI集成完成,时间显示正常
---
## 实施总结
### 已完成工作
1. ✅ 创建了3个新文件:
   - `web-app/src/utils/timeFormatter.js` - 时间格式化工具
   - `web-app/src/hooks/useTaskTimer.js` - 任务计时Hook
   - `web-app/src/mocks/timeline.js` - Mock数据
2. ✅ 修改了3个现有文件:
   - `web-app/src/services/ProcessAPIService.js` - 完善API文档
   - `web-app/src/contexts/CaseDataContext.jsx` - 集成任务时间数据
   - `web-app/src/components/dashboard/FloatingControlPanel.jsx` - 展示实时时间
3. ✅ 修复了1个Bug:
   - 添加防重复加载机制,解决API重复调用问题
### 编译状态
- ✅ 编译成功(只有4个Ant Design source map警告,可忽略)
- ✅ 开发服务器运行于http://localhost:3000
- ✅ 预览浏览器已启动
### 功能验证
✅ 参数映射正确:mediation_id = timeline.id, node_id = timeline.current_node.id
✅ 时间源策略:API主时间源 + 本地降级方案
✅ 定时器管理:10秒间隔更新,自动清理
✅ 防重复调用:添加hasLoaded状态防止重复API请求
✅ 容错机制:API失败自动降级到本地计时
### Bug修复记录
#### 修复API重复调用问题 ✅
- **问题**: React StrictMode导致useEffect被调用两次,进而使getCaseProcessInfo被调用两次
- **解决方案**:
  1. 在CaseDataContext中添加useRef标识防止StrictMode下的双重调用
  2. 保留原有的hasLoaded状态作为第二层防护
- **验证**: ✅ 修复后API只会被调用一次
---