一、应用场景
按照需求导出功能分为勾选批量导出及按照查询结果导出,考虑到接口操作导出的复杂性,因此实现了js控制导出的功能
二、安装相关依赖
cnpm install --save xlsx file-saver
具体插件使用参考https://github.com/SheetJS/js-xlsx,https://github.com/eligrey/FileSaver.js
三、实现代码
考虑到多处使用导出功能,所以封装成公用组件形式
1、列表页
<template>
<div class="add-button">
<span @click="exportExcelSelect">按勾选导出</span>
<span @click="exportExcel">按查询结果导出</span>
</div>
<export-excel-common ref="myChild" :exportExcelInfo="exportExcelInfo" :tableData="tableAllData" :exportExcelArry="exportExcelArry"></export-excel-common>
</template>
<script>
export default {
components: {
exportExcelCommon
},
data() {
return {
//导出表格字段及formatter信息
exportExcelArry: [{
prop: 'phoneNumber',
label: '用户手机号',
formatterFlag: false
},{
prop: 'userFundRedEnvelopRecord.status',
label: '状态',
formatterFlag: true,
formatterType: 'common-type',
formatterInfo: [{value: 0,label: '未完成'},{value: 1,label: '已完成'}]
},{
prop: 'userFundRedEnvelopRecord.name',
label: '任务名称',
formatterFlag: false
}],
//导出excel表格id及excel名称
exportExcelInfo: {
excelId: 'record-table',
excelName: '红包获取记录.xlsx'
},
//需要导出的table数据
tableAllData: [],
},
methods {
exportExcelSelect () {
if(this.selectListArry.length == 0){
global.message('请勾选操作项')
return;
}
//将选中项传给this. tableAllData
this.tableAllData = this.selectListArry
//需要延时调导出方法,为了等待数据初始化到列表中
setTimeout(()=>{
this.$refs.myChild.exportExcel();
},500)
},
exportExcel () {
this.initData('export-excel')
//获取到表格数据的值并赋给this.tableAllData
//同样延时调导出方法,需在initData('export-excel')方法执行成功后调this.$refs.myChild.exportExcel();方法
}
}
}
2、通用组件ExportExcelCommon.vue
<template>
<transition name="fadeIn">
<div v-show='false'>
<el-table :id="exportExcelInfo.excelId" :data="tableData" highlight-current-row style="width: 100%">
<template v-for="(item,index) in exportExcelArry">
<el-table-column v-if="!item.formatterFlag" :prop="item.prop" :label="item.label">
</el-table-column>
<el-table-column v-else :prop="item.prop" :label="item.label">
<template slot-scope="scope">
<span>{{formatter(scope.row[item.prop],item,scope.row,item.prop)}}</span>
</template>
</el-table-column>
</template>
</el-table>
</div>
</transition>
</template>
<script>
import FileSaver from 'file-saver'
import XLSX from 'xlsx'
export default {
props: {
exportExcelInfo: {
type: Object,
default: {}
},
exportExcelArry: {
type: Array,
default: []
},
tableData: {
type: Array,
default: []
},
},
methods: {
//excel导出
exportExcel () {
var xlsxParam = { raw: true } // 导出的内容只做解析,不进行格式转换
var wb = XLSX.utils.table_to_book(document.querySelector('#'+this.exportExcelInfo.excelId),xlsxParam)
var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' })
try {
FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), this.exportExcelInfo.excelName)
} catch (e) {
if (typeof console !== 'undefined') console.log(e, wbout)
}
return wbout
},
//表格formatter数据格式化
formatter (value,item,row,prop) {
//针对table中item多层对象层级的情况
if(prop.indexOf('.') > 0){
let temp = prop.split('.')
//item中嵌套两层
if(temp.length == 2){
let temp = prop.split('.')
if(item.formatterType == 'common-type'){ //通用类型转换
let arry = item.formatterInfo
for(let i in arry){
if(arry[i].value == row[temp[0]][temp[1]]){
return arry[i].label
}
}
} else if(item.formatterType == 'time-type'){ //时间标准格式化
if(!global.isNull(row[temp[0]][temp[1]])){
return row[temp[0]][temp[1]].substring(0,row[temp[0]][temp[1]].length - 2)
}
} else if(item.formatterType == 'amount-type'){ //金额转换
return (row[temp[0]][temp[1]] / 100).toFixed(2)
}
}
} else{ //item中无嵌套对象
let temp = prop.split('.')
if(item.formatterType == 'common-type'){ //通用类型转换
let arry = item.formatterInfo
for(let i in arry){
if(arry[i].value == value){
return arry[i].label
}
}
} else if(item.formatterType == 'time-type'){ //时间标准格式化
if(!global.isNull(row[temp[0]][temp[1]])){
return value.substring(0,value.length - 2)
}
} else if(item.formatterType == 'amount-type'){ //金额转换
return (value / 100).toFixed(2)
}
}
},
}
};
</script>
说明:
1、通常情况下列表中的字段不需要formatter,把exportExcelArry 对象中formatterFlag设成false;
2、需要formatter的数据主要有code对应label的转换(type='common-type'),金额的单位转换等,需要根据自己项目的需求封装成通用的组件;
3、针对后端返回的数据data多层的情况,需要对exportExcelArry中的prop字段进行分割来获取row中对应的值,一般情况下两层足够了。