notice.vue 4.47 KB
<template>
    <transition :name="transitionName" @enter="handleEnter" @leave="handleLeave">
        <div :class="classes" :style="styles">
            <template>
                <div :class="[baseClass + '-content']" ref="content">
                    <div :class="[baseClass + '-content-text']" v-html="content"></div>
                    <a :class="[baseClass + '-close']" @click="close" v-if="closable">
                        <i class="icon icon-close-tip"></i>
                    </a>
                </div>
            </template>
        </div>
    </transition>
</template>
<script>
export default {
    props: {
        prefixCls: {
            type: String,
            default: ''
        },
        duration: {
            type: Number,
            default: 1.5
        },
        type: {
            type: String
        },
        content: {
            type: String,
            default: ''
        },
        styles: {
            type: Object,
            default: function() {
                return {
                    right: '50%'
                };
            }
        },
        closable: {
            type: Boolean,
            default: false
        },
        className: {
            type: String
        },
        name: {
            type: String,
            required: true
        },
        onClose: {
            type: Function
        },
        transitionName: {
            type: String
        }
    },
    data() {
        return {
            withDesc: false
        };
    },
    computed: {
        baseClass() {
            return `${this.prefixCls}-notice`;
        },
        classes() {
            return [
                this.baseClass,
                {
                    [`${this.className}`]: !!this.className,
                    [`${this.baseClass}-closable`]: this.closable,
                    [`${this.baseClass}-with-desc`]: this.withDesc
                }
            ];
        },
        contentClasses() {
            return `${this.baseClass}-content`;
        }
    },
    methods: {
        clearCloseTimer() {
            if (this.closeTimer) {
                clearTimeout(this.closeTimer);
                this.closeTimer = null;
            }
        },
        close() {
            this.clearCloseTimer();
            this.onClose();
            this.$parent.close(this.name);
        },
        handleEnter(el) {
            if (this.type === 'message') {
                el.style.height = el.scrollHeight + 'px';
            }
        },
        handleLeave(el) {
            if (this.type === 'message') {
                if (document.getElementsByClassName('blk-message-notice').length !== 1) {
                    el.style.height = 0;
                    el.style.paddingTop = 0;
                    el.style.paddingBottom = 0;
                }
            }
        }
    },
    mounted() {
        this.clearCloseTimer();

        if (this.duration !== 0) {
            this.closeTimer = setTimeout(() => {
                this.close();
            }, this.duration * 1000);
        }

        if (this.prefixCls === 'blk-notice') {
            this.withDesc = this.$refs.content.querySelectorAll(`.${this.prefixCls}-desc`)[0].innerHTML !== '';
        }
    },
    beforeDestroy() {
        this.clearCloseTimer();
    }
};
</script>
<style lang="scss">
.blk-message {
    font-size: 24px;
    position: fixed;
    z-index: 1010;
    width: 100%;
    top: 50%;
    left: 0;
    pointer-events: none;

    &-notice {
        padding: 8px;
        text-align: center;
        transition: height .3s ease-in-out, padding .3s ease-in-out;

        &:first-child {
            margin-top: -8px;
        }

        .icon-default-tip {
            color: #2db7f5;
        }

        .icon-error-tip {
            color: #ed3f14;
        }

        .icon-success-tip {
            color: #19be6b;
        }
    }

    &-notice-content {
        display: inline-block;
        pointer-events: all;
        padding: 10px 20px;
        border-radius: 8px;
        box-shadow: 0 1px 6px rgba(0, 0, 0, .2);
        background-color: rgba(0, 0, 0, 0.7);
        position: relative;
        color: #fff;
        font-size: 28px;
        &-text {
            display: inline-block;
        }
    }

    &-notice-closable {
        .blk-message-notice-content-text {
            padding-right: 32px;
        }
    }

    .icon {
        margin-right: 8px;
        font-size: 26px;
        top: 1px;
        position: relative;

        &.icon-close-tip {
            font-size: 30px;
        }
    }
}
</style>