vue-element-admin导入组件封装
模板和样式
首先封装一个类似的组件,首先需要注意的是,类似功能,vue-element-admin已经提供了,我们只需要改造即可
excel导入功能需要使用npm包xlsx,所以需要安装xlsx插件
npm i xlsx
将vue-element-admin提供的导入功能新建一个组件,位置: src/components/UploadExcel
import CommonTools from './CommonTools' import UploadExcel from './UploadExcel' export default { install(Vue) { Vue.component('CommonTools', CommonTools) // 注册工具栏组件 Vue.component('UploadExcel', UploadExcel) // 注册导入excel组件 } }
修改样式和布局
<template> <div> <div> <el-button :loading="loading" size="mini" type="primary" @click="handleUpload"> 点击上传 </el-button> </div> <input ref="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick"> <div @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover"> <i /> <span>将文件拖到此处</span> </div> </div> </template> <script> import XLSX from 'xlsx' export default { props: { beforeUpload: Function, // eslint-disable-line onSuccess: Function// eslint-disable-line }, data() { return { loading: false, excelData: { header: null, results: null } } }, methods: { generateData({ header, results }) { this.excelData.header = header this.excelData.results = results this.onSuccess && this.onSuccess(this.excelData) }, handleDrop(e) { e.stopPropagation() e.preventDefault() if (this.loading) return const files = e.dataTransfer.files if (files.length !== 1) { this.$message.error('Only support uploading one file!') return } const rawFile = files[0] // only use files[0] if (!this.isExcel(rawFile)) { this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files') return false } this.upload(rawFile) e.stopPropagation() e.preventDefault() }, handleDragover(e) { e.stopPropagation() e.preventDefault() e.dataTransfer.dropEffect = 'copy' }, handleUpload() { this.$refs['excel-upload-input'].click() }, handleClick(e) { const files = e.target.files const rawFile = files[0] // only use files[0] if (!rawFile) return this.upload(rawFile) }, upload(rawFile) { this.$refs['excel-upload-input'].value = null // fix can't select the same excel if (!this.beforeUpload) { this.readerData(rawFile) return } const before = this.beforeUpload(rawFile) if (before) { this.readerData(rawFile) } }, readerData(rawFile) { this.loading = true return new Promise((resolve, reject) => { const reader = new FileReader() reader.onload = e => { const data = e.target.result const workbook = XLSX.read(data, { type: 'array' }) const firstSheetName = workbook.SheetNames[0] const worksheet = workbook.Sheets[firstSheetName] const header = this.getHeaderRow(worksheet) const results = XLSX.utils.sheet_to_json(worksheet) this.generateData({ header, results }) this.loading = false resolve() } reader.readAsArrayBuffer(rawFile) }) }, getHeaderRow(sheet) { const headers = [] const range = XLSX.utils.decode_range(sheet['!ref']) let C const R = range.s.r /* start in the first row */ for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */ const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] /* find the cell in the first row */ let hdr = 'UNKNOWN ' + C // <-- replace with your desired default if (cell && cell.t) hdr = XLSX.utils.format_cell(cell) headers.push(hdr) } return headers }, isExcel(file) { return /\.(xlsx|xls|csv)$/.test(file.name) } } } </script> <style scoped lang="scss"> .upload-excel { display: flex; justify-content: center; margin-top: 100px; .excel-upload-input{ display: none; z-index: -9999; } .btn-upload , .drop{ border: 1px dashed #bbb; width: 350px; height: 160px; text-align: center; line-height: 160px; } .drop{ line-height: 80px; color: #bbb; i { font-size: 60px; display: block; } } } </style>
创建路由和组件
建立公共导入的页面路由,新建一个公共的导入页面,挂载路由 src/router/index.js
path: '/import', component: Layout, hidden: true, // 隐藏在左侧菜单中 children: [{ path: '', // 二级路由path什么都不写 表示二级默认路由 component: () => import('@/views/import') }] },
创建import路由组件 src/views/import/index.vue
<template> <!-- 公共导入组件 --> <upload-excel :on-success="success" /> </template>
实现导入封装导入用户的api接口
export function importUser(data) { return request({ url: 'user/batch', method: 'post', data }) }
获取导入的excel数据, 导入excel接口