iviwe table 合并行(element/iview 通用)

418 阅读2分钟

最近开发任务的需求,合并行,话不多说先上需求

image.png

需要将第一行拉通,第三列通过分组设置合并行,简单了解下文档。

设置属性 span-method 可以指定合并行或列的算法,该方法参数为 4 个对象:

  • row: 当前行
  • column: 当前列
  • rowIndex: 当前行索引
  • columnIndex: 当前列索引 该函数可以返回一个包含两个元素的数组,第一个元素代表 rowspan,第二个元素代表 colspan。 也可以返回一个键名为 rowspan 和 colspan 的对象。这是一个官网描述

处理第一行合并拉通

/** 行合并 */
handleSpan({ row, column, rowIndex, columnIndex }) {
    // 第一列所有行合并
    if (rowIndex === 0 && columnIndex === 0) {
        return {
            rowspan: this.dataSource.length,
            colspan: 1
        }
    } else if (rowIndex !== 0 && columnIndex === 0) {
        return {
            rowspan: 0,
            colspan: 0
        }
    }
}

通过判断行索引和列索引 逗是否为0 如果是 ,则合并rowspan,否则就隐藏。第一个合并的解决了,看下效果

image.png

开始处理第三列数据行

怎么合并呢,怎么确定合并多少行?先看看我的方式 咋样

  • 通过关键字遍历每条数据进行分组
  • 统计该关键字出现的次数
  • 再次循环数据,通过key值,将统计的行数赋值给第一次出现的对象,并删除统计的行数
/** 处理数据 */
handleDataSource() {
    const obj = {} // 记录 合并行 行数
    const GROUP_FIELD = 'group'

    // 记录需要合并的行数
    this.dataSource.forEach((item) => {
        if (!obj[item[GROUP_FIELD]]) {
            obj[item[GROUP_FIELD]] = 1
        } else {
            obj[item[GROUP_FIELD]] += 1
        }
    })

    // 将合并的第二列通过 rowSpanCounter来记录,如果有值 则分组,如果没值,则在分组内
    this.dataSource = this.dataSource.map((item) => {
        if (obj[item[GROUP_FIELD]]) {
            item.rowSpanCounter = obj[item[GROUP_FIELD]]
            delete obj[item[GROUP_FIELD]]
        }
        return item
    })
}

注意观察格式,只有合并的行才会出现rowSpanCounter,那么在合并行处理的时候就直接判断行是否有这个属性就行了 image.png

// 第二列通过分组来合并
if (columnIndex === 2) {
    // 如果行存在rowSpanCounter,则通过这个字段来合并行
    if (row.rowSpanCounter) {
        return {
            rowspan: row.rowSpanCounter,
            colspan: 1
        }
    } else {
        return {
            rowspan: 0,
            colspan: 0
        }
    }
}

实现效果:

image.png

ok,是否所有都解决了呢,贴个完整代码,有需要的自取,当然有更好的处理方式,欢迎讨论

<template>
    <Drawer :title="$t('HPC专属资源池-价格详情')" width="700" v-model="visible">
        <h4>
            <span>{{ $t('计算资源') }}</span>
        </h4>
        <Table :columns="columns" :data="dataSource" border :span-method="handleSpan"></Table>
    </Drawer>
</template>
<script>
export default {
    data() {
        this.rules = {}
        this.columns = [
            { title: this.$t('资源类型'), key: 'resourceType', ellipsis: true, width: 100 },
            { title: this.$t('规格分组'), key: 'specGroup', ellipsis: true, width: 100 },
            { title: this.$t('计费规格'), key: 'chargeSped', ellipsis: true, width: 100 },
            {
                title: this.$t('价格'),
                key: 'price'
            }
        ]
        return {
            visible: true,
            loading: false,
            dataSource: []
        }
    },
    created() {
        this.dataSource = [
            {
                resourceType: '计算',
                group: 'test',
                specGroup: 'test(HA)',
                chargeSped: 'paired',
                price: '按量计费:¥0.00000/小时'
            },
            {
                resourceType: '计算',
                group: 'test',
                specGroup: 'test(HA)',
                chargeSped: 'paired',
                price: '包年包月:¥10.00/月'
            },
            {
                resourceType: '计算',
                group: 'test1',
                specGroup: 'test(非HA)',
                chargeSped: 'paired',
                price: '按量计费:¥0.00000/小时'
            },
            {
                resourceType: '计算',
                group: 'test1',
                specGroup: 'test(非HA)',
                chargeSped: 'paired',
                price: '包年包月:¥10.00/月'
            },
            {
                resourceType: '计算',
                group: 'test3',
                specGroup: 'test(HA)',
                chargeSped: 'paired',
                price: '按量计费:¥0.00000/小时'
            },
            {
                resourceType: '计算',
                group: 'test3',
                specGroup: 'test(HA)',
                chargeSped: 'paired',
                price: '包年包月:¥10.00/月'
            },
            {
                resourceType: '计算',
                group: 'test4',
                specGroup: 'test(HA)',
                chargeSped: 'paired',
                price: '按量计费:¥0.00000/小时'
            },
            {
                resourceType: '计算',
                group: 'test4',
                specGroup: 'test(HA)',
                chargeSped: 'paired',
                price: '包年包月:¥10.00/月'
            }
        ]
        this.handleDataSource()
    },
    methods: {
        /** 处理数据 */
        handleDataSource() {
            const obj = {} // 记录 合并行 行数
            const GROUP_FIELD = 'group'

            // 记录需要合并的行数
            this.dataSource.forEach((item) => {
                if (!obj[item[GROUP_FIELD]]) {
                    obj[item[GROUP_FIELD]] = 1
                } else {
                    obj[item[GROUP_FIELD]] += 1
                }
            })

            // 将合并的第二列通过 rowSpanCounter来记录,如果有值 则分组,如果没值,则在分组内
            this.dataSource = this.dataSource.map((item) => {
                if (obj[item[GROUP_FIELD]]) {
                    item.rowSpanCounter = obj[item[GROUP_FIELD]]
                    delete obj[item[GROUP_FIELD]]
                }
                return item
            })
        },
        openModal(id) {
            this.visible = true
        },
        /** 行合并 */
        handleSpan({ row, column, rowIndex, columnIndex }) {
            // 第一列所有行合并
            if (rowIndex === 0 && columnIndex === 0) {
                return {
                    rowspan: this.dataSource.length,
                    colspan: 1
                }
            } else if (rowIndex !== 0 && columnIndex === 0) {
                return {
                    rowspan: 0,
                    colspan: 0
                }
            }

            // 第二列通过分组来合并
            if (columnIndex === 2) {
                // 如果行存在rowSpanCounter,则通过这个字段来合并行
                if (row.rowSpanCounter) {
                    return {
                        rowspan: row.rowSpanCounter,
                        colspan: 1
                    }
                } else {
                    return {
                        rowspan: 0,
                        colspan: 0
                    }
                }
            }
        }
    }
}
</script>

<style lang="less" scoped>
h4 {
    background: #f5f6f7;
    line-height: 35px;
    padding: 0 15px;
    margin: 0 0 15px 0;
}
</style>