Explorar o código

fix: 修复注释跨环境渲染问题

- 新增 updateAnnotationUrls 方法,自动更新注释对象中的服务器地址
- 修复浏览器端保存的注释数据在桌面端(Electron)无法渲染的问题
- 在渲染注释时自动替换 referencedImageId 和 referencedImageURI 中的服务器地址
- 使用正则表达式匹配并替换 URL 中的协议+域名/IP+端口部分
- 新增服务器地址获取失败的容错处理和日志记录

改动文件:
- src/features/imageAnnotation/services/AnnotationManager.ts
- CHANGELOG.md
- package.json (版本更新: 1.10.1 -> 1.10.2)
dengdx hai 4 semanas
pai
achega
8b4fe688ea
Modificáronse 4 ficheiros con 79 adicións e 6 borrados
  1. 28 0
      CHANGELOG.md
  2. 2 2
      package-lock.json
  3. 1 1
      package.json
  4. 48 3
      src/features/imageAnnotation/services/AnnotationManager.ts

+ 28 - 0
CHANGELOG.md

@@ -5,6 +5,34 @@
 格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
 版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
 
+## [1.10.2] - 2025-12-16 15:01
+
+### 修复 (Fixed)
+- **注释跨环境渲染问题** ([src/features/imageAnnotation/services/AnnotationManager.ts](src/features/imageAnnotation/services/AnnotationManager.ts))
+  - 新增 `updateAnnotationUrls` 方法,自动更新注释对象中的服务器地址
+  - 修复浏览器端保存的注释数据在桌面端(Electron)无法渲染的问题
+  - 在渲染注释时自动替换 referencedImageId 和 referencedImageURI 中的服务器地址
+  - 使用正则表达式匹配并替换 URL 中的协议+域名/IP+端口部分
+  - 新增服务器地址获取失败的容错处理和日志记录
+
+**核心改进:**
+- 跨环境兼容性:注释数据可以在不同服务器环境之间正确渲染
+- 自动 URL 更新:无需手动修改注释数据中的服务器地址
+- 容错处理:服务器地址获取失败时跳过更新,不影响渲染流程
+- 完整日志:记录 URL 更新前后的详细信息,便于调试
+
+**技术实现:**
+- 使用 `getIpPort()` 获取当前服务器地址
+- 正则表达式 `/(https?:\/\/[^\/]+)/` 匹配 URL 中的服务器部分
+- 更新 metadata.referencedImageId 和 metadata.referencedImageURI
+- 在 renderAnnotations 中调用 updateAnnotationUrls 处理每个注释
+
+**改动文件:**
+- src/features/imageAnnotation/services/AnnotationManager.ts
+- package.json (版本更新: 1.10.1 -> 1.10.2)
+
+---
+
 ## [1.10.1] - 2025-12-16 13:04
 
 ### 修复 (Fixed)

+ 2 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "zsis",
-  "version": "1.2.7",
+  "version": "1.10.2",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "zsis",
-      "version": "1.2.7",
+      "version": "1.10.2",
       "dependencies": {
         "@babel/runtime": "^7.24.4",
         "@cornerstonejs/core": "^3.28.0",

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "zsis",
-  "version": "1.10.1",
+  "version": "1.10.2",
   "private": true,
   "description": "医学成像系统",
   "main": "main.js",

+ 48 - 3
src/features/imageAnnotation/services/AnnotationManager.ts

@@ -10,6 +10,8 @@ import { annotationAPI } from '../../../API/annotation';
 import { extractSopInstanceUid } from '../../../utils/dicomUtils';
 import type { AnnotationData, AnnotationEventType } from '../types/annotation';
 import { IRenderingEngine, IStackViewport } from '@cornerstonejs/core/dist/esm/types';
+import * as cornerstoneTools from '@cornerstonejs/tools';
+import { getIpPort } from '../../../API/config';
 
 export class AnnotationManager {
   private eventListenersRegistered: boolean = false;
@@ -397,7 +399,7 @@ export class AnnotationManager {
   private findElementsByFOR(imageId: string): any[] {
     const elements: any[] = [];
     const renderingEngines = getRenderingEngines();
-    
+
     if (renderingEngines) {
       renderingEngines.forEach((re: IRenderingEngine) => {
         re.getViewports().forEach((vp: IStackViewport) => {
@@ -416,13 +418,56 @@ export class AnnotationManager {
     return elements;
   }
 
+  /**
+   * 更新注释对象中的 URL,替换为当前服务器地址
+   * @param annotation 注释对象
+   * @returns 更新后的注释对象
+   */
+  private updateAnnotationUrls(annotation: any): any {
+    try {
+      const currentIpPort = getIpPort();
+      if (!currentIpPort) {
+        console.warn('【annotationmanager】无法获取当前服务器地址,跳过 URL 更新');
+        return annotation;
+      }
+
+      // 正则表达式:匹配 URL 中的协议+域名/IP+端口部分
+      // 例如:dicomweb:http://192.168.110.245:6001/path -> 提取 http://192.168.110.245:6001
+      const urlRegex = /(https?:\/\/[^\/]+)/;
+
+      // 更新 metadata.referencedImageId
+      if (annotation.metadata?.referencedImageId) {
+        const originalUrl = annotation.metadata.referencedImageId;
+        const updatedUrl = originalUrl.replace(urlRegex, currentIpPort);
+        annotation.metadata.referencedImageId = updatedUrl;
+        console.log(`【annotationmanager】已更新 referencedImageId: ${originalUrl} -> ${updatedUrl}`);
+      }
+
+      // 更新 metadata.referencedImageURI(如果存在)
+      if (annotation.metadata?.referencedImageURI) {
+        const originalUrl = annotation.metadata.referencedImageURI;
+        const updatedUrl = originalUrl.replace(urlRegex, currentIpPort);
+        annotation.metadata.referencedImageURI = updatedUrl;
+        console.log(`【annotationmanager】已更新 referencedImageURI: ${originalUrl} -> ${updatedUrl}`);
+      }
+
+      return annotation;
+    } catch (error) {
+      console.error('【annotationmanager】更新注释 URL 失败:', error);
+      return annotation;
+    }
+  }
+
   private async renderAnnotations(annotationStrings: string[]): Promise<void> {
     console.log(`【annotationmanager】🎨 渲染 ${annotationStrings.length} 个注释`);
 
     for (const annotationString of annotationStrings) {
       try {
         // 反序列化为Cornerstone格式
-        const deserializedAnnotation = this.serializer.deserialize(annotationString);
+        let deserializedAnnotation = this.serializer.deserialize(annotationString);
+
+        // 更新注释中的 URL,替换为当前服务器地址
+        deserializedAnnotation = this.updateAnnotationUrls(deserializedAnnotation);
 
         // 1. 从注释元数据中获取图像ID
         const imageId = deserializedAnnotation.metadata?.referencedImageId;
@@ -456,7 +501,7 @@ export class AnnotationManager {
           console.warn('【annotationmanager】未找到对应的 viewport,跳过');
           continue;
         }
-
+        console.log(`【annotationmanager】渲染注释 ${JSON.stringify(deserializedAnnotation)} 到 imageid ${imageId} 的 viewport`);
         // 3. ✅ 使用正确的 element 参数添加注释
         corAnnotation.state.addAnnotation(deserializedAnnotation, targetElement);