| <template> | 
|   <view | 
|     v-if="visibleSync" | 
|     class="tn-tips-class tn-tips" | 
|     :class="[tipsClass]" | 
|     :style="[tipsStyle]" | 
|   > | 
|     <view | 
|       class="tn-tips__content" | 
|       :class="[ | 
|         backgroundColorClass, | 
|         fontColorClass | 
|       ]" | 
|       :style="{ | 
|         backgroundColor: backgroundColorStyle, | 
|         color: fontColorStyle | 
|       }" | 
|     >{{ msg }}</view> | 
|   </view> | 
| </template> | 
|   | 
| <script> | 
|    | 
|   export default { | 
|     name: 'tn-tips', | 
|     props: { | 
|       // 层级 | 
|       zIndex: { | 
|         type: Number, | 
|         default: 0 | 
|       }, | 
|       // 提示框显示位置 top center bottom | 
|       position: { | 
|         type: String, | 
|         default: 'top' | 
|       }, | 
|       // 当位置设置为top的时候,设置距离顶部的距离 | 
|       top: { | 
|         type: Number, | 
|         default: 0 | 
|       } | 
|     }, | 
|     computed: { | 
|       tipsClass() { | 
|         let clazz = '' | 
|         switch (this.position) { | 
|           case 'top': | 
|             clazz += ' tn-tips--top' | 
|             break | 
|           case 'center': | 
|             clazz += ' tn-tips--center' | 
|             break | 
|           case 'bottom': | 
|             clazz += ' tn-tips--bottom' | 
|             break | 
|           default: | 
|             clazz += ' tn-tips--top' | 
|         } | 
|         if (this.showTips) { | 
|           clazz += ' tn-tips--show' | 
|         } | 
|          | 
|         return clazz | 
|       }, | 
|       tipsStyle() { | 
|         let style = {} | 
|         if ((this.position === 'top' || this.position === '') && this.top) { | 
|           style.top = this.top + 'px' | 
|         } | 
|         style.zIndex = (this.zIndex ? this.zIndex : this.$t.zIndex.tips) + 1 | 
|          | 
|         return style | 
|       }, | 
|       backgroundColorStyle() { | 
|         return this.$t.color.getBackgroundColorStyle(this.backgroundColor) | 
|       }, | 
|       backgroundColorClass() { | 
|         return this.$t.color.getBackgroundColorInternalClass(this.backgroundColor) | 
|       }, | 
|       fontColorStyle() { | 
|         return this.$t.color.getFontColorStyle(this.fontColor) | 
|       }, | 
|       fontColorClass() { | 
|         return this.$t.color.getFontColorInternalClass(this.fontColor) | 
|       }, | 
|     }, | 
|     data() { | 
|       return { | 
|         //关闭提示框定时器 | 
|         timer: null, | 
|         // 是否渲染组件 | 
|         visibleSync: false, | 
|         // 是否显示内容 | 
|         showTips: false, | 
|         // 提示信息 | 
|         msg: '', | 
|         // 背景颜色 | 
|         backgroundColor: '', | 
|         // 字体颜色 | 
|         fontColor: '' | 
|       } | 
|     }, | 
|     methods: { | 
|       show(options = {}) { | 
|         const { | 
|           duration = 2000, | 
|           msg = '', | 
|           backgroundColor = '', | 
|           fontColor = '' | 
|         } = options | 
|          | 
|         if (this.timer !== null) clearTimeout(this.timer) | 
|          | 
|         // 如果没有设置内容则不弹出 | 
|         if (!msg) { | 
|           this._clearOptions() | 
|           this.$emit('close') | 
|           return | 
|         } | 
|          | 
|         this.msg = msg | 
|         this.backgroundColor = backgroundColor || '#01BEFF' | 
|         this.fontColor = fontColor || '#FFFFFF' | 
|          | 
|         this.change('visibleSync', 'showTips', true) | 
|          | 
|         this.timer = setTimeout(() => { | 
|           clearTimeout(this.timer) | 
|           this.timer = null | 
|           this.change('showTips', 'visibleSync', false) | 
|         }, duration) | 
|       }, | 
|        | 
|       // 关闭时先通过动画隐藏弹窗和遮罩,再移除整个组件 | 
|       // 打开时,先渲染组件,延时一定时间再让遮罩和弹窗的动画起作用 | 
|       change(param1, param2, status) { | 
|         this[param1] = status | 
|         if (status) { | 
|           // #ifdef H5 || MP | 
|           this.timer = setTimeout(() => { | 
|             this[param2] = status | 
|             this.$emit(status ? 'open' : 'close') | 
|           }, 50) | 
|           // #endif | 
|           // #ifndef H5 || MP | 
|           this.$nextTick(() => { | 
|             this[param2] = status | 
|             this.$emit(status ? 'open' : 'close') | 
|           }) | 
|           // #endif | 
|         } else { | 
|           this.timer = setTimeout(() => { | 
|             this[param2] = status | 
|             this.$emit(status ? 'open' : 'close') | 
|             this._clearOptions() | 
|           }, 300) | 
|         } | 
|       }, | 
|        | 
|       // 清除传递的参数 | 
|       _clearOptions() { | 
|         this.msg = '' | 
|         this.backgroundColor = '' | 
|         this.fontColor = '' | 
|       }, | 
|     } | 
|   } | 
| </script> | 
|   | 
| <style lang="scss" scoped> | 
|    | 
|   /*注意问题: | 
|    1、fixed 元素宽度无法自适应,所以增加了子元素 | 
|    2、fixed 和 display冲突导致动画效果消失,暂时使用visibility替代 | 
|   */ | 
|   .tn-tips { | 
|     height: auto; | 
|     position: fixed; | 
|     box-sizing: border-box; | 
|     display: flex; | 
|     align-items: center; | 
|     justify-content: center; | 
|     transition: all 0.3s ease-in-out; | 
|     opacity: 0; | 
|      | 
|     &__content { | 
|       word-wrap: break-word; | 
|       word-break: break-all; | 
|       width: 100%; | 
|       height: auto; | 
|       text-align: center; | 
|       background-color: rgba(0, 0, 0, 0.7); | 
|       color: #FFFFFF; | 
|     } | 
|      | 
|     &--top { | 
|       width: 100% !important; | 
|       /* padding: 18rpx 30rpx; */ | 
|       top: 0; | 
|       left: 0; | 
|       transform: translateY(-100%) translateZ(0); | 
|       word-break: break-all; | 
|     } | 
|      | 
|     &--center { | 
|       left: 50%; | 
|       top: 50%; | 
|       transform: translate(-50%, -50%); | 
|     } | 
|      | 
|     &--bottom { | 
|       bottom: 120rpx; | 
|       left: 50%; | 
|       transform: translateX(-50%); | 
|     } | 
|      | 
|     &--center, &--bottom { | 
|       .content { | 
|         border-radius: 8rpx; | 
|         padding: 0; | 
|       } | 
|     } | 
|      | 
|     &--center, &--bottom { | 
|       .tn-tips__content { | 
|         padding: 18rpx 30rpx !important; | 
|       } | 
|     } | 
|      | 
|     &--show { | 
|       opacity: 1; | 
|        | 
|       &.tn-tips--top { | 
|         transform: translateY(0) translateZ(0) !important; | 
|       } | 
|     } | 
|      | 
|   } | 
|    | 
| </style> |