elementui表格嵌套上传文件直传到oss服务器(表单上传)

提示:记录项目中遇到的问题,仅供参考

文章目录

  • 前言
  • 一、vue代码
  • 二、js接口请求代码


前言

项目需求是在表格中嵌套一个上传图片的功能,并且回显选择的图片和已上传的图片,再通过点击操作列中上传按钮才开始上传,使用的方法是实际是通过表单上传实现的
elementui表格嵌套上传文件直传到oss服务器(表单上传)_第1张图片
在这里插入图片描述


一、vue代码

这里就只展示主要代码,对elementui的函数方法不熟系的,可以对照elementui文档来理解

提示:下面的 scope.row.status 是指状态,为 9 时才可以上传图片,为 0 时图片已经上传

<template>
	<el-table v-loading="loading" :data="formRefundRecordList" v-if="showTable">
		<div slot="empty" style="text-align: left;">暂无数据</div>
		<el-table-column label="退充截图" align="center" prop="screenshot" :key="Math.random()" width="150px">
		     <template slot-scope="scope">
		         <el-upload :class="{hideUpload:dialogImageUrls[`i${scope.row.id}`] != null}"
		             :action="upData.host" :ref="`reScreenshot${scope.row.id}`" :limit="1"
		             :accept="accept.join(',')" :auto-upload="false" list-type="picture-card"
		             :on-preview="(file)=>{return handlePreview(file, scope.row.id)}"
		             :on-remove="(file,fileList)=>{return handleRemove(file, fileList, scope.row.id)}"
		             :on-change="(file,fileList)=>{return handleChange(file, fileList, scope.row.id)}"
		             v-if="scope.row.status == 9">
		             <i class="el-icon-plus"></i>
		         </el-upload>
		
		         <!-- 上传成功后图片预览 -->
		         <!-- src 为图片预览前显示的内容 -->
		         <!-- preview-src-list 为图片预览时显示的内容 -->
		         <el-image v-if="dialogImageUrls[`i${scope.row.id}`] != null && scope.row.status != 9"
		             class="hideUpload" :src="dialogImageUrls[`i${scope.row.id}`]"
		             :preview-src-list="[dialogImageUrls[`i${scope.row.id}`]]">
		         </el-image>
		     </template>
	     </el-table-column>
		<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right"
		width="200px">
			<template slot-scope="scope">
				<el-button size="mini" type="text" @click="UpdateStatus(scope.row, 0)" :disabled="scope.row.status != 9">通过</el-button>
			</template>
		</el-table-column>
	</el-table>
	
	<!-- 上传前图片预览 -->
	<el-image-viewer v-if="showViewer" :on-close="closeViewer" :url-list="srcList" />
