先上效果图
新建一个dialog.vue文件,把下面的代码复制进去
// dialog.vue
<template>
<div class="dialogBox" v-show="dialoShow">
<div class="conte " :style="{width:`${width}%`,left: `${(100 - width)/2}%`}" @mousedown="talkBtnBoxMousedown" id="dialogBoxDrag">
<div class="title">
<!-- <span class="line"></span> -->
<span class="text">{{title}}</span>
</div>
<div class="contentBox" id="dialogContentBox" ref="dialogContentBox" v-closeSelectDropdown>
<div class="mar" >
<slot></slot>
</div>
</div>
<div class="foot" v-if="btnShow">
<div class="btnGround">
<span class="footDesc">
<slot name="footDesc"></slot>
</span>
<el-button class=" crmColorBtn" v-if="cancelBtnShow" @click.stop="cancelClick" size="mini" >{{cancelText}}</el-button>
<el-button class="crmColorBgBtn" :disabled="saveBtnDisabled" @click.stop="updateSave" type="primary" size="mini" :loading="dis" >{{saveText}}</el-button>
</div>
</div>
<div class="foot" v-else-if="!btnShow">
<div class="btnGround">
<el-button class=" cancal crmColorBtn" size="mini" @click.stop="closeDialo">{{closeText}}</el-button>
</div>
</div>
<i class="el-icon-close closeIcon" @click.stop="closeDialo"></i>
</div>
</div>
</template>
<script>
export default {
// props:['title', 'dialoShow', 'width'],
props: {
title: {
type: String,
required: true,
},
dialoShow: {
type: Boolean,
required: true,
},
width: {
type: Number,
default: 30
},
btnShow: {
type: Boolean,
default: true
},
height: {
type: Number | String,
default: 0
},
saveText: {
type: String,
default: '保存'
},
cancelText:{
type:String,
default: "取消"
},
closeText:{
type:String,
default:"关闭"
},
saveBtnDisabled:{
type: Boolean,
required: false,
default: false
},
cancelBtnShow:{
type: Boolean,
required: false,
default: true
}
},
methods: {
updateSave(ev) {
ev.stopPropagation();
this.$emit('updateSave');
},
closeDialo(ev) {
ev.stopPropagation();
this.$emit('closeDialo', 'iconCloseClick');
},
cancelClick(ev) {
ev.stopPropagation();
this.$emit('cancelClick');
this.$emit('closeDialo');
},
resetDomScrollHeight(){
const refDom = this.$refs.dialogContentBox;
this.$nextTick(()=>{
if(refDom)refDom.scrollTop = 0;
})
},
setHeight() {
window.setTimeout(() => {
let winHeight = window.innerHeight;
let conHeight = null;
let dialogBox = document.querySelectorAll(".dialogBox");
if(dialogBox.length > 0) {
for(const val of dialogBox) {
if(val.style.display !== 'none'){
conHeight = val.childNodes[0].childNodes[2].childNodes[0].clientHeight;
let percentage = parseInt(((conHeight + 160)/winHeight )*100) ; // 计算出弹窗实际内容高度占浏览器高度比
if (percentage + 8 < 80 && !this.height) {
let num = `${percentage + 10}%`
val.childNodes[0].style.height = num;
} else {
if(typeof this.height === 'number'){
val.childNodes[0].style.height = this.height ? `${this.height}%` : '82%';
} else if(typeof this.height === 'string'){
console.log(this.height);
val.childNodes[0].style.height = this.height ? `${this.height}` : '82%';
}
}
}
}
}
}, 100)
},
// 拖动
talkBtnBoxMousedown(event) {
if(event.target.nodeName.toLowerCase() !== 'div'){
return false;
}
// event.stopPropagation();
let talkBtnBox = this.findParentNodeId(event.target);
let talkBtnBoxX = talkBtnBox.offsetLeft;
let talkBtnBoxY = talkBtnBox.offsetTop;
let mouseX = event.clientX;
let mouseY = event.clientY;
let distanceX = mouseX - talkBtnBoxX;
let distanceY = mouseY - talkBtnBoxY;
document.onmousemove = (ev) => {
console.log('move');
ev.stopPropagation();
talkBtnBox.style.left = ev.clientX - distanceX + 'px';
talkBtnBox.style.top = ev.clientY - distanceY + 'px';
}
document.onmouseup = (evt) => {
evt.stopPropagation();
document.onmousemove = null;
document.onmouseup = null;
}
},
findParentNodeId(target) {
var parentNodeList = [];
parentNodeList.push(target);
while(target.parentNode) {
parentNodeList.unshift(target.parentNode);
target = target.parentNode;
}
if(parentNodeList.length > 0) {
for(let i = 0; i < parentNodeList.length; i++) {
if(parentNodeList[i].id === 'dialogBoxDrag') {
return parentNodeList[i];
}
}
}
return null;
},
},
watch: {
dialoShow(nv,ov) {
if(nv) {
this.setHeight();
}
if(!ov && nv){
this.resetDomScrollHeight();
}
},
},
computed: {
dis() {
return this.$store.state.disabledBtn;
}
}
}
</script>
<style scoped>
.dialogBox{
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0,0,0,0.3);
z-index: 1000;
}
.conte{
background: #fff;
position: fixed;
top: 12%;
left: 35%;
border-radius:16px;
height: 80%;
overflow: hidden;
min-height: 280px;
min-width: 360px;
}
.title{
width: 100%;
/* padding: 14px 0; */
line-height: 40px;
border-bottom: 1px solid #EEEEEE;
}
.line{
width: 4px;
height:20px ;
display: inline-block;
background: #118ca1;
background: #32cecb;
vertical-align: middle;
margin-left: 26px;
margin-right: 10px;
}
.text{
margin-left: 22px;
font-family: PingFangSC-Semibold;
font-size: 16px;
color: #118ca1;
color: rgba(0,0,0,0.85);
vertical-align: middle;
font-weight: 600;
}
.contentBox{
margin: 16px 0;
/* padding-bottom: 40px; */
/* max-height: 555px; */
overflow-x: hidden;
overflow-y: auto;
height: calc(100% - 110px);
}
/* .contentBox::-webkit-scrollbar{
opacity: 0;
} */
.contentBox::-webkit-scrollbar{
/* opacity: 0; */
width: 6px;
min-height: 20px;
background: #e3e3e3;
}
.contentBox::-webkit-scrollbar-thumb {
/* //滚动条里面小方块/ */
border-radius: 10px;
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: #ccc;
}
.mar{
margin: 0 28px;
margin-left: 32px;
font-size: 14px;
}
.foot{
overflow: hidden;
padding: 10px 0;
position: absolute;
bottom: 0px;;
width:100%;
border-top: 1px solid #EEEEEE;
}
.btnGround{
float: right;
margin-right: 50px;
}
.buttons{
padding: 10px 16px;
display: inline-block;
cursor: pointer;
background: #fff;
}
.cancal{
border: 1px solid #C0C4CC;
border-radius: 4px;
margin-right: 10px;
}
.save{
background: #1D82FA;
border-radius: 4px;
color: #fff;
}
.closeIcon{
position:absolute;
top:10px;
right:14px;
color:#C0C4CC;
cursor:pointer;
font-size:18px;
}
.footDesc{
margin-right: 16px;
}
</style>