从vue-element-admin中提供的excel导入功能迁移到当前的项目中
安装插件
npm install xlsx
将vue-element-admin提供的组件复制到我们自己的项目 **src/components/UploadExcel
**下
注册为全局组件
新建一个公共的导入页面,import路由组件src/views/import/index.vue
在页面中使用前面封装的excel上传组件,并补充导入成功后的回调函数
<template>
<upload-excel :on-success="handleSuccess" />
template>
<script>
export default {
name: 'Import',
methods: {
handleSuccess({ header, results }) {
console.log(header, results)
}
}
}
script>
这个路由不需要根据权限控制,也不需要显示在左侧菜单 ,直接定义为静态路由即可。在**src/router/index.js
**下的静态路由中添加一个路由
{
path: '/import',
component: Layout,
hidden: true, // 不显示到左侧菜单
children: [{
path: '',
component: () => import('@/views/import')
}]
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-geLsuA7b-1629724067018)(解决跨域的几种方法.assets/image-20210823205507375.png)]
handleSuccess({ header, results }) {
// header 标题
// ['姓名','手机号']
// results excel表格的内容
// [ {'姓名':'小张', '手机号': '13712345678'}, {.....} ]
console.log(header, results)
}
处理内容包含:
姓名
,而后端需要的是username
为了方便维护代码,单独封装一个方法来实现这个转换的功能。
/**
* results excel表格的内容
// [
{'姓名':'小张', '手机号': '13712345678'}
, {.....}
]
// 目标
// [ {'username':'小张','mobile': '13712345678'}, {.....} ]
*/
// 把一个对象数组中的每个对象的属性名,从中文改成英文
// 思路:对于原数组每个对象来说
// (1) 找出所有的中文key
// (2) 得到对应的英文key
// (3) 拼接一个新对象: 英文key:值
transExcel(results) {
const mapInfo = {
'入职日期': 'timeOfEntry',
'手机号': 'mobile',
'姓名': 'username',
'转正日期': 'correctionTime',
'工号': 'workNumber',
'部门': 'departmentName',
'聘用形式': 'formOfEmployment'
}
return results.map(zhObj => {
const enObj = {}
const zhKeys = Object.keys(zhObj) // ['姓名', '手机号']
zhKeys.forEach(zhKey => {
const enKey = mapInfo[zhKey]
enObj[enKey] = zhObj[zhKey]
})
return enObj
})
}
// 把excel文件中的日期格式的内容转回成标准时间
// https://blog.csdn.net/qq_15054679/article/details/107712966
export function formatExcelDate(numb, format = '/') {
const time = new Date((numb - 25567) * 24 * 3600000 - 5 * 60 * 1000 - 43 * 1000 - 24 * 3600000 - 8 * 3600000)
time.setYear(time.getFullYear())
const year = time.getFullYear() + ''
const month = time.getMonth() + 1 + ''
const date = time.getDate() + ''
if (format && format.length === 1) {
return year + format + month + format + date
}
return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
}
import { formatExcelDate } from '@/utils/index.js'
// 更新格式转换函数
transExcel(results) {
const mapInfo = {
'入职日期': 'timeOfEntry',
'手机号': 'mobile',
'姓名': 'username',
'转正日期': 'correctionTime',
'工号': 'workNumber',
'部门': 'departmentName',
'聘用形式': 'formOfEmployment'
}
return results.map(zhObj => {
const enObj = {}
const zhKeys = Object.keys(zhObj) // ['姓名', '手机号']
zhKeys.forEach(zhKey => {
const enKey = mapInfo[zhKey]
+ if (enKey === 'timeOfEntry' || enKey === 'correctionTime') {
// 后端需要的日期格式是标准时间
+ enObj[enKey] = new Date(formatExcelDate(zhObj[zhKey]))
} else {
enObj[enKey] = zhObj[zhKey]
}
})
return enObj
})
}
/**
* @description: 导入excel
* @param {*} data
* @return {*}
*/
export function importEmployee(data) {
return request({
url: '/sys/user/batch',
method: 'post',
data
})
}
导入API
封装doImport
import { importEmployee } from '@/api/employees'
async doImport(data) {
try {
const res = await importEmployee(data)
console.log('importEmployee', res)
this.$message.success('导入成功')
// 页面后退
this.$router.back()
} catch (err) {
console.log('importEmployee', err)
this.$message.error('导入失败')
}
},
// 1. 把数据从excel文件读入到浏览器内存
handleSuccess({ header, results }) {
console.log(header, results)
// 2. 按接口要求 组装数据
const data = this.transExcel(results)
console.log('按接口要求 组装数据', data)
// 3. 调用接口做上传
this.doImport(data)
}
插件包位于src/vendor/export2Excel
中,采用的是按需引入的方式
什么时候正式要使用导出功能了,插件才会被正式引入到应用里
import('@/vendor/Export2Excel').then(excel => {})
Export2Excel
依赖的包有js-xlsx
、file-saver
和script-loader
也就是说,在项目跑起来之前要安装依赖
npm install file-saver script-loader --save
将vue-element-admin中的src/vendor/export2Excel复制到项目中,直接使用
import('@/vendor/Export2Excel').then(excel => {
// excel表示导入的模块对象
console.log(excel)
excel.export_json_to_excel({
header: ['姓名', '工资'], // 表头 必填
data: [
['刘备', 100],
['关羽', 500]
], // 具体数据 必填
filename: 'excel-list', // 文件名称
autoWidth: true, // 宽度是否自适应
bookType: 'xlsx' // 生成的文件类型
})
})
Excel导出参数说明
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
header | 导出数据的表头 | Array | / | [] |
data | 导出的具体数据 | Array | / | [[]] |
filename | 导出文件名 | String | / | excel-list |
autoWidth | 单元格是否要自适应宽度 | Boolean | true / false | true |
bookType | 导出文件类型 | String | xlsx, csv, txt, more | xlsx |
formatData(list) {
const map = {
'id': '编号',
'password': '密码',
'mobile': '手机号',
'username': '姓名',
'timeOfEntry': '入职日期',
'formOfEmployment': '聘用形式',
'correctionTime': '转正日期',
'workNumber': '工号',
'departmentName': '部门',
'staffPhoto': '头像地址'
}
console.log(list)
let header = []
// header = ['id', 'mobile', 'username', .....]
// data = [
// ['65c2', '1380000002', '管理员', ....],
// ['65c3', '1380000003', '孙财', ....],
// ]
let data = []
// 开始代码
// 找到一个元素
const one = list[0]
if (!one) {
return { header, data }
}
header = Object.keys(one).map(key => {
return map[key]
})
// data把list中每一个对象转成 对应的value数组
data = list.map(obj => {
// 把 Obj['formOfEmployment']: 1 , 2 ---> '正式', '非正式'
const key = obj['formOfEmployment'] // 1, 2
obj['formOfEmployment'] = hireTypEnmu[key] // hireTypEnmu:{1:'正式', '2':'非正式' }
return Object.values(obj)
})
return { header, data }
},
hExport() {
import('@/vendor/Export2Excel').then(async excel => {
// 发ajax请求,获取数据
const res = await getEmployee(this.page, this.size)
const list = res.data.rows
console.log('从后端获取的数据', list)
const { header, data } = this.formatData(list)
// excel表示导入的模块对象
console.log(header, data)
excel.export_json_to_excel({
// header: ['姓名', '工资'], // 表头 必填
header: header, // 表头 必填
data: data,
// data: [
// ['刘备11111111111111', 100],
// ['关羽', 500]
// ], // 具体数据 必填
filename: 'excel-list', // 文件名称
autoWidth: true, // 宽度是否自适应
bookType: 'xlsx' // 生成的文件类型
})
})
},