# 急诊流程 - Token 获取与传递机制 ## 概述 本文档详细说明了系统中急诊模式的完整逻辑,包括 guest token 的获取、存储、传递机制以及急诊操作的完整流程。 ## 1. Token 的来源(初始化阶段) ### 相关文件 - `src/API/softwareInfo.ts` - API 调用 - `src/states/productSlice.ts` - Redux 状态管理 ### 获取流程 在系统启动时,通过 `initializeProductState` thunk 自动获取软件信息: ```typescript // API 调用 GET / pub / software_info; // 返回数据结构 interface SoftwareInfo { guest: string; // 用于急诊访问数据的 token FPD: string; GEN: string; language: string[]; product: string; sn: string; server: Record; } ``` ### 存储到 Redux ```typescript // productSlice.ts export const initializeProductState = createAsyncThunk( 'product/initializeProductState', async () => { const softwareInfo = await fetchSoftwareInfo(); return { productName: softwareInfo.product as 'DROS' | 'VETDROS', language: softwareInfo.language[0], source: 'Browser' as const, guest: softwareInfo.guest, // 存储 guest token }; } ); ``` ### 关键点 - ✅ `guest` 字段本质上就是急诊模式下使用的 token - ✅ 在系统初始化时就已经从后端获取并保存 - ✅ 存储在 Redux 的 `productSlice` 中,路径:`state.product.guest` - ✅ 无需用户登录即可获得 ## 2. Token 的传递机制 ### 相关文件 - `src/API/interceptor.ts` - Axios 拦截器 ### 核心逻辑 在每个 API 请求发出前,axios 请求拦截器会自动根据当前系统模式选择合适的 token: ```typescript axiosInstance.interceptors.request.use((config) => { const state = store.getState(); // 根据系统模式选择 token const token = state.systemMode.mode === SystemMode.Emergency ? state.product.guest // 急诊模式使用 guest token : state.userInfo.token; // 正常模式使用登录 token // 设置请求头 config.headers.Authorization = `Bearer ${token}`; config.headers.Language = language; config.headers.Product = productName; config.headers.Source = source; return config; }); ``` ### 判断逻辑 | 系统模式 | Token 来源 | 说明 | | ----------- | ---------------------- | ------------------------------------ | | `Emergency` | `state.product.guest` | 急诊模式,使用预先获取的 guest token | | `Normal` | `state.userInfo.token` | 正常模式,使用用户登录后的 token | | `Unknown` | `state.userInfo.token` | 未知状态,默认使用登录 token | ### 优势 - ✅ **透明化**:业务代码无需关心 token 的选择,由拦截器统一处理 - ✅ **自动化**:根据系统模式自动切换 token - ✅ **集中管理**:所有 API 请求的认证逻辑集中在一处 - ✅ **易维护**:修改认证逻辑只需修改拦截器 ## 3. 急诊操作的完整流程 ### 相关文件 - `src/domain/patient/handleEmergencyOperation.ts` - 急诊操作主流程 - `src/domain/patient/registrationGenerator.ts` - 生成注册信息 - `src/API/patient/workActions.ts` - 注册 API - `src/states/systemModeSlice.ts` - 系统模式管理 ### 流程图 ``` 开始 ↓ 1. 设置系统模式为 Emergency ↓ 2. 生成急诊注册信息 ↓ 3. 调用注册 API (自动使用 guest token) ↓ 4. 保存注册结果到缓存 ↓ 5. 切换业务流程到检查页面 ↓ 结束 ``` ### 详细代码流程 ```typescript const handleEmergencyOperation = async () => { const dispatch = store.dispatch; try { // 步骤 1: 设置系统模式为急诊 dispatch(setSystemMode(SystemMode.Emergency)); // 步骤 2: 生成注册信息 const registrationInfo = generateRegistrationInfo(); // 返回的数据包含 study_type: 'Emergency' // 步骤 3: 注册急诊工作 // 此时 API 请求会自动使用 guest token(通过拦截器) const registrationResult = await registerWork(registrationInfo); // 步骤 4: 保存结果到缓存 const task = mapToTask(registrationResult.data); dispatch(addWork(task)); // 步骤 5: 切换到检查流程 dispatch(setBusinessFlow('exam')); } catch (error) { console.error('Error in handleEmergencyOperation:', error); throw error; } }; ``` ### 注册信息生成 ```typescript // registrationGenerator.ts function generateRegistrationInfo() { return { study_type: 'Emergency', // 标记为急诊类型 accession_number: maxNumber, patient_id: `EMERGENCY_${timestamp}`, patient_name: `急诊患者_${number}`, // ... 其他字段 }; } ``` ## 4. 系统模式状态管理 ### 相关文件 - `src/states/systemModeSlice.ts` ### 模式定义 ```typescript export const SystemMode = { Unknown: 'Unknown', // 未知状态 Emergency: 'Emergency', // 急诊模式 Normal: 'Normal', // 正常模式 }; interface SystemModeState { mode: SystemMode; } const initialState: SystemModeState = { mode: SystemMode.Unknown, }; ``` ### 状态转换 | 从状态 | 到状态 | 触发条件 | | ----------- | ----------- | ---------------------- | | `Unknown` | `Emergency` | 执行急诊操作 | | `Unknown` | `Normal` | 用户正常登录 | | `Emergency` | `Normal` | 急诊流程结束(待实现) | | `Normal` | `Emergency` | 切换到急诊模式 | ### 使用方式 ```typescript // 设置为急诊模式 dispatch(setSystemMode(SystemMode.Emergency)); // 设置为正常模式 dispatch(setSystemMode(SystemMode.Normal)); // 获取当前模式 const currentMode = state.systemMode.mode; ``` ## 5. 核心设计思想 ### 5.1 预先获取 Token - **设计理念**:guest token 在系统初始化时就获取,无需等待用户登录 - **优势**:急诊场景下可以立即使用,无需认证流程 - **实现**:通过 `initializeProductState` thunk 在应用启动时自动获取 ### 5.2 模式驱动 - **设计理念**:通过系统模式(Emergency/Normal)自动切换使用不同的 token - **优势**:业务逻辑与认证逻辑解耦 - **实现**:在 axios 拦截器中根据 `systemMode.mode` 选择 token ### 5.3 透明传递 - **设计理念**:业务代码不需要关心 token 的选择 - **优势**:降低代码复杂度,减少出错可能 - **实现**:由 axios 拦截器统一处理 ### 5.4 急诊快速启动 - **设计理念**:无需登录认证流程,直接使用预设的 guest token - **优势**:紧急情况下快速响应 - **实现**:一键触发急诊流程,自动完成注册和进入检查页面 ## 6. API 接口说明 ### 6.1 获取软件信息 ```http GET /pub/software_info ``` **响应示例:** ```json { "code": "0x000000", "data": { "guest": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "product": "DROS", "language": ["en", "zh"], "FPD": "Simulator", "GEN": "Simulator", "sn": "2edbc382-044adc78-95bed11b-51c9328a" } } ``` ### 6.2 注册急诊工作 ```http POST /dr/api/v1/auth/study Authorization: Bearer {guest_token} ``` **请求体:** ```json { "study_type": "Emergency", "accession_number": "ACC0012345", "patient_id": "EMERGENCY_20250625143339", "patient_name": "急诊患者_001" // ... 其他患者信息 } ``` ## 7. 关键文件总结 | 文件路径 | 作用 | 关键功能 | | ------------------------------------------------ | -------------- | ----------------------------------------------- | | `src/API/softwareInfo.ts` | 获取软件信息 | 调用 `/pub/software_info` API,获取 guest token | | `src/states/productSlice.ts` | 产品状态管理 | 存储 guest token 到 Redux | | `src/states/systemModeSlice.ts` | 系统模式管理 | 管理 Emergency/Normal 模式切换 | | `src/API/interceptor.ts` | API 拦截器 | 根据系统模式自动选择 token 并添加到请求头 | | `src/domain/patient/handleEmergencyOperation.ts` | 急诊操作主流程 | 执行完整的急诊注册流程 | | `src/domain/patient/registrationGenerator.ts` | 注册信息生成 | 生成急诊患者的注册信息 | | `src/API/patient/workActions.ts` | 工作注册 API | 调用后端注册接口 | ## 8. 使用示例 ### 8.1 触发急诊流程 ```typescript import handleEmergencyOperation from '@/domain/patient/handleEmergencyOperation'; // 在某个组件或页面中触发急诊 const handleEmergencyClick = async () => { try { await handleEmergencyOperation(); // 成功后会自动跳转到检查页面 } catch (error) { console.error('急诊操作失败:', error); message.error('急诊操作失败,请重试'); } }; ``` ### 8.2 检查当前系统模式 ```typescript import { useSelector } from 'react-redux'; import { SystemMode } from '@/states/systemModeSlice'; const MyComponent = () => { const currentMode = useSelector(state => state.systemMode.mode); const isEmergencyMode = currentMode === SystemMode.Emergency; return (
{isEmergencyMode ? '急诊模式' : '正常模式'}
); }; ``` ### 8.3 手动切换系统模式 ```typescript import { useDispatch } from 'react-redux'; import { setSystemMode, SystemMode } from '@/states/systemModeSlice'; const MyComponent = () => { const dispatch = useDispatch(); const switchToNormal = () => { dispatch(setSystemMode(SystemMode.Normal)); }; const switchToEmergency = () => { dispatch(setSystemMode(SystemMode.Emergency)); }; return ( <> ); }; ``` ## 9. 注意事项 ### 9.1 Token 有效期 - guest token 有过期时间(expire 字段) - 建议在应用中监控 token 过期状态 - 过期后需要重新调用 `/pub/software_info` 获取新的 guest token ### 9.2 系统模式切换 - 当前急诊流程结束后,系统模式的切换逻辑尚未完全实现(代码中被注释) - 建议在急诊流程完成后显式切换回 Normal 模式 ```typescript // 在 handleEmergencyOperation 的 finally 中 finally { dispatch(setSystemMode(SystemMode.Normal)); } ``` ### 9.3 错误处理 - 所有 API 调用都应有适当的错误处理 - 急诊流程失败时应给用户明确的提示 - 考虑添加重试机制 ### 9.4 安全性 - guest token 的权限应该受到限制,只能访问急诊相关的功能 - 后端应验证请求的 study_type 与使用的 token 类型是否匹配 - 建议添加访问日志记录急诊操作 ## 10. 未来改进建议 ### 10.1 Token 刷新机制 实现 guest token 的自动刷新: ```typescript // 在拦截器中检查 token 是否即将过期 if (isTokenExpiringSoon(state.product.guest)) { await refreshGuestToken(); } ``` ### 10.2 急诊流程状态跟踪 添加更详细的急诊流程状态: ```typescript enum EmergencyFlowStatus { NotStarted = 'NotStarted', Generating = 'Generating', Registering = 'Registering', Completed = 'Completed', Failed = 'Failed', } ``` ### 10.3 急诊模式自动退出 实现急诊流程完成后自动退出急诊模式: ```typescript const handleEmergencyOperation = async () => { try { dispatch(setSystemMode(SystemMode.Emergency)); // ... 执行急诊流程 dispatch(setBusinessFlow('exam')); } finally { // 检查完成后自动退出急诊模式 dispatch(setSystemMode(SystemMode.Normal)); } }; ``` ### 10.4 审计日志 记录所有急诊操作以便审计: ```typescript const logEmergencyOperation = (operation: string, data: any) => { console.log('[EMERGENCY]', { timestamp: new Date().toISOString(), operation, data, mode: store.getState().systemMode.mode, }); }; ``` ## 11. 总结 急诊流程的设计充分体现了以下特点: 1. **快速响应**:通过预先获取 guest token,无需登录即可快速启动急诊流程 2. **自动化**:系统模式驱动的 token 选择机制,业务代码无需关心认证细节 3. **集中管理**:所有认证逻辑集中在 axios 拦截器中,便于维护 4. **清晰分层**:状态管理、API 调用、业务逻辑分层明确 5. **易于扩展**:模块化设计便于未来功能扩展 这种设计使得急诊功能既能快速响应紧急情况,又保持了代码的可维护性和可扩展性。