<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>