// plugins/draggable.client.ts import { defineNuxtPlugin } from '#app' export default defineNuxtPlugin((nuxtApp) => { // 拖拽指令 nuxtApp.vueApp.directive('draggable', { mounted(el, binding) { // 只在客户端执行 if (import.meta.server) return const triggerSelector = binding.value?.triggerSelector || '.el-dialog__header' const dialogHeaderEl = el.querySelector(triggerSelector) as HTMLElement const dialogEl = el.querySelector('.el-dialog') as HTMLElement if (!dialogHeaderEl || !dialogEl) return let isDragging = false let offsetX = 0 let offsetY = 0 const startDrag = (e: MouseEvent) => { isDragging = true const rect = dialogEl.getBoundingClientRect() offsetX = e.clientX - rect.left offsetY = e.clientY - rect.top dialogEl.style.cursor = 'move' } const onDrag = (e: MouseEvent) => { if (!isDragging) return const x = e.clientX - offsetX const y = e.clientY - offsetY // 边界限制 const maxX = window.innerWidth - dialogEl.offsetWidth const maxY = window.innerHeight - dialogEl.offsetHeight dialogEl.style.left = `${Math.max(0, Math.min(x, maxX))}px` dialogEl.style.top = `${Math.max(0, Math.min(y, maxY))}px` } const stopDrag = () => { isDragging = false dialogEl.style.cursor = '' } dialogHeaderEl.addEventListener('mousedown', startDrag) document.addEventListener('mousemove', onDrag) document.addEventListener('mouseup', stopDrag) // 清理函数 ; (el as any)._dragCleanup = () => { dialogHeaderEl.removeEventListener('mousedown', startDrag) document.removeEventListener('mousemove', onDrag) document.removeEventListener('mouseup', stopDrag) } }, unmounted(el) { ; (el as any)._dragCleanup?.() } }) })