DocImageUpload.vue 6.47 KB
<template>
    <div class='doc-image-upload'>
        <div class='text-12 description'>{{ description }}</div>
        <div class='mt-2 py-3 text-center upload-btn' @click='fileSelect'>
            <doc-icon type='doc-upload' class='mr-2 text-16' />
            <span>{{ btText }}</span>
        </div>
        <div class='flex flex-wrap mt-4 image-box'>
            <div v-for="item in innerImage.filter(e => e.fileType != 'pdf')" :key='item.id'
                 class='item-img' @click.stop='toPreview(item)'>
                <DocImage :src='item.trueDownloadUrl' remove @onRemove='removeImage(item)' />
            </div>
            <div v-for="item in innerImage.filter(e => e.fileType == 'pdf')" :key='item.id'
                 class='item-pdf'>
                <DocImage isPdf :src='item.trueDownloadUrl' name='pdf文件名称' remove @onRemove='removeImage(item)' />
            </div>
        </div>
        <!-- accept='.jpg,.jpeg,.png,.pdf' -->
        <input type='file'
               accept="image/*"
               ref='fileElem'
               style='display: none;'
               @change='handleFiles'
               :key='inputKey'>

        <van-overlay :show='imgShow' @click='imgShow = false'>
            <div class='wrapper'>
                <van-swipe class='block' :initial-swipe='initSwipe'>
                    <van-swipe-item v-for="image in innerImage.filter(e => e.fileType != 'pdf')" :key='image'>
                        <img :src='image.trueDownloadUrl' style='width: 100%;height: 100%' />
                    </van-swipe-item>
                </van-swipe>
            </div>
        </van-overlay>
    </div>
</template>

<script>
import DocImage from './DocImage.vue'
import { showToast } from 'vant'
import { fileUpload } from '@/api/base'
import { useCustomFieldValue } from '@vant/use';

export default {
    name: 'DocImageUpload',
    components: {
        DocImage
    },
    props: {
        // 上传描述
        description: { default: '温馨提示:请上传JPG、PNG格式图片,文件大小不超过10M' },
        // 传入的img数据 { id, trueDownloadUrl }
        imageData: { default: () => [] },
        // 上传按键的文字
        btText: { default: '上传图片' },
        // 图片框大小
        size: String,
        // 上传最大数量
        maxLength: { default: 1 },
        lengthMessage: { default: '已达到图片上限,请移除后再上传' }
    },
    data() {
        return {
            // 内部图片对象
            innerImage: [],
            file: null,
            spinning: false,
            inputKey: '1',
            // viewer显示
            visible: false,
            //显示图片所在位置
            initSwipe: 0,
            imgShow: false
        }
    },
    computed: {
        fileElem() {
            return this.$refs['fileElem']
        },
        ids() {
            return this.innerImage.map(e => e.id).join(',')
        }
    },
    methods: {
        init() {
            if (this.imageData?.length) {
                this.innerImage = [...this.imageData]
                useCustomFieldValue(() => this.ids)
            } else {
                this.innerImage = [
                    // { fileType: 'pdf', id: 1, trueDownloadUrl: testUrl },
                    // { fileType: 'png', id: 2, trueDownloadUrl: testUrl },
                    // { fileType: 'png', id: 3, trueDownloadUrl: testUrl },
                    // { fileType: 'png', id: 4, trueDownloadUrl: testUrl }
                ]
            }
        },
        fileSelect() {
            console.log(this.innerImage, this.maxLength)
            if (this.innerImage?.length >= this.maxLength) {
                showToast(this.lengthMessage)
                return
            }
            const dom = this.$refs['fileElem']
            if (dom) {
                dom.click()
            }
        },
        upload() {
            let formData = new FormData()
            formData.append('file', this.file)
            this.spinning = true
            fileUpload(formData).then(res => {
                // this.$message.success('上传成功')
                let result = res.data || {}
                this.$emit('upload', result)
                this.addImage(result)
                this.inputKey = Math.random().toString(16).substring(2, 6)
                this.$emit('change', this.ids, this.innerImage)
                useCustomFieldValue(() => this.ids)
            }).finally(() => {
                this.spinning = false
            })
        },
        handleFiles() {
            let files = this.$refs['fileElem'].files
            if (files.length <= 0) {
                showToast('未选中文件,请尝试重新选择')
                return
            }
            if (files[0].size / 1024 / 1024 > 10) {
                showToast('图片大小不能超过10M')
                return
            }
            this.file = files[0]
            this.upload()
        },
        addImage(data = {}) {
            if (!data.id) {
                console.warn('addImage 文件为空')
                return
            }
            if (!this.innerImage.find(e => e.id === data.id)) {
                this.innerImage.push(data)
            }
        },
        removeImage(item) {
            if (!item) return
            this.innerImage = this.innerImage.filter(e => e.id != item.id)
            this.$emit('change', this.ids, this.innerImage)
            useCustomFieldValue(() => this.ids)
        },
        //图片预览
        toPreview(val) {
            let res = this.innerImage.filter(e => e.fileType != 'pdf')
            let index = res.findIndex(e => val.id == e.id)
            this.initSwipe = index
            this.imgShow = true
        }
    },
    watch: {
        imageData: {
            handler(value) {
                this.init()
            },
            immediate: true
        }
    }
}
</script>

<style lang='less' scoped>
.description {
    color: #A5AEBE;
}

.upload-btn {
    color: var(--van-primary-color);
    border: 1px solid #eee;
    background-color: #FAFAFA;
    border-radius: 8px;
}

.image-box {
    row-gap: 8px;
    column-gap: 12px;

    .item-img {
        width: calc(33.3% - 8px);
    }

    .item-pdf {
        width: 100%;
    }

    > div {
        width: calc(33.3% - 8px);
        position: relative;
        border-radius: 2px;

        img {
            object-fit: contain;
        }
    }
}

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

    .block {
        width: 100%;
    }
}
</style>