|
@@ -10,6 +10,8 @@ import { annotationAPI } from '../../../API/annotation';
|
|
|
import { extractSopInstanceUid } from '../../../utils/dicomUtils';
|
|
import { extractSopInstanceUid } from '../../../utils/dicomUtils';
|
|
|
import type { AnnotationData, AnnotationEventType } from '../types/annotation';
|
|
import type { AnnotationData, AnnotationEventType } from '../types/annotation';
|
|
|
import { IRenderingEngine, IStackViewport } from '@cornerstonejs/core/dist/esm/types';
|
|
import { IRenderingEngine, IStackViewport } from '@cornerstonejs/core/dist/esm/types';
|
|
|
|
|
+import * as cornerstoneTools from '@cornerstonejs/tools';
|
|
|
|
|
+import { getIpPort } from '../../../API/config';
|
|
|
|
|
|
|
|
export class AnnotationManager {
|
|
export class AnnotationManager {
|
|
|
private eventListenersRegistered: boolean = false;
|
|
private eventListenersRegistered: boolean = false;
|
|
@@ -397,7 +399,7 @@ export class AnnotationManager {
|
|
|
private findElementsByFOR(imageId: string): any[] {
|
|
private findElementsByFOR(imageId: string): any[] {
|
|
|
const elements: any[] = [];
|
|
const elements: any[] = [];
|
|
|
const renderingEngines = getRenderingEngines();
|
|
const renderingEngines = getRenderingEngines();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (renderingEngines) {
|
|
if (renderingEngines) {
|
|
|
renderingEngines.forEach((re: IRenderingEngine) => {
|
|
renderingEngines.forEach((re: IRenderingEngine) => {
|
|
|
re.getViewports().forEach((vp: IStackViewport) => {
|
|
re.getViewports().forEach((vp: IStackViewport) => {
|
|
@@ -416,13 +418,56 @@ export class AnnotationManager {
|
|
|
return elements;
|
|
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> {
|
|
private async renderAnnotations(annotationStrings: string[]): Promise<void> {
|
|
|
console.log(`【annotationmanager】🎨 渲染 ${annotationStrings.length} 个注释`);
|
|
console.log(`【annotationmanager】🎨 渲染 ${annotationStrings.length} 个注释`);
|
|
|
|
|
|
|
|
for (const annotationString of annotationStrings) {
|
|
for (const annotationString of annotationStrings) {
|
|
|
try {
|
|
try {
|
|
|
// 反序列化为Cornerstone格式
|
|
// 反序列化为Cornerstone格式
|
|
|
- const deserializedAnnotation = this.serializer.deserialize(annotationString);
|
|
|
|
|
|
|
+ let deserializedAnnotation = this.serializer.deserialize(annotationString);
|
|
|
|
|
+
|
|
|
|
|
+ // 更新注释中的 URL,替换为当前服务器地址
|
|
|
|
|
+ deserializedAnnotation = this.updateAnnotationUrls(deserializedAnnotation);
|
|
|
|
|
|
|
|
// 1. 从注释元数据中获取图像ID
|
|
// 1. 从注释元数据中获取图像ID
|
|
|
const imageId = deserializedAnnotation.metadata?.referencedImageId;
|
|
const imageId = deserializedAnnotation.metadata?.referencedImageId;
|
|
@@ -456,7 +501,7 @@ export class AnnotationManager {
|
|
|
console.warn('【annotationmanager】未找到对应的 viewport,跳过');
|
|
console.warn('【annotationmanager】未找到对应的 viewport,跳过');
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ console.log(`【annotationmanager】渲染注释 ${JSON.stringify(deserializedAnnotation)} 到 imageid ${imageId} 的 viewport`);
|
|
|
// 3. ✅ 使用正确的 element 参数添加注释
|
|
// 3. ✅ 使用正确的 element 参数添加注释
|
|
|
corAnnotation.state.addAnnotation(deserializedAnnotation, targetElement);
|
|
corAnnotation.state.addAnnotation(deserializedAnnotation, targetElement);
|
|
|
|
|
|