iview table表格中独家实现表头分组的改造

2022-03-12 1391点热度 0人点赞 0条评论

需求说明

iView的表格虽然有了很多定制化的功能,不过有一个需求,官方始终没有实现,那就是表格的分组功能,来看下这个需求,客户想要实现如图的分组功能:

根据时间的不同,按照『今天』,『昨天』,『一周内』,『一个月内』,『更早』,另外根据其他需求的不同,根据其他类别进行分组展示。

硬核独家实现

虽然官方没有提供现成的解决方案,不过iView表格文档的『特定样式』进行改造,来实现这部分效果。这部分网上查了没有相关的实现,是我自己想出来的,应该算是独家吧,哈哈。

如上图,分组显示的列其实也是普通的一行,只是使用列合并把整行都跨过去了。另外针对这种特殊的行(带有_group的)加上了特定的样式。

HTML代码如下:

<i-table stripe border :columns="columns" :data="list" :row-class-name="rowClassName" :span-method="handleSpan"></i-table>

rowClassName就是定制分组表头的样式,handleSpan就进行列合并:

handleSpan({row, column, rowIndex, columnIndex}) {
    if (row['_group']) {
        return columnIndex === 0 ? [1, this.columns.length] : [1, 0];
    }
    return [1, 1]
},
rowClassName(row, index) {
    if (row['_group']) {
        return 'group-row';
    }
    return '';
},

分组行用到的样式:

<style type="text/css">
    /*自定义表格分组*/
    .ivu-table .group-row td {
        background-color: #D7D9DD !important;
        height: 32px;
        font-weight: 600;
        text-align: left;
        /*color: #fff;*/
    }

    .ivu-table .group-row1 td {
        background-color: #D7D9DD !important;
        height: 32px;
        padding-left: 60px;
        font-weight: 600;
        text-align: left;
        /*color: #fff;*/
    }

    .span-min-with-item {
        display: inline-block;
        min-width: 80px;
        font-weight: 600;
    }
</style>

list就是数组数据,我们对后端返回的数据进行了分组再处理,给新的一行加上特殊的标记(_group)标志这这一行是分组行

function groupList(list, keyGetter, type, noGetter) {
    if(!list) {
        return [];
    }
    const map = new Map();
    let emptyKey = false;
    list.forEach((item) => {
        let key = keyGetter(item);
        if (key && type === 'date') {
            let date = moment(key);
            if (date.isValid()) {
                if (date.isSame(moment(), "day")) {
                    key = "今天";
                } else if (date.isSame(moment().subtract(1, 'days'), "day")) {
                    key = '昨天';
                } else if (date.isSame(moment().subtract(2, 'days'), "day")) {
                    key = '前天';
                } else if (date.isAfter(moment().subtract(7, 'days'), "day")) {
                    key = '一周内';
                } else if (date.isAfter(moment().subtract(1, 'months'), "day")) {
                    key = '一月内';
                } else {
                    key = date.format("更早");
                    // key = date.format("YYYY-MM");
                    // key = date.format("YYYY-MM-DD");
                }
            }
        }

        if (!key) {
            key = '--';
            emptyKey = true;
        }
        const collection = map.get(key);
        if (!collection) {
            map.set(key, [item]);
        } else {
            collection.push(item);
        }
    });
    if (map.size === 1 && emptyKey) {//只有一个,而且是空的,就不分组了
        return list;
    }
    let newItems = [];
    map.forEach((value, key) => {
        if (key) {
            let itm = {_group: key};
            if (noGetter) {
                itm['_groupNo'] = noGetter(value[0]);
            }
            newItems.push(itm);
        }
        newItems.push(...value);
    });
    // console.log(newItems)
    return newItems;
}

以上是分组加工使用的工具方法,我们对后台传过来的list进行如下处理:

var list = [];//后台传来的数据,这里省略

// 对数据的startDate进行分组,分组后,会对不同的组。加上一行特殊的行,(带有_group)
this.list = groupList(list, itm => itm["startDate"], "date");

columns的定义如下:

var columns = [
    {
        title: '审批状态',
        width: 110,
        key: 'action',
        render: function (h, params) {
            // 第一列是带有分组标志的,特殊返回
            if(params.row['_group']) {
                return h("span", params.row['_group']);
            }
            var found = app.actions.find(function (item) {
                return item.id == params.row.action;
            });
            var foundName = found ? found.name : '';
            var color = 'default';
            switch (params.row.action) {
                case 1:
                    color = 'success';
                    break;
                case 0:
                    color = 'warning';
                    break;
                case 3:
                    color = 'volcano';
                    break;
                case 2:
                case 4:
                    color = 'error';
                    break;
                default:
                    break;
            }
            return h('Tag', {
                props: {color: color}
            }, foundName)
        },
        filters: this.actions.map(function (item) {
            return {label: item.name, value: item.id}
        }),
        filterMultiple: false,
        filterRemote: function (value) {
            app.filterColumn = 'action';
            app.filterValue = value.length > 0 ? value[0] : '';
            app.loadList(1);
        }
    },
    {
        title: '仪器名称',
        minWidth: 180,
        key: 'equipName',
        sortable: 'custom'
    }
    // 后面其他的列,省略
    ]

 

 

admin

这个人很懒,什么都没留下

文章评论

您需要 登录 之后才可以评论