VisActor / VisActor/VTable

[Feature] 树形表格, extensionRows形式扩展的行列,支持自定义表头及单元格

Open
#3,040 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature
Dominant language
TypeScript
Stars
3.7k
Forks
486
Avg merge
1d 19h
Merged PRs (30d)
16

Description

What problem does this feature solve?

https://visactor.com/vtable/demo/table-type/pivot-table-multi-tree 基础上,扩展出实现一个带合并单元格及树形节点的表格demo, 期望能针对节点自定义。

实现基础: extensionRows能力(如果有其他方式能实现如下效果也可以替代)

image

简单代码例子:
`
const useData = [
{
"group0": "111",
"group1": "Ouput",
"group2": "1",
"METRIC": "test111",
"unit": "个",
// "State": "test111-2221", 汇总行数据,需要去除子节点临时标识
"DIMENSION_1": "456",
"DIMENSION_2": "457",
rowId: 1,
},
{
"group0": "111",
"group1": "Ouput",
"group2": "1",
"METRIC": "test111",
"unit": "%",
"State": "test111-2221",
"DIMENSION_1": "458",
"DIMENSION_2": "459",
rowId: 2,
},
{
"group0": "111",
"group1": "Ouput",
"group2": "1",
"METRIC": "test111",
"unit": "%",
"State": "test111-2221", // 父亲标识
"State1": "test111-2221", // 叶子结点标识
"DIMENSION_1": "458",
"DIMENSION_2": "459",
rowId: 3,
},
{
"group0": "111",
"group1": "Ouput",
"group2": "11.1",
"METRIC": "test1111",
"unit": "%",
"DIMENSION_1": null,
"DIMENSION_2": "459",
rowId: 4,
},
// 汇总行
{
"group0": "222",
"group1": "input",
"group2": "222-111",
"METRIC": "tes333",
"unit": "%",
// "State": "test111-2222",
"DIMENSION_1": "458",
"DIMENSION_2": "457.899",
rowId: 5,
},
{
"group0": "222",
"group1": "input",
"group2": "222-111",
"METRIC": "tes333",
"unit": "%",
"State": "test111-2222", // 非汇总行值
"DIMENSION_1": "458",
"DIMENSION_2": "459",
rowId: 6,
},
]
const option = {
// records: data.map((item,index)=>{
// item.rowindex = index
// return item
// }),
records: useData.map((item,index)=>{
item.rowindex = index
return item
}),
rowSeriesNumber: {
title: "行号",
width: 70,
format: (col, row, table)=> {
// 使用固定列叶子结点所在列,从1开始数, 可以拿到原数据
let record = table.getRecordByCell(6, row) || {}
let a = table.getCellRawValue(6,row) || []
// console.log('11111',col,row,record[0], a)
return record[0]?.rowId || row
}
},
// 根节点行,有多少值,就有多少项
rowTree: [
{
dimensionKey: 'group0',
value: '111',
},
{
dimensionKey: 'group0',
value: '222',
}
// {
// dimensionKey: 'group1',
// value: 'Ouput',
// },
// {
// dimensionKey: 'group1',
// value: 'input'
// },
],
columnTree: [
{
value: '趋势',
indicatorKey: 'DIMENSION_0',
dimensionKey:'DIMENSION_0'
},
{
value: '2024-12-01',
indicatorKey: 'DIMENSION_1',
dimensionKey:'DIMENSION_1'
},
{
value: '2024-12-02',
indicatorKey: 'DIMENSION_2',
dimensionKey:'DIMENSION_2'
}
],
// 行维度列(非数据列),配置扩展行时,只指定第一个列也可以
rows: [
{
dimensionKey: 'group0',
title: '分组0',
minWidth: 100
}
// {
// dimensionKey: 'group1',
// title: '分组1',
// minWidth: 100
// },
// {
// dimensionKey: 'group2',
// title: '分组2',
// minWidth: 100
// },
// {
// dimensionKey: 'metric',
// title: '树节点列',
// minWidth: 100
// },
// {
// dimensionKey: 'unit',
// title: '单位',
// minWidth: 100
// },
],
// columnTree:[],
// 无列维度
columns: [
// {
// dimensionKey: 'group0',
// title: '分组0',
// headerStyle: {
// textStick: true
// },
// minWidth: '100'
// },
// {
// dimensionKey: 'group1',
// title: '分组1',
// headerStyle: {
// textStick: true
// },
// minWidth: '100'
// },
// {
// dimensionKey: 'group2',
// title: '分组2',
// headerStyle: {
// textStick: true
// },
// minWidth: '100'
// },
// {
// dimensionKey: 'unit',
// title: '单位',
// headerStyle: {
// textStick: true
// },
// width: 'auto'
// }
],
extensionRows: [
{
rows: [{ dimensionKey: 'group1', title: '分组1', minWidth: 100 }],
rowTree(args) {
const valueData = ['Ouput','input']
// valueData.forEach((item)=>{
const currentROWS = useData.find((data)=>{
return data['group0'] === args[0].value
})
console.log('---11111111---2222----',args,currentROWS)

        return [{
          dimensionKey: 'group1',
          value: currentROWS['group1'] || 'input'
        }]
      },
    },
    {
      rows: [{ dimensionKey: 'group2', title: '分组2', minWidth: 100 }, ],
      rowTree(args) {
        console.log('分组2', args)
        if (args[1].value === 'input') {
          return [
            {
              dimensionKey: 'group2',
              value: '222-111'
            }
          ]
        }
        return [
            {
              dimensionKey: 'group2',
              value: '1'
            },
            {
              dimensionKey: 'group2',
              value: '11.1'
            },
        ]
      },
    },
    {
      rows: [{ dimensionKey: 'METRIC', title: '树节点列', minWidth: 200 }, 'State', 'State1'],
      rowTree(args) {
        console.log('args[1].value', args)
        if (args[2].value === '1') {
          return [
            {
              dimensionKey: 'METRIC',
              value: 'test111',
              children: [
                {
                  dimensionKey: 'State',
                  value: 'test111-2221',
                  children: [{
                    dimensionKey: 'State1',
                    value: 'test111-2221',
                  }]
                },
              ]
            },
          ]
        }
        if(args[2].value === '11.1'){
          return [
            {
              dimensionKey: 'METRIC',
              value: 'test1111'
            },
          ]
        }
        return [
            {
              dimensionKey: 'METRIC',
              value: 'tes333',
              children: [
                {
                  dimensionKey: 'State',
                  value: 'test111-2222'
                },
              ]
            },
        ]
      },
    },
    {
      rows: [{ dimensionKey: 'unit', title: "单位", minWidth: 200 }],
      rowTree(args) {
        // 前置列的下标
        if (args[3].value === 'test111') {
          console.log('args', args)
          return [
            {
              dimensionKey: 'unit',
              value: '个',
            },
          ]
        }
        return [
            {
              dimensionKey: 'unit',
              value: '%',
            },
        ]
      },
    }
  ],
  indicators: [
    {
      indicatorKey: 'DIMENSION_1',
      title: '2024-12-01',
      minWidth: 120,
      showSort: false,
      headerStyle: {
        fontWeight: 'normal'
      },
      // format: value => {
      //   if (value) {
      //     return '$' + Number(value).toFixed(2);
      //   }
      //   return '';
      // },
      style: {
        padding: [16, 28, 16, 28],
        color(args) {
          if (args.dataValue >= 0) {
            return 'black';
          }
          return 'red';
        }
      }
    },
    {
      indicatorKey: 'DIMENSION_2',
      title: '2024-12-02',
      minWidth: 120,
      showSort: false,
      headerStyle: {
        fontWeight: 'normal'
      },
      // format: value => {
      //   if (value) {
      //     return '$' + Number(value).toFixed(2);
      //   }
      //   return '';
      // },
      style: {
        padding: [16, 28, 16, 28],
        color(args) {
          if (args.dataValue >= 0) {
            return 'black';
          }
          return 'red';
        }
      }
    },
  ],
  corner: {
    titleOnDimension: 'row',
    headerStyle: {
      textStick: true
    }
  },
  rowHierarchyType: 'tree',
  widthMode: 'standard',
  rowHierarchyIndent: 20,
  rowExpandLevel: 1,
  rowHierarchyTextStartAlignment: true,
  dragHeaderMode: 'all'
};

const instance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option);
window.tableInstance = instance;
`
What does the proposed API look like?

类似单元格 stye 等,有特定的配置项即可

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the PivotTable option example in the issue, especially extensionRows, rowTree, custom headers, and cell-related configuration. Define the configuration needed to customize merged tree-table headers and cells, then verify that the proposed API supports the shown hierarchy and data before adding a focused demo or test; no repository file or test is named in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
data-visualization, frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.