fix: 修复画布组件嵌套拖拽的问题 (#364)

* fix: 修复画布组件嵌套拖拽的问题
This commit is contained in:
Gene 2024-04-18 04:22:59 -07:00 committed by GitHub
parent 681a6fa612
commit e54edca915
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 15 deletions

View File

@ -68,7 +68,7 @@
<div v-show="hoverState.configure?.isContainer" class="corner-mark-bottom-right">拖放元素到容器内</div> <div v-show="hoverState.configure?.isContainer" class="corner-mark-bottom-right">拖放元素到容器内</div>
</div> </div>
<div v-show="lineState.height && lineState.width" class="canvas-rect line"> <div v-show="lineState.height && lineState.width" class="canvas-rect line">
<div :class="['hover-line', lineState.position]"> <div :class="['hover-line', lineState.position, { forbidden: lineState.forbidden }]">
<div v-if="lineState.position === 'in' && hoverState.configure" class="choose-slots"></div> <div v-if="lineState.position === 'in' && hoverState.configure" class="choose-slots"></div>
</div> </div>
</div> </div>
@ -540,11 +540,12 @@ export default {
height: 100%; height: 100%;
background: var(--ti-lowcode-canvas-hover-line-in-bg-color); background: var(--ti-lowcode-canvas-hover-line-in-bg-color);
} }
&.forbid { &.forbidden:not(.in) {
width: 100%;
height: 100%;
background: var(--ti-lowcode-canvas-hover-line-forbid-bg-color); background: var(--ti-lowcode-canvas-hover-line-forbid-bg-color);
} }
&.forbidden.in {
background: var(--ti-lowcode-canvas-hover-line-in-forbid-bg-color);
}
} }
.choose-slots { .choose-slots {

View File

@ -25,8 +25,7 @@ export const POSITION = Object.freeze({
BOTTOM: 'bottom', BOTTOM: 'bottom',
LEFT: 'left', LEFT: 'left',
RIGHT: 'right', RIGHT: 'right',
IN: 'in', IN: 'in'
FORBID: 'forbid'
}) })
import { isVsCodeEnv } from '@opentiny/tiny-engine-controller/js/environments' import { isVsCodeEnv } from '@opentiny/tiny-engine-controller/js/environments'
@ -98,6 +97,7 @@ const initialLineState = {
width: 0, width: 0,
left: 0, left: 0,
position: '', position: '',
forbidden: false,
id: '', id: '',
config: null, config: null,
doc: null doc: null
@ -416,6 +416,23 @@ export const allowInsert = (configure = hoverState.configure || {}, data = dragS
return flag return flag
} }
const isAncestor = (ancestor, descendant) => {
const ancestorId = typeof ancestor === 'string' ? ancestor : ancestor.id
let descendantId = typeof descendant === 'string' ? descendant : descendant.id
while (descendantId) {
const { parent } = getNode(descendantId, true) || {}
if (parent.id === ancestorId) {
return true
}
descendantId = parent.id
}
return false
}
// 获取位置信息,返回状态 // 获取位置信息,返回状态
const lineAbs = 20 const lineAbs = 20
const getPosLine = (rect, configure) => { const getPosLine = (rect, configure) => {
@ -423,6 +440,7 @@ const getPosLine = (rect, configure) => {
const yAbs = Math.min(lineAbs, rect.height / 3) const yAbs = Math.min(lineAbs, rect.height / 3)
const xAbs = Math.min(lineAbs, rect.width / 3) const xAbs = Math.min(lineAbs, rect.width / 3)
let type let type
let forbidden = false
if (mousePos.y < rect.top + yAbs) { if (mousePos.y < rect.top + yAbs) {
type = POSITION.TOP type = POSITION.TOP
@ -433,12 +451,21 @@ const getPosLine = (rect, configure) => {
} else if (mousePos.x > rect.right - xAbs) { } else if (mousePos.x > rect.right - xAbs) {
type = POSITION.RIGHT type = POSITION.RIGHT
} else if (configure.isContainer) { } else if (configure.isContainer) {
type = allowInsert() ? POSITION.IN : POSITION.FORBID type = POSITION.IN
if (!allowInsert()) {
forbidden = true
}
} else { } else {
type = POSITION.BOTTOM type = POSITION.BOTTOM
} }
return { type } // 如果被拖拽的节点不是新增的,并且是放置的节点的祖先节点,则禁止插入
const draggedId = dragState.data?.id
if (draggedId && isAncestor(draggedId, lineState.id)) {
forbidden = true
}
return { type, forbidden }
} }
const isBodyEl = (element) => element.nodeName === 'BODY' const isBodyEl = (element) => element.nodeName === 'BODY'
@ -484,20 +511,24 @@ const setHoverRect = (element, data) => {
const childRect = getRect(childEle) const childRect = getRect(childEle)
const { left, height, top, width } = childRect const { left, height, top, width } = childRect
const { x, y } = getOffset(childEle) const { x, y } = getOffset(childEle)
const posLine = getPosLine(childRect, lineState.configure)
Object.assign(lineState, { Object.assign(lineState, {
width: width * scale, width: width * scale,
height: height * scale, height: height * scale,
top: top * scale + y - siteCanvasRect.y, top: top * scale + y - siteCanvasRect.y,
left: left * scale + x - siteCanvasRect.x, left: left * scale + x - siteCanvasRect.x,
position: canvasState.type === 'absolute' || getPosLine(childRect, lineState.configure).type position: canvasState.type === 'absolute' || posLine.type,
forbidden: posLine.forbidden
}) })
} else { } else {
const posLine = getPosLine(rect, configure)
Object.assign(lineState, { Object.assign(lineState, {
width: width * scale, width: width * scale,
height: height * scale, height: height * scale,
top: top * scale + y - siteCanvasRect.y, top: top * scale + y - siteCanvasRect.y,
left: left * scale + x - siteCanvasRect.x, left: left * scale + x - siteCanvasRect.x,
position: canvasState.type === 'absolute' || getPosLine(rect, configure).type position: canvasState.type === 'absolute' || posLine.type,
forbidden: posLine.forbidden
}) })
} }
@ -670,13 +701,12 @@ export const copyNode = (id) => {
export const onMouseUp = () => { export const onMouseUp = () => {
const { draging, data } = dragState const { draging, data } = dragState
const { position } = lineState const { position, forbidden } = lineState
const absolute = canvasState.type === 'absolute' const absolute = canvasState.type === 'absolute'
const sourceId = data?.id const sourceId = data?.id
const lineId = lineState.id const lineId = lineState.id
const allowInsert = position !== POSITION.FORBID
if (draging && allowInsert) { if (draging && !forbidden) {
const { parent, node } = getNode(lineId, true) || {} // target const { parent, node } = getNode(lineId, true) || {} // target
const targetNode = { parent, node, data: toRaw(data) } const targetNode = { parent, node, data: toRaw(data) }

View File

@ -1,7 +1,8 @@
#canvas-wrap { #canvas-wrap {
--ti-lowcode-canvas-rect-border-color: var(--ti-lowcode-base-primary-color-2); --ti-lowcode-canvas-rect-border-color: var(--ti-lowcode-base-primary-color-2);
--ti-lowcode-canvas-hover-line-in-bg-color: rgba(0, 255, 0, 0.1); --ti-lowcode-canvas-hover-line-in-bg-color: rgba(0, 255, 0, 0.1);
--ti-lowcode-canvas-hover-line-forbid-bg-color: rgb(255, 66, 77); --ti-lowcode-canvas-hover-line-forbid-bg-color: var(--ti-lowcode-base-error-color);
--ti-lowcode-canvas-hover-line-in-forbid-bg-color: rgba(242, 48, 48, 0.3);
--ti-lowcode-canvas-choose-slot-border-color: var(--ti-lowcode-base-text-color-2); --ti-lowcode-canvas-choose-slot-border-color: var(--ti-lowcode-base-text-color-2);
--ti-lowcode-canvas-choose-slot-color: var(--ti-lowcode-base-text-color-2); --ti-lowcode-canvas-choose-slot-color: var(--ti-lowcode-base-text-color-2);
--ti-lowcode-canvas-corner-mark-left-color: var(--ti-lowcode-base-text-color-2); --ti-lowcode-canvas-corner-mark-left-color: var(--ti-lowcode-base-text-color-2);

View File

@ -1,7 +1,8 @@
#canvas-wrap { #canvas-wrap {
--ti-lowcode-canvas-rect-border-color: var(--ti-lowcode-base-primary-color-2); --ti-lowcode-canvas-rect-border-color: var(--ti-lowcode-base-primary-color-2);
--ti-lowcode-canvas-hover-line-in-bg-color: rgba(0, 255, 0, 0.1); --ti-lowcode-canvas-hover-line-in-bg-color: rgba(0, 255, 0, 0.1);
--ti-lowcode-canvas-hover-line-forbid-bg-color: rgb(255, 66, 77); --ti-lowcode-canvas-hover-line-forbid-bg-color: var(--ti-lowcode-base-error-color);
--ti-lowcode-canvas-hover-line-in-forbid-bg-color: rgba(242, 48, 48, 0.3);
--ti-lowcode-canvas-choose-slot-border-color: var(--ti-lowcode-base-text-color-2); --ti-lowcode-canvas-choose-slot-border-color: var(--ti-lowcode-base-text-color-2);
--ti-lowcode-canvas-choose-slot-color: var(--ti-lowcode-base-text-color-2); --ti-lowcode-canvas-choose-slot-color: var(--ti-lowcode-base-text-color-2);
--ti-lowcode-canvas-corner-mark-left-color: var(--ti-lowcode-base-text-color-2); --ti-lowcode-canvas-corner-mark-left-color: var(--ti-lowcode-base-text-color-2);