vxe-table 4.13.4 → 4.13.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/es/grid/src/grid.js +1 -1
  2. package/es/index.css +1 -1
  3. package/es/index.min.css +1 -1
  4. package/es/locale/lang/ar-EG.js +3 -2
  5. package/es/locale/lang/de-DE.js +3 -2
  6. package/es/locale/lang/en-US.js +2 -1
  7. package/es/locale/lang/es-ES.js +3 -2
  8. package/es/locale/lang/fr-FR.js +2 -1
  9. package/es/locale/lang/hu-HU.js +2 -1
  10. package/es/locale/lang/hy-AM.js +2 -1
  11. package/es/locale/lang/id-ID.js +2 -1
  12. package/es/locale/lang/it-IT.js +2 -1
  13. package/es/locale/lang/ja-JP.js +2 -1
  14. package/es/locale/lang/ko-KR.js +2 -1
  15. package/es/locale/lang/nb-NO.js +2 -1
  16. package/es/locale/lang/pt-BR.js +2 -1
  17. package/es/locale/lang/ru-RU.js +2 -1
  18. package/es/locale/lang/th-TH.js +2 -1
  19. package/es/locale/lang/ug-CN.js +2 -1
  20. package/es/locale/lang/uk-UA.js +2 -1
  21. package/es/locale/lang/vi-VN.js +2 -1
  22. package/es/locale/lang/zh-CHT.js +2 -1
  23. package/es/locale/lang/zh-CN.js +2 -1
  24. package/es/style.css +1 -1
  25. package/es/style.min.css +1 -1
  26. package/es/table/module/custom/hook.js +11 -8
  27. package/es/table/module/custom/panel.js +7 -7
  28. package/es/table/module/export/hook.js +21 -20
  29. package/es/table/module/keyboard/hook.js +3 -2
  30. package/es/table/src/body.js +45 -10
  31. package/es/table/src/cell.js +159 -69
  32. package/es/table/src/column.js +2 -0
  33. package/es/table/src/columnInfo.js +1 -0
  34. package/es/table/src/emits.js +1 -0
  35. package/es/table/src/props.js +9 -7
  36. package/es/table/src/table.js +656 -173
  37. package/es/table/style.css +71 -41
  38. package/es/table/style.min.css +1 -1
  39. package/es/ui/index.js +13 -1
  40. package/es/ui/src/dom.js +3 -0
  41. package/es/ui/src/log.js +1 -1
  42. package/es/vxe-table/style.css +71 -41
  43. package/es/vxe-table/style.min.css +1 -1
  44. package/lib/grid/src/grid.js +1 -1
  45. package/lib/grid/src/grid.min.js +1 -1
  46. package/lib/index.css +1 -1
  47. package/lib/index.min.css +1 -1
  48. package/lib/index.umd.js +421 -180
  49. package/lib/index.umd.min.js +1 -1
  50. package/lib/locale/lang/ar-EG.js +3 -2
  51. package/lib/locale/lang/ar-EG.min.js +1 -1
  52. package/lib/locale/lang/de-DE.js +3 -2
  53. package/lib/locale/lang/de-DE.min.js +1 -1
  54. package/lib/locale/lang/en-US.js +2 -1
  55. package/lib/locale/lang/en-US.min.js +1 -1
  56. package/lib/locale/lang/en-US.umd.js +2 -1
  57. package/lib/locale/lang/es-ES.js +3 -2
  58. package/lib/locale/lang/es-ES.min.js +1 -1
  59. package/lib/locale/lang/es-ES.umd.js +3 -2
  60. package/lib/locale/lang/fr-FR.js +2 -1
  61. package/lib/locale/lang/fr-FR.min.js +1 -1
  62. package/lib/locale/lang/hu-HU.js +2 -1
  63. package/lib/locale/lang/hu-HU.min.js +1 -1
  64. package/lib/locale/lang/hu-HU.umd.js +2 -1
  65. package/lib/locale/lang/hy-AM.js +2 -1
  66. package/lib/locale/lang/hy-AM.min.js +1 -1
  67. package/lib/locale/lang/id-ID.js +2 -1
  68. package/lib/locale/lang/id-ID.min.js +1 -1
  69. package/lib/locale/lang/it-IT.js +2 -1
  70. package/lib/locale/lang/it-IT.min.js +1 -1
  71. package/lib/locale/lang/ja-JP.js +2 -1
  72. package/lib/locale/lang/ja-JP.min.js +1 -1
  73. package/lib/locale/lang/ja-JP.umd.js +2 -1
  74. package/lib/locale/lang/ko-KR.js +2 -1
  75. package/lib/locale/lang/ko-KR.min.js +1 -1
  76. package/lib/locale/lang/ko-KR.umd.js +2 -1
  77. package/lib/locale/lang/nb-NO.js +2 -1
  78. package/lib/locale/lang/nb-NO.min.js +1 -1
  79. package/lib/locale/lang/pt-BR.js +2 -1
  80. package/lib/locale/lang/pt-BR.min.js +1 -1
  81. package/lib/locale/lang/pt-BR.umd.js +2 -1
  82. package/lib/locale/lang/ru-RU.js +2 -1
  83. package/lib/locale/lang/ru-RU.min.js +1 -1
  84. package/lib/locale/lang/ru-RU.umd.js +2 -1
  85. package/lib/locale/lang/th-TH.js +2 -1
  86. package/lib/locale/lang/th-TH.min.js +1 -1
  87. package/lib/locale/lang/ug-CN.js +2 -1
  88. package/lib/locale/lang/ug-CN.min.js +1 -1
  89. package/lib/locale/lang/uk-UA.js +2 -1
  90. package/lib/locale/lang/uk-UA.min.js +1 -1
  91. package/lib/locale/lang/uk-UA.umd.js +2 -1
  92. package/lib/locale/lang/vi-VN.js +2 -1
  93. package/lib/locale/lang/vi-VN.min.js +1 -1
  94. package/lib/locale/lang/zh-CHT.js +2 -1
  95. package/lib/locale/lang/zh-CHT.min.js +1 -1
  96. package/lib/locale/lang/zh-CN.js +2 -1
  97. package/lib/locale/lang/zh-CN.min.js +1 -1
  98. package/lib/locale/lang/zh-CN.umd.js +2 -1
  99. package/lib/style.css +1 -1
  100. package/lib/style.min.css +1 -1
  101. package/lib/table/module/custom/hook.js +11 -1
  102. package/lib/table/module/custom/hook.min.js +1 -1
  103. package/lib/table/module/custom/panel.js +6 -2
  104. package/lib/table/module/custom/panel.min.js +1 -1
  105. package/lib/table/module/export/hook.js +21 -11
  106. package/lib/table/module/export/hook.min.js +1 -1
  107. package/lib/table/module/keyboard/hook.js +2 -1
  108. package/lib/table/module/keyboard/hook.min.js +1 -1
  109. package/lib/table/src/body.js +35 -9
  110. package/lib/table/src/body.min.js +1 -1
  111. package/lib/table/src/cell.js +177 -52
  112. package/lib/table/src/cell.min.js +1 -1
  113. package/lib/table/src/column.js +2 -0
  114. package/lib/table/src/column.min.js +1 -1
  115. package/lib/table/src/columnInfo.js +1 -0
  116. package/lib/table/src/columnInfo.min.js +1 -1
  117. package/lib/table/src/emits.js +1 -1
  118. package/lib/table/src/emits.min.js +1 -1
  119. package/lib/table/src/props.js +9 -7
  120. package/lib/table/src/props.min.js +1 -1
  121. package/lib/table/src/table.js +136 -92
  122. package/lib/table/src/table.min.js +1 -1
  123. package/lib/table/style/style.css +71 -41
  124. package/lib/table/style/style.min.css +1 -1
  125. package/lib/ui/index.js +13 -1
  126. package/lib/ui/index.min.js +1 -1
  127. package/lib/ui/src/dom.js +4 -0
  128. package/lib/ui/src/dom.min.js +1 -1
  129. package/lib/ui/src/log.js +1 -1
  130. package/lib/ui/src/log.min.js +1 -1
  131. package/lib/vxe-table/style/style.css +71 -41
  132. package/lib/vxe-table/style/style.min.css +1 -1
  133. package/package.json +2 -2
  134. package/packages/grid/src/grid.ts +1 -1
  135. package/packages/locale/lang/ar-EG.ts +3 -2
  136. package/packages/locale/lang/de-DE.ts +3 -2
  137. package/packages/locale/lang/en-US.ts +2 -1
  138. package/packages/locale/lang/es-ES.ts +3 -2
  139. package/packages/locale/lang/fr-FR.ts +2 -1
  140. package/packages/locale/lang/hu-HU.ts +2 -1
  141. package/packages/locale/lang/hy-AM.ts +2 -1
  142. package/packages/locale/lang/id-ID.ts +2 -1
  143. package/packages/locale/lang/it-IT.ts +2 -1
  144. package/packages/locale/lang/ja-JP.ts +2 -1
  145. package/packages/locale/lang/ko-KR.ts +2 -1
  146. package/packages/locale/lang/nb-NO.ts +2 -1
  147. package/packages/locale/lang/pt-BR.ts +2 -1
  148. package/packages/locale/lang/ru-RU.ts +2 -1
  149. package/packages/locale/lang/th-TH.ts +2 -1
  150. package/packages/locale/lang/ug-CN.ts +2 -1
  151. package/packages/locale/lang/uk-UA.ts +2 -1
  152. package/packages/locale/lang/vi-VN.ts +2 -1
  153. package/packages/locale/lang/zh-CHT.ts +2 -1
  154. package/packages/locale/lang/zh-CN.ts +2 -1
  155. package/packages/table/module/custom/hook.ts +14 -8
  156. package/packages/table/module/custom/panel.ts +7 -7
  157. package/packages/table/module/export/hook.ts +28 -27
  158. package/packages/table/module/keyboard/hook.ts +3 -2
  159. package/packages/table/src/body.ts +46 -10
  160. package/packages/table/src/cell.ts +162 -73
  161. package/packages/table/src/column.ts +2 -0
  162. package/packages/table/src/columnInfo.ts +1 -0
  163. package/packages/table/src/emits.ts +1 -0
  164. package/packages/table/src/props.ts +9 -7
  165. package/packages/table/src/table.ts +661 -178
  166. package/packages/ui/index.ts +12 -0
  167. package/packages/ui/src/dom.ts +4 -0
  168. package/styles/components/table.scss +133 -93
  169. /package/es/{iconfont.1744768289920.ttf → iconfont.1745197925862.ttf} +0 -0
  170. /package/es/{iconfont.1744768289920.woff → iconfont.1745197925862.woff} +0 -0
  171. /package/es/{iconfont.1744768289920.woff2 → iconfont.1745197925862.woff2} +0 -0
  172. /package/lib/{iconfont.1744768289920.ttf → iconfont.1745197925862.ttf} +0 -0
  173. /package/lib/{iconfont.1744768289920.woff → iconfont.1745197925862.woff} +0 -0
  174. /package/lib/{iconfont.1744768289920.woff2 → iconfont.1745197925862.woff2} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, h, reactive, ref, provide, inject, nextTick, onActivated, onDeactivated, onBeforeUnmount, onUnmounted, watch, computed, onMounted } from 'vue';
2
2
  import XEUtils from 'xe-utils';
3
- import { initTpImg, getTpImg, isPx, isScale, hasClass, addClass, removeClass, getEventTargetNode, getPaddingTopBottomSize, getOffsetPos, setScrollTop, setScrollLeft, toCssUnit } from '../../ui/src/dom';
3
+ import { initTpImg, getTpImg, isPx, isScale, hasClass, addClass, removeClass, getEventTargetNode, getPaddingTopBottomSize, getOffsetPos, setScrollTop, setScrollLeft, toCssUnit, hasControlKey } from '../../ui/src/dom';
4
4
  import { getLastZIndex, nextZIndex, hasChildrenList, getFuncText, isEnableConf, formatText, eqEmptyValue } from '../../ui/src/utils';
