 zq
					
					5 months ago
						zq
					
					5 months ago
					
				
				 10 changed files with 12544 additions and 14854 deletions
			
			
		| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 1.4 KiB | 
| After Width: | Height: | Size: 1.6 KiB | 
| @ -0,0 +1,170 @@ | |||
| <template> | |||
|   <transition name="fade"> | |||
|     <div v-if="visible" class="custom-message" :class="[type, position]"> | |||
|       <img v-if="showImage" :src="imageUrl" class="message-image" /> | |||
|       <i v-else :class="iconClass"></i> | |||
|       <span class="message-content">{{ message }}</span> | |||
|     </div> | |||
|   </transition> | |||
| </template> | |||
| 
 | |||
| <script> | |||
| export default { | |||
|   name: 'CustomMessage', | |||
|   props: { | |||
|     type: { | |||
|       type: String, | |||
|       default: 'info', | |||
|       validator: value => ['success', 'warning', 'error', 'info'].includes(value) | |||
|     }, | |||
|     message: { | |||
|       type: String, | |||
|       required: true | |||
|     }, | |||
|     duration: { | |||
|       type: Number, | |||
|       default: 3000 | |||
|     }, | |||
|     position: { | |||
|       type: String, | |||
|       default: 'top-center', | |||
|       validator: value => ['top-center', 'top-right', 'top-left', 'bottom-center', 'bottom-right', 'bottom-left'].includes(value) | |||
|     }, | |||
|     showImage: { | |||
|       type: Boolean, | |||
|       default: false | |||
|     }, | |||
|     imageUrl: { | |||
|       type: String, | |||
|       default: '' | |||
|     }, | |||
|     iconClass: { | |||
|       type: String, | |||
|       default: '' | |||
|     } | |||
|   }, | |||
|   data() { | |||
|     return { | |||
|       visible: false | |||
|     } | |||
|   }, | |||
|   mounted() { | |||
|     this.visible = true | |||
|     this.startTimer() | |||
|   }, | |||
|   methods: { | |||
|     startTimer() { | |||
|       if (this.duration > 0) { | |||
|         setTimeout(() => { | |||
|           this.close() | |||
|         }, this.duration) | |||
|       } | |||
|     }, | |||
|     close() { | |||
|       this.visible = false | |||
|       setTimeout(() => { | |||
|         this.$destroy() | |||
|         this.$el.parentNode.removeChild(this.$el) | |||
|       }, 300) | |||
|     } | |||
|   } | |||
| } | |||
| </script> | |||
| 
 | |||
| <style scoped> | |||
| .custom-message { | |||
|   position: fixed; | |||
|   z-index: 9999; | |||
|   display: flex; | |||
|   align-items: center; | |||
|   padding: 14px 21px; | |||
|   transition: all 0.3s; | |||
|   font-size: 14px; | |||
|   font-weight: normal; | |||
|   line-height: normal; | |||
|   letter-spacing: 0.08em; | |||
|   color: #626573; | |||
|   border-radius: 4px; | |||
|   background: #FFFFFF; | |||
|   /* 阴影/低阴影 */ | |||
|   box-shadow: 0px 3px 8px 0px rgba(0, 0, 0, 0.16); | |||
| } | |||
| 
 | |||
| /* 位置样式 */ | |||
| .top-center { | |||
|   top: 20px; | |||
|   left: 50%; | |||
|   transform: translateX(-50%); | |||
| } | |||
| .top-right { | |||
|   top: 20px; | |||
|   right: 20px; | |||
| } | |||
| .top-left { | |||
|   top: 20px; | |||
|   left: 20px; | |||
| } | |||
| .bottom-center { | |||
|   bottom: 20px; | |||
|   left: 50%; | |||
|   transform: translateX(-50%); | |||
| } | |||
| .bottom-right { | |||
|   bottom: 20px; | |||
|   right: 20px; | |||
| } | |||
| .bottom-left { | |||
|   bottom: 20px; | |||
|   left: 20px; | |||
| } | |||
| 
 | |||
| /* 类型样式 */ | |||
| /* .success { | |||
|   background-color: #f6ffed; | |||
|   border: 1px solid #b7eb8f; | |||
|   color: #52c41a; | |||
| } | |||
| .info { | |||
|   background-color: #e6f7ff; | |||
|   border: 1px solid #91d5ff; | |||
|   color: #1890ff; | |||
| } | |||
| .warning { | |||
|   background-color: #fffbe6; | |||
|   border: 1px solid #ffe58f; | |||
|   color: #faad14; | |||
| } | |||
| .error { | |||
|   background-color: #fff2f0; | |||
|   border: 1px solid #ffccc7; | |||
|   color: #f5222d; | |||
| } */ | |||
| 
 | |||
