DocImage.vue 4.05 KB
<template>
    <div class="doc-image">
        <div v-if="isPdf" class="p-2 flex items-center view-pdf">
            <doc-icon type="doc-PDF" style="font-size: .48rem" class="shrink-0"/>
            <span class="grow px-4 text-ellipsis">{{name}}</span>
            <span class="close-btn" @click.stop="removeBtn" v-if="remove">
                <doc-icon type="close-circle" />
            </span>
        </div>
        <div class="view-img" v-if="status==='success' && !isPdf">
            <img :src="src" :alt="name"
                :loading="loading" >
        </div>
        <template v-if="!isPdf">
            <div class="doc-image-wrapper" v-if="status==='loading'">
                <slot name="placeholder">
                    <div class="doc-image-default">加载中...</div>
                </slot>
            </div>
            <div class="doc-image-wrapper" v-if="status==='fail'">
                <slot name="fail">
                    <div class="doc-image-default">加载失败</div>
                </slot>
            </div>
            <span class="close-btn" @click.stop="removeBtn" v-if="remove">
                <doc-icon type="close-circle" />
            </span>
        </template>
    </div>
</template>

<script>
export default {
    name: 'doc-image',
    props: {
        src: String,
        // 浏览器应当如何加载该图像
        // img标签中的属性 需要浏览器支持
        // https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img
        // eager 立即加载图像
        // lazy 延迟加载图像,直到它和视口接近到一个计算得到的距离
        loading: String,
        // 开启删除功能
        remove: Boolean,
        // 处理pdf预览
        isPdf: Boolean,
        name: String
    },
    emits: ['removeBtn'],
    data() {
        return {
            // 图片加载状态 loading | fail | success
            status: 'loading',
            imgStyle: {},
            // viewer显示
            visible: false,
            // 按键界面显示
            btVisible: false
        }
    },
    methods: {
        loadImage() {
            if (this.isPdf) {
                this.status = 'success'
                return
            }
            const image = new Image()
            image.onload = () => {
                this.show = true
                this.status = 'success'
            }
            image.onerror = (err) => {
                console.warn('doc-image', err)
                this.show = false
                this.status = 'fail'
            }
            this.status = 'loading'
            image.src = this.src
        },
        removeBtn() {
            this.btVisible = false
            this.$emit('onRemove', this.src)
        }
    },
    watch: {
        src: {
            handler(val) {
                if (val) {
                    this.loadImage()
                }
            },
            immediate: true
        }
    }
}
</script>

<style lang="less" scoped>
.doc-image {
    display: inline-block;
    width: 100%;
    height: 100%;
    position: relative;
    .view-img {
        width: 100%;
        height: 100%;
        min-height: 90px;
        border: 1px dashed #d9d9d9;
        background: #fafafa;
        img {
            width: 100%;
            height: 90px;
            object-fit: contain;
        }
    }
    .view-pdf {
        width: 100%;
        min-height: 48px;
        overflow-y: hidden;
        border-radius: 8px;
        border: 1px solid #EEEEEE;
        .close-btn {
            top: 50%;
            right: 8px;
            transform: translateY(-50%);
        }
    }
    .close-btn {
        position: absolute;
        font-size: 16px;
        top: -8px;
        right: -8px;
    }
}

.doc-image-wrapper {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
}

.doc-image-default {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 14px;
    background: #f5faf7;
    color: #a8abb2;
    vertical-align: middle;
    user-select: none;
}
</style>