# APR参数管理流程需求文档 ## 概述 本文档描述APR(自动程序检索,Automatic Program Retrieval)参数在不同场景下的获取、设置和下发流程。 ## 术语说明 - **APR**: 自动程序检索,包含曝光参数配置(kV、mA、mAs、ms等) - **体位**: 检查时的身体姿势和位置 - **体型**: 患者体型大小(如Small、Medium、Large等) - **工作位**: 工作站位置(如立位、卧位、自由位等) ## 业务场景 ### 场景1: 更改体位后的APR流程 **触发条件**: 用户选择新的体位 **当前实现**: 1. ✅ 触发 `setSelectedBodyPosition` action 2. ✅ 使用当前的 `aprConfig` 数据 3. ✅ 构建设备参数(包含kV、mA、ms、mAs、工作位等) 4. ✅ 调用 `SetAPR` API下发到后端设备 **实现位置**: - `src/states/exam/aprSlice.ts` - `extraReducers` 中的 `setSelectedBodyPosition` 处理 **数据流**: ``` 用户选择体位 → dispatch(setSelectedBodyPosition) → aprSlice extraReducer监听 → 使用当前aprConfig构建参数 → SetAPR API下发到设备 ``` **状态**: ✅ 已完整实现 --- ### 场景2: 更新体型后的APR流程 **触发条件**: 用户更改患者体型(如从Medium改为Large) **当前实现**: 1. ✅ 触发 `setBodysize` action 2. ✅ aprMiddleware 拦截该action 3. ✅ 调用 `getAprExposureParams` API获取新的APR参数 4. ✅ 通过 `setAprConfig` 更新Redux store 5. ✅ UI自动响应显示新参数 6. ❌ **缺少**: 未调用 `SetAPR` 下发到后端设备 **实现位置**: - `src/states/exam/aprSlice.ts` - `aprMiddleware` 中间件 - `src/pages/exam/ContentAreaLarge.tsx` - UI触发点 **数据流**: ``` 用户更改体型 → dispatch(setBodysize) → aprMiddleware拦截 → getAprExposureParams获取新参数 → setAprConfig更新store → UI显示更新 ❌ 缺少:SetAPR下发到设备 ``` **状态**: ⚠️ 部分实现,缺少设备下发步骤 --- ### 场景3: 更改工作位后的APR流程 **触发条件**: 用户更改工作位(如从立位改为卧位) **当前实现**: 1. ✅ 触发 `setWorkstation` action 2. ✅ aprMiddleware 拦截该action 3. ✅ 调用 `getAprExposureParams` API获取新的APR参数 4. ✅ 通过 `setAprConfig` 更新Redux store 5. ✅ UI自动响应显示新参数 6. ❌ **缺少**: 未调用 `SetAPR` 下发到后端设备 **实现位置**: - `src/states/exam/aprSlice.ts` - `aprMiddleware` 中间件 - `src/pages/exam/ContentAreaLarge.tsx` - UI触发点 **数据流**: ``` 用户更改工作位 → dispatch(setWorkstation) → aprMiddleware拦截 → getAprExposureParams获取新参数 → setAprConfig更新store → UI显示更新 ❌ 缺少:SetAPR下发到设备 ``` **状态**: ⚠️ 部分实现,缺少设备下发步骤 --- ## 问题分析 ### 当前存在的不一致性 三个场景的实现逻辑不一致: | 场景 | 获取APR参数 | 更新UI | 下发到设备 | | ---------- | --------------- | ------ | ---------- | | 更改体位 | N/A(使用已有) | ✅ | ✅ | | 更新体型 | ✅ | ✅ | ❌ | | 更改工作位 | ✅ | ✅ | ❌ | ### 潜在影响 1. **UI与设备状态不同步**: - 用户在UI上看到的参数已更新 - 但设备实际使用的仍是旧参数 - 可能导致曝光参数错误 2. **用户体验不一致**: - 更改体位时设备会同步 - 更改体型/工作位时设备不会同步 - 用户可能困惑为什么有些操作生效有些不生效 ## 改进建议 ### 方案1: 统一在middleware中处理(推荐) 在 `aprMiddleware` 中: 1. 监听 `setBodysize` 和 `setWorkstation` action 2. 获取新的APR参数后 3. **立即调用 `SetAPR` 下发到设备** **优点**: - 逻辑集中,易于维护 - 所有场景行为一致 - 自动确保UI和设备同步 **缺点**: - 需要在middleware中处理异步调用链 ### 方案2: 在setAprConfig的extraReducer中处理 当 `setAprConfig` 被调用时: 1. 更新store 2. 自动调用 `SetAPR` 下发到设备 **优点**: - 无论何种原因更新APR,都会同步到设备 - 统一的同步点 **缺点**: - 可能导致重复下发(如果有多次快速更新) - 需要防抖处理 ### 方案3: 创建统一的updateAPR action 创建新的 thunk action `updateAPR`: 1. 接收参数(bodysize、workstation等) 2. 调用API获取新参数 3. 更新store 4. 下发到设备 **优点**: - 完全控制整个流程 - 可以添加加载状态、错误处理等 **缺点**: - 需要修改现有调用点 - 代码重构量较大 ## 技术实现细节 ### SetAPR API参数结构 ```typescript { deviceUri: "DIOS/DEVICE/Generator", reqName: "SetAPR", reqParam: JSON.stringify({ P0: { FOCUS: "0", TECHMODE: "0", AECFIELD: "101", AECFILM: "0", AECDENSITY: "0", KV: string, // 从aprConfig获取 MA: string, // 从aprConfig获取 MS: string, // 从aprConfig获取 MAS: string, // 从aprConfig获取 KV2: "0.0", MA2: "0.0", MS2: "0.0", DOSE: "0.0", FILTER: "null", TUBELOAD: "0.0", WORKSTATION: number // 从selectedBodyPosition获取 } }) } ``` ### 相关文件 1. **API层**: - `src/API/exam/APRActions.ts` - APR相关API调用 2. **状态管理**: - `src/states/exam/aprSlice.ts` - APR状态和逻辑 - `src/states/exam/bodyPositionListSlice.ts` - 体位状态 3. **UI组件**: - `src/pages/exam/ContentAreaLarge.tsx` - 体型和工作位选择器 ## 实施优先级 1. **高优先级**: 修复体型和工作位更改后的设备同步问题 2. **中优先级**: 添加加载状态和错误处理 3. **低优先级**: 优化性能(防抖、取消重复请求等) ## 验收标准 1. ✅ 更改体位后,UI显示正确且设备参数已更新 2. ✅ 更新体型后,UI显示正确且设备参数已更新 3. ✅ 更改工作位后,UI显示正确且设备参数已更新 4. ✅ 所有场景的行为逻辑一致 5. ✅ 有适当的加载状态提示 6. ✅ 有错误处理和用户反馈 ## 附录 ### 当前代码片段 #### aprMiddleware 当前实现 ```typescript const aprMiddleware: Middleware = (store) => (next) => (action: any) => { const result = next(action); if ( action.type === aprSlice.actions.setBodysize.type || action.type === aprSlice.actions.setWorkstation.type ) { // ... 获取APR参数 getAprExposureParams(id, workStationId, patientSize).then((data) => { if (data) { store.dispatch(setAprConfig(data)); // ❌ 缺少:调用 SetAPR 下发到设备 } }); // ... } return result; }; ``` #### setSelectedBodyPosition extraReducer 当前实现 ```typescript .addCase(setSelectedBodyPosition, (state, action) => { const selectedBodyPosition = action.payload; if (selectedBodyPosition) { const reqParam = JSON.stringify({/* ... */}); SetAPR(reqParam) // ✅ 正确下发到设备 .then(() => console.log('SetAPR method called successfully')) .catch((error) => console.error('Error calling SetAPR method:', error)); } }) ``` --- **文档版本**: 1.0 **创建日期**: 2025-10-08 **最后更新**: 2025-10-08 **负责人**: Development Team