阅读量:0
一、配置api
// 题目导入模板下载接口 export function exportTemplate() { return request({ url: '/edu/question/exportTemplate', method: 'get', //必加 header: { headers: { 'Content-Type': 'application/x-download' }, }, responseType: "blob",//必加 }) } // 题目模板数据导入接口 export function importTemplate(file) { const data = new FormData()//必加 data.append('file', file)//必加 return request({ url: '/edu/question/import', method: 'post', data }) }
二、vue中引用Api
import { exportTemplate, importTemplate, } from "@/api/edu/question";
三、引用下载文件的方法
//引用下载文件的方法 import { download } from "@/utils/excel";
方法:/utils/excel
/** * 通用js方法封装处理 * Copyright (c) 2019 */ /** * 参数处理 * @param {*} params 参数 */ // 封装exceljs import ExcelJS from 'exceljs' import FileSaver from 'file-saver' export function tansParams(params) { let result = '' for (const propName of Object.keys(params)) { const value = params[propName] let part = `${encodeURIComponent(propName)}=` if (value !== null && value !== '' && typeof value !== 'undefined') { if (typeof value === 'object') { for (const key of Object.keys(value)) { if ( value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined' ) { let params = `${propName}[${key}]` let subPart = `${encodeURIComponent(params)}=` result += `${subPart + encodeURIComponent(value[key])}&` } } } else { result += `${part + encodeURIComponent(value)}&` } } } return result } // 验证是否为blob格式 export function blobValidate(data) { return data.type !== 'application/json' } // export function getSrc(url) { // return `https://${url}` // } // 得到字典某个值的内容 export function getDictLabel(dict, value) { let res = dict.filter((item) => item.value === value) return res[0] } // promise 只执行一次 export function oncePromise(fn, p = null) { return function (...arg) { // eslint-disable-next-line no-return-assign return p || (p = fn(...arg).finally(() => (p = null))) } } /** * 导出数据到Excel方法 * @param {Array[Object]} config.data 表格数据 * @param {Array[String]} config.fields 字段列表 * @param {Array[String]} config.headers excel表头列表[[]],可以是多级表头[['A1','B1'],['A2','B2']] * @param {Array[Object]} config.merges 需要合并的单元格,需要考虑表头的行数[{row:1, col:1, rowspan: 1, colspan: 2}] * @param {Array[Object]} config.attrs 单元格样式配置 * @param {Array[Object]} config.views 工作表视图配置 * @param {Array[Number]} columnsWidth 每个字段列对应的宽度 * @param {Object} config.protect 工作表保护【此配置会保护全表,一般推荐只针对单元格进行保护配置】 * @param {String} sheetName 工作表名称,默认从sheet1开始 * @param {String} fileName excel文件名称 */ export function exportDataToExcel(config, fileName) { if (!config) return const options = { fileName: fileName || `导出excel文件【${Date.now()}】.xlsx`, worksheets: [], } if (!Array.isArray(config)) { config = [config] } config.forEach((item) => { // 深拷贝data【JSON.stringify有缺陷,可自行换成_.cloneDeep】 const data = JSON.parse(JSON.stringify(item.data)) const results = data.map((obj) => item.fields.map((key) => obj[key])) // 生成完整excel数据 let excelData = [] excelData = excelData.concat(item.headers).concat(results) // 单元格合并处理【excel数据的第一行/列是从1开始】 let excelMerges = [] excelMerges = item.merges.map((m) => [ m.row + 1, m.col + 1, m.row + m.rowspan, m.col + m.colspan, ]) // 单元格配置处理【excel数据的第一行/列是从1开始】 let excelAttrs = [] excelAttrs = item.attrs.map((attr) => { attr.rowStart += 1 attr.rowEnd += 1 attr.colStart += 1 attr.colEnd += 1 return attr }) options.worksheets.push({ data: excelData, merges: excelMerges, attrs: excelAttrs, views: item.views, columnsWidth: item.columnsWidth, protect: item.protect, sheetName: item.sheetName, }) }) createExcel(options) } // 创建Excel文件方法 async function createExcel(options) { if (!options.worksheets.length) return // 创建工作簿 const workbook = new ExcelJS.Workbook() for (let i = 0; i < options.worksheets.length; i++) { const sheetOption = options.worksheets[i] // 创建工作表 const sheet = workbook.addWorksheet( sheetOption.sheetName || `sheet${i + 1}` ) // 添加数据行 sheet.addRows(sheetOption.data) // 配置视图 sheet.views = sheetOption.views // 单元格合并处理【开始行,开始列,结束行,结束列】 if (sheetOption.merges) { sheetOption.merges.forEach((item) => { sheet.mergeCells(item) }) } // 工作表保护 if (sheetOption.protect) { const res = await sheet.protect( sheetOption.protect.password, sheetOption.protect.options ) } // 单元格样式处理 if (sheetOption.attrs.length) { sheetOption.attrs.forEach((item) => { const attr = item.attr || {} // 获取开始行-结束行; 开始列-结束列 const { rowStart } = item const { rowEnd } = item const { colStart } = item const { colEnd } = item if (rowStart) { // 设置行 for (let r = rowStart; r <= rowEnd; r++) { // 获取当前行 const row = sheet.getRow(r) if (colStart) { // 列设置 for (let c = colStart; c <= colEnd; c++) { // 获取当前单元格 const cell = row.getCell(c) Object.keys(attr).forEach((key) => { // 给当前单元格设置定义的样式 cell[key] = attr[key] }) } } else { // 未设置列,整行设置【大纲级别】 Object.keys(attr).forEach((key) => { row[key] = attr[key] }) } } } else if (colStart) { // 未设置行,只设置了列 for (let c = colStart; c <= colEnd; c++) { // 获取当前列,整列设置【大纲级别】 const column = sheet.getColumn(c) Object.keys(attr).forEach((key) => { column[key] = attr[key] }) } } else { // 没有设置具体的行列,则为整表设置 Object.keys(attr).forEach((key) => { sheet[key] = attr[key] }) } }) } // 列宽设置 if (sheetOption.columnsWidth) { for (let j = 0; j < sheet.columns.length; j++) { sheet.columns[j].width = sheetOption.columnsWidth[j] } } } // 生成excel文件 workbook.xlsx.writeBuffer().then((buffer) => { // application/octet-stream 二进制数据 FileSaver.saveAs( new Blob([buffer], { type: 'application/octet-stream' }), options.fileName ) }) } // 下载文件流文件 export const download = (res, type, filename) => { // 创建blob对象,解析流数据 const blob = new Blob([res], { // 设置返回的文件类型 // type: 'application/pdf;charset=UTF-8' 表示下载文档为pdf,如果是word则设置为msword,excel为'application/vnd.ms-excel' type, }) // 这里就是创建一个a标签,等下用来模拟点击事件 const a = document.createElement('a') // 兼容webkix浏览器,处理webkit浏览器中href自动添加blob前缀,默认在浏览器打开而不是下载 const URL = window.URL || window.webkitURL // 根据解析后的blob对象创建URL 对象 const href = URL.createObjectURL(blob) // 下载链接 a.href = href // 下载文件名,如果后端没有返回,可以自己写a.download = '文件.pdf' a.download = filename document.body.appendChild(a) // 点击a标签,进行下载 a.click() // 收尾工作,在内存中移除URL 对象 document.body.removeChild(a) window.URL.revokeObjectURL(href) }
三、添加点击事件下载
HTML:
<template> <!-- 导入对话框 --> <el-dialog :title="title" :visible.sync="localImportShow" width="600px" @close="localImportClose" append-to-body > <el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-row> <el-col :span="24"> <el-form-item label="下载模板" prop="downloadTemplate"> <el-button type="primary" @click="downloadCClick"> 下载 <i class="el-icon-download"></i> </el-button> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="导入数据" prop="file"> <el-upload ref="uploadExcel" class="upload-btn" action="#" :auto-upload="false" accept=".xls, .xlsx" :show-file-list="true" :file-list="form.file" :on-change="change" :on-remove="handleRemove" :limit="1" > <el-button slot="trigger" size="small" type="primary"> 选取文件 </el-button> </el-upload> </el-form-item> </el-col> </el-row> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </div> </el-dialog> </template>
VUEJS:
<script> import { exportTemplate, importTemplate } from "@/api/edu/question"; import { download } from "@/utils/excel"; export default { props: { //弹出框是否展示 importShow: { type: Boolean, default: false, }, }, data() { return { title: "导入试题数据", form: { file: [], }, // 弹出框是否展示 localImportShow: this.importShow, rules: { file: [{ required: true, message: "请导入数据", trigger: "change" }], }, }; }, watch: { importShow(newVal) { this.localImportShow = newVal; }, "form.file": { handler(nval) { if (nval.length) { this.$refs.form.clearValidate(["file"]); } }, deep: true, }, }, methods: { localImportClose() { this.$emit("update:importShow", false); this.reset(); }, // 点击下载模板按钮 downloadCClick() { exportTemplate().then((res) => { download(res, "application/vnd.ms-excel", "试题模板.xlsx"); }); }, // 更换上传文件 change({ raw }) { //使用set watch才能监测到有值 this.$set(this.form.file, 0, raw); }, handleRemove(file, fileList) { // 移除上传文件 this.form.file = []; }, // 提交事件 submitForm() { this.$refs["form"].validate((valid) => { if (valid) { importTemplate(this.form.file[0]) .then((res) => { if (res.code === 200) { this.localImportShow = false; this.$modal.msgSuccess("导入成功"); this.$emit("getList"); } }) .catch((err) => { this.localImportShow = false; }); this.$nextTick(() => { this.reset(); }); } }); }, // 取消按钮 cancel() { this.localImportShow = false; this.reset(); }, // 重置数据 reset() { this.$refs.form.clearValidate(); this.form = { // parentId: null, file: [], }; }, }, }; </script>