el-upload实现上传图片/pdf,回显图片/pdf功能。

el-upload实现上传图片/pdf,回显图片/pdf功能。

功能背景:上传图片和查看图片要在一个页面。

如何回显当前行数据已上传的文件?

答:把请求获取的数据赋值给绑定的fileList

<el-upload
    :action="url"
    multiple
    list-type="picture-card"
    :on-preview="handlePictureCardPreview"
    :on-success="successFirstImg"
    :on-remove="removeFirstImg"
    :file-list="firstImgList"
>
   <i class="el-icon-plus"></i>
</el-upload>
this.firstImgList = this.processImageList(res, 1);

文件上传成功后,绑定的filelist变量的length会自动增加一个吗?

答:不会,需要赋值,on-sucess绑定的事件参数filelist 赋值给data中定义的filelist

successFirstImg(res, file, fileList) {
    this.$message.success(res.msg);
    this.firstImgList = fileList;
},

如何把回显的文件和操作上传的文件一起提交给后台

答案:回显的文件中没有response对象,上传成功的文件会包含response对象,把两种数据提取出来组合在一起就可以了

如何显示和回显pdf文件,

在 HTML 中,<img> 标签主要用于显示图像文件,如 JPEG、PNG、GIF 等。PDF 文件并不是图像文件,因此 <img> 标签无法直接显示 PDF 内容。

el-upload内置的是img标签所以不支持pdf,

1.第一种方案用的iframe标签

缺点: iframe加载很慢,最少得等40秒才能出来,

2.第二种方案用的embed标签加载很快,

使用embed 或object标签

- 这些标签可以嵌入 PDF 文件,并且大多数现代浏览器都支持这些标签来显示 PDF。
<embed src="path/to/your/file.pdf" type="application/pdf" width="600" height="500">
<object data="path/to/your/file.pdf" type="application/pdf" width="600" height="500">
  <p>您的浏览器不支持 PDF 显示。</p>
</object>

总结:用embed 或 object 标签更合适。

其中重要的是,el-upload中用插槽以后,会覆盖组件本身封装的结构,所以on-remove,和on-preview绑定的事件就不生效了,得自己定义
removeSecondImg(file) {
    let uploadFiles = this.$refs.elUpload.uploadFiles;
    let index = uploadFiles.findIndex((item) => {
        return item.uid == file.uid;
    });
    console.log("🚀 ~ index ~ index:", index);
    uploadFiles.splice(index, 1);
    this.secondImgList = uploadFiles;
},

上传文件filelist中每个文件会有一个uid字段,用uid找出要删除的文件,进行删除。

效果取下:

预览PDF:

完整代码如下:

