Files
maintenance_system/src/views/largeScreen/components/newMap/dialog/baseDialog.vue
2025-10-11 09:56:33 +08:00

270 lines
6.2 KiB
Vue

<script setup lang="ts">
import { ref, watch, onMounted, nextTick } from 'vue';
const props = defineProps({
title: {
type: String,
default: ''
},
width: {
type: String,
default: ''
},
height: {
type: String,
default: ''
},
top: {
type: String,
default: ''
},
left: {
type: String,
default: ''
},
id: {
type: String,
default: ''
},
bodyId: {
type: String,
default: ''
},
clearAnimation: {
type: Boolean,
default: false
},
fix: {
type: Boolean,
default: false
},
className: {
type: String
},
nofold: {
type: Boolean,
default: false
},
isfold: {
type: Boolean,
default: false
},
noClose: {
type: Boolean,
default: false
},
show: {
type: Boolean,
default: false
},
closeCallback: {
type: Function,
default: () => {}
}
});
// 内部状态
const first = ref(false);
const dialogVisible = ref(false);
const FontChart = ref(undefined);
const callback = ref(undefined);
const baseDialog = ref(null);
const titleBox = ref(null);
const dialogContent = ref(null);
const tableData = ref([]);
// 方法定义
const open = (data) => {
if (!first.value) {
first.value = true;
dialogVisible.value = true;
nextTick(() => {
moveDiv();
});
}
dialogVisible.value = true;
nextTick(() => {
// setTimeout(() => {
// openPosition()
// }, 0)
if (baseDialog.value) {
baseDialog.value.style.width = props.width;
baseDialog.value.style.height = props.height;
baseDialog.value.style.top = props.top;
baseDialog.value.style.left = props.left;
baseDialog.value.style.position = props.fix ? 'fixed' : 'absolute';
}
});
};
const close = () => {
dialogVisible.value = false;
if (props.clearAnimation) {
// 假设mapService是全局可用的
// window.mapService?.removeAnimation();
}
callback.value && callback.value();
props.closeCallback && props.closeCallback();
};
const moveDiv = () => {
let x = 0;
let y = 0;
let l = 0;
let t = 0;
const oClickDiv = baseDialog.value;
const oMoveDiv = titleBox.value;
if (oClickDiv) {
// console.log(oMoveDiv);
oMoveDiv.onmousedown = (e) => {
// 获取对话框尺寸
const oMoveDivHeight = baseDialog.value.offsetHeight;
const oMoveDivWidth = baseDialog.value.offsetWidth;
x = e.clientX;
y = e.clientY;
const leftPx = window.getComputedStyle(baseDialog.value).left;
const topPx = window.getComputedStyle(baseDialog.value).top;
l = parseFloat(leftPx);
t = parseFloat(topPx);
// 获取视口大小
const container = props.bodyId ? document.getElementById(props.bodyId) : document.body;
const windowHeight = container.clientHeight;
const windowWidth = container.clientWidth;
// 鼠标移动事件处理
const handleMouseMove = (e) => {
e.preventDefault();
const nx = e.clientX;
const ny = e.clientY;
// 计算新位置
let newLeft = nx - (x - l);
let newTop = ny - (y - t);
// 边界检查
if (newLeft < 0) {
newLeft = 0;
} else if (newLeft + oMoveDivWidth > windowWidth) {
newLeft = windowWidth - oMoveDivWidth;
}
if (newTop <= 0) {
newTop = 0;
} else if (newTop + oMoveDivHeight > windowHeight) {
newTop = windowHeight - oMoveDivHeight;
}
// 更新位置
if (baseDialog.value) {
baseDialog.value.style.left = newLeft + 'px';
baseDialog.value.style.top = newTop + 'px';
baseDialog.value.style.bottom = 'unset';
baseDialog.value.style.right = 'unset';
}
};
// 鼠标抬起事件处理
const handleMouseUp = () => {
window.removeEventListener('mousemove', handleMouseMove);
window.removeEventListener('mouseup', handleMouseUp);
};
// 添加事件监听
window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('mouseup', handleMouseUp);
};
}
};
const openPosition = () => {
const oMoveDiv = baseDialog.value;
if (!oMoveDiv) return;
// 获取对话框尺寸
const oMoveDivHeight = oMoveDiv.offsetHeight;
const oMoveDivWidth = oMoveDiv.offsetWidth;
// 获取当前位置
const leftPx = parseFloat(window.getComputedStyle(oMoveDiv).left);
const topPx = parseFloat(window.getComputedStyle(oMoveDiv).top);
// 获取视口大小
const container = props.bodyId ? document.getElementById(props.bodyId) : document.body;
const windowHeight = container.clientHeight;
const windowWidth = container.clientWidth;
// 边界检查
let newLeft = leftPx;
let newTop = topPx;
if (newLeft < 0) {
newLeft = 0;
} else if (newLeft + oMoveDivWidth > windowWidth) {
newLeft = windowWidth - oMoveDivWidth;
}
if (newTop - 10 <= 0) {
newTop = -10;
} else if (newTop + oMoveDivHeight > windowHeight) {
newTop = windowHeight - oMoveDivHeight;
}
// 更新位置
oMoveDiv.style.left = newLeft + 'px';
oMoveDiv.style.top = newTop + 'px';
};
// 暴露公共方法
defineExpose({
open,
close,
moveDiv,
openPosition
});
</script>
<template>
<div class="YJ-custom-base-dialog" :class="className" ref="baseDialog" :id="id" v-if="dialogVisible" v-show="dialogVisible">
<div class="title-box" ref="titleBox">
<span class="title">{{ title }}</span
><span class="close-box" @click="close"><span class="close"></span><i></i></span>
</div>
<div class="content" style="padding: 0 24px 0 24px">
<div>
<slot name="content"></slot>
</div>
</div>
<div class="foot">
<slot name="footer"></slot>
</div>
</div>
</template>
<style scoped lang="scss">
.YJ-custom-base-dialog {
::v-deep .el-tabs {
width: 100%;
.el-tabs__item {
padding: 0 8px;
color: #fff;
}
.el-tabs__item:nth-child(2) {
padding-left: 0;
}
.el-tabs__item.is-active,
.el-tabs__item:hover {
color: #fff;
}
.el-tabs__active-bar {
background-color: rgb(0, 255, 255);
}
.el-tabs__nav-wrap:after {
background-color: rgba(204, 204, 204, 0.2);
}
}
}
</style>