This commit is contained in:
wfz
2026-01-20 19:43:40 +08:00
parent 378fb65c76
commit ad2322b553
9 changed files with 1650 additions and 9 deletions

View File

@@ -147,5 +147,5 @@
"activeTabId": "mxfx11j"
}
},
"lastUpdated": "2025-12-22T15:54:13.388Z"
"lastUpdated": "2026-01-20T11:33:21.385Z"
}

View File

@@ -2,6 +2,7 @@
import { ref, onMounted, onUnmounted, watch, nextTick, computed } from 'vue'
import { useInteractionStore, useDragStore, generateElementPath } from '../../plugins'
import type { ElementType, InteractionTarget } from '../../plugins'
import { useVueFileStore } from '../../stores/vueFileStore'
import DropZone from './DropZone.vue'
import DragPreview from './DragPreview.vue'
@@ -11,6 +12,7 @@ const props = defineProps<{
const interactionStore = useInteractionStore()
const dragStore = useDragStore()
const vueFileStore = useVueFileStore()
const containerRef = ref<HTMLElement | null>(null)
// 存储所有绑定的事件清理函数
@@ -222,13 +224,25 @@ const clearDragHighlight = () => {
})
}
/**
* 全局鼠标移动处理(拖拽时更新方向)
*/
const handleGlobalMouseMove = (e: MouseEvent) => {
if (dragStore.isDragging && dragStore.selectedNode) {
dragStore.updateDirectionFromMouse(e.clientX, e.clientY)
}
}
/**
* 全局鼠标松开处理
*/
const handleGlobalMouseUp = () => {
const handleGlobalMouseUp = async () => {
if (dragStore.isDragging && dragStore.selectedNode && dragStore.hoverDirection) {
// 确认拖放
dragStore.confirmDrop()
// 获取当前页面路径从vueFileStore
const pagePath = vueFileStore.selectedFilePath
// 确认拖放,传入页面路径
await dragStore.confirmDrop(pagePath || undefined)
}
dragStore.endDrag()
@@ -247,6 +261,8 @@ onMounted(() => {
// 添加键盘事件监听
document.addEventListener('keydown', handleKeyDown)
// 添加全局鼠标移动事件(用于更新拖放方向)
document.addEventListener('mousemove', handleGlobalMouseMove)
// 添加全局鼠标松开事件
document.addEventListener('mouseup', handleGlobalMouseUp)
})
@@ -263,6 +279,7 @@ onUnmounted(() => {
// 移除键盘事件监听
document.removeEventListener('keydown', handleKeyDown)
document.removeEventListener('mousemove', handleGlobalMouseMove)
document.removeEventListener('mouseup', handleGlobalMouseUp)
})

View File

@@ -3,6 +3,9 @@ import { ref, computed } from 'vue'
import type { InteractionTarget, ElementType } from './interactionStore'
import { parsePath } from './pathUtils'
// 后端服务地址
const TEMPLATE_SERVICE_URL = 'http://localhost:3001'
/**
* 拖放方向
*/
@@ -177,16 +180,17 @@ export const useDragStore = defineStore('drag', () => {
// 3. 找到最接近的深度
if (oldSelectedDepth !== undefined && nodes.length > 0) {
let closestIndex = 0
let minDiff = Math.abs(nodes[0].depth - oldSelectedDepth)
let minDiff = Math.abs((nodes[0]?.depth ?? 0) - oldSelectedDepth)
for (let i = 1; i < nodes.length; i++) {
const diff = Math.abs(nodes[i].depth - oldSelectedDepth)
const nodeDepth = nodes[i]?.depth ?? 0
const diff = Math.abs(nodeDepth - oldSelectedDepth)
if (diff < minDiff) {
minDiff = diff
closestIndex = i
}
}
selectedHierarchyIndex.value = closestIndex
console.log('[DragStore] 选择最接近深度:', nodes[closestIndex].path)
console.log('[DragStore] 选择最接近深度:', nodes[closestIndex]?.path)
} else {
// 4. 默认选中最深层级
selectedHierarchyIndex.value = 0
@@ -242,9 +246,32 @@ export const useDragStore = defineStore('drag', () => {
}
/**
* 确认拖放
* 根据鼠标位置自动计算拖放方向
* @param mouseX 鼠标X坐标
* @param mouseY 鼠标Y坐标
*/
const confirmDrop = () => {
const updateDirectionFromMouse = (mouseX: number, mouseY: number) => {
if (!selectedNode.value?.element) return
const rect = selectedNode.value.element.getBoundingClientRect()
const isRow = selectedNode.value.type === 'er'
if (isRow) {
// Row: 上下方向
const centerY = rect.top + rect.height / 2
hoverDirection.value = mouseY < centerY ? 'top' : 'bottom'
} else {
// Col: 左右方向
const centerX = rect.left + rect.width / 2
hoverDirection.value = mouseX < centerX ? 'left' : 'right'
}
}
/**
* 确认拖放
* @param pagePath 当前页面路径相对于views目录
*/
const confirmDrop = async (pagePath?: string): Promise<DropRecord | null> => {
if (!isDragging.value || !dragSource.value || !selectedNode.value || !hoverDirection.value) {
console.log('[DragStore] 拖放条件不满足')
return null
@@ -263,9 +290,52 @@ export const useDragStore = defineStore('drag', () => {
console.log('[DragStore] 确认拖放:', record)
// 如果提供了页面路径发送API请求到后端
if (pagePath && record.source.type === 'canvas-element') {
await sendMoveRequest(pagePath, record)
}
return record
}
/**
* 发送移动请求到后端服务
*/
const sendMoveRequest = async (pagePath: string, record: DropRecord) => {
try {
console.log('[DragStore] 发送移动请求:', { pagePath, record })
const response = await fetch(`${TEMPLATE_SERVICE_URL}/api/move-element`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
pagePath,
source: record.source,
targetPath: record.targetPath,
targetType: record.targetType,
direction: record.direction
})
})
const result = await response.json()
if (result.success) {
console.log('[DragStore] 移动成功:', result.message)
// 触发页面刷新事件
window.dispatchEvent(new CustomEvent('vue-template-updated', { detail: { pagePath } }))
} else {
console.error('[DragStore] 移动失败:', result.error)
}
return result
} catch (error) {
console.error('[DragStore] API请求失败:', error)
return { success: false, error: (error as Error).message }
}
}
/**
* 取消拖拽
*/
@@ -342,6 +412,7 @@ export const useDragStore = defineStore('drag', () => {
selectParentLevel,
selectChildLevel,
setHoverDirection,
updateDirectionFromMouse,
confirmDrop,
cancelDrag,
endDrag,

View File

@@ -0,0 +1,8 @@
{
"folders": [
{
"path": "../../../.."
}
],
"settings": {}
}