SOURCE

let tableData =
    [
        {
            bank: 'gfBank',
            werks: '5041',
            zquarter: 'quarter1',
            paper_money: '50',
            deposit: '50',
            edate: '2022-10',
            id: '82',
        },
        {
            bank: 'gfBank',
            werks: '3031',
            zquarter: 'quarter1',
            paper_money: '40',
            deposit: '40',
            edate: '2022-09',
            id: '81',
        },
        {
            bank: 'gfBank',
            werks: '1011',
            zquarter: 'quarter1',
            paper_money: '60',
            deposit: '60',
            edate: '2022-09',
            id: '80',
        },
        {
            bank: 'jsBank',
            werks: '1011',
            zquarter: 'quarter2',
            paper_money: '50',
            deposit: '50',
            edate: '2022-09',
            id: '79',
        },
        {
            bank: 'jsBank',
            werks: '1011',
            zquarter: 'quarter1',
            paper_money: '50',
            deposit: '50',
            edate: '2022-09',
            id: '78',
        },
        {
            bank: 'gfBank',
            werks: '3031',
            zquarter: 'quarter3',
            edate: '2022-12',
            paper_money: '900',
            deposit: '1000',
            id: '77',
        },
        {
            bank: 'gfBank',
            werks: '3031',
            zquarter: 'quarter3',
            edate: '2022-11',
            paper_money: '900',
            deposit: '1000',
            id: '76',
        },
        {
            bank: 'gfBank',
            werks: '3031',
            zquarter: 'quarter3',
            edate: '2022-10',
            paper_money: '900',
            deposit: '1000',
            id: '75',
        },
        // {
        //     bank: 'gfBank',
        //     werks: '3031',
        //     zquarter: 'quarter3',
        //     edate: '2022-09',
        //     paper_money: '900',
        //     deposit: '1000',
        //     id: '74',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '1011',
        //     zquarter: 'quarter3',
        //     edate: '2022-12',
        //     paper_money: '800',
        //     deposit: '900',
        //     id: '73',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '1011',
        //     zquarter: 'quarter3',
        //     edate: '2022-11',
        //     paper_money: '800',
        //     deposit: '900',
        //     id: '72',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '1011',
        //     zquarter: 'quarter3',
        //     edate: '2022-10',
        //     paper_money: '800',
        //     deposit: '900',
        //     id: '71',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '1011',
        //     zquarter: 'quarter3',
        //     edate: '2022-09',
        //     paper_money: '800',
        //     deposit: '900',
        //     id: '70',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '4031',
        //     zquarter: 'quarter3',
        //     edate: '2022-12',
        //     paper_money: '700',
        //     deposit: '800',
        //     id: '69',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '4031',
        //     zquarter: 'quarter3',
        //     edate: '2022-11',
        //     paper_money: '700',
        //     deposit: '800',
        //     id: '68',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '4031',
        //     zquarter: 'quarter3',
        //     edate: '2022-10',
        //     paper_money: '700',
        //     deposit: '800',
        //     id: '67',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '4031',
        //     zquarter: 'quarter3',
        //     edate: '2022-09',
        //     paper_money: '700',
        //     deposit: '800',
        //     id: '66',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '5041',
        //     zquarter: 'quarter3',
        //     edate: '2022-12',
        //     paper_money: '600',
        //     deposit: '700',
        //     id: '65',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '5041',
        //     zquarter: 'quarter3',
        //     edate: '2022-11',
        //     paper_money: '600',
        //     deposit: '700',
        //     id: '64',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '5041',
        //     zquarter: 'quarter3',
        //     edate: '2022-10',
        //     paper_money: '600',
        //     deposit: '700',
        //     id: '63',
        // },
        // {
        //     bank: 'gfBank',
        //     werks: '5041',
        //     zquarter: 'quarter3',
        //     edate: '2022-09',
        //     paper_money: '600',
        //     deposit: '700',
        //     id: '62',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '3031',
        //     zquarter: 'quarter3',
        //     edate: '2022-12',
        //     paper_money: '500',
        //     deposit: '600',
        //     id: '61',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '3031',
        //     zquarter: 'quarter3',
        //     edate: '2022-11',
        //     paper_money: '500',
        //     deposit: '600',
        //     id: '60',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '3031',
        //     zquarter: 'quarter3',
        //     edate: '2022-10',
        //     paper_money: '500',
        //     deposit: '600',
        //     id: '59',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '3031',
        //     zquarter: 'quarter3',
        //     edate: '2022-09',
        //     paper_money: '500',
        //     deposit: '600',
        //     id: '58',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '1011',
        //     zquarter: 'quarter3',
        //     edate: '2022-12',
        //     paper_money: '400',
        //     deposit: '500',
        //     id: '57',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '1011',
        //     zquarter: 'quarter3',
        //     edate: '2022-11',
        //     paper_money: '400',
        //     deposit: '500',
        //     id: '56',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '1011',
        //     zquarter: 'quarter3',
        //     edate: '2022-10',
        //     paper_money: '400',
        //     deposit: '500',
        //     id: '55',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '1011',
        //     zquarter: 'quarter3',
        //     edate: '2022-09',
        //     paper_money: '400',
        //     deposit: '500',
        //     id: '54',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '4031',
        //     zquarter: 'quarter3',
        //     edate: '2022-12',
        //     paper_money: '300',
        //     deposit: '400',
        //     id: '53',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '4031',
        //     zquarter: 'quarter3',
        //     edate: '2022-11',
        //     paper_money: '300',
        //     deposit: '400',
        //     id: '52',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '4031',
        //     zquarter: 'quarter3',
        //     edate: '2022-10',
        //     paper_money: '300',
        //     deposit: '400',
        //     id: '51',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '4031',
        //     zquarter: 'quarter3',
        //     edate: '2022-09',
        //     paper_money: '300',
        //     deposit: '400',
        //     id: '50',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '5041',
        //     zquarter: 'quarter3',
        //     edate: '2022-12',
        //     paper_money: '200',
        //     deposit: '300',
        //     id: '49',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '5041',
        //     zquarter: 'quarter3',
        //     edate: '2022-11',
        //     paper_money: '200',
        //     deposit: '300',
        //     id: '48',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '5041',
        //     zquarter: 'quarter3',
        //     edate: '2022-10',
        //     paper_money: '200',
        //     deposit: '300',
        //     id: '47',
        // },
        // {
        //     bank: 'cnBank',
        //     werks: '5041',
        //     zquarter: 'quarter3',
        //     edate: '2022-09',
        //     paper_money: '200',
        //     deposit: '300',
        //     id: '46',
        // },
    ]






function subtotal({ data, subtotalFields, quatoFields }) {
    const res = [];
    const subtotalFieldsObj = Object.fromEntries(subtotalFields.map(item => [item, '']))
    const total = (function dfs(items, i) {
        const total = Object.fromEntries(quatoFields.map((k) => [k, 0]));
        if (i == subtotalFields.length) {
            items.forEach((item) => {
                quatoFields.forEach((k) => (total[k] += +item[k]))
            });
            res.push(...items);
        } else {
            const k = subtotalFields[i++];
            items
                .reduce((map, item) => {
                    const feature = item[k];
                    if (map.has(feature)) {
                        item[k] = '';
                    } else {
                        map.set(feature, []);
                    }
                    map.get(feature).push(item);
                    return map;
                }, new Map())
                .forEach((items, feature) => {
                    const sub = dfs(items, i);
                    res.push({ ...subtotalFieldsObj, [k]: feature + '小计', ...sub });
                    quatoFields.forEach((k) => (total[k] += sub[k]));
                });
        }
        return total;
    })(data.map((item) => ({ ...item, rawItem: item })), 0);
    return [res, total];
}

const [res, total] = subtotal({
    data: tableData,
    subtotalFields: ["bank"],
    quatoFields: ["paper_money", "deposit"],
});

console.log(res);
console.log(total);


console.log(tableData)
function calcRowSpan({ data, subtotalFields, i = 0 }) {
    let map = {}
    data.forEach((item, index) => {
        map[item[subtotalFields[i]]] = map[item[subtotalFields[i]]] || {}
    })
    if (i == subtotalFields.length - 1) {
        for (let k in map) {
            map[k].children = data.filter(item => item[subtotalFields[i]] == k)
            map[k].rowSpan = map[k].children.length
        }
    } else {
        for (let k in map) {
            const filterData = data.filter(item => item[subtotalFields[i]] == k)
            map[k].children = calcRowSpan({ data: filterData, subtotalFields, i: i + 1 })
            for (let k1 in map[k].children) {
                map[k].rowSpan = map[k].rowSpan || 0;
                map[k].rowSpan += map[k].children[k1].rowSpan;
                if (map[k].children[k1].rowSpan !== 0) {
                    map[k].rowSpan += 1;
                }
            }
        }
    }

    return map
}

let rowSpanMap = calcRowSpan({ data: tableData, subtotalFields: ["bank"] })
console.log(rowSpanMap)
console 命令行工具 X clear

                    
>
console