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', | ||||||
|   props: { |   model: { | ||||||
|     visible: { |     prop: "visible", | ||||||
|       type: Boolean, |     event: "input" | ||||||
|       default: false |   }, | ||||||
|     }, |   props: { | ||||||
|     title: { |     visible: Boolean, | ||||||
|       type: String, |     title: {type: String, default: ''}, | ||||||
|       default: '' |     customFooter: Boolean, | ||||||
|     }, |     isDrag: {type: Boolean, default: true} | ||||||
|     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,12 +122,9 @@ 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; | ||||||
|  |     font-size: 16px; | ||||||
|     h2 { |     font-weight: 700; | ||||||
|       font-size: 16px; |  | ||||||
|       font-weight: 700; |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .el-dialog__footer { |   .el-dialog__footer { | ||||||
| @@ -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