需求:vue+vue_table 实现导出表格(数据量大+表格显示的为部分列,要求是导出所有列)
背景:表格导出要求前端实现,数据量可以通过后端的查询表格的接口获取数据(查询接口是有分页的),我们是要导出所有的数据为一个表格(不是当前页的数据)。
思考:目前vxe-table在导出数据时提供了 自定义数据导出。 例如:
exportDataEvent4 () { this.$refs.xTable4.exportData({ filename: '自定义文件名', type: 'html', isHeader: true, isFooter: true, // 自定义导出的数据源 data: [ { name: 'Name1', sex: '男', age: 26, role: '前端', html1: '<a>xxx1</a>' }, { name: 'Name2', sex: '女', age: 20, role: '测试', html1: '<a>xxx2</a>' }, { name: 'Name4', sex: '女', age: 22, role: '设计师', html1: '<a>xxx3</a>' } ] }) },
目前vxe-table支持的是:
通过调用 exportData 函数指定 type='csv' 可以直接将表格导出为 CSV/HTML/XML/TXT 格式的文件;
默认会排除 field 为空和 type 相关的功能列(除 seq、checkbox、radio 之外),可以通过自定义 columnFilterMethod 列过滤方法
对于 csv 等特殊类型,可以通过设置 cell-type 将数值类型转为字符串类型
如果是服务端导出,通过设置 remote 和 exportMethod 开启服务端自定义导出
分析: 1.如果后端数据量很大,我们可以通过给接口入参传入的size定位total即可,或者是默认传一个很大的数值。 2.只能导出表格内存在的列,也就是说表格未展示出来的列是不会导出的(包括了列是使用的隐藏,:visible="false")
实现方法
1.官方提供了"高级导出"的方法,即:通过一个弹窗选择需要的导出。
代码实现:
openExportEvent () { this.$refs.xTable1.openExport() }
但是在用户操作上,通过弹窗设置还是太过繁琐,很多需求包括对用户的操作上都不太友好。
2.表头上方加入 显示/隐藏 对应的列 来设置需要导出的列名,通过控制显示出来的列名,导出的表格中也只是导出展示的列名的数据,未显示的列名则不导出。
代码实现:
<div class="labelSty">
<el-tooltip effect="light" content="显示/隐层列" placement="top" class="labelSty">
<el-dropdown
size="mini"
split-button
type="primary"
:hide-on-click="false"
style="margin: 0 5px"
>
<i class="el-icon-s-grid"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="item in tableLabel"
:key="item.field"
:command="item.field"
>
<el-checkbox-group
v-model="checkList"
style="display: inline-block; padding-left: 20px"
>
<el-checkbox
:label="item.field"
@change="selectColumn($event, item.field)"
>{{item.label}}</el-checkbox>
</el-checkbox-group>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
<el-tooltip effect="light" content="导出表格数据" placement="top" class="labelSty" style="margin-right: 20px">
<el-button type="primary" size="small" icon="el-icon-download" @click="exportData">
导出数据
</el-button>
</el-tooltip>
</div>
tableLabel:[
{
field:'chatid',
label:'群聊ID'
},
{
field:'creater',
label:'创建人'
},
{
field:'charger',
label:'负责人'
},
{
field:'receiver',
label:'关注人'
},
{
field:'department',
label:'部门'
},
{
field:'type',
label:'来源'
},
{
field:'title',
label:'标题'
},
{
field:'content',
label:'内容'
},{
field:'metric',
label:'metric'
},
{
field:'tags',
label:'tags'
},
{
field:'alarm_time',
label:'告警时间'
},
{
field:'start_time',
label:'响应开始时间'
},
{
field:'end_time',
label:'恢复时间'
},
{
field:'influences_time',
label:'响应时长'
},
{
field:'status',
label:'状态'
},
{
field:'fileurl',
label:'乐文档'
}
],
checkList: [ "creater", "charger", "department", "type","title","alarm_time","start_time", "end_time","influences_time", "status","fileurl"],
exportData() {
setTimeout(()=>{
let obj = {
page: 1,
per_page: 20000,
user: this.admin,
department: this.departmentCheckeds,
creater: this.createrCheckeds,
charger: this.chargerCheckeds,
status: this.statusCheckeds,
type: this.typeCheckeds,
};
this.$api.emergency.alarm_record(obj).then((res) => {
if (res.code == 200) {
this.$refs.xTable.exportData({
type: "csv",
filename: "历史事件",
isHeader: true,
data: res.data.list,
});
}
});
},100)
},
ok,我们这样就相当于是本来是为了只实现导出功能,现在我们给它新加了一个显示/隐藏列的功能。这个相当于增加了需求,但是到这反而是要跟产品经理去商量一下是否有必要把这个功能增加进去。很明显,这里我们就能看到其弊端。
3.新增一个显示所有列名的表格并把表格隐藏掉,当点击导出表格时,导出的是隐藏掉的表格,而不是显示给你看的表格(这里要注意的是:用户其实只能看到一个表格,这个表格只展示了几列重要的信息,要导出的是全部列的信息) 如图1:是看到的图,图2则是导出的数据
这里默认显示出来的表格我们给的ref和需要导出的表格的ref不能相同,不然导出的还是显示的表格。显示出来的表格就是原来查看的表格,代码就不写了,我们写实现功能的代码。
代码块:
<!-- 按钮 -->
<el-tooltip effect="light" content="导出表格数据" placement="top" class="labalSon">
<el-button
type="primary"
size="small"
icon="el-icon-download"
@click="exportData"
>导出数据</el-button>
</el-tooltip>
<!-- 用于导出的表格,隐藏起来 -->
<vxe-grid
v-show="false
"
ref="export_xTable"
v-bind="exportGridOptions"
:column-config="{resizable: true,minWidth:150}"
></vxe-grid>
exportGridOptions: {
resizable: true,
border: true,
showOverflow: false,
showHeader: true,
columns: [
{
field: "fingerprint",
title: "sql指纹"
},
{
field: "service_name",
title: "数据库ip:port"
},
{
field: "username",
title: "执行用户"
},
{
field: "first_time",
title: "首次执行时间"
},
{
field: "last_time",
title: "最后执行时间"
},
{
field: "num_queries",
title: "执行次数"
},
{
field: "m_query_time_sum",
title: "总执行时间"
},
{
field: "m_query_time_max",
title: "最大执行时间"
},
{
field: "m_query_time_p99",
title: "平均执行时间"
},
{
field: "m_query_time_min",
title: "最小执行时间"
},
{
field: "m_rows_examined_sum",
title: "总扫描行数"
},
{
field: "m_rows_examined_max",
title: "最大扫描数"
},
{
field: "m_rows_examined_p99",
title: "平均扫描数"
},
{
field: "m_rows_examined_min",
title: "最小扫描数"
},
{
field: "m_rows_sent_sum",
title: "总发送数"
},
{
field: "m_rows_sent_max",
title: "最大发送数"
},
{
field: "m_rows_sent_p99",
title: "平均发送数"
},
{
field: "m_rows_sent_min",
title: "最小发送数"
},
{
field: "m_rows_affected_sum",
title: "总影响行数"
},
{
field: "m_rows_affected_max",
title: "最大影响行数"
},
{
field: "m_rows_affected_p99",
title: "平均影响行数"
},
{
field: "m_rows_affected_min",
title: "最小影响行数"
},
{
field: "m_lock_time_sum",
title: "总锁时间"
},
{
field: "m_lock_time_max",
title: "最大锁时间"
},
{
field: "m_lock_time_min",
title: "最小锁时间"
}
],
data: []
},
// 导出数据
exportData() {
setTimeout(() => {
let obj = {
db_type: this.instanceTit,
start: this.timeLineVal[0],
end: this.timeLineVal[1],
service_name: this.instanceVal.join(","),
query_user: this.userVal.join(","),
page: 1,
size: this.page.totalResult,
order_by_field: this.sortProperty,
order_by_type: this.sortOrder
};
this.$api.data.slow_query(obj).then(res => {
if (res.code == 200) {
this.$refs.export_xTable.exportData({
type: "csv",
filename: `${this.instanceTit}_slowlog`,
isHeader: true,
data: res.data.results
});
}
});
}, 100);
},
目前测试是导出5000多条很流畅,不流畅就看后端优化接口吧。