封装一个通用的工具栏
目标
:封装一个通用的工具栏供大家使用
通用工具栏的组件结构
在后续的业务开发中,经常会用到一个类似下图的工具栏,作为公共组件,进行一下封装
组件 src/components/PageTools/index.vue
<template> <el-card class="page-tools"> <el-row type="flex" justify="space-between" align="middle"> <el-col> <div v-if="showBefore" class="before"> <i class="el-icon-info" /> <!-- 定义前面得插槽 --> <slot name="before" /> </div> </el-col> <el-col> <el-row type="flex" justify="end"> <!-- 定义后面的插槽 --> <slot name="after" /> </el-row> </el-col> </el-row> </el-card> </template> <script> export default { props: { showBefore: { type: Boolean, default: false } } } </script> <style lang='scss'> .page-tools { margin: 10px 0; .before { line-height: 34px; i { margin-right: 5px; color: #409eff; } display: inline-block; padding: 0px 10px; border-radius: 3px; border: 1px solid rgba(145, 213, 255, 1); background: rgba(230, 247, 255, 1); } } </style>
组件统一注册
为了方便所有的页面都可以不用引用该组件,可以进行全局注册
提供注册入口 src/componets/index.js
// 该文件负责所有的公共的组件的全局注册 Vue.use import PageTools from './PageTools' export default { install(Vue) { // 注册全局的通用栏组件对象 Vue.component('PageTools', PageTools) } }
在入口处进行注册
src/main.js
import Component from '@/components' Vue.use(Component) // 注册自己的插件
提交代码
本节任务
: 封装一个通用的工具栏
员工列表页面的基本布局和结构
目标
:实现员工列表页面的基本布局和结构
结构代码 src/employees/index.vue
<template> <div class="dashboard-container"> <div class="app-container"> <page-tools :show-before="true"> <span slot="before">共166条记录</span> <template slot="after"> <el-button size="small" type="warning">导入</el-button> <el-button size="small" type="danger">导出</el-button> <el-button size="small" type="primary">新增员工</el-button> </template> </page-tools> <!-- 放置表格和分页 --> <el-card> <el-table border> <el-table-column label="序号" sortable="" /> <el-table-column label="姓名" sortable="" /> <el-table-column label="工号" sortable="" /> <el-table-column label="聘用形式" sortable="" /> <el-table-column label="部门" sortable="" /> <el-table-column label="入职时间" sortable="" /> <el-table-column label="账户状态" sortable="" /> <el-table-column label="操作" sortable="" fixed="right" width="280"> <template> <el-button type="text" size="small">查看</el-button> <el-button type="text" size="small">转正</el-button> <el-button type="text" size="small">调岗</el-button> <el-button type="text" size="small">离职</el-button> <el-button type="text" size="small">角色</el-button> <el-button type="text" size="small">删除</el-button> </template> </el-table-column> </el-table> <!-- 分页组件 --> <el-row type="flex" justify="center" align="middle" style="height: 60px"> <el-pagination layout="prev, pager, next" /> </el-row> </el-card> </div> </div> </template>
提交代码
本节任务
:员工列表页面的基本布局和结构
员工列表数据请求和分页加载
目标
实现员工数据的加载和分页请求
首先,封装员工的加载请求 src/api/employees.js
/** * 获取员工的综合列表数据 * ***/ export function getEmployeeList(params) { return request({ url: '/sys/user', params }) }
然后,实现加载数据和分页的逻辑
import { getEmployeeList } from '@/api/employees' export default { data() { return { loading: false, list: [], // 接数据的 page: { page: 1, // 当前页码 size: 10, total: 0 // 总数 } } }, created() { this.getEmployeeList() }, methods: { changePage(newPage) { this.page.page = newPage this.getEmployeeList() }, async getEmployeeList() { this.loading = true const { total, rows } = await getEmployeeList(this.page) this.page.total = total this.list = rows this.loading = false } } }
绑定表格
<el-card v-loading="loading"> <el-table border :data="list"> <el-table-column label="序号" sortable="" type="index" /> <el-table-column label="姓名" sortable="" prop="username" /> <el-table-column label="工号" sortable="" prop="workNumber" /> <el-table-column label="聘用形式" sortable="" prop="formOfEmployment" /> <el-table-column label="部门" sortable="" prop="departmentName" /> <el-table-column label="入职时间" sortable="" prop="timeOfEntry" /> <el-table-column label="账户状态" sortable="" prop="enableState" /> <el-table-column label="操作" sortable="" fixed="right" width="280"> <template> <el-button type="text" size="small">查看</el-button> <el-button type="text" size="small">转正</el-button> <el-button type="text" size="small">调岗</el-button> <el-button type="text" size="small">离职</el-button> <el-button type="text" size="small">角色</el-button> <el-button type="text" size="small">删除</el-button> </template> </el-table-column> </el-table> <!-- 分页组件 --> <el-row type="flex" justify="center" align="middle" style="height: 60px"> <el-pagination layout="prev, pager, next" :page-size="page.size" :current-page="page.page" :total="page.total" @current-change="changePage" /> </el-row> </el-card>
提交代码
本节任务
员工列表数据请求和分页加载
员工列表中的数据进行格式化
目标
:将列表中的内容进行格式化
利用列格式化属性处理聘用形式
上小节中,列表中的聘用形式/入职时间和账户状态需要进行显示内容的处理
那么聘用形式中1代表什么含义,这实际上是我们需要的枚举数据,该数据的存放文件位于我们提供的资源/枚举
中,可以将枚举下的文件夹放于src/api
文件夹下
针对聘用形式,可以使用el-table-column的formatter属性进行设置
import EmployeeEnum from '@/api/constant/employees' <!-- 格式化聘用形式 --> <el-table-column label="聘用形式" sortable :formatter="formatEmployment" prop="formOfEmployment" /> // 格式化聘用形式 formatEmployment(row, column, cellValue, index) { // 要去找 1所对应的值 const obj = EmployeeEnum.hireType.find(item => item.id === cellValue) return obj ? obj.value : '未知' }
过滤器解决时间格式的处理
针对入职时间,我们可以采用作用域插槽进行处理
<el-table-column label="入职时间" sortable prop="timeOfEntry"> <template slot-scope="obj"> { { obj.row.timeOfEntry | 过滤器 }} </template> </el-table-column>
问题来了,过滤器从哪里呢?
在资源/过滤器
中,我们提供了若干工具方法,我们可以将其转化成过滤器,首先将其拷贝到src
在main.js
中将工具方法转化成过滤器
import * as filters from '@/filters' // 引入工具类 // 注册全局的过滤器 Object.keys(filters).forEach(key => { // 注册过滤器 Vue.filter(key, filters[key]) })
好了,现在可以愉快的用过滤器的方式使用工具类的方法了
<el-table-column label="入职时间" sortable="" align="center"> <!-- 作用域插槽 --> <template slot-scope="{ row }">{ { row.timeOfEntry | formatDate }}</template> </el-table-column>
最后一项,账户状态,可以用开关组件switch进行显示
<el-table-column label="账户状态" align="center" sortable="" prop="enableState"> <template slot-scope="{ row }"> <!-- 根据当前状态来确定 是否打开开关 --> <el-switch :value="row.enableState === 1" /> </template> </el-table-column>
提交代码
本节任务
员工列表中的数据进行格式化
删除员工功能
目标
实现删除员工的功能
首先封装 删除员工的请求
/** * 删除员工接口 * ****/ export function delEmployee(id) { return request({ url: `/sys/user/${id}`, method: 'delete' }) }
删除功能
<template slot-scope="{ row }"> <el-button type="text" size="small">查看</el-button> <el-button type="text" size="small">转正</el-button> <el-button type="text" size="small">调岗</el-button> <el-button type="text" size="small">离职</el-button> <el-button type="text" size="small">角色</el-button> <el-button type="text" size="small" @click="deleteEmployee(row.id)">删除</el-button> </template>
// 删除员工 async deleteEmployee(id) { try { await this.$confirm('您确定删除该员工吗') await delEmployee(id) // 如果不是第一页,且只有一个元素,删除成功,则需要把页码-1,重新拉取列表 if (this.list.length === 1 && this.page.page !== 1) { this.page.page-- } this.getEmployeeList() this.$message.success('删除员工成功') } catch (error) { console.log(error) } }
提交代码
本节任务
: 删除员工功能
新增员工功能-弹层-校验-部门
目标
:实现新增员工的功能
新建员工弹层组件
当我们点击新增员工时,我们需要一个类似的弹层
类似组织架构
的组件,同样新建一个弹层组件 src/views/employees/components/add-employee.vue
<template> <el-dialog title="新增员工" :visible="showDialog"> <!-- 表单 --> <el-form label-width="120px"> <el-form-item label="姓名"> <el-input style="width:50%" placeholder="请输入姓名" /> </el-form-item> <el-form-item label="手机"> <el-input style="width:50%" placeholder="请输入手机号" /> </el-form-item> <el-form-item label="入职时间"> <el-date-picker style="width:50%" placeholder="请选择入职时间" /> </el-form-item> <el-form-item label="聘用形式"> <el-select style="width:50%" placeholder="请选择" /> </el-form-item> <el-form-item label="工号"> <el-input style="width:50%" placeholder="请输入工号" /> </el-form-item> <el-form-item label="部门"> <el-input style="width:50%" placeholder="请选择部门" /> </el-form-item> <el-form-item label="转正时间"> <el-date-picker style="width:50%" placeholder="请选择转正时间" /> </el-form-item> </el-form> <!-- footer插槽 --> <template v-slot:footer> <el-row type="flex" justify="center"> <el-col :span="6"> <el-button size="small">取消</el-button> <el-button type="primary" size="small">确定</el-button> </el-col> </el-row> </template> </el-dialog> </template> <script> export default { props: { showDialog: { type: Boolean, default: false } } } </script> <style> </style>
引用弹出层,点击弹出
父组件中引用,弹出层
import AddEmployee from './components/add-employee'
//data里面定义 showDialog: false // 弹出层显示控制变量
<!-- 放置新增组件 --> <add-employee :show-dialog.sync="showDialog" /> <!--按钮绑定事件--> <el-button icon="plus" type="primary" size="small" @click="showDialog = true">新增员工</el-button>
新增员工的表单校验
封装新增员工api src/api/employees.js
/** ** * 新增员工的接口 * **/ export function addEmployee(data) { return request({ method: 'post', url: '/sys/user', data }) }
针对员工属性,添加校验规则
import EmployeeEnum from '@/api/constant/employees' data() { return { EmployeeEnum, // 在data中定义数据 // 表单数据 treeData: [], // 定义数组接收树形数据 showTree: false, // 控制树形的显示或者隐藏 loading: false, // 控制树的显示或者隐藏进度条 formData: { username: '', mobile: '', formOfEmployment: '', workNumber: '', departmentName: '', timeOfEntry: '', correctionTime: '' }, rules: { username: [{ required: true, message: '用户姓名不能为空', trigger: 'blur' }, { min: 1, max: 4, message: '用户姓名为1-4位' }], mobile: [{ required: true, message: '手机号不能为空', trigger: 'blur' }, { pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' }], formOfEmployment: [{ required: true, message: '聘用形式不能为空', trigger: 'blur' }], workNumber: [{ required: true, message: '工号不能为空', trigger: 'blur' }], departmentName: [{ required: true, message: '部门不能为空', trigger: 'change' }], timeOfEntry: [{ required: true, message: '入职时间', trigger: 'blur' }] } } }
绑定数据和规则校验
<el-form :model="formData" ref="addEmployee" :rules="rules" label-width="120px"> <el-form-item label="姓名" prop="username"> <el-input v-model="formData.username" style="width:50%" placeholder="请输入姓名" /> </el-form-item> <el-form-item label="手机" prop="mobile"> <el-input v-model="formData.mobile" style="width:50%" placeholder="请输入手机号" /> </el-form-item> <el-form-item label="入职时间" prop="timeOfEntry"> <el-date-picker v-model="formData.timeOfEntry" style="width:50%" placeholder="请选择日期" /> </el-form-item> <el-form-item label="聘用形式" prop="formOfEmployment"> <el-select v-model="formData.formOfEmployment" style="width:50%" placeholder="请选择" /> </el-form-item> <el-form-item label="工号" prop="workNumber"> <el-input v-model="formData.workNumber" style="width:50%" placeholder="请输入工号" /> </el-form-item> <el-form-item label="部门" prop="departmentName"> <el-input v-model="formData.departmentName" style="width:50%" placeholder="请选择部门" /> </el-form-item> <el-form-item label="转正时间" prop="correctionTime"> <el-date-picker v-model="formData.correctionTime" style="width:50%" placeholder="请选择日期" /> </el-form-item> </el-form>
加载部门数据转化树形
聘用形式和选择部门的处理
员工的部门是从树形部门中选择一个部门
获取部门数据,转化树形
import { getDepartments } from '@/api/departments' import { tranListToTreeData } from '@/utils' data () { return { // 表单数据 treeData: [], // 定义数组接收树形数据 showTree: false, // 控制树形的显示或者隐藏 loading: false, // 控制树的显示或者隐藏进度条 } }, methods: { async getDepartments() { this.showTree = true this.loading = true const { depts } = await getDepartments() // depts是数组 但不是树形 this.treeData = tranListToTreeData(depts, '') this.loading = false }, }
点击部门赋值表单数据
选择部门,赋值表单数据
<el-form-item label="部门" prop="departmentName"> <el-input v-model="formData.departmentName" style="width:50%" placeholder="请选择部门" @focus="getDepartments" /> <!-- 放置一个tree组件 --> <el-tree v-if="showTree" v-loading="loading" :data="treeData" default-expand-all="" :props="{ label: 'name' }" @node-click="selectNode" /> </el-form-item>
点击部门时触发
selectNode(node) { this.formData.departmentName = node.name this.showTree = false }
聘用形式
<el-form-item label="聘用形式" prop="formOfEmployment"> <el-select v-model="formData.formOfEmployment" style="width:50%" placeholder="请选择"> <!-- 遍历只能遍历组件的数据 --> <el-option v-for="item in EmployeeEnum.hireType" :key="item.id" :label="item.value" :value="item.id" /> </el-select> </el-form-item>
新增员工功能-确定-取消
绑定确定和取消事件
<el-button size="small" @click="btnCancel">取消</el-button> <el-button type="primary" size="small" @click="btnOK">确定</el-button>
调用新增接口
// 导入请求方法 import { addEmployee } from '@/api/employees'
// 点击确定时 校验整个表单 async btnOK() { try { await this.$refs.addEmployee.validate() // 调用新增接口 await addEmployee(this.formData) // 新增员工 // 告诉父组件更新数据 // this.$parent 可以直接调用到父组件的实例 实际上就是父组件this // this.$emit this.$parent.getEmployeeList() this.$parent.showDialog = false } catch (error) { console.log(error) } }, btnCancel() { // 重置原来的数据 this.formData = { username: '', mobile: '', formOfEmployment: '', workNumber: '', departmentName: '', timeOfEntry: '', correctionTime: '' } this.$refs.addEmployee.resetFields() // 重置校验结果 this.$emit('update:showDialog', false) }
新增员工的功能和组织架构的功能极其类似,这里不做过多阐述
提交代码
本节任务
新增员工功能和弹层
员工导入组件封装
目标
:封装一个导入excel数据的文件
首先封装一个类似的组件,首先需要注意的是,类似功能,vue-element-admin已经提供了,我们只需要改造即可 代码地址
类似功能性的组件,我们只需要会使用和封装即可
excel导入功能需要使用npm包xlsx
,所以需要安装xlsx
插件
$ npm i xlsx
将vue-element-admin提供的导入功能新建一个组件,位置:
src/components/UploadExcel
注册全局的导入excel组件
import PageTools from './PageTools' import UploadExcel from './UploadExcel' export default { install(Vue) { Vue.component('PageTools', PageTools) // 注册工具栏组件 Vue.component('UploadExcel', UploadExcel) // 注册导入excel组件 } }
修改样式和布局
<template> <div class="upload-excel"> <div class="btn-upload"> <el-button :loading="loading" size="mini" type="primary" @click="handleUpload"> 点击上传 </el-button> </div> <input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick"> <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover"> <i class="el-icon-upload" /> <span>将文件拖到此处</span> </div> </div> </template> <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>
分析excel导入代码,封装接口
封装导入员工的api接口
/** * * 封装一个导入员工的接口 * * ***/ export function importEmployee(data) { return request({ url: '/sys/user/batch', method: 'post', data }) }
实现excel导入
获取导入的excel数据, 导入excel接口
async success({ header, results }) { // 如果是导入员工 const userRelations = { '入职日期': 'timeOfEntry', '手机号': 'mobile', '姓名': 'username', '转正日期': 'correctionTime', '工号': 'workNumber' } const arr = [] results.forEach(item => { const userInfo = {} Object.keys(item).forEach(key => { userInfo[userRelations[key]] = item[key] }) arr.push(userInfo) }) await importEmployee(arr) // 调用导入接口 this.$router.back() }
为了让这个页面可以服务更多的导入功能,我们可以在页面中用参数来判断,是否是导入员工
data() { return { type: this.$route.query.type } },
当excel中有日期格式的时候,实际转化的值为一个数字,我们需要一个方法进行转化
formatDate(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 + format + date } return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date) }
需要注意,
导入的手机号不能和之前的存在的手机号重复
逻辑判断
async success({ header, results }) { if (this.type === 'user') { const userRelations = { '入职日期': 'timeOfEntry', '手机号': 'mobile', '姓名': 'username', '转正日期': 'correctionTime', '工号': 'workNumber' } const arr = [] // 遍历所有的数组 results.forEach(item => { // 需要将每一个条数据里面的中文都换成英文 const userInfo = {} Object.keys(item).forEach(key => { // key是当前的中文名 找到对应的英文名 if (userRelations[key] === 'timeOfEntry' || userRelations[key] === 'correctionTime') { userInfo[userRelations[key]] = new Date(this.formatDate(item[key], '/')) // 只有这样, 才能入库 return } userInfo[userRelations[key]] = item[key] }) // 最终userInfo变成了全是英文 arr.push(userInfo) }) await importEmployee(arr) this.$message.success('导入成功') } this.$router.back() // 回到上一页 }, formatDate(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 + format + date } return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date) }
员工页面跳转
<el-button type="warning" size="small" @click="$router.push('/import?type=user')">导入</el-button>
目标
: 实现员工的导入
员工导出excel功能
目标: 实现将员工数据导出功能
日常业务中,我们经常遇到excel导出功能, 怎么使用呢
Excel 的导入导出都是依赖于js-xlsx来实现的。
在 js-xlsx
的基础上又封装了Export2Excel.js来方便导出数据。
安装excel所需依赖和按需加载
由于 Export2Excel
不仅依赖js-xlsx
还依赖file-saver
和script-loader
。
所以你先需要安装如下命令:
npm install xlsx file-saver -S npm install script-loader -S -D
由于js-xlsx
体积还是很大的,导出功能也不是一个非常常用的功能,所以使用的时候建议使用懒加载。使用方法如下:
import('@/vendor/Export2Excel').then(excel => { excel.export_json_to_excel({ header: tHeader, //表头 必填 data, //具体数据 必填 filename: 'excel-list', //非必填 autoWidth: true, //非必填 bookType: 'xlsx' //非必填 }) })
excel导出参数的介绍
vue-element-admin提供了导出的功能模块,在课程资源/excel导出目录下,放置到src目录下
参数
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
header | 导出数据的表头 | Array | / | [] |
data | 导出的具体数据 | Array | / | [[]] |
filename | 导出文件名 | String | / | excel-list |
autoWidth | 单元格是否要自适应宽度 | Boolean | true / false | true |
bookType | 导出文件类型 | String | xlsx, csv, txt, more | xlsx |
excel导出基本的结构
我们最重要的一件事,就是把表头和数据进行相应的对应
因为数据中的key是英文,想要导出的表头是中文的话,需要将中文和英文做对应
const headers = { '手机号': 'mobile', '姓名': 'username', '入职日期': 'timeOfEntry', '聘用形式': 'formOfEmployment', '转正日期': 'correctionTime', '工号': 'workNumber', '部门': 'departmentName' }
然后,完成导出代码
// 导出excel数据 exportData() { // 做操作 // 表头对应关系 const headers = { '姓名': 'username', '手机号': 'mobile', '入职日期': 'timeOfEntry', '聘用形式': 'formOfEmployment', '转正日期': 'correctionTime', '工号': 'workNumber', '部门': 'departmentName' } // 懒加载 import('@/vendor/Export2Excel').then(async excel => { const { rows } = await getEmployeeList({ page: 1, size: this.page.total }) const data = this.formatJson(headers, rows) excel.export_json_to_excel({ header: Object.keys(headers), data, filename: '员工信息表', autoWidth: true, bookType: 'xlsx' }) // 获取所有的数据 // excel.export_json_to_excel({ // header: ['姓名', '薪资'], // data: [['张三', 12000], ['李四', 5000]], // filename: '员工薪资表', // autoWidth: true, // bookType: 'csv' // }) }) }, // 该方法负责将数组转化成二维数组 formatJson(headers, rows) { // 首先遍历数组 // [{ username: '张三'},{},{}] => [[’张三'],[],[]] return rows.map(item => { return Object.keys(headers).map(key => { if (headers[key] === 'timeOfEntry' || headers[key] === 'correctionTime') { return formatDate(item[headers[key]]) // 返回格式化之前的时间 } else if (headers[key] === 'formOfEmployment') { var en = EmployeeEnum.hireType.find(obj => obj.id === item[headers[key]]) return en ? en.value : '未知' } return item[headers[key]] }) // => ["张三", "13811","2018","1", "2018", "10002"] }) // return data // return rows.map(item => { // // item是对象 => 转化成只有值的数组 => 数组值的顺序依1赖headers {username: '张三' } // // Object.keys(headers) => ["姓名", "手机号",...] // return Object.keys(headers).map(key => { // return item[headers[key]] // }) // / 得到 ['张三',’129‘,’dd‘,'dd'] // }) }
导出时间格式的处理
formatJson(headers, rows) { return rows.map(item => { // item是一个对象 { mobile: 132111,username: '张三' } // ["手机号", "姓名", "入职日期" 。。] return Object.keys(headers).map(key => { // 需要判断 字段 if (headers[key] === 'timeOfEntry' || headers[key] === 'correctionTime') { // 格式化日期 return formatDate(item[headers[key]]) } else if (headers[key] === 'formOfEmployment') { const obj = EmployeeEnum.hireType.find(obj => obj.id === item[headers[key]]) return obj ? obj.value : '未知' } return item[headers[key]] }) // ["132", '张三’, ‘’,‘’,‘’d] }) // return rows.map(item => Object.keys(headers).map(key => item[headers[key]])) // 需要处理时间格式问题 }
扩展
复杂表头的导出
当需要导出复杂表头的时候,vue-element-admin同样支持该类操作
vue-element-admin 提供的导出方法中有 multiHeader和merges 的参数
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
multiHeader | 复杂表头的部分 | Array | / | [[]] |
merges | 需要合并的部分 | Array | / | [] |
multiHeader里面是一个二维数组,里面的一个元素是一行表头,假设你想得到一个如图的结构
mutiHeader应该这样定义
const multiHeader = [['姓名', '主要信息', '', '', '', '', '部门']]
multiHeader中的一行表头中的字段的个数需要和真正的列数相等,假设想要跨列,多余的空间需要定义成空串
它主要对应的是标准的表头
const header = ['姓名', '手机号', '入职日期', '聘用形式', '转正日期', '工号', '部门']
如果,我们要实现其合并的效果, 需要设定merges选项
const merges = ['A1:A2', 'B1:F1', 'G1:G2']
merges的顺序是没关系的,只要配置这两个属性,就可以导出复杂表头的excel了
exportData() { const headers = { '姓名': 'username', '手机号': 'mobile', '入职日期': 'timeOfEntry', '聘用形式': 'formOfEmployment', '转正日期': 'correctionTime', '工号': 'workNumber', '部门': 'departmentName' } // 导出excel import('@/vendor/Export2Excel').then(async excel => { // excel是引入文件的导出对象 // 导出 header从哪里来 // data从哪里来 // 现在没有一个接口获取所有的数据 // 获取员工的接口 页码 每页条数 100 1 10000 const { rows } = await getEmployeeList({ page: 1, size: this.page.total }) const data = this.formatJson(headers, rows) // 返回的data就是 要导出的结构 const multiHeader = [['姓名', '主要信息', '', '', '', '', '部门']] const merges = ['A1:A2', 'B1:F1', 'G1:G2'] excel.export_json_to_excel({ header: Object.keys(headers), data, filename: '员工资料表', multiHeader, // 复杂表头 merges // 合并选项 }) // excel.export_json_to_excel({ // header: ['姓名', '工资'], // data: [['张三', 3000], ['李四', 5000]], // filename: '员工工资表' // }) // [{ username: '张三',mobile: 13112345678 }] => [[]] // 要转化 数据结构 还要和表头的顺序对应上 // 要求转出的标题是中文 }) }, // 将表头数据和数据进行对应 // [{}] => [[]] formatJson(headers, rows) { return rows.map(item => { // item是一个对象 { mobile: 132111,username: '张三' } // ["手机号", "姓名", "入职日期" 。。] return Object.keys(headers).map(key => { // 需要判断 字段 if (headers[key] === 'timeOfEntry' || headers[key] === 'correctionTime') { // 格式化日期 return formatDate(item[headers[key]]) } else if (headers[key] === 'formOfEmployment') { const obj = EmployeeEnum.hireType.find(obj => obj.id === item[headers[key]]) return obj ? obj.value : '未知' } return item[headers[key]] }) // ["132", '张三’, ‘’,‘’,‘’d] }) // return rows.map(item => Object.keys(headers).map(key => item[headers[key]])) // 需要处理时间格式问题 }
提交代码