项目中我么有时候可以用到可以展开的表格树形表格,方便我们数据和层级关系。
效果图:

实现方式:递归组件思路,使用iview的表格https://www.iviewui.com/components/table#KZK
封装的组件:
src/views/commonComponents/ExpandTable/ExpandTable.vue
<template>
<div :class="['ExpandTable', 'ExpandTableLevel'+ lev, {'no-table-header': lev !== 1}]">
<Table :class="['table', 'table-level-' + lev]" :loading="tableLoading" :columns="columnsIn" :data="tableData" @on-row-dblclick="handleRowDBclick"></Table>
</div>
</template>
<script>
// import util from '@/libs/util';
import ExpandTable from './ExpandTable.vue';
export default {
name: 'ExpandTable',
components: {ExpandTable},
/**
* @on-update-complete 数据更新完成的 事件 ,配合 update props 可以做到 表格数据筛选, 在这个时间内 把 update字段 更改未 false
* */
props: {
//展开是接口
api: String,
// row: Object,
//展开时上级Id 的字段名称
parentIDFiled: {
type: String,
default: 'depId'
},
id: String,
// beginDate: String,
// endDate: String,
//层级(使用时这个props不用传)
level: {
type: Number,
default: 0
},
//固定的请求参数
reqParam: {
type: Object,
default: ()=>({})
},
//表格列
columns: {
type: Array,
default: ()=>([])
},
update: Boolean, // false -> true 时更新 展开表格的数据
/**
* 处理接口响应数据的函数, 主要是对接口响应的列表数据挂载 _disableExpand 字段 -> 为true 禁用展开(不显示前面的 展开符号)
* @return 此函数必须 返回 表格数据 处理后表格的数据
* */
handleResFun: {
type: Function,
required: true
}
},
data(){
return {
lev: 1,
tableLoading: false,
tableData: [],
columnsIn: [
{
type: 'expand',
width: 50,
render: (h, params) => {
return h(ExpandTable, {
props: {
api: this.api,
// id: params.row.depId,
id: params.row[this.parentIDFiled],
level: this.lev,
// beginDate: this.beginDate,
// endDate: this.endDate
reqParam: this.reqParam,
parentIDFiled: this.parentIDFiled,
columns: this.columns,
handleResFun: this.handleResFun
}
})
}
},
...this.columns
]
}
},
watch: {
update(val){
val && this.lev === 1 && (this.getTableOfData())
}
},
methods: {
//表格行双击 展开与折叠
handleRowDBclick(row, index){
//禁用状态不能展开
if(row._disableExpand) return;
if(this.tableData[index]['_expanded']){
this.$set(this.tableData[index], '_expanded', false);
}else {
this.$set(this.tableData[index], '_expanded', true);
}
},
//获取表格数据
getTableOfData(){
let that = this;
this.tableLoading = true;
this.$post(this.api, { [this.parentIDFiled]: this.id, ...this.reqParam }).then( response => {
if (response.success) {
/*
response.data.list.forEach(item=> {
//如果是人state '1' count '0' 没有子项 禁用展开、
if( item.state === '1' || item.count === '0' ) item._disableExpand = true
});
that.tableData = response.data.list;
*/
that.tableData = this.handleResFun(response);
} else {
that.$Message.error(`查询失败:${response.msg}`);
}
that.tableLoading = false;
this.$emit('on-update-complete')
}).catch(error => {
console.log('列表查询出错', error);
});
},
},
created() {
this.lev = this.level + 1;
},
mounted () {
// console.log(`显示第${this.lev}层数据`);
this.getTableOfData();
}
};
</script>
<style scoped>
.ExpandTable {
background: #fff;
}
.ExpandTable >>> .table {
border: none;
margin-left: 30px;
}
.ExpandTable >>> .table .ivu-table-expanded-cell {
background: #fff;
padding: 0;
}
.ExpandTable.no-table-header >>> .table .ivu-table-header {
display: none;
}
/*最外层边框*/
.ExpandTableLevel1 >>> .table-level-1.ivu-table-wrapper {
position: relative;
border: 1px solid #dcdee2;
border-bottom: 0;
/*border-right: 0;*/
overflow: hidden;
}
.ExpandTableLevel1 >>> .ivu-table-overflowX {
overflow: unset;
}
.ExpandTableLevel1 >>> .table-level-1 {
margin-left: 0;
}
/*所有子项下边线*/
/*
.ExpandTable >>> .table .ivu-table::before {
height: 0;
}
*/
.ExpandTable >>> .table .ivu-table::after {
width: 0;
}
.ExpandTable >>> .table .ivu-table td {
border-bottom: none;
}
</style>
使用时:src/views/storeshop/stat/timeLimitStat.vue
<template>
<div class="timeLimitStat wrapper_box">
<ExpandTable
api="/pointStock/increment"
parentIDFiled="depId"
:columns="columns"
:update="updateTable"
:reqParam="{beginDate: formSearch.beginDate, endDate: formSearch.endDate}"
:handleResFun="handleResDataFun"
@on-update-complete="handleUpdateComplete"/>
</div>
</template>
<script>
import ExpandTable from '../../commonComponents/ExpandTable/ExpandTable';
export default {
name: 'timeLimitStat',
inject: ['export'],
components: { ExpandTable },
data(){
return {
//展开层级
// lev: 0,
// tableData: [],
//表格列定义
columns: [
{
title: '部门',
key: 'depName',
},
{
title: '期初',
width: 400,
key: 'beginPoint',
},
{
title: '期末',
width: 400,
key: 'endPoint',
},
{
title: '增量',
width: 400,
key: 'beginPoint',
render: (h, params)=> h('span', Number(params.row.endPoint) - Number(params.row.beginPoint) )
},
],
updateTable: false, //是否更新 展开表格的数据
}
},
methods: {
// /pointStock/increment 接口数据处理函数
handleResDataFun(response){
response.data.list.forEach(item=> {
//如果是人state '1' count '0' 没有子项 禁用展开、
if( item.state === '1' || item.count === '0' ) item._disableExpand = true
});
return response.data.list;
},
// 展开表格数据请求完毕的函数
handleUpdateComplete(){
this.updateTable = false;
}
},
created(){
this.computedTime(this.formSearch.timeArr);
},
mounted () {
}
};
</script>
<style scoped>
.timeLimitStat >>> .ivu-table-expanded-cell {
padding: 0;
}
</style>
效果图:
