tn-toast.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <template>
  2. <view v-if="visible">
  3. <view
  4. class="tn-toast-class tn-toast"
  5. :class="[toastClass]"
  6. :style="[toastStyle]"
  7. >
  8. <image v-if="image" :src="image" class="tn-toast__img" :class="{'tn-margin-bottom-sm': title || content}"></image>
  9. <view v-if="icon" class="tn-toast__icon">
  10. <view :class="['tn-icon-' + icon]"></view>
  11. </view>
  12. <view
  13. v-if="title"
  14. class="tn-toast__text"
  15. :class="[haveIcon || haveContent ? '' : 'tn-toast--unicon']"
  16. >{{ title }}</view>
  17. <view
  18. v-if="haveContent"
  19. class="tn-toast__text tn-toast__content"
  20. >{{ content }}</view>
  21. </view>
  22. <view class="tn-toast__mask" :class="[visible ? 'tn-toast__mask--show' : '']" :style="[maskStyle]"></view>
  23. </view>
  24. </template>
  25. <script>
  26. export default {
  27. name: 'tn-toast',
  28. props: {
  29. // 层级
  30. zIndex: {
  31. type: Number,
  32. default: 0
  33. }
  34. },
  35. computed: {
  36. toastClass() {
  37. let clazz = ''
  38. if (this.visible) {
  39. clazz += ' tn-toast--show'
  40. }
  41. if (this.content) {
  42. clazz += ' tn-toast--padding'
  43. }
  44. if (this.icon || this.image) {
  45. clazz += ' tn-toast--unicon'
  46. }
  47. return clazz
  48. },
  49. toastStyle() {
  50. let style = {}
  51. style.width = 'auto'
  52. if (this.icon || this.image) {
  53. // style.width = this.content ? '420rpx' : '360rpx'
  54. }
  55. style.zIndex = this.zIndex ? this.zIndex : this.$t.zIndex.toast
  56. return style
  57. },
  58. maskStyle() {
  59. let style = {}
  60. const zIndex = this.zIndex ? this.zIndex : this.$t.zIndex.toast
  61. style.zIndex = zIndex - 1
  62. return style
  63. },
  64. haveIcon() {
  65. return this.icon || this.image
  66. },
  67. haveContent() {
  68. return this.content
  69. }
  70. },
  71. data() {
  72. return {
  73. // 自动关闭定时器
  74. timer: null,
  75. // 是否显示
  76. visible: false,
  77. // 显示的标题
  78. title: '操作成功',
  79. // 显示的内容
  80. content: "",
  81. // 是否显示icon (icon库的图标)
  82. icon: '',
  83. // 是否显示图片 (图片地址)
  84. image: ''
  85. }
  86. },
  87. methods: {
  88. // 显示弹框
  89. show(options = {}) {
  90. const {
  91. duration = 2000,
  92. title = '',
  93. content = '',
  94. icon = '',
  95. image = ''
  96. } = options
  97. if (this.timer !== null ){
  98. clearTimeout(this.timer)
  99. }
  100. // 如果没有设置任何内容就不弹出
  101. if (!icon && !image && !title && !content) {
  102. this._clearOptions()
  103. this.$emit('closed')
  104. return
  105. }
  106. this.visible = true
  107. this.title = title
  108. this.content = content
  109. this.icon = icon
  110. if (!icon) {
  111. this.image = image
  112. }
  113. this.timer = setTimeout(() => {
  114. this.visible = false
  115. clearTimeout(this.timer)
  116. this.timer = null
  117. this._clearOptions()
  118. this.$emit('closed')
  119. }, duration)
  120. },
  121. // 清除传递的参数
  122. _clearOptions() {
  123. this.title = ''
  124. this.content = ''
  125. this.icon = ''
  126. this.image = ''
  127. }
  128. }
  129. }
  130. </script>
  131. <style lang="scss" scoped>
  132. .tn-toast {
  133. height: auto;
  134. background-color: rgba(0, 0, 0, 0.4);
  135. border-radius: 10rpx;
  136. opacity: 0;
  137. position: fixed;
  138. left: 50%;
  139. top: 48%;
  140. transform: translate(-50%, -50%);
  141. transition: 0.3 ease-in-out;
  142. transition-property: opacity, visibility;
  143. display: flex;
  144. align-items: center;
  145. flex-direction: column;
  146. padding: 20rpx 20rpx 20rpx 20rpx;
  147. box-sizing: border-box;
  148. &--show {
  149. opacity: 1;
  150. &.tn-toast--padding {
  151. padding-top: 50rpx !important;
  152. padding-bottom: 50rpx !important;
  153. }
  154. &.tn-toast--unicon {
  155. padding: 20rpx 20rpx 20rpx 20rpx !important;
  156. }
  157. }
  158. &__img {
  159. width: 120rpx;
  160. height: 120rpx;
  161. display: block;
  162. }
  163. &__text {
  164. font-size: 28rpx;
  165. line-height: 28rpx;
  166. color: #ffffff;
  167. text-align: center;
  168. }
  169. &__icon {
  170. color: #FFFFFF;
  171. font-size: 64rpx;
  172. }
  173. &__content {
  174. padding-top: 10rpx;
  175. font-size: 24rpx !important;
  176. }
  177. &--unicon {
  178. padding: 0;
  179. word-break: break-all;
  180. }
  181. &--padding {
  182. padding: 10rpx;
  183. }
  184. &__mask {
  185. width: 100%;
  186. height: 100%;
  187. position: fixed;
  188. top: 0;
  189. left: 0;
  190. right: 0;
  191. border: 0;
  192. background-color: rgba(0, 0, 0, 0);
  193. transition: 0.3s ease-in-out;
  194. transition-property: opacity;
  195. opacity: 0;
  196. &--show {
  197. height: 100%;
  198. opacity: 1;
  199. }
  200. }
  201. }
  202. </style>