You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							197 lines
						
					
					
						
							4.2 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							197 lines
						
					
					
						
							4.2 KiB
						
					
					
				| <template> | |
|   <Teleport> | |
|     <Transition name="fade"> | |
|       <div :class="['mask-layer', { 'none-mask': noneMask }]" v-if="modelVisible"> | |
|         <BackgroundClip class='dialog' | |
|           clipPath="polygon(calc(100% - var(--clip-width)) 0, 100% var(--clip-width), 100% 100%, var(--clip-width) 100%, 0 calc(100% - var(--clip-width)), 0 0)" | |
|           borderColor="linear-gradient(180deg, rgba(78, 174, 204, .9), rgba(78, 174, 204, 0))" | |
|           bgColor="linear-gradient(180deg, rgba(14, 69, 92, 0.9) 0%, rgba(20, 89, 119, 0.9) 100%)" ref="DialogContentRef"> | |
|           <div class="dialog-title"> | |
|             <img class="title-icon" src="@screen/images/dialog/title-icon.svg" /> | |
|             <span>{{ title }}</span> | |
|             <img class="icon-close" @click.stop="modelVisible = false" src="@screen/images/dialog/icon-close.svg" /> | |
|           </div> | |
| 
 | |
|           <div class="dialog-content"> | |
|             <slot /> | |
|           </div> | |
| 
 | |
|           <img class="bottom-right" src="@screen/images/dialog/right-bottom.svg"> | |
| 
 | |
|           <div class="footer" v-if="$slots.footer"> | |
|             <slot name="footer"></slot> | |
|           </div> | |
|         </BackgroundClip> | |
|       </div> | |
|     </Transition> | |
|   </Teleport> | |
| </template> | |
| 
 | |
| <script> | |
| import Teleport from '../Teleport.vue'; | |
| import BackgroundClip from "@screen/components/Decorations/BackgroundClip.vue"; | |
| import { moveable, stopPropagation } from "./utils" | |
| 
 | |
| export default { | |
|   components: { | |
|     Teleport, | |
|     BackgroundClip | |
|   }, | |
|   model: { | |
|     prop: 'visible', | |
|     event: "update:value" | |
|   }, | |
|   name: 'Dialog', | |
|   props: { | |
|     title: { | |
|       type: String | |
|     }, | |
|     visible: Boolean, | |
|     noneMask: { | |
|       type: Boolean, | |
|       default: false | |
|     } | |
|   }, | |
|   watch: { | |
|     visible: { | |
|       deep: true, | |
|       handler(bool) { | |
|         this.$nextTick(() => { | |
|           if (!bool) return this.destroyMoveable?.() | |
| 
 | |
|           const container = this.$refs.DialogContentRef.$el; | |
| 
 | |
|           this.destroyMoveable = moveable(container, { target: container.querySelector(".dialog-title") }); | |
| 
 | |
|           stopPropagation(container.querySelector(".dialog-title").lastChild) | |
| 
 | |
|           this.$once("hook:beforeDestroy", () => this.destroyMoveable?.()); | |
|         }) | |
|       } | |
|     } | |
|   }, | |
|   computed: { | |
|     modelVisible: { | |
|       get() { | |
|         return this.visible | |
|       }, | |
|       set(val) { | |
|         this.$emit('update:value', val) | |
|       } | |
|     } | |
|   }, | |
|   beforeDestroy() { | |
|     this.modelVisible = false; | |
|   }, | |
| } | |
| </script> | |
| 
 | |
| <style lang='scss' scoped> | |
| .mask-layer { | |
|   position: fixed; | |
|   top: 0; | |
|   width: 100%; | |
|   height: 100%; | |
|   background: rgba(0, 0, 0, .36); | |
|   border-radius: 0px 0px 0px 0px; | |
|   z-index: 100; | |
|   display: flex; | |
|   align-items: center; | |
|   justify-content: center; | |
| 
 | |
|   --border-width: 1px; | |
|   --clip-width-num: 24; | |
|   --clip-width: calc(var(--clip-width-num) * 1px); | |
| } | |
| 
 | |
| .none-mask { | |
|   background: rgba(0, 0, 0, 0); | |
|   pointer-events: none; | |
| } | |
| 
 | |
| .fade-enter-active, | |
| .fade-leave-active { | |
|   transition: opacity .24s; | |
| } | |
| 
 | |
| .fade-enter, | |
| .fade-leave-to { | |
|   opacity: 0; | |
| } | |
| 
 | |
| .dialog { | |
|   max-width: 72vw; | |
|   opacity: 1; | |
|   background-clip: padding-box; | |
|   position: relative; | |
|   box-sizing: border-box; | |
|   margin: calc(var(--border-width) / 2); | |
| 
 | |
|   pointer-events: all; | |
| 
 | |
|   .dialog-title { | |
|     position: relative; | |
|     width: calc(100% - 2px); | |
|     height: 51px; | |
|     display: flex; | |
|     padding-top: 3px; | |
|     align-items: center; | |
|     justify-content: space-between; | |
|     background: linear-gradient(90deg, #267494 0%, rgba(38, 116, 148, 0) 100%); | |
|     font-size: 19px; | |
|     font-family: PingFang SC, PingFang SC; | |
|     font-weight: 500; | |
|     color: #3de8ff; | |
| 
 | |
|     .title-icon { | |
|       position: absolute; | |
|       top: -1px; | |
|       left: -1px; | |
|       height: 6px; | |
|     } | |
| 
 | |
|     .icon-close { | |
|       cursor: pointer; | |
|       margin-right: 21px; | |
|     } | |
| 
 | |
|     span { | |
|       margin-left: 20px; | |
|       height: 48px; | |
|       display: flex; | |
|       align-items: center; | |
|     } | |
|   } | |
| 
 | |
|   .dialog-content { | |
|     padding: 9px 21px 27px 21px; | |
|     max-height: 90vh; | |
|     overflow-y: auto; | |
|   } | |
| 
 | |
|   .bottom-right { | |
|     position: absolute; | |
|     right: 0; | |
|     bottom: 0; | |
|   } | |
| 
 | |
|   .footer { | |
|     display: flex; | |
|     align-items: center; | |
|     gap: 9px; | |
|     width: 100%; | |
|     justify-content: flex-end; | |
|     margin-bottom: 21px; | |
|     padding: 0 27px; | |
| 
 | |
|     ::v-deep { | |
|       >div { | |
|         min-width: 96px; | |
|       } | |
|     } | |
| 
 | |
|     // padding: 21px 36px; | |
|     // padding-top: 9px; | |
|   } | |
| } | |
| </style>
 | |
| 
 |