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

news2024/12/24 20:55:31

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

文章目录

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


前言

项目需求是在表格中嵌套一个上传图片的功能,并且回显选择的图片和已上传的图片,再通过点击操作列中上传按钮才开始上传,使用的方法是实际是通过表单上传实现的
在这里插入图片描述
在这里插入图片描述


一、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
    })
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/893729.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝牙资讯|安卓将加强耳机音量监控,耳机查找功能将更加普遍

为了保护用户的听力健康&#xff0c;Android 14 将增加一项新功能&#xff0c;当用户使用耳机听音乐时&#xff0c;如果音量过高或持续时间过长&#xff0c;系统会发出警告&#xff0c;并自动降低音量。这个功能叫做“耳机音量过高警告&#xff08;headphone loud sound alert&…

蓝奥声智能工业安全用电监测与智慧能源解决方案

能源管理变得越来越重要。如今&#xff0c;能源成本已成为国内预算的核心因素&#xff0c;因此用电监控对大多数现代企业来说都很重要。许多企业在日常能源消耗监控中面临着一些挑战&#xff0c;因为它们的规模庞大&#xff0c;基础设施多样化&#xff0c;灵活性低&#xff0c;…

每天一道leetcode:剑指 Offer 55 - I. 二叉树的深度(适合初学者树图论层次遍历)

今日份题目&#xff1a; 输入一棵二叉树的根节点&#xff0c;求该树的深度。从根节点到叶节点依次经过的节点&#xff08;含根、叶节点&#xff09;形成树的一条路径&#xff0c;最长路径的长度为树的深度。 示例 给定二叉树 [3,9,20,null,null,15,7]&#xff0c; 3/ \9 20…

深入探索智能未来:文本生成与问答模型的创新融合

深入探索智能未来&#xff1a;文本生成与问答模型的创新融合 1.Filling Model with T5 1.1背景介绍 该项目用于将句子中 [MASK] 位置通过生成模型还原&#xff0c;以实现 UIE 信息抽取中 Mask Then Filling 数据增强策略。 Mask Then Fill 是一种基于生成模型的信息抽取数据…

科学规划假期学习,猿辅导《暑假一本通》获用户好评

一直以来&#xff0c;有效利用寒、暑假期查漏补缺、解决偏科问题、初步养成好的自主学习习惯等是很多家长对学生的期望。但当前市面上教辅品类繁多&#xff0c;内容质量却参差不齐。据北京开卷统计数据显示&#xff0c;2022年前三季度零售市场上的教辅图书超过8000种&#xff0…

高级AI赋能Fortinet FortiXDR解决方案

扩展检测和响应 (XDR&#xff1a;Extended Detection and Response) 解决方案旨在帮助组织整合分布式安全技术&#xff0c;更有效地识别和响应活动的威胁。虽然 XDR 是一种新的技术概念&#xff0c;但其构建基础是端点检测和响应 (EDR&#xff1a;Endpoint Detection and Respo…

CW4L2-3A-S电源滤波器

CW4L2-3A-T CW4L2-6A-T CW4L2-10A-T CW4L2-20A-T CW4L2-3A-S CW4L2-6A-S CW4L2-10A-S CW4L2-20A-S 安装位置应靠近电源线入口处&#xff0c;尽可能滤除沿电源线侵入和窜出的电磁干扰。 确保滤波器外壳与设备机箱良好电接触&#xff0c;并接好地线。 滤波器的输入输出…

PoseiSwap 更新质押系统,并将在 8 月18 日开启“Trident ”快照

自 DeFi Summer 后&#xff0c;DeFi 设施整体的形态并未发生本质的变化&#xff0c;我们看到 DeFi 应用仍旧不具向外长期捕获价值、用户的能力&#xff0c;老旧叙事导致 DeFi 赛道整体的发展停滞不前。伴随着行业进入到下行周期&#xff0c;DeFi 赛道的资金、用户不断出逃&…

政务、商务数据资源有效共享:让数据上“链”,记录每一个存储过程!

数据上链是目前“区块链”最常见的场景。因为链上所有参与方都分享了统一的事实来源&#xff0c;所有人都可以即时获得最新的信息&#xff0c;数据可用不可见。因此&#xff0c;不同参与方之间的协作效率得以大幅提高。同时&#xff0c;因为区块链上的数据难以篡改&#xff0c;…

猿辅导与中街1946联手推出“冷知识冰棍”,带来学习新体验

为了给孩子们的暑假学习加点“料”&#xff0c;猿辅导近日脑洞大开&#xff0c;和中街1946携手推出了“冷知识冰棍”&#xff0c;以数学、英语、语文、科学4个科目为外包装&#xff0c;分别对应草莓山楂、青提菠萝、茉莉蓝莓和蜜桃乌龙等4种口味&#xff0c;为孩子们开启了夏日…

学习笔记」左偏树

dist 的性质 对于一棵二叉树&#xff0c;我们定义左孩子或右孩子为空的节点为外节点&#xff0c;定义外节点的 distdist 为 11&#xff0c;空节点的 distdist 为 00&#xff0c;不是外节点也不是空节点的 distdist 为其到子树中最近的外节点的距离加一。 一棵根的 distdist 为…

多线段的研究

1.AutoCAD分为二维多线段(命令pline)&#xff0c;三维多线段(3dpoly)。 1.1&#xff1a;二维多线段 对应类Acdb2dPolyline&#xff0c;有起点&#xff0c;末点的宽度。由Acdb2dVertex&#xff08;顶点组成&#xff09; 1.2:三维多义线&#xff0c;(三维多义线的顶点没有凸度&a…

地理测绘基础知识(3)-观测与遮挡

在上一篇文章中&#xff0c;我们介绍了椭球模型下的一系列基础的坐标操作。本节&#xff0c;介绍观测与遮挡问题。 观测主要用于从观察点A观测大地标准点B&#xff0c;用来解决观测的仰角、方位角与大地坐标系之间的关系。 在没有GPS卫星的时代&#xff0c;为了测量一个位置的…

ipad手写笔一定要买苹果的吗?适合学生党电容笔推荐

暑假接近尾声&#xff0c;不少学生党开始为开学而做准备了。如果你想要一个与iPad相匹配的电容笔&#xff0c;可以买一个Apple Pencil吧。但事实上&#xff0c;这个苹果产品性能比较出色&#xff0c;卖的还是很好的。但是平替电容笔也是个不错的选择&#xff0c;而且价格也很合…

构建LLM应用程序时需要了解的5件事

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 1.幻觉 使用LLM时应注意的主要方面之一是幻觉。在LLM的背景下&#xff0c;幻觉是指产生不真实的&#xff0c;不正确的&#xff0c;无意义的信息。LLM非常有创意&#xff0c;它们可以用于不同的领域&am…

亚马逊如何登录多个买家号?如何防止账号关联?

如果有多买家账号需要登录使用&#xff0c;以下是在同一设备上登录多个买家账号的一般步骤&#xff1a; 1、登出当前账号&#xff1a;如果您已经登录了一个买家账号&#xff0c;首先需要退出该账号。在页面右上角&#xff0c;通常会看到一个"Hello, [您的用户名]"&a…

终端安全无忧!迅软科技助力母婴用品企业保护隐私信息

客户简要介绍 某母婴用品企业是专业的婴幼儿用品综合制造厂商&#xff0c;是总部设在上海&#xff0c;致力于研发集安全性、舒适性、功能性以及环保于一体的产品。 企业的重要诉求 公司内部奶瓶、纸尿裤等产品的销售数据以及新品设计图片要避免外传被竞争对手拿到&#xff0c;需…

Java“牵手”根据关键词搜索(分类搜索)1688商品列表页面数据获取方法,1688API实现批量商品数据抓取示例

1688商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取1688商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问1688商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…

yaml语法规则

1.语法规则 大小写敏感属性层级关系使用多行描述&#xff0c;每行结尾使用冒号结束使用缩进表示层级关系&#xff0c;同层级左侧对齐&#xff0c;只允许使用空格&#xff08;不允许 使用Tab键&#xff09;属性值前面添加空格&#xff08;属性名与属性值之间使用冒号空格作为分…

Azure VM上意外禁用NIC如何还原恢复

创建一个windows虚拟机&#xff0c;并远程连接管理员的方式打开powershell 首先查看虚拟网卡&#xff0c;netsh interface show interface 然后禁用虚拟网卡 ,netsh interface set interface Ethernet disable 去Azure虚拟机控制台&#xff0c;打开串行控制台 控制台中键入cmd,…