<template>
    <div class="dialogBox">
        <el-dialog
            :title="title"
            :visible.sync="visible"
            :close-on-click-modal="false"
            :width="width"
            @close="cancel"
        >
            <div style="display: flex; font-size: 16px">
                <div style="width: 33.3%">
                    <ImgTitle :title="firstTitle" />
                    <div class="imgCenter">
                        <el-upload
                            :action="url"
                            multiple
                            list-type="picture-card"
                            :on-preview="handlePictureCardPreview"
                            :on-success="successFirstImg"
                            :on-remove="removeFirstImg"
                            :file-list="firstImgList"
                        >
                            <i class="el-icon-plus"></i>
                        </el-upload>
                    </div>
                </div>
                <div style="width: 33.3%">
                    <ImgTitle :title="secondTitle" />
                    <div class="imgCenter">
                        <el-upload
                            ref="elUpload"
                            :action="url"
                            multiple
                            list-type="picture-card"
                            :on-success="successSecondImg"
                            :file-list="secondImgList"
                        >
                            <i class="el-icon-plus"></i>
                            <div slot="file" slot-scope="{ file }">
                                <embed
                                    v-if="isPdfFile(file)"
                                    :src="file.url"
                                    width="100%"
                                ></embed>
                                <img
                                    v-else
                                    class="el-upload-list__item-thumbnail"
                                    :src="file.url"
                                    alt=""
                                />
                                <span class="el-upload-list__item-actions">
                                    <span
                                        class="el-upload-list__item-preview"
                                        @click="
                                            handlePictureCardPreview(file)
                                        "
                                    >
                                        <i class="el-icon-zoom-in"></i>
                                    </span>
                                    <span
                                        v-if="!disabled"
                                        class="el-upload-list__item-delete"
                                        @click="removeSecondImg(file)"
                                    >
                                        <i class="el-icon-delete"></i>
                                    </span>
                                </span>
                            </div>
                        </el-upload>
                    </div>
                </div>
                <div style="width: 33.3%">
                    <ImgTitle :title="thirdTitle" />
                    <div class="imgCenter">
                        <el-upload
                            :action="url"
                            multiple
                            list-type="picture-card"
                            :on-preview="handlePictureCardPreview"
                            :on-success="successThirdImg"
                            :on-remove="removeThirdImg"
                            :file-list="thirdImgList"
                        >
                            <i class="el-icon-plus"></i>
                        </el-upload>
                    </div>
                </div>
            </div>

            <span slot="footer" class="dialog-footer">
                <el-button @click="cancel">取消</el-button>
                <el-button type="primary" @click="submitFn" v-preventReClick
                    >确定</el-button
                >
            </span>
        </el-dialog>
        <el-dialog :visible.sync="dialogVisible">
            <embed width="100%" height="500" :src="dialogImageUrl" v-if='dialogImageUrl.endsWith(".pdf")'></embed>
            <img width="100%" :src="dialogImageUrl" alt="" v-else/>
        </el-dialog>
    </div>
</template>
<script>
import { uploadImg, saveImg, selectPileImgs } from "_config/url.js";
import ImgTitle from "./ImgTitle";
export default {
    components: {
        ImgTitle,
    },
    data() {
        return {
            title: "上传图片",
            visible: false,
            url: uploadImg,
            width: "800px",
            firstTitle: "铭牌照片",
            secondTitle: "第三方检测报告",
            thirdTitle: "枪口数量图片",
            dialogVisible: false,
            dialogImageUrl: "",
            params: null,
            firstImgList: [],
            secondImgList: [],
            thirdImgList: [],
        };
    },
    methods: {
        isPdfFile(file) {
            if (!file.url && !file.name) return false;
            const pdfRegex = /\.pdf$/i;
            return (
                (file.url && pdfRegex.test(file.url)) ||
                (file.name && pdfRegex.test(file.name))
            );
        },
        async show(params) {
            console.log("🚀 ~ show ~ params:", params);
            this.params = params;
            await this.getInfo();
            this.visible = true;
        },
        // 预览图片
        handlePictureCardPreview(file) {
            this.dialogImageUrl = file.url;
            this.dialogVisible = true;
        },
        // 移除图片
        removeFirstImg(file, fileList) {
            this.firstImgList = fileList;
        },
        removeSecondImg(file) {
            let uploadFiles = this.$refs.elUpload.uploadFiles;
            let index = uploadFiles.findIndex((item) => {
                return item.uid == file.uid;
            });
            console.log("🚀 ~ index ~ index:", index);
            uploadFiles.splice(index, 1);
            this.secondImgList = uploadFiles;
        },
        removeThirdImg(file, fileList) {
            this.thirdImgList = fileList;
        },
        // 上传图片成功
        successFirstImg(res, file, fileList) {
            this.$message.success(res.msg);
            this.firstImgList = fileList;
        },
        successSecondImg(res, file, fileList) {
            this.$message.success(res.msg);
            this.secondImgList = fileList;
        },
        successThirdImg(res, file, fileList) {
            this.$message.success(res.msg);
            this.thirdImgList = fileList;
        },
        getList(fileList, fileListName) {
            console.log("🚀 ~ getList ~ fileList:", fileList);
            const imgTypeMap = {
                firstImgList: 1,
                secondImgList: 2,
                thirdImgList: 3,
            };
            let imgType = imgTypeMap[fileListName];

            if (fileList.length > 0) {
                // 上传的图片列表
                let submitImgList = fileList

                    .filter((i) => i.response && i.response.msg == "上传成功")
                    .map((j, index) => {
                        return {
                            imgUrl: j.response.imgUrl,
                            imgType,
                        };
                    });
                // 已上传的图片列表回显
                let echoImgList = fileList
                    .filter((i) => !i.response && i.sequence)
                    .map((j, index) => {
                        return {
                            imgUrl: this.extractPathFromUrl(j.url),
                            imgType: j.imgType,
                        };
                    });
                console.log("🚀 ~ getList ~ echoImgList :", echoImgList);
                //图片列表合并添加排序
                this[fileListName] = [...echoImgList, ...submitImgList].map(
                    (i, index) => {
                        return {
                            imgUrl: i.imgUrl,
                            imgType: i.imgType,
                            code: this.params[0].code,
                            sequence: index + 1,
                        };
                    }
                );
            }
            console.log(
                "🚀 ~ getList ~   this.firstImgList;:",
                this.firstImgList
            );
            console.log(
                "🚀 ~ getList ~   this.secondImgList:",
                this.secondImgList
            );
            console.log(
                "🚀 ~ getList ~   this.thirdImgList:",
                this.thirdImgList
            );
        },
        // 提交上传
        async submitFn() {
            this.getList(this.firstImgList, "firstImgList");
            this.getList(this.secondImgList, "secondImgList");
            this.getList(this.thirdImgList, "thirdImgList");
            let imgList = [
                ...this.firstImgList,
                ...this.secondImgList,
                ...this.thirdImgList,
            ];
            console.log("🚀 ~ submitFn ~ imgList:", imgList);
            try {
                let res = await this.$post(saveImg, imgList);
                if (res.status == 1) {
                    this.$message.success(res.msg);
                } else {
                    this.$message.error(res.msg);
                }
                this.cancel();
            } catch (err) {
                console.log(err);
            }
        },
        // 查看图片
        async getInfo() {
            try {
                let res = await this.$post(selectPileImgs, {
                    code: this.params[0].code,
                });
                console.log("🚀 ~ getInfo ~ res :", res);
                if (res) {
                    this.firstImgList = this.processImageList(res, 1);
                    this.secondImgList = this.processImageList(res, 2);
                    this.thirdImgList = this.processImageList(res, 3);
                } else {
                    this.firstImgList = [];
                    this.secondImgList = [];
                    this.thirdImgList = [];
                }
            } catch (err) {
                console.log(err);
            }
        },
        cancel() {
            this.visible = false;
            this.dialogVisible = false;
            this.dialogImageUrl = "";
            this.firstImgList = [];
            this.secondImgList = [];
            this.thirdImgList = [];
            this.params = null;
            this.$emit("close");
        },
        // 回显时处理图片列表
        //根据imgType分类,根据sequence排序
        processImageList(res, imgType) {
            return res
                .filter((i) => i.img_type === imgType)
                .map((i) => ({
                    url: this.PIC_URL + i.url,
                    sequence: i.sequence,
                    imgType: i.img_type,
                }))
                .sort((a, b) => a.sequence - b.sequence);
        },
        // 图片路径处理, 去掉前缀PIC_URL
        extractPathFromUrl(url) {
            if (url.startsWith(this.PIC_URL)) {
                return url.substring(this.PIC_URL.length);
            }
            return "";
        },
    },
};
</script>
<style scoped lang="less">
/deep/ .el-upload-list__item-name {
    overflow: auto;
    white-space: normal;
}
/deep/ .el-image__inner {
    width: 180px;
    height: 180px;
    border: 1px solid #00000080;
    margin-bottom: 3px;
    border-radius: 10px;
}
.imgCenter {
    margin: 0 auto;
    text-align: center;
}
.img {
    width: 261px;
    height: 187px;
    display: block;
    margin: 20px auto;
}
.avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
}
.avatar-uploader .el-upload:hover {
    border-color: #409eff;
}
.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
}
.avatar {
    width: 178px;
    height: 178px;
    display: block;
}
</style>

posted @   崛起崛起  阅读(1577)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示