ali-react-table icon indicating copy to clipboard operation
ali-react-table copied to clipboard

CrossTable 可以对数据排序么?

Open daguanjia opened this issue 3 years ago • 5 comments

想对CrossTable的数据进行排序

daguanjia avatar Jul 06 '21 12:07 daguanjia

我们也是:希望支持对CrossTable的排序功能?

xiaoxudoo avatar Jul 07 '21 13:07 xiaoxudoo

收到,我有空了之后看下,如果大家有什么排序的好想法,也可以在这里写一下

feichao93 avatar Jul 08 '21 11:07 feichao93

交叉表排序有个问题,因为code都一样,会激活多列。 onChangeSorts的参数nextSorts也只有code,无法区分到底是哪一列激活了排序。 目前卡在这里了,需要知道是具体哪一列触发了排序。

jydeng avatar Jul 05 '22 12:07 jydeng

可以用buildCrossTableCrossTable 的数据转换成 BaseTable 的 props,然后使用 sort feature

zhang0ZGC avatar Jul 06 '22 02:07 zhang0ZGC

经过一番折腾解决了,大概说一下思路: 1、排序插件提供了 SortHeaderCell,可以传递 ReactNode,不过也意味着要完全自己做了; 2、自定义 SortHeaderCell,可以获取到具体哪一列触发了排序,例如: 福州/利润、厦门/利润,可以获取到具体是福州还是厦门; 3、获取到具体哪列之后,问题就剩下排序算法,可以查看一下 leftDrillTree,这个数据顺序决定了排序; 4、排序 leftDrillTree,生成新的matrix,完成排序。

总结一下,现有SortItem只有code,order,对于CrossTable按列值排序的场景不太适用,缺少了关键的dataKey,自己实现的话比较绕一些,要重复实现排序效果与事件。

  const pipeline = useTablePipeline()
    .input({ dataSource: dataSource, columns: columns })
    .use(
      features.sort({
        mode: 'single',
        highlightColumnWhenActive: false,
        keepDataSource: true,
        SortHeaderCell: props => (
          <SortHeaderCell {...props} {...sortItem} onSort={setSortItem} />
        ),
      }),
    );

// 获取当前排序,用于相同code排序的情况
function getCurOrder(
  column: any,
  dataKey: string,
  code: string,
  order: SortOrder,
): SortOrder {
  const isSameCode = column.code === code;
  const isSameDataKey = getDataKey(column) === dataKey;
  return isSameCode && isSameDataKey ? order : 'none';
}

// 获取下一个排序
function nextOrder(order: SortOrder): SortOrder {
  const orders: SortOrder[] = ['asc', 'desc', 'none'];
  const curIdx = orders.findIndex(t => t === order);
  return orders[curIdx === orders.length - 1 ? 0 : curIdx + 1];
}

// 获取dataKey
function getDataKey(column: any): string {
  return column?.data?.dataKey || '';
}

// 自定义排序表头
function SortHeaderCell({
  children,
  column,
  dataKey,
  code,
  order,
  onSort,
}: AdSortHeaderCellProps) {
  const curOrder = getCurOrder(column, dataKey, code, order);
  return (
    <div
      style={{ cursor: 'pointer' }}
      onClick={() =>
        onSort({
          dataKey: getDataKey(column),
          code: column.code as string,
          order: nextOrder(curOrder),
        })
      }
    >
      {children}
      <SortIcon size={16} order={curOrder} />
    </div>
  );
}

jydeng avatar Jul 07 '22 02:07 jydeng