hejianhao
2026-04-02 0940d56748a73525790c350c393a5be960aab62c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
import { ref, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
 
/**
 * Canvas管理器 - 解决初始化竞态条件
 */
export function useCanvasManager() {
  // 初始化Promise,用于处理并发初始化请求
  const initializePromise = ref(null);
  
  // Canvas相关引用
  const canvasRef = ref(null);
  const imageRef = ref(null);
  const imageContainerRef = ref(null);
  
  // 标注绘制器实例
  let annotationDrawer = null;
  
  /**
   * 设置标注绘制器
   */
  const setAnnotationDrawer = (drawer) => {
    annotationDrawer = drawer;
  };
  
  /**
   * 初始化Canvas(带并发控制)
   */
  const initializeCanvas = async (refs, settings) => {
    // 如果正在初始化,返回现有的Promise
    if (initializePromise.value) {
      console.log('[CanvasManager] Canvas正在初始化,等待完成...');
      return initializePromise.value;
    }
    
    // 创建新的初始化Promise
    initializePromise.value = new Promise(async (resolve, reject) => {
      try {
        console.log('[CanvasManager] 开始初始化Canvas...');
        
        // 验证必要的引用
        const { canvas, image, container } = refs;
        if (!canvas || !image || !container) {
          throw new Error('Canvas初始化失败:缺少必要的DOM引用');
        }
        
        // 保存引用
        canvasRef.value = canvas;
        imageRef.value = image;
        imageContainerRef.value = container;
        
        // 确保DOM已更新
        await nextTick();
        
        // 初始化标注绘制器
        if (!annotationDrawer) {
          throw new Error('Canvas初始化失败:标注绘制器未设置');
        }
        
        annotationDrawer.initialize(canvas, image, container);
        
        // 应用初始设置
        if (settings) {
          console.log('[CanvasManager] 应用初始设置:', settings);
          
          // 批量应用设置,减少重绘次数
          annotationDrawer.initializeSettings({
            lineWidth: settings.lineWidth || 2,
            mode: settings.mode || null, // 不设置默认模式,由页面初始化时设置
            annotationList: settings.annotations || [],
            highlightedIds: settings.highlightedIds || [],
            currentCategory: settings.currentCategory || null
          });
        }
        
        console.log('[CanvasManager] Canvas初始化成功');
        resolve(true);
      } catch (error) {
        console.error('[CanvasManager] Canvas初始化失败:', error);
        reject(error);
      } finally {
        // 清除Promise引用,允许下次初始化
        setTimeout(() => {
          initializePromise.value = null;
        }, 100);
      }
    });
    
    return initializePromise.value;
  };
  
  /**
   * 销毁Canvas
   */
  const destroyCanvas = () => {
    if (annotationDrawer && typeof annotationDrawer.destroy === 'function') {
      annotationDrawer.destroy();
    }
    
    canvasRef.value = null;
    imageRef.value = null;
    imageContainerRef.value = null;
    initializePromise.value = null;
    
    console.log('[CanvasManager] Canvas已销毁');
  };
  
  /**
   * 清除Canvas内容
   */
  const clearCanvas = () => {
    if (annotationDrawer && typeof annotationDrawer.clearAllAnnotations === 'function') {
      annotationDrawer.clearAllAnnotations();
    }
  };
  
  /**
   * 更新Canvas设置
   */
  const updateCanvasSettings = (settings) => {
    if (!annotationDrawer) {
      console.warn('[CanvasManager] 无法更新设置:标注绘制器未初始化');
      return;
    }
    
    // 分别更新各项设置,避免不必要的重绘
    if (settings.lineWidth !== undefined) {
      annotationDrawer.setLineWidth(settings.lineWidth);
    }
    
    if (settings.mode !== undefined) {
      annotationDrawer.setAnnotationMode(settings.mode);
    }
    
    if (settings.highlightedIds !== undefined) {
      annotationDrawer.setHighlightedAnnotations(settings.highlightedIds);
    }
    
    if (settings.currentCategory !== undefined) {
      annotationDrawer.setCurrentCategory(settings.currentCategory);
    }
  };
  
  /**
   * 批量更新标注(差量更新)
   */
  const updateAnnotations = (changes) => {
    if (!annotationDrawer) {
      console.warn('[CanvasManager] 无法更新标注:标注绘制器未初始化');
      return;
    }
    
    console.log('[CanvasManager] 执行差量更新:', {
      added: changes.added?.length || 0,
      removed: changes.removed?.length || 0,
      updated: changes.updated?.length || 0
    });
    
    // 添加新标注
    changes.added?.forEach(annotation => {
      annotationDrawer.addAnnotation(annotation);
    });
    
    // 删除标注
    changes.removed?.forEach(annotationId => {
      annotationDrawer.removeAnnotation(annotationId);
    });
    
    // 更新标注
    changes.updated?.forEach(annotation => {
      annotationDrawer.updateAnnotation(annotation);
    });
  };
  
  /**
   * 渲染所有标注(全量更新)
   */
  const renderAllAnnotations = (annotations) => {
    if (!annotationDrawer) {
      console.warn('[CanvasManager] 无法渲染标注:标注绘制器未初始化');
      return;
    }
    
    clearCanvas();
    annotationDrawer.renderExistingAnnotations(annotations);
  };
  
  /**
   * 更新覆盖层位置(缩放时调用)
   */
  const updateOverlayPosition = () => {
    if (annotationDrawer && typeof annotationDrawer.updateOverlayPosition === 'function') {
      annotationDrawer.updateOverlayPosition();
    }
  };
  
  /**
   * 设置标注完成回调
   */
  const setAnnotationCompleteCallback = (callback) => {
    if (annotationDrawer) {
      annotationDrawer.setOnAnnotationComplete(callback);
    }
  };
  
  return {
    // 引用
    canvasRef,
    imageRef,
    imageContainerRef,
    
    // 方法
    setAnnotationDrawer,
    initializeCanvas,
    destroyCanvas,
    clearCanvas,
    updateCanvasSettings,
    updateAnnotations,
    renderAllAnnotations,
    updateOverlayPosition,
    setAnnotationCompleteCallback,
    
    // 获取绘制器实例(调试用)
    getDrawer: () => annotationDrawer
  };
}