持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
当然我们主角还是vue-element-admin啦,一个半成品的后台管理系统,那么接下来看看这个文件给我们提供了什么条件吧
实现的功能
批量新增员工就需要excel的导入导出啦
员工导入组件封装
目标
:封装一个导入excel数据
的组件
首先封装一个类似的组件,首先需要注意的是,类似功能,vue-element-admin已经提供了,我们只需要改造即可 代码地址
类似功能性的组件,我们只需要会使用和封装即可
excel导入功能需要使用npm包**xlsx
,所以需要安装xlsx
**插件 (new FileReader() 选中了某个文件, 可以通过FileReader去读)
$ yarn add xlsx
复制代码
将vue-element-admin提供的导入功能新建一个组件,位置:
src/components/UploadExcel
注册全局的导入excel组件
// 该文件, 可以进行组件的批量全局注册, 可以以插件的方式使用 => Vue.use(xxx)
// 将来这个插件(对象), 被Vue.use使用时, 会执行内部的install方法, 进行插件的初始化
import PageTools from './PageTools'
import UploadExcel from './UploadExcel'
export default {
// 插件的初始化, 插件给你提供的全局的功能, 都可以在这里配置
install(Vue) {
// 进行组件的全局注册
Vue.component('PageTools', PageTools) // 注册工具栏组件
Vue.component('UploadExcel', UploadExcel) // 注册导入excel组件
}
}
复制代码
温馨小提示:如果你引入组件上传文件报错的话,打开vue-element-admin源代码中瞅瞅,看看XLSX的安装是不是指定的版本,如果不是可以加上* as 导入:如下图
建立公共导入的页面路由
新建一个公共的导入页面, 即import路由组件 src/views/import/index.vue
<template>
<upload-excel />
</template>
<script>
export default {
name: 'Import'
}
</script>
复制代码
挂载路由src/router/index.js
{
path: '/import',
component: Layout,
hidden: true, // 隐藏在左侧菜单中
children: [{
path: '', // 二级路由path什么都不写 表示二级默认路由
component: () => import('@/views/import')
}]
},
复制代码
效果图:
分析excel导入代码,封装接口
从点击按钮开始, 分析代码, 这里点击按钮, 触发了input:file 的click事件, 进行了上传
<div class="btn-upload">
<el-button :loading="loading" size="mini" type="primary" @click="handleUpload">
点击上传
</el-button>
</div>
复制代码
配置成功函数
<template>
<upload-excel :on-success="handleSuccess" />
</template>
<script>
export default {
name: 'Import',
methods: {
handleSuccess({ header, results }) {
console.log(header, results)
}
}
}
</script>
复制代码
封装批量导入员工的api接口
/** *
* 封装一个批量导入员工的接口
* data: [{}, {}, {}, {}, ... ]
* ***/
export function reqImportEmployee(data) {
return request({
url: 'xxx',
method: 'post',
data
})
}
复制代码
实现excel导入
获取导入的excel数据, 导入excel接口
import { reqImportEmployee } from '@/api/employees'
export default {
name: 'Import',
methods: {
async handleSuccess({ header, results }) {
// header中, results中的数据是中文的, 但是提交给后台的要是英文的
const userRelations = {
'入职日期': 'timeOfEntry',
'手机号': 'mobile',
'姓名': 'username',
'转正日期': 'correctionTime',
'工号': 'workNumber'
}
const arr = []
results.forEach(item => {
const userInfo = {}
for (const key in item) {
userInfo[userRelations[key]] = item[key]
}
arr.push(userInfo)
})
// 调用导入接口
await reqImportEmployee(arr) // 调用导入接口
this.$router.back()
}
}
}
复制代码
当excel中有日期格式的时候,实际转化的值为一个数字,我们需要一个方法进行转化
Excel存储的日期是从1900年1月1日开始按天数来计算的,也就是说1900年1月1日在Excel中是1。
formatExcelDate(numb, format) {
const time = new Date((numb - 1) * 24 * 3600000 + 1) // 毫秒
time.setYear(time.getFullYear() - 70)
const year = time.getFullYear() + ''
const month = time.getMonth() + 1 + ''
const date = time.getDate() - 1 + ''
if (format && format.length === 1) {
return year + format + (month < 10 ? '0' + month : month) + format + (date < 10 ? '0' + date : date)
}
return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
}
复制代码
需要注意,
导入的手机号不能和之前的存在的手机号重复
处理日期:
<script>
import { reqImportEmployee } from '@/api/employees'
export default {
name: 'Import',
methods: {
async handleSuccess({ header, results }) {
// header中, results中的数据是中文的, 但是提交给后台的要是英文的
const userRelations = {
'入职日期': 'timeOfEntry',
'手机号': 'mobile',
'姓名': 'username',
'转正日期': 'correctionTime',
'工号': 'workNumber'
}
const arr = []
results.forEach(item => {
const userInfo = {}
for (const key in item) {
if (['timeOfEntry', 'correctionTime'].includes(userRelations[key])) {
userInfo[userRelations[key]] = this.formatExcelDate(item[key], '-')
} else {
userInfo[userRelations[key]] = item[key]
}
}
arr.push(userInfo)
})
// 调用导入接口
await reqImportEmployee(arr) // 调用导入接口
this.$router.back()
},
// 转换excel的日期格式
formatExcelDate(numb, format) {
const time = new Date((numb - 1) * 24 * 3600000 + 1)
time.setYear(time.getFullYear() - 70)
const year = time.getFullYear() + ''
const month = time.getMonth() + 1 + ''
const date = time.getDate() - 1 + ''
if (format && format.length === 1) {
return year + format + (month < 10 ? '0' + month : month) + format + (date < 10 ? '0' + date : date)
}
return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
}
}
}
</script>
复制代码
为了让这个页面可以服务更多的导入功能,我们可以在页面中用参数来判断,是否是导入员工
员工页面跳转
<el-button size="small" type="warning" @click="$router.push('/import?type=user')">excel导入</el-button>
复制代码
computed: {
type() {
return this.$route.query.type
}
},
复制代码
添加判断
async handleSuccess({ header, results }) {
if (this.type === 'user') {
...
}
},
复制代码
大概具体过程就是这样,如有不足,请多多指教