当前位置: 首页 > news >正文

vue3-导入导出文件和打印文件

调用api下载excel文件

export const exportShopTarget = (参数) => request.get(`api链接?查询参数`, { Body请求参数 }, { responseType: 'blob' } )

一定要加上responseType: 'blob'这个参数,否则会显示文件损坏

下载单个文件:

const exportData = async () => { try { const response = await exportShopTarget(参数) const url = window.URL.createObjectURL(new Blob([response.data])) const link = document.createElement('a') link.href = url link.setAttribute( 'download', `目标数据.xlsx` ) // 设置下载文件的名称 document.body.appendChild(link) link.click() // 清理:释放内存中的URL对象 document.body.removeChild(link) window.URL.revokeObjectURL(url) } catch (error) { ElMessage({ message: `导出失败`, type: 'error' }) } }

批量下载压缩文件:

把selectedFileList数组使用encodeURIComponent编码传递

const encodedElements = selectedFileList.value.map((item) => '"' + item + '"') const queryString = encodedElements.join(',') const codeListEncoded = encodeURIComponent('[' + queryString + ']') const response = await downloadFile(codeListEncoded) if (response.status === 200) { const url = window.URL.createObjectURL(new Blob([response.data])) const link = document.createElement('a') link.href = url link.setAttribute('download', '批量下载.zip') document.body.appendChild(link) link.click() document.body.removeChild(link) loading.value = false } else { ElMessage({ message: `文件下载失败,${response.data.msg}`, type: 'error' }) }

读取excel文件里的数据转化为json数组

首先安装xlsx

pnpm install xlsx
import * as XLSX from 'xlsx' const file = fileList.value[0] const reader = new FileReader() reader.onload = async (e) => { const data = new Uint8Array(e.target.result) const workbook = XLSX.read(data, { type: 'array' }) const sheetName = workbook.SheetNames[0] // 获取第一个工作表的名称 const worksheet = workbook.Sheets[sheetName] const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) // header: 1 表示第一行作为头部信息 console.log(jsonData.splice(1))//获取除去表头的json数据 } reader.readAsArrayBuffer(file)

下载静态excel文件模板

把文件放置在public文件里面的static文件里,文件名要用英文

<el-button type="primary" color="#A88D5B"> <a href="/static/importTemplate.xlsx" download="店铺目标导入模板" style="color: white; text-decoration: none" >下载导入模板 </a> </el-button>

调用api上传文件

import request from '@/utils/request' //文件上传接口 export const fileUpload = (formData) => request.post('接口', formData, { headers: { 'Content-Type': 'multipart/form-data' // 设置 Content-Type 为 multipart/form-data } })
import { fileUpload } from '@/api/file.js' import { ref } from 'vue' const selectedFileList = ref({ fileList: [], codeList: [] }) const uploadFile = (e, code) => { let file = e.target.files[0] // 获取选中的文件 if (file) { selectedFileList.value.fileList.push(file)//文件列表 selectedFileList.value.codeList.push(code)//文件对应的code列表 } e.target.value = '' // 允许重复上传同一个文件 } const submit = () => { if (selectedFileList.value.fileList.length === 0) { ElMessage({ message: '请至少勾选一个要上传的文件', type: 'warning' }) return } ElMessageBox.confirm( `确认上传已勾选的${selectedFileList.value.fileList.length}个文件?`, '温馨提示', { type: 'info', confirmButtonText: '确认', cancelButtonText: '取消', confirmButtonClass: 'ExitConfirmButton', cancelButtonClass: 'ExitCancelButton' } ) .then(async () => { let formData = new FormData() selectedFileList.value.fileList.forEach((fileObj, index) => { formData.append(`files[${index}]`, fileObj) }) selectedFileList.value.codeList.forEach((code, index) => { formData.append(`fileCodes[${index}]`, code) }) const response = await fileUpload(formData) if (response.data.code === 0) { ElMessage({ message: '文件上传成功', type: 'success' }) filterFileList() selectedFileList.value = { fileList: [], codeList: [] } } else { ElMessage({ message: `文件上传失败,${response.data.msg}`, type: 'error' }) } }) .catch(() => { //取消后执行 }) }
<input type="file" @change="(e) => uploadFile(e,文件code)" />

使用formData上传文件的注意点:

1.api接口里要加headers: {
'Content-Type': 'multipart/form-data'
}

2.formData就类似于一个对象,使用api传递时外面就不要包{}了,就变成json类型了

3.formData.append(参数名, 值):参数名要和后端对应上

4.查看是否携带内容,标头有内容长度

打印文件

const printTotal = async () => { const content = printFrame.value.contentWindow.document content.open() content.write(document.getElementById('salesTotal').innerHTML) // 获取并写入内容 content.close() printFrame.value.contentWindow.print() }
<ticketTotal style="zoom: 1.5" id="salesTotal" />

可以打印某个组件里的内容,而不打印全部页面,而且也不影响其他的运行

zoom: 1.5的作用是放大/缩小组件的显示

或者写成:

const getPrintHtml = (elementId) => { const el = document.getElementById(elementId) if (!el) return '' const clone = el.cloneNode(true) clone.removeAttribute('id') clone.style.zoom = '1' clone.style.marginTop = '0' return clone.outerHTML } const printDocument = (elementId) => { const html = getPrintHtml(elementId) if (!html) return const doc = printFrame.value.contentWindow.document doc.open() doc.write(`<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> @page { size: 80mm auto; margin: 0; } html, body { margin: 0; padding: 0; width: auto; height: auto; } @media print { html, body { height: auto; overflow: visible; } } </style> </head> <body>${html}</body> </html>`) doc.close() printFrame.value.contentWindow.print() } const printTotal = () => printDocument('salesTotal')

style设置的解析:

  • @page { size: 80mm auto; margin: 0; }— 按热敏小票宽度(约 80mm,可根据打印机实际宽度来调整),高度随内容自动伸缩;设置margin: 0会去掉勾选系统自带的页眉和页脚功能
  • margin: 0; padding: 0
    去掉浏览器默认边距,避免四周多出空白。

  • width/height: auto
    让页面宽高跟小票内容走,而不是固定成一整页屏幕高度。

  • @media print里的height: auto+overflow: visible
    只在真正打印时生效:高度仍随内容伸缩,内容不被裁切,方便配合上面的@page { size: 80mm auto }做「纸宽固定、纸高自适应」。

http://www.jsqmd.com/news/1192131/

相关文章:

  • 温州市泰顺县 2026最新靠谱黄金回收门店TOP排行榜 黄金回收白银回收铂金回收店铺及电话地址推荐 - 盛世金银回收
  • 运算器实验——从74LS181到进位锁存:8位ALU的时序与状态管理实战
  • 蓝牙音频模块与共振喇叭技术:嵌入式音频设备开发指南
  • 汽车级升压控制器LM51501-Q1设计:宽压输入、低IQ与EMI优化实战
  • 2026 年更新:聊城优秀的玻璃纤维聚酯防腐板生产商哪家强,厂房倒闭前老板才发现:这玩意儿竟让维修费暴跌90% - 行业鉴选官
  • 亲身到店探访广州伯爵官方售后服务中心|完整官方电话和网点地址(2026年7月最新) - 亨得利钟表维修中心
  • RabbitMQ 高级特性
  • 如何为r2modmanPlus添加多语言支持:3步实现国际化界面
  • 生产级pandas多维聚合:性能、可维护性与下游兼容性实战
  • 如何用OpenCore Legacy Patcher让老旧Mac重获新生:完整免费升级指南
  • 温州市文成县 2026最新靠谱黄金回收门店TOP排行榜 黄金回收白银回收铂金回收店铺及电话地址推荐 - 盛世金银回收
  • Geant4粒子模拟实践:从核心架构到工程实现
  • 实战全流程:浏览器端语音识别系统Whisper Web深度解析与部署指南
  • 从零构建高性能力矩控制器:C++实现与嵌入式实战指南
  • 《The Finals》UE5引擎崩溃闪退问题:从原理到实战的完整解决指南
  • 临沂市罗庄区亨得利官方名表服务中心电话公示(2026年7月最新) - 亨得利官方
  • 头歌:从SQL约束到CIA模型,构建数据安全的第一道防线
  • NumPy索引与切片:从基础到高级数据提取实战
  • 温州市永嘉县 2026最新靠谱黄金回收门店TOP排行榜 黄金回收白银回收铂金回收店铺及电话地址推荐 - 盛世金银回收
  • 本地商家如何用Google Maps做竞对分析
  • 5步掌握开源量化交易框架:从数据采集到策略执行
  • 64位Linux栈溢出利用:return-to-csu技术原理与实践
  • SAP ABAP 标准Excel导出:兼容Web的实战方案解析
  • FFT频谱分析实战:从原理到误差控制的MATLAB实验指南
  • 从OSI到TCP/IP:网络分层模型的演进、对比与实战协议映射
  • TPS25814 Type-C控制器硬件配置、I2C通信与电源管理实战解析
  • MATLAB机器视觉工具箱:从算法调用到自动化视觉检测系统构建
  • 劳力士冰蓝迪计时功能的专业保养与维修指南权威公示(2026年7月最新) - 劳力士服务中心
  • Vibe Coding实战指南:从自然语言到可执行代码的完整开发流程
  • UE5 C++编译失败终极排查指南:从环境配置到错误解决