88 :windowGetClickEventTarget =" target"
99 :resize =" canvasState.type === 'absolute'"
1010 :multiStateLength =" multiStateLength"
11+ :isMultiDragging =" isMultiDragging()"
1112 @select-slot =" selectSlot"
1213 @setting =" settingModel"
1314 ></canvas-action >
1415 </div >
16+ <canvas-multi-drag-indicator
17+ :lineState =" lineState"
18+ :multiDragState =" multiDragState"
19+ :multiStateLength =" multiStateLength"
20+ :isMultiDragging =" isMultiDragging()"
21+ :getMultiDragPositionText =" getMultiDragPositionText"
22+ ></canvas-multi-drag-indicator >
1523 <canvas-router-jumper :hoverState =" hoverState" :inactiveHoverState =" inactiveHoverState" ></canvas-router-jumper >
1624 <canvas-viewer-switcher :hoverState =" hoverState" :inactiveHoverState =" inactiveHoverState" ></canvas-viewer-switcher >
1725 <canvas-divider :selectState =" computedSelectState" ></canvas-divider >
@@ -62,7 +70,9 @@ import CanvasViewerSwitcher from './components/CanvasViewerSwitcher.vue'
6270import CanvasResize from ' ./components/CanvasResize.vue'
6371import CanvasDivider from ' ./components/CanvasDivider.vue'
6472import CanvasResizeBorder from ' ./components/CanvasResizeBorder.vue'
73+ import CanvasMultiDragIndicator from ' ./components/CanvasMultiDragIndicator.vue'
6574import { useMultiSelect } from ' ./composables/useMultiSelect'
75+ import { useMultiDrag } from ' ./composables/useMultiDrag'
6676import {
6777 canvasState ,
6878 onMouseUp ,
@@ -92,7 +102,8 @@ export default {
92102 CanvasDivider,
93103 CanvasResizeBorder,
94104 CanvasRouterJumper,
95- CanvasViewerSwitcher
105+ CanvasViewerSwitcher,
106+ CanvasMultiDragIndicator
96107 },
97108 props: {
98109 controller: Object ,
@@ -113,9 +124,11 @@ export default {
113124 const containerPanel = ref (null )
114125 const insertContainer = ref (false )
115126
116- const { multiSelectedStates } = useMultiSelect ()
127+ const { multiSelectedStates , isMouseDown } = useMultiSelect ()
117128
118129 const multiStateLength = computed (() => multiSelectedStates .value .length )
130+ const { startMultiDrag , moveMultiDrag , endMultiDrag , isMultiDragging , getMultiDragPositionText , multiDragState } =
131+ useMultiDrag ()
119132
120133 const computedSelectState = computed (() => {
121134 if (multiSelectedStates .value .length === 1 ) {
@@ -129,6 +142,15 @@ export default {
129142 const { clientX , clientY } = event
130143 const element = getElement (event .target )
131144 closeMenu ()
145+
146+ if (! element) return
147+
148+ // 优先处理右键菜单
149+ if (event .button === 2 ) {
150+ openMenu (event )
151+ return
152+ }
153+
132154 let node = getCurrent ().schema
133155
134156 if (element) {
@@ -144,15 +166,17 @@ export default {
144166 }
145167 }
146168
147- if (event .button === 0 && element !== element .ownerDocument .body ) {
148- const { x , y } = element .getBoundingClientRect ()
149-
150- dragStart (node, element, { offsetX: clientX - x, offsetY: clientY - y })
169+ // 处理多选拖拽开始 - 确保在单节点拖拽之前处理
170+ if (startMultiDrag (event , element)) {
171+ return
151172 }
152173
153- // 如果是点击右键则打开右键菜单
154- if (event .button === 2 ) {
155- openMenu (event )
174+ // 处理单节点拖拽开始
175+ if (event .button === 0 && element !== element .ownerDocument .body ) {
176+ const { x , y } = element .getBoundingClientRect ()
177+ if (multiStateLength .value === 1 ) {
178+ dragStart (node, element, { offsetX: clientX - x, offsetY: clientY - y })
179+ }
156180 }
157181 }
158182 }
@@ -206,9 +230,10 @@ export default {
206230 const doc = iframe .value .contentDocument
207231 const win = iframe .value .contentWindow
208232
233+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
209234 let isScrolling = false
210235
211- // 以下是内部iframe监听的事件
236+ // 监听鼠标按下事件
212237 win .addEventListener (' mousedown' , (event ) => {
213238 handleCanvasEvent (() => {
214239 // html元素使用scroll和mouseup事件处理
@@ -222,6 +247,8 @@ export default {
222247 return
223248 }
224249
250+ isMouseDown .value = true
251+
225252 insertPosition .value = false
226253 insertContainer .value = false
227254 setCurrentNode (event )
@@ -235,32 +262,49 @@ export default {
235262 isScrolling = true
236263 })
237264
238- win .addEventListener (' mouseup' , (event ) => {
239- if (event .target !== doc .documentElement || isScrolling) {
240- return
241- }
265+ // 监听鼠标移动事件
266+ win .addEventListener (' mousemove' , (ev ) => {
267+ handleCanvasEvent (() => {
268+ // 优先处理多选拖拽移动
269+ if (! moveMultiDrag (ev)) {
270+ // 如果不是多选拖拽,则处理普通拖拽
271+ dragMove (ev, true )
272+ }
273+ })
274+ })
275+
276+ // 监听拖拽结束事件
277+ win .addEventListener (' mouseup' , (ev ) => {
278+ handleCanvasEvent (() => {
279+ if (ev .button === 0 && isMouseDown .value ) {
280+ isMouseDown .value = false
281+ }
242282
243- insertPosition .value = false
244- insertContainer .value = false
245- setCurrentNode (event )
246- target .value = event .target
283+ // 优先处理多选拖拽结束
284+ if (! endMultiDrag ()) {
285+ // 如果不是多选拖拽,则处理普通拖拽结束
286+ onMouseUp (ev)
287+ }
288+ })
247289 })
248290
291+ // 监听拖拽过程事件
249292 win .addEventListener (' dragover' , (ev ) => {
250293 ev .dataTransfer .dropEffect = ' move'
251294 ev .preventDefault ()
252- dragMove (ev)
295+ // 优先处理多选拖拽移动
296+ if (! moveMultiDrag (ev)) {
297+ dragMove (ev)
298+ }
253299 })
254300
301+ // 监听放置事件
255302 win .addEventListener (' drop' , (ev ) => {
256303 ev .preventDefault ()
257- onMouseUp (ev)
258- })
259-
260- win .addEventListener (' mousemove' , (ev ) => {
261- handleCanvasEvent (() => {
262- dragMove (ev, true )
263- })
304+ // 优先处理多选拖拽结束
305+ if (! endMultiDrag ()) {
306+ onMouseUp (ev)
307+ }
264308 })
265309
266310 // 阻止浏览器默认的右键菜单功能
@@ -327,6 +371,7 @@ export default {
327371 document .addEventListener (' canvasReady' , canvasReady)
328372
329373 return {
374+ isMouseDown,
330375 iframe,
331376 dragState,
332377 hoverState,
@@ -347,7 +392,10 @@ export default {
347392 insertPosition,
348393 insertContainer,
349394 loading,
350- srcAttrName
395+ srcAttrName,
396+ isMultiDragging,
397+ multiDragState,
398+ getMultiDragPositionText
351399 }
352400 }
353401}
0 commit comments