初步完成

This commit is contained in:
wfz
2026-01-20 20:25:03 +08:00
parent 1bf26e6e71
commit 4a90340ab3
10 changed files with 763 additions and 1715 deletions

View File

@@ -57,6 +57,14 @@ const bindElementEvents = (element: HTMLElement, type: ElementType, path: string
if (!dragStore.isDragging) {
element.classList.add('fauto-hover')
} else {
// 拖拽时移动到不同元素,进入目标选择阶段
// 检查是否是不同的元素(不是源元素或其父级)
const sourcePath = dragStore.confirmedSource?.path || dragStore.dragSource?.path
if (sourcePath && path !== sourcePath && !path.startsWith(sourcePath)) {
dragStore.enterTargetPhase(element)
updateSelectedHighlight()
}
}
}
@@ -93,8 +101,8 @@ const bindElementEvents = (element: HTMLElement, type: ElementType, path: string
// 如果已经有拖拽源,不处理
if (dragStore.isDragging) return
// 开始画布内元素拖拽
dragStore.startDragFromCanvas(path, type)
// 开始画布内元素拖拽,传入元素引用以立即构建层级列表
dragStore.startDragFromCanvas(path, type, element)
}
// 绑定事件
@@ -228,7 +236,8 @@ const clearDragHighlight = () => {
* 全局鼠标移动处理(拖拽时更新方向)
*/
const handleGlobalMouseMove = (e: MouseEvent) => {
if (dragStore.isDragging && dragStore.selectedNode) {
// 只在目标选择阶段才更新方向
if (dragStore.isDragging && dragStore.dragPhase === 'target' && dragStore.selectedNode) {
dragStore.updateDirectionFromMouse(e.clientX, e.clientY)
}
}
@@ -237,7 +246,8 @@ const handleGlobalMouseMove = (e: MouseEvent) => {
* 全局鼠标松开处理
*/
const handleGlobalMouseUp = async () => {
if (dragStore.isDragging && dragStore.selectedNode && dragStore.hoverDirection) {
// 只在目标选择阶段才执行拖放
if (dragStore.isDragging && dragStore.dragPhase === 'target' && dragStore.selectedNode && dragStore.hoverDirection) {
// 获取当前页面路径从vueFileStore
const pagePath = vueFileStore.selectedFilePath

View File

@@ -58,6 +58,16 @@ export const useDragStore = defineStore('drag', () => {
// 拖拽源
const dragSource = ref<DragSource | null>(null)
// 拖拽阶段: 'source' = 源选择阶段, 'target' = 目标选择阶段
const dragPhase = ref<'source' | 'target'>('source')
// 已确定的源元素信息(当进入目标选择阶段时保存)
const confirmedSource = ref<{
path: string
type: ElementType
element: HTMLElement
} | null>(null)
// ========== 层级选择状态 ==========
// 当前悬停位置的所有层级节点(从深到浅排序)
@@ -103,15 +113,57 @@ export const useDragStore = defineStore('drag', () => {
/**
* 开始拖拽(从画布内元素)
* @param path 元素路径
* @param elementType 元素类型
* @param element 元素DOM引用用于立即构建层级列表
*/
const startDragFromCanvas = (path: string, elementType: ElementType) => {
const startDragFromCanvas = (path: string, elementType: ElementType, element?: HTMLElement) => {
isDragging.value = true
dragPhase.value = 'source' // 进入源选择阶段
confirmedSource.value = null // 清除之前的确定源
dragSource.value = {
type: 'canvas-element',
path,
elementType
}
console.log('[DragStore] 开始拖拽画布元素:', path)
// 立即构建层级列表,让用户可以在原地通过上下键切换源元素层级
if (element) {
updateHierarchy(element)
}
console.log('[DragStore] 开始拖拽画布元素 (源选择阶段):', path)
}
/**
* 进入目标选择阶段
* 当鼠标移动到不同元素时调用
*/
const enterTargetPhase = (targetElement: HTMLElement) => {
if (dragPhase.value === 'source' && selectedNode.value) {
// 保存当前选中的源元素
confirmedSource.value = {
path: selectedNode.value.path,
type: selectedNode.value.type,
element: selectedNode.value.element
}
// 更新 dragSource 中的路径和类型
if (dragSource.value) {
dragSource.value.path = selectedNode.value.path
dragSource.value.elementType = selectedNode.value.type
}
console.log('[DragStore] 确定源元素:', confirmedSource.value.path)
}
// 进入目标选择阶段
dragPhase.value = 'target'
// 更新层级列表为目标元素的层级
updateHierarchy(targetElement)
console.log('[DragStore] 进入目标选择阶段')
}
/**
@@ -215,6 +267,8 @@ export const useDragStore = defineStore('drag', () => {
hierarchyNodes.value = []
selectedHierarchyIndex.value = 0
hoverDirection.value = null
dragPhase.value = 'source'
confirmedSource.value = null
}
/**
@@ -252,12 +306,11 @@ export const useDragStore = defineStore('drag', () => {
* 是否为跨类型拖放(源和目标类型不同)
*/
const isCrossTypeDrop = computed(() => {
if (!dragSource.value || !selectedNode.value) return false
// 只有在目标选择阶段才考虑跨类型
if (dragPhase.value !== 'target') return false
if (!confirmedSource.value || !selectedNode.value) return false
// 只有画布内元素拖放才考虑跨类型
if (dragSource.value.type !== 'canvas-element') return false
const sourceType = dragSource.value.elementType
const sourceType = confirmedSource.value.type
const targetType = selectedNode.value.type
// er 拖到 ec 或 ec 拖到 er 都是跨类型
@@ -427,6 +480,8 @@ export const useDragStore = defineStore('drag', () => {
// 状态
isDragging,
dragSource,
dragPhase,
confirmedSource,
hierarchyNodes,
selectedHierarchyIndex,
selectedNode,
@@ -439,6 +494,7 @@ export const useDragStore = defineStore('drag', () => {
// 方法
startDragFromComponentList,
startDragFromCanvas,
enterTargetPhase,
updateHierarchy,
clearHierarchy,
selectParentLevel,

View File

@@ -9,16 +9,18 @@
<div class="design-component">右侧标题</div>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12">
<div class="design-component">右侧列2</div>
</el-col>
</el-row>
<el-col :span="12">
<div class="design-component">右侧列1</div>
</el-col>
<el-row :gutter="10">
<el-col :span="12">
<div class="design-component">右侧列2</div>
</el-col>
</el-row>
</el-col>
<el-col :span="12">
<div class="design-component">右侧列1</div>
</el-col>
</el-row>
</template>