| .message-image { | |||
|   width: 18px; | |||
|   height: 18px; | |||
|   margin-right: 10px; | |||
| } | |||
| 
 | |||
| /* 动画效果 */ | |||
| .fade-enter-active, .fade-leave-active { | |||
|   transition: opacity 0.3s, transform 0.3s; | |||
| } | |||
| .fade-enter, .fade-leave-to { | |||
|   opacity: 0; | |||
| } | |||
| .fade-enter.top-center, .fade-leave-to.top-center { | |||
|   transform: translate(-50%, -20px); | |||
| } | |||
| .fade-enter.top-right, .fade-leave-to.top-right, | |||
| .fade-enter.top-left, .fade-leave-to.top-left { | |||
|   transform: translateY(-20px); | |||
| } | |||
| .fade-enter.bottom-center, .fade-leave-to.bottom-center { | |||
|   transform: translate(-50%, 20px); | |||
| } | |||
| .fade-enter.bottom-right, .fade-leave-to.bottom-right, | |||
| .fade-enter.bottom-left, .fade-leave-to.bottom-left { | |||
|   transform: translateY(20px); | |||
| } | |||
| </style> | |||
| @ -0,0 +1,94 @@ | |||
| import Vue from 'vue' | |||
| import GuipMessage from './GuipMessage.vue' | |||
| 
 | |||
| // 默认图标配置
 | |||
| const defaultIcons = { | |||
|   success: 'icon-success', // 替换为你的图标类名
 | |||
|   info: 'icon-info', | |||
|   warning: 'icon-warning', | |||
|   error: 'icon-error' | |||
| } | |||
| 
 | |||
| // 默认图片配置
 | |||
| const defaultImages = { | |||
|   success: require('@/assets/message_Success.png'), | |||
|   info: require('@/assets/message_Warning.png'), | |||
|   warning: require('@/assets/message_Warning.png'), | |||
|   error: require('@/assets/message_error.png') | |||
| } | |||
| const MessageConstructor = Vue.extend(GuipMessage) | |||
| 
 | |||
| // let messageInstance = null
 | |||
| let messageQueue = [] | |||
| 
 | |||
| function showMessage(options) { | |||
|   if (typeof options === 'string') { | |||
|     options = { | |||
|       message: options | |||
|     } | |||
|   } | |||
| 
 | |||
|   // 合并默认配置
 | |||
|   const config = { | |||
|     type: 'info', | |||
|     duration: 3000, | |||
|     position: 'top-center', | |||
|     showImage: true, | |||
|     ...options | |||
|   } | |||
| 
 | |||
|   // 设置图标或图片
 | |||
|   if (config.showImage) { | |||
|     config.imageUrl = options.imageUrl || defaultImages[config.type] | |||
|   } else { | |||
|     config.iconClass = options.iconClass || defaultIcons[config.type] | |||
|   } | |||
| 
 | |||
|   // 创建实例
 | |||
|   const instance = new MessageConstructor({ | |||
|     propsData: config | |||
|   }) | |||
| 
 | |||
|   // 挂载到DOM
 | |||
|   instance.$mount() | |||
|   document.body.appendChild(instance.$el) | |||
| 
 | |||
|   // 添加到队列
 | |||
|   messageQueue.push(instance) | |||
| 
 | |||
|   // 返回关闭方法
 | |||
|   return { | |||
|     close: () => instance.close() | |||
|   } | |||
| } | |||
| 
 | |||
| function install(Vue, options = {}) { | |||
|   // 合并默认配置
 | |||
|   if (options.icons) { | |||
|     Object.assign(defaultIcons, options.icons) | |||
|   } | |||
|   if (options.images) { | |||
|     Object.assign(defaultImages, options.images) | |||
|   } | |||
| 
 | |||
|   // 添加全局方法
 | |||
|   Vue.prototype.$Message = showMessage | |||
|   Vue.prototype.$Message.closeAll = () => { | |||
|     messageQueue.forEach(instance => instance.close()) | |||
|     messageQueue = [] | |||
|   } | |||
| 
 | |||
|   // 添加快捷方法
 | |||
|   const types = ['success', 'info', 'warning', 'error'] | |||
|   types.forEach(type => { | |||
|     Vue.prototype.$Message[type] = (message, options = {}) => { | |||
|       return showMessage({ | |||
|         message, | |||
|         type, | |||
|         ...options | |||
|       }) | |||
|     } | |||
|   }) | |||
| } | |||
| 
 | |||
| export default { install } | |||
								
									
										File diff suppressed because it is too large
									
								
							
						
					
					Loading…
					
					
				
		Reference in new issue