console
var Main = {
data () {
return {
filterName: '',
loading: false,
tableData: [],
originData: [],
tableTreeConfig: {
children: 'children',
accordion: true, // 一层只允许展开一个节点
expandAll: false // 默认是否全部展开
}
}
},
created () {
this.loading = true
this.findList().then(data => {
//this.tableData = this.getGroupSummary(data)
this.originData = this.getGroupSummary(data)
this.loading = false
this.handleSearch()
})
},
methods: {
findList () {
return new Promise(resolve => {
setTimeout(() => {
let list = [
{
name: '一班',
level: '',
age: '',
rate: '',
children: [
{ name: 'test7', rate: 9, age: 24, level: 1 },
{ name: 'test6', rate: 14, age: 20, level: 3 },
{
name: '第一组',
level: '',
age: '',
rate: '',
children: [
{ name: 'test85', rate: 13, age: 32, level: 1 },
{ name: 'test37', rate: 9, age: 29, level: 4 },
{ name: 'test93', rate: 22, age: 28, level: 5 },
{ name: 'test90', rate: 55, age: 26, level: 2 }
]
},
{ name: 'test32', rate: 11, age: 21, level: 1 }
]
},
{
name: '二班',
level: '',
age: '',
rate: '',
children: [
{ name: 'test15', rate: 13, age: 32, level: 1 },
{ name: 'test44', rate: 9, age: 29, level: 4 },
{
name: '第一组',
level: '',
age: '',
rate: '',
children: [
{ name: 'test37', rate: 9, age: 29, level: 4 },
{ name: 'test93', rate: 22, age: 28, level: 5 }
]
},
{
name: '第二组',
level: '',
age: '',
rate: '',
children: [
{ name: 'test74', rate: 11, age: 32, level: 5 },
{ name: 'test99', rate: 23, age: 18, level: 4 },
{
name: '第一排',
level: '',
age: '',
rate: '',
children: [
{ name: 'test48', rate: 77, age: 29, level: 4 },
{ name: 'test38', rate: 34, age: 21, level: 2 }
]
},
{ name: 'test16', rate: 22, age: 26, level: 5 }
]
},
{ name: 'test91', rate: 16, age: 27, level: 5 },
{
name: '第三组',
level: '',
age: '',
rate: '',
children: [
{ name: 'test77', rate: 11, age: 35, level: 1 },
{ name: 'test89', rate: 40, age: 18, level: 4 },
{ name: 'test10', rate: 22, age: 20, level: 2 }
]
}
]
},
{
name: '三班',
level: '',
age: '',
rate: '',
children: [
{ name: 'test6', rate: 3, age: 22, level: 2 },
{ name: 'test2', rate: 5, age: 25, level: 3 },
{ name: 'test42', rate: 17, age: 35, level: 4 }
]
}
]
resolve(list)
}, 300)
})
},
formatName ({ row }) {
return row.children && row.children.length ? `${row.name} (${row.num}人)` : row.name
},
meanNum (list, field) {
let count = 0
list.forEach(item => {
count += Number(item[field])
})
return count / list.length
},
sumNum (list, field) {
let count = 0
list.forEach(item => {
count += Number(item[field])
})
return count
},
// 计算逻辑
handleSummary (children) {
return {
num: this.sumNum(children, 'num'),
level: Math.floor(this.sumNum(children, 'level')),
age: parseInt(this.meanNum(children, 'age')),
rate: this.sumNum(children, 'rate')
}
},
getGroupSummary (data) {
XEUtils.eachTree(data, (row, index, items, path, parent, nodes) => {
let children = row.children
if (children && children.length) {
// 合计子节点
Object.assign(row, this.handleSummary(children))
} else {
row.num = 1
if (index === items.length - 1) {
// 全量汇总
for (let len = nodes.length - 2; len >= 0; len--) {
Object.assign(nodes[len], this.handleSummary(nodes[len].children))
}
}
}
}, this.tableTreeConfig)
XEUtils.eachTree(data, (row) => {
let children = row.children
if (children && children.length) {
// 动态增加一行汇总
children.push({
name: `合计 (${row.name})`,
level: row.level,
age: row.age,
rate: row.rate
})
}
}, this.tableTreeConfig)
return data
},
colspanMethod ({ row, column }) {
// 当行被展开时将行合并
let xTree = this.$refs.xTree
if (row.children && row.children.length && xTree && xTree.isTreeExpandByRow(row)) {
if (column.treeNode) {
return {
rowspan: 1,
colspan: 4
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
}
},
footerMethod ({ columns, data }) {
return [
columns.map((column, columnIndex) => {
if (columnIndex === 0) {
return `合计 (${this.sumNum(data, 'num')}人)`
}
switch (column.property) {
case 'level':
return `总计 ${Math.floor(this.sumNum(data, 'level'))}`
case 'age':
return `总计 ${Math.floor(this.sumNum(data, 'age'))}`
case 'rate':
return `总计 ${this.sumNum(data, 'rate')}`
}
return '-'
})
]
},
handleSearch () {
let filterName = XEUtils.toValueString(this.filterName).trim()
if (filterName) {
let options = { children: 'children' }
let searchProps = ['name']
this.tableData = XEUtils.searchTree(this.originData, item => searchProps.some(key => XEUtils.toValueString(item[key]).indexOf(filterName) > -1), options)
// 搜索之后默认展开所有子节点
this.$nextTick(() => {
this.$refs.xTree.setAllTreeExpand(true)
})
} else {
this.tableData = this.originData
}
},
// 创建一个防反跳策略函数,调用频率间隔 500 毫秒
searchEvent: XEUtils.debounce(function () {
this.handleSearch()
}, 500, { leading: false, trailing: true })
}
};
var app = new Vue(Main).$mount('#app')
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://cdn.jsdelivr.net/npm/xe-utils"></script>
<script src="https://cdn.jsdelivr.net/npm/vxe-table"></script>
<!-- 使用 cdn 引用方式需要注意是否锁定版本,默认指向最新版本 -->
<div id="app">
<template>
<div>
<vxe-toolbar>
<template #buttons>
<vxe-button @click="$refs.xTree.setAllTreeExpand(true)">展开所有</vxe-button>
<vxe-button @click="$refs.xTree.clearTreeExpand()">关闭所有</vxe-button>
</template>
</vxe-toolbar>
<vxe-table
resizable
show-footer
ref="xTree"
max-height="400"
:loading="loading"
:tree-config="tableTreeConfig"
:span-method="colspanMethod"
:footer-method="footerMethod"
:data="tableData">
<vxe-table-column field="name" title="名称" tree-node :formatter="formatName">
<template #header="{ row }">
<div>用户</div>
<input v-model="filterName" type="type" placeholder="请输入手机号" @keyup="searchEvent">
</template>
</vxe-table-column>
<vxe-table-column field="level" title="现金券充值(入金)"></vxe-table-column>
<vxe-table-column field="age" title="现金券提现(出金)"></vxe-table-column>
<vxe-table-column field="rate" title="现金券互转(出金)"></vxe-table-column>
</vxe-table>
</div>
</template>
</div>
@import url("https://cdn.jsdelivr.net/npm/vxe-table/lib/style.css");