# 滑动参数调节面板 - 双模式处理流程 > SliderAdjustmentPanel 组件的完整处理流程文档 ## 📖 概述 本文档描述了滑动参数调节面板(SliderAdjustmentPanel)的完整处理流程,包括传统模式和WASM模式的双模式支持。 --- ## 🎯 组件职责 滑动参数调节面板是三级面板,用于调整图像处理参数,支持: - 实时参数调节与预览 - 参数持久化保存 - 风格预设切换 - 双处理模式(传统模式 / WASM模式) --- ## 🔄 完整处理流程 ### 1. 组件初始化阶段 ```mermaid graph TD A[组件挂载] --> B[读取系统配置] B --> C{处理模式?} C -->|传统模式| D[传统模式初始化] C -->|WASM模式| E[WASM模式初始化] E --> F[初始化SDK] F --> G[注册enhanced loader] D --> H[获取图像ID] G --> H H --> I[加载图像参数] I --> J[渲染UI] ``` #### 1.1 读取处理模式配置 ```typescript // 从系统设置Redux store读取 const processingMode = useAppSelector(selectProcessingMode); const isWASMMode = processingMode === 'wasm'; ``` #### 1.2 获取当前图像ID ```typescript useEffect(() => { // 从 viewer 容器获取当前选中的图像 const dcmUrls = store.getState().viewerContainer.selectedViewers; // 验证:必须且仅有一个选中的图像 if (dcmUrls.length !== 1) { console.error('异常:选中图像数量不为1'); return; } // 提取 SOP Instance UID const sopInstanceUid = getSopInstanceUidFromUrl(dcmUrls[0]); if (sopInstanceUid) { // 加载该图像的处理参数 dispatch(loadImageProcessingParams(sopInstanceUid)); } }, [dispatch]); ``` #### 1.3 加载图像处理参数 ```typescript // Redux Thunk 异步操作 loadImageProcessingParams(sopInstanceUid) ├─> 调用 API: getImageProcessingParams(sopInstanceUid) ├─> 返回参数: { contrast, detail, latitude, noise } └─> 更新 Redux state ├─> parameters (合并前端参数 brightness, sharpness) ├─> currentImageId └─> isInitialLoad = true (防止触发自动预览) ``` --- ### 2. 传统模式处理流程 #### 2.1 参数调节流程 ```mermaid graph LR A[用户拖动滑块] --> B[handleParameterChange] B --> C[更新Redux state] C --> D{是后端参数?} D -->|是| E[触发防抖预览] D -->|否| F[仅更新UI] E --> G[500ms后执行] G --> H[buildProcessedDcmUrl] H --> I[添加URL参数] I --> J[updateViewerUrl] J --> K[Cornerstone重新渲染] ``` #### 2.2 URL参数构建 ```typescript // 传统模式:构建带参数的DCM URL const processedUrl = buildProcessedDcmUrl(currentImageId, { contrast: params.contrast.toString(), detail: params.detail.toString(), latitude: params.latitude.toString(), noise: params.noise.toString(), }); // 示例URL // /dr/api/v1/pub/dcm/1.2.3.4.5?contrast=5&detail=3&latitude=7&noise=2 ``` #### 2.3 后端参数 vs 前端参数 | 参数名称 | 参数类型 | 处理方式 | |---------|---------|---------| | contrast (增益) | 后端参数 | URL传递,后端处理 | | detail (细节) | 后端参数 | URL传递,后端处理 | | latitude (动态范围) | 后端参数 | URL传递,后端处理 | | noise (噪声模式) | 后端参数 | URL传递,后端处理 | | brightness (对比度) | 前端参数 | 仅UI更新,不触发预览 | | sharpness (亮度) | 前端参数 | 仅UI更新,不触发预览 | --- ### 3. WASM模式处理流程 #### 3.1 SDK初始化 ```typescript // 使用自定义Hook初始化SDK const { sdk, isSDKReady, isInitializing, error: sdkError } = useImageEnhancementSDK({ sopInstanceUid: currentImageId, enabled: isWASMMode, // 仅在WASM模式下启用 }); // Hook内部流程 useImageEnhancementSDK ├─> 初始化Cornerstone3D ├─> 创建SDK实例 (createImageEnhancementSDK) │ ├─> 配置WASM URL: /static/DRENHANCE.js │ ├─> 配置TIF URL: /dr/api/v1/pub/tif/{sopInstanceUid}-0001.tif │ └─> 配置DCM URL: /dr/api/v1/pub/dcm/{sopInstanceUid}.dcm ├─> 注册 'enhanced' schema loader └─> 返回SDK实例 ``` #### 3.2 WASM参数调节流程 ```mermaid graph LR A[用户拖动滑块] --> B[handleParameterChange] B --> C[更新Redux state] C --> D[更新SDK ParameterManager] D --> E[触发WASM防抖预览] E --> F[300ms后执行] F --> G[生成新imageId+时间戳] G --> H[enhanced:sopInstanceUid_timestamp] H --> I[updateViewerUrl] I --> J[触发enhanced loader] J --> K[SDK WASM处理] K --> L[返回增强图像] L --> M[Cornerstone渲染] ``` #### 3.3 WASM预览实现 ```typescript const debouncedWASMPreview = useCallback( (params: FullProcessingParams) => { if (isInitialLoad || !sdk || !currentImageId) return; clearTimeout(saveTimerRef.current); saveTimerRef.current = setTimeout(async () => { // 1. 更新SDK参数管理器 sdk.parameterManager.updateParameters(params); // 2. 生成唯一imageId(带时间戳强制重新加载) const timestamp = Date.now(); const enhancedImageId = `enhanced:${currentImageId}_${timestamp}`; // 3. 更新viewer URL dispatch(updateViewerUrl({ originalUrl: dcmUrls[0], newUrl: enhancedImageId, })); // 4. Cornerstone调用enhanced loader // 5. SDK处理TIF数据并应用WASM增强 // 6. 返回增强后的图像 }, 300); // WASM模式使用更短的防抖时间 }, [currentImageId, isInitialLoad, sdk, dispatch] ); ``` --- ## 🎯 滑块调整后的完整执行流程 ### 概览:从滑块到屏幕显示 ``` 用户滑动滑块 ↓ handleParameterChange() 被触发 ↓ 1️⃣ 立即更新Redux State(UI响应) ↓ 2️⃣ 检查参数类型(后端 vs 前端) ↓ 3️⃣ 判断处理模式(WASM / 传统) ↓ 4️⃣ 执行对应的防抖预览函数 ↓ 5️⃣ 更新Viewer URL ↓ 6️⃣ Cornerstone重新渲染图像 ``` --- ### 📊 完整时间轴对比 #### WASM模式时间轴(默认) ``` 时间点 0ms ├─ 用户滑动滑块(例如:增益从5调到7) └─ onChange事件触发 时间点 0ms(立即) ├─ handleParameterChange('contrast', 7) 执行 ├─ dispatch(updateParameter({ name: 'contrast', value: 7 })) ├─ Redux state更新:parameters.contrast = 7 └─ UI立即显示新值:滑块位置 = 7 时间点 0ms(立即) ├─ 构建新参数对象:newParams = { ...parameters, contrast: 7 } ├─ 判断:'contrast' 属于后端参数 ✅ ├─ 判断:当前模式 = 'wasm' ✅ └─ 调用:debouncedWASMPreview(newParams) 时间点 0-300ms └─ 防抖等待中...(用户可能继续调参) 时间点 300ms(防抖结束) ├─ 清除之前的定时器 ├─ 开始执行WASM预览逻辑 ├─ Step 1: sdk.parameterManager.updateParameters(newParams) │ └─ SDK内部参数存储更新 ├─ Step 2: 生成唯一imageId │ └─ enhancedImageId = `enhanced:1.2.3.4.5_1701364800000` └─ Step 3: dispatch(updateViewerUrl({ newUrl: enhancedImageId })) 时间点 300ms+(网络请求开始) ├─ Cornerstone检测到URL变化 ├─ 调用注册的Enhanced Loader └─ EnhancedImageLoader.loadImage(enhancedImageId) 执行 ├─ Step 1: prefetchMetadata() │ ├─ URL: /dr/api/v1/pub/dcm/1.2.3.4.5.dcm │ ├─ 网络请求1:获取DCM元数据(几KB) │ └─ DicomMetaDataManager缓存元数据 │ ├─ Step 2: DicomMetaDataManager.get() │ └─ 从缓存读取元数据(窗宽窗位等) │ ├─ Step 3: tifService.fetchImageData() 🎯 关键! │ ├─ URL: /dr/api/v1/pub/tif/1.2.3.4.5-0001.tif │ ├─ 网络请求2:下载TIF文件(2-4MB,16-bit原始数据) │ ├─ 解析TIFF格式 │ └─ 返回: TIFImageData { │ width: 512, │ height: 512, │ bitsPerSample: 16, │ pixelData: Uint16Array(262144) // 512×512像素 │ } │ └─ Step 4: imageCreator.createEnhancedImage() ├─ 调用WASM增强算法 ├─ Module.enhancePixelData(pixelData, params) │ └─ 使用新参数处理16-bit像素数据 ├─ 创建Cornerstone图像对象 └─ 返回:CornerstoneImage 时间点 300ms++ (渲染) ├─ Cornerstone接收增强后的图像 ├─ 应用窗宽窗位 ├─ GPU渲染到Canvas └─ 屏幕显示更新后的图像 ✨ 总耗时:约 300ms(防抖)+ 100-300ms(网络+WASM处理) ``` --- #### 传统模式时间轴 ``` 时间点 0ms └─ 用户滑动滑块 时间点 0ms(立即) ├─ handleParameterChange('contrast', 7) ├─ Redux state更新 └─ UI显示新值 时间点 0ms(立即) ├─ 判断:当前模式 = 'traditional' └─ 调用:debouncedPreview(newParams) 时间点 0-500ms └─ 防抖等待中... 时间点 500ms(防抖结束) ├─ 构建处理URL │ └─ /dr/api/v1/pub/dcm/xxx.dcm?contrast=7&detail=5&latitude=5&noise=5 ├─ dispatch(updateViewerUrl({ newUrl: `dicomweb:${url}` })) └─ Cornerstone检测到URL变化 时间点 500ms+ ├─ 网络请求:带参数的DCM文件 ├─ 后端服务器处理图像(应用参数) ├─ 返回处理后的DCM └─ Cornerstone渲染 总耗时:约 500ms(防抖)+ 200-500ms(后端处理) ``` --- ### 🔗 WASM模式TIF获取完整调用链 ```typescript // 📍 Level 1: 用户交互层 handleParameterChange('contrast', value)} /> ↓ // 📍 Level 2: 参数处理层 (SliderAdjustmentPanel.tsx) handleParameterChange(name: 'contrast', value: 7) { // 1. 立即更新UI dispatch(updateParameter({ name: 'contrast', value: 7 })) // 2. 准备新参数 const newParams = { ...parameters, contrast: 7 } // 3. 检查并调用WASM预览 if (['contrast', 'detail', 'latitude', 'noise'].includes(name)) { if (isWASMMode) { debouncedWASMPreview(newParams) // ← 这里 } } } ↓ // 📍 Level 3: 防抖预览层 (SliderAdjustmentPanel.tsx) debouncedWASMPreview(params) { setTimeout(async () => { // 1. 更新SDK参数管理器 sdk.parameterManager.updateParameters(params) // 2. 生成唯一ID(带时间戳) const timestamp = Date.now() const enhancedImageId = `enhanced:${currentImageId}_${timestamp}` // 3. 触发URL更新 dispatch(updateViewerUrl({ originalUrl: dcmUrls[0], newUrl: enhancedImageId // ← 关键:新URL触发重新加载 })) }, 300) } ↓ // 📍 Level 4: Cornerstone层 // Cornerstone检测到imageId变化,调用注册的loader cornerstone.imageLoader.loadImage(enhancedImageId) → 查找 'enhanced:' schema的loader → 调用 EnhancedImageLoader.loadImage() ↓ // 📍 Level 5: 图像加载器层 (EnhancedImageLoader.ts) async loadImage(imageId: string): Promise { console.log(`🔄 Loader被调用 - imageId: ${imageId}`) // 清理imageId(移除前缀和时间戳) const cleanId = imageId.replace(/^enhanced:/, "").split('_')[0] // cleanId = "1.2.3.4.5" try { // 🔑 Step 1: 预加载DCM元数据 await prefetchMetadata(imageId) // 🔍 Step 2: 从缓存获取元数据 const metadataUrl = this.getMetadataUrl(cleanId) const dcmMetadata = DicomMetaDataManager.get(metadataUrl) // 🎯 Step 3: 获取TIF原始数据 ← 关键步骤! const tifData = await this.tifService.fetchImageData(cleanId) console.log('📦 TIF数据获取成功:', { width: tifData.width, // 512 height: tifData.height, // 512 bits: tifData.bitsPerSample // 16 }) // 🏗️ Step 4: WASM增强 + 创建图像 const enhancedImage = await this.imageCreator .createEnhancedImage(tifData, dcmMetadata) return enhancedImage } catch (error) { console.error('❌ 增强图像加载失败:', error) throw error } } ↓ // 📍 Level 6: TIF服务层 (TIFImageService.ts) async fetchImageData(sopInstanceUID: string): Promise { // 1. 构建TIF URL const tifUrl = `${this.baseUrl}/tif/${sopInstanceUID}-0001.tif` // tifUrl = "/dr/api/v1/pub/tif/1.2.3.4.5-0001.tif" console.log('🌐 开始下载TIF文件:', tifUrl) // 2. 网络请求获取TIF文件 const response = await fetch(tifUrl, { headers: { 'Authorization': this.authorization, 'Accept': 'image/tiff', ...this.headers } }) if (!response.ok) { throw new Error(`TIF下载失败: ${response.status}`) } // 3. 获取二进制数据 const arrayBuffer = await response.arrayBuffer() console.log('📦 TIF文件下载完成:', { size: `${(arrayBuffer.byteLength / 1024 / 1024).toFixed(2)} MB` }) // 4. 解析TIFF格式 const tiffData = await this.parseTIFF(arrayBuffer) // 5. 提取16-bit像素数据 return { width: tiffData.width, height: tiffData.height, bitsPerSample: 16, pixelData: new Uint16Array(tiffData.data), photometricInterpretation: 'MONOCHROME2' } } ↓ // 📍 Level 7: WASM增强层 (EnhancedImageCreator.ts) async createEnhancedImage( tifData: TIFImageData, dcmMetadata?: DicomMetadata ): Promise { // 1. 获取当前参数 const params = this.parameterManager.getCurrentParameters() console.log('🎛️ 应用增强参数:', params) // 2. WASM算法处理像素数据 const enhancedPixels = await this.wasmEnhancer.enhancePixelData( tifData.pixelData, // Uint16Array(262144) - 16bit原始数据 params // { contrast: 7, detail: 5, ... } ) // 3. 创建Cornerstone图像对象 const image: CornerstoneImage = { imageId: this.generateImageId(), width: tifData.width, height: tifData.height, color: false, // 使用增强后的像素数据 getPixelData: () => enhancedPixels, // 从DCM元数据获取 minPixelValue: dcmMetadata?.image?.smallestPixelValue || 0, maxPixelValue: dcmMetadata?.image?.largestPixelValue || 65535, slope: dcmMetadata?.modalityLut?.rescaleSlope || 1, intercept: dcmMetadata?.modalityLut?.rescaleIntercept || 0, windowCenter: dcmMetadata?.voiLut?.windowCenter?.[0] || 32768, windowWidth: dcmMetadata?.voiLut?.windowWidth?.[0] || 65536, // 其他属性... } return image } ↓ // 📍 Level 8: WASM模块层 (WASMEnhancer.ts) async enhancePixelData( pixelData: Uint16Array, params: EnhancementParams ): Promise { console.log('⚙️ WASM模块开始处理...') // 调用编译好的WASM函数 const result = this.wasmModule._enhance_image( pixelData, params.contrast, // 7 (新值) params.detail, // 5 params.latitude, // 5 params.noise // 5 ) console.log('✅ WASM处理完成') return new Uint16Array(result) } ↓ // 📍 Level 9: 渲染层 // Cornerstone接收增强后的图像对象 // → 应用窗宽窗位 // → GPU渲染到Canvas // → 屏幕显示更新 ✨ ``` --- ### 📡 网络请求详解 #### WASM模式的两次网络请求 ```typescript // 请求1: DCM元数据(首次加载时,后续从缓存读取) GET /dr/api/v1/pub/dcm/1.2.3.4.5.dcm Headers: { Authorization: "Bearer xxx", Accept: "application/dicom" } Response: - Size: 几KB到几十KB - Content: DICOM元数据(患者信息、窗宽窗位等) - 用途: 提供图像显示参数 - 缓存: DicomMetaDataManager(整个会话期间) // 请求2: TIF原始数据(每次参数调整都会请求) GET /dr/api/v1/pub/tif/1.2.3.4.5-0001.tif Headers: { Authorization: "Bearer xxx", Accept: "image/tiff" } Response: - Size: 2-4MB (512×512×2字节) - Content: 16-bit TIFF图像 - 用途: 提供原始像素数据用于WASM增强 - 缓存: 无(每次重新获取以应用新参数) ``` #### 传统模式的一次网络请求 ```typescript // 请求: 带参数的DCM文件 GET /dr/api/v1/pub/dcm/1.2.3.4.5.dcm?contrast=7&detail=5&latitude=5&noise=5 Headers: { Authorization: "Bearer xxx" } Response: - Size: 完整DCM文件 - Content: 后端处理后的DICOM图像 - 用途: 直接用于显示 - 缓存: Cornerstone缓存机制 ``` --- ### 🔄 数据流转详解 #### 16-bit像素数据的转换流程 ``` 1️⃣ 服务器TIF文件 └─ TIFF格式,16-bit灰度图像 └─ 文件大小:约2-4MB(512×512×2) ↓ fetch网络请求 2️⃣ ArrayBuffer(二进制数据) └─ JavaScript二进制缓冲区 └─ 包含完整TIFF文件内容 ↓ parseTIFF解析 3️⃣ TIFImageData对象 { width: 512, height: 512, bitsPerSample: 16, pixelData: Uint16Array(262144), // 512×512个16位整数 photometricInterpretation: 'MONOCHROME2' } ↓ WASM增强算法 4️⃣ 增强后的像素数据 └─ Uint16Array(262144) └─ 应用了新参数的增强结果 └─ 例如:对比度增强、细节提升、噪声抑制 ↓ 创建Cornerstone图像 5️⃣ CornerstoneImage对象 { imageId: "enhanced:1.2.3.4.5_timestamp", width: 512, height: 512, getPixelData: () => enhancedPixels, windowCenter: 32768, windowWidth: 65536, // ... 其他属性 } ↓ Cornerstone渲染管线 6️⃣ GPU渲染 └─ 应用窗宽窗位映射 └─ 转换为8-bit RGB显示 └─ WebGL渲染到Canvas ↓ 7️⃣ 屏幕显示 └─ 用户看到增强后的图像 ✨ ``` --- ### ⚡ 性能优化分析 #### 防抖机制的作用 ```typescript // 场景:用户快速拖动滑块 时间 0ms: 滑块值 5 → 触发,设置300ms定时器A 时间 50ms: 滑块值 6 → 取消A,设置300ms定时器B 时间 100ms: 滑块值 7 → 取消B,设置300ms定时器C 时间 150ms: 滑块值 8 → 取消C,设置300ms定时器D 时间 200ms: 用户停止拖动 时间 500ms: 定时器D触发,仅执行一次WASM处理(参数=8) 优势: ✅ 避免频繁网络请求(TIF下载) ✅ 避免频繁WASM处理(CPU密集) ✅ 最终状态一致(参数=8) ✅ 用户体验流畅(UI立即响应) ``` #### WASM vs 传统模式性能对比 ``` 场景:用户调节参数10次 传统模式: ├─ 防抖: 500ms × 10次 = 不一定(可能合并) ├─ 网络请求: 10次后端DCM处理请求 ├─ 后端处理: 10次图像处理(服务器负载) └─ 总耗时: 较长(网络往返+后端处理) WASM模式: ├─ 防抖: 300ms × 10次 = 不一定(可能合并) ├─ 网络请求: 10次TIF下载(可优化为缓存) ├─ 本地处理: 10次WASM增强(浏览器本地) └─ 总耗时: 较短(本地处理更快) 优化建议: 💡 WASM模式可增加TIF缓存(首次下载后复用) 💡 调参时仅更新SDK参数,不重新下载TIF 💡 进一步缩短防抖时间(如200ms) ``` --- ### 🐛 常见问题排查 #### 问题1:滑块移动但图像不更新 **可能原因**: ```typescript // 检查1:是否为初始加载状态 if (isInitialLoad) { // 初始加载时不会触发预览 console.log('初始加载中,跳过预览') } // 检查2:是否为前端参数 if (['brightness', 'sharpness'].includes(paramName)) { // 前端参数不触发预览 console.log('前端参数,不触发预览') } // 检查3:WASM模式SDK是否就绪 if (isWASMMode && !isSDKReady) { console.error('SDK未就绪,无法预览') } // 检查4:是否有网络错误 // 查看浏览器Network标签 ``` #### 问题2:TIF下载失败 ```typescript // 检查URL是否正确 const expectedUrl = `/dr/api/v1/pub/tif/${sopInstanceUid}-0001.tif` // 检查认证令牌 headers: { 'Authorization': `Bearer ${token}` } // 检查CORS配置 // 服务器需允许跨域请求 // 检查文件是否存在 // 后端日志查看TIF文件路径 ``` #### 问题3:WASM处理很慢 ```typescript // 可能原因: 1. WASM模块未正确加载 → 检查 /static/DRENHANCE.js 是否可访问 2. 参数范围过大导致计算密集 → 优化WASM算法或限制参数范围 3. 图像尺寸过大 → 大图像(如1024×1024)处理时间更长 ``` --- ### 4. 风格切换流程 ```mermaid graph TD A[用户选择风格] --> B[handleStyleChange] B --> C[applyPreset - 应用预设参数] C --> D[更新Redux state] D --> E{处理模式?} E -->|传统模式| F[触发URL预览] E -->|WASM模式| G[触发WASM预览] F --> H[延迟100ms保存参数] G --> H H --> I[saveProcessingParams] I --> J[后端持久化] ``` **风格预设映射**: ```typescript const PROCESSING_PRESETS = { '均衡': { contrast: 5, detail: 5, latitude: 5, noise: 5, brightness: 0, sharpness: 0, }, '高对比': { contrast: 8, detail: 3, latitude: 7, noise: 2, brightness: 0, sharpness: 0, }, '锐组织': { contrast: 6, detail: 8, latitude: 4, noise: 3, brightness: 0, sharpness: 0, }, '骨骼': { contrast: 7, detail: 2, latitude: 8, noise: 1, brightness: 0, sharpness: 0, }, }; ``` --- ### 5. 参数保存流程 #### 5.1 手动保存 ```typescript handleSave() ├─> 提取后端参数 (contrast, detail, latitude, noise) ├─> dispatch(saveProcessingParams) ├─> API调用: POST /api/image-processing-params/{sopInstanceUid} ├─> 后端持久化到数据库 └─> 显示成功消息 ``` #### 5.2 自动保存时机 - ✅ 风格切换后 - ✅ 参数重置后 - ❌ 参数调节中(不自动保存,避免频繁请求) --- ### 6. 重置参数流程 ```typescript handleReset() ├─> dispatch(resetToPreset) │ └─> 恢复当前风格的默认参数 ├─> 显示成功消息 ├─> 延迟100ms保存参数 └─> 持久化到后端 ``` --- ### 7. 双模式对比总结 | 特性 | 传统模式 | WASM模式 | |------|---------|---------| | **数据源** | DCM文件 | TIF原始数据 (16-bit) | | **处理位置** | 后端服务器 | 浏览器本地 (WASM) | | **URL Schema** | `dicomweb:/dr/api/v1/pub/dcm/xxx?params` | `enhanced:sopInstanceUid_timestamp` | | **参数传递** | URL查询参数 | SDK ParameterManager | | **防抖延迟** | 500ms | 300ms (更快) | | **处理参数** | 4个后端参数 | 4个后端参数 + 2个前端参数 | | **图像质量** | 标准 | 高质量 (16-bit增强) | | **网络依赖** | 每次调参需请求 | 仅初始加载TIF | | **适用场景** | 标准工作流 | 高质量增强需求 | --- ### 8. 参数类型说明 #### 8.1 FullProcessingParams 接口 ```typescript interface FullProcessingParams { // 后端参数(会发送到服务器) contrast: number; // 增益 (0-10) detail: number; // 细节 (0-10) latitude: number; // 动态范围 (0-10) noise: number; // 噪声模式 (0-10) // 前端参数(仅本地维护) brightness: number; // 对比度 (-5 to 5) sharpness: number; // 亮度 (-5 to 5) } ``` #### 8.2 参数范围定义 ```typescript const PARAMETER_RANGES = { gain: { min: 0, max: 10, step: 0.1 }, // 增益 detail: { min: 0, max: 10, step: 0.1 }, // 细节 latitude: { min: 0, max: 10, step: 0.1 }, // 动态范围 noise: { min: 0, max: 10, step: 0.1 }, // 噪声模式 brightness: { min: -5, max: 5, step: 0.1 }, // 对比度 sharpness: { min: -5, max: 5, step: 0.1 }, // 亮度 }; ``` --- ### 9. 错误处理 #### 9.1 初始化错误 ```typescript // 图像选择异常 if (dcmUrls.length !== 1) { console.error('没有选中的图像或数量大于1,无法加载参数'); return; // 阻止后续执行 } // SDK初始化失败(WASM模式) if (isWASMMode && sdkError) { // UI显示: SDK错误指示器 // 降级: 可考虑自动切换到传统模式 } ``` #### 9.2 参数加载错误 ```typescript // Redux error state监听 useEffect(() => { if (error) { message.error(error); // 显示错误消息 // 使用默认参数继续工作 } }, [error]); ``` #### 9.3 预览更新错误 ```typescript try { // 更新预览逻辑 } catch (error) { console.error('更新预览图像失败:', error); message.error('更新预览图像失败'); // 不阻止用户继续操作 } ``` --- ### 10. 性能优化要点 #### 10.1 防抖机制 - **传统模式**: 500ms 防抖,减少后端请求 - **WASM模式**: 300ms 防抖,本地处理更快响应 #### 10.2 初始加载优化 ```typescript const isInitialLoad = useAppSelector(selectIsInitialLoad); // 初始加载时不触发预览,避免不必要的渲染 if (isInitialLoad) { return; // 跳过预览 } ``` #### 10.3 定时器清理 ```typescript useEffect(() => { return () => { // 组件卸载时清理定时器 if (saveTimerRef.current) { clearTimeout(saveTimerRef.current); } }; }, []); ``` --- ### 11. 模式切换时机 用户在**系统设置 > 首选项 > 高级处理模式**中配置处理模式后: 1. 配置保存到后端数据库 2. Redux state更新 3. **需要重新进入SliderAdjustmentPanel才生效** 4. 面板根据新配置初始化对应模式 --- ### 12. 未来扩展点 #### 12.1 模式自动降级 ```typescript // WASM模式初始化失败时自动降级到传统模式 if (isWASMMode && sdkError) { console.warn('WASM模式初始化失败,降级到传统模式'); dispatch(updateProcessingMode('traditional')); } ``` #### 12.2 参数预设模板 支持用户自定义参数预设,保存常用的参数组合。 #### 12.3 实时性能监控 - WASM处理耗时 - 网络请求耗时 - 渲染性能指标 --- ## 📊 状态流转图 ```mermaid stateDiagram-v2 [*] --> Initializing: 组件挂载 Initializing --> LoadingConfig: 读取处理模式 LoadingConfig --> InitTraditional: 传统模式 LoadingConfig --> InitWASM: WASM模式 InitTraditional --> LoadingParams: 初始化完成 InitWASM --> LoadingParams: SDK就绪 LoadingParams --> Ready: 参数加载完成 Ready --> Adjusting: 用户调参 Adjusting --> Previewing: 防抖触发 Previewing --> Ready: 预览完成 Ready --> Saving: 保存参数 Saving --> Ready: 保存完成 Ready --> [*]: 返回上级 ``` --- ## 🔧 关键代码片段 ### 防抖预览核心逻辑 ```typescript const debouncedPreview = useCallback( (params: FullProcessingParams) => { if (isInitialLoad) return; clearTimeout(saveTimerRef.current); saveTimerRef.current = setTimeout(() => { if (!currentImageId) return; try { const dcmUrls = store.getState().viewerContainer.selectedViewers; if (dcmUrls.length !== 1) return; const processedUrl = buildProcessedDcmUrl(currentImageId, { contrast: params.contrast.toString(), detail: params.detail.toString(), latitude: params.latitude.toString(), noise: params.noise.toString(), }); dispatch(updateViewerUrl({ originalUrl: dcmUrls[0], newUrl: `dicomweb:${processedUrl}`, })); } catch (error) { message.error('更新预览图像失败'); } }, 500); }, [currentImageId, isInitialLoad, dispatch] ); ``` --- ## 📝 总结 SliderAdjustmentPanel通过配置驱动的方式支持双处理模式: - **传统模式**:稳定可靠,适合标准工作流 - **WASM模式**:高质量增强,适合专业场景 两种模式在用户体验上保持一致,底层处理逻辑根据配置自动切换,实现了灵活性和可维护性的平衡。 --- **文档版本**: 1.0 **创建日期**: 2025-11-30 **最后更新**: 2025-11-30