# RIS自动同步Toast卡住问题分析与解决方案 ## 📋 问题描述 在worklist页面,偶尔会出现"正在同步RIS数据"的toast消息一直显示,不消失的问题,严重影响用户体验。 ## 🔍 问题分析 ### Toast出现机制 - **位置**:`src/hooks/useRisAutoSync.ts` 中的 `onSyncStart` 回调 - **代码**:`message.loading('正在同步RIS数据...', 0)` - 第二个参数 `0` 表示不自动消失 - **触发条件**:RIS自动同步开始时 ### Toast消失机制 - **位置**:`src/hooks/useRisAutoSync.ts` 中的 `onSyncComplete` 回调 - **代码**:`messageDestroyRef.current()` 关闭loading消息 - **触发条件**:同步完成(成功或失败)后 ### 根本原因 1. **缺少超时设置**:`src/API/interceptor.ts` 中的 axios 实例没有设置 `timeout`,导致请求可能无限等待 2. **同步流程卡住**:如果 `/auth/study/ris` API 请求卡住,`await syncRis(params)` 永远不会完成 3. **错误处理不完整**:卡住的请求不会抛出错误,因此不会触发 `onSyncComplete` 回调 ### 代码流程分析 ```mermaid sequenceDiagram participant Hook as useRisAutoSync participant Service as RisSyncService participant API as syncRis participant Toast Hook->>Service: start() Service->>API: syncRis() - 卡住 Note over API: 请求无限等待 Service->>Service: 等待响应(永远) Note over Toast: Toast永远显示 ``` ## 🐛 复现步骤 ### 方法1:使用浏览器开发者工具模拟网络问题(推荐) 1. **打开浏览器开发者工具** - 按 `F12` 或右键选择"检查元素" - 切换到 `Network` 标签页 2. **设置网络限速** - 点击网络标签页顶部的设置图标(⚙️) - 选择 `No throttling` 下拉菜单 - 选择 `Offline` 或自定义慢速网络: - 添加自定义配置:`Name: Very Slow 3G`,`Download: 50kb/s`,`Upload: 50kb/s`,`Latency: 2000ms` 3. **进入worklist页面** - 登录应用并进入worklist页面 - 等待RIS自动同步触发(根据配置间隔,通常5分钟) - 或者手动触发同步(如果有相关按钮) 4. **观察现象** - toast显示"正在同步RIS数据..." - 由于网络极慢,请求会卡住 - toast永远不会消失 ### 方法2:修改代码临时移除超时(开发环境) ```typescript // src/API/interceptor.ts 中临时添加 const axiosInstance = axios.create({ baseURL: API_BASE_URL, timeout: 24 * 60 * 60 * 1000, // 24小时超时(实际上无限等待) // ... 其他配置 }); ``` ### 方法3:使用Charles/Fiddler等代理工具 1. **安装代理工具**(Charles或Fiddler) 2. **配置网络代理** 3. **设置断点或延迟** - 在 `/auth/study/ris` 请求上设置断点 - 或者添加延迟规则让请求永远不响应 ### 方法4:服务器端模拟 如果可以访问后端服务器: 1. **修改后端代码** - 让 `/auth/study/ris` 接口故意不返回响应 - 或者添加很长的处理时间 2. **重启服务器并测试** ## 🔍 验证问题 要确认问题确实复现,可以: 1. **检查浏览器Network标签** - 看到 `/auth/study/ris` 请求处于 `pending` 状态 - 请求没有完成也没有失败 2. **检查控制台日志** - 没有看到 `[RisSyncService] 同步成功` 或 `[RisSyncService] 同步失败` 日志 - 同步过程卡在 `await syncRis(params)` 这一行 3. **检查UI状态** - toast消息一直显示 - 无法关闭应用或切换页面(除非强制刷新) ## 🛠️ 解决方案 ### 方案1:添加请求超时(已实施) 为 axios 实例添加超时设置,防止请求无限等待。 **修改文件**:`src/API/interceptor.ts` ```typescript const axiosInstance = axios.create({ baseURL: API_BASE_URL, timeout: 30000, // 30秒超时 // ... 其他配置 }); ``` **优点**: - 简单有效,直接解决问题 - 防止所有API请求无限等待 - 30秒超时对于同步操作来说是合理的 **缺点**: - 所有请求使用相同超时时间,可能不够灵活 - 对于某些需要更长等待的操作可能不够 ### 方案2:改进错误处理(可选) 在同步服务中添加超时控制,确保即使请求卡住也能触发错误处理。 ### 方案3:添加手动取消机制(可选) 允许用户手动取消正在进行的同步操作。 ## 💡 验证修复效果 修复后,可以通过以下方式验证: 1. **设置短超时**:将axios timeout设置为5000ms(5秒) 2. **重复复现步骤** 3. **观察结果**:5秒后toast应该消失,并显示错误消息 ## 📝 实施记录 - **问题发现时间**:2025-11-07 - **问题分析时间**:2025-11-07 - **修复方案**:添加axios全局超时设置(30秒) - **修复时间**:2025-11-07 - **验证状态**:修复已实施,待测试验证 ## 🔗 相关文件 - `src/hooks/useRisAutoSync.ts` - 自动同步Hook - `src/services/risSync/RisSyncService.ts` - 同步服务 - `src/API/interceptor.ts` - axios配置(已修改) - `src/API/patient/risActions.ts` - RIS API接口 --- *文档版本:1.0.0* *创建日期:2025-11-07* *作者:系统维护者*