Skip to content

fix: resolve mismatch between drag indices and update checkbox logic for groups issue 3975 #4008

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

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from

Conversation

PoorShawn
Copy link
Contributor

[中文版模板 / Chinese template]

🤔 This is a ...

  • New feature
  • Bug fix
  • TypeScript definition update
  • Bundle size optimization
  • Performance optimization
  • Enhancement feature
  • Refactoring
  • Update dependency
  • Code style optimization
  • Test Case
  • Branch merge
  • Site / documentation update
  • Demo update
  • Workflow
  • Chore
  • Release
  • Other (about what?)

🔗 Related issue link

relate #3975

💡 Background and solution

🐞问题一(Issue 1):“刻舟求剑”索引错误

在 checkbox.ts 中,source 和 target 的索引映射是通过 getRecordIndexByCell() 函数,根据 sourceIndex 和 targetIndex 的行号来获取的。

然而该函数内部依赖 _currentPagerIndexedData 进行索引查找,而这个数据已经是拖拽处理之后的结果。

与此同时,sourceIndex 和 targetIndex 依然代表的是拖拽处理前的行号。

因此,source 和 target 的索引映射会出现不一致,导致逻辑错误。

🛠️ 解决方法一

在数据源更新前,提前获取源记录和目标记录的索引信息。

在 endMoveCol 中,在调用 changeRecordOrder 之前,预先通过 getRecordIndexByCell() 获取并保存索引数据,确保索引准确无误。

🐞 问题二(Issue 2):组间/组内移动未保持 checkbox 状态

当整组(group)移动时,其内部的子项和子孙项未能正确保持其 checkbox 状态。

同样地,组内不同层级的移动,也会出现 checkbox 状态丢失或错乱的情况。

🛠️ 解决方法二

对于组级别的移动:使用 key.startsWith(${sourceIndex}) 来确保组内所有子项同步移动,并保持 checkbox 状态一致。

对于组内任意层级的移动:通过判断路径长度相等且共享相同的父路径,实现对同一层级的识别,并借助 parentPath 维持父级上下文,仅在同一父节点下完成移动。

对于包含嵌套子项的复杂移动:通过前缀匹配策略,使用如下正则精确定位和移动子项:

new RegExp(`^${parentPath},${i}([,]|$)`)

📝 Changelog

Language Changelog
🇺🇸 English Fixed incorrect index mapping caused by mismatch between pre-drag and post-drag data; Ensured checkbox states are preserved during group and nested item moves
zh Chinese 修复索引映射错误,避免因拖拽前后数据不一致导致的“刻舟求剑”问题; 支持组及其子项在拖拽移动时保持 checkbox 状态一致性

☑️ Self-Check before Merge

⚠️ Please check all items below before requesting a reviewing. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • TypeScript definition is updated/provided or not needed
  • Changelog is provided or not needed

🚀 Summary

copilot:summary

🔍 Walkthrough

copilot:walkthrough

@github-actions github-actions bot added the vtable label Jun 6, 2025
fix: update checkbox status in rowMov of tree ListTable
@Rui-Sun
Copy link
Contributor

Rui-Sun commented Jun 12, 2025

调整顺序的时候有报错,再看一下吧

20250612-153506.mp4

@PoorShawn
Copy link
Contributor Author

嗯嗯好滴,我再看看是哪里出问题了

@PoorShawn
Copy link
Contributor Author

@Rui-Sun 感谢你的测试!想问问可以提供测试的相关代码吗?方便我定位问题和错误

@PoorShawn
Copy link
Contributor Author

@Rui-Sun 原来是我忽略了对于 Pivot 透视表和转置表的处理,现在应该 OK 了!

@Rui-Sun
Copy link
Contributor

Rui-Sun commented Jun 20, 2025

#4033 (comment)

@PoorShawn
Copy link
Contributor Author

#4033 (comment)

@Rui-Sun 您好,我注意到这是一段 PivotTable 透视表的配置(没有复选框)。经过测试,在行移动的时候,没有发现什么问题

@github-actions github-actions bot added the docs label Jul 7, 2025
@Rui-Sun
Copy link
Contributor

Rui-Sun commented Jul 7, 2025

我又测试了一下,看起还是有问题,麻烦再看一下这个例子


  // your code here
  const dom = document.querySelector('#' + BUGSERVER_CONTAINER_ID);
  dom.style.width = '800px';
  dom.style.height = '400px';

    const option = { 
    container: dom,
    columns: [
      {
        field: 'p',
        // fieldKey: 'progress',
        fieldFormat(rec) {
          return `ii已完成${rec.progress}%`;
        },
        headerStyle: {
          textAlign: 'center',
          font: 'bold 12px sans-serif',
        },
        caption: 'progress',
        description: '这是一个标题的详细描述',
        width: 'calc(20% - 20px)',
      },
      {
        caption: 'Name',
        headerStyle: {
          textAlign: 'center',
          font: 'bold 13px sans-serif',
        },
        columns: [
          {
            field: 'fname',
            caption: 'First Name',
            width: '20%',
            minWidth: 150,
            headerStyle: {
              textAlign: 'center',
            },
          },
          {
            field: 'lname',
            caption: 'Last Name',
            width: '20%',
            minWidth: 150,
          },
        ],
      },
{
        caption: 'Name 1',
        headerStyle: {
          textAlign: 'center',
          font: 'bold 13px sans-serif',
        },
        columns: [
          {
            field: 'fname',
            caption: 'First Name 1',
            width: '20%',
            minWidth: 150,
            headerStyle: {
              textAlign: 'center',
            },
          },
          {
            field: 'lname',
            caption: 'Last Name 1',
            width: '20%',
            minWidth: 150,
          },
        ],
      },
      {
        field: 'email',
        caption: 'email',
        width: 200,
        headerStyle: {
          autoWrapText: true,
          textAlign: 'center',
        },
        style: {
          textOverflow: 'ellipsis',
          lineClamp: 2,
        },
        headerIcon: [
          {
            type: 'svg',
            svg: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 50 50"><path d="M 25 3 C 19.923765 3 15.799157 4.8329838 13.003906 8.0429688 C 11.376688 7.7090996 10.048176 6.6197602 9.4316406 5.1875 C 9.1136666 4.4502862 8.4137807 4.0506086 7.6972656 4.0136719 C 6.9807506 3.9767351 6.2463213 4.3028249 5.859375 5.0117188 C 5.3428601 5.9578802 5.0488281 7.0426881 5.0488281 8.1894531 C 5.0488281 11.130702 6.9742012 13.631632 9.6484375 14.583984 C 9.2235695 16.246808 9 18.058949 9 20 L 9 21.464844 C 6.447 23.270844 3.0507813 27.486062 3.0507812 32.789062 C 3.0507812 33.919063 3.5290469 34.886219 4.3730469 35.449219 C 5.0790469 35.921219 5.9515781 36.062891 6.7675781 35.837891 C 7.6155781 35.604891 8.3249375 35.007219 8.7109375 34.199219 C 9.1859375 33.205219 9.7939531 32.1635 10.376953 31.3125 C 11.112953 35.0875 12.211859 38.180938 12.755859 39.585938 C 11.349859 40.519937 9 42.532078 9 45.580078 L 9 46 C 9 46.553 9.447 47 10 47 L 20 47 C 20.553 47 21 46.553 21 46 L 21 39.339844 C 22.111 39.638844 23.72 40 25 40 C 26.28 40 27.889 39.638844 29 39.339844 L 29 46 C 29 46.553 29.447 47 30 47 L 40 47 C 40.553 47 41 46.553 41 46 L 41 45.580078 C 41 42.539078 38.661141 40.527891 37.244141 39.587891 C 37.788141 38.182891 38.887047 35.090453 39.623047 31.314453 C 40.206047 32.165453 40.814063 33.207172 41.289062 34.201172 C 41.676063 35.009172 42.385422 35.605844 43.232422 35.839844 C 44.050422 36.063844 44.921719 35.921312 45.636719 35.445312 C 46.471719 34.887313 46.949219 33.919063 46.949219 32.789062 C 46.950219 27.486063 43.553 23.271844 41 21.464844 L 41 20 C 41 18.070345 40.779378 16.268082 40.359375 14.613281 C 43.079425 13.684441 45.048828 11.160748 45.048828 8.1875 C 45.048828 7.040735 44.752843 5.955927 44.236328 5.0097656 C 43.849004 4.3011956 43.114786 3.9764337 42.398438 4.0136719 C 41.682088 4.05091 40.982037 4.4502862 40.664062 5.1875 C 40.037352 6.6433987 38.675813 7.7469237 37.011719 8.0605469 C 34.216277 4.8395401 30.085569 3 25 3 z M 7.6074219 5.9960938 C 8.3727736 7.7576119 9.871471 9.1193049 11.720703 9.7558594 C 11.148015 10.652801 10.659142 11.626854 10.261719 12.675781 C 8.3755339 11.982565 7.0488281 10.237119 7.0488281 8.1894531 C 7.0488281 7.3942059 7.2523534 6.6557012 7.6074219 5.9960938 z M 42.488281 5.9960938 C 42.843344 6.6556973 43.048828 7.3922592 43.048828 8.1875 C 43.048828 10.265432 41.685081 12.039408 39.753906 12.710938 C 39.358396 11.659862 38.869893 10.684253 38.298828 9.7851562 C 40.183822 9.1606408 41.712264 7.7821595 42.488281 5.9960938 z M 18 16 C 19.104 16 20 16.895 20 18 C 20 19.105 19.104 20 18 20 C 16.896 20 16 19.105 16 18 C 16 16.895 16.896 16 18 16 z M 32 16 C 33.104 16 34 16.895 34 18 C 34 19.105 33.104 20 32 20 C 30.896 20 30 19.105 30 18 C 30 16.895 30.896 16 32 16 z M 22.058594 22.001953 C 22.447141 22.02525 22.804156 22.277219 22.941406 22.667969 C 23.206406 23.414969 24.111 24 25 24 C 25.889 24 26.793594 23.414969 27.058594 22.667969 C 27.242594 22.146969 27.815031 21.874594 28.332031 22.058594 C 28.853031 22.241594 29.126406 22.812031 28.941406 23.332031 C 28.395406 24.878031 26.738 26 25 26 C 23.262 26 21.604594 24.878031 21.058594 23.332031 C 20.873594 22.811031 21.146969 22.241594 21.667969 22.058594 C 21.797469 22.012594 21.929078 21.994187 22.058594 22.001953 z"></path></svg>',
            width: 14,
            height: 14,
            name: 'iconKey',
            positionType: xTable.TYPES.IconPosition.contentLeft,
          },
          {
            type: 'svg', //指定svg格式图标,其他还支持path,image,font
            svg: `<svg t="1669210764476" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9160" width="200" height="200"><path d="M512.5 214c39.6 0 71.7-32.1 71.7-71.7s-32.1-71.7-71.7-71.7-71.7 32.1-71.7 71.7 32.1 71.7 71.7 71.7zM501.9 668.7v250.8c0 45.1-67.6 45.1-67.6 0V668.7h-89.6l95.9-332.6h-15.1l-56.5 190c-13.4 41.4-70.3 24.4-57.3-20l62.7-206.4c6.7-23.5 36.5-65.3 88-65.3H561c51.1 0 81 42.1 88.7 65.3l62.7 206.2c12.5 44.3-43.9 62.7-57.3 19.5l-56.4-189.3h-16.3l96.9 332.6h-90v251.2c0 44.8-67.3 44.6-67.3 0V668.7h-20.1z" p-id="9161"></path></svg>`,
            width: 22,
            height: 22,
            // funcType: xTable.TYPES.IconFuncTypeEnum.sort,//对应内部特定功能的图标,目前有sort pin expand等
            name: 'woman', //定义图标的名称,在内部会作为缓存的key值
            positionType: xTable.TYPES.IconPosition.contentRight, // 指定位置,可以在文本的前后,或者在绝对定位在单元格的左侧右侧
            marginLeft: 0, // 左侧内容间隔 在特定位置position中起作用
            marginRight: 0, // 右侧内容间隔 在特定位置position中起作用
            visibleTime: 'always', // 显示时机, 'always' | 'mouseover_cell' | 'click_cell'
            hover: {
              // 热区大小
              width: 40,
              height: 40,
              bgColor: 'rgba(144,144,144,0.2)',
            },
            tooltip: {
              // 气泡框,按钮的的解释信息
              title: '女生',
            },
          },
        ],
        dropDownMenu: ['升序排序b', '降序排序b', '冻结列b'],
      },
      {
        field: 'birthday',
        fieldFormat: {
          get(rec) {
            const d = rec.birthday;
            return isNaN(d)
              ? d
              : `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`;
          },
          set(rec, val) {
            const date = new Date(val);
            rec.birthday = isNaN(parseInt(date.toString(), 10)) ? val : date;
          },
        },
        caption: 'Birthday',
        width: 150,
      },
    ],
    records: [
      {
        personid: 1,
        fname: 'Aria',
        lname: 'Jenkins',
        birthday: '1999-03-12T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 5,
        progress: 20,
      },
      {
        personid: 2,
        fname: 'Isaac',
        lname: 'Evans',
        birthday: '1990-03-22T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 4,
        progress: 13,
      },
      {
        personid: 3,
        fname: 'Gabriella',
        lname: 'Hall',
        birthday: '1990-12-17T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 2,
        progress: 39,
      },
      {
        personid: 4,
        fname: 'Harper',
        lname: 'Walker',
        birthday: '2000-03-30T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 4,
        progress: 87,
      },
      {
        personid: 5,
        fname: 'Jackson',
        lname: 'Barnes',
        birthday: '1994-11-14T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 3,
        progress: 34,
      },
      {
        personid: 6,
        fname: 'Audrey',
        lname: 'Kelly',
        birthday: '1997-01-19T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 3,
        progress: 97,
      },
      {
        personid: 7,
        fname: 'Christian',
        lname: 'Gomez',
        birthday: '1990-10-26T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 2,
        progress: 34,
      },
      {
        personid: 8,
        fname: 'Joshua',
        lname: 'Cook',
        birthday: '1998-05-22T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 4,
        progress: 50,
      },
      {
        personid: 9,
        fname: 'Mason',
        lname: 'Sanders',
        birthday: '2001-10-09T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 5,
        progress: 100,
      },
      {
        personid: 10,
        fname: 'Evelyn',
        lname: 'Price',
        birthday: '1998-09-11T16:00:00.000Z',
        longtext: '',
        email: '[email protected]',
        stars: 3,
        progress: 79,
      },
    ],
    dragHeaderMode: 'column',
transpose:true,
widthMode:'autoWidth',
    rowSeriesNumber: {
      enable: true,
      title: '行号',
      field: 'name',
      dragOrder: true,
      // format: (args: any) => {
      //   return args.value;
      // },
      style: {
        color: 'red'
      }
    }
  };

  const instance = new VTable.ListTable(option);
  

@PoorShawn
Copy link
Contributor Author

为我的疏忽感到抱歉,我将再仔细地检查和测试。非常感谢你耐心的测试和沟通!

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

Successfully merging this pull request may close these issues.

2 participants