<template>
<script>
	import { updateFormRefundRecord, getOssPolicy, uploadOss } from "@/api/bol/refundInternalMedia";
	import SparkMD5 from "spark-md5";
	import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
	export default {
        name: "refundInternalMedia",
        components: { ElImageViewer },
        data() {
            return {
            	// 图片详情放大列表(上传前)
                srcList: [],
                // 图片详情放大是否显示
                showViewer: false,
                // 上传前文件列表
                fileList: {},
                // 上传成功后回显时文件的域名(例:https://xxxxxx.xxxx.com)
                fileDominName: process.env.VUE_APP_File_SHOW_DOMAIN_NAME,
                // 上传截图携带的参数(实际上不需要这个,但没有又会报错)
                upData: {
                    host: ''
                },
                // 允许上传截图的格式
                accept: ['.png', '.jpg', '.jpeg'],
                // 截图弹窗显示与隐藏
                dialogVisibles: {},
                // 截图文件路径(表格所有的)
                dialogImageUrls: {},
                // 表格显示
                showTable: true,
                // 遮罩层
                loading: true,
                // 表格数据
                formRefundRecordList: [],
			}
		},
		methods: {
            // 关闭图片放大(上传前的)
            closeViewer() {
                this.srcList = [];
                this.showViewer = false;
            },
            // 删除截图的事件
            handleRemove(file, fileList, id) {
                this.$set(this.dialogImageUrls, `i${id}`, null)
                this.$delete(this.fileList, `f${id}`)
                // 刷新表格
                this.showTable = false
                this.showTable = true
            },
            // 点击已上传的截图时的事件
            handlePreview(file, id) {
                this.srcList = [file.url];
                this.showViewer = true;
            },
            // 截图状态改变时的钩子,添加文件、上传成功和上传失败时的事件
            handleChange(file, fileList, id) {
                this.$set(this.dialogImageUrls, `i${id}`, file.url)
                this.$set(this.fileList, `f${id}`, file.raw)
                // 刷新表格
                this.showTable = false
                this.showTable = true
            },
            // 上传截图
            async uploadFile(file, id) {
                // 文件md5值
                let md5
                await this.fileMd5(file).then((res) => {
                    md5 = res
                })

                // 文件后缀名
                var suffix = file.name.substring(file.name.lastIndexOf(".")); //.xxx
                // 上传oss的文件名
                let fileName = md5 + suffix
                // 生成一个以年月作为文件夹名(例:'20230703/')
                let fileDirName = this.getDirName()
                // 存放文件的路径(放到bol项目文件夹下的 refundScreenshot 退款截图文件夹下)
                let filePath = 'bol/refundScreenshot/' + fileDirName + '/'

                // 限制允许上传文件类型
                if (!this.accept.includes(suffix)) {
                    this.$message.warning('上传文件格式有误,请检查后重新上传。')
                    return false
                }

                getOssPolicy({}).then((res) => {
                    // 拿到签名信息后,组装表单数据,作参考,具体的字段找后台要
                    let config = res.data

                    let fd = new FormData()
                    fd.append('key', filePath + fileName)
                    fd.append('success_action_status', '200')
                    fd.append('x-oss-object-acl', 'public-read')
                    fd.append('x-oss-meta-fullname', fileName)
                    fd.append('OSSAccessKeyId', config.accessid)
                    fd.append('policy', config.policy)
                    fd.append('signature', config.signature)
                    fd.append('file', file)
                    if (config.host.indexOf('http:') > -1) {
                        var protocol = window.location.protocol || 'http:'
                        var subUrl = config.host.substring(5, config.host.length)
                        config.host = protocol + subUrl
                    }
                    // 组装请求参数
                    let pre = {
                        url: config.host,
                        data: fd
                    }
                    uploadOss(pre).then(() => {
                        // 组装数据
                        let data = {
                            id: id,
                            screenshot: filePath + fileName,
                            status: 0
                        }
                        // 执行通过
                        updateFormRefundRecord(data).then((res) => {
                            this.getList();
                            this.$modal.msgSuccess("成功通过");
                        }).catch(() => {
                            this.$message.error(res.msg);
                        })
                    }).catch(err => {
                        this.$message.warning('图片上传失败')
                    })

                }).catch((err) => {
                    this.$message.warning('验签获取失败')
                })
            },

            // 生成一个以年月为文件名的字符
            getDirName() {
                var date = new Date();
                var year = date.getFullYear();
                var month = date.getMonth() + 1;

                if (month >= 1 && month <= 9) {
                    month = "0" + month;
                }
                var DirName = year + '' + month;
                return DirName;
            },
            // 返回文件md5值
            async fileMd5(file) {
                var fileReader = new FileReader();
                var spark = new SparkMD5.ArrayBuffer();
                // 获取文件二进制数据
                // fileReader.readAsArrayBuffer(event.target.files[0]);
                fileReader.readAsArrayBuffer(file);
                return new Promise((resolve, reject) => {
                    fileReader.onload = function (e) {
                        spark.append(e.target.result);
                        var md5 = spark.end();
                        resolve(md5)
                    };
                })
            },
            /** 通过操作 */
            UpdateStatus(row, status) {
                // 组装数据
                const data = {
                    id: row.id,
                    status
                }
                let that = this
                this.$modal.confirm(`是否确认 通过 xxxx单编号为 “${row.id}” 的数据项?`).then(() => {
                    // 判断点击的是通过按钮,点击通过按钮要先上传图片
                    if (status == 0) {
                        // 判断是否上传了图片
                        if (this.dialogImageUrls[`i${row.id}`]) {
                            this.uploadFile(this.fileList[`f${row.id}`], row.id);
                        } else {
                            this.$message('请先上传图片');
                        }
                    } else {
                        ........;
                    }
                }).catch(() => { });
            },
		},
	}
</script>
<style lang="scss" scoped>
    ::v-deep .el-upload--picture-card {
        margin: 5px 0;
        width: 120px;
        height: 80px;
        line-height: 80px;
    }

    ::v-deep .el-upload-list--picture-card .el-upload-list__item {
        width: 120px;
        height: 80px;
        margin-top: 0;
    }

    .hideUpload {
        margin: 5px 0;
        width: 120px;
        height: 80px;
    }

    .hideUpload ::v-deep .el-upload {
        display: none;
        /* 上传按钮隐藏 */
    }
</style>

二、js接口请求代码

提示:下面的请求接口是进行封装过的,就不进行具体展示了

import request from '@/utils/request'

// 更新退款媒介内部单数据
export function updateFormRefundRecord(data) {
    return request({
        url: 'xxxxxxxxxx',
        method: 'put',
        data: data
    })
}

// 获取阿里OSS签名
export function getOssPolicy(data) {
    return request({
        url: 'xxxxxxx',
        method: 'get',
        params: data
    })
}

// 上传到阿里OSS
export function uploadOss(pre) {
    return request({
        url: pre.url,
        method: 'post',
        data: pre.data
    })
}


你可能感兴趣的:(elementUi,vue,js,elementui,前端,vue.js)