|
|
@@ -1,14 +1,15 @@
|
|
|
// src/features/imageAnnotation/services/AnnotationManager.ts
|
|
|
// 全局注释管理器 - 负责监听Cornerstone事件并管理注释的保存/加载
|
|
|
|
|
|
-import { eventTarget } from '@cornerstonejs/core';
|
|
|
+import { eventTarget, getRenderingEngines } from '@cornerstonejs/core';
|
|
|
import { EVENTS } from '@cornerstonejs/core';
|
|
|
-import { annotation, Enums } from '@cornerstonejs/tools';
|
|
|
+import { annotation as corAnnotation, Enums } from '@cornerstonejs/tools';
|
|
|
import { AnnotationSerializer } from './AnnotationSerializer';
|
|
|
import { AnnotationValidator } from './AnnotationValidator';
|
|
|
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';
|
|
|
|
|
|
export class AnnotationManager {
|
|
|
private eventListenersRegistered: boolean = false;
|
|
|
@@ -222,7 +223,8 @@ export class AnnotationManager {
|
|
|
console.log('🎯 监听到注释删除事件:', evt);
|
|
|
console.log('📋 事件详情:', evt.detail);
|
|
|
|
|
|
- const { annotationUID } = evt.detail;
|
|
|
+ const { annotation } = evt.detail;
|
|
|
+ const annotationUID = annotation.annotationUID;
|
|
|
console.log(`【annotationmanager】🗑️ 注释删除完成: ${annotationUID}`);
|
|
|
|
|
|
// 确保有活动的图像ID
|
|
|
@@ -232,7 +234,7 @@ export class AnnotationManager {
|
|
|
}
|
|
|
|
|
|
// 实现注释删除逻辑
|
|
|
- this.deleteAnnotation(annotationUID);
|
|
|
+ this.deleteAnnotation(annotation);
|
|
|
};
|
|
|
|
|
|
// ============ 注释操作方法 ============
|
|
|
@@ -305,8 +307,9 @@ export class AnnotationManager {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private async deleteAnnotation(annotationUID: string): Promise<void> {
|
|
|
+ private async deleteAnnotation(annotation: any): Promise<void> {
|
|
|
try {
|
|
|
+ const annotationUID = annotation.annotationUID;
|
|
|
console.log(`【annotationmanager】🗑️ 删除注释: ${annotationUID}`);
|
|
|
|
|
|
if (!this.activeImageId) {
|
|
|
@@ -314,15 +317,66 @@ export class AnnotationManager {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 调用API删除注释
|
|
|
- await annotationAPI.deleteAnnotations(this.activeImageId, annotationUID);
|
|
|
+ // 从 annotation 中获取 FrameOfReferenceUID
|
|
|
+ const forUID = annotation.metadata?.referencedImageId;
|
|
|
+
|
|
|
+ if (!forUID) {
|
|
|
+ console.warn('【annotationmanager】FrameOfReferenceUID 未找到,跳过删除操作');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 用 FrameOfReferenceUID 查找相关的 elements
|
|
|
+ const elements = this.findElementsByFOR(forUID);
|
|
|
+
|
|
|
+ // 收集删除后的所有注释
|
|
|
+ const allAnnotationStrings: string[] = [];
|
|
|
+
|
|
|
+ elements.forEach(element => {
|
|
|
+ const anns = corAnnotation.state.getAnnotations('', element);
|
|
|
+
|
|
|
+ if (anns) {
|
|
|
+ // 序列化所有注释
|
|
|
+ for (const [toolName, ann] of Object.entries(anns as any)) {
|
|
|
+ try {
|
|
|
+ const serialized = this.serializer.serialize(ann, toolName);
|
|
|
+ allAnnotationStrings.push(serialized);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('序列化注释失败:', error);
|
|
|
+ // 跳过序列化失败的注释
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 保存所有注释
|
|
|
+ await annotationAPI.saveAnnotations(this.activeImageId, allAnnotationStrings);
|
|
|
|
|
|
- console.log(`【annotationmanager】✅ 注释删除完成: ${annotationUID}`);
|
|
|
+ console.log(`【annotationmanager】✅ 注释删除完成: ${annotationUID} (剩余 ${allAnnotationStrings.length} 个注释)`);
|
|
|
} catch (error) {
|
|
|
- console.error(`【annotationmanager】❌ 注释删除失败 ${annotationUID}:`, error);
|
|
|
+ console.error(`【annotationmanager】❌ 注释删除失败:`, error);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 用 FrameOfReferenceUID 查找 viewport elements
|
|
|
+ private findElementsByFOR(imageId: string): any[] {
|
|
|
+ const elements: any[] = [];
|
|
|
+ if (!!getRenderingEngines) {
|
|
|
+ const renderingEngines = getRenderingEngines();
|
|
|
+ renderingEngines?.forEach((re: IRenderingEngine) => {
|
|
|
+ re.getViewports().forEach((vp: IStackViewport) => {
|
|
|
+ if (vp && vp.hasImageId(imageId) === true && vp.element) {
|
|
|
+ elements.push(vp.element);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ console.warn('【annotationmanager】getRenderingEngines 方法不可用,无法查找元素');
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return elements;
|
|
|
+ }
|
|
|
+
|
|
|
private async renderAnnotations(annotationStrings: string[]): Promise<void> {
|
|
|
console.log(`【annotationmanager】🎨 渲染 ${annotationStrings.length} 个注释`);
|
|
|
|
|
|
@@ -332,7 +386,7 @@ export class AnnotationManager {
|
|
|
const deserializedAnnotation = this.serializer.deserialize(annotationString);
|
|
|
|
|
|
// 添加到Cornerstone注释状态
|
|
|
- annotation.state.addAnnotation(deserializedAnnotation, deserializedAnnotation.metadata?.toolName || 'UnknownTool');
|
|
|
+ corAnnotation.state.addAnnotation(deserializedAnnotation, deserializedAnnotation.metadata?.toolName || 'UnknownTool');
|
|
|
|
|
|
console.log(`【annotationmanager】✅ 注释渲染成功`);
|
|
|
} catch (error) {
|