1
0
mirror of https://github.com/zclzone/vue-naive-admin.git synced 2025-05-01 06:39:01 +08:00

feat: 增加MeModal拖拽功能

This commit is contained in:
zclzone 2024-01-13 17:43:48 +08:00
parent 2c9604a829
commit a6773cbfec
3 changed files with 118 additions and 10 deletions

View File

@ -1,7 +1,7 @@
<!--------------------------------
- @Author: Ronnie Zhang
- @LastEditor: Ronnie Zhang
- @LastEditTime: 2023/12/16 18:50:02
- @LastEditTime: 2024/01/13 17:41:38
- @Email: zclzone@outlook.com
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
--------------------------------->
@ -9,17 +9,17 @@
<template>
<n-modal
v-model:show="show"
class="modal-box"
:style="{ width: modalOptions.width, ...modalOptions.modalStyle }"
:preset="undefined"
size="huge"
:bordered="false"
@after-leave="onAfterLeave"
>
<n-card
:title="modalOptions.title"
:style="modalOptions.contentStyle"
:closable="modalOptions.closable"
@close="close()"
>
<n-card :style="modalOptions.contentStyle" :closable="modalOptions.closable" @close="close()">
<template #header>
<header class="modal-header">{{ modalOptions.title }}</header>
</template>
<slot></slot>
<!-- 底部按钮 -->
@ -45,6 +45,7 @@
</template>
<script setup>
import { initDrag } from './utils'
const props = defineProps({
width: {
type: String,
@ -101,12 +102,17 @@ const show = ref(false)
const modalOptions = ref({})
//
function open(options = {}) {
async function open(options = {}) {
// propsoptionsmodalOptions
modalOptions.value = { ...props, ...options }
// showtrue
show.value = true
await nextTick()
initDrag(
Array.prototype.at.call(document.querySelectorAll('.modal-header'), -1),
Array.prototype.at.call(document.querySelectorAll('.modal-box'), -1)
)
}
// close
@ -149,6 +155,14 @@ async function handleCancel(data) {
}
}
async function onAfterLeave() {
await nextTick()
initDrag(
Array.prototype.at.call(document.querySelectorAll('.modal-header'), -1),
Array.prototype.at.call(document.querySelectorAll('.modal-box'), -1)
)
}
const okLoading = computed({
get() {
return !!modalOptions.value?.okLoading

View File

@ -0,0 +1,94 @@
/**********************************
* @Author: Ronnie Zhang
* @LastEditor: Ronnie Zhang
* @LastEditTime: 2024/01/13 17:41:26
* @Email: zclzone@outlook.com
* Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
**********************************/
// 获取元素的CSS样式
function getCss(element, key) {
return element.currentStyle
? element.currentStyle[key]
: window.getComputedStyle(element, null)[key]
}
const params = {
left: 0,
top: 0,
currentX: 0,
currentY: 0,
flag: false,
}
// 初始化拖拽
export function initDrag(bar, box) {
if (!bar || !box) return
const screenWidth = document.body.clientWidth // 页面宽度
const screenHeight = document.documentElement.clientHeight // 页面可见区域高度
const dragDomWidth = box.offsetWidth // 盒子宽度
const dragDomHeight = box.offsetHeight // 盒子高度
const minDomLeft = box.offsetLeft // 盒子相对于父元素的左偏移量
const minDomTop = box.offsetTop // 盒子相对于父元素的上偏移量
const maxDragDomLeft = screenWidth - minDomLeft - dragDomWidth // 盒子在水平方向上可拖拽的最大距离
const maxDragDomTop = screenHeight - minDomTop - dragDomHeight // 盒子在垂直方向上可拖拽的最大距离
if (getCss(box, 'left') !== 'auto') {
params.left = getCss(box, 'left')
}
if (getCss(box, 'top') !== 'auto') {
params.top = getCss(box, 'top')
}
// 设置触发拖动元素的鼠标样式为移动图标
bar.style.cursor = 'move'
// 鼠标按下事件处理函数
bar.onmousedown = function (e) {
params.flag = true // 设置拖拽标志为true
e.preventDefault() // 阻止默认事件
params.currentX = e.clientX // 鼠标当前位置的X坐标
params.currentY = e.clientY // 鼠标当前位置的Y坐标
}
document.onmouseup = function () {
params.flag = false // 设置拖拽标志为false
if (getCss(box, 'left') !== 'auto') {
params.left = getCss(box, 'left')
}
if (getCss(box, 'top') !== 'auto') {
params.top = getCss(box, 'top')
}
}
document.onmousemove = function (e) {
e.preventDefault() // 阻止默认事件
// 如果拖拽标志为true
if (params.flag) {
const nowX = e.clientX // 鼠标当前位置的X坐标
const nowY = e.clientY // 鼠标当前位置的Y坐标
const disX = nowX - params.currentX // 鼠标移动的X距离
const disY = nowY - params.currentY // 鼠标移动的Y距离
let left = parseInt(params.left) + disX // 盒子元素的新left值
let top = parseInt(params.top) + disY // 盒子元素的新top值
// 拖出屏幕边缘
if (-left > minDomLeft) {
left = -minDomLeft
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft
}
if (-top > minDomTop) {
top = -minDomTop
} else if (top > maxDragDomTop) {
top = maxDragDomTop
}
box.style.left = left + 'px'
box.style.top = top + 'px'
}
}
}

View File

@ -1,7 +1,7 @@
<!--------------------------------
- @Author: Ronnie Zhang
- @LastEditor: Ronnie Zhang
- @LastEditTime: 2023/12/16 18:51:56
- @LastEditTime: 2024/01/13 17:41:47
- @Email: zclzone@outlook.com
- Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top
--------------------------------->
@ -55,7 +55,7 @@ function openModal2() {
$modal2.value?.open({
cancelText: '关闭当前',
okText: '关闭所有弹窗',
modalStyle: { width: '320px', padding: '12px', top: '100px' },
width: '400px',
async onOk() {
okLoading2.value = true
$message.loading('正在关闭...', { key: 'modal2' })