SliderAdjustmentPanel 组件的完整处理流程文档
本文档描述了滑动参数调节面板(SliderAdjustmentPanel)的完整处理流程,包括传统模式和WASM模式的双模式支持。
滑动参数调节面板是三级面板,用于调整图像处理参数,支持:
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]
// 从系统设置Redux store读取
const processingMode = useAppSelector(selectProcessingMode);
const isWASMMode = processingMode === 'wasm';
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]);
// Redux Thunk 异步操作
loadImageProcessingParams(sopInstanceUid)
├─> 调用 API: getImageProcessingParams(sopInstanceUid)
├─> 返回参数: { contrast, detail, latitude, noise }
└─> 更新 Redux state
├─> parameters (合并前端参数 brightness, sharpness)
├─> currentImageId
└─> isInitialLoad = true (防止触发自动预览)
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重新渲染]
// 传统模式:构建带参数的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
| 参数名称 | 参数类型 | 处理方式 |
|---|---|---|
| contrast (增益) | 后端参数 | URL传递,后端处理 |
| detail (细节) | 后端参数 | URL传递,后端处理 |
| latitude (动态范围) | 后端参数 | URL传递,后端处理 |
| noise (噪声模式) | 后端参数 | URL传递,后端处理 |
| brightness (对比度) | 前端参数 | 仅UI更新,不触发预览 |
| sharpness (亮度) | 前端参数 | 仅UI更新,不触发预览 |
// 使用自定义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实例
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渲染]
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重新渲染图像
时间点 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(后端处理)
// 📍 Level 1: 用户交互层
<ParameterSlider onChange={(value) => 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<CornerstoneImage> {
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<TIFImageData> {
// 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<CornerstoneImage> {
// 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<Uint16Array> {
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
// → 屏幕显示更新 ✨
// 请求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增强
- 缓存: 无(每次重新获取以应用新参数)
// 请求: 带参数的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缓存机制
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️⃣ 屏幕显示
└─ 用户看到增强后的图像 ✨
// 场景:用户快速拖动滑块
时间 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立即响应)
场景:用户调节参数10次
传统模式:
├─ 防抖: 500ms × 10次 = 不一定(可能合并)
├─ 网络请求: 10次后端DCM处理请求
├─ 后端处理: 10次图像处理(服务器负载)
└─ 总耗时: 较长(网络往返+后端处理)
WASM模式:
├─ 防抖: 300ms × 10次 = 不一定(可能合并)
├─ 网络请求: 10次TIF下载(可优化为缓存)
├─ 本地处理: 10次WASM增强(浏览器本地)
└─ 总耗时: 较短(本地处理更快)
优化建议:
💡 WASM模式可增加TIF缓存(首次下载后复用)
💡 调参时仅更新SDK参数,不重新下载TIF
💡 进一步缩短防抖时间(如200ms)
可能原因:
// 检查1:是否为初始加载状态
if (isInitialLoad) {
// 初始加载时不会触发预览
console.log('初始加载中,跳过预览')
}
// 检查2:是否为前端参数
if (['brightness', 'sharpness'].includes(paramName)) {
// 前端参数不触发预览
console.log('前端参数,不触发预览')
}
// 检查3:WASM模式SDK是否就绪
if (isWASMMode && !isSDKReady) {
console.error('SDK未就绪,无法预览')
}
// 检查4:是否有网络错误
// 查看浏览器Network标签
// 检查URL是否正确
const expectedUrl = `/dr/api/v1/pub/tif/${sopInstanceUid}-0001.tif`
// 检查认证令牌
headers: {
'Authorization': `Bearer ${token}`
}
// 检查CORS配置
// 服务器需允许跨域请求
// 检查文件是否存在
// 后端日志查看TIF文件路径
// 可能原因:
1. WASM模块未正确加载
→ 检查 /static/DRENHANCE.js 是否可访问
2. 参数范围过大导致计算密集
→ 优化WASM算法或限制参数范围
3. 图像尺寸过大
→ 大图像(如1024×1024)处理时间更长
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[后端持久化]
风格预设映射:
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,
},
};
handleSave()
├─> 提取后端参数 (contrast, detail, latitude, noise)
├─> dispatch(saveProcessingParams)
├─> API调用: POST /api/image-processing-params/{sopInstanceUid}
├─> 后端持久化到数据库
└─> 显示成功消息
handleReset()
├─> dispatch(resetToPreset)
│ └─> 恢复当前风格的默认参数
├─> 显示成功消息
├─> 延迟100ms保存参数
└─> 持久化到后端
| 特性 | 传统模式 | 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 |
| 适用场景 | 标准工作流 | 高质量增强需求 |
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)
}
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 }, // 亮度
};
// 图像选择异常
if (dcmUrls.length !== 1) {
console.error('没有选中的图像或数量大于1,无法加载参数');
return; // 阻止后续执行
}
// SDK初始化失败(WASM模式)
if (isWASMMode && sdkError) {
// UI显示: SDK错误指示器
// 降级: 可考虑自动切换到传统模式
}
// Redux error state监听
useEffect(() => {
if (error) {
message.error(error); // 显示错误消息
// 使用默认参数继续工作
}
}, [error]);
try {
// 更新预览逻辑
} catch (error) {
console.error('更新预览图像失败:', error);
message.error('更新预览图像失败');
// 不阻止用户继续操作
}
const isInitialLoad = useAppSelector(selectIsInitialLoad);
// 初始加载时不触发预览,避免不必要的渲染
if (isInitialLoad) {
return; // 跳过预览
}
useEffect(() => {
return () => {
// 组件卸载时清理定时器
if (saveTimerRef.current) {
clearTimeout(saveTimerRef.current);
}
};
}, []);
用户在系统设置 > 首选项 > 高级处理模式中配置处理模式后:
// WASM模式初始化失败时自动降级到传统模式
if (isWASMMode && sdkError) {
console.warn('WASM模式初始化失败,降级到传统模式');
dispatch(updateProcessingMode('traditional'));
}
支持用户自定义参数预设,保存常用的参数组合。
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 --> [*]: 返回上级
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通过配置驱动的方式支持双处理模式:
两种模式在用户体验上保持一致,底层处理逻辑根据配置自动切换,实现了灵活性和可维护性的平衡。
文档版本: 1.0
创建日期: 2025-11-30
最后更新: 2025-11-30