vxe-table 4.13.5 → 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 +653 -171
  37. package/es/table/style.css +70 -40
  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 +70 -40
  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 +419 -179
  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 +134 -91
  122. package/lib/table/src/table.min.js +1 -1
  123. package/lib/table/style/style.css +70 -40
  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 +70 -40
  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 +658 -176
  166. package/packages/ui/index.ts +12 -0
  167. package/packages/ui/src/dom.ts +4 -0
  168. package/styles/components/table.scss +131 -92
  169. /package/es/{iconfont.1744880866629.ttf → iconfont.1745197925862.ttf} +0 -0
  170. /package/es/{iconfont.1744880866629.woff → iconfont.1745197925862.woff} +0 -0
  171. /package/es/{iconfont.1744880866629.woff2 → iconfont.1745197925862.woff2} +0 -0
  172. /package/lib/{iconfont.1744880866629.ttf → iconfont.1745197925862.ttf} +0 -0
  173. /package/lib/{iconfont.1744880866629.woff → iconfont.1745197925862.woff} +0 -0
  174. /package/lib/{iconfont.1744880866629.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) {
@@ -5220,7 +5517,7 @@ export default defineComponent({
5220
5517
  });
5221
5518
  if (isUpdate) {
5222
5519
  if (!remote) {
5223
- tablePrivateMethods.handleTableData(true);
5520
+ $xeTable.handleTableData(true);
5224
5521
  }
5225
5522
  $xeTable.handleColumnSortEvent(new Event('click'), firstColumn);
5226
5523
  }
@@ -5248,7 +5545,7 @@ export default defineComponent({
5248
5545
  clearAllSort();
5249
5546
  }
5250
5547
  if (!sortOpts.remote) {
5251
- tablePrivateMethods.handleTableData(true);
5548
+ $xeTable.handleTableData(true);
5252
5549
  }
5253
5550
  return nextTick().then(updateStyle);
5254
5551
  },
@@ -5394,8 +5691,8 @@ export default defineComponent({
5394
5691
  const expandOpts = computeExpandOpts.value;
5395
5692
  const { reserve, lazy, accordion, toggleMethod } = expandOpts;
5396
5693
  const lazyRests = [];
5397
- const columnIndex = $xeTable.getColumnIndex(expandColumn);
5398
- const $columnIndex = $xeTable.getVMColumnIndex(expandColumn);
5694
+ const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1;
5695
+ const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1;
5399
5696
  if (rows) {
5400
5697
  if (!XEUtils.isArray(rows)) {
5401
5698
  rows = [rows];
@@ -5499,6 +5796,70 @@ export default defineComponent({
5499
5796
  });
5500
5797
  return rest;
5501
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
+ },
5502
5863
  getTreeExpandRecords() {
5503
5864
  const rest = [];
5504
5865
  XEUtils.each(internalData.treeExpandedMaps, item => {
@@ -5542,11 +5903,11 @@ export default defineComponent({
5542
5903
  });
5543
5904
  }
5544
5905
  internalData.treeExpandedMaps = {};
5545
- reactData.treeExpandedFlag++;
5546
5906
  if (transform) {
5547
5907
  handleVirtualTreeToList();
5548
- return $xeTable.handleTableData();
5908
+ $xeTable.handleTableData();
5549
5909
  }
5910
+ reactData.treeExpandedFlag++;
5550
5911
  return nextTick();
5551
5912
  },
5552
5913
  /**
@@ -5560,15 +5921,16 @@ export default defineComponent({
5560
5921
  const { transform, lazy } = treeOpts;
5561
5922
  const rowid = getRowid($xeTable, row);
5562
5923
  if (lazy && row[hasChildField] && !treeExpandLazyLoadedMaps[rowid]) {
5563
- return tableMethods.clearTreeExpandLoaded(row).then(() => {
5924
+ return $xeTable.clearTreeExpandLoaded(row).then(() => {
5564
5925
  return handleAsyncTreeExpandChilds(row);
5565
5926
  }).then(() => {
5566
5927
  if (transform) {
5567
5928
  handleVirtualTreeToList();
5568
- return tablePrivateMethods.handleTableData();
5929
+ $xeTable.handleTableData();
5569
5930
  }
5931
+ reactData.treeExpandedFlag++;
5570
5932
  }).then(() => {
5571
- return tableMethods.recalculate();
5933
+ return $xeTable.recalculate();
5572
5934
  });
5573
5935
  }
5574
5936
  return nextTick();
@@ -5578,13 +5940,13 @@ export default defineComponent({
5578
5940
  warnLog('vxe.error.delFunc', ['reloadTreeChilds', 'reloadTreeExpand']);
5579
5941
  }
5580
5942
  // 即将废弃
5581
- return tableMethods.reloadTreeExpand(row);
5943
+ return $xeTable.reloadTreeExpand(row);
5582
5944
  },
5583
5945
  /**
5584
5946
  * 切换/展开树节点
5585
5947
  */
5586
5948
  toggleTreeExpand(row) {
5587
- return tableMethods.setTreeExpand(row, !tableMethods.isTreeExpandByRow(row));
5949
+ return $xeTable.setTreeExpand(row, !$xeTable.isTreeExpandByRow(row));
5588
5950
  },
5589
5951
  /**
5590
5952
  * 设置所有树节点的展开与否
@@ -5602,10 +5964,11 @@ export default defineComponent({
5602
5964
  expandeds.push(row);
5603
5965
  }
5604
5966
  }, { children: childrenField });
5605
- return tableMethods.setTreeExpand(expandeds, expanded).then(() => {
5967
+ return $xeTable.setTreeExpand(expandeds, expanded).then(() => {
5606
5968
  if (transform) {
5607
5969
  handleVirtualTreeToList();
5608
- return tableMethods.recalculate();
5970
+ reactData.treeExpandedFlag++;
5971
+ return $xeTable.recalculate();
5609
5972
  }
5610
5973
  });
5611
5974
  },
@@ -5654,15 +6017,15 @@ export default defineComponent({
5654
6017
  const { transform, reserve } = treeOpts;
5655
6018
  const expList = $xeTable.getTreeExpandRecords();
5656
6019
  internalData.treeExpandedMaps = {};
5657
- reactData.treeExpandedFlag++;
5658
6020
  if (reserve) {
5659
6021
  XEUtils.eachTree(tableFullTreeData, row => handleTreeExpandReserve(row, false), { children: childrenField });
5660
6022
  }
5661
6023
  return $xeTable.handleTableData().then(() => {
5662
6024
  if (transform) {
5663
6025
  handleVirtualTreeToList();
5664
- return $xeTable.handleTableData();
6026
+ $xeTable.handleTableData();
5665
6027
  }
6028
+ reactData.treeExpandedFlag++;
5666
6029
  }).then(() => {
5667
6030
  if (expList.length) {
5668
6031
  return $xeTable.recalculate();
@@ -5973,7 +6336,7 @@ export default defineComponent({
5973
6336
  hasResizable = 1;
5974
6337
  resizableData[colKey] = column.renderWidth;
5975
6338
  }
5976
- if (isCustomVisible && (!checkMethod || checkMethod({ column }))) {
6339
+ if (isCustomVisible && (!checkMethod || checkMethod({ $table: $xeTable, column }))) {
5977
6340
  if (!column.visible && column.defaultVisible) {
5978
6341
  hasVisible = 1;
5979
6342
  visibleData[colKey] = false;
@@ -6251,8 +6614,7 @@ export default defineComponent({
6251
6614
  const hasDeleteKey = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.DELETE);
6252
6615
  const isF2 = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.F2);
6253
6616
  const isContextMenu = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.CONTEXT_MENU);
6254
- const hasMetaKey = evnt.metaKey;
6255
- const hasCtrlKey = evnt.ctrlKey;
6617
+ const isControlKey = hasControlKey(evnt);
6256
6618
  const hasShiftKey = evnt.shiftKey;
6257
6619
  const isAltKey = evnt.altKey;
6258
6620
  const operArrow = isLeftArrow || isUpArrow || isRightArrow || isDwArrow;
@@ -6320,7 +6682,7 @@ export default defineComponent({
6320
6682
  else if (isEnter && !isAltKey && keyboardConfig && keyboardOpts.isEnter && (selected.row || actived.row || (treeConfig && (rowOpts.isCurrent || highlightCurrentRow) && currentRow))) {
6321
6683
  const { isLastEnterAppendRow, beforeEnterMethod, enterMethod } = keyboardOpts;
6322
6684
  // 退出选中
6323
- if (hasCtrlKey) {
6685
+ if (isControlKey) {
6324
6686
  // 如果是激活编辑状态,则取消编辑
6325
6687
  if (actived.row) {
6326
6688
  const params = actived.args;
@@ -6500,7 +6862,7 @@ export default defineComponent({
6500
6862
  .then(() => $xeTable.triggerCurrentRowEvent(evnt, params));
6501
6863
  }
6502
6864
  }
6503
- 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))) {
6504
6866
  const { editMode, editMethod } = keyboardOpts;
6505
6867
  // 启用编辑后,空格键功能将失效
6506
6868
  // if (isSpacebar) {
@@ -6646,9 +7008,11 @@ export default defineComponent({
6646
7008
  const rTooltipMethod = tooltipMethod || (dragConfig ? dragConfig.rowTooltipMethod : null);
6647
7009
  let tipContent = '';
6648
7010
  if (rTooltipMethod) {
6649
- tipContent = `${rTooltipMethod({
7011
+ const rtParams = {
7012
+ $table: $xeTable,
6650
7013
  row: dragRow
6651
- }) || ''}`;
7014
+ };
7015
+ tipContent = `${rTooltipMethod(rtParams) || ''}`;
6652
7016
  }
6653
7017
  else {
6654
7018
  tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || '']);
@@ -6684,9 +7048,11 @@ export default defineComponent({
6684
7048
  const { tooltipMethod } = columnDragOpts;
6685
7049
  let tipContent = '';
6686
7050
  if (tooltipMethod) {
6687
- tipContent = `${tooltipMethod({
7051
+ const dtParams = {
7052
+ $table: $xeTable,
6688
7053
  column: dragCol
6689
- }) || ''}`;
7054
+ };
7055
+ tipContent = `${tooltipMethod(dtParams) || ''}`;
6690
7056
  }
6691
7057
  else {
6692
7058
  tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || '']);
@@ -6968,11 +7334,8 @@ export default defineComponent({
6968
7334
  */
6969
7335
  cacheRowMap(isReset) {
6970
7336
  const { treeConfig } = props;
6971
- const { fullAllDataRowIdData, tableFullData, tableFullTreeData, treeExpandedMaps } = internalData;
6972
- const treeOpts = computeTreeOpts.value;
6973
- const childrenField = treeOpts.children || treeOpts.childrenField;
6974
- const hasChildField = treeOpts.hasChild || treeOpts.hasChildField;
6975
- const { lazy } = treeOpts;
7337
+ const { isRowGroupStatus } = reactData;
7338
+ const { fullAllDataRowIdData, tableFullData, tableFullTreeData, tableFullGroupData, treeExpandedMaps } = internalData;
6976
7339
  const fullAllDataRowIdMaps = isReset ? {} : Object.assign({}, fullAllDataRowIdData); // 存在已删除数据
6977
7340
  const fullDataRowIdMaps = {};
6978
7341
  const { handleUpdateRowId } = createHandleUpdateRowId($xeTable);
@@ -6995,6 +7358,10 @@ export default defineComponent({
6995
7358
  fullAllDataRowIdMaps[rowid] = rowRest;
6996
7359
  };
6997
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;
6998
7365
  XEUtils.eachTree(tableFullTreeData, (row, index, items, path, parentRow, nodes) => {
6999
7366
  const rowid = handleUpdateRowId(row);
7000
7367
  if (treeConfig && lazy) {
@@ -7010,6 +7377,14 @@ export default defineComponent({
7010
7377
  handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path));
7011
7378
  }, { children: childrenField });
7012
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
+ }
7013
7388
  else {
7014
7389
  tableFullData.forEach((row, index, items) => {
7015
7390
  handleRowCache(row, index, items, index, null, handleUpdateRowId(row), 0, index + 1);
@@ -7446,6 +7821,7 @@ export default defineComponent({
7446
7821
  : tableMethods.getCustomStoreData();
7447
7822
  if (updateStore) {
7448
7823
  return updateStore({
7824
+ $table: $xeTable,
7449
7825
  id: tableId,
7450
7826
  type,
7451
7827
  storeData
@@ -7516,29 +7892,46 @@ export default defineComponent({
7516
7892
  },
7517
7893
  updateCheckboxStatus() {
7518
7894
  const { treeConfig } = props;
7519
- const { selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
7895
+ const { isRowGroupStatus } = reactData;
7896
+ const { afterTreeFullData, afterGroupFullData, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
7897
+ const rowGroupOpts = computeRowGroupOpts.value;
7520
7898
  const treeOpts = computeTreeOpts.value;
7521
- const { transform, mapChildrenField } = treeOpts;
7522
7899
  const childrenField = treeOpts.children || treeOpts.childrenField;
7523
7900
  const checkboxOpts = computeCheckboxOpts.value;
7524
7901
  const { checkField, checkStrictly, checkMethod } = checkboxOpts;
7525
- const { afterTreeFullData } = internalData;
7526
7902
  if (checkStrictly) {
7527
7903
  return;
7528
7904
  }
7529
- // 树结构
7530
- if (treeConfig) {
7905
+ if (isRowGroupStatus || treeConfig) {
7531
7906
  const { handleGetRowId } = createHandleGetRowId($xeTable);
7532
7907
  const childRowMaps = {};
7533
7908
  const childRowList = [];
7534
- XEUtils.eachTree(afterTreeFullData, (row) => {
7535
- const rowid = handleGetRowId(row);
7536
- const childList = row[transform ? mapChildrenField : childrenField];
7537
- if (childList && childList.length && !childRowMaps[rowid]) {
7538
- childRowMaps[rowid] = 1;
7539
- 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 });
7540
7921
  }
7541
- }, { 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
+ }
7542
7935
  childRowList.forEach(vals => {
7543
7936
  const row = vals[0];
7544
7937
  const rowid = vals[1];
@@ -7550,7 +7943,7 @@ export default defineComponent({
7550
7943
  ? (item) => {
7551
7944
  const childRowid = handleGetRowId(item);
7552
7945
  const isSelect = checkField ? XEUtils.get(item, checkField) : selectCheckboxMaps[childRowid];
7553
- if (checkMethod({ row: item })) {
7946
+ if (checkMethod({ $table: $xeTable, row: item })) {
7554
7947
  if (isSelect) {
7555
7948
  sLen++;
7556
7949
  }
@@ -7613,19 +8006,20 @@ export default defineComponent({
7613
8006
  },
7614
8007
  updateAllCheckboxStatus() {
7615
8008
  const { treeConfig } = props;
7616
- const { afterFullData, afterTreeFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
8009
+ const { isRowGroupStatus } = reactData;
8010
+ const { afterFullData, afterTreeFullData, afterGroupFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData;
7617
8011
  const checkboxOpts = computeCheckboxOpts.value;
7618
8012
  const { checkField, checkMethod, showReserveStatus } = checkboxOpts;
7619
8013
  const { handleGetRowId } = createHandleGetRowId($xeTable);
7620
8014
  let sLen = 0; // 已选
7621
8015
  let hLen = 0; // 半选
7622
8016
  let vLen = 0; // 有效行
7623
- const rootList = (treeConfig ? afterTreeFullData : afterFullData);
8017
+ const rootList = (treeConfig ? afterTreeFullData : (isRowGroupStatus ? afterGroupFullData : afterFullData));
7624
8018
  rootList.forEach(checkMethod
7625
8019
  ? row => {
7626
8020
  const childRowid = handleGetRowId(row);
7627
8021
  const selected = checkField ? XEUtils.get(row, checkField) : selectCheckboxMaps[childRowid];
7628
- if (checkMethod({ row })) {
8022
+ if (checkMethod({ $table: $xeTable, row })) {
7629
8023
  if (selected) {
7630
8024
  sLen++;
7631
8025
  }
@@ -7673,7 +8067,9 @@ export default defineComponent({
7673
8067
  */
7674
8068
  handleBatchSelectRows(rows, checked, isForce) {
7675
8069
  const { treeConfig } = props;
8070
+ const { isRowGroupStatus } = reactData;
7676
8071
  const { selectCheckboxMaps } = internalData;
8072
+ const rowGroupOpts = computeRowGroupOpts.value;
7677
8073
  const treeOpts = computeTreeOpts.value;
7678
8074
  const { transform, mapChildrenField } = treeOpts;
7679
8075
  const childrenField = treeOpts.children || treeOpts.childrenField;
@@ -7684,10 +8080,10 @@ export default defineComponent({
7684
8080
  const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField;
7685
8081
  if (checkField) {
7686
8082
  // 树结构
7687
- if (treeConfig && !checkStrictly) {
8083
+ if ((treeConfig || isRowGroupStatus) && !checkStrictly) {
7688
8084
  // 更新子节点状态
7689
8085
  XEUtils.eachTree(rows, (row) => {
7690
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8086
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7691
8087
  XEUtils.set(row, checkField, checked);
7692
8088
  if (indeterminateField) {
7693
8089
  XEUtils.set(row, indeterminateField, false);
@@ -7700,7 +8096,7 @@ export default defineComponent({
7700
8096
  }
7701
8097
  // 列表
7702
8098
  rows.forEach(row => {
7703
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8099
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7704
8100
  XEUtils.set(row, checkField, checked);
7705
8101
  handleCheckboxReserveRow(row, checked);
7706
8102
  }
@@ -7709,29 +8105,50 @@ export default defineComponent({
7709
8105
  return;
7710
8106
  }
7711
8107
  // 树结构
7712
- if (treeConfig && !checkStrictly) {
7713
- // 更新子节点状态
7714
- XEUtils.eachTree(rows, (row) => {
7715
- const rowid = handleGetRowId(row);
7716
- if (isForce || (!checkMethod || checkMethod({ row }))) {
7717
- if (checked) {
7718
- 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);
7719
8123
  }
7720
- else {
7721
- if (selectCheckboxMaps[rowid]) {
7722
- 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
+ }
7723
8140
  }
8141
+ handleCheckboxReserveRow(row, checked);
7724
8142
  }
7725
- handleCheckboxReserveRow(row, checked);
7726
- }
7727
- }, { children: transform ? mapChildrenField : childrenField });
7728
- reactData.updateCheckboxFlag++;
7729
- return;
8143
+ }, { children: transform ? mapChildrenField : childrenField });
8144
+ reactData.updateCheckboxFlag++;
8145
+ return;
8146
+ }
7730
8147
  }
7731
8148
  // 列表
7732
8149
  rows.forEach(row => {
7733
8150
  const rowid = handleGetRowId(row);
7734
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8151
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7735
8152
  if (checked) {
7736
8153
  if (!selectCheckboxMaps[rowid]) {
7737
8154
  selectCheckboxMaps[rowid] = row;
@@ -7904,20 +8321,22 @@ export default defineComponent({
7904
8321
  const radioOpts = computeRadioOpts.value;
7905
8322
  const checkboxOpts = computeCheckboxOpts.value;
7906
8323
  const keyboardOpts = computeKeyboardOpts.value;
8324
+ const rowGroupOpts = computeRowGroupOpts.value;
7907
8325
  const rowOpts = computeRowOpts.value;
7908
8326
  const columnOpts = computeColumnOpts.value;
7909
8327
  const currentColumnOpts = computeCurrentColumnOpts.value;
7910
8328
  const { actived, focused } = editStore;
7911
8329
  const { row, column } = params;
7912
- const { type, treeNode } = column;
8330
+ const { type, treeNode, rowGroupNode } = column;
7913
8331
  const isRadioType = type === 'radio';
7914
8332
  const isCheckboxType = type === 'checkbox';
7915
8333
  const isExpandType = type === 'expand';
7916
8334
  const cell = evnt.currentTarget;
7917
8335
  const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag;
7918
8336
  const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag;
7919
- const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag;
8337
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag;
7920
8338
  const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag;
8339
+ const triggerRowGroupNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-row-group--node-btn').flag;
7921
8340
  params = Object.assign({ cell, triggerRadio, triggerCheckbox, triggerTreeNode, triggerExpandNode }, params);
7922
8341
  if (!triggerCheckbox && !triggerRadio) {
7923
8342
  // 如果是展开行
@@ -7928,10 +8347,14 @@ export default defineComponent({
7928
8347
  if ((treeOpts.trigger === 'row' || (treeNode && treeOpts.trigger === 'cell'))) {
7929
8348
  $xeTable.triggerTreeExpandEvent(evnt, params);
7930
8349
  }
8350
+ // 如果是行分组
8351
+ if ((rowGroupOpts.trigger === 'row' || (rowGroupNode && rowGroupOpts.trigger === 'cell'))) {
8352
+ $xeTable.triggerRowGroupExpandEvent(evnt, params);
8353
+ }
7931
8354
  }
7932
8355
  // 如果点击了树节点
7933
8356
  if (!triggerTreeNode) {
7934
- if (!triggerExpandNode) {
8357
+ if (!triggerExpandNode && !triggerRowGroupNode) {
7935
8358
  // 如果是当前行
7936
8359
  if (rowOpts.isCurrent || highlightCurrentRow) {
7937
8360
  if (!triggerCheckbox && !triggerRadio) {
@@ -8052,7 +8475,9 @@ export default defineComponent({
8052
8475
  }
8053
8476
  },
8054
8477
  triggerCheckRowEvent(evnt, params, checked) {
8478
+ const { treeConfig } = props;
8055
8479
  const { row } = params;
8480
+ const { isRowGroupStatus } = reactData;
8056
8481
  const { afterFullData } = internalData;
8057
8482
  const checkboxOpts = computeCheckboxOpts.value;
8058
8483
  const { checkMethod, trigger } = checkboxOpts;
@@ -8060,7 +8485,7 @@ export default defineComponent({
8060
8485
  return;
8061
8486
  }
8062
8487
  evnt.stopPropagation();
8063
- if (checkboxOpts.isShiftKey && evnt.shiftKey && !props.treeConfig) {
8488
+ if (checkboxOpts.isShiftKey && evnt.shiftKey && !(treeConfig || isRowGroupStatus)) {
8064
8489
  const checkboxRecords = $xeTable.getCheckboxRecords();
8065
8490
  if (checkboxRecords.length) {
8066
8491
  const firstRow = checkboxRecords[0];
@@ -8077,7 +8502,7 @@ export default defineComponent({
8077
8502
  }
8078
8503
  }
8079
8504
  }
8080
- if (!checkMethod || checkMethod({ row })) {
8505
+ if (!checkMethod || checkMethod({ $table: $xeTable, row })) {
8081
8506
  $xeTable.handleBatchSelectRows([row], checked);
8082
8507
  $xeTable.checkSelectionStatus();
8083
8508
  dispatchEvent('checkbox-change', Object.assign({
@@ -8178,7 +8603,7 @@ export default defineComponent({
8178
8603
  * 展开行事件
8179
8604
  */
8180
8605
  triggerRowExpandEvent(evnt, params) {
8181
- const { expandColumn: column } = reactData;
8606
+ const { expandColumn } = reactData;
8182
8607
  const { rowExpandLazyLoadedMaps } = internalData;
8183
8608
  const expandOpts = computeExpandOpts.value;
8184
8609
  const { row } = params;
@@ -8190,12 +8615,12 @@ export default defineComponent({
8190
8615
  const rowid = getRowid($xeTable, row);
8191
8616
  if (!lazy || !rowExpandLazyLoadedMaps[rowid]) {
8192
8617
  const expanded = !$xeTable.isRowExpandByRow(row);
8193
- const columnIndex = $xeTable.getColumnIndex(column);
8194
- const $columnIndex = $xeTable.getVMColumnIndex(column);
8618
+ const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1;
8619
+ const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1;
8195
8620
  $xeTable.setRowExpand(row, expanded);
8196
8621
  dispatchEvent('toggle-row-expand', {
8197
8622
  expanded,
8198
- column,
8623
+ column: expandColumn,
8199
8624
  columnIndex,
8200
8625
  $columnIndex,
8201
8626
  row,
@@ -8204,6 +8629,25 @@ export default defineComponent({
8204
8629
  }, evnt);
8205
8630
  }
8206
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
+ },
8207
8651
  /**
8208
8652
  * 展开树节点事件
8209
8653
  */
@@ -8340,7 +8784,7 @@ export default defineComponent({
8340
8784
  const triggerInput = cell && cell.tagName && cell.tagName.toLowerCase() === 'input';
8341
8785
  const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag;
8342
8786
  const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag;
8343
- const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag;
8787
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag;
8344
8788
  const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag;
8345
8789
  let isColDragCell = false;
8346
8790
  if (rowOpts.drag) {
@@ -8601,7 +9045,7 @@ export default defineComponent({
8601
9045
  evnt.preventDefault();
8602
9046
  return;
8603
9047
  }
8604
- const hasCtrlKey = evnt.ctrlKey;
9048
+ const isControlKey = hasControlKey(evnt);
8605
9049
  const trEl = evnt.currentTarget;
8606
9050
  const rowid = trEl.getAttribute('rowid') || '';
8607
9051
  const rest = fullAllDataRowIdData[rowid];
@@ -8613,11 +9057,11 @@ export default defineComponent({
8613
9057
  const { dragRow } = reactData;
8614
9058
  const offsetY = evnt.clientY - trEl.getBoundingClientRect().y;
8615
9059
  const dragPos = offsetY < trEl.clientHeight / 2 ? 'top' : 'bottom';
8616
- internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && hasCtrlKey);
9060
+ internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && isControlKey);
8617
9061
  internalData.prevDragRow = row;
8618
9062
  internalData.prevDragPos = dragPos;
8619
9063
  if ($xeTable.eqRow(dragRow, row) ||
8620
- (hasCtrlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
9064
+ (isControlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
8621
9065
  (!isCrossDrag && treeConfig && transform && (isPeerDrag ? dragRow[parentField] !== row[parentField] : rest.level))) {
8622
9066
  showDropTip(evnt, trEl, null, false, dragPos);
8623
9067
  return;
@@ -8866,7 +9310,7 @@ export default defineComponent({
8866
9310
  evnt.preventDefault();
8867
9311
  return;
8868
9312
  }
8869
- const hasCtrlKey = evnt.ctrlKey;
9313
+ const isControlKey = hasControlKey(evnt);
8870
9314
  const thEl = evnt.currentTarget;
8871
9315
  const colid = thEl.getAttribute('colid');
8872
9316
  const column = $xeTable.getColumnById(colid);
@@ -8875,7 +9319,7 @@ export default defineComponent({
8875
9319
  const { clientX } = evnt;
8876
9320
  const offsetX = clientX - thEl.getBoundingClientRect().x;
8877
9321
  const dragPos = offsetX < thEl.clientWidth / 2 ? 'left' : 'right';
8878
- internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && hasCtrlKey);
9322
+ internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && isControlKey);
8879
9323
  internalData.prevDragCol = column;
8880
9324
  internalData.prevDragPos = dragPos;
8881
9325
  if (column.fixed ||
@@ -9396,17 +9840,19 @@ export default defineComponent({
9396
9840
  */
9397
9841
  scrollToTreeRow(row) {
9398
9842
  const { treeConfig } = props;
9843
+ const { isRowGroupStatus } = reactData;
9399
9844
  const { tableFullData } = internalData;
9400
9845
  const rests = [];
9401
- if (treeConfig) {
9846
+ if (treeConfig || isRowGroupStatus) {
9847
+ const rowGroupOpts = computeRowGroupOpts.value;
9402
9848
  const treeOpts = computeTreeOpts.value;
9403
9849
  const childrenField = treeOpts.children || treeOpts.childrenField;
9404
- 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 });
9405
9851
  if (matchObj) {
9406
9852
  const nodes = matchObj.nodes;
9407
9853
  nodes.forEach((row, index) => {
9408
- if (index < nodes.length - 1 && !tableMethods.isTreeExpandByRow(row)) {
9409
- rests.push(tableMethods.setTreeExpand(row, true));
9854
+ if (index < nodes.length - 1 && !$xeTable.isTreeExpandByRow(row)) {
9855
+ rests.push($xeTable.setTreeExpand(row, true));
9410
9856
  }
9411
9857
  });
9412
9858
  }
@@ -9826,7 +10272,7 @@ export default defineComponent({
9826
10272
  };
9827
10273
  const renderRowExpandedVNs = () => {
9828
10274
  const { treeConfig } = props;
9829
- const { expandColumn } = reactData;
10275
+ const { expandColumn, isRowGroupStatus } = reactData;
9830
10276
  const tableRowExpandedList = computeTableRowExpandedList.value;
9831
10277
  const expandOpts = computeExpandOpts.value;
9832
10278
  const { mode } = expandOpts;
@@ -9843,13 +10289,15 @@ export default defineComponent({
9843
10289
  const { handleGetRowId } = createHandleGetRowId($xeTable);
9844
10290
  tableRowExpandedList.forEach((row) => {
9845
10291
  const expandOpts = computeExpandOpts.value;
9846
- const { height: expandHeight, padding } = expandOpts;
9847
- const { fullAllDataRowIdData } = internalData;
10292
+ const { height: expandHeight, padding, indent } = expandOpts;
10293
+ const { fullAllDataRowIdData, fullColumnIdData } = internalData;
9848
10294
  const treeOpts = computeTreeOpts.value;
9849
10295
  const { transform, seqMode } = treeOpts;
9850
10296
  const cellStyle = {};
9851
10297
  const rowid = handleGetRowId(row);
9852
10298
  const rowRest = fullAllDataRowIdData[rowid];
10299
+ const colid = expandColumn.id;
10300
+ const colRest = fullColumnIdData[colid] || {};
9853
10301
  let rowLevel = 0;
9854
10302
  let seq = -1;
9855
10303
  let _rowIndex = -1;
@@ -9857,7 +10305,7 @@ export default defineComponent({
9857
10305
  let $rowIndex = -1;
9858
10306
  if (rowRest) {
9859
10307
  rowLevel = rowRest.level;
9860
- if (treeConfig && transform && seqMode === 'increasing') {
10308
+ if (isRowGroupStatus || (treeConfig && transform && seqMode === 'increasing')) {
9861
10309
  seq = rowRest._index + 1;
9862
10310
  }
9863
10311
  else {
@@ -9870,10 +10318,39 @@ export default defineComponent({
9870
10318
  if (expandHeight) {
9871
10319
  cellStyle.height = `${expandHeight}px`;
9872
10320
  }
9873
- if (treeConfig) {
9874
- cellStyle.paddingLeft = `${(rowLevel * treeOpts.indent) + 30}px`;
10321
+ if (isRowGroupStatus || treeConfig) {
10322
+ cellStyle.paddingLeft = `${(rowLevel * (XEUtils.isNumber(indent) ? indent : treeOpts.indent)) + 30}px`;
9875
10323
  }
9876
- 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
+ };
9877
10354
  expandVNs.push(h('div', {
9878
10355
  key: rowid,
9879
10356
  class: ['vxe-body--row-expanded-cell', {
@@ -10017,7 +10494,7 @@ export default defineComponent({
10017
10494
  };
10018
10495
  const renderVN = () => {
10019
10496
  const { loading, stripe, showHeader, height, treeConfig, mouseConfig, showFooter, highlightCell, highlightHoverRow, highlightHoverColumn, editConfig, editRules } = props;
10020
- 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;
10021
10498
  const { leftList, rightList } = columnStore;
10022
10499
  const loadingSlot = slots.loading;
10023
10500
  const tableTipConfig = computeTableTipConfig.value;
@@ -10058,6 +10535,7 @@ export default defineComponent({
10058
10535
  'is--header': showHeader,
10059
10536
  'is--footer': showFooter,
10060
10537
  'is--group': isGroup,
10538
+ 'is-row-group': isRowGroupStatus,
10061
10539
  'is--tree-line': treeConfig && (treeOpts.showLine || treeOpts.line),
10062
10540
  'is--fixed-left': leftList.length,
10063
10541
  'is--fixed-right': rightList.length,
@@ -10428,6 +10906,9 @@ export default defineComponent({
10428
10906
  }
10429
10907
  });
10430
10908
  });
10909
+ watch(computeRowGroupFields, (val) => {
10910
+ handleUpdateRowGroup(val);
10911
+ });
10431
10912
  if ($xeTabs) {
10432
10913
  watch(() => $xeTabs ? $xeTabs.reactData.resizeFlag : null, () => {
10433
10914
  handleGlobalResizeEvent();
@@ -10456,9 +10937,12 @@ export default defineComponent({
10456
10937
  const columnOpts = computeColumnOpts.value;
10457
10938
  const rowOpts = computeRowOpts.value;
10458
10939
  const customOpts = computeCustomOpts.value;
10940
+ const rowGroupOpts = computeRowGroupOpts.value;
10941
+ const { groupFields } = rowGroupOpts;
10459
10942
  if (columnOpts.drag || rowOpts.drag || customOpts.allowSort) {
10460
10943
  initTpImg();
10461
10944
  }
10945
+ handleUpdateRowGroup(groupFields);
10462
10946
  nextTick(() => {
10463
10947
  const { data, exportConfig, importConfig, treeConfig, showOverflow, highlightCurrentRow, highlightCurrentColumn } = props;
10464
10948
  const { scrollXStore, scrollYStore } = internalData;
@@ -10474,8 +10958,6 @@ export default defineComponent({
10474
10958
  const importOpts = computeImportOpts.value;
10475
10959
  const currentRowOpts = computeCurrentRowOpts.value;
10476
10960
  const currentColumnOpts = computeCurrentColumnOpts.value;
10477
- const virtualXOpts = computeVirtualXOpts.value;
10478
- const virtualYOpts = computeVirtualYOpts.value;
10479
10961
  const keyboardOpts = computeKeyboardOpts.value;
10480
10962
  if (props.rowId) {
10481
10963
  warnLog('vxe.error.delProp', ['row-id', 'row-config.keyField']);
@@ -10598,19 +11080,19 @@ export default defineComponent({
10598
11080
  warnLog('vxe.error.notConflictProp', ['column-config.isCurrent', 'current-column-config.isFollowSelected']);
10599
11081
  }
10600
11082
  // 如果不支持虚拟滚动
10601
- if (props.spanMethod) {
10602
- if (virtualXOpts.enabled) {
10603
- warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-x-config.enabled=false']);
10604
- }
10605
- if (virtualYOpts.enabled) {
10606
- warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-y-config.enabled=false']);
10607
- }
10608
- }
10609
- if (props.footerSpanMethod) {
10610
- if (virtualXOpts.enabled) {
10611
- warnLog('vxe.error.notConflictProp', ['footer-span-method', 'virtual-x-config.enabled=false']);
10612
- }
10613
- }
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
+ // }
10614
11096
  // 检查是否有安装需要的模块
10615
11097
  if (props.editConfig && !$xeTable.insert) {
10616
11098
  errLog('vxe.error.reqModule', ['Edit']);