Parcourir la source

添加请求的超时控制,避免RIS自动同步时可能触发的一直等待现象--有一个toast提示一直存在在页面上

dengdx il y a 3 semaines
Parent
commit
c1790aef92
2 fichiers modifiés avec 170 ajouts et 0 suppressions
  1. 169 0
      docs/RIS_AUTO_SYNC_TOAST_STUCK_ISSUE.md
  2. 1 0
      src/API/interceptor.ts

+ 169 - 0
docs/RIS_AUTO_SYNC_TOAST_STUCK_ISSUE.md

@@ -0,0 +1,169 @@
+# 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*
+*作者:系统维护者*

+ 1 - 0
src/API/interceptor.ts

@@ -7,6 +7,7 @@ import { throttleCount } from '@/utils/throttle';
 
 const axiosInstance = axios.create({
   baseURL: API_BASE_URL,
+  timeout: 30000, // 30秒超时,防止请求无限等待
 });
 
 function expensiveLog(mode) {