<template> 
 | 
    <view class="u-toast"> 
 | 
        <u-overlay 
 | 
            :show="isShow" 
 | 
            :custom-style="overlayStyle" 
 | 
        > 
 | 
            <view 
 | 
                class="u-toast__content" 
 | 
                :style="[contentStyle]" 
 | 
                :class="['u-type-' + tmpConfig.type, (tmpConfig.type === 'loading' || tmpConfig.loading) ?  'u-toast__content--loading' : '']" 
 | 
            > 
 | 
                <u-loading-icon 
 | 
                    v-if="tmpConfig.type === 'loading'" 
 | 
                    mode="circle" 
 | 
                    color="rgb(255, 255, 255)" 
 | 
                    inactiveColor="rgb(120, 120, 120)" 
 | 
                    size="25" 
 | 
                ></u-loading-icon> 
 | 
                <u-icon 
 | 
                    v-else-if="tmpConfig.type !== 'defalut' && iconName" 
 | 
                    :name="iconName" 
 | 
                    size="17" 
 | 
                    :color="tmpConfig.type" 
 | 
                    :customStyle="iconStyle" 
 | 
                ></u-icon> 
 | 
                <u-gap 
 | 
                    v-if="tmpConfig.type === 'loading' || tmpConfig.loading" 
 | 
                    height="12" 
 | 
                    bgColor="transparent" 
 | 
                ></u-gap> 
 | 
                <text 
 | 
                    class="u-toast__content__text" 
 | 
                    :class="['u-toast__content__text--' + tmpConfig.type]" 
 | 
                    style="max-width: 400rpx;" 
 | 
                >{{ tmpConfig.message }}</text> 
 | 
            </view> 
 | 
        </u-overlay> 
 | 
    </view> 
 | 
</template> 
 | 
  
 | 
