@@ -12,8 +12,6 @@ class PopupManager {
1212 // 保存当前活动弹窗及其信息
1313 static activePopup = null ;
1414 static activePopupInfo = null ;
15- static isDragging = false ;
16- static dragOffset = { x : 0 , y : 0 } ;
1715 static eventHandlers = {
1816 mousedown : null ,
1917 keydown : null ,
@@ -90,7 +88,10 @@ class PopupManager {
9088 preventCloseOnElementTypes
9189 } ;
9290
93-
91+ // 如果启用窗口大小调节,提前设置,因为它会修改DOM
92+ if ( enableResize ) {
93+ this . setupResizeEvents ( popup ) ;
94+ }
9495
9596 // 计算弹窗位置
9697 this . positionPopup ( popup , anchorButton ) ;
@@ -106,11 +107,6 @@ class PopupManager {
106107 // 设置拖动事件
107108 this . setupDragEvents ( popup ) ;
108109
109- // 如果启用窗口大小调节,设置调节事件
110- if ( enableResize ) {
111- this . setupResizeEvents ( popup ) ;
112- }
113-
114110 // 返回弹窗元素
115111 return popup ;
116112 }
@@ -145,10 +141,6 @@ class PopupManager {
145141 logger . error ( `执行弹窗清理函数失败: ${ error . message } ` ) ;
146142 }
147143 }
148-
149- // 清理拖动相关状态
150- this . isDragging = false ;
151- this . dragOffset = { x : 0 , y : 0 } ;
152144 }
153145
154146 /**
@@ -161,6 +153,10 @@ class PopupManager {
161153 // 设置鼠标样式,表示可拖动
162154 titleBar . style . cursor = 'move' ;
163155
156+ // 拖动相关变量
157+ let isDragging = false ;
158+ let dragOffset = { x : 0 , y : 0 } ;
159+
164160 const handleMouseDown = ( e ) => {
165161 // 如果点击的是按钮、输入框或调节手柄,不启动拖动
166162 if ( e . target . closest ( '.popup_btn' ) ||
@@ -174,37 +170,43 @@ class PopupManager {
174170 // 如果点击的是标题栏或标题文本,允许拖动
175171 if ( e . target . closest ( '.popup_title' ) || e . target === titleBar || e . target . closest ( '.popup_search_container' ) ) {
176172 e . preventDefault ( ) ;
177- this . isDragging = true ;
173+ isDragging = true ;
178174
179175 // 添加拖动状态类
180176 popup . classList . add ( 'dragging' ) ;
181177 titleBar . classList . add ( 'dragging' ) ;
182178
183179 // 计算鼠标点击位置与弹窗左上角的偏移
180+ // 使用强制回流确保获取准确的位置信息
181+ void popup . offsetWidth ; // 强制回流
184182 const rect = popup . getBoundingClientRect ( ) ;
185- this . dragOffset = {
183+ dragOffset = {
186184 x : e . clientX - rect . left ,
187185 y : e . clientY - rect . top
188186 } ;
189187
190188 // 添加拖动时的样式
191189 popup . style . transition = 'none' ;
192190 titleBar . style . cursor = 'grabbing' ;
191+
192+ // 添加临时的全局事件监听器
193+ document . addEventListener ( 'mousemove' , handleMouseMove , { passive : false } ) ;
194+ document . addEventListener ( 'mouseup' , handleMouseUp , { once : true } ) ;
193195 }
194196 } ;
195197
196198 const handleMouseMove = ( e ) => {
197- if ( ! this . isDragging ) return ;
199+ if ( ! isDragging ) return ;
198200
199201 e . preventDefault ( ) ;
200202
201203 // 计算新位置,确保不超出视窗边界
202204 const newLeft = Math . max ( 0 , Math . min (
203- e . clientX - this . dragOffset . x ,
205+ e . clientX - dragOffset . x ,
204206 window . innerWidth - popup . offsetWidth
205207 ) ) ;
206208 const newTop = Math . max ( 0 , Math . min (
207- e . clientY - this . dragOffset . y ,
209+ e . clientY - dragOffset . y ,
208210 window . innerHeight - popup . offsetHeight
209211 ) ) ;
210212
@@ -214,31 +216,46 @@ class PopupManager {
214216 } ;
215217
216218 const handleMouseUp = ( ) => {
217- if ( ! this . isDragging ) return ;
219+ if ( ! isDragging ) return ;
218220
219- this . isDragging = false ;
221+ isDragging = false ;
220222
221223 // 移除拖动状态类
222224 popup . classList . remove ( 'dragging' ) ;
223225 titleBar . classList . remove ( 'dragging' ) ;
224226
225227 titleBar . style . cursor = 'move' ;
226228 popup . style . transition = '' ; // 恢复过渡效果
229+
230+ // 移除临时的事件监听器
231+ document . removeEventListener ( 'mousemove' , handleMouseMove ) ;
232+ document . removeEventListener ( 'mouseup' , handleMouseUp ) ;
227233 } ;
228234
229- // 添加事件监听
235+ // 只添加初始的mousedown事件监听
230236 titleBar . addEventListener ( 'mousedown' , handleMouseDown ) ;
231- document . addEventListener ( 'mousemove' , handleMouseMove ) ;
232- document . addEventListener ( 'mouseup' , handleMouseUp ) ;
233237
234- // 保存清理函数
235- const originalCleanup = popup . _cleanup || ( ( ) => { } ) ;
236- popup . _cleanup = ( ) => {
237- originalCleanup ( ) ;
238+ // 改进清理函数的保存方式,避免覆盖
239+ if ( ! popup . _cleanupFunctions ) {
240+ popup . _cleanupFunctions = [ ] ;
241+ }
242+
243+ popup . _cleanupFunctions . push ( ( ) => {
238244 titleBar . removeEventListener ( 'mousedown' , handleMouseDown ) ;
245+ // 确保清理可能残留的事件监听器
239246 document . removeEventListener ( 'mousemove' , handleMouseMove ) ;
240247 document . removeEventListener ( 'mouseup' , handleMouseUp ) ;
241- } ;
248+ } ) ;
249+
250+ // 如果还没有总的清理函数,创建一个
251+ if ( ! popup . _cleanup ) {
252+ popup . _cleanup = ( ) => {
253+ if ( popup . _cleanupFunctions ) {
254+ popup . _cleanupFunctions . forEach ( cleanup => cleanup ( ) ) ;
255+ popup . _cleanupFunctions = [ ] ;
256+ }
257+ } ;
258+ }
242259 }
243260
244261 /**
@@ -252,6 +269,7 @@ class PopupManager {
252269 const iconElement = document . createElement ( 'div' ) ;
253270 iconElement . className = 'icon-resize-handle' ;
254271 resizeHandle . appendChild ( iconElement ) ;
272+
255273 popup . appendChild ( resizeHandle ) ;
256274
257275 // 窗口大小调节相关变量
@@ -281,6 +299,10 @@ class PopupManager {
281299 // 阻止文本选择
282300 document . body . style . userSelect = 'none' ;
283301 document . body . style . cursor = 'nw-resize' ;
302+
303+ // 添加临时的全局事件监听器
304+ document . addEventListener ( 'mousemove' , handleResizeMove , { passive : false } ) ;
305+ document . addEventListener ( 'mouseup' , handleResizeEnd , { once : true } ) ;
284306 } ;
285307
286308 const handleResizeMove = ( e ) => {
@@ -322,25 +344,40 @@ class PopupManager {
322344 // 恢复默认样式
323345 document . body . style . userSelect = '' ;
324346 document . body . style . cursor = '' ;
347+
348+ // 移除临时的事件监听器
349+ document . removeEventListener ( 'mousemove' , handleResizeMove ) ;
350+ document . removeEventListener ( 'mouseup' , handleResizeEnd ) ;
325351 } ;
326352
327- // 添加事件监听
353+ // 只添加初始的mousedown事件监听
328354 resizeHandle . addEventListener ( 'mousedown' , handleResizeStart ) ;
329- document . addEventListener ( 'mousemove' , handleResizeMove ) ;
330- document . addEventListener ( 'mouseup' , handleResizeEnd ) ;
331355
332- // 保存清理函数
333- const originalCleanup = popup . _cleanup || ( ( ) => { } ) ;
334- popup . _cleanup = ( ) => {
335- originalCleanup ( ) ;
356+ // 改进清理函数的保存方式,避免覆盖
357+ if ( ! popup . _cleanupFunctions ) {
358+ popup . _cleanupFunctions = [ ] ;
359+ }
360+
361+ popup . _cleanupFunctions . push ( ( ) => {
336362 resizeHandle . removeEventListener ( 'mousedown' , handleResizeStart ) ;
363+ // 确保清理可能残留的事件监听器
337364 document . removeEventListener ( 'mousemove' , handleResizeMove ) ;
338365 document . removeEventListener ( 'mouseup' , handleResizeEnd ) ;
339366
340367 // 恢复默认样式
341368 document . body . style . userSelect = '' ;
342369 document . body . style . cursor = '' ;
343- } ;
370+ } ) ;
371+
372+ // 如果还没有总的清理函数,创建一个
373+ if ( ! popup . _cleanup ) {
374+ popup . _cleanup = ( ) => {
375+ if ( popup . _cleanupFunctions ) {
376+ popup . _cleanupFunctions . forEach ( cleanup => cleanup ( ) ) ;
377+ popup . _cleanupFunctions = [ ] ;
378+ }
379+ } ;
380+ }
344381 }
345382
346383 /**
0 commit comments