# 高级处理双端保存方案 ## 📋 需求说明 在高级处理(`SliderAdjustmentPanel`)中实现**双端保存机制**: ### 核心目标 **在保存参数时调用后端API保存参数并重建DCM** ### 具体要求 - 用户通过滑动条调节图像参数时,仅更新前端预览 - 用户点击"保存参数"按钮或执行特定操作时,触发后端保存 - 调用 `rebuildDcm` API 进行**异步保存和重建DCM** - 实现前端预览 + 后端持久化的**双端同步机制** ## 🔍 当前实现分析 ### 1. 当前代码流程 **文件位置**: `src/pages/view/components/SliderAdjustmentPanel.tsx` ``` 用户滑动参数 ↓ handleParameterChange (更新Redux状态) ↓ debouncedPreview / debouncedWASMPreview (防抖500ms/300ms) ↓ 更新 viewer URL (触发图像重新渲染) ↓ ✅ 预览更新完成 ❌ 没有调用后端保存 API,也不需要 ``` ### 2. 现有的保存机制 目前只有以下1种情况会调用 `rebuildDcm`: 1. **手动保存** (`handleSave`) - 用户点击"保存参数"按钮 ### 3. 相关API **文件位置**: `src/API/imageActions.ts` ```typescript /** * 重建dcm(保存应用增强参数后的dcm) */ export const rebuildDcm = async ( sopInstanceUid: string, params: RebuildDcmRequest ): Promise interface RebuildDcmRequest { contrast: number; // 增益 detail: number; // 细节 latitude: number; // 动态范围 noise: number; // 噪声模式 ww_coef: number; // 对比度 wl_coef: number; // 亮度 } ``` ## 🔄 参数变化触发场景 参数变化可由多种用户操作和系统行为触发,需要区分哪些场景需要保存到后端: ### 场景1: 初始化加载 ❌ 不保存 **触发时机**: 组件挂载时自动执行 ```typescript useEffect(() => { // 从后端加载当前图像的参数 dispatch(loadImageProcessingParams(sopInstanceUid)); }, [dispatch]); ``` **行为**: - 从后端读取已保存的参数 - 更新 Redux 状态 - 设置 `isInitialLoad = true` 标志 - **不触发保存**(避免循环调用) ### 场景2: 用户滑动滑块 ❌ 不保存 **触发时机**: 用户拖动任一参数滑块 ```typescript handleParameterChange('contrast', 5.0) // 增益 handleParameterChange('detail', 8.0) // 细节 handleParameterChange('latitude', 6.0) // 动态范围 handleParameterChange('noise', 4.0) // 噪声模式 handleParameterChange('brightness', 1.2) // 对比度 handleParameterChange('sharpness', -0.5) // 亮度 ``` **行为**: - 更新 Redux 状态 - 设置 `isInitialLoad = false` - **仅触发防抖预览** - 更新前端预览(仅前端状态,不保存到后端) ### 场景3: 切换风格 ❌ 不保存 **触发时机**: 用户在下拉框中选择风格 ```typescript handleStyleChange('高对比') // 均衡 | 高对比 | 锐组织 | 骨骼 ``` **行为**: - 应用风格预设参数 - 更新 Redux 状态 - 设置 `isInitialLoad = false` - **仅更新前端预览**(参数已批量更新,不保存到后端) ### 场景4: 重置参数 ❌ 不保存 **触发时机**: 用户点击"重置参数"按钮 ```typescript handleReset() ``` **行为**: - 重置为当前风格的默认参数 - 更新 Redux 状态 - 设置 `isInitialLoad = false` - **仅更新前端预览**(参数已批量更新,不保存到后端) ### 场景5: 手动保存 ✅ 立即保存 **触发时机**: 用户点击"保存参数"按钮 ```typescript handleSave() ``` **行为**: - 使用当前 Redux 中的参数 - **立即调用 saveProcessingParams** → **触发 rebuildDcm** - 不更新预览(仅保存) ### 场景6: 算法/LUT切换 ⚠️ 前端状态 **触发时机**: 用户切换算法或LUT ```typescript handleAlgorithmChange('算法A') handleLUTChange('LUT1') ``` **行为**: - 仅更新前端 Redux 状态 - **不调用后端API**(算法和LUT是前端渲染配置) ## 🎯 实现方案 ### 目标流程 ``` 用户滑动参数 ↓ handleParameterChange (更新Redux状态) ↓ debouncedPreview / debouncedWASMPreview (防抖) ↓ 更新 viewer URL (触发图像重新渲染) ↓ ✅ 预览更新完成(仅前端状态) ``` ### 保存时机 重建DCM仅在以下情况调用: 1. **手动保存**: 用户点击"保存参数"按钮时,保存当前参数到后端并重建DCM ### 实现步骤 **无需修改 `debouncedPreview` 和 `debouncedWASMPreview` 函数** - 保持原有逻辑,仅用于前端预览更新 - 不添加自动保存调用 ## ⚙️ 技术细节 ### 1. 防抖机制 - 传统模式: 500ms 防抖延迟 - WASM模式: 300ms 防抖延迟 - 仅用于平滑预览更新,不涉及API调用 ### 2. 保存参数映射 ```typescript Redux State → API Request ------------------------------ contrast → contrast detail → detail latitude → latitude noise → noise brightness → ww_coef sharpness → wl_coef ``` ### 3. 保存错误处理策略 ```typescript try { await rebuildDcm(...); // 保存到后端 console.log('✅ 参数已保存到后端'); } catch (saveError) { console.error('⚠️ 保存参数失败:', saveError); // 显示错误提示,但不影响其他操作 } ``` ## 🔒 注意事项 ### 1. 性能考虑 - ✅ 前端预览响应迅速,无API调用阻塞 - ✅ 保存操作异步执行,不影响UI响应 - ✅ 防抖机制确保预览流畅 ### 2. 用户体验 - ✅ 滑动参数时即时预览,无延迟 - ✅ 需要时手动保存,控制数据持久化 - ✅ 保存状态明确反馈 ### 3. 与现有功能的兼容性 - ✅ 保留"保存参数"按钮(立即保存) - ✅ 风格切换和重置参数仅更新前端预览 - ✅ 不影响初始加载逻辑 ### 4. 两种模式的处理 - **传统模式**: 前端预览 + 按需保存到后端 - **WASM模式**: 本地WASM预览 + 按需保存到后端 ## 📝 测试清单 - [ ] 滑动参数时,仅更新预览,不调用后端API - [ ] 防抖生效,快速滑动时预览流畅 - [ ] 传统模式下预览正常 - [ ] WASM模式下预览正常 - [ ] 手动保存按钮可用,点击后调用rebuildDcm - [ ] 保存成功时,控制台显示"参数已保存到后端" - [ ] 保存失败时,显示错误提示 - [ ] 切换风格仅更新前端预览,不调用后端API - [ ] 重置参数仅更新前端预览,不调用后端API ## 🔧 相关文件 - **组件**: `src/pages/view/components/SliderAdjustmentPanel.tsx` - **API**: `src/API/imageActions.ts` - **Redux**: `src/states/view/sliderAdjustmentPanelSlice.ts` - **类型**: `src/types/imageProcessing.ts` ## 📚 相关文档 - [滑动参数调节面板功能](./滑动参数调节面板功能.md) - [滑动参数调节面板-双模式处理流程](./滑动参数调节面板-双模式处理流程.md)