SOURCE

console 命令行工具 X clear

                    
>
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");