| | |
| | | 4. **幂等性保证**:页面刷新时不重复发起外呼,继续监听现有任务 |
| | | 5. **自动清理**:通话结束后自动移除气泡和存储数据 |
| | | 6. **错误容错**:API 失败时提供友好提示,不阻塞主流程 |
| | | 7. **失败任务可视化**:失败任务在气泡中清晰展示,带红色状态指示灯 |
| | | 8. **重复防护**:相同联系人失败任务自动去重,避免信息冗余 |
| | | 9. **自动过期清理**:失败任务超过24小时自动清除 |
| | | |
| | | ### Non-Goals |
| | | - 不涉及后端外呼接口实现 |
| | | - 不涉及通话录音播放功能 |
| | | - 不涉及外呼任务的手动取消或重试操作 |
| | | - 不涉及复杂的权限控制(当前仅前端功能) |
| | | - 不涉及失败任务的自动重试机制 |
| | | |
| | | ## Decisions |
| | | |
| | |
| | | ### Decision 2: jobId 状态管理 - localStorage + 活跃状态过滤 |
| | | |
| | | **数据结构设计**: |
| | | |
| | | **成功任务存储**: |
| | | ```javascript |
| | | // localStorage key: 'outbound_call_jobs' |
| | | [ |
| | |
| | | callStatus: "Scheduling", // 或 Executing, Paused, Drafted, Succeeded, Failed, Cancelled |
| | | personId: "2303191513081131", |
| | | mediationId: 20, |
| | | caseId: "CASE_001", // 用于轮询查询的 caseRef 参数 |
| | | perClassName: "申请人", // 人员类型名称 |
| | | trueName: "张三", // 真实姓名 |
| | | startTime: 1738228800000, // 触发时间戳 |
| | | retryCount: 0, // 重试次数 |
| | | pollStartTime: 1738228800000 // 轮询开始时间(用于2小时超时检测) |
| | | } |
| | | ] |
| | | ``` |
| | | |
| | | **失败任务存储**: |
| | | ```javascript |
| | | // localStorage key: 'outbound_call_jobs_failed' |
| | | [ |
| | | { |
| | | personId: "2303191513081131", |
| | | message: "今日呼叫次数已达上限(3次)", |
| | | perClassName: "申请人", // 人员类型名称 |
| | | trueName: "张三", // 真实姓名 |
| | | errorCode: 1001, // 错误码 |
| | | startTime: 1738228800000 // 失败时间戳(用于24小时过期清理) |
| | | } |
| | | ] |
| | | ``` |
| | |
| | | 3. 实现 localStorage 状态管理 |
| | | 4. 完成错误处理和重试机制 |
| | | |
| | | ### Phase 2: 优化与扩展(后续迭代) |
| | | ### Phase 2: 用户体验优化(当前完成) |
| | | 1. 失败任务独立存储和展示 |
| | | 2. 失败任务去重机制(按 personId 去重) |
| | | 3. 失败任务自动清理(24小时过期) |
| | | 4. 视觉优化:成功任务绿色指示灯,失败任务红色指示灯 |
| | | 5. 重复气泡防护,避免信息冗余 |
| | | |
| | | ### Phase 3: 优化与扩展(后续迭代) |
| | | 1. 支持手动取消外呼任务 |
| | | 2. 外呼结果通知(成功/失败弹窗) |
| | | 3. 外呼历史记录查询 |