Dialog升级,支持可拖动,支持v-model控制显隐
This commit is contained in:
@@ -1,112 +1,103 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="ai-dialog__wrapper">
|
<section class="ai-dialog__wrapper">
|
||||||
<el-dialog
|
<el-dialog custom-class="ai-dialog" v-on="$listeners" v-bind="$attrs" :visible.sync="dialog">
|
||||||
custom-class="ai-dialog"
|
<div class="ai-dialog__header fill" slot="title" v-text="title"/>
|
||||||
v-on="$listeners"
|
<div class="ai-dialog__content">
|
||||||
v-if="isEmpty"
|
<div class="ai-dialog__content--wrapper pad-r8">
|
||||||
:close-on-click-modal="closeOnClickModal"
|
<slot/>
|
||||||
v-bind="$attrs"
|
|
||||||
:destroy-on-close="destroyOnClose"
|
|
||||||
:visible.sync="dialogVisible">
|
|
||||||
<div class="ai-dialog__header" slot="title">
|
|
||||||
<h2>{{ title }}</h2>
|
|
||||||
</div>
|
|
||||||
<div class="ai-dialog__content" :style="{'max-height': isScrool ? '500px' : 'auto'}">
|
|
||||||
<div class="ai-dialog__content--wrapper" :style="{'padding-right': isScrool ? '8px' : '0'}">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="customFooter" slot="footer">
|
<template v-if="customFooter" slot="footer">
|
||||||
<slot name="footer"></slot>
|
<slot name="footer"/>
|
||||||
</template>
|
</template>
|
||||||
<div v-else class="dialog-footer" slot="footer">
|
<div v-else class="dialog-footer" slot="footer">
|
||||||
<el-button @click="onCancel">取消</el-button>
|
<el-button @click="onCancel">取消</el-button>
|
||||||
<el-button @click="onConfirm" type="primary" style="width: 92px;">确认</el-button>
|
<el-button @click="onConfirm" type="primary">确认</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AiDialog',
|
name: 'AiDialog',
|
||||||
|
model: {
|
||||||
|
prop: "visible",
|
||||||
|
event: "input"
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
visible: {
|
visible: Boolean,
|
||||||
type: Boolean,
|
title: {type: String, default: ''},
|
||||||
default: false
|
customFooter: Boolean,
|
||||||
|
isDrag: {type: Boolean, default: true}
|
||||||
},
|
},
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
customFooter: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
'close-on-click-modal': {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
destroyOnClose: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dialogVisible: false,
|
dialog: false,
|
||||||
isScrool: true,
|
|
||||||
isEmpty: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
visible: {
|
dialog(v) {
|
||||||
handler(val) {
|
this.visible != v && this.$emit("input", v)
|
||||||
this.dialogVisible = val
|
},
|
||||||
|
visible(v) {
|
||||||
// if (val) {
|
this.dialog = v
|
||||||
// this.$nextTick(() => {
|
|
||||||
// setTimeout(() => {
|
|
||||||
// this.isScrool = document.querySelector('.ai-dialog__content') && document.querySelector('.ai-dialog__content').clientHeight >= 500
|
|
||||||
// }, 100)
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (this.destroyOnClose && !val) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.isEmpty = false
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.isEmpty = true
|
|
||||||
}, 50)
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onCancel() {
|
onCancel() {
|
||||||
this.$emit('update:visible', false)
|
this.dialog = false
|
||||||
this.$emit('onCancel')
|
|
||||||
this.$emit('cancel')
|
this.$emit('cancel')
|
||||||
},
|
},
|
||||||
|
|
||||||
onConfirm() {
|
onConfirm() {
|
||||||
this.$emit('onConfirm')
|
|
||||||
this.$emit('confirm')
|
this.$emit('confirm')
|
||||||
|
},
|
||||||
|
initDraggable() {
|
||||||
|
const dialogHeaderEl = this.$el.querySelector('.el-dialog__header')
|
||||||
|
const dragDom = this.$el.querySelector('.el-dialog')
|
||||||
|
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
|
||||||
|
|
||||||
|
dialogHeaderEl.onmousedown = e => {
|
||||||
|
console.log(e)
|
||||||
|
// 鼠标按下,获得鼠标在盒子内的坐标(鼠标在页面的坐标 减去 对话框的坐标),计算当前元素距离可视区的距离
|
||||||
|
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
||||||
|
const disY = e.clientY - dialogHeaderEl.offsetTop
|
||||||
|
// 获取到的值带px 正则匹配替换
|
||||||
|
let styL, styT
|
||||||
|
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
|
||||||
|
if (sty.left.includes('%')) {
|
||||||
|
styL = +document.body.clientWidth * (+sty.left.replace(/%/g, '') / 100)
|
||||||
|
styT = +document.body.clientHeight * (+sty.top.replace(/%/g, '') / 100)
|
||||||
|
} else {
|
||||||
|
styL = +sty.left.replace(/px/g, '')
|
||||||
|
styT = +sty.top.replace(/px/g, '')
|
||||||
}
|
}
|
||||||
|
document.onmousemove = function (e) {
|
||||||
|
// 鼠标移动,用鼠标在页面的坐标 减去 鼠标在盒子里的坐标,获得模态框的left和top值
|
||||||
|
// 通过事件委托,计算移动的距离
|
||||||
|
const l = e.clientX - disX
|
||||||
|
const t = e.clientY - disY
|
||||||
|
// 移动当前元素
|
||||||
|
dragDom.style.left = `${l + styL}px`
|
||||||
|
dragDom.style.top = `${t + styT}px`
|
||||||
|
}
|
||||||
|
document.onmouseup = function () {
|
||||||
|
// 鼠标弹起,移除鼠标移动事件
|
||||||
|
document.onmousemove = null
|
||||||
|
document.onmouseup = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.isDrag && this.initDraggable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.ai-dialog {
|
.ai-dialog {
|
||||||
margin: 0 !important;
|
margin: unset !important;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
@@ -118,11 +109,12 @@ export default {
|
|||||||
.ai-dialog__content {
|
.ai-dialog__content {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
|
max-height: 500px;
|
||||||
|
|
||||||
.ai-dialog__content--wrapper {
|
.ai-dialog__content--wrapper {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: overlay;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,13 +122,10 @@ export default {
|
|||||||
height: 48px;
|
height: 48px;
|
||||||
line-height: 48px;
|
line-height: 48px;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
border-bottom: 1px solid #eee;
|
cursor: move;
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.el-dialog__footer {
|
.el-dialog__footer {
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
@@ -155,11 +144,17 @@ export default {
|
|||||||
|
|
||||||
.el-dialog__header {
|
.el-dialog__header {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__headerbtn {
|
.el-dialog__headerbtn {
|
||||||
top: 24px;
|
position: relative;
|
||||||
transform: translateY(-50%);
|
flex-shrink: 0;
|
||||||
|
top: unset;
|
||||||
|
right: unset;
|
||||||
|
margin: 0 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user