<script> 
 | 
    /** 
 | 
     * toast 消息提示 
 | 
     * @description 此组件表现形式类似uni的uni.showToastAPI,但也有不同的地方。 
 | 
     * @tutorial https://www.uviewui.com/components/toast.html 
 | 
     * @property {String | Number}    zIndex        toast展示时的zIndex值 (默认 10090 ) 
 | 
     * @property {Boolean}            loading        是否加载中 (默认 false ) 
 | 
     * @property {String | Number}    message        显示的文字内容 
 | 
     * @property {String}            icon        图标,或者绝对路径的图片 
 | 
     * @property {String}            type        主题类型 (默认 default) 
 | 
     * @property {Boolean}            show        是否显示该组件 (默认 false) 
 | 
     * @property {Boolean}            overlay        是否显示透明遮罩,防止点击穿透 (默认 false ) 
 | 
     * @property {String}            position    位置 (默认 'center' ) 
 | 
     * @property {Object}            params        跳转的参数  
 | 
     * @property {String | Number}  duration    展示时间,单位ms (默认 2000 ) 
 | 
     * @property {Boolean}            isTab        是否返回的为tab页面 (默认 false ) 
 | 
     * @property {String}            url            toast消失后是否跳转页面,有则跳转,优先级高于back参数  
 | 
     * @property {Function}            complete    执行完后的回调函数  
 | 
     * @property {Boolean}            back        结束toast是否自动返回上一页 (默认 false ) 
 | 
     * @property {Object}            customStyle    组件的样式,对象形式 
 | 
     * @event {Function} show 显示toast,如需一进入页面就显示toast,请在onReady生命周期调用 
 | 
     * @example <u-toast ref="uToast" /> 
 | 
     */ 
 | 
    export default { 
 | 
        name: 'u-toast', 
 | 
        mixins: [uni.$u.mpMixin, uni.$u.mixin], 
 | 
        data() { 
 | 
            return { 
 | 
                isShow: false, 
 | 
                timer: null, // 定时器 
 | 
                config: { 
 | 
                    message: '', // 显示文本 
 | 
                    type: '', // 主题类型,primary,success,error,warning,black 
 | 
                    duration: 2000, // 显示的时间,毫秒 
 | 
                    icon: true, // 显示的图标 
 | 
                    position: 'center', // toast出现的位置 
 | 
                    complete: null, // 执行完后的回调函数 
 | 
                    overlay: false, // 是否防止触摸穿透 
 | 
                    loading: false, // 是否加载中状态 
 | 
                }, 
 | 
                tmpConfig: {}, // 将用户配置和内置配置合并后的临时配置变量 
 | 
            } 
 | 
        }, 
 | 
        computed: { 
 | 
            iconName() { 
 | 
                // 只有不为none,并且type为error|warning|succes|info时候,才显示图标 
 | 
                if(!this.tmpConfig.icon || this.tmpConfig.icon == 'none') { 
 | 
                    return ''; 
 | 
                } 
 | 
                if (['error', 'warning', 'success', 'primary'].includes(this.tmpConfig.type)) { 
 | 
                    return uni.$u.type2icon(this.tmpConfig.type) 
 | 
                } else { 
 | 
                    return '' 
 | 
                } 
 | 
            }, 
 | 
            overlayStyle() { 
 | 
                const style = { 
 | 
                    justifyContent: 'center', 
 | 
                    alignItems: 'center', 
 | 
                    display: 'flex' 
 | 
                } 
 | 
                // 将遮罩设置为100%透明度,避免出现灰色背景 
 | 
                style.backgroundColor = 'rgba(0, 0, 0, 0)' 
 | 
                return style 
 | 
            }, 
 | 
            iconStyle() { 
 | 
                const style = {} 
 | 
                // 图标需要一个右边距,以跟右边的文字有隔开的距离 
 | 
                style.marginRight = '4px' 
 | 
                // #ifdef APP-NVUE 
 | 
                // iOSAPP下,图标有1px的向下偏移,这里进行修正 
 | 
                if (uni.$u.os() === 'ios') { 
 | 
                    style.marginTop = '-1px' 
 | 
                } 
 | 
                // #endif 
 | 
                return style 
 | 
            }, 
 | 
            loadingIconColor() { 
 | 
                let color = 'rgb(255, 255, 255)' 
 | 
                if (['error', 'warning', 'success', 'primary'].includes(this.tmpConfig.type)) { 
 | 
                    // loading-icon组件内部会对color参数进行一个透明度处理,该方法要求传入的颜色值 
 | 
                    // 必须为rgb格式的,所以这里做一个处理 
 | 
                    color = uni.$u.hexToRgb(uni.$u.color[this.tmpConfig.type]) 
 | 
                } 
 | 
                return color 
 | 
            }, 
 | 
            // 内容盒子的样式 
 | 
            contentStyle() { 
 | 
                const windowHeight = uni.$u.sys().windowHeight, style = {} 
 | 
                let value = 0 
 | 
                // 根据top和bottom,对Y轴进行窗体高度的百分比偏移 
 | 
                if(this.tmpConfig.position === 'top') { 
 | 
                    value = - windowHeight * 0.25 
 | 
                } else if(this.tmpConfig.position === 'bottom') { 
 | 
                    value = windowHeight * 0.25 
 | 
                } 
 | 
                style.transform = `translateY(${value}px)` 
 | 
                return style 
 | 
            } 
 | 
        }, 
 | 
        created() { 
 | 
            // 通过主题的形式调用toast,批量生成方法函数 
 | 
            ['primary', 'success', 'error', 'warning', 'default', 'loading'].map(item => { 
 | 
                this[item] = message => this.show({ 
 | 
                    type: item, 
 | 
                    message 
 | 
                }) 
 | 
            }) 
 | 
        }, 
 | 
        methods: { 
 | 
            // 显示toast组件,由父组件通过this.$refs.xxx.show(options)形式调用 
 | 
            show(options) { 
 | 
                // 不将结果合并到this.config变量,避免多次调用u-toast,前后的配置造成混乱 
 | 
                this.tmpConfig = uni.$u.deepMerge(this.config, options) 
 | 
                // 清除定时器 
 | 
                this.clearTimer() 
 | 
                this.isShow = true 
 | 
                this.timer = setTimeout(() => { 
 | 
                    // 倒计时结束,清除定时器,隐藏toast组件 
 | 
                    this.clearTimer() 
 | 
                    // 判断是否存在callback方法,如果存在就执行 
 | 
                    typeof(this.tmpConfig.complete) === 'function' && this.tmpConfig.complete() 
 | 
                }, this.tmpConfig.duration) 
 | 
            }, 
 | 
            // 隐藏toast组件,由父组件通过this.$refs.xxx.hide()形式调用 
 | 
            hide() { 
 | 
                this.clearTimer() 
 | 
            }, 
 | 
            clearTimer() { 
 | 
                this.isShow = false 
 | 
                // 清除定时器 
 | 
                clearTimeout(this.timer) 
 | 
                this.timer = null 
 | 
            } 
 | 
        }, 
 | 
        beforeDestroy() { 
 | 
            this.clearTimer() 
 | 
        } 
 | 
    } 
 | 
</script> 
 | 
  
 | 
<style lang="scss" scoped> 
 | 
    @import "../../libs/css/components.scss"; 
 | 
  
 | 
    $u-toast-color:#fff !default; 
 | 
    $u-toast-border-radius:4px !default; 
 | 
    $u-toast-border-background-color:#585858 !default; 
 | 
    $u-toast-border-font-size:14px !default; 
 | 
    $u-toast-border-padding:12px 20px !default; 
 | 
    $u-toast-loading-border-padding: 20px 20px !default; 
 | 
    $u-toast-content-text-color:#fff !default; 
 | 
    $u-toast-content-text-font-size:15px !default; 
 | 
    $u-toast-u-icon:10rpx !default; 
 | 
    $u-toast-u-type-primary-color:$u-primary !default; 
 | 
    $u-toast-u-type-primary-background-color:#ecf5ff !default; 
 | 
    $u-toast-u-type-primary-border-color:rgb(215, 234, 254) !default; 
 | 
    $u-toast-u-type-primary-border-width:1px !default; 
 | 
    $u-toast-u-type-success-color: $u-success !default; 
 | 
    $u-toast-u-type-success-background-color: #dbf1e1 !default; 
 | 
    $u-toast-u-type-success-border-color: #BEF5C8 !default; 
 | 
    $u-toast-u-type-success-border-width: 1px !default; 
 | 
    $u-toast-u-type-error-color:$u-error !default; 
 | 
    $u-toast-u-type-error-background-color:#fef0f0 !default; 
 | 
    $u-toast-u-type-error-border-color:#fde2e2 !default; 
 | 
    $u-toast-u-type-error-border-width: 1px !default; 
 | 
    $u-toast-u-type-warning-color:$u-warning !default; 
 | 
    $u-toast-u-type-warning-background-color:#fdf6ec !default; 
 | 
    $u-toast-u-type-warning-border-color:#faecd8 !default; 
 | 
    $u-toast-u-type-warning-border-width: 1px !default; 
 | 
    $u-toast-u-type-default-color:#fff !default; 
 | 
    $u-toast-u-type-default-background-color:#585858 !default; 
 | 
  
 | 
    .u-toast { 
 | 
        &__content { 
 | 
            @include flex; 
 | 
            padding: $u-toast-border-padding; 
 | 
            border-radius: $u-toast-border-radius; 
 | 
            background-color: $u-toast-border-background-color; 
 | 
            color: $u-toast-color; 
 | 
            align-items: center; 
 | 
            /* #ifndef APP-NVUE */ 
 | 
            max-width: 600rpx; 
 | 
            /* #endif */ 
 | 
            position: relative; 
 | 
  
 | 
            &--loading { 
 | 
                flex-direction: column; 
 | 
                padding: $u-toast-loading-border-padding; 
 | 
            } 
 | 
  
 | 
            &__text { 
 | 
                color: $u-toast-content-text-color; 
 | 
                font-size: $u-toast-content-text-font-size; 
 | 
                line-height: $u-toast-content-text-font-size; 
 | 
  
 | 
                &--default { 
 | 
                    color: $u-toast-content-text-color; 
 | 
                } 
 | 
  
 | 
                &--error { 
 | 
                    color: $u-error; 
 | 
                } 
 | 
  
 | 
                &--primary { 
 | 
                    color: $u-primary; 
 | 
                } 
 | 
  
 | 
                &--success { 
 | 
                    color: $u-success; 
 | 
                } 
 | 
  
 | 
                &--warning { 
 | 
                    color: $u-warning; 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    .u-type-primary { 
 | 
        color: $u-toast-u-type-primary-color; 
 | 
        background-color: $u-toast-u-type-primary-background-color; 
 | 
        border-color: $u-toast-u-type-primary-border-color; 
 | 
        border-width: $u-toast-u-type-primary-border-width; 
 | 
    } 
 | 
  
 | 
    .u-type-success { 
 | 
        color: $u-toast-u-type-success-color; 
 | 
        background-color: $u-toast-u-type-success-background-color; 
 | 
        border-color: $u-toast-u-type-success-border-color; 
 | 
        border-width: 1px; 
 | 
    } 
 | 
  
 | 
    .u-type-error { 
 | 
        color: $u-toast-u-type-error-color; 
 | 
        background-color: $u-toast-u-type-error-background-color; 
 | 
        border-color: $u-toast-u-type-error-border-color; 
 | 
        border-width: $u-toast-u-type-error-border-width; 
 | 
    } 
 | 
  
 | 
    .u-type-warning { 
 | 
        color: $u-toast-u-type-warning-color; 
 | 
        background-color: $u-toast-u-type-warning-background-color; 
 | 
        border-color: $u-toast-u-type-warning-border-color; 
 | 
        border-width: 1px; 
 | 
    } 
 | 
  
 | 
    .u-type-default { 
 | 
        color: $u-toast-u-type-default-color; 
 | 
        background-color: $u-toast-u-type-default-background-color; 
 | 
    } 
 | 
</style> 
 |