Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[table] 带拖拽功能的树表格表头操作全选,会选中已禁用选择的行 #3499

Closed
chenli1989 opened this issue Oct 19, 2023 · 8 comments
Assignees

Comments

@chenli1989
Copy link

chenli1989 commented Oct 19, 2023

tdesign-vue-next 版本

1.6.3

重现链接

https://codesandbox.io/s/tree-table-forked-n6l5vw?file=/src/Demo.vue

重现步骤

树表格开启选择行,设置指定行禁用选择。树表格表头操作全选,会把设置禁用选择的行一起选中。
[t-table] 组件正常。
[t-enhanced-table] 组件异常,不应该一起选中已禁用选择的行!

期望结果

树表格表头操作全选,不要选中已禁用选择的行

实际结果

树表格表头操作全选,选中已禁用选择的行

框架版本

3.3.4

浏览器版本

Chrome(118.0.5735.248)

系统版本

Windows 11

Node版本

v18..17.1

补充说明

看重现

@github-actions
Copy link
Contributor

👋 @chenli1989,感谢给 TDesign 提出了 issue。
请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。

@chenli1989 chenli1989 changed the title [组件名称] 描述问题的标题 [t-enhanced-table] 树表格表头操作全选,选中已禁用选择的行 Oct 19, 2023
@chenli1989 chenli1989 changed the title [t-enhanced-table] 树表格表头操作全选,选中已禁用选择的行 [table] 树表格表头操作全选,选中已禁用选择的行 Nov 1, 2023
Copy link
Contributor

github-actions bot commented Nov 1, 2023

♥️ 有劳 @Louiszhai @PengYYYYY @chaishi 尽快确认问题。
确认有效后将下一步计划和可能需要的时间回复给 @chenli1989

@chenli1989
Copy link
Author

♥️ 有劳 @Louiszhai @PengYYYYY @chaishi 尽快确认问题。 确认有效后将下一步计划和可能需要的时间回复给 @chenli1989

升级至 1.6.6 问题还存在

@chaishi
Copy link
Collaborator

chaishi commented Nov 5, 2023

去掉行拖拽功能就表现正常了

https://codesandbox.io/s/tree-table-forked-wn7wn9?file=/src/Demo.vue:0-12596

image

@chaishi chaishi changed the title [table] 树表格表头操作全选,选中已禁用选择的行 [table] 带拖拽功能的树表格表头操作全选,会选中已禁用选择的行 Nov 5, 2023
@chaishi
Copy link
Collaborator

chaishi commented Nov 5, 2023

涉及到表格拖拽功能的问题,后续关注 #3567 这里

@chaishi chaishi closed this as completed Nov 5, 2023
@chaishi
Copy link
Collaborator

chaishi commented Nov 5, 2023

我看官网是正常的,提供的示例代码,和官网代码,最大的区别是什么
image

{
    // 列拖拽排序必要参数
    colKey: 'drag',
    title: '排序',
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    cell: (h) => <MoveIcon />,
    width: 46,
  },

Vue3 和 sortablejs 拖拽插件不兼容,会引起一些意料之外的问题,
Vue2/React 中使用 sortablejs 没有问题。

后续考虑方案,移除 Vue3 中使用的插件 sortablejs,更为单独实现,避免 Vue3 一系列不兼容的问题

@chenli1989
Copy link
Author

我看官网是正常的,提供的示例代码,和官网代码,最大的区别是什么 image

{
    // 列拖拽排序必要参数
    colKey: 'drag',
    title: '排序',
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    cell: (h) => <MoveIcon />,
    width: 46,
  },

Vue3 和 sortablejs 拖拽插件不兼容,会引起一些意料之外的问题, Vue2/React 中使用 sortablejs 没有问题。

后续考虑方案,移除 Vue3 中使用的插件 sortablejs,更为单独实现,避免 Vue3 一系列不兼容的问题

@chaishi 与官网示例的差别就是在树表格上多一个开启行可拖拽功能。开启行可拖拽功能,全选操作就会出现已禁用选择的行会被选中。目前这个问题在 v1.6.8 版本还是存在。

@huangchen1031
Copy link
Contributor

huangchen1031 commented Jan 3, 2024

这个BUG应该和Vue3以及sortablejs没关系。

跟踪代码发现,第一层问题在这里:

// useTreeSelect.tsx
// line: 183 ~ 193

  function onInnerSelectChange(rowKeys: SelectChangeParams[0], extraData: SelectChangeParams[1]) {
    if (!tree.value || tree.value.checkStrictly) {
      setTSelectedRowKeys(rowKeys, extraData);
      return;
    }
    if (extraData.currentRowKey === 'CHECK_ALL_BOX') {
      handleSelectAll(extraData);
    } else {
      handleSelect(rowKeys, extraData);
    }
  }

经检验发现,treeConfig增加checkStrictly属性,全选勾选正常。说明问题在第二个if里,然后检查下面的方法:

// useTreeSelect.tsx
// line 195 ~ 213

  function handleSelectAll(extraData: SelectChangeParams[1]) {
    const newRowKeys: Array<string | number> = [];
    const newRowData: TableRowData[] = [];
    if (extraData.type === 'check') {
      const arr = [...treeDataMap.value.values()];
      for (let i = 0, len = arr.length; i < len; i++) {
        const item = arr[i];
        // 问题在这里的状态不对
        if (!item.disabled) {
          newRowData.push(item.row);
          newRowKeys.push(get(item.row, rowDataKeys.value.rowKey));
        }
      }
    }
    const newExtraData = {
      ...extraData,
      selectedRowData: newRowData || [],
    };
    setTSelectedRowKeys(newRowKeys, newExtraData);
  }

关键在202行的判断,所以其实是treeDataMap里面本身的状态有问题。
然后追踪到初始化的地方:

// tree-store.ts
// line 648 ~ 680

  initialTreeDataMap(
    treeDataMap: TableTreeDataMap,
    dataSource: T[],
    column: PrimaryTableCol,
    keys: KeysType,
    level = 0,
    parent: TableRowState = null,
  ) {
    for (let i = 0, len = dataSource.length; i < len; i++) {
      const item = dataSource[i];
      const rowValue = getUniqueRowValue(item, keys.rowKey);
      if (isUndefined(rowValue)) {
        log.error('EnhancedTable', '`rowKey` could be wrong, can not get rowValue from `data` by `rowKey`.');
        return;
      }
      const children = get(item, keys.childrenKey);
      const state: TableRowState = {
        id: rowValue,
        row: item,
        rowIndex: level === 0 ? i : -1,
        level,
        expanded: false,
        expandChildrenLength: 0,
        disabled: isRowSelectedDisabled(column, item, i),
        parent,
      };
      state.path = parent ? parent.path.concat(state) : [state];
      treeDataMap.set(rowValue, state);
      if (children?.length) {
        this.initialTreeDataMap(treeDataMap, children, column, keys, level + 1, state);
      }
    }
  }

发现disabled是根据传进来的column去计算获得,于是乎:

// tree-store.ts
// line 72 ~ 75

  initialTreeStore(dataSource: T[], columns: PrimaryTableCol[], keys: KeysType) {
    this.treeDataMap?.clear();
    this.initialTreeDataMap(this.treeDataMap, dataSource, columns[0], keys);
  }

这里居然用columns[0]去当做复选框列进行传参。。。
改了下示例代码,调换dragrow-select两列的顺序全选禁用又生效了~ 所以确定是这里的问题。。。

根据其他地方的写法,这里可以改写成

// from useTreeData.tsx
columns.find((col) => col.colKey === 'row-select')

又或者

// from useRowSelect.tsx
columns.find(({ type }) => ['multiple', 'single'].includes(type))

顺便吐槽一下这两个地方的写法不一致~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants