Ant Design Vue和VUE3下的upload组件使用以及文件预览

在这里插入图片描述

Ant Design Vue和VUE3下的upload组件使用以及文件预览

文章目录

  • Ant Design Vue和VUE3下的upload组件使用以及文件预览
    • 一、多文件上传
      • 1.需求
      • 2.样例
      • 3.代码
    • 二、单文件上传
      • 1. 需求
      • 2. 样例
      • 3.代码
    • 二、多文件上传产生的时间超时问题
    • 三、文件系统名称更改
      • 1. 修改文件`index.html`
      • 2. 修改文件`index.js`
      • 3. 修改数据库存储的系统名称
    • 四、系统登陆后的首页更改

用到技术:Ant Design Vue、VUE3、xlsx的文件预览功能(也可预览txt,csv)

一、多文件上传

1.需求

  1. 可以多文件上传
  2. 文件先上传到本地,点击开始上传再通过后端接口继续上传
  3. 上传后显示全部、正确和错误的数据信息
  4. 上传后可以下载

注意细节:

  1. 最开始文件上传到本地时,右边页面不加载,当点击上传后,在右边未获取数据之前,
    a.上传组件无法再次上传;
    b:右边数据均处于加载中状态;
    c.文件下载处于不可编辑状态
  2. 加载出数据后,
    a.上传组件可再次上传;
    b.文件预览中的全部、正确和错误数据均需显示出对应的数据序号
    c.正确和错误的数据,均不显示‘比对结果’,仅全部数据显示
  3. 文件下载接口注意文件类型为‘blob’

2.样例

在这里插入图片描述

3.代码

<template><a-row :gutter="8"><a-col :span="8"><a-card title="文件上传"><a-upload-draggerv-model:fileList="fileList"name="files"accept=".txt":multiple="true":action="action":before-upload="beforeUpload":disabled="upLoadDisabled"@remove="handleRemove":showUploadList="{showRemoveIcon: true}"><p class="ant-upload-drag-icon"><inbox-outlined></inbox-outlined></p><p class="ant-upload-text">点击或将文件拖拽到这里上传, 支持扩展名:.txt</p></a-upload-dragger><div style="text-align: right"><a-buttontype="primary":disabled="fileList.length === 0":loading="uploading"style="margin-top: 16px"@click="handleUpload">{{ uploading ? '上传中' : '开始上传' }}</a-button></div></a-card></a-col><a-col :span="16"><a-card><a-spin :spinning="upLoadSpinning" tip="数据加载中..."><a-row :gutter="16"><a-col :span="12"><a-statistic title="正确/错误(个)" :value="trueNum" class="demo-class"><template #suffix><span>/{{ falseNum }}</span></template></a-statistic></a-col><a-col :span="12"><a-statistic title="完善度" :value="wcdPercent" style="margin-right: 50px" /></a-col></a-row></a-spin></a-card><a-card title="文件预览" style="margin-top: 5px"><a-spin :spinning="upLoadSpinning" tip="数据加载中..."><a-tabs v-model:activeKey="activeKey" type="card" @change="tabChange"><a-tab-pane key="0"><template #tab><div>全部</div></template><div style="padding-bottom: 20px; padding-top: 20px"><div v-if="tableData0.length > 0"><a-table :columns="columns" :data-source="tableData0" bordered> </a-table></div><div v-else><div class="emptyStyle"></div></div></div></a-tab-pane><a-tab-pane key="1"><template #tab><div>正确</div></template><div style="padding-bottom: 20px; padding-top: 20px"><div v-if="tableData1.length > 0"><a-table :columns="columns1" :data-source="tableData1" bordered> </a-table></div><div v-else><div class="emptyStyle"></div></div></div></a-tab-pane><a-tab-pane key="2"><template #tab><div>错误</div></template><div style="padding-bottom: 20px; padding-top: 20px"><div v-if="tableData2.length > 0"><a-table :columns="columns1" :data-source="tableData2" bordered> </a-table></div><div v-else><div class="emptyStyle"></div></div></div></a-tab-pane><template #rightExtra><a-button @click="fileDownloadBtn" type="primary" :disabled="fileDownload">文件下载</a-button></template></a-tabs></a-spin></a-card></a-col></a-row>
</template><script setup>import { message } from 'ant-design-vue'import sysConfig from '@/config'import uploadApi from '@/api/auth/uploadApi'import * as XLSX from 'xlsx'import { clone } from 'lodash-es'import fileApi from '@/api/dev/fileApi'const props = defineProps({action: {type: String,default: '/biz/file/upload',required: false}})const action = sysConfig.API_URL + props.actionconst fileList = ref([])const beforeUpload = (file) => {fileList.value = [...(fileList.value || []), file]return false}const handleRemove = (file) => {const index = fileList.value.indexOf(file)const newFileList = fileList.value.slice()newFileList.splice(index, 1)fileList.value = newFileList}const handleUpload = () => {// 可预览upLoadSpinning.value = trueupLoadDisabled.value = truefileDownload.value = trueuploading.value = trueconst fileData = new FormData()fileList.value.forEach((item) => {fileData.append('files', item.originFileObj)})uploadApi.upload(fileData).then((res) => {message.success(`文件上传成功`)previewFile()trueNum.value = res.trueNumfalseNum.value = res.falseNumwcdPercent.value = res.wcdPercent}).catch(() => {message.error(`文件上传失败`)}).finally(() => {//开始上传按钮uploading.value = false//文件上传禁选择upLoadDisabled.value = false//可预览upLoadSpinning.value = false//可下载fileDownload.value = false})}const activeKey = ref('0')const uploading = ref(false)const upLoadSpinning = ref(true)const upLoadDisabled = ref(true)const tableData = ref([])const tableData0 = ref([])const tableData1 = ref([])const tableData2 = ref([])const columns = ref({})const columns1 = ref({})const previewFile = () => {uploadApi.download().then((res) => {const reader = new FileReader()reader.readAsBinaryString(res.data)reader.onload = (ev) => {try {const data = ev.target.resultconst wb = XLSX.read(data, {type: 'binary',cellText: false,cellDates: true})const outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])let tableheader = outdata[0]columns.value = [{title: '序号',dataIndex: '序号',key: '序号'}]columns1.value = [{title: '序号',dataIndex: '序号',key: '序号'}]for (let val in tableheader) {if (val !== '__EMPTY') {columns.value.push({title: val,dataIndex: val,key: val})if (val !== '比对结果') {columns1.value.push({title: val,dataIndex: val,key: val})}}}tableData.value = clone(outdata)tabChange(activeKey.value)} catch (e) {return false}}fileDownload.value = false}).catch((error) => {console.log(error)})}const tabChange = (key) => {if (key === '0') {const tableAll = tableData.valuetableAll.forEach((v, i) => {v['序号'] = v.__EMPTY + 1v = { ...v, key: i + 1 }})tableData0.value = tableAll} else if (key === '1') {const tableTrue = tableData.value.filter((item) => item['比对结果'] === 1)tableTrue.forEach((v, i) => {v['序号'] = i + 1})tableData1.value = tableTrue} else if (key === '2') {const tableFalse = tableData.value.filter((item) => item['比对结果'] === 0)tableFalse.forEach((v, i) => {v['序号'] = i + 1})tableData2.value = tableFalse}}const fileDownload = ref(true)const trueNum = ref(0)const falseNum = ref(0)const wcdPercent = ref(0)const fileDownloadBtn = () => {upLoadSpinning.value = trueupLoadDisabled.value = truefileDownload.value = trueuploadApi.download().then((res) => {message.success('文件下载成功')const blob = new Blob([res.data], { type: 'application/octet-stream;charset=UTF-8' })const $link = document.createElement('a')$link.href = URL.createObjectURL(blob)// $link.download = 'xxx.xlsx'$link.download = 'xxx.csv'$link.click()document.body.appendChild($link)document.body.removeChild($link) // 下载完成移除元素window.URL.revokeObjectURL($link.href) // 释放掉blob对象//文件上传禁选择upLoadDisabled.value = false//可预览upLoadSpinning.value = false//可下载fileDownload.value = false}).catch((error) => {console.log(error)})}onMounted(() => {//文件上传禁选择upLoadDisabled.value = false//可预览upLoadSpinning.value = false})
</script><style scoped>.emptyStyle {height: 200px;background-image: url(../../assets/images/empty1.png);background-position: center;background-repeat: no-repeat;background-size: 200px 200px;cursor: default;}
</style>

二、单文件上传

1. 需求

  1. 单个文件上传
  2. 文件直接上传,直接调用后端接口
  3. 上传后显示全部、正确和错误的数据信息
  4. 上传后可以下载

注意细节:

  1. 文件上传未完成时,不可以再次上传,不可以下载,右边需要处于加载状态
  2. 文件再次上传后,原文件被覆盖,需要清除之前的fileList
  3. 文件下载接口注意类型为blob

2. 样例

在这里插入图片描述

3.代码

<template><a-row :gutter="8"><a-col :span="8"><a-card title="文件上传"><a-upload-draggerv-model:fileList="fileList"name="files"accept=".txt":multiple="false":action="action"@change="handleChange":disabled="upLoadDisabled":showUploadList="{showRemoveIcon: false}"><p class="ant-upload-drag-icon"><inbox-outlined></inbox-outlined></p><p class="ant-upload-text">点击或将文件拖拽到这里上传, 支持扩展名:.txt</p><p class="ant-upload-hint">仅支持单个文件上传</p><template #removeIcon><StarOutlined></StarOutlined></template></a-upload-dragger></a-card></a-col><a-col :span="16"><a-card><a-spin :spinning="upLoadSpinning" tip="文件加载中..."><a-row :gutter="16"><a-col :span="12"><a-statistic title="正确/错误(个)" :value="trueNum" class="demo-class"><template #suffix><span>/{{ falseNum }}</span></template></a-statistic></a-col><a-col :span="12"><a-statistic title="完善度" :value="wcdPercent" style="margin-right: 50px" /></a-col></a-row></a-spin></a-card><a-card title="文件预览" style="margin-top: 5px"><a-spin :spinning="upLoadSpinning" tip="文件加载中..."><a-tabs v-model:activeKey="activeKey" type="card" @change="tabChange"><a-tab-pane key="0"><template #tab><div>全部</div></template><div style="padding-bottom: 20px; padding-top: 20px"><div v-if="tableData0.length > 0"><a-table :columns="columns" :data-source="tableData0" bordered> </a-table></div><div v-else><div class="emptyStyle"></div></div></div></a-tab-pane><a-tab-pane key="1"><template #tab><div>正确</div></template><div style="padding-bottom: 20px; padding-top: 20px"><div v-if="tableData1.length > 0"><a-table :columns="columns1" :data-source="tableData1" bordered> </a-table></div><div v-else><div class="emptyStyle"></div></div></div></a-tab-pane><a-tab-pane key="2"><template #tab><div>错误</div></template><div style="padding-bottom: 20px; padding-top: 20px"><div v-if="tableData2.length > 0"><a-table :columns="columns1" :data-source="tableData2" bordered> </a-table></div><div v-else><div class="emptyStyle"></div></div></div></a-tab-pane><template #rightExtra><a-button @click="fileDownloadBtn" type="primary" :disabled="fileDownload">文件下载</a-button></template></a-tabs></a-spin></a-card></a-col></a-row>
</template><script setup>import { message } from 'ant-design-vue'import sysConfig from '@/config'import uploadApi from '@/api/auth/uploadApi'import * as XLSX from 'xlsx'import { clone } from 'lodash-es'const props = defineProps({action: {type: String,default: '/biz/file/upload',required: false}})const action = sysConfig.API_URL + props.actionconst fileList = ref([])const handleChange = (info) => {if (fileList.value.length > 1) {fileList.value.shift()}upLoadSpinning.value = trueupLoadDisabled.value = truefileDownload.value = trueconst status = info.file.statusif (status === 'done') {if (info.file.response.code === 200) {message.success(`${info.file.name}上传成功`)trueNum.value = info.file.response.data.trueNumfalseNum.value = info.file.response.data.falseNumwcdPercent.value = info.file.response.data.wcdPercent//文件上传禁选择upLoadDisabled.value = false}//可预览upLoadSpinning.value = false//可下载fileDownload.value = falsepreviewFile(1)} else if (status === 'error') {message.error(`${info.file.name}上传失败`)//文件上传禁选择upLoadDisabled.value = false//可预览upLoadSpinning.value = false//可下载fileDownload.value = false} else if (status === 'removed') {//文件上传禁选择upLoadDisabled.value = false//可预览upLoadSpinning.value = false//可下载fileDownload.value = false}}const activeKey = ref('0')const upLoadSpinning = ref(true)const upLoadDisabled = ref(true)const tableData = ref([])const tableData0 = ref([])const tableData1 = ref([])const tableData2 = ref([])const columns = ref({})const columns1 = ref({})const previewFile = () => {uploadApi.download().then((res) => {const reader = new FileReader()reader.readAsBinaryString(res.data)reader.onload = (ev) => {try {const data = ev.target.resultconst wb = XLSX.read(data, {type: 'binary',cellText: false,cellDates: true})const outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])let tableheader = outdata[0]columns.value = [{title: '序号',dataIndex: '序号',key: '序号'}]columns1.value = [{title: '序号',dataIndex: '序号',key: '序号'}]for (let val in tableheader) {if (val !== '__EMPTY') {columns.value.push({title: val,dataIndex: val,key: val})if (val !== '比对结果') {columns1.value.push({title: val,dataIndex: val,key: val})}}}tableData.value = clone(outdata)tabChange(activeKey.value)} catch (e) {return false}}fileDownload.value = falseupLoadDisabled.value = false//可预览upLoadSpinning.value = false}).catch((error) => {console.log(error)})}const tabChange = (key) => {console.log(key, 'key')if (key === '0') {const tableAll = tableData.valuetableAll.forEach((v, i) => {v['序号'] = v.__EMPTY + 1v = { ...v, key: i + 1 }})tableData0.value = tableAll} else if (key === '1') {const tableTrue = tableData.value.filter((item) => item['比对结果'] === 1)tableTrue.forEach((v, i) => {v['序号'] = i + 1})tableData1.value = tableTrue} else if (key === '2') {const tableFalse = tableData.value.filter((item) => item['比对结果'] === 0)tableFalse.forEach((v, i) => {v['序号'] = i + 1})tableData2.value = tableFalse}}const fileDownload = ref(true)const trueNum = ref(0)const falseNum = ref(0)const wcdPercent = ref(0)const fileDownloadBtn = () => {upLoadSpinning.value = trueupLoadDisabled.value = truefileDownload.value = trueuploadApi.download().then((res) => {message.success('文件下载成功')const blob = new Blob([res.data], { type: 'application/octet-stream;charset=UTF-8' })const $link = document.createElement('a')$link.href = URL.createObjectURL(blob)// $link.download = 'xxx.xlsx'$link.download = 'xxx.csv'$link.click()document.body.appendChild($link)document.body.removeChild($link) // 下载完成移除元素window.URL.revokeObjectURL($link.href) // 释放掉blob对象//文件上传禁选择upLoadDisabled.value = false//可预览upLoadSpinning.value = false//可下载fileDownload.value = false}).catch((error) => {console.log(error)})}onMounted(() => {//文件上传禁选择upLoadDisabled.value = false//可预览upLoadSpinning.value = false})
</script><style scoped>.emptyStyle {height: 200px;background-image: url(../../assets/images/empty1.png);background-position: center;background-repeat: no-repeat;background-size: 200px 200px;cursor: default;}
</style>

二、多文件上传产生的时间超时问题

当上传文件太多时,需要延长请求时间,以减少报错情况

文件路径:src/config/index.js
修改该文件中的TIMEOUT以延长请求时间
在这里插入图片描述

三、文件系统名称更改

1. 修改文件index.html

文件路径:index.html,修改这两处,即可修改刷新系统时候,浏览器显示的系统名称
在这里插入图片描述

2. 修改文件index.js

文件路径:src/config/index.js,修改此处即可修改登陆页面系统名称
在这里插入图片描述

3. 修改数据库存储的系统名称

在这里插入图片描述

四、系统登陆后的首页更改

原始首页为个人首页,若想修改为自己想要的页面,并且面包屑也不显示已去除的个人首页时,需修改文件util.js
文件路径:src/views/auth/login/util.js
在这里插入图片描述

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

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

相关文章

Leetcode热题100:图论

Leetcode 200. 岛屿数量 深度优先搜索法&#xff1a; 对于这道题来说&#xff0c;是一个非常经典的图的问题&#xff0c;我们可以先从宏观上面来看问题&#xff0c;也就是说在不想具体算法的前提下&#xff0c;简单的说出如何找到所有的岛屿呢&#xff1f; 如图中所示&#x…

oracle 19c单机版本补丁升级

文章目录 一、补丁包概述二、备份opatch三、替换高版本opatch四、打DB补丁1、关闭数据库2、关闭监听3、解压补丁4、冲突检测5、补丁空间检查6、执行补丁升级7、将更新内容加载到数据库8、最后查看数据库版本9、卸载补丁包 一、补丁包概述 补丁升级包 链接&#xff1a;https://…

【系统架构设计师】计算机系统基础知识 03

系统架构设计师 - 系列文章目录 01 系统工程与信息系统基础 02 软件架构设计 03 计算机系统基础知识 文章目录 系统架构设计师 - 系列文章目录 文章目录 前言 一、计算机系统概述 1.计算机组成 ​编辑2.存储系统 二、操作系统 ★★★★ 1.进程管理 2.存储管理 1.页式存储 …

Golang Gorm 自动分批查询

场景&#xff1a; 目标查询全量数据&#xff0c;但需要每次Limit分批查询&#xff0c;保护数据库 文档&#xff1a; https://gorm.io/zh_CN/docs/advanced_query.html // Param: // dest 目标地址 // batchSize 大小 // fc 处理函数func (db *DB) FindInBatc…

安卓 Android Activity 生命周期

文章目录 Intro生命周期方法 & 执行顺序结论code Intro 本文提供一个测试类通过打印的方式展示在多个Activity之间互相跳转的时候&#xff0c;各个Activity的生命周期相关方法的执行顺序。 生命周期方法 & 执行顺序结论 下图出自 郭霖 《第一行代码&#xff08;第二…

电网的正序参数和等值电路(一)

本篇为本科课程《电力系统稳分析》的笔记。 本篇为第二章的第一篇笔记。 电力系统正常运行中&#xff0c;可以认为系统的三相结构和三相负荷完全对称。而对称三相的计算可以用一相来完成&#xff0c;其中所有给出的标称电压都是线电压的有效值&#xff0c;假定系统全部是Y-Y型…

【网站项目】291校园疫情防控系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

The 2023 Guangdong Provincial Collegiate Programming Contest

I. Path Planning 嗯&#xff0c;怎么说呢&#xff0c;一般二维图&#xff0c;数据不是很大的比如n*m*log级别允许的&#xff0c;如果一眼不是bfs&#xff0c;可以考虑结合一下二分 本题可知&#xff0c;只能向下或者向右&#xff0c;那么我们就像如果答案为x&#xff0c;那么…

windows下使用压缩包安装mysql8.0数据库

获取安装包 可以访问mysql 官网下载压缩安装包 &#xff08;官网地址&#xff1a;https://downloads.mysql.com/archives/community/&#xff09; 根据自己的需要&#xff0c;下载对应mysql版本&#xff0c;我选择是是8.0.16版本 安装 解压之后&#xff0c;可以看到压缩包…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《基于老化成本实时次梯度的异构储能系统功率分配策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

Vue3 大量赋值导致reactive响应丢失问题

问题阐述 如上图所示&#xff0c;我定义了响应式对象arrreactive({data:[]})&#xff0c;尝试将indexedDB两千条数据一口气赋值给arr.data。但事与愿违&#xff0c;页面上的{{}}在展示先前数组的三秒后变为空。 问题探究 vue3的响应应该与console.log有异曲同工之妙&#xff0…

如何系统的入门大模型?

GPT图解&#xff0c;从0到1构建大模型。 本书将以生动活泼的笔触&#xff0c;将枯燥的技术细节化作轻松幽默的故事和缤纷多彩的图画&#xff0c;引领读者穿梭于不同技术的时空&#xff0c;见证自然语言处理技术的传承、演进与蜕变。在这场不断攀登技术新峰的奇妙之旅中&#xf…

如何进行软件测试

1、测试用例带给我们的好处 &#xff08;1&#xff09;测试执行者的依据 &#xff08;2&#xff09;使得工作可重复&#xff0c;自动化测试的基础 &#xff08;3&#xff09;评估需求覆盖率 &#xff08;4&#xff09;用例的复用 &#xff08;5&#xff09;积累测试的方法思…

嵌入式典型总线及协议

在嵌入式系统中&#xff0c;各种总线和通信协议扮演着关键的角色&#xff0c;它们连接和协调系统中的各种硬件组件&#xff0c;实现数据传输和控制。本文将介绍一些典型的嵌入式总线及其通信协议&#xff0c;以及它们在嵌入式系统中的应用。 以下是我整理的关于嵌入式开发的一…

华为OD机试 - 按照路径替换二叉树(Java 2024 C卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff…

FreeRTOS教程10 低功耗

目录 1、准备材料 2、学习目标 3、前提知识 3.1、HAL 库基础时钟 3.1.1、使用 SysTick 定时器 3.1.1.1、工作原理 3.1.1.2、中断处理 3.1.2、使用其他定时器 3.1.2.1、工作原理 3.1.2.2、中断处理 3.2、FreeRTOS 基础时钟 3.2.1、工作原理 3.2.2、中断处理 3.3、…

基于SpringBoot精品在线试题库系统

采用技术 基于SpringBoot精品在线试题库系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 系统功能结构图 学生管理 教师管理 专业管理 试卷管理 …

美食杂志制作秘籍:引领潮流,引领味蕾

美食杂志是一种介绍美食文化、烹饪技巧和美食体验的杂志&#xff0c;通过精美的图片和生动的文字&#xff0c;向读者展示各种美食的魅力。那么&#xff0c;如何制作一本既美观又实用的美食杂志呢&#xff1f; 首先&#xff0c;你需要选择一款适合你的制作软件。比如FLBOOK在线制…

VUE+Vant实现H5组织架构选人选公司组件

提醒自己&#xff1a; 这是之前的逻辑&#xff0c;或许你重新写会有更好的方法&#xff0c;可以参考逻辑&#xff01;&#xff01;&#xff01; 功能介绍 1.有面包屑点击切换 2.有公司、部门、人员 3.单选、多选实现 4.编辑/回显 5.使用随意切换层级和跳转到指定层级回显等功…

设计编程网站集:生活部分:饮食+农业,植物(暂记)

这里写目录标题 植物相关综合教程**大型植物&#xff1a;****高大乔木&#xff08;Trees&#xff09;&#xff1a;** 具有坚硬的木质茎&#xff0c;通常高度超过6米。例如&#xff0c;橡树、松树、榉树等。松树梧桐 **灌木&#xff08;Shrubs&#xff09;&#xff1a;** 比乔木…