5
5
  import { VxeUI } from '../../ui';
6
6
  import Cell from './cell';
@@ -77,6 +77,8 @@ export default defineComponent({
77
77
  selectRadioRow: null,
78
78
  // 表尾合计数据
79
79
  footerTableData: [],
80
+ // 行分组列信息
81
+ rowGroupColumn: null,
80
82
  // 展开列信息
81
83
  expandColumn: null,
82
84
  // 树节点列信息
@@ -228,6 +230,10 @@ export default defineComponent({
228
230
  isTitle: false,
229
231
  isFooter: false
230
232
  },
233
+ visiblwRowsFlag: 1,
234
+ isRowGroupStatus: false,
235
+ rowGroupList: [],
236
+ rowGroupExpandedFlag: 1,
231
237
  rowExpandedFlag: 1,
232
238
  treeExpandedFlag: 1,
233
239
  updateCheckboxFlag: 1,
@@ -317,10 +323,13 @@ export default defineComponent({
317
323
  tableFullData: [],
318
324
  afterFullData: [],
319
325
  afterTreeFullData: [],
326
+ afterGroupFullData: [],
320
327
  // 列表条件处理后数据集合
321
328
  afterFullRowMaps: {},
322
329
  // 树结构完整数据、条件处理后
323
330
  tableFullTreeData: [],
331
+ // 行分组全量数据、条件处理后
332
+ tableFullGroupData: [],
324
333
  tableSynchData: [],
325
334
  tableSourceData: [],
326
335
  // 收集的列配置(带分组)
@@ -353,6 +362,8 @@ export default defineComponent({
353
362
  rowExpandedMaps: {},
354
363
  // 懒加载中的展开行的集合
355
364
  rowExpandLazyLoadedMaps: {},
365
+ // 已展开的分组行
366
+ rowGroupExpandedMaps: {},
356
367
  // 已展开树节点集合
357
368
  treeExpandedMaps: {},
358
369
  // 懒加载中的树节点的集合
@@ -512,6 +523,9 @@ export default defineComponent({
512
523
  const computeRowOpts = computed(() => {
513
524
  return Object.assign({}, getConfig().table.rowConfig, props.rowConfig);
514
525
  });
526
+ const computeRowGroupOpts = computed(() => {
527
+ return Object.assign({}, getConfig().table.rowGroupConfig, props.rowGroupConfig);
528
+ });
515
529
  const computeCurrentRowOpts = computed(() => {
516
530
  return Object.assign({}, getConfig().table.currentRowConfig, props.currentRowConfig);
517
531
  });
@@ -656,20 +670,22 @@ export default defineComponent({
656
670
  });
657
671
  const computeTableRowExpandedList = computed(() => {
658
672
  const { treeConfig } = props;
659
- const { rowExpandedFlag, expandColumn } = reactData;
673
+ const { rowExpandedFlag, expandColumn, rowGroupExpandedFlag, treeExpandedFlag, isRowGroupStatus } = reactData;
660
674
  const { visibleDataRowIdData, rowExpandedMaps } = internalData;
661
675
  const treeOpts = computeTreeOpts.value;
662
676
  const { transform } = treeOpts;
663
677
  const expandList = [];
664
- if (expandColumn && rowExpandedFlag) {
665
- if (treeConfig && !transform) {
678
+ if (expandColumn && rowExpandedFlag && rowGroupExpandedFlag && treeExpandedFlag) {
679
+ if (isRowGroupStatus || (treeConfig && transform)) {
680
+ XEUtils.each(rowExpandedMaps, (row, rowid) => {
681
+ if (visibleDataRowIdData[rowid]) {
682
+ expandList.push(row);
683
+ }
684
+ });
685
+ }
686
+ else {
666
687
  return XEUtils.values(rowExpandedMaps);
667
688
  }
668
- XEUtils.each(rowExpandedMaps, (row, rowid) => {
669
- if (visibleDataRowIdData[rowid]) {
670
- expandList.push(row);
671
- }
672
- });
673
689
  }
674
690
  return expandList;
675
691
  });
@@ -724,7 +740,7 @@ export default defineComponent({
724
740
  // 暂时不支持树形结构
725
741
  }
726
742
  // 如果所有行都被禁用
727
- return tableFullData.every((row) => !checkMethod({ row }));
743
+ return tableFullData.every((row) => !checkMethod({ $table: $xeTable, row }));
728
744
  }
729
745
  return false;
730
746
  }
@@ -739,6 +755,10 @@ export default defineComponent({
739
755
  y: overflowY && scrollYLoad
740
756
  };
741
757
  });
758
+ const computeRowGroupFields = computed(() => {
759
+ const rowGroupOpts = computeRowGroupOpts.value;
760
+ return rowGroupOpts.groupFields;
761
+ });
742
762
  const refMaps = {
743
763
  refElem,
744
764
  refTooltip,
@@ -785,6 +805,7 @@ export default defineComponent({
785
805
  computeHeaderCellOpts,
786
806
  computeFooterCellOpts,
787
807
  computeRowOpts,
808
+ computeRowGroupOpts,
788
809
  computeCurrentRowOpts,
789
810
  computeRowDragOpts,
790
811
  computeColumnDragOpts,
@@ -1282,7 +1303,7 @@ export default defineComponent({
1282
1303
  }
1283
1304
  const storeData = getCustomStorageMap(tableId);
1284
1305
  if (restoreStore) {
1285
- return Promise.resolve(restoreStore({ id: tableId, type: 'restore', storeData })).then(storeData => {
1306
+ return Promise.resolve(restoreStore({ $table: $xeTable, id: tableId, type: 'restore', storeData })).then(storeData => {
1286
1307
  if (!storeData) {
1287
1308
  return;
1288
1309
  }
@@ -1313,6 +1334,7 @@ export default defineComponent({
1313
1334
  const rowOpts = computeRowOpts.value;
1314
1335
  const isGroup = collectColumn.some(hasChildrenList);
1315
1336
  let isAllOverflow = !!props.showOverflow;
1337
+ let rowGroupColumn;
1316
1338
  let expandColumn;
1317
1339
  let treeNodeColumn;
1318
1340
  let checkboxColumn;
@@ -1320,7 +1342,7 @@ export default defineComponent({
1320
1342
  let htmlColumn;
1321
1343
  let hasFixed;
1322
1344
  const handleFunc = (column, index, items, path, parentColumn) => {
1323
- const { id: colid, field, fixed, type, treeNode } = column;
1345
+ const { id: colid, field, fixed, type, treeNode, rowGroupNode } = column;
1324
1346
  const rest = { $index: -1, _index: -1, column, colid, index, items, parent: parentColumn || null, width: 0, oLeft: 0 };
1325
1347
  if (field) {
1326
1348
  if (fullColumnFieldData[field]) {
@@ -1347,7 +1369,15 @@ export default defineComponent({
1347
1369
  treeNodeColumn = column;
1348
1370
  }
1349
1371
  }
1350
- else if (type === 'expand') {
1372
+ if (rowGroupNode) {
1373
+ if (treeNodeColumn) {
1374
+ warnLog('vxe.error.colRepet', ['row-group-node', rowGroupNode]);
1375
+ }
1376
+ if (!rowGroupColumn) {
1377
+ rowGroupColumn = column;
1378
+ }
1379
+ }
1380
+ if (type === 'expand') {
1351
1381
  if (expandColumn) {
1352
1382
  warnLog('vxe.error.colRepet', ['type', type]);
1353
1383
  }
@@ -1403,6 +1433,7 @@ export default defineComponent({
1403
1433
  }
1404
1434
  }
1405
1435
  reactData.isGroup = isGroup;
1436
+ reactData.rowGroupColumn = rowGroupColumn;
1406
1437
  reactData.treeNodeColumn = treeNodeColumn;
1407
1438
  reactData.expandColumn = expandColumn;
1408
1439
  reactData.isAllOverflow = isAllOverflow;
@@ -1673,18 +1704,20 @@ export default defineComponent({
1673
1704
  }
1674
1705
  };
1675
1706
  /**
1676
- * 如果为虚拟树,将树结构拍平
1707
+ * 如果为虚拟树、行分组、则将树结构拍平
1677
1708
  * @returns
1678
1709
  */
1679
1710
  const handleVirtualTreeToList = () => {
1680
1711
  const { treeConfig } = props;
1681
- const { fullAllDataRowIdData, treeExpandedMaps } = internalData;
1712
+ const { isRowGroupStatus } = reactData;
1713
+ const { fullAllDataRowIdData, treeExpandedMaps, rowGroupExpandedMaps } = internalData;
1714
+ const rowGroupOpts = computeRowGroupOpts.value;
1682
1715
  const treeOpts = computeTreeOpts.value;
1683
- const childrenField = treeOpts.children || treeOpts.childrenField;
1716
+ const { handleGetRowId } = createHandleGetRowId($xeTable);
1717
+ const fullData = [];
1718
+ const expandMaps = {};
1684
1719
  if (treeConfig && treeOpts.transform) {
1685
- const { handleGetRowId } = createHandleGetRowId($xeTable);
1686
- const fullData = [];
1687
- const expandMaps = {};
1720
+ const childrenField = treeOpts.children || treeOpts.childrenField;
1688
1721
  XEUtils.eachTree(internalData.afterTreeFullData, (row, index, items, path, parentRow) => {
1689
1722
  const rowid = handleGetRowId(row);
1690
1723
  const parentRowid = handleGetRowId(parentRow);
@@ -1701,17 +1734,37 @@ export default defineComponent({
1701
1734
  updateScrollYStatus(fullData);
1702
1735
  return fullData;
1703
1736
  }
1737
+ else if (isRowGroupStatus) {
1738
+ const { childrenField } = rowGroupOpts;
1739
+ XEUtils.eachTree(internalData.afterGroupFullData, (row, index, items, path, parentRow) => {
1740
+ const rowid = handleGetRowId(row);
1741
+ const parentRowid = handleGetRowId(parentRow);
1742
+ if (!parentRow || (expandMaps[parentRowid] && rowGroupExpandedMaps[parentRowid])) {
1743
+ const rowRest = fullAllDataRowIdData[rowid];
1744
+ if (rowRest) {
1745
+ rowRest._index = fullData.length;
1746
+ }
1747
+ expandMaps[rowid] = 1;
1748
+ fullData.push(row);
1749
+ }
1750
+ }, { children: childrenField });
1751
+ internalData.afterFullData = fullData;
1752
+ updateScrollYStatus(fullData);
1753
+ return fullData;
1754
+ }
1704
1755
  return internalData.afterFullData;
1705
1756
  };
1706
1757
  /**
1707
- * 获取处理后全量的表格数据
1758
+ * 编译处理后全量的表格数据
1708
1759
  * 如果存在筛选条件,继续处理
1709
1760
  */
1710
1761
  const updateAfterFullData = () => {
1711
1762
  const { treeConfig } = props;
1712
- const { tableFullColumn, tableFullData, tableFullTreeData } = internalData;
1763
+ const { isRowGroupStatus } = reactData;
1764
+ const { tableFullColumn, tableFullData, tableFullTreeData, tableFullGroupData } = internalData;
1713
1765
  const filterOpts = computeFilterOpts.value;
1714
1766
  const sortOpts = computeSortOpts.value;
1767
+ const rowGroupOpts = computeRowGroupOpts.value;
1715
1768
  const treeOpts = computeTreeOpts.value;
1716
1769
  const childrenField = treeOpts.children || treeOpts.childrenField;
1717
1770
  const { transform, rowField, parentField, mapChildrenField } = treeOpts;
@@ -1762,7 +1815,7 @@ export default defineComponent({
1762
1815
  return itemList.some((item) => compFilterMethod({ value: item.value, option: item, cellValue, row, column, $table: $xeTable }));
1763
1816
  }
1764
1817
  else if (allFilterMethod) {
1765
- return allFilterMethod({ options: itemList, values: valueList, cellValue, row, column });
1818
+ return allFilterMethod({ $table: $xeTable, options: itemList, values: valueList, cellValue, row, column });
1766
1819
  }
1767
1820
  else if (tdFilterMethod) {
1768
1821
  return itemList.some((item) => tdFilterMethod({ value: item.value, option: item, cellValue, row, column, $table: $xeTable }));
@@ -1770,7 +1823,17 @@ export default defineComponent({
1770
1823
  return valueList.indexOf(XEUtils.get(row, column.field)) > -1;
1771
1824
  });
1772
1825
  };
1773
- if (treeConfig && transform) {
1826
+ if (isRowGroupStatus) {
1827
+ // 行分组
1828
+ tableTree = XEUtils.searchTree(tableFullGroupData, handleFilter, {
1829
+ original: true,
1830
+ isEvery: true,
1831
+ children: rowGroupOpts.mapChildrenField,
1832
+ mapChildren: rowGroupOpts.childrenField
1833
+ });
1834
+ tableData = tableTree;
1835
+ }
1836
+ else if (treeConfig && transform) {
1774
1837
  // 筛选虚拟树
1775
1838
  tableTree = XEUtils.searchTree(tableFullTreeData, handleFilter, {
1776
1839
  original: true,
@@ -1786,7 +1849,17 @@ export default defineComponent({
1786
1849
  }
1787
1850
  }
1788
1851
  else {
1789
- if (treeConfig && transform) {
1852
+ if (isRowGroupStatus) {
1853
+ // 还原行分组
1854
+ tableTree = XEUtils.searchTree(tableFullGroupData, () => true, {
1855
+ original: true,
1856
+ isEvery: true,
1857
+ children: rowGroupOpts.mapChildrenField,
1858
+ mapChildren: rowGroupOpts.childrenField
1859
+ });
1860
+ tableData = tableTree;
1861
+ }
1862
+ else if (treeConfig && transform) {
1790
1863
  // 还原虚拟树
1791
1864
  tableTree = XEUtils.searchTree(tableFullTreeData, () => true, {
1792
1865
  original: true,
@@ -1801,11 +1874,32 @@ export default defineComponent({
1801
1874
  tableTree = tableData;
1802
1875
  }
1803
1876
  }
1804
- // 处理排序(不能用于树形结构)
1877
+ // 处理排序
1805
1878
  // 支持单列、多列、组合排序
1806
1879
  if (!allRemoteSort && orderColumns.length) {
1807
- if (treeConfig && transform) {
1808
- // 虚拟树和列表一样,只能排序根级节点
1880
+ if (isRowGroupStatus) {
1881
+ // 行分组的排序
1882
+ if (allSortMethod) {
1883
+ const sortRests = allSortMethod({ data: tableTree, sortList: orderColumns, $table: $xeTable });
1884
+ tableTree = XEUtils.isArray(sortRests) ? sortRests : tableTree;
1885
+ }
1886
+ else {
1887
+ const treeList = XEUtils.toTreeArray(tableTree, {
1888
+ key: rowGroupOpts.rowField,
1889
+ parentKey: rowGroupOpts.parentField,
1890
+ children: rowGroupOpts.mapChildrenField
1891
+ });
1892
+ tableTree = XEUtils.toArrayTree(XEUtils.orderBy(treeList, orderColumns.map(({ column, order }) => [getOrderField(column), order])), {
1893
+ key: rowGroupOpts.rowField,
1894
+ parentKey: rowGroupOpts.parentField,
1895
+ children: rowGroupOpts.childrenField,
1896
+ mapChildren: rowGroupOpts.mapChildrenField
1897
+ });
1898
+ }
1899
+ tableData = tableTree;
1900
+ }
1901
+ else if (treeConfig && transform) {
1902
+ // 虚拟树的排序
1809
1903
  if (allSortMethod) {
1810
1904
  const sortRests = allSortMethod({ data: tableTree, sortList: orderColumns, $table: $xeTable });
1811
1905
  tableTree = XEUtils.isArray(sortRests) ? sortRests : tableTree;
@@ -1836,12 +1930,23 @@ export default defineComponent({
1836
1930
  }
1837
1931
  }
1838
1932
  else {
1839
- if (treeConfig && transform) {
1933
+ if (isRowGroupStatus) {
1934
+ // 还原行分组
1935
+ // 还原虚拟树
1936
+ tableTree = XEUtils.searchTree(tableFullGroupData, () => true, {
1937
+ original: true,
1938
+ isEvery: true,
1939
+ children: rowGroupOpts.mapChildrenField,
1940
+ mapChildren: rowGroupOpts.childrenField
1941
+ });
1942
+ tableData = tableTree;
1943
+ }
1944
+ else if (treeConfig && transform) {
1840
1945
  // 还原虚拟树
1841
1946
  tableTree = XEUtils.searchTree(tableFullTreeData, () => true, {
1842
1947
  original: true,
1843
1948
  isEvery,
1844
- children: treeOpts.mapChildrenField,
1949
+ children: mapChildrenField,
1845
1950
  mapChildren: childrenField
1846
1951
  });
1847
1952
  tableData = tableTree;
@@ -1853,6 +1958,7 @@ export default defineComponent({
1853
1958
  }
1854
1959
  internalData.afterFullData = tableData;
1855
1960
  internalData.afterTreeFullData = tableTree;
1961
+ internalData.afterGroupFullData = tableTree;
1856
1962
  updateAfterDataIndex();
1857
1963
  };
1858
1964
  const updateStyle = () => {
@@ -2252,7 +2358,7 @@ export default defineComponent({
2252
2358
  const handleCheckedRadioRow = (row, isForce) => {
2253
2359
  const radioOpts = computeRadioOpts.value;
2254
2360
  const { checkMethod } = radioOpts;
2255
- if (row && (isForce || (!checkMethod || checkMethod({ row })))) {
2361
+ if (row && (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row })))) {
2256
2362
  reactData.selectRadioRow = row;
2257
2363
  handleRadioReserveRow(row);
2258
2364
  }
@@ -2268,8 +2374,10 @@ export default defineComponent({
2268
2374
  };
2269
2375
  const handleCheckedAllCheckboxRow = (checked, isForce) => {
2270
2376
  const { treeConfig } = props;
2271
- const { afterFullData, checkboxReserveRowMap, selectCheckboxMaps } = internalData;
2377
+ const { isRowGroupStatus } = reactData;
2378
+ const { afterFullData, afterTreeFullData, afterGroupFullData, checkboxReserveRowMap, selectCheckboxMaps } = internalData;
2272
2379
  const treeOpts = computeTreeOpts.value;
2380
+ const rowGroupOpts = computeRowGroupOpts.value;
2273
2381
  const childrenField = treeOpts.children || treeOpts.childrenField;
2274
2382
  const checkboxOpts = computeCheckboxOpts.value;
2275
2383
  const { checkField, reserve, checkMethod } = checkboxOpts;
@@ -2278,24 +2386,24 @@ export default defineComponent({
2278
2386
  const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField;
2279
2387
  const selectRowMaps = {};
2280
2388
  /**
2281
- * 绑定属性方式(高性能,有污染)
2389
+ * 绑定属性方式(有污染)
2282
2390
  * 必须在行数据存在对应的属性,否则将不响应
2283
2391
  */
2284
2392
  if (checkField) {
2285
2393
  const checkValFn = (row) => {
2286
- if (isForce || (!checkMethod || checkMethod({ row }))) {
2394
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
2287
2395
  if (checked) {
2288
2396
  selectRowMaps[handleGetRowId(row)] = row;
2289
2397
  }
2290
2398
  XEUtils.set(row, checkField, checked);
2291
2399
  }
2292
- if (treeConfig && indeterminateField) {
2400
+ if ((treeConfig || isRowGroupStatus) && indeterminateField) {
2293
2401
  XEUtils.set(row, indeterminateField, false);
2294
2402
  }
2295
2403
  };
2296
2404
  // 如果存在选中方法
2297
2405
  // 如果方法成立,则更新值,否则忽略该数据
2298
- if (treeConfig) {
2406
+ if ((treeConfig || isRowGroupStatus)) {
2299
2407
  XEUtils.eachTree(afterFullData, checkValFn, { children: childrenField });
2300
2408
  }
2301
2409
  else {
@@ -2304,17 +2412,45 @@ export default defineComponent({
2304
2412
  }
2305
2413
  else {
2306
2414
  /**
2307
- * 默认方式(低性能,无污染)
2308
- * 无需任何属性,直接绑定
2309
- */
2310
- if (treeConfig) {
2415
+ * 默认方式(无污染)
2416
+ * 无需任何属性,直接绑定
2417
+ */
2418
+ if (isRowGroupStatus) {
2311
2419
  if (checked) {
2312
2420
  /**
2313
- * 如果是树勾选
2314
- * 如果方法成立,则添加到临时集合中
2315
- */
2316
- XEUtils.eachTree(afterFullData, (row) => {
2317
- if (isForce || (!checkMethod || checkMethod({ row }))) {
2421
+ * 如果是行分组勾选
2422
+ * 如果方法成立,则添加到临时集合中
2423
+ */
2424
+ XEUtils.eachTree(afterGroupFullData, (row) => {
2425
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
2426
+ const rowid = handleGetRowId(row);
2427
+ selectRowMaps[rowid] = row;
2428
+ }
2429
+ }, { children: rowGroupOpts.mapChildrenField });
2430
+ }
2431
+ else {
2432
+ /**
2433
+ * 如果是树取消
2434
+ * 如果方法成立,则不添加到临时集合中
2435
+ */
2436
+ if (!isForce && checkMethod) {
2437
+ XEUtils.eachTree(afterGroupFullData, (row) => {
2438
+ const rowid = handleGetRowId(row);
2439
+ if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
2440
+ selectRowMaps[rowid] = row;
2441
+ }
2442
+ }, { children: rowGroupOpts.mapChildrenField });
2443
+ }
2444
+ }
2445
+ }
2446
+ else if (treeConfig) {
2447
+ if (checked) {
2448
+ /**
2449
+ * 如果是树勾选
2450
+ * 如果方法成立,则添加到临时集合中
2451
+ */
2452
+ XEUtils.eachTree(afterTreeFullData, (row) => {
2453
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
2318
2454
  const rowid = handleGetRowId(row);
2319
2455
  selectRowMaps[rowid] = row;
2320
2456
  }
@@ -2322,13 +2458,13 @@ export default defineComponent({
2322
2458
  }
2323
2459
  else {
2324
2460
  /**
2325
- * 如果是树取消
2326
- * 如果方法成立,则不添加到临时集合中
2327
- */
2461
+ * 如果是树取消
2462
+ * 如果方法成立,则不添加到临时集合中
2463
+ */
2328
2464
  if (!isForce && checkMethod) {
2329
- XEUtils.eachTree(afterFullData, (row) => {
2465
+ XEUtils.eachTree(afterTreeFullData, (row) => {
2330
2466
  const rowid = handleGetRowId(row);
2331
- if (checkMethod({ row }) ? 0 : selectCheckboxMaps[rowid]) {
2467
+ if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
2332
2468
  selectRowMaps[rowid] = row;
2333
2469
  }
2334
2470
  }, { children: childrenField });
@@ -2338,14 +2474,14 @@ export default defineComponent({
2338
2474
  else {
2339
2475
  if (checked) {
2340
2476
  /**
2341
- * 如果是行勾选
2342
- * 如果存在选中方法且成立或者本身已勾选,则添加到临时集合中
2343
- * 如果不存在选中方法,则添加所有数据到临时集合中
2344
- */
2477
+ * 如果是行勾选
2478
+ * 如果存在选中方法且成立或者本身已勾选,则添加到临时集合中
2479
+ * 如果不存在选中方法,则添加所有数据到临时集合中
2480
+ */
2345
2481
  if (!isForce && checkMethod) {
2346
2482
  afterFullData.forEach((row) => {
2347
2483
  const rowid = handleGetRowId(row);
2348
- if (selectCheckboxMaps[rowid] || checkMethod({ row })) {
2484
+ if (selectCheckboxMaps[rowid] || checkMethod({ $table: $xeTable, row })) {
2349
2485
  selectRowMaps[rowid] = row;
2350
2486
  }
2351
2487
  });
@@ -2359,14 +2495,14 @@ export default defineComponent({
2359
2495
  }
2360
2496
  else {
2361
2497
  /**
2362
- * 如果是行取消
2363
- * 如果方法成立,则不添加到临时集合中;如果方法不成立则判断当前是否已勾选,如果已被勾选则添加到新集合中
2364
- * 如果不存在选中方法,无需处理,临时集合默认为空
2365
- */
2498
+ * 如果是行取消
2499
+ * 如果方法成立,则不添加到临时集合中;如果方法不成立则判断当前是否已勾选,如果已被勾选则添加到新集合中
2500
+ * 如果不存在选中方法,无需处理,临时集合默认为空
2501
+ */
2366
2502
  if (!isForce && checkMethod) {
2367
2503
  afterFullData.forEach((row) => {
2368
2504
  const rowid = handleGetRowId(row);
2369
- if (checkMethod({ row }) ? 0 : selectCheckboxMaps[rowid]) {
2505
+ if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
2370
2506
  selectRowMaps[rowid] = row;
2371
2507
  }
2372
2508
  });
@@ -2711,14 +2847,85 @@ export default defineComponent({
2711
2847
  }
2712
2848
  });
2713
2849
  };
2850
+ const handleUpdateRowGroup = (groupFields) => {
2851
+ reactData.rowGroupList = groupFields
2852
+ ? (XEUtils.isArray(groupFields) ? groupFields : [groupFields]).map(field => {
2853
+ return {
2854
+ field
2855
+ };
2856
+ })
2857
+ : [];
2858
+ };
2859
+ const handleGroupData = (list, rowGroups) => {
2860
+ let fullData = list;
2861
+ let treeData = list;
2862
+ if (rowGroups) {
2863
+ const rowGroupOpts = computeRowGroupOpts.value;
2864
+ const { rowField, parentField, childrenField, mapChildrenField } = rowGroupOpts;
2865
+ const checkboxOpts = computeCheckboxOpts.value;
2866
+ const { checkField } = checkboxOpts;
2867
+ const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField;
2868
+ const rgItem = rowGroups[0];
2869
+ if (rgItem && rowField && parentField && childrenField && mapChildrenField) {
2870
+ fullData = [];
2871
+ treeData = [];
2872
+ const groupField = rgItem.field;
2873
+ const groupColumn = $xeTable.getColumnByField(groupField);
2874
+ const groupMaps = {};
2875
+ const rowkey = getRowkey($xeTable);
2876
+ list.forEach((row) => {
2877
+ const cellValue = groupColumn ? $xeTable.getCellLabel(row, groupColumn) : XEUtils.get(row, groupField);
2878
+ const groupValue = XEUtils.eqNull(cellValue) ? '' : cellValue;
2879
+ let childList = groupMaps[groupValue];
2880
+ if (!childList) {
2881
+ childList = [];
2882
+ groupMaps[groupValue] = childList;
2883
+ }
2884
+ if (row.isAggregate) {
2885
+ row.isAggregate = undefined;
2886
+ }
2887
+ childList.push(row);
2888
+ });
2889
+ XEUtils.objectEach(groupMaps, (childList, groupValue) => {
2890
+ const { fullData: childFullData, treeData: childTreeData } = handleGroupData(childList, rowGroups.slice(1));
2891
+ const groupRow = {
2892
+ isAggregate: true,
2893
+ groupContent: groupValue,
2894
+ groupField,
2895
+ [rowField]: getRowUniqueId(),
2896
+ [parentField]: null,
2897
+ [rowkey]: getRowUniqueId(),
2898
+ [childrenField]: childTreeData,
2899
+ [mapChildrenField]: childTreeData
2900
+ };
2901
+ if (checkField) {
2902
+ groupRow[checkField] = false;
2903
+ }
2904
+ if (indeterminateField) {
2905
+ groupRow[indeterminateField] = false;
2906
+ }
2907
+ treeData.push(groupRow);
2908
+ fullData.push(groupRow);
2909
+ if (childFullData.length) {
2910
+ fullData.push(...childFullData);
2911
+ }
2912
+ });
2913
+ }
2914
+ }
2915
+ return {
2916
+ treeData,
2917
+ fullData
2918
+ };
2919
+ };
2714
2920
  /**
2715
2921
  * 加载表格数据
2716
2922
  * @param {Array} datas 数据
2717
2923
  */
2718
2924
  const loadTableData = (datas, isReset) => {
2719
- const { keepSource, treeConfig } = props;
2720
- const { scrollYLoad: oldScrollYLoad } = reactData;
2925
+ const { keepSource, treeConfig, rowGroupConfig } = props;
2926
+ const { rowGroupList, scrollYLoad: oldScrollYLoad } = reactData;
2721
2927
  const { scrollYStore, scrollXStore, lastScrollLeft, lastScrollTop } = internalData;
2928
+ const rowOpts = computeRowOpts.value;
2722
2929
  const treeOpts = computeTreeOpts.value;
2723
2930
  const expandOpts = computeExpandOpts.value;
2724
2931
  const { transform } = treeOpts;
@@ -2728,6 +2935,15 @@ export default defineComponent({
2728
2935
  if (fullData.length > supportMaxRow) {
2729
2936
  errLog('vxe.error.errMaxRow', [supportMaxRow]);
2730
2937
  }
2938
+ if (treeConfig && rowGroupList.length) {
2939
+ errLog('vxe.error.noTree', ['row-group-config']);
2940
+ return nextTick();
2941
+ }
2942
+ if (rowOpts.drag && rowGroupList.length) {
2943
+ errLog('vxe.error.errConflicts', ['row-config.drag', 'row-group-config']);
2944
+ return nextTick();
2945
+ }
2946
+ let isRGroup = false;
2731
2947
  if (treeConfig) {
2732
2948
  if (transform) {
2733
2949
  // 树结构自动转换
@@ -2763,6 +2979,13 @@ export default defineComponent({
2763
2979
  treeData = fullData.slice(0);
2764
2980
  }
2765
2981
  }
2982
+ else if (rowGroupConfig && rowGroupList.length) {
2983
+ const groupRest = handleGroupData(fullData, rowGroupList);
2984
+ treeData = groupRest.treeData;
2985
+ fullData = groupRest.fullData;
2986
+ isRGroup = true;
2987
+ }
2988
+ reactData.isRowGroupStatus = isRGroup;
2766
2989
  scrollYStore.startIndex = 0;
2767
2990
  scrollYStore.endIndex = 1;
2768
2991
  scrollXStore.startIndex = 0;
@@ -2776,7 +2999,8 @@ export default defineComponent({
2776
2999
  reactData.isDragRowMove = false;
2777
3000
  // 全量数据
2778
3001
  internalData.tableFullData = fullData;
2779
- internalData.tableFullTreeData = treeData;
3002
+ internalData.tableFullTreeData = isRGroup ? [] : treeData;
3003
+ internalData.tableFullGroupData = isRGroup ? treeData : [];
2780
3004
  // 缓存数据
2781
3005
  $xeTable.cacheRowMap(isReset);
2782
3006
  // 原始数据
@@ -3139,7 +3363,7 @@ export default defineComponent({
3139
3363
  */
3140
3364
  const handleBaseTreeExpand = (rows, expanded) => {
3141
3365
  const { treeNodeColumn } = reactData;
3142
- const { fullAllDataRowIdData, tableFullData, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData;
3366
+ const { fullAllDataRowIdData, tableFullTreeData, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData;
3143
3367
  const treeOpts = computeTreeOpts.value;
3144
3368
  const { reserve, lazy, accordion, toggleMethod } = treeOpts;
3145
3369
  const childrenField = treeOpts.children || treeOpts.childrenField;
@@ -3152,7 +3376,7 @@ export default defineComponent({
3152
3376
  if (accordion) {
3153
3377
  validRows = validRows.length ? [validRows[validRows.length - 1]] : [];
3154
3378
  // 同一级只能展开一个
3155
- const matchObj = XEUtils.findTree(tableFullData, item => item === validRows[0], { children: childrenField });
3379
+ const matchObj = XEUtils.findTree(tableFullTreeData, item => item === validRows[0], { children: childrenField });
3156
3380
  if (matchObj) {
3157
3381
  matchObj.items.forEach(item => {
3158
3382
  const rowid = handleGetRowId(item);
@@ -3208,6 +3432,79 @@ export default defineComponent({
3208
3432
  return handleBaseTreeExpand(rows, expanded).then(() => {
3209
3433
  handleVirtualTreeToList();
3210
3434
  $xeTable.handleTableData();
3435
+ reactData.treeExpandedFlag++;
3436
+ updateAfterDataIndex();
3437
+ return nextTick();
3438
+ }).then(() => {
3439
+ return $xeTable.recalculate(true);
3440
+ }).then(() => {
3441
+ setTimeout(() => {
3442
+ $xeTable.updateCellAreas();
3443
+ }, 30);
3444
+ });
3445
+ };
3446
+ /**
3447
+ * 展开与收起行分组节点
3448
+ * @param rows
3449
+ * @param expanded
3450
+ * @returns
3451
+ */
3452
+ const handleRowGroupBaseExpand = (rows, expanded) => {
3453
+ const { fullAllDataRowIdData, tableFullGroupData, rowGroupExpandedMaps } = internalData;
3454
+ const rowGroupOpts = computeRowGroupOpts.value;
3455
+ const { mapChildrenField, accordion } = rowGroupOpts;
3456
+ const { handleGetRowId } = createHandleGetRowId($xeTable);
3457
+ let validRows = rows;
3458
+ if (mapChildrenField) {
3459
+ if (accordion) {
3460
+ validRows = validRows.length ? [validRows[validRows.length - 1]] : [];
3461
+ // 同一级只能展开一个
3462
+ const matchObj = XEUtils.findTree(tableFullGroupData, item => getRowid($xeTable, item) === getRowid($xeTable, validRows[0]), { children: mapChildrenField });
3463
+ if (matchObj) {
3464
+ matchObj.items.forEach(item => {
3465
+ const rowid = handleGetRowId(item);
3466
+ if (rowGroupExpandedMaps[rowid]) {
3467
+ delete rowGroupExpandedMaps[rowid];
3468
+ }
3469
+ });
3470
+ }
3471
+ }
3472
+ if (expanded) {
3473
+ validRows.forEach((row) => {
3474
+ const rowid = handleGetRowId(row);
3475
+ if (!rowGroupExpandedMaps[rowid]) {
3476
+ const rowRest = fullAllDataRowIdData[rowid];
3477
+ if (rowRest) {
3478
+ if (row[mapChildrenField] && row[mapChildrenField].length) {
3479
+ rowGroupExpandedMaps[rowid] = row;
3480
+ }
3481
+ }
3482
+ }
3483
+ });
3484
+ }
3485
+ else {
3486
+ validRows.forEach(item => {
3487
+ const rowid = handleGetRowId(item);
3488
+ if (rowGroupExpandedMaps[rowid]) {
3489
+ delete rowGroupExpandedMaps[rowid];
3490
+ }
3491
+ });
3492
+ }
3493
+ }
3494
+ reactData.rowGroupExpandedFlag++;
3495
+ return $xeTable.recalculate();
3496
+ };
3497
+ /**
3498
+ * 行分组的展开与收起
3499
+ * @param rows
3500
+ * @param expanded
3501
+ * @returns
3502
+ */
3503
+ const handleRowGroupVirtualExpand = (rows, expanded) => {
3504
+ return handleRowGroupBaseExpand(rows, expanded).then(() => {
3505
+ handleVirtualTreeToList();
3506
+ $xeTable.handleTableData();
3507
+ reactData.rowGroupExpandedFlag++;
3211
3508
  updateAfterDataIndex();
3212
3509
  return nextTick();
3213
3510
  }).then(() => {
@@ -3967,7 +4264,7 @@ export default defineComponent({
3967
4264
  if (!column) {
3968
4265
  return null;
3969
4266
  }
3970
- const formatter = column.formatter;
4267
+ const { formatter } = column;
3971
4268
  const cellValue = getCellValue(row, column);
3972
4269
  let cellLabel = cellValue;
3973
4270
  if (formatter) {
@@ -4214,7 +4511,7 @@ export default defineComponent({
4214
4511
  getCheckboxRecords(isFull) {
4215
4512
  const { treeConfig } = props;
4216
4513
  const { updateCheckboxFlag } = reactData;
4217
- const { tableFullData, afterFullData, afterTreeFullData, tableFullTreeData, fullDataRowIdData, afterFullRowMaps, selectCheckboxMaps } = internalData;
4514
+ const { tableFullData, afterFullData, tableFullTreeData, fullDataRowIdData, afterFullRowMaps, selectCheckboxMaps } = internalData;
4218
4515
  const treeOpts = computeTreeOpts.value;
4219
4516
  const checkboxOpts = computeCheckboxOpts.value;
4220
4517
  const { transform, mapChildrenField } = treeOpts;
@@ -4224,7 +4521,8 @@ export default defineComponent({
4224
4521
  if (updateCheckboxFlag) {
4225
4522
  if (checkField) {
4226
4523
  if (treeConfig) {
4227
- const currTableData = isFull ? (transform ? tableFullTreeData : tableFullData) : (transform ? afterTreeFullData : afterFullData);
4524
+ // 如果开启 transform 默认就是完整数据
4525
+ const currTableData = isFull ? (transform ? tableFullTreeData : tableFullData) : (transform ? tableFullTreeData : afterFullData);
4228
4526
  rowList = XEUtils.filterTree(currTableData, row => XEUtils.get(row, checkField), { children: transform ? mapChildrenField : childrenField });
4229
4527
  }
4230
4528
  else {
@@ -5219,7 +5517,7 @@ export default defineComponent({
5219
5517
  });
5220
5518
  if (isUpdate) {
5221
5519
  if (!remote) {
5222
- tablePrivateMethods.handleTableData(true);
5520
+ $xeTable.handleTableData(true);
5223
5521
  }
5224
5522
  $xeTable.handleColumnSortEvent(new Event('click'), firstColumn);
5225
5523
  }
@@ -5247,7 +5545,7 @@ export default defineComponent({
5247
5545
  clearAllSort();
5248
5546
  }
5249
5547
  if (!sortOpts.remote) {
5250
- tablePrivateMethods.handleTableData(true);
5548
+ $xeTable.handleTableData(true);
5251
5549
  }
5252
5550
  return nextTick().then(updateStyle);
5253
5551
  },
@@ -5393,8 +5691,8 @@ export default defineComponent({
5393
5691
  const expandOpts = computeExpandOpts.value;
5394
5692
  const { reserve, lazy, accordion, toggleMethod } = expandOpts;
5395
5693
  const lazyRests = [];
5396
- const columnIndex = $xeTable.getColumnIndex(expandColumn);
5397
- const $columnIndex = $xeTable.getVMColumnIndex(expandColumn);
5694
+ const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1;
5695
+ const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1;
5398
5696
  if (rows) {
5399
5697
  if (!XEUtils.isArray(rows)) {
5400
5698
  rows = [rows];
@@ -5498,6 +5796,70 @@ export default defineComponent({
5498
5796
  });
5499
5797
  return rest;
5500
5798
  },
5799
+ setRowGroups(fieldOrColumns) {
5800
+ const { rowGroupConfig } = props;
5801
+ if (!rowGroupConfig) {
5802
+ errLog('vxe.error.reqProp', ['row-group-config']);
5803
+ return nextTick();
5804
+ }
5805
+ if (fieldOrColumns) {
5806
+ handleUpdateRowGroup((XEUtils.isArray(fieldOrColumns) ? fieldOrColumns : [fieldOrColumns]).map(fieldOrColumn => {
5807
+ return XEUtils.isString(fieldOrColumn) ? fieldOrColumn : fieldOrColumn.field;
5808
+ }));
5809
+ return loadTableData(internalData.tableSynchData, true);
5810
+ }
5811
+ return nextTick();
5812
+ },
5813
+ clearRowGroups() {
5814
+ const { rowGroupConfig } = props;
5815
+ if (!rowGroupConfig) {
5816
+ errLog('vxe.error.reqProp', ['row-group-config']);
5817
+ return nextTick();
5818
+ }
5819
+ handleUpdateRowGroup([]);
5820
+ return loadTableData(internalData.tableSynchData, true);
5821
+ },
5822
+ isRowGroupRecord(row) {
5823
+ const { isRowGroupStatus } = reactData;
5824
+ return isRowGroupStatus && row.isAggregate;
5825
+ },
5826
+ isRowGroupExpandByRow(row) {
5827
+ const { rowGroupExpandedFlag } = reactData;
5828
+ const { rowGroupExpandedMaps } = internalData;
5829
+ return !!rowGroupExpandedFlag && !!rowGroupExpandedMaps[getRowid($xeTable, row)];
5830
+ },
5831
+ setRowGroupExpand(rows, expanded) {
5832
+ if (rows) {
5833
+ if (!XEUtils.isArray(rows)) {
5834
+ rows = [rows];
5835
+ }
5836
+ return handleRowGroupVirtualExpand(rows, expanded);
5837
+ }
5838
+ return nextTick();
5839
+ },
5840
+ setAllRowGroupExpand(expanded) {
5841
+ const { tableFullGroupData } = internalData;
5842
+ const rowGroupOpts = computeRowGroupOpts.value;
5843
+ const { mapChildrenField } = rowGroupOpts;
5844
+ const rgExpandedMaps = {};
5845
+ if (expanded && mapChildrenField) {
5846
+ XEUtils.eachTree(tableFullGroupData, (row) => {
5847
+ if (row[mapChildrenField] && row[mapChildrenField].length) {
5848
+ rgExpandedMaps[getRowid($xeTable, row)] = row;
5849
+ }
5850
+ }, { children: mapChildrenField });
5851
+ }
5852
+ internalData.rowGroupExpandedMaps = rgExpandedMaps;
5853
+ handleVirtualTreeToList();
5854
+ reactData.rowGroupExpandedFlag++;
5855
+ return $xeTable.handleTableData();
5856
+ },
5857
+ clearRowGroupExpand() {
5858
+ internalData.rowGroupExpandedMaps = {};
5859
+ handleVirtualTreeToList();
5860
+ reactData.rowGroupExpandedFlag++;
5861
+ return $xeTable.handleTableData();
5862
+ },
5501
5863
  getTreeExpandRecords() {
5502
5864
  const rest = [];
5503
5865
  XEUtils.each(internalData.treeExpandedMaps, item => {
@@ -5541,11 +5903,11 @@ export default defineComponent({
5541
5903
  });
5542
5904
  }
5543
5905
  internalData.treeExpandedMaps = {};
5544
- reactData.treeExpandedFlag++;
5545
5906
  if (transform) {
5546
5907
  handleVirtualTreeToList();
5547
- return $xeTable.handleTableData();
5908
+ $xeTable.handleTableData();
5548
5909
  }
5910
+ reactData.treeExpandedFlag++;
5549
5911
  return nextTick();
5550
5912
  },
5551
5913
  /**
@@ -5559,15 +5921,16 @@ export default defineComponent({
5559
5921
  const { transform, lazy } = treeOpts;
5560
5922
  const rowid = getRowid($xeTable, row);
5561
5923
  if (lazy && row[hasChildField] && !treeExpandLazyLoadedMaps[rowid]) {
5562
- return tableMethods.clearTreeExpandLoaded(row).then(() => {
5924
+ return $xeTable.clearTreeExpandLoaded(row).then(() => {
5563
5925
  return handleAsyncTreeExpandChilds(row);
5564
5926
  }).then(() => {
5565
5927
  if (transform) {
5566
5928
  handleVirtualTreeToList();
5567
- return tablePrivateMethods.handleTableData();
5929
+ $xeTable.handleTableData();
5568
5930
  }
5931
+ reactData.treeExpandedFlag++;
5569
5932
  }).then(() => {
5570
- return tableMethods.recalculate();
5933
+ return $xeTable.recalculate();
5571
5934
  });
5572
5935
  }
5573
5936
  return nextTick();
@@ -5577,13 +5940,13 @@ export default defineComponent({
5577
5940
  warnLog('vxe.error.delFunc', ['reloadTreeChilds', 'reloadTreeExpand']);
5578
5941
  }
5579
5942
  // 即将废弃
5580
- return tableMethods.reloadTreeExpand(row);
5943
+ return $xeTable.reloadTreeExpand(row);
5581
5944
  },
5582
5945
  /**
5583
5946
  * 切换/展开树节点
5584
5947
  */
5585
5948
  toggleTreeExpand(row) {
5586
- return tableMethods.setTreeExpand(row, !tableMethods.isTreeExpandByRow(row));
5949
+ return $xeTable.setTreeExpand(row, !$xeTable.isTreeExpandByRow(row));
5587
5950
  },
5588
5951
  /**
5589
5952
  * 设置所有树节点的展开与否
@@ -5601,10 +5964,11 @@ export default defineComponent({
5601
5964
  expandeds.push(row);
5602
5965
  }
5603
5966
  }, { children: childrenField });
5604
- return tableMethods.setTreeExpand(expandeds, expanded).then(() => {
5967
+ return $xeTable.setTreeExpand(expandeds, expanded).then(() => {
5605
5968
  if (transform) {
5606
5969
  handleVirtualTreeToList();
5607
- return tableMethods.recalculate();
5970
+ reactData.treeExpandedFlag++;
5971
+ return $xeTable.recalculate();
5608
5972
  }
5609
5973
  });
5610
5974
  },
@@ -5653,15 +6017,15 @@ export default defineComponent({
5653
6017
  const { transform, reserve } = treeOpts;
5654
6018
  const expList = $xeTable.getTreeExpandRecords();
5655
6019
  internalData.treeExpandedMaps = {};
5656
- reactData.treeExpandedFlag++;
5657
6020
  if (reserve) {
5658
6021
  XEUtils.eachTree(tableFullTreeData, row => handleTreeExpandReserve(row, false), { children: childrenField });
5659
6022
  }
5660
6023
  return $xeTable.handleTableData().then(() => {
5661
6024
  if (transform) {
5662
6025
  handleVirtualTreeToList();
5663
- return $xeTable.handleTableData();
6026
+ $xeTable.handleTableData();
5664
6027
  }
6028
+ reactData.treeExpandedFlag++;
5665
6029
  }).then(() => {
5666
6030
  if (expList.length) {
5667
6031
  return $xeTable.recalculate();
@@ -5972,7 +6336,7 @@ export default defineComponent({
5972
6336
  hasResizable = 1;
5973
6337
  resizableData[colKey] = column.renderWidth;
5974
6338
  }
5975
- if (isCustomVisible && (!checkMethod || checkMethod({ column }))) {
6339
+ if (isCustomVisible && (!checkMethod || checkMethod({ $table: $xeTable, column }))) {
5976
6340
  if (!column.visible && column.defaultVisible) {
5977
6341
  hasVisible = 1;
5978
6342
  visibleData[colKey] = false;
@@ -6250,8 +6614,7 @@ export default defineComponent({
6250
6614
  const hasDeleteKey = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.DELETE);
6251
6615
  const isF2 = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.F2);
6252
6616
  const isContextMenu = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.CONTEXT_MENU);
6253
- const hasMetaKey = evnt.metaKey;
6254
- const hasCtrlKey = evnt.ctrlKey;
6617
+ const isControlKey = hasControlKey(evnt);
6255
6618
  const hasShiftKey = evnt.shiftKey;
6256
6619
  const isAltKey = evnt.altKey;
6257
6620
  const operArrow = isLeftArrow || isUpArrow || isRightArrow || isDwArrow;
@@ -6319,7 +6682,7 @@ export default defineComponent({
6319
6682
  else if (isEnter && !isAltKey && keyboardConfig && keyboardOpts.isEnter && (selected.row || actived.row || (treeConfig && (rowOpts.isCurrent || highlightCurrentRow) && currentRow))) {
6320
6683
  const { isLastEnterAppendRow, beforeEnterMethod, enterMethod } = keyboardOpts;
6321
6684
  // 退出选中
6322
- if (hasCtrlKey) {
6685
+ if (isControlKey) {
6323
6686
  // 如果是激活编辑状态,则取消编辑
6324
6687
  if (actived.row) {
6325
6688
  const params = actived.args;
@@ -6499,7 +6862,7 @@ export default defineComponent({
6499
6862
  .then(() => $xeTable.triggerCurrentRowEvent(evnt, params));
6500
6863
  }
6501
6864
  }
6502
- else if (keyboardConfig && isEnableConf(editConfig) && keyboardOpts.isEdit && !hasCtrlKey && !hasMetaKey && (isSpacebar || (keyCode >= 48 && keyCode <= 57) || (keyCode >= 65 && keyCode <= 90) || (keyCode >= 96 && keyCode <= 111) || (keyCode >= 186 && keyCode <= 192) || (keyCode >= 219 && keyCode <= 222))) {
6865
+ else if (keyboardConfig && isEnableConf(editConfig) && keyboardOpts.isEdit && !isControlKey && (isSpacebar || (keyCode >= 48 && keyCode <= 57) || (keyCode >= 65 && keyCode <= 90) || (keyCode >= 96 && keyCode <= 111) || (keyCode >= 186 && keyCode <= 192) || (keyCode >= 219 && keyCode <= 222))) {
6503
6866
  const { editMode, editMethod } = keyboardOpts;
6504
6867
  // 启用编辑后,空格键功能将失效
6505
6868
  // if (isSpacebar) {
@@ -6645,9 +7008,11 @@ export default defineComponent({
6645
7008
  const rTooltipMethod = tooltipMethod || (dragConfig ? dragConfig.rowTooltipMethod : null);
6646
7009
  let tipContent = '';
6647
7010
  if (rTooltipMethod) {
6648
- tipContent = `${rTooltipMethod({
7011
+ const rtParams = {
7012
+ $table: $xeTable,
6649
7013
  row: dragRow
6650
- }) || ''}`;
7014
+ };
7015
+ tipContent = `${rTooltipMethod(rtParams) || ''}`;
6651
7016
  }
6652
7017
  else {
6653
7018
  tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || '']);
@@ -6683,9 +7048,11 @@ export default defineComponent({
6683
7048
  const { tooltipMethod } = columnDragOpts;
6684
7049
  let tipContent = '';
6685
7050
  if (tooltipMethod) {
6686
- tipContent = `${tooltipMethod({
7051
+ const dtParams = {
7052
+ $table: $xeTable,
6687
7053
  column: dragCol
6688
- }) || ''}`;
7054
+ };
7055
+ tipContent = `${tooltipMethod(dtParams) || ''}`;
6689
7056
  }
6690
7057
  else {
6691
7058
  tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || '']);
@@ -6967,11 +7334,8 @@ export default defineComponent({
6967
7334
  */
6968
7335
  cacheRowMap(isReset) {
6969
7336
  const { treeConfig } = props;
6970
- const { fullAllDataRowIdData, tableFullData, tableFullTreeData, treeExpandedMaps } = internalData;
6971
- const treeOpts = computeTreeOpts.value;
6972
- const childrenField = treeOpts.children || treeOpts.childrenField;
6973
- const hasChildField = treeOpts.hasChild || treeOpts.hasChildField;
6974
- const { lazy } = treeOpts;
7337
+ const { isRowGroupStatus } = reactData;
7338
+ const { fullAllDataRowIdData, tableFullData, tableFullTreeData, tableFullGroupData, treeExpandedMaps } = internalData;
6975
7339
  const fullAllDataRowIdMaps = isReset ? {} : Object.assign({}, fullAllDataRowIdData); // 存在已删除数据
6976
7340
  const fullDataRowIdMaps = {};
6977
7341
  const { handleUpdateRowId } = createHandleUpdateRowId($xeTable);
@@ -6994,6 +7358,10 @@ export default defineComponent({
6994
7358
  fullAllDataRowIdMaps[rowid] = rowRest;
6995
7359
  };
6996
7360
  if (treeConfig) {
7361
+ const treeOpts = computeTreeOpts.value;
7362
+ const { lazy } = treeOpts;
7363
+ const childrenField = treeOpts.children || treeOpts.childrenField;
7364
+ const hasChildField = treeOpts.hasChild || treeOpts.hasChildField;
6997
7365
  XEUtils.eachTree(tableFullTreeData, (row, index, items, path, parentRow, nodes) => {
6998
7366
  const rowid = handleUpdateRowId(row);
6999
7367
  if (treeConfig && lazy) {
@@ -7009,6 +7377,14 @@ export default defineComponent({
7009
7377
  handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path));
7010
7378
  }, { children: childrenField });
7011
7379
  }
7380
+ else if (isRowGroupStatus) {
7381
+ const rowGroupOpts = computeRowGroupOpts.value;
7382
+ const { mapChildrenField } = rowGroupOpts;
7383
+ XEUtils.eachTree(tableFullGroupData, (row, index, items, path, parentRow, nodes) => {
7384
+ const rowid = handleUpdateRowId(row);
7385
+ handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path));
7386
+ }, { children: mapChildrenField });
7387
+ }
7012
7388
  else {
7013
7389
  tableFullData.forEach((row, index, items) => {
7014
7390
  handleRowCache(row, index, items, index, null, handleUpdateRowId(row), 0, index + 1);
@@ -7445,6 +7821,7 @@ export default defineComponent({
7445
7821
  : tableMethods.getCustomStoreData();
7446
7822
  if (updateStore) {
7447
7823
  return updateStore({
7824
+ $table: $xeTable,
7448
7825
  id: tableId,
7449
7826
  type,
7450
7827
  storeData
@@ -7515,29 +7892,46 @@ export default defineComponent({
7515
7892
  },
7516
7893
  updateCheckboxStatus() {
7517
7894
  const { treeConfig } = props;
7518
- const { selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
7895
+ const { isRowGroupStatus } = reactData;
7896
+ const { afterTreeFullData, afterGroupFullData, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
7897
+ const rowGroupOpts = computeRowGroupOpts.value;
7519
7898
  const treeOpts = computeTreeOpts.value;
7520
- const { transform, mapChildrenField } = treeOpts;
7521
7899
  const childrenField = treeOpts.children || treeOpts.childrenField;
7522
7900
  const checkboxOpts = computeCheckboxOpts.value;
7523
7901
  const { checkField, checkStrictly, checkMethod } = checkboxOpts;
7524
- const { afterTreeFullData } = internalData;
7525
7902
  if (checkStrictly) {
7526
7903
  return;
7527
7904
  }
7528
- // 树结构
7529
- if (treeConfig) {
7905
+ if (isRowGroupStatus || treeConfig) {
7530
7906
  const { handleGetRowId } = createHandleGetRowId($xeTable);
7531
7907
  const childRowMaps = {};
7532
7908
  const childRowList = [];
7533
- XEUtils.eachTree(afterTreeFullData, (row) => {
7534
- const rowid = handleGetRowId(row);
7535
- const childList = row[transform ? mapChildrenField : childrenField];
7536
- if (childList && childList.length && !childRowMaps[rowid]) {
7537
- childRowMaps[rowid] = 1;
7538
- childRowList.unshift([row, rowid, childList]);
7909
+ if (isRowGroupStatus) {
7910
+ // 行分组
7911
+ const mapChildrenField = rowGroupOpts.mapChildrenField;
7912
+ if (mapChildrenField) {
7913
+ XEUtils.eachTree(afterGroupFullData, (row) => {
7914
+ const rowid = handleGetRowId(row);
7915
+ const childList = row[mapChildrenField];
7916
+ if (childList && childList.length && !childRowMaps[rowid]) {
7917
+ childRowMaps[rowid] = 1;
7918
+ childRowList.unshift([row, rowid, childList]);
7919
+ }
7920
+ }, { children: mapChildrenField });
7539
7921
  }
7540
- }, { children: transform ? mapChildrenField : childrenField });
7922
+ }
7923
+ else if (treeConfig) {
7924
+ // 树结构
7925
+ const { transform, mapChildrenField } = treeOpts;
7926
+ XEUtils.eachTree(afterTreeFullData, (row) => {
7927
+ const rowid = handleGetRowId(row);
7928
+ const childList = row[transform ? mapChildrenField : childrenField];
7929
+ if (childList && childList.length && !childRowMaps[rowid]) {
7930
+ childRowMaps[rowid] = 1;
7931
+ childRowList.unshift([row, rowid, childList]);
7932
+ }
7933
+ }, { children: transform ? mapChildrenField : childrenField });
7934
+ }
7541
7935
  childRowList.forEach(vals => {
7542
7936
  const row = vals[0];
7543
7937
  const rowid = vals[1];
@@ -7549,7 +7943,7 @@ export default defineComponent({
7549
7943
  ? (item) => {
7550
7944
  const childRowid = handleGetRowId(item);
7551
7945
  const isSelect = checkField ? XEUtils.get(item, checkField) : selectCheckboxMaps[childRowid];
7552
- if (checkMethod({ row: item })) {
7946
+ if (checkMethod({ $table: $xeTable, row: item })) {
7553
7947
  if (isSelect) {
7554
7948
  sLen++;
7555
7949
  }
@@ -7612,19 +8006,20 @@ export default defineComponent({
7612
8006
  },
7613
8007
  updateAllCheckboxStatus() {
7614
8008
  const { treeConfig } = props;
7615
- const { afterFullData, afterTreeFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
8009
+ const { isRowGroupStatus } = reactData;
8010
+ const { afterFullData, afterTreeFullData, afterGroupFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
7616
8011
  const checkboxOpts = computeCheckboxOpts.value;
7617
8012
  const { checkField, checkMethod, showReserveStatus } = checkboxOpts;
7618
8013
  const { handleGetRowId } = createHandleGetRowId($xeTable);
7619
8014
  let sLen = 0; // 已选
7620
8015
  let hLen = 0; // 半选
7621
8016
  let vLen = 0; // 有效行
7622
- const rootList = (treeConfig ? afterTreeFullData : afterFullData);
8017
+ const rootList = (treeConfig ? afterTreeFullData : (isRowGroupStatus ? afterGroupFullData : afterFullData));
7623
8018
  rootList.forEach(checkMethod
7624
8019
  ? row => {
7625
8020
  const childRowid = handleGetRowId(row);
7626
8021
  const selected = checkField ? XEUtils.get(row, checkField) : selectCheckboxMaps[childRowid];
7627
- if (checkMethod({ row })) {
8022
+ if (checkMethod({ $table: $xeTable, row })) {
7628
8023
  if (selected) {
7629
8024
  sLen++;
7630
8025
  }
@@ -7672,7 +8067,9 @@ export default defineComponent({
7672
8067
  */
7673
8068
  handleBatchSelectRows(rows, checked, isForce) {
7674
8069
  const { treeConfig } = props;
8070
+ const { isRowGroupStatus } = reactData;
7675
8071
  const { selectCheckboxMaps } = internalData;
8072
+ const rowGroupOpts = computeRowGroupOpts.value;
7676
8073
  const treeOpts = computeTreeOpts.value;
7677
8074
  const { transform, mapChildrenField } = treeOpts;
7678
8075
  const childrenField = treeOpts.children || treeOpts.childrenField;
@@ -7683,10 +8080,10 @@ export default defineComponent({
7683
8080
  const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField;
7684
8081
  if (checkField) {
7685
8082
  // 树结构
7686
- if (treeConfig && !checkStrictly) {
8083
+ if ((treeConfig || isRowGroupStatus) && !checkStrictly) {
7687
8084
  // 更新子节点状态
7688
8085
  XEUtils.eachTree(rows, (row) => {
7689
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8086
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7690
8087
  XEUtils.set(row, checkField, checked);
7691
8088
  if (indeterminateField) {
7692
8089
  XEUtils.set(row, indeterminateField, false);
@@ -7699,7 +8096,7 @@ export default defineComponent({
7699
8096
  }
7700
8097
  // 列表
7701
8098
  rows.forEach(row => {
7702
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8099
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7703
8100
  XEUtils.set(row, checkField, checked);
7704
8101
  handleCheckboxReserveRow(row, checked);
7705
8102
  }
@@ -7708,29 +8105,50 @@ export default defineComponent({
7708
8105
  return;
7709
8106
  }
7710
8107
  // 树结构
7711
- if (treeConfig && !checkStrictly) {
7712
- // 更新子节点状态
7713
- XEUtils.eachTree(rows, (row) => {
7714
- const rowid = handleGetRowId(row);
7715
- if (isForce || (!checkMethod || checkMethod({ row }))) {
7716
- if (checked) {
7717
- selectCheckboxMaps[rowid] = row;
8108
+ if (!checkStrictly) {
8109
+ if (isRowGroupStatus) {
8110
+ // 更新行分组节点状态
8111
+ XEUtils.eachTree(rows, (row) => {
8112
+ const rowid = handleGetRowId(row);
8113
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
8114
+ if (checked) {
8115
+ selectCheckboxMaps[rowid] = row;
8116
+ }
8117
+ else {
8118
+ if (selectCheckboxMaps[rowid]) {
8119
+ delete selectCheckboxMaps[rowid];
8120
+ }
8121
+ }
8122
+ handleCheckboxReserveRow(row, checked);
7718
8123
  }
7719
- else {
7720
- if (selectCheckboxMaps[rowid]) {
7721
- delete selectCheckboxMaps[rowid];
8124
+ }, { children: rowGroupOpts.mapChildrenField });
8125
+ reactData.updateCheckboxFlag++;
8126
+ return;
8127
+ }
8128
+ else if (treeConfig) {
8129
+ // 更新子节点状态
8130
+ XEUtils.eachTree(rows, (row) => {
8131
+ const rowid = handleGetRowId(row);
8132
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
8133
+ if (checked) {
8134
+ selectCheckboxMaps[rowid] = row;
8135
+ }
8136
+ else {
8137
+ if (selectCheckboxMaps[rowid]) {
8138
+ delete selectCheckboxMaps[rowid];
8139
+ }
7722
8140
  }
8141
+ handleCheckboxReserveRow(row, checked);
7723
8142
  }
7724
- handleCheckboxReserveRow(row, checked);
7725
- }
7726
- }, { children: transform ? mapChildrenField : childrenField });
7727
- reactData.updateCheckboxFlag++;
7728
- return;
8143
+ }, { children: transform ? mapChildrenField : childrenField });
8144
+ reactData.updateCheckboxFlag++;
8145
+ return;
8146
+ }
7729
8147
  }
7730
8148
  // 列表
7731
8149
  rows.forEach(row => {
7732
8150
  const rowid = handleGetRowId(row);
7733
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8151
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7734
8152
  if (checked) {
7735
8153
  if (!selectCheckboxMaps[rowid]) {
7736
8154
  selectCheckboxMaps[rowid] = row;
@@ -7903,20 +8321,22 @@ export default defineComponent({
7903
8321
  const radioOpts = computeRadioOpts.value;
7904
8322
  const checkboxOpts = computeCheckboxOpts.value;
7905
8323
  const keyboardOpts = computeKeyboardOpts.value;
8324
+ const rowGroupOpts = computeRowGroupOpts.value;
7906
8325
  const rowOpts = computeRowOpts.value;
7907
8326
  const columnOpts = computeColumnOpts.value;
7908
8327
  const currentColumnOpts = computeCurrentColumnOpts.value;
7909
8328
  const { actived, focused } = editStore;
7910
8329
  const { row, column } = params;
7911
- const { type, treeNode } = column;
8330
+ const { type, treeNode, rowGroupNode } = column;
7912
8331
  const isRadioType = type === 'radio';
7913
8332
  const isCheckboxType = type === 'checkbox';
7914
8333
  const isExpandType = type === 'expand';
7915
8334
  const cell = evnt.currentTarget;
7916
8335
  const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag;
7917
8336
  const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag;
7918
- const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag;
8337
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag;
7919
8338
  const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag;
8339
+ const triggerRowGroupNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-row-group--node-btn').flag;
7920
8340
  params = Object.assign({ cell, triggerRadio, triggerCheckbox, triggerTreeNode, triggerExpandNode }, params);
7921
8341
  if (!triggerCheckbox && !triggerRadio) {
7922
8342
  // 如果是展开行
@@ -7927,10 +8347,14 @@ export default defineComponent({
7927
8347
  if ((treeOpts.trigger === 'row' || (treeNode && treeOpts.trigger === 'cell'))) {
7928
8348
  $xeTable.triggerTreeExpandEvent(evnt, params);
7929
8349
  }
8350
+ // 如果是行分组
8351
+ if ((rowGroupOpts.trigger === 'row' || (rowGroupNode && rowGroupOpts.trigger === 'cell'))) {
8352
+ $xeTable.triggerRowGroupExpandEvent(evnt, params);
8353
+ }
7930
8354
  }
7931
8355
  // 如果点击了树节点
7932
8356
  if (!triggerTreeNode) {
7933
- if (!triggerExpandNode) {
8357
+ if (!triggerExpandNode && !triggerRowGroupNode) {
7934
8358
  // 如果是当前行
7935
8359
  if (rowOpts.isCurrent || highlightCurrentRow) {
7936
8360
  if (!triggerCheckbox && !triggerRadio) {
@@ -8051,7 +8475,9 @@ export default defineComponent({
8051
8475
  }
8052
8476
  },
8053
8477
  triggerCheckRowEvent(evnt, params, checked) {
8478
+ const { treeConfig } = props;
8054
8479
  const { row } = params;
8480
+ const { isRowGroupStatus } = reactData;
8055
8481
  const { afterFullData } = internalData;
8056
8482
  const checkboxOpts = computeCheckboxOpts.value;
8057
8483
  const { checkMethod, trigger } = checkboxOpts;
@@ -8059,7 +8485,7 @@ export default defineComponent({
8059
8485
  return;
8060
8486
  }
8061
8487
  evnt.stopPropagation();
8062
- if (checkboxOpts.isShiftKey && evnt.shiftKey && !props.treeConfig) {
8488
+ if (checkboxOpts.isShiftKey && evnt.shiftKey && !(treeConfig || isRowGroupStatus)) {
8063
8489
  const checkboxRecords = $xeTable.getCheckboxRecords();
8064
8490
  if (checkboxRecords.length) {
8065
8491
  const firstRow = checkboxRecords[0];
@@ -8076,7 +8502,7 @@ export default defineComponent({
8076
8502
  }
8077
8503
  }
8078
8504
  }
8079
- if (!checkMethod || checkMethod({ row })) {
8505
+ if (!checkMethod || checkMethod({ $table: $xeTable, row })) {
8080
8506
  $xeTable.handleBatchSelectRows([row], checked);
8081
8507
  $xeTable.checkSelectionStatus();
8082
8508
  dispatchEvent('checkbox-change', Object.assign({
@@ -8177,7 +8603,7 @@ export default defineComponent({
8177
8603
  * 展开行事件
8178
8604
  */
8179
8605
  triggerRowExpandEvent(evnt, params) {
8180
- const { expandColumn: column } = reactData;
8606
+ const { expandColumn } = reactData;
8181
8607
  const { rowExpandLazyLoadedMaps } = internalData;
8182
8608
  const expandOpts = computeExpandOpts.value;
8183
8609
  const { row } = params;
@@ -8189,12 +8615,12 @@ export default defineComponent({
8189
8615
  const rowid = getRowid($xeTable, row);
8190
8616
  if (!lazy || !rowExpandLazyLoadedMaps[rowid]) {
8191
8617
  const expanded = !$xeTable.isRowExpandByRow(row);
8192
- const columnIndex = $xeTable.getColumnIndex(column);
8193
- const $columnIndex = $xeTable.getVMColumnIndex(column);
8618
+ const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1;
8619
+ const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1;
8194
8620
  $xeTable.setRowExpand(row, expanded);
8195
8621
  dispatchEvent('toggle-row-expand', {
8196
8622
  expanded,
8197
- column,
8623
+ column: expandColumn,
8198
8624
  columnIndex,
8199
8625
  $columnIndex,
8200
8626
  row,
@@ -8203,6 +8629,25 @@ export default defineComponent({
8203
8629
  }, evnt);
8204
8630
  }
8205
8631
  },
8632
+ /**
8633
+ * 行分组事件
8634
+ */
8635
+ triggerRowGroupExpandEvent(evnt, params) {
8636
+ const { rowGroupExpandedMaps } = internalData;
8637
+ const rowGroupOpts = computeRowGroupOpts.value;
8638
+ const { row, column } = params;
8639
+ const { trigger } = rowGroupOpts;
8640
+ if (trigger === 'manual') {
8641
+ return;
8642
+ }
8643
+ evnt.stopPropagation();
8644
+ const rowid = getRowid($xeTable, row);
8645
+ const expanded = !rowGroupExpandedMaps[rowid];
8646
+ const columnIndex = $xeTable.getColumnIndex(column);
8647
+ const $columnIndex = $xeTable.getVMColumnIndex(column);
8648
+ $xeTable.setRowGroupExpand(row, expanded);
8649
+ dispatchEvent('toggle-row-group-expand', { expanded, column, columnIndex, $columnIndex, row }, evnt);
8650
+ },
8206
8651
  /**
8207
8652
  * 展开树节点事件
8208
8653
  */
@@ -8339,7 +8784,7 @@ export default defineComponent({
8339
8784
  const triggerInput = cell && cell.tagName && cell.tagName.toLowerCase() === 'input';
8340
8785
  const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag;
8341
8786
  const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag;
8342
- const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag;
8787
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag;
8343
8788
  const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag;
8344
8789
  let isColDragCell = false;
8345
8790
  if (rowOpts.drag) {
@@ -8600,7 +9045,7 @@ export default defineComponent({
8600
9045
  evnt.preventDefault();
8601
9046
  return;
8602
9047
  }
8603
- const hasCtrlKey = evnt.ctrlKey;
9048
+ const isControlKey = hasControlKey(evnt);
8604
9049
  const trEl = evnt.currentTarget;
8605
9050
  const rowid = trEl.getAttribute('rowid') || '';
8606
9051
  const rest = fullAllDataRowIdData[rowid];
@@ -8612,11 +9057,11 @@ export default defineComponent({
8612
9057
  const { dragRow } = reactData;
8613
9058
  const offsetY = evnt.clientY - trEl.getBoundingClientRect().y;
8614
9059
  const dragPos = offsetY < trEl.clientHeight / 2 ? 'top' : 'bottom';
8615
- internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && hasCtrlKey);
9060
+ internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && isControlKey);
8616
9061
  internalData.prevDragRow = row;
8617
9062
  internalData.prevDragPos = dragPos;
8618
9063
  if ($xeTable.eqRow(dragRow, row) ||
8619
- (hasCtrlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
9064
+ (isControlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
8620
9065
  (!isCrossDrag && treeConfig && transform && (isPeerDrag ? dragRow[parentField] !== row[parentField] : rest.level))) {
8621
9066
  showDropTip(evnt, trEl, null, false, dragPos);
8622
9067
  return;
@@ -8865,7 +9310,7 @@ export default defineComponent({
8865
9310
  evnt.preventDefault();
8866
9311
  return;
8867
9312
  }
8868
- const hasCtrlKey = evnt.ctrlKey;
9313
+ const isControlKey = hasControlKey(evnt);
8869
9314
  const thEl = evnt.currentTarget;
8870
9315
  const colid = thEl.getAttribute('colid');
8871
9316
  const column = $xeTable.getColumnById(colid);
@@ -8874,7 +9319,7 @@ export default defineComponent({
8874
9319
  const { clientX } = evnt;
8875
9320
  const offsetX = clientX - thEl.getBoundingClientRect().x;
8876
9321
  const dragPos = offsetX < thEl.clientWidth / 2 ? 'left' : 'right';
8877
- internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && hasCtrlKey);
9322
+ internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && isControlKey);
8878
9323
  internalData.prevDragCol = column;
8879
9324
  internalData.prevDragPos = dragPos;
8880
9325
  if (column.fixed ||
@@ -9395,17 +9840,19 @@ export default defineComponent({
9395
9840
  */
9396
9841
  scrollToTreeRow(row) {
9397
9842
  const { treeConfig } = props;
9843
+ const { isRowGroupStatus } = reactData;
9398
9844
  const { tableFullData } = internalData;
9399
9845
  const rests = [];
9400
- if (treeConfig) {
9846
+ if (treeConfig || isRowGroupStatus) {
9847
+ const rowGroupOpts = computeRowGroupOpts.value;
9401
9848
  const treeOpts = computeTreeOpts.value;
9402
9849
  const childrenField = treeOpts.children || treeOpts.childrenField;
9403
- const matchObj = XEUtils.findTree(tableFullData, item => $xeTable.eqRow(item, row), { children: childrenField });
9850
+ const matchObj = XEUtils.findTree(tableFullData, item => $xeTable.eqRow(item, row), { children: isRowGroupStatus ? rowGroupOpts.mapChildrenField : childrenField });
9404
9851
  if (matchObj) {
9405
9852
  const nodes = matchObj.nodes;
9406
9853
  nodes.forEach((row, index) => {
9407
- if (index < nodes.length - 1 && !tableMethods.isTreeExpandByRow(row)) {
9408
- rests.push(tableMethods.setTreeExpand(row, true));
9854
+ if (index < nodes.length - 1 && !$xeTable.isTreeExpandByRow(row)) {
9855
+ rests.push($xeTable.setTreeExpand(row, true));
9409
9856
  }
9410
9857
  });
9411
9858
  }
@@ -9825,7 +10272,7 @@ export default defineComponent({
9825
10272
  };
9826
10273
  const renderRowExpandedVNs = () => {
9827
10274
  const { treeConfig } = props;
9828
- const { expandColumn } = reactData;
10275
+ const { expandColumn, isRowGroupStatus } = reactData;
9829
10276
  const tableRowExpandedList = computeTableRowExpandedList.value;
9830
10277
  const expandOpts = computeExpandOpts.value;
9831
10278
  const { mode } = expandOpts;
@@ -9842,13 +10289,15 @@ export default defineComponent({
9842
10289
  const { handleGetRowId } = createHandleGetRowId($xeTable);
9843
10290
  tableRowExpandedList.forEach((row) => {
9844
10291
  const expandOpts = computeExpandOpts.value;
9845
- const { height: expandHeight, padding } = expandOpts;
9846
- const { fullAllDataRowIdData } = internalData;
10292
+ const { height: expandHeight, padding, indent } = expandOpts;
10293
+ const { fullAllDataRowIdData, fullColumnIdData } = internalData;
9847
10294
  const treeOpts = computeTreeOpts.value;
9848
10295
  const { transform, seqMode } = treeOpts;
9849
10296
  const cellStyle = {};
9850
10297
  const rowid = handleGetRowId(row);
9851
10298
  const rowRest = fullAllDataRowIdData[rowid];
10299
+ const colid = expandColumn.id;
10300
+ const colRest = fullColumnIdData[colid] || {};
9852
10301
  let rowLevel = 0;
9853
10302
  let seq = -1;
9854
10303
  let _rowIndex = -1;
@@ -9856,7 +10305,7 @@ export default defineComponent({
9856
10305
  let $rowIndex = -1;
9857
10306
  if (rowRest) {
9858
10307
  rowLevel = rowRest.level;
9859
- if (treeConfig && transform && seqMode === 'increasing') {
10308
+ if (isRowGroupStatus || (treeConfig && transform && seqMode === 'increasing')) {
9860
10309
  seq = rowRest._index + 1;
9861
10310
  }
9862
10311
  else {
@@ -9869,10 +10318,39 @@ export default defineComponent({
9869
10318
  if (expandHeight) {
9870
10319
  cellStyle.height = `${expandHeight}px`;
9871
10320
  }
9872
- if (treeConfig) {
9873
- cellStyle.paddingLeft = `${(rowLevel * treeOpts.indent) + 30}px`;
10321
+ if (isRowGroupStatus || treeConfig) {
10322
+ cellStyle.paddingLeft = `${(rowLevel * (XEUtils.isNumber(indent) ? indent : treeOpts.indent)) + 30}px`;
9874
10323
  }
9875
- const expandParams = { $table: $xeTable, seq, column: expandColumn, fixed: '', type: 'body', level: rowLevel, row, rowIndex, $rowIndex, _rowIndex };
10324
+ let columnIndex = -1;
10325
+ let $columnIndex = -1;
10326
+ let _columnIndex = -1;
10327
+ if (colRest) {
10328
+ columnIndex = colRest.index;
10329
+ $columnIndex = colRest.$index;
10330
+ _columnIndex = colRest._index;
10331
+ }
10332
+ const expandParams = {
10333
+ $grid: $xeGrid,
10334
+ $table: $xeTable,
10335
+ seq,
10336
+ column: expandColumn,
10337
+ columnIndex,
10338
+ $columnIndex,
10339
+ _columnIndex,
10340
+ fixed: '',
10341
+ type: 'body',
10342
+ level: rowLevel,
10343
+ rowid,
10344
+ row,
10345
+ rowIndex,
10346
+ $rowIndex,
10347
+ _rowIndex,
10348
+ isHidden: false,
10349
+ isEdit: false,
10350
+ visibleData: [],
10351
+ data: [],
10352
+ items: []
10353
+ };
9876
10354
  expandVNs.push(h('div', {
9877
10355
  key: rowid,
9878
10356
  class: ['vxe-body--row-expanded-cell', {
@@ -10016,7 +10494,7 @@ export default defineComponent({
10016
10494
  };
10017
10495
  const renderVN = () => {
10018
10496
  const { loading, stripe, showHeader, height, treeConfig, mouseConfig, showFooter, highlightCell, highlightHoverRow, highlightHoverColumn, editConfig, editRules } = props;
10019
- const { isGroup, overflowX, overflowY, scrollXLoad, scrollYLoad, tableData, initStore, columnStore, filterStore, customStore } = reactData;
10497
+ const { isGroup, overflowX, overflowY, scrollXLoad, scrollYLoad, tableData, initStore, isRowGroupStatus, columnStore, filterStore, customStore } = reactData;
10020
10498
  const { leftList, rightList } = columnStore;
10021
10499
  const loadingSlot = slots.loading;
10022
10500
  const tableTipConfig = computeTableTipConfig.value;
@@ -10057,6 +10535,7 @@ export default defineComponent({
10057
10535
  'is--header': showHeader,
10058
10536
  'is--footer': showFooter,
10059
10537
  'is--group': isGroup,
10538
+ 'is-row-group': isRowGroupStatus,
10060
10539
  'is--tree-line': treeConfig && (treeOpts.showLine || treeOpts.line),
10061
10540
  'is--fixed-left': leftList.length,
10062
10541
  'is--fixed-right': rightList.length,
@@ -10427,6 +10906,9 @@ export default defineComponent({
10427
10906
  }
10428
10907
  });
10429
10908
  });
10909
+ watch(computeRowGroupFields, (val) => {
10910
+ handleUpdateRowGroup(val);
10911
+ });
10430
10912
  if ($xeTabs) {
10431
10913
  watch(() => $xeTabs ? $xeTabs.reactData.resizeFlag : null, () => {
10432
10914
  handleGlobalResizeEvent();
@@ -10455,9 +10937,12 @@ export default defineComponent({
10455
10937
  const columnOpts = computeColumnOpts.value;
10456
10938
  const rowOpts = computeRowOpts.value;
10457
10939
  const customOpts = computeCustomOpts.value;
10940
+ const rowGroupOpts = computeRowGroupOpts.value;
10941
+ const { groupFields } = rowGroupOpts;
10458
10942
  if (columnOpts.drag || rowOpts.drag || customOpts.allowSort) {
10459
10943
  initTpImg();
10460
10944
  }
10945
+ handleUpdateRowGroup(groupFields);
10461
10946
  nextTick(() => {
10462
10947
  const { data, exportConfig, importConfig, treeConfig, showOverflow, highlightCurrentRow, highlightCurrentColumn } = props;
10463
10948
  const { scrollXStore, scrollYStore } = internalData;
@@ -10473,8 +10958,6 @@ export default defineComponent({
10473
10958
  const importOpts = computeImportOpts.value;
10474
10959
  const currentRowOpts = computeCurrentRowOpts.value;
10475
10960
  const currentColumnOpts = computeCurrentColumnOpts.value;
10476
- const virtualXOpts = computeVirtualXOpts.value;
10477
- const virtualYOpts = computeVirtualYOpts.value;
10478
10961
  const keyboardOpts = computeKeyboardOpts.value;
10479
10962
  if (props.rowId) {
10480
10963
  warnLog('vxe.error.delProp', ['row-id', 'row-config.keyField']);
@@ -10597,19 +11080,19 @@ export default defineComponent({
10597
11080
  warnLog('vxe.error.notConflictProp', ['column-config.isCurrent', 'current-column-config.isFollowSelected']);
10598
11081
  }
10599
11082
  // 如果不支持虚拟滚动
10600
- if (props.spanMethod) {
10601
- if (virtualXOpts.enabled) {
10602
- warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-x-config.enabled=false']);
10603
- }
10604
- if (virtualYOpts.enabled) {
10605
- warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-y-config.enabled=false']);
10606
- }
10607
- }
10608
- if (props.footerSpanMethod) {
10609
- if (virtualXOpts.enabled) {
10610
- warnLog('vxe.error.notConflictProp', ['footer-span-method', 'virtual-x-config.enabled=false']);
10611
- }
10612
- }
11083
+ // if (props.spanMethod) {
11084
+ // if (virtualXOpts.enabled) {
11085
+ // warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-x-config.enabled=false'])
11086
+ // }
11087
+ // if (virtualYOpts.enabled) {
11088
+ // warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-y-config.enabled=false'])
11089
+ // }
11090
+ // }
11091
+ // if (props.footerSpanMethod) {
11092
+ // if (virtualXOpts.enabled) {
11093
+ // warnLog('vxe.error.notConflictProp', ['footer-span-method', 'virtual-x-config.enabled=false'])
11094
+ // }
11095
+ // }
10613
11096
  // 检查是否有安装需要的模块
10614
11097
  if (props.editConfig && !$xeTable.insert) {
10615
11098
  errLog('vxe.error.reqModule', ['Edit']);