yunshangxie/tuniao-ui/components/tn-toast/tn-toast.vue

228 lines
4.9 KiB
Vue
Raw Normal View History

2023-12-25 17:56:30 +08:00
<template>
<view v-if="visible">
<view
class="tn-toast-class tn-toast"
:class="[toastClass]"
:style="[toastStyle]"
>
<image v-if="image" :src="image" class="tn-toast__img" :class="{'tn-margin-bottom-sm': title || content}"></image>
<view v-if="icon" class="tn-toast__icon">
<view :class="['tn-icon-' + icon]"></view>
</view>
<view
v-if="title"
class="tn-toast__text"
:class="[haveIcon || haveContent ? '' : 'tn-toast--unicon']"
>{{ title }}</view>
<view
v-if="haveContent"
class="tn-toast__text tn-toast__content"
>{{ content }}</view>
</view>
<view class="tn-toast__mask" :class="[visible ? 'tn-toast__mask--show' : '']" :style="[maskStyle]"></view>
</view>
</template>
<script>
export default {
name: 'tn-toast',
props: {
// 层级
zIndex: {
type: Number,
default: 0
}
},
computed: {
toastClass() {
let clazz = ''
if (this.visible) {
clazz += ' tn-toast--show'
}
if (this.content) {
clazz += ' tn-toast--padding'
}
if (this.icon || this.image) {
clazz += ' tn-toast--unicon'
}
return clazz
},
toastStyle() {
let style = {}
style.width = 'auto'
if (this.icon || this.image) {
// style.width = this.content ? '420rpx' : '360rpx'
}
style.zIndex = this.zIndex ? this.zIndex : this.$tn.zIndex.toast
return style
},
maskStyle() {
let style = {}
const zIndex = this.zIndex ? this.zIndex : this.$tn.zIndex.toast
style.zIndex = zIndex - 1
return style
},
haveIcon() {
return this.icon || this.image
},
haveContent() {
return this.content
}
},
data() {
return {
// 自动关闭定时器
timer: null,
// 是否显示
visible: false,
// 显示的标题
title: '操作成功',
// 显示的内容
content: "",
// 是否显示icon (icon库的图标)
icon: '',
// 是否显示图片 (图片地址)
image: ''
}
},
methods: {
// 显示弹框
show(options = {}) {
const {
duration = 2000,
title = '',
content = '',
icon = '',
image = ''
} = options
if (this.timer !== null ){
clearTimeout(this.timer)
}
// 如果没有设置任何内容就不弹出
if (!icon && !image && !title && !content) {
this._clearOptions()
this.$emit('closed')
return
}
this.visible = true
this.title = title
this.content = content
this.icon = icon
if (!icon) {
this.image = image
}
this.timer = setTimeout(() => {
this.visible = false
clearTimeout(this.timer)
this.timer = null
this._clearOptions()
this.$emit('closed')
}, duration)
},
// 清除传递的参数
_clearOptions() {
this.title = ''
this.content = ''
this.icon = ''
this.image = ''
}
}
}
</script>
<style lang="scss" scoped>
.tn-toast {
height: auto;
background-color: rgba(0, 0, 0, 0.4);
border-radius: 10rpx;
opacity: 0;
position: fixed;
left: 50%;
top: 48%;
transform: translate(-50%, -50%);
transition: 0.3 ease-in-out;
transition-property: opacity, visibility;
display: flex;
align-items: center;
flex-direction: column;
padding: 20rpx 20rpx 20rpx 20rpx;
box-sizing: border-box;
&--show {
opacity: 1;
&.tn-toast--padding {
padding-top: 50rpx !important;
padding-bottom: 50rpx !important;
}
&.tn-toast--unicon {
padding: 20rpx 20rpx 20rpx 20rpx !important;
}
}
&__img {
width: 120rpx;
height: 120rpx;
display: block;
}
&__text {
font-size: 28rpx;
line-height: 28rpx;
color: #ffffff;
text-align: center;
}
&__icon {
color: #FFFFFF;
font-size: 64rpx;
}
&__content {
padding-top: 10rpx;
font-size: 24rpx !important;
}
&--unicon {
padding: 0;
word-break: break-all;
}
&--padding {
padding: 10rpx;
}
&__mask {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
right: 0;
border: 0;
background-color: rgba(0, 0, 0, 0);
transition: 0.3s ease-in-out;
transition-property: opacity;
opacity: 0;
&--show {
height: 100%;
opacity: 1;
}
}
}
</style>