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数组首先安装xlsxpnpm install xlsximport * 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 typeprimary color#A88D5B a href/static/importTemplate.xlsx download店铺目标导入模板 stylecolor: 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 typefile 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 stylezoom: 1.5 idsalesTotal /可以打印某个组件里的内容而不打印全部页面而且也不影响其他的运行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 charsetUTF-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: autooverflow: visible只在真正打印时生效高度仍随内容伸缩内容不被裁切方便配合上面的page { size: 80mm auto }做「纸宽固定、纸高自适应」。