|
@@ -0,0 +1,365 @@
|
|
|
+# 滑动参数调节面板功能实现文档
|
|
|
+
|
|
|
+## 功能概述
|
|
|
+
|
|
|
+在"图像处理"面板(AdvancedProcessingPanel)上添加一个"高级"按钮,点击后打开"滑动参数调节"面板(SliderAdjustmentPanel)。这是一个三级面板,点击返回按钮后会返回到"图像处理"面板。
|
|
|
+
|
|
|
+## 面板层级结构
|
|
|
+
|
|
|
+```
|
|
|
+OperationPanel (二级面板)
|
|
|
+ └── AdvancedProcessingPanel (图像处理 - 三级面板)
|
|
|
+ └── SliderAdjustmentPanel (滑动参数调节 - 四级面板)
|
|
|
+```
|
|
|
+
|
|
|
+## 功能特性
|
|
|
+
|
|
|
+### 1. 参数调整
|
|
|
+- **增益** (contrast): -5~45,步长0.1
|
|
|
+- **细节** (detail): -0.5~24.5,步长0.1
|
|
|
+- **动态范围** (latitude): -5~20,步长0.1
|
|
|
+- **噪声模式** (noise): 0~20,步长0.1
|
|
|
+- **对比度** (brightness): -8~8,步长0.1(仅前端维护)
|
|
|
+- **亮度** (sharpness): -8~8,步长0.1(仅前端维护)
|
|
|
+
|
|
|
+### 2. 下拉选择
|
|
|
+- **算法选择**: RSymphony(默认)
|
|
|
+- **LUT选择**: SIGMOID(默认)、LINER 等
|
|
|
+- **风格选择**: 均衡、高对比、锐组织、骨骼
|
|
|
+
|
|
|
+### 3. 实时预览(新增)
|
|
|
+- 滑块调整后自动获取预览图像(500ms防抖)
|
|
|
+- 使用 Blob URL 实现即时预览
|
|
|
+- 仅后端参数触发预览(contrast, detail, latitude, noise)
|
|
|
+- 前端参数调整不触发后端请求
|
|
|
+
|
|
|
+### 4. 手动操作
|
|
|
+- **重置参数**: 重置为当前风格的默认值
|
|
|
+- **保存参数**: 永久保存到dcm文件
|
|
|
+
|
|
|
+## 技术实现
|
|
|
+
|
|
|
+### 1. 文件结构
|
|
|
+
|
|
|
+```
|
|
|
+src/
|
|
|
+├── types/
|
|
|
+│ └── imageProcessing.ts # 类型定义
|
|
|
+├── domain/
|
|
|
+│ ├── lutConfig.ts # LUT配置
|
|
|
+│ └── processingPresets.ts # 风格预设配置
|
|
|
+├── API/
|
|
|
+│ └── imageActions.ts # 新增API接口
|
|
|
+├── states/
|
|
|
+│ ├── panelSwitchSliceForView.ts # 面板切换状态(已修改)
|
|
|
+│ ├── store.ts # Redux Store(已修改)
|
|
|
+│ └── view/
|
|
|
+│ └── sliderAdjustmentPanelSlice.ts # 滑动参数调节面板状态
|
|
|
+└── pages/
|
|
|
+ └── view/
|
|
|
+ └── components/
|
|
|
+ ├── ParameterSlider.tsx # 参数滑块组件
|
|
|
+ ├── SliderAdjustmentPanel.tsx # 滑动参数调节面板
|
|
|
+ ├── AdvancedProcessingPanel.tsx # 高级处理面板(已修改)
|
|
|
+ └── OperationPanel.tsx # 操作面板(已修改)
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 核心组件
|
|
|
+
|
|
|
+#### ParameterSlider 组件
|
|
|
+- 可复用的参数滑块组件
|
|
|
+- 包含:标签、范围提示、当前值显示、滑块、加减按钮
|
|
|
+- 支持自定义范围、步长、禁用状态
|
|
|
+
|
|
|
+#### SliderAdjustmentPanel 组件
|
|
|
+- 主要面板组件
|
|
|
+- 集成6个参数滑块
|
|
|
+- 集成算法、LUT、风格下拉选择
|
|
|
+- 实现防抖自动保存
|
|
|
+- 提供重置和手动保存按钮
|
|
|
+
|
|
|
+### 3. 状态管理
|
|
|
+
|
|
|
+#### sliderAdjustmentPanelSlice
|
|
|
+- **状态**:
|
|
|
+ - `currentImageId`: 当前图像ID
|
|
|
+ - `parameters`: 当前参数值
|
|
|
+ - `selectedStyle`: 当前风格
|
|
|
+ - `selectedAlgorithm`: 当前算法
|
|
|
+ - `selectedLUT`: 当前LUT
|
|
|
+ - `isLoading`: 加载状态
|
|
|
+ - `isSaving`: 保存状态
|
|
|
+ - `isInitialLoad`: 初始加载标志
|
|
|
+ - `error`: 错误信息
|
|
|
+
|
|
|
+- **异步操作**:
|
|
|
+ - `loadImageProcessingParams`: 加载图像处理参数
|
|
|
+ - `saveProcessingParams`: 保存图像处理参数
|
|
|
+
|
|
|
+- **同步操作**:
|
|
|
+ - `setCurrentImageId`: 设置当前图像ID
|
|
|
+ - `updateParameter`: 更新单个参数
|
|
|
+ - `applyPreset`: 应用风格预设
|
|
|
+ - `resetToPreset`: 重置为当前风格默认值
|
|
|
+ - `setAlgorithm`: 设置算法
|
|
|
+ - `setLUT`: 设置LUT
|
|
|
+ - `clearError`: 清除错误
|
|
|
+ - `resetState`: 重置状态
|
|
|
+
|
|
|
+#### panelSwitchSliceForView(修改)
|
|
|
+- 新增 `SliderAdjustmentPanel` 面板类型
|
|
|
+- 新增 `switchToSliderAdjustmentPanel` action
|
|
|
+
|
|
|
+### 4. API接口
|
|
|
+
|
|
|
+#### getImageProcessingParams
|
|
|
+```typescript
|
|
|
+GET /auth/image/{sopInstanceUid}/preparation
|
|
|
+```
|
|
|
+获取当前图像处理参数(增益、细节、动态范围、噪声模式)
|
|
|
+
|
|
|
+#### getProcessedDcm(新增)
|
|
|
+```typescript
|
|
|
+GET /auth/image/{sopInstanceUid}/proc?contrast=5.0&detail=9.0&latitude=25.0&noise=12.0
|
|
|
+```
|
|
|
+获取应用指定参数后的处理后dcm文件(用于实时预览)
|
|
|
+- **返回**: 直接返回dcm文件的二进制数据(Blob)
|
|
|
+- **用途**: 滑块调整时实时预览
|
|
|
+- **机制**:
|
|
|
+ 1. 前端调用API获取Blob
|
|
|
+ 2. 使用 `URL.createObjectURL(blob)` 创建临时URL
|
|
|
+ 3. 更新Viewer显示新图像
|
|
|
+ 4. 适当时机调用 `URL.revokeObjectURL()` 释放内存
|
|
|
+
|
|
|
+#### saveImageProcessingParams
|
|
|
+```typescript
|
|
|
+POST /auth/image/{sopInstanceUid}/proc
|
|
|
+Body: {
|
|
|
+ contrast: number, // 增益
|
|
|
+ detail: number, // 细节
|
|
|
+ latitude: number, // 动态范围
|
|
|
+ noise: number // 噪声模式
|
|
|
+}
|
|
|
+```
|
|
|
+保存图像处理参数到DICOM文件(永久保存)
|
|
|
+- **用途**: 点击"保存参数"按钮时调用
|
|
|
+- **效果**: 将处理后的dcm永久保存到文件系统
|
|
|
+
|
|
|
+### 5. 配置文件
|
|
|
+
|
|
|
+#### processingPresets.ts
|
|
|
+```typescript
|
|
|
+export const PROCESSING_PRESETS: Record<ProcessingStyle, PresetConfig> = {
|
|
|
+ '均衡': {
|
|
|
+ name: '均衡',
|
|
|
+ params: { contrast: 5.0, detail: 9.0, latitude: 25.0, noise: 12.0, brightness: -2.0, sharpness: 1.0 }
|
|
|
+ },
|
|
|
+ '高对比': {
|
|
|
+ name: '高对比',
|
|
|
+ params: { contrast: 10.0, detail: 5.0, latitude: 15.0, noise: 8.0, brightness: 0.0, sharpness: 2.0 }
|
|
|
+ },
|
|
|
+ // ...
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+#### lutConfig.ts
|
|
|
+```typescript
|
|
|
+export const LUT_OPTIONS: LUTType[] = [
|
|
|
+ 'SIGMOID',
|
|
|
+ 'LINER',
|
|
|
+ // ...
|
|
|
+];
|
|
|
+```
|
|
|
+
|
|
|
+## 用户交互流程
|
|
|
+
|
|
|
+### 1. 进入滑动参数调节面板
|
|
|
+```
|
|
|
+用户在"图像处理"面板
|
|
|
+ → 点击"高级"按钮
|
|
|
+ → 进入"滑动参数调节"面板
|
|
|
+ → 自动加载当前图像的参数
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 调整参数(实时预览)
|
|
|
+```
|
|
|
+用户拖动滑块或点击加减按钮
|
|
|
+ → 参数值实时更新到Redux
|
|
|
+ → 触发500ms防抖定时器
|
|
|
+ → 调用GET API获取预览dcm(Blob)
|
|
|
+ → 创建Blob URL
|
|
|
+ → 刷新Viewer显示
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 保存参数(永久保存)
|
|
|
+```
|
|
|
+用户点击"保存参数"按钮
|
|
|
+ → 调用POST API永久保存
|
|
|
+ → 成功提示
|
|
|
+```
|
|
|
+
|
|
|
+### 4. 切换风格
|
|
|
+```
|
|
|
+用户选择不同风格
|
|
|
+ → 应用对应的预设参数
|
|
|
+ → 立即保存到后端(POST)
|
|
|
+```
|
|
|
+
|
|
|
+### 5. 返回上级面板
|
|
|
+```
|
|
|
+用户点击返回按钮
|
|
|
+ → 返回到"图像处理"面板
|
|
|
+```
|
|
|
+
|
|
|
+## 数据流
|
|
|
+
|
|
|
+### 实时预览流程
|
|
|
+```
|
|
|
+用户拖动滑块
|
|
|
+ ↓
|
|
|
+UI组件 (SliderAdjustmentPanel)
|
|
|
+ ↓
|
|
|
+Redux Action (updateParameter)
|
|
|
+ ↓
|
|
|
+Redux State 更新
|
|
|
+ ↓
|
|
|
+防抖处理 (500ms)
|
|
|
+ ↓
|
|
|
+API调用 GET /proc (getProcessedDcm)
|
|
|
+ ↓
|
|
|
+获取Blob数据
|
|
|
+ ↓
|
|
|
+创建Blob URL
|
|
|
+ ↓
|
|
|
+更新Viewer显示(TODO)
|
|
|
+```
|
|
|
+
|
|
|
+### 永久保存流程
|
|
|
+```
|
|
|
+用户点击"保存参数"
|
|
|
+ ↓
|
|
|
+UI组件 (SliderAdjustmentPanel)
|
|
|
+ ↓
|
|
|
+Redux Thunk (saveProcessingParams)
|
|
|
+ ↓
|
|
|
+API调用 POST /proc (saveImageProcessingParams)
|
|
|
+ ↓
|
|
|
+后端永久保存到dcm文件
|
|
|
+ ↓
|
|
|
+成功提示
|
|
|
+```
|
|
|
+
|
|
|
+## 注意事项
|
|
|
+
|
|
|
+### 1. 参数分类
|
|
|
+- **后端参数** (4个): contrast, detail, latitude, noise
|
|
|
+ - 会保存到DICOM文件
|
|
|
+ - 通过API接口同步
|
|
|
+
|
|
|
+- **前端参数** (2个): brightness, sharpness
|
|
|
+ - 仅在前端维护
|
|
|
+ - 不会保存到后端
|
|
|
+
|
|
|
+### 2. 防抖机制
|
|
|
+- 参数调整触发500ms防抖
|
|
|
+- 避免频繁调用预览API
|
|
|
+- 初始加载时不触发预览
|
|
|
+- 前端参数(brightness, sharpness)不触发后端请求
|
|
|
+
|
|
|
+### 3. 错误处理
|
|
|
+- API调用失败时显示错误提示
|
|
|
+- 加载失败时使用默认值
|
|
|
+- 错误信息存储在Redux state中
|
|
|
+
|
|
|
+### 4. 待完善功能
|
|
|
+- 当前图像ID获取逻辑(TODO)
|
|
|
+- 需要从ViewerContainer或其他地方获取当前选中图像的sopInstanceUid
|
|
|
+
|
|
|
+## 测试步骤
|
|
|
+
|
|
|
+### 1. 面板切换测试
|
|
|
+- [ ] 从"图像处理"面板点击"高级"按钮
|
|
|
+- [ ] 验证进入"滑动参数调节"面板
|
|
|
+- [ ] 点击返回按钮
|
|
|
+- [ ] 验证返回到"图像处理"面板
|
|
|
+
|
|
|
+### 2. 参数调整测试
|
|
|
+- [ ] 拖动各个参数滑块
|
|
|
+- [ ] 验证参数值实时更新
|
|
|
+- [ ] 验证UI显示正确
|
|
|
+- [ ] 等待500ms后验证API调用
|
|
|
+
|
|
|
+### 3. 风格切换测试
|
|
|
+- [ ] 选择不同的风格
|
|
|
+- [ ] 验证参数值立即更新
|
|
|
+- [ ] 验证立即触发保存
|
|
|
+
|
|
|
+### 4. 手动操作测试
|
|
|
+- [ ] 点击"重置参数"按钮
|
|
|
+- [ ] 验证参数恢复到当前风格默认值
|
|
|
+- [ ] 点击"保存参数"按钮
|
|
|
+- [ ] 验证手动触发保存
|
|
|
+
|
|
|
+### 5. 边界条件测试
|
|
|
+- [ ] 参数值达到最大值/最小值时的表现
|
|
|
+- [ ] 网络请求失败时的错误处理
|
|
|
+- [ ] 快速切换参数时的防抖效果
|
|
|
+
|
|
|
+## 潜在问题与解决方案
|
|
|
+
|
|
|
+### 1. 图像ID获取
|
|
|
+**问题**: 当前代码中sopInstanceUid获取逻辑未实现
|
|
|
+**解决方案**: 需要从ViewerContainer或selectedBodyPosition中获取当前选中图像的ID
|
|
|
+
|
|
|
+### 2. 参数同步
|
|
|
+**问题**: 前端参数(brightness, sharpness)与后端参数(contrast, detail等)的同步
|
|
|
+**解决方案**:
|
|
|
+- 后端参数通过API同步
|
|
|
+- 前端参数仅在Redux中维护
|
|
|
+- 加载时只更新后端返回的4个参数
|
|
|
+
|
|
|
+### 3. Blob URL内存管理
|
|
|
+**问题**: 每次预览都创建新的Blob URL,可能导致内存泄漏
|
|
|
+**解决方案**:
|
|
|
+- 在创建新URL前,先revoke旧的URL
|
|
|
+- 组件卸载时清理所有Blob URL
|
|
|
+- 考虑使用useRef存储当前的blobUrl
|
|
|
+
|
|
|
+### 4. 并发请求
|
|
|
+**问题**: 用户快速切换参数可能导致多次API调用
|
|
|
+**解决方案**: 使用500ms防抖机制,合并多次操作为一次请求
|
|
|
+
|
|
|
+## 扩展建议
|
|
|
+
|
|
|
+1. **参数预览**: 在调整参数时实时预览效果
|
|
|
+2. **参数历史**: 记录参数调整历史,支持撤销/重做
|
|
|
+3. **自定义风格**: 允许用户保存自定义的参数组合为新风格
|
|
|
+4. **参数对比**: 支持查看调整前后的参数对比
|
|
|
+5. **批量应用**: 支持将当前参数应用到多张图像
|
|
|
+
|
|
|
+## 更新日志
|
|
|
+
|
|
|
+### 2025-01-22
|
|
|
+- ✅ 完成类型定义
|
|
|
+- ✅ 完成配置文件创建
|
|
|
+- ✅ 完成API接口扩展(包括getProcessedDcm)
|
|
|
+- ✅ 完成状态管理实现
|
|
|
+- ✅ 完成UI组件开发
|
|
|
+- ✅ 完成面板集成
|
|
|
+- ✅ 实现实时预览API调用逻辑
|
|
|
+- ⏳ 待完成:获取当前图像ID逻辑
|
|
|
+- ⏳ 待完成:Cornerstone图像刷新实现
|
|
|
+- ⏳ 待完成:Blob URL内存管理
|
|
|
+- ⏳ 待完成:功能测试
|
|
|
+
|
|
|
+### 实时预览实现细节
|
|
|
+**已实现**:
|
|
|
+1. 新增 `getProcessedDcm` API - 获取处理后的dcm Blob
|
|
|
+2. 修改滑块逻辑 - 调用预览API而非保存API
|
|
|
+3. 区分前端参数和后端参数 - 只有后端参数触发预览
|
|
|
+4. 防抖机制 - 500ms延迟避免频繁请求
|
|
|
+
|
|
|
+**待实现**:
|
|
|
+1. Blob URL → Cornerstone 图像刷新
|
|
|
+2. Blob URL 内存管理(revoke机制)
|
|
|
+3. 获取当前图像ID的完整逻辑
|