vxe-table 4.13.5 → 4.13.7

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 +659 -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 +664 -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.1745290253213.ttf} +0 -0
  170. /package/es/{iconfont.1744880866629.woff → iconfont.1745290253213.woff} +0 -0
  171. /package/es/{iconfont.1744880866629.woff2 → iconfont.1745290253213.woff2} +0 -0
  172. /package/lib/{iconfont.1744880866629.ttf → iconfont.1745290253213.ttf} +0 -0
  173. /package/lib/{iconfont.1744880866629.woff → iconfont.1745290253213.woff} +0 -0
  174. /package/lib/{iconfont.1744880866629.woff2 → iconfont.1745290253213.woff2} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, h, ComponentPublicInstance, reactive, ref, 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'
@@ -89,6 +89,8 @@ export default defineComponent({
89
89
  selectRadioRow: null,
90
90
  // 表尾合计数据
91
91
  footerTableData: [],
92
+ // 行分组列信息
93
+ rowGroupColumn: null,
92
94
  // 展开列信息
93
95
  expandColumn: null,
94
96
  // 树节点列信息
@@ -241,6 +243,12 @@ export default defineComponent({
241
243
  isFooter: false
242
244
  },
243
245
 
246
+ visiblwRowsFlag: 1,
247
+
248
+ isRowGroupStatus: false,
249
+ rowGroupList: [],
250
+
251
+ rowGroupExpandedFlag: 1,
244
252
  rowExpandedFlag: 1,
245
253
  treeExpandedFlag: 1,
246
254
  updateCheckboxFlag: 1,
@@ -337,10 +345,13 @@ export default defineComponent({
337
345
  tableFullData: [],
338
346
  afterFullData: [],
339
347
  afterTreeFullData: [],
348
+ afterGroupFullData: [],
340
349
  // 列表条件处理后数据集合
341
350
  afterFullRowMaps: {},
342
351
  // 树结构完整数据、条件处理后
343
352
  tableFullTreeData: [],
353
+ // 行分组全量数据、条件处理后
354
+ tableFullGroupData: [],
344
355
  tableSynchData: [],
345
356
  tableSourceData: [],
346
357
  // 收集的列配置(带分组)
@@ -374,6 +385,8 @@ export default defineComponent({
374
385
  rowExpandedMaps: {},
375
386
  // 懒加载中的展开行的集合
376
387
  rowExpandLazyLoadedMaps: {},
388
+ // 已展开的分组行
389
+ rowGroupExpandedMaps: {},
377
390
  // 已展开树节点集合
378
391
  treeExpandedMaps: {},
379
392
  // 懒加载中的树节点的集合
@@ -562,6 +575,10 @@ export default defineComponent({
562
575
  return Object.assign({}, getConfig().table.rowConfig, props.rowConfig)
563
576
  })
564
577
 
578
+ const computeRowGroupOpts = computed(() => {
579
+ return Object.assign({}, getConfig().table.rowGroupConfig, props.rowGroupConfig)
580
+ })
581
+
565
582
  const computeCurrentRowOpts = computed(() => {
566
583
  return Object.assign({}, getConfig().table.currentRowConfig, props.currentRowConfig)
567
584
  })
@@ -742,20 +759,21 @@ export default defineComponent({
742
759
 
743
760
  const computeTableRowExpandedList = computed(() => {
744
761
  const { treeConfig } = props
745
- const { rowExpandedFlag, expandColumn } = reactData
762
+ const { rowExpandedFlag, expandColumn, rowGroupExpandedFlag, treeExpandedFlag, isRowGroupStatus } = reactData
746
763
  const { visibleDataRowIdData, rowExpandedMaps } = internalData
747
764
  const treeOpts = computeTreeOpts.value
748
765
  const { transform } = treeOpts
749
766
  const expandList: any[] = []
750
- if (expandColumn && rowExpandedFlag) {
751
- if (treeConfig && !transform) {
767
+ if (expandColumn && rowExpandedFlag && rowGroupExpandedFlag && treeExpandedFlag) {
768
+ if (isRowGroupStatus || (treeConfig && transform)) {
769
+ XEUtils.each(rowExpandedMaps, (row, rowid) => {
770
+ if (visibleDataRowIdData[rowid]) {
771
+ expandList.push(row)
772
+ }
773
+ })
774
+ } else {
752
775
  return XEUtils.values(rowExpandedMaps)
753
776
  }
754
- XEUtils.each(rowExpandedMaps, (row, rowid) => {
755
- if (visibleDataRowIdData[rowid]) {
756
- expandList.push(row)
757
- }
758
- })
759
777
  }
760
778
  return expandList
761
779
  })
@@ -815,7 +833,7 @@ export default defineComponent({
815
833
  // 暂时不支持树形结构
816
834
  }
817
835
  // 如果所有行都被禁用
818
- return tableFullData.every((row) => !checkMethod({ row }))
836
+ return tableFullData.every((row) => !checkMethod({ $table: $xeTable, row }))
819
837
  }
820
838
  return false
821
839
  }
@@ -832,6 +850,11 @@ export default defineComponent({
832
850
  }
833
851
  })
834
852
 
853
+ const computeRowGroupFields = computed(() => {
854
+ const rowGroupOpts = computeRowGroupOpts.value
855
+ return rowGroupOpts.groupFields
856
+ })
857
+
835
858
  const refMaps: VxeTablePrivateRef = {
836
859
  refElem,
837
860
  refTooltip,
@@ -879,6 +902,7 @@ export default defineComponent({
879
902
  computeHeaderCellOpts,
880
903
  computeFooterCellOpts,
881
904
  computeRowOpts,
905
+ computeRowGroupOpts,
882
906
  computeCurrentRowOpts,
883
907
  computeRowDragOpts,
884
908
  computeColumnDragOpts,
@@ -1388,7 +1412,7 @@ export default defineComponent({
1388
1412
  const storeData: VxeTableDefines.CustomStoreData = getCustomStorageMap(tableId)
1389
1413
  if (restoreStore) {
1390
1414
  return Promise.resolve(
1391
- restoreStore({ id: tableId, type: 'restore', storeData })
1415
+ restoreStore({ $table: $xeTable, id: tableId, type: 'restore', storeData })
1392
1416
  ).then(storeData => {
1393
1417
  if (!storeData) {
1394
1418
  return
@@ -1420,6 +1444,7 @@ export default defineComponent({
1420
1444
  const rowOpts = computeRowOpts.value
1421
1445
  const isGroup = collectColumn.some(hasChildrenList)
1422
1446
  let isAllOverflow = !!props.showOverflow
1447
+ let rowGroupColumn: VxeTableDefines.ColumnInfo | undefined
1423
1448
  let expandColumn: VxeTableDefines.ColumnInfo | undefined
1424
1449
  let treeNodeColumn: VxeTableDefines.ColumnInfo | undefined
1425
1450
  let checkboxColumn: VxeTableDefines.ColumnInfo | undefined
@@ -1427,7 +1452,7 @@ export default defineComponent({
1427
1452
  let htmlColumn: VxeTableDefines.ColumnInfo | undefined
1428
1453
  let hasFixed: VxeColumnPropTypes.Fixed | undefined
1429
1454
  const handleFunc = (column: VxeTableDefines.ColumnInfo, index: number, items: VxeTableDefines.ColumnInfo[], path?: string[], parentColumn?: VxeTableDefines.ColumnInfo) => {
1430
- const { id: colid, field, fixed, type, treeNode } = column
1455
+ const { id: colid, field, fixed, type, treeNode, rowGroupNode } = column
1431
1456
  const rest = { $index: -1, _index: -1, column, colid, index, items, parent: parentColumn || null, width: 0, oLeft: 0 }
1432
1457
  if (field) {
1433
1458
  if (fullColumnFieldData[field]) {
@@ -1452,7 +1477,16 @@ export default defineComponent({
1452
1477
  if (!treeNodeColumn) {
1453
1478
  treeNodeColumn = column
1454
1479
  }
1455
- } else if (type === 'expand') {
1480
+ }
1481
+ if (rowGroupNode) {
1482
+ if (treeNodeColumn) {
1483
+ warnLog('vxe.error.colRepet', ['row-group-node', rowGroupNode])
1484
+ }
1485
+ if (!rowGroupColumn) {
1486
+ rowGroupColumn = column
1487
+ }
1488
+ }
1489
+ if (type === 'expand') {
1456
1490
  if (expandColumn) {
1457
1491
  warnLog('vxe.error.colRepet', ['type', type])
1458
1492
  }
@@ -1509,6 +1543,7 @@ export default defineComponent({
1509
1543
  }
1510
1544
 
1511
1545
  reactData.isGroup = isGroup
1546
+ reactData.rowGroupColumn = rowGroupColumn
1512
1547
  reactData.treeNodeColumn = treeNodeColumn
1513
1548
  reactData.expandColumn = expandColumn
1514
1549
  reactData.isAllOverflow = isAllOverflow
@@ -1782,20 +1817,22 @@ export default defineComponent({
1782
1817
  }
1783
1818
 
1784
1819
  /**
1785
- * 如果为虚拟树,将树结构拍平
1820
+ * 如果为虚拟树、行分组、则将树结构拍平
1786
1821
  * @returns
1787
1822
  */
1788
1823
  const handleVirtualTreeToList = () => {
1789
1824
  const { treeConfig } = props
1790
- const { fullAllDataRowIdData, treeExpandedMaps } = internalData
1825
+ const { isRowGroupStatus } = reactData
1826
+ const { fullAllDataRowIdData, treeExpandedMaps, rowGroupExpandedMaps } = internalData
1827
+ const rowGroupOpts = computeRowGroupOpts.value
1791
1828
  const treeOpts = computeTreeOpts.value
1792
- const childrenField = treeOpts.children || treeOpts.childrenField
1829
+ const { handleGetRowId } = createHandleGetRowId($xeTable)
1830
+ const fullData: any[] = []
1831
+ const expandMaps: {
1832
+ [key: string]: number
1833
+ } = {}
1793
1834
  if (treeConfig && treeOpts.transform) {
1794
- const { handleGetRowId } = createHandleGetRowId($xeTable)
1795
- const fullData: any[] = []
1796
- const expandMaps: {
1797
- [key: string]: number
1798
- } = {}
1835
+ const childrenField = treeOpts.children || treeOpts.childrenField
1799
1836
  XEUtils.eachTree(internalData.afterTreeFullData, (row, index, items, path, parentRow) => {
1800
1837
  const rowid = handleGetRowId(row)
1801
1838
  const parentRowid = handleGetRowId(parentRow)
@@ -1811,19 +1848,38 @@ export default defineComponent({
1811
1848
  internalData.afterFullData = fullData
1812
1849
  updateScrollYStatus(fullData)
1813
1850
  return fullData
1851
+ } else if (isRowGroupStatus) {
1852
+ const { childrenField } = rowGroupOpts
1853
+ XEUtils.eachTree(internalData.afterGroupFullData, (row, index, items, path, parentRow) => {
1854
+ const rowid = handleGetRowId(row)
1855
+ const parentRowid = handleGetRowId(parentRow)
1856
+ if (!parentRow || (expandMaps[parentRowid] && rowGroupExpandedMaps[parentRowid])) {
1857
+ const rowRest = fullAllDataRowIdData[rowid]
1858
+ if (rowRest) {
1859
+ rowRest._index = fullData.length
1860
+ }
1861
+ expandMaps[rowid] = 1
1862
+ fullData.push(row)
1863
+ }
1864
+ }, { children: childrenField })
1865
+ internalData.afterFullData = fullData
1866
+ updateScrollYStatus(fullData)
1867
+ return fullData
1814
1868
  }
1815
1869
  return internalData.afterFullData
1816
1870
  }
1817
1871
 
1818
1872
  /**
1819
- * 获取处理后全量的表格数据
1873
+ * 编译处理后全量的表格数据
1820
1874
  * 如果存在筛选条件,继续处理
1821
1875
  */
1822
1876
  const updateAfterFullData = () => {
1823
1877
  const { treeConfig } = props
1824
- const { tableFullColumn, tableFullData, tableFullTreeData } = internalData
1878
+ const { isRowGroupStatus } = reactData
1879
+ const { tableFullColumn, tableFullData, tableFullTreeData, tableFullGroupData } = internalData
1825
1880
  const filterOpts = computeFilterOpts.value
1826
1881
  const sortOpts = computeSortOpts.value
1882
+ const rowGroupOpts = computeRowGroupOpts.value
1827
1883
  const treeOpts = computeTreeOpts.value
1828
1884
  const childrenField = treeOpts.children || treeOpts.childrenField
1829
1885
  const { transform, rowField, parentField, mapChildrenField } = treeOpts
@@ -1831,7 +1887,6 @@ export default defineComponent({
1831
1887
  const { remote: allRemoteSort, sortMethod: allSortMethod, multiple: sortMultiple, chronological } = sortOpts
1832
1888
  let tableData: any[] = []
1833
1889
  let tableTree: any[] = []
1834
-
1835
1890
  // 处理数据
1836
1891
  if (!allRemoteFilter || !allRemoteSort) {
1837
1892
  const filterColumns: {
@@ -1878,14 +1933,23 @@ export default defineComponent({
1878
1933
  } else if (compFilterMethod) {
1879
1934
  return itemList.some((item) => compFilterMethod({ value: item.value, option: item, cellValue, row, column, $table: $xeTable }))
1880
1935
  } else if (allFilterMethod) {
1881
- return allFilterMethod({ options: itemList, values: valueList, cellValue, row, column })
1936
+ return allFilterMethod({ $table: $xeTable, options: itemList, values: valueList, cellValue, row, column })
1882
1937
  } else if (tdFilterMethod) {
1883
1938
  return itemList.some((item) => tdFilterMethod({ value: item.value, option: item, cellValue, row, column, $table: $xeTable }))
1884
1939
  }
1885
1940
  return valueList.indexOf(XEUtils.get(row, column.field)) > -1
1886
1941
  })
1887
1942
  }
1888
- if (treeConfig && transform) {
1943
+ if (isRowGroupStatus) {
1944
+ // 行分组
1945
+ tableTree = XEUtils.searchTree(tableFullGroupData, handleFilter, {
1946
+ original: true,
1947
+ isEvery: true,
1948
+ children: rowGroupOpts.mapChildrenField,
1949
+ mapChildren: rowGroupOpts.childrenField
1950
+ })
1951
+ tableData = tableTree
1952
+ } else if (treeConfig && transform) {
1889
1953
  // 筛选虚拟树
1890
1954
  tableTree = XEUtils.searchTree(tableFullTreeData, handleFilter, {
1891
1955
  original: true,
@@ -1899,7 +1963,16 @@ export default defineComponent({
1899
1963
  tableTree = tableData
1900
1964
  }
1901
1965
  } else {
1902
- if (treeConfig && transform) {
1966
+ if (isRowGroupStatus) {
1967
+ // 还原行分组
1968
+ tableTree = XEUtils.searchTree(tableFullGroupData, () => true, {
1969
+ original: true,
1970
+ isEvery: true,
1971
+ children: rowGroupOpts.mapChildrenField,
1972
+ mapChildren: rowGroupOpts.childrenField
1973
+ })
1974
+ tableData = tableTree
1975
+ } else if (treeConfig && transform) {
1903
1976
  // 还原虚拟树
1904
1977
  tableTree = XEUtils.searchTree(tableFullTreeData, () => true, {
1905
1978
  original: true,
@@ -1914,11 +1987,33 @@ export default defineComponent({
1914
1987
  }
1915
1988
  }
1916
1989
 
1917
- // 处理排序(不能用于树形结构)
1990
+ // 处理排序
1918
1991
  // 支持单列、多列、组合排序
1919
1992
  if (!allRemoteSort && orderColumns.length) {
1920
- if (treeConfig && transform) {
1921
- // 虚拟树和列表一样,只能排序根级节点
1993
+ if (isRowGroupStatus) {
1994
+ // 行分组的排序
1995
+ if (allSortMethod) {
1996
+ const sortRests = allSortMethod({ data: tableTree, sortList: orderColumns, $table: $xeTable })
1997
+ tableTree = XEUtils.isArray(sortRests) ? sortRests : tableTree
1998
+ } else {
1999
+ const treeList = XEUtils.toTreeArray(tableTree, {
2000
+ key: rowGroupOpts.rowField,
2001
+ parentKey: rowGroupOpts.parentField,
2002
+ children: rowGroupOpts.mapChildrenField
2003
+ })
2004
+ tableTree = XEUtils.toArrayTree(
2005
+ XEUtils.orderBy(treeList, orderColumns.map(({ column, order }) => [getOrderField(column), order])),
2006
+ {
2007
+ key: rowGroupOpts.rowField,
2008
+ parentKey: rowGroupOpts.parentField,
2009
+ children: rowGroupOpts.childrenField,
2010
+ mapChildren: rowGroupOpts.mapChildrenField
2011
+ }
2012
+ )
2013
+ }
2014
+ tableData = tableTree
2015
+ } else if (treeConfig && transform) {
2016
+ // 虚拟树的排序
1922
2017
  if (allSortMethod) {
1923
2018
  const sortRests = allSortMethod({ data: tableTree, sortList: orderColumns, $table: $xeTable })
1924
2019
  tableTree = XEUtils.isArray(sortRests) ? sortRests : tableTree
@@ -1948,12 +2043,22 @@ export default defineComponent({
1948
2043
  }
1949
2044
  }
1950
2045
  } else {
1951
- if (treeConfig && transform) {
2046
+ if (isRowGroupStatus) {
2047
+ // 还原行分组
2048
+ // 还原虚拟树
2049
+ tableTree = XEUtils.searchTree(tableFullGroupData, () => true, {
2050
+ original: true,
2051
+ isEvery: true,
2052
+ children: rowGroupOpts.mapChildrenField,
2053
+ mapChildren: rowGroupOpts.childrenField
2054
+ })
2055
+ tableData = tableTree
2056
+ } else if (treeConfig && transform) {
1952
2057
  // 还原虚拟树
1953
2058
  tableTree = XEUtils.searchTree(tableFullTreeData, () => true, {
1954
2059
  original: true,
1955
2060
  isEvery,
1956
- children: treeOpts.mapChildrenField,
2061
+ children: mapChildrenField,
1957
2062
  mapChildren: childrenField
1958
2063
  })
1959
2064
  tableData = tableTree
@@ -1964,6 +2069,7 @@ export default defineComponent({
1964
2069
  }
1965
2070
  internalData.afterFullData = tableData
1966
2071
  internalData.afterTreeFullData = tableTree
2072
+ internalData.afterGroupFullData = tableTree
1967
2073
  updateAfterDataIndex()
1968
2074
  }
1969
2075
 
@@ -2383,7 +2489,7 @@ export default defineComponent({
2383
2489
  const handleCheckedRadioRow = (row: any, isForce?: boolean) => {
2384
2490
  const radioOpts = computeRadioOpts.value
2385
2491
  const { checkMethod } = radioOpts
2386
- if (row && (isForce || (!checkMethod || checkMethod({ row })))) {
2492
+ if (row && (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row })))) {
2387
2493
  reactData.selectRadioRow = row
2388
2494
  handleRadioReserveRow(row)
2389
2495
  }
@@ -2401,8 +2507,10 @@ export default defineComponent({
2401
2507
 
2402
2508
  const handleCheckedAllCheckboxRow = (checked: boolean, isForce?: boolean) => {
2403
2509
  const { treeConfig } = props
2404
- const { afterFullData, checkboxReserveRowMap, selectCheckboxMaps } = internalData
2510
+ const { isRowGroupStatus } = reactData
2511
+ const { afterFullData, afterTreeFullData, afterGroupFullData, checkboxReserveRowMap, selectCheckboxMaps } = internalData
2405
2512
  const treeOpts = computeTreeOpts.value
2513
+ const rowGroupOpts = computeRowGroupOpts.value
2406
2514
  const childrenField = treeOpts.children || treeOpts.childrenField
2407
2515
  const checkboxOpts = computeCheckboxOpts.value
2408
2516
  const { checkField, reserve, checkMethod } = checkboxOpts
@@ -2412,54 +2520,80 @@ export default defineComponent({
2412
2520
  const selectRowMaps: Record<string, any> = {}
2413
2521
 
2414
2522
  /**
2415
- * 绑定属性方式(高性能,有污染)
2523
+ * 绑定属性方式(有污染)
2416
2524
  * 必须在行数据存在对应的属性,否则将不响应
2417
2525
  */
2418
2526
  if (checkField) {
2419
2527
  const checkValFn = (row: any) => {
2420
- if (isForce || (!checkMethod || checkMethod({ row }))) {
2528
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
2421
2529
  if (checked) {
2422
2530
  selectRowMaps[handleGetRowId(row)] = row
2423
2531
  }
2424
2532
  XEUtils.set(row, checkField, checked)
2425
2533
  }
2426
- if (treeConfig && indeterminateField) {
2534
+ if ((treeConfig || isRowGroupStatus) && indeterminateField) {
2427
2535
  XEUtils.set(row, indeterminateField, false)
2428
2536
  }
2429
2537
  }
2430
2538
  // 如果存在选中方法
2431
2539
  // 如果方法成立,则更新值,否则忽略该数据
2432
- if (treeConfig) {
2540
+ if ((treeConfig || isRowGroupStatus)) {
2433
2541
  XEUtils.eachTree(afterFullData, checkValFn, { children: childrenField })
2434
2542
  } else {
2435
2543
  afterFullData.forEach(checkValFn)
2436
2544
  }
2437
2545
  } else {
2438
2546
  /**
2439
- * 默认方式(低性能,无污染)
2440
- * 无需任何属性,直接绑定
2441
- */
2442
- if (treeConfig) {
2547
+ * 默认方式(无污染)
2548
+ * 无需任何属性,直接绑定
2549
+ */
2550
+ if (isRowGroupStatus) {
2551
+ if (checked) {
2552
+ /**
2553
+ * 如果是行分组勾选
2554
+ * 如果方法成立,则添加到临时集合中
2555
+ */
2556
+ XEUtils.eachTree(afterGroupFullData, (row) => {
2557
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
2558
+ const rowid = handleGetRowId(row)
2559
+ selectRowMaps[rowid] = row
2560
+ }
2561
+ }, { children: rowGroupOpts.mapChildrenField })
2562
+ } else {
2563
+ /**
2564
+ * 如果是树取消
2565
+ * 如果方法成立,则不添加到临时集合中
2566
+ */
2567
+ if (!isForce && checkMethod) {
2568
+ XEUtils.eachTree(afterGroupFullData, (row) => {
2569
+ const rowid = handleGetRowId(row)
2570
+ if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
2571
+ selectRowMaps[rowid] = row
2572
+ }
2573
+ }, { children: rowGroupOpts.mapChildrenField })
2574
+ }
2575
+ }
2576
+ } else if (treeConfig) {
2443
2577
  if (checked) {
2444
2578
  /**
2445
- * 如果是树勾选
2446
- * 如果方法成立,则添加到临时集合中
2447
- */
2448
- XEUtils.eachTree(afterFullData, (row) => {
2449
- if (isForce || (!checkMethod || checkMethod({ row }))) {
2579
+ * 如果是树勾选
2580
+ * 如果方法成立,则添加到临时集合中
2581
+ */
2582
+ XEUtils.eachTree(afterTreeFullData, (row) => {
2583
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
2450
2584
  const rowid = handleGetRowId(row)
2451
2585
  selectRowMaps[rowid] = row
2452
2586
  }
2453
2587
  }, { children: childrenField })
2454
2588
  } else {
2455
2589
  /**
2456
- * 如果是树取消
2457
- * 如果方法成立,则不添加到临时集合中
2458
- */
2590
+ * 如果是树取消
2591
+ * 如果方法成立,则不添加到临时集合中
2592
+ */
2459
2593
  if (!isForce && checkMethod) {
2460
- XEUtils.eachTree(afterFullData, (row) => {
2594
+ XEUtils.eachTree(afterTreeFullData, (row) => {
2461
2595
  const rowid = handleGetRowId(row)
2462
- if (checkMethod({ row }) ? 0 : selectCheckboxMaps[rowid]) {
2596
+ if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
2463
2597
  selectRowMaps[rowid] = row
2464
2598
  }
2465
2599
  }, { children: childrenField })
@@ -2468,14 +2602,14 @@ export default defineComponent({
2468
2602
  } else {
2469
2603
  if (checked) {
2470
2604
  /**
2471
- * 如果是行勾选
2472
- * 如果存在选中方法且成立或者本身已勾选,则添加到临时集合中
2473
- * 如果不存在选中方法,则添加所有数据到临时集合中
2474
- */
2605
+ * 如果是行勾选
2606
+ * 如果存在选中方法且成立或者本身已勾选,则添加到临时集合中
2607
+ * 如果不存在选中方法,则添加所有数据到临时集合中
2608
+ */
2475
2609
  if (!isForce && checkMethod) {
2476
2610
  afterFullData.forEach((row) => {
2477
2611
  const rowid = handleGetRowId(row)
2478
- if (selectCheckboxMaps[rowid] || checkMethod({ row })) {
2612
+ if (selectCheckboxMaps[rowid] || checkMethod({ $table: $xeTable, row })) {
2479
2613
  selectRowMaps[rowid] = row
2480
2614
  }
2481
2615
  })
@@ -2487,14 +2621,14 @@ export default defineComponent({
2487
2621
  }
2488
2622
  } else {
2489
2623
  /**
2490
- * 如果是行取消
2491
- * 如果方法成立,则不添加到临时集合中;如果方法不成立则判断当前是否已勾选,如果已被勾选则添加到新集合中
2492
- * 如果不存在选中方法,无需处理,临时集合默认为空
2493
- */
2624
+ * 如果是行取消
2625
+ * 如果方法成立,则不添加到临时集合中;如果方法不成立则判断当前是否已勾选,如果已被勾选则添加到新集合中
2626
+ * 如果不存在选中方法,无需处理,临时集合默认为空
2627
+ */
2494
2628
  if (!isForce && checkMethod) {
2495
2629
  afterFullData.forEach((row) => {
2496
2630
  const rowid = handleGetRowId(row)
2497
- if (checkMethod({ row }) ? 0 : selectCheckboxMaps[rowid]) {
2631
+ if (checkMethod({ $table: $xeTable, row }) ? false : selectCheckboxMaps[rowid]) {
2498
2632
  selectRowMaps[rowid] = row
2499
2633
  }
2500
2634
  })
@@ -2851,14 +2985,87 @@ export default defineComponent({
2851
2985
  })
2852
2986
  }
2853
2987
 
2988
+ const handleUpdateRowGroup = (groupFields?: string[]) => {
2989
+ reactData.rowGroupList = groupFields
2990
+ ? (XEUtils.isArray(groupFields) ? groupFields : [groupFields]).map(field => {
2991
+ return {
2992
+ field
2993
+ }
2994
+ })
2995
+ : []
2996
+ }
2997
+
2998
+ const handleGroupData = (list: any[], rowGroups: VxeTableDefines.RowGroupItem[]) => {
2999
+ let fullData = list
3000
+ let treeData = list
3001
+ if (rowGroups) {
3002
+ const rowGroupOpts = computeRowGroupOpts.value
3003
+ const { rowField, parentField, childrenField, mapChildrenField } = rowGroupOpts
3004
+ const checkboxOpts = computeCheckboxOpts.value
3005
+ const { checkField } = checkboxOpts
3006
+ const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField
3007
+ const rgItem = rowGroups[0]
3008
+ if (rgItem && rowField && parentField && childrenField && mapChildrenField) {
3009
+ fullData = []
3010
+ treeData = []
3011
+ const groupField = rgItem.field
3012
+ const groupColumn = $xeTable.getColumnByField(groupField)
3013
+ const groupMaps: Record<string, any[]> = {}
3014
+ const rowkey = getRowkey($xeTable)
3015
+ list.forEach((row) => {
3016
+ const cellValue = groupColumn ? $xeTable.getCellLabel(row, groupColumn) : XEUtils.get(row, groupField)
3017
+ const groupValue = XEUtils.eqNull(cellValue) ? '' : cellValue
3018
+ let childList = groupMaps[groupValue]
3019
+ if (!childList) {
3020
+ childList = []
3021
+ groupMaps[groupValue] = childList
3022
+ }
3023
+ if (row.isAggregate) {
3024
+ row.isAggregate = undefined
3025
+ }
3026
+ childList.push(row)
3027
+ })
3028
+ XEUtils.objectEach(groupMaps, (childList, groupValue) => {
3029
+ const { fullData: childFullData, treeData: childTreeData } = handleGroupData(childList, rowGroups.slice(1))
3030
+ const groupRow = {
3031
+ isAggregate: true,
3032
+ groupContent: groupValue,
3033
+ groupField,
3034
+ [rowField]: getRowUniqueId(),
3035
+ [parentField]: null,
3036
+ [rowkey]: getRowUniqueId(),
3037
+ [childrenField]: childTreeData,
3038
+ [mapChildrenField]: childTreeData
3039
+ }
3040
+ if (checkField) {
3041
+ groupRow[checkField] = false
3042
+ }
3043
+ if (indeterminateField) {
3044
+ groupRow[indeterminateField] = false
3045
+ }
3046
+ treeData.push(groupRow)
3047
+ fullData.push(groupRow)
3048
+ if (childFullData.length) {
3049
+ fullData.push(...childFullData)
3050
+ }
3051
+ })
3052
+ }
3053
+ }
3054
+ return {
3055
+ treeData,
3056
+ fullData
3057
+ }
3058
+ }
3059
+
2854
3060
  /**
2855
3061
  * 加载表格数据
2856
3062
  * @param {Array} datas 数据
2857
3063
  */
2858
3064
  const loadTableData = (datas: any[], isReset: boolean) => {
2859
- const { keepSource, treeConfig } = props
2860
- const { scrollYLoad: oldScrollYLoad } = reactData
3065
+ const { keepSource, treeConfig, rowGroupConfig } = props
3066
+ const { rowGroupList, scrollYLoad: oldScrollYLoad } = reactData
2861
3067
  const { scrollYStore, scrollXStore, lastScrollLeft, lastScrollTop } = internalData
3068
+ const rowOpts = computeRowOpts.value
2862
3069
  const treeOpts = computeTreeOpts.value
2863
3070
  const expandOpts = computeExpandOpts.value
2864
3071
  const { transform } = treeOpts
@@ -2868,6 +3075,15 @@ export default defineComponent({
2868
3075
  if (fullData.length > supportMaxRow) {
2869
3076
  errLog('vxe.error.errMaxRow', [supportMaxRow])
2870
3077
  }
3078
+ if (treeConfig && rowGroupList.length) {
3079
+ errLog('vxe.error.noTree', ['row-group-config'])
3080
+ return nextTick()
3081
+ }
3082
+ if (rowOpts.drag && rowGroupList.length) {
3083
+ errLog('vxe.error.errConflicts', ['row-config.drag', 'row-group-config'])
3084
+ return nextTick()
3085
+ }
3086
+ let isRGroup = false
2871
3087
  if (treeConfig) {
2872
3088
  if (transform) {
2873
3089
  // 树结构自动转换
@@ -2901,21 +3117,34 @@ export default defineComponent({
2901
3117
  } else {
2902
3118
  treeData = fullData.slice(0)
2903
3119
  }
3120
+ } else if (rowGroupConfig && rowGroupList.length) {
3121
+ const groupRest = handleGroupData(fullData, rowGroupList)
3122
+ treeData = groupRest.treeData
3123
+ fullData = groupRest.fullData
3124
+ isRGroup = true
2904
3125
  }
3126
+ reactData.isRowGroupStatus = isRGroup
2905
3127
  scrollYStore.startIndex = 0
2906
3128
  scrollYStore.endIndex = 1
2907
3129
  scrollXStore.startIndex = 0
2908
3130
  scrollXStore.endIndex = 1
2909
3131
  reactData.isRowLoading = true
2910
3132
  reactData.scrollVMLoading = false
3133
+ internalData.treeExpandedMaps = {}
3134
+ reactData.treeExpandedFlag++
3135
+ internalData.rowExpandedMaps = {}
3136
+ reactData.rowExpandedFlag++
2911
3137
  internalData.insertRowMaps = {}
3138
+ reactData.insertRowFlag++
2912
3139
  internalData.removeRowMaps = {}
3140
+ reactData.removeRowFlag++
2913
3141
  const sYLoad = updateScrollYStatus(fullData)
2914
3142
  reactData.isDragColMove = false
2915
3143
  reactData.isDragRowMove = false
2916
3144
  // 全量数据
2917
3145
  internalData.tableFullData = fullData
2918
- internalData.tableFullTreeData = treeData
3146
+ internalData.tableFullTreeData = isRGroup ? [] : treeData
3147
+ internalData.tableFullGroupData = isRGroup ? treeData : []
2919
3148
  // 缓存数据
2920
3149
  $xeTable.cacheRowMap(isReset)
2921
3150
  // 原始数据
@@ -3287,7 +3516,7 @@ export default defineComponent({
3287
3516
  */
3288
3517
  const handleBaseTreeExpand = (rows: any[], expanded: boolean) => {
3289
3518
  const { treeNodeColumn } = reactData
3290
- const { fullAllDataRowIdData, tableFullData, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData
3519
+ const { fullAllDataRowIdData, tableFullTreeData, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData
3291
3520
  const treeOpts = computeTreeOpts.value
3292
3521
  const { reserve, lazy, accordion, toggleMethod } = treeOpts
3293
3522
  const childrenField = treeOpts.children || treeOpts.childrenField
@@ -3300,7 +3529,7 @@ export default defineComponent({
3300
3529
  if (accordion) {
3301
3530
  validRows = validRows.length ? [validRows[validRows.length - 1]] : []
3302
3531
  // 同一级只能展开一个
3303
- const matchObj = XEUtils.findTree(tableFullData, item => item === validRows[0], { children: childrenField })
3532
+ const matchObj = XEUtils.findTree(tableFullTreeData, item => item === validRows[0], { children: childrenField })
3304
3533
  if (matchObj) {
3305
3534
  matchObj.items.forEach(item => {
3306
3535
  const rowid = handleGetRowId(item)
@@ -3355,6 +3584,80 @@ export default defineComponent({
3355
3584
  return handleBaseTreeExpand(rows, expanded).then(() => {
3356
3585
  handleVirtualTreeToList()
3357
3586
  $xeTable.handleTableData()
3587
+ reactData.treeExpandedFlag++
3588
+ updateAfterDataIndex()
3589
+ return nextTick()
3590
+ }).then(() => {
3591
+ return $xeTable.recalculate(true)
3592
+ }).then(() => {
3593
+ setTimeout(() => {
3594
+ $xeTable.updateCellAreas()
3595
+ }, 30)
3596
+ })
3597
+ }
3598
+
3599
+ /**
3600
+ * 展开与收起行分组节点
3601
+ * @param rows
3602
+ * @param expanded
3603
+ * @returns
3604
+ */
3605
+ const handleRowGroupBaseExpand = (rows: any[], expanded: boolean) => {
3606
+ const { fullAllDataRowIdData, tableFullGroupData, rowGroupExpandedMaps } = internalData
3607
+ const rowGroupOpts = computeRowGroupOpts.value
3608
+ const { mapChildrenField, accordion } = rowGroupOpts
3609
+ const { handleGetRowId } = createHandleGetRowId($xeTable)
3610
+ let validRows = rows
3611
+ if (mapChildrenField) {
3612
+ if (accordion) {
3613
+ validRows = validRows.length ? [validRows[validRows.length - 1]] : []
3614
+ // 同一级只能展开一个
3615
+ const matchObj = XEUtils.findTree(tableFullGroupData, item => getRowid($xeTable, item) === getRowid($xeTable, validRows[0]), { children: mapChildrenField })
3616
+ if (matchObj) {
3617
+ matchObj.items.forEach(item => {
3618
+ const rowid = handleGetRowId(item)
3619
+ if (rowGroupExpandedMaps[rowid]) {
3620
+ delete rowGroupExpandedMaps[rowid]
3621
+ }
3622
+ })
3623
+ }
3624
+ }
3625
+ if (expanded) {
3626
+ validRows.forEach((row) => {
3627
+ const rowid = handleGetRowId(row)
3628
+ if (!rowGroupExpandedMaps[rowid]) {
3629
+ const rowRest = fullAllDataRowIdData[rowid]
3630
+ if (rowRest) {
3631
+ if (row[mapChildrenField] && row[mapChildrenField].length) {
3632
+ rowGroupExpandedMaps[rowid] = row
3633
+ }
3634
+ }
3635
+ }
3636
+ })
3637
+ } else {
3638
+ validRows.forEach(item => {
3639
+ const rowid = handleGetRowId(item)
3640
+ if (rowGroupExpandedMaps[rowid]) {
3641
+ delete rowGroupExpandedMaps[rowid]
3642
+ }
3643
+ })
3644
+ }
3645
+ }
3646
+ reactData.rowGroupExpandedFlag++
3647
+ return $xeTable.recalculate()
3648
+ }
3649
+
3650
+ /**
3651
+ * 行分组的展开与收起
3652
+ * @param rows
3653
+ * @param expanded
3654
+ * @returns
3655
+ */
3656
+ const handleRowGroupVirtualExpand = (rows: any[], expanded: boolean) => {
3657
+ return handleRowGroupBaseExpand(rows, expanded).then(() => {
3658
+ handleVirtualTreeToList()
3659
+ $xeTable.handleTableData()
3660
+ reactData.rowGroupExpandedFlag++
3358
3661
  updateAfterDataIndex()
3359
3662
  return nextTick()
3360
3663
  }).then(() => {
@@ -4122,7 +4425,7 @@ export default defineComponent({
4122
4425
  if (!column) {
4123
4426
  return null
4124
4427
  }
4125
- const formatter = column.formatter
4428
+ const { formatter } = column
4126
4429
  const cellValue = getCellValue(row, column)
4127
4430
  let cellLabel = cellValue
4128
4431
  if (formatter) {
@@ -5364,7 +5667,7 @@ export default defineComponent({
5364
5667
  })
5365
5668
  if (isUpdate) {
5366
5669
  if (!remote) {
5367
- tablePrivateMethods.handleTableData(true)
5670
+ $xeTable.handleTableData(true)
5368
5671
  }
5369
5672
  $xeTable.handleColumnSortEvent(new Event('click'), firstColumn)
5370
5673
  }
@@ -5391,7 +5694,7 @@ export default defineComponent({
5391
5694
  clearAllSort()
5392
5695
  }
5393
5696
  if (!sortOpts.remote) {
5394
- tablePrivateMethods.handleTableData(true)
5697
+ $xeTable.handleTableData(true)
5395
5698
  }
5396
5699
  return nextTick().then(updateStyle)
5397
5700
  },
@@ -5536,8 +5839,8 @@ export default defineComponent({
5536
5839
  const expandOpts = computeExpandOpts.value
5537
5840
  const { reserve, lazy, accordion, toggleMethod } = expandOpts
5538
5841
  const lazyRests: any[] = []
5539
- const columnIndex = $xeTable.getColumnIndex(expandColumn)
5540
- const $columnIndex = $xeTable.getVMColumnIndex(expandColumn)
5842
+ const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1
5843
+ const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1
5541
5844
  if (rows) {
5542
5845
  if (!XEUtils.isArray(rows)) {
5543
5846
  rows = [rows]
@@ -5548,9 +5851,9 @@ export default defineComponent({
5548
5851
  internalData.rowExpandedMaps = rowExpandedMaps
5549
5852
  rows = rows.slice(rows.length - 1, rows.length)
5550
5853
  }
5551
- const validRows: any[] = toggleMethod ? rows.filter((row: any) => toggleMethod({ $table: $xeTable, expanded, column: expandColumn, columnIndex, $columnIndex, row, rowIndex: $xeTable.getRowIndex(row), $rowIndex: $xeTable.getVMRowIndex(row) })) : rows
5854
+ const validRows: any[] = toggleMethod ? rows.filter((row: any) => toggleMethod({ $table: $xeTable, expanded, column: expandColumn as VxeTableDefines.ColumnInfo, columnIndex, $columnIndex, row, rowIndex: $xeTable.getRowIndex(row), $rowIndex: $xeTable.getVMRowIndex(row) })) : rows
5552
5855
  if (expanded) {
5553
- validRows.forEach((row: any) => {
5856
+ validRows.forEach((row) => {
5554
5857
  const rowid = handleGetRowId(row)
5555
5858
  if (!rowExpandedMaps[rowid]) {
5556
5859
  const rowRest = fullAllDataRowIdData[rowid]
@@ -5639,6 +5942,70 @@ export default defineComponent({
5639
5942
  })
5640
5943
  return rest
5641
5944
  },
5945
+ setRowGroups (fieldOrColumns) {
5946
+ const { rowGroupConfig } = props
5947
+ if (!rowGroupConfig) {
5948
+ errLog('vxe.error.reqProp', ['row-group-config'])
5949
+ return nextTick()
5950
+ }
5951
+ if (fieldOrColumns) {
5952
+ handleUpdateRowGroup((XEUtils.isArray(fieldOrColumns) ? fieldOrColumns : [fieldOrColumns]).map(fieldOrColumn => {
5953
+ return XEUtils.isString(fieldOrColumn) ? fieldOrColumn : fieldOrColumn.field
5954
+ }))
5955
+ return loadTableData(internalData.tableSynchData, true)
5956
+ }
5957
+ return nextTick()
5958
+ },
5959
+ clearRowGroups () {
5960
+ const { rowGroupConfig } = props
5961
+ if (!rowGroupConfig) {
5962
+ errLog('vxe.error.reqProp', ['row-group-config'])
5963
+ return nextTick()
5964
+ }
5965
+ handleUpdateRowGroup([])
5966
+ return loadTableData(internalData.tableSynchData, true)
5967
+ },
5968
+ isRowGroupRecord (row) {
5969
+ const { isRowGroupStatus } = reactData
5970
+ return isRowGroupStatus && row.isAggregate
5971
+ },
5972
+ isRowGroupExpandByRow (row) {
5973
+ const { rowGroupExpandedFlag } = reactData
5974
+ const { rowGroupExpandedMaps } = internalData
5975
+ return !!rowGroupExpandedFlag && !!rowGroupExpandedMaps[getRowid($xeTable, row)]
5976
+ },
5977
+ setRowGroupExpand (rows, expanded) {
5978
+ if (rows) {
5979
+ if (!XEUtils.isArray(rows)) {
5980
+ rows = [rows]
5981
+ }
5982
+ return handleRowGroupVirtualExpand(rows, expanded)
5983
+ }
5984
+ return nextTick()
5985
+ },
5986
+ setAllRowGroupExpand (expanded) {
5987
+ const { tableFullGroupData } = internalData
5988
+ const rowGroupOpts = computeRowGroupOpts.value
5989
+ const { mapChildrenField } = rowGroupOpts
5990
+ const rgExpandedMaps: Record<string, any> = {}
5991
+ if (expanded && mapChildrenField) {
5992
+ XEUtils.eachTree(tableFullGroupData, (row) => {
5993
+ if (row[mapChildrenField] && row[mapChildrenField].length) {
5994
+ rgExpandedMaps[getRowid($xeTable, row)] = row
5995
+ }
5996
+ }, { children: mapChildrenField })
5997
+ }
5998
+ internalData.rowGroupExpandedMaps = rgExpandedMaps
5999
+ handleVirtualTreeToList()
6000
+ reactData.rowGroupExpandedFlag++
6001
+ return $xeTable.handleTableData()
6002
+ },
6003
+ clearRowGroupExpand () {
6004
+ internalData.rowGroupExpandedMaps = {}
6005
+ handleVirtualTreeToList()
6006
+ reactData.rowGroupExpandedFlag++
6007
+ return $xeTable.handleTableData()
6008
+ },
5642
6009
  getTreeExpandRecords () {
5643
6010
  const rest: any[] = []
5644
6011
  XEUtils.each(internalData.treeExpandedMaps, item => {
@@ -5681,11 +6048,11 @@ export default defineComponent({
5681
6048
  })
5682
6049
  }
5683
6050
  internalData.treeExpandedMaps = {}
5684
- reactData.treeExpandedFlag++
5685
6051
  if (transform) {
5686
6052
  handleVirtualTreeToList()
5687
- return $xeTable.handleTableData()
6053
+ $xeTable.handleTableData()
5688
6054
  }
6055
+ reactData.treeExpandedFlag++
5689
6056
  return nextTick()
5690
6057
  },
5691
6058
  /**
@@ -5699,15 +6066,16 @@ export default defineComponent({
5699
6066
  const { transform, lazy } = treeOpts
5700
6067
  const rowid = getRowid($xeTable, row)
5701
6068
  if (lazy && row[hasChildField] && !treeExpandLazyLoadedMaps[rowid]) {
5702
- return tableMethods.clearTreeExpandLoaded(row).then(() => {
6069
+ return $xeTable.clearTreeExpandLoaded(row).then(() => {
5703
6070
  return handleAsyncTreeExpandChilds(row)
5704
6071
  }).then(() => {
5705
6072
  if (transform) {
5706
6073
  handleVirtualTreeToList()
5707
- return tablePrivateMethods.handleTableData()
6074
+ $xeTable.handleTableData()
5708
6075
  }
6076
+ reactData.treeExpandedFlag++
5709
6077
  }).then(() => {
5710
- return tableMethods.recalculate()
6078
+ return $xeTable.recalculate()
5711
6079
  })
5712
6080
  }
5713
6081
  return nextTick()
@@ -5717,13 +6085,13 @@ export default defineComponent({
5717
6085
  warnLog('vxe.error.delFunc', ['reloadTreeChilds', 'reloadTreeExpand'])
5718
6086
  }
5719
6087
  // 即将废弃
5720
- return tableMethods.reloadTreeExpand(row)
6088
+ return $xeTable.reloadTreeExpand(row)
5721
6089
  },
5722
6090
  /**
5723
6091
  * 切换/展开树节点
5724
6092
  */
5725
6093
  toggleTreeExpand (row) {
5726
- return tableMethods.setTreeExpand(row, !tableMethods.isTreeExpandByRow(row))
6094
+ return $xeTable.setTreeExpand(row, !$xeTable.isTreeExpandByRow(row))
5727
6095
  },
5728
6096
  /**
5729
6097
  * 设置所有树节点的展开与否
@@ -5741,10 +6109,11 @@ export default defineComponent({
5741
6109
  expandeds.push(row)
5742
6110
  }
5743
6111
  }, { children: childrenField })
5744
- return tableMethods.setTreeExpand(expandeds, expanded).then(() => {
6112
+ return $xeTable.setTreeExpand(expandeds, expanded).then(() => {
5745
6113
  if (transform) {
5746
6114
  handleVirtualTreeToList()
5747
- return tableMethods.recalculate()
6115
+ reactData.treeExpandedFlag++
6116
+ return $xeTable.recalculate()
5748
6117
  }
5749
6118
  })
5750
6119
  },
@@ -5792,15 +6161,15 @@ export default defineComponent({
5792
6161
  const { transform, reserve } = treeOpts
5793
6162
  const expList = $xeTable.getTreeExpandRecords()
5794
6163
  internalData.treeExpandedMaps = {}
5795
- reactData.treeExpandedFlag++
5796
6164
  if (reserve) {
5797
6165
  XEUtils.eachTree(tableFullTreeData, row => handleTreeExpandReserve(row, false), { children: childrenField })
5798
6166
  }
5799
6167
  return $xeTable.handleTableData().then(() => {
5800
6168
  if (transform) {
5801
6169
  handleVirtualTreeToList()
5802
- return $xeTable.handleTableData()
6170
+ $xeTable.handleTableData()
5803
6171
  }
6172
+ reactData.treeExpandedFlag++
5804
6173
  }).then(() => {
5805
6174
  if (expList.length) {
5806
6175
  return $xeTable.recalculate()
@@ -6115,7 +6484,7 @@ export default defineComponent({
6115
6484
  hasResizable = 1
6116
6485
  resizableData[colKey] = column.renderWidth
6117
6486
  }
6118
- if (isCustomVisible && (!checkMethod || checkMethod({ column }))) {
6487
+ if (isCustomVisible && (!checkMethod || checkMethod({ $table: $xeTable, column }))) {
6119
6488
  if (!column.visible && column.defaultVisible) {
6120
6489
  hasVisible = 1
6121
6490
  visibleData[colKey] = false
@@ -6391,8 +6760,7 @@ export default defineComponent({
6391
6760
  const hasDeleteKey = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.DELETE)
6392
6761
  const isF2 = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.F2)
6393
6762
  const isContextMenu = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.CONTEXT_MENU)
6394
- const hasMetaKey = evnt.metaKey
6395
- const hasCtrlKey = evnt.ctrlKey
6763
+ const isControlKey = hasControlKey(evnt)
6396
6764
  const hasShiftKey = evnt.shiftKey
6397
6765
  const isAltKey = evnt.altKey
6398
6766
  const operArrow = isLeftArrow || isUpArrow || isRightArrow || isDwArrow
@@ -6452,7 +6820,7 @@ export default defineComponent({
6452
6820
  } else if (isEnter && !isAltKey && keyboardConfig && keyboardOpts.isEnter && (selected.row || actived.row || (treeConfig && (rowOpts.isCurrent || highlightCurrentRow) && currentRow))) {
6453
6821
  const { isLastEnterAppendRow, beforeEnterMethod, enterMethod } = keyboardOpts
6454
6822
  // 退出选中
6455
- if (hasCtrlKey) {
6823
+ if (isControlKey) {
6456
6824
  // 如果是激活编辑状态,则取消编辑
6457
6825
  if (actived.row) {
6458
6826
  const params = actived.args
@@ -6617,7 +6985,7 @@ export default defineComponent({
6617
6985
  .then(() => $xeTable.scrollToRow(parentRow))
6618
6986
  .then(() => $xeTable.triggerCurrentRowEvent(evnt, params))
6619
6987
  }
6620
- } 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))) {
6988
+ } 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))) {
6621
6989
  const { editMode, editMethod } = keyboardOpts
6622
6990
  // 启用编辑后,空格键功能将失效
6623
6991
  // if (isSpacebar) {
@@ -6770,9 +7138,11 @@ export default defineComponent({
6770
7138
  const rTooltipMethod = tooltipMethod || (dragConfig ? dragConfig.rowTooltipMethod : null)
6771
7139
  let tipContent = ''
6772
7140
  if (rTooltipMethod) {
6773
- tipContent = `${rTooltipMethod({
7141
+ const rtParams = {
7142
+ $table: $xeTable,
6774
7143
  row: dragRow
6775
- }) || ''}`
7144
+ }
7145
+ tipContent = `${rTooltipMethod(rtParams) || ''}`
6776
7146
  } else {
6777
7147
  tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || ''])
6778
7148
  }
@@ -6810,9 +7180,11 @@ export default defineComponent({
6810
7180
  const { tooltipMethod } = columnDragOpts
6811
7181
  let tipContent = ''
6812
7182
  if (tooltipMethod) {
6813
- tipContent = `${tooltipMethod({
7183
+ const dtParams = {
7184
+ $table: $xeTable,
6814
7185
  column: dragCol as VxeTableDefines.ColumnInfo
6815
- }) || ''}`
7186
+ }
7187
+ tipContent = `${tooltipMethod(dtParams) || ''}`
6816
7188
  } else {
6817
7189
  tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || ''])
6818
7190
  }
@@ -7092,11 +7464,8 @@ export default defineComponent({
7092
7464
  */
7093
7465
  cacheRowMap (isReset) {
7094
7466
  const { treeConfig } = props
7095
- const { fullAllDataRowIdData, tableFullData, tableFullTreeData, treeExpandedMaps } = internalData
7096
- const treeOpts = computeTreeOpts.value
7097
- const childrenField = treeOpts.children || treeOpts.childrenField
7098
- const hasChildField = treeOpts.hasChild || treeOpts.hasChildField
7099
- const { lazy } = treeOpts
7467
+ const { isRowGroupStatus } = reactData
7468
+ const { fullAllDataRowIdData, tableFullData, tableFullTreeData, tableFullGroupData, treeExpandedMaps } = internalData
7100
7469
  const fullAllDataRowIdMaps: Record<string, VxeTableDefines.RowCacheItem> = isReset ? {} : { ...fullAllDataRowIdData } // 存在已删除数据
7101
7470
  const fullDataRowIdMaps: Record<string, VxeTableDefines.RowCacheItem> = {}
7102
7471
 
@@ -7123,6 +7492,10 @@ export default defineComponent({
7123
7492
  }
7124
7493
 
7125
7494
  if (treeConfig) {
7495
+ const treeOpts = computeTreeOpts.value
7496
+ const { lazy } = treeOpts
7497
+ const childrenField = treeOpts.children || treeOpts.childrenField
7498
+ const hasChildField = treeOpts.hasChild || treeOpts.hasChildField
7126
7499
  XEUtils.eachTree(tableFullTreeData, (row, index, items, path, parentRow, nodes) => {
7127
7500
  const rowid = handleUpdateRowId(row)
7128
7501
  if (treeConfig && lazy) {
@@ -7137,6 +7510,13 @@ export default defineComponent({
7137
7510
  }
7138
7511
  handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path))
7139
7512
  }, { children: childrenField })
7513
+ } else if (isRowGroupStatus) {
7514
+ const rowGroupOpts = computeRowGroupOpts.value
7515
+ const { mapChildrenField } = rowGroupOpts
7516
+ XEUtils.eachTree(tableFullGroupData, (row, index, items, path, parentRow, nodes) => {
7517
+ const rowid = handleUpdateRowId(row)
7518
+ handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path))
7519
+ }, { children: mapChildrenField })
7140
7520
  } else {
7141
7521
  tableFullData.forEach((row, index, items) => {
7142
7522
  handleRowCache(row, index, items, index, null, handleUpdateRowId(row), 0, index + 1)
@@ -7567,6 +7947,7 @@ export default defineComponent({
7567
7947
  : tableMethods.getCustomStoreData()
7568
7948
  if (updateStore) {
7569
7949
  return updateStore({
7950
+ $table: $xeTable,
7570
7951
  id: tableId,
7571
7952
  type,
7572
7953
  storeData
@@ -7637,29 +8018,47 @@ export default defineComponent({
7637
8018
  },
7638
8019
  updateCheckboxStatus () {
7639
8020
  const { treeConfig } = props
7640
- const { selectCheckboxMaps, treeIndeterminateRowMaps } = internalData
8021
+ const { isRowGroupStatus } = reactData
8022
+ const { afterTreeFullData, afterGroupFullData, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData
8023
+ const rowGroupOpts = computeRowGroupOpts.value
7641
8024
  const treeOpts = computeTreeOpts.value
7642
- const { transform, mapChildrenField } = treeOpts
7643
8025
  const childrenField = treeOpts.children || treeOpts.childrenField
7644
8026
  const checkboxOpts = computeCheckboxOpts.value
7645
8027
  const { checkField, checkStrictly, checkMethod } = checkboxOpts
7646
- const { afterTreeFullData } = internalData
7647
8028
  if (checkStrictly) {
7648
8029
  return
7649
8030
  }
7650
- // 树结构
7651
- if (treeConfig) {
8031
+ if (isRowGroupStatus || treeConfig) {
7652
8032
  const { handleGetRowId } = createHandleGetRowId($xeTable)
7653
8033
  const childRowMaps: Record<string, number> = {}
7654
8034
  const childRowList: any[][] = []
7655
- XEUtils.eachTree(afterTreeFullData, (row) => {
7656
- const rowid = handleGetRowId(row)
7657
- const childList = row[transform ? mapChildrenField : childrenField]
7658
- if (childList && childList.length && !childRowMaps[rowid]) {
7659
- childRowMaps[rowid] = 1
7660
- childRowList.unshift([row, rowid, childList])
8035
+
8036
+ if (isRowGroupStatus) {
8037
+ // 行分组
8038
+ const mapChildrenField = rowGroupOpts.mapChildrenField
8039
+ if (mapChildrenField) {
8040
+ XEUtils.eachTree(afterGroupFullData, (row) => {
8041
+ const rowid = handleGetRowId(row)
8042
+ const childList = row[mapChildrenField]
8043
+ if (childList && childList.length && !childRowMaps[rowid]) {
8044
+ childRowMaps[rowid] = 1
8045
+ childRowList.unshift([row, rowid, childList])
8046
+ }
8047
+ }, { children: mapChildrenField })
7661
8048
  }
7662
- }, { children: transform ? mapChildrenField : childrenField })
8049
+ } else if (treeConfig) {
8050
+ // 树结构
8051
+ const { transform, mapChildrenField } = treeOpts
8052
+ XEUtils.eachTree(afterTreeFullData, (row) => {
8053
+ const rowid = handleGetRowId(row)
8054
+ const childList = row[transform ? mapChildrenField : childrenField]
8055
+ if (childList && childList.length && !childRowMaps[rowid]) {
8056
+ childRowMaps[rowid] = 1
8057
+ childRowList.unshift([row, rowid, childList])
8058
+ }
8059
+ }, { children: transform ? mapChildrenField : childrenField })
8060
+ }
8061
+
7663
8062
  childRowList.forEach(vals => {
7664
8063
  const row: string = vals[0]
7665
8064
  const rowid: string = vals[1]
@@ -7672,7 +8071,7 @@ export default defineComponent({
7672
8071
  ? (item) => {
7673
8072
  const childRowid = handleGetRowId(item)
7674
8073
  const isSelect = checkField ? XEUtils.get(item, checkField) : selectCheckboxMaps[childRowid]
7675
- if (checkMethod({ row: item })) {
8074
+ if (checkMethod({ $table: $xeTable, row: item })) {
7676
8075
  if (isSelect) {
7677
8076
  sLen++
7678
8077
  } else if (treeIndeterminateRowMaps[childRowid]) {
@@ -7730,7 +8129,8 @@ export default defineComponent({
7730
8129
  },
7731
8130
  updateAllCheckboxStatus () {
7732
8131
  const { treeConfig } = props
7733
- const { afterFullData, afterTreeFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData
8132
+ const { isRowGroupStatus } = reactData
8133
+ const { afterFullData, afterTreeFullData, afterGroupFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData
7734
8134
  const checkboxOpts = computeCheckboxOpts.value
7735
8135
  const { checkField, checkMethod, showReserveStatus } = checkboxOpts
7736
8136
  const { handleGetRowId } = createHandleGetRowId($xeTable)
@@ -7739,12 +8139,12 @@ export default defineComponent({
7739
8139
  let hLen = 0 // 半选
7740
8140
  let vLen = 0 // 有效行
7741
8141
 
7742
- const rootList = (treeConfig ? afterTreeFullData : afterFullData)
8142
+ const rootList = (treeConfig ? afterTreeFullData : (isRowGroupStatus ? afterGroupFullData : afterFullData))
7743
8143
  rootList.forEach(checkMethod
7744
8144
  ? row => {
7745
8145
  const childRowid = handleGetRowId(row)
7746
8146
  const selected = checkField ? XEUtils.get(row, checkField) : selectCheckboxMaps[childRowid]
7747
- if (checkMethod({ row })) {
8147
+ if (checkMethod({ $table: $xeTable, row })) {
7748
8148
  if (selected) {
7749
8149
  sLen++
7750
8150
  } else if (treeIndeterminateRowMaps[childRowid]) {
@@ -7791,7 +8191,9 @@ export default defineComponent({
7791
8191
  */
7792
8192
  handleBatchSelectRows (rows, checked, isForce) {
7793
8193
  const { treeConfig } = props
8194
+ const { isRowGroupStatus } = reactData
7794
8195
  const { selectCheckboxMaps } = internalData
8196
+ const rowGroupOpts = computeRowGroupOpts.value
7795
8197
  const treeOpts = computeTreeOpts.value
7796
8198
  const { transform, mapChildrenField } = treeOpts
7797
8199
  const childrenField = treeOpts.children || treeOpts.childrenField
@@ -7802,10 +8204,10 @@ export default defineComponent({
7802
8204
  const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField
7803
8205
  if (checkField) {
7804
8206
  // 树结构
7805
- if (treeConfig && !checkStrictly) {
8207
+ if ((treeConfig || isRowGroupStatus) && !checkStrictly) {
7806
8208
  // 更新子节点状态
7807
8209
  XEUtils.eachTree(rows, (row) => {
7808
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8210
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7809
8211
  XEUtils.set(row, checkField, checked)
7810
8212
  if (indeterminateField) {
7811
8213
  XEUtils.set(row, indeterminateField, false)
@@ -7818,7 +8220,7 @@ export default defineComponent({
7818
8220
  }
7819
8221
  // 列表
7820
8222
  rows.forEach(row => {
7821
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8223
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7822
8224
  XEUtils.set(row, checkField, checked)
7823
8225
  handleCheckboxReserveRow(row, checked)
7824
8226
  }
@@ -7828,29 +8230,48 @@ export default defineComponent({
7828
8230
  }
7829
8231
 
7830
8232
  // 树结构
7831
- if (treeConfig && !checkStrictly) {
7832
- // 更新子节点状态
7833
- XEUtils.eachTree(rows, (row) => {
7834
- const rowid = handleGetRowId(row)
7835
- if (isForce || (!checkMethod || checkMethod({ row }))) {
7836
- if (checked) {
7837
- selectCheckboxMaps[rowid] = row
7838
- } else {
7839
- if (selectCheckboxMaps[rowid]) {
7840
- delete selectCheckboxMaps[rowid]
8233
+ if (!checkStrictly) {
8234
+ if (isRowGroupStatus) {
8235
+ // 更新行分组节点状态
8236
+ XEUtils.eachTree(rows, (row) => {
8237
+ const rowid = handleGetRowId(row)
8238
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
8239
+ if (checked) {
8240
+ selectCheckboxMaps[rowid] = row
8241
+ } else {
8242
+ if (selectCheckboxMaps[rowid]) {
8243
+ delete selectCheckboxMaps[rowid]
8244
+ }
7841
8245
  }
8246
+ handleCheckboxReserveRow(row, checked)
7842
8247
  }
7843
- handleCheckboxReserveRow(row, checked)
7844
- }
7845
- }, { children: transform ? mapChildrenField : childrenField })
7846
- reactData.updateCheckboxFlag++
7847
- return
8248
+ }, { children: rowGroupOpts.mapChildrenField })
8249
+ reactData.updateCheckboxFlag++
8250
+ return
8251
+ } else if (treeConfig) {
8252
+ // 更新子节点状态
8253
+ XEUtils.eachTree(rows, (row) => {
8254
+ const rowid = handleGetRowId(row)
8255
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
8256
+ if (checked) {
8257
+ selectCheckboxMaps[rowid] = row
8258
+ } else {
8259
+ if (selectCheckboxMaps[rowid]) {
8260
+ delete selectCheckboxMaps[rowid]
8261
+ }
8262
+ }
8263
+ handleCheckboxReserveRow(row, checked)
8264
+ }
8265
+ }, { children: transform ? mapChildrenField : childrenField })
8266
+ reactData.updateCheckboxFlag++
8267
+ return
8268
+ }
7848
8269
  }
7849
8270
 
7850
8271
  // 列表
7851
8272
  rows.forEach(row => {
7852
8273
  const rowid = handleGetRowId(row)
7853
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8274
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7854
8275
  if (checked) {
7855
8276
  if (!selectCheckboxMaps[rowid]) {
7856
8277
  selectCheckboxMaps[rowid] = row
@@ -8021,20 +8442,22 @@ export default defineComponent({
8021
8442
  const radioOpts = computeRadioOpts.value
8022
8443
  const checkboxOpts = computeCheckboxOpts.value
8023
8444
  const keyboardOpts = computeKeyboardOpts.value
8445
+ const rowGroupOpts = computeRowGroupOpts.value
8024
8446
  const rowOpts = computeRowOpts.value
8025
8447
  const columnOpts = computeColumnOpts.value
8026
8448
  const currentColumnOpts = computeCurrentColumnOpts.value
8027
8449
  const { actived, focused } = editStore
8028
8450
  const { row, column } = params
8029
- const { type, treeNode } = column
8451
+ const { type, treeNode, rowGroupNode } = column
8030
8452
  const isRadioType = type === 'radio'
8031
8453
  const isCheckboxType = type === 'checkbox'
8032
8454
  const isExpandType = type === 'expand'
8033
8455
  const cell = evnt.currentTarget as HTMLDivElement
8034
8456
  const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag
8035
8457
  const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag
8036
- const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag
8458
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag
8037
8459
  const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag
8460
+ const triggerRowGroupNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-row-group--node-btn').flag
8038
8461
  params = Object.assign({ cell, triggerRadio, triggerCheckbox, triggerTreeNode, triggerExpandNode }, params)
8039
8462
  if (!triggerCheckbox && !triggerRadio) {
8040
8463
  // 如果是展开行
@@ -8045,10 +8468,14 @@ export default defineComponent({
8045
8468
  if ((treeOpts.trigger === 'row' || (treeNode && treeOpts.trigger === 'cell'))) {
8046
8469
  $xeTable.triggerTreeExpandEvent(evnt, params)
8047
8470
  }
8471
+ // 如果是行分组
8472
+ if ((rowGroupOpts.trigger === 'row' || (rowGroupNode && rowGroupOpts.trigger === 'cell'))) {
8473
+ $xeTable.triggerRowGroupExpandEvent(evnt, params)
8474
+ }
8048
8475
  }
8049
8476
  // 如果点击了树节点
8050
8477
  if (!triggerTreeNode) {
8051
- if (!triggerExpandNode) {
8478
+ if (!triggerExpandNode && !triggerRowGroupNode) {
8052
8479
  // 如果是当前行
8053
8480
  if (rowOpts.isCurrent || highlightCurrentRow) {
8054
8481
  if (!triggerCheckbox && !triggerRadio) {
@@ -8163,7 +8590,9 @@ export default defineComponent({
8163
8590
  }
8164
8591
  },
8165
8592
  triggerCheckRowEvent (evnt: MouseEvent, params, checked) {
8593
+ const { treeConfig } = props
8166
8594
  const { row } = params
8595
+ const { isRowGroupStatus } = reactData
8167
8596
  const { afterFullData } = internalData
8168
8597
  const checkboxOpts = computeCheckboxOpts.value
8169
8598
  const { checkMethod, trigger } = checkboxOpts
@@ -8171,7 +8600,7 @@ export default defineComponent({
8171
8600
  return
8172
8601
  }
8173
8602
  evnt.stopPropagation()
8174
- if (checkboxOpts.isShiftKey && evnt.shiftKey && !props.treeConfig) {
8603
+ if (checkboxOpts.isShiftKey && evnt.shiftKey && !(treeConfig || isRowGroupStatus)) {
8175
8604
  const checkboxRecords = $xeTable.getCheckboxRecords()
8176
8605
  if (checkboxRecords.length) {
8177
8606
  const firstRow = checkboxRecords[0]
@@ -8188,7 +8617,7 @@ export default defineComponent({
8188
8617
  }
8189
8618
  }
8190
8619
  }
8191
- if (!checkMethod || checkMethod({ row })) {
8620
+ if (!checkMethod || checkMethod({ $table: $xeTable, row })) {
8192
8621
  $xeTable.handleBatchSelectRows([row], checked)
8193
8622
  $xeTable.checkSelectionStatus()
8194
8623
  dispatchEvent('checkbox-change', Object.assign({
@@ -8286,7 +8715,7 @@ export default defineComponent({
8286
8715
  * 展开行事件
8287
8716
  */
8288
8717
  triggerRowExpandEvent (evnt, params) {
8289
- const { expandColumn: column } = reactData
8718
+ const { expandColumn } = reactData
8290
8719
  const { rowExpandLazyLoadedMaps } = internalData
8291
8720
  const expandOpts = computeExpandOpts.value
8292
8721
  const { row } = params
@@ -8298,12 +8727,12 @@ export default defineComponent({
8298
8727
  const rowid = getRowid($xeTable, row)
8299
8728
  if (!lazy || !rowExpandLazyLoadedMaps[rowid]) {
8300
8729
  const expanded = !$xeTable.isRowExpandByRow(row)
8301
- const columnIndex = $xeTable.getColumnIndex(column)
8302
- const $columnIndex = $xeTable.getVMColumnIndex(column)
8730
+ const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1
8731
+ const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1
8303
8732
  $xeTable.setRowExpand(row, expanded)
8304
8733
  dispatchEvent('toggle-row-expand', {
8305
8734
  expanded,
8306
- column,
8735
+ column: expandColumn,
8307
8736
  columnIndex,
8308
8737
  $columnIndex,
8309
8738
  row,
@@ -8312,6 +8741,25 @@ export default defineComponent({
8312
8741
  }, evnt)
8313
8742
  }
8314
8743
  },
8744
+ /**
8745
+ * 行分组事件
8746
+ */
8747
+ triggerRowGroupExpandEvent (evnt, params) {
8748
+ const { rowGroupExpandedMaps } = internalData
8749
+ const rowGroupOpts = computeRowGroupOpts.value
8750
+ const { row, column } = params
8751
+ const { trigger } = rowGroupOpts
8752
+ if (trigger === 'manual') {
8753
+ return
8754
+ }
8755
+ evnt.stopPropagation()
8756
+ const rowid = getRowid($xeTable, row)
8757
+ const expanded = !rowGroupExpandedMaps[rowid]
8758
+ const columnIndex = $xeTable.getColumnIndex(column)
8759
+ const $columnIndex = $xeTable.getVMColumnIndex(column)
8760
+ $xeTable.setRowGroupExpand(row, expanded)
8761
+ dispatchEvent('toggle-row-group-expand', { expanded, column, columnIndex, $columnIndex, row }, evnt)
8762
+ },
8315
8763
  /**
8316
8764
  * 展开树节点事件
8317
8765
  */
@@ -8447,7 +8895,7 @@ export default defineComponent({
8447
8895
  const triggerInput = cell && cell.tagName && cell.tagName.toLowerCase() === 'input'
8448
8896
  const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag
8449
8897
  const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag
8450
- const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag
8898
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag
8451
8899
  const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag
8452
8900
  let isColDragCell = false
8453
8901
  if (rowOpts.drag) {
@@ -8717,7 +9165,7 @@ export default defineComponent({
8717
9165
  evnt.preventDefault()
8718
9166
  return
8719
9167
  }
8720
- const hasCtrlKey = evnt.ctrlKey
9168
+ const isControlKey = hasControlKey(evnt)
8721
9169
  const trEl = evnt.currentTarget as HTMLElement
8722
9170
  const rowid = trEl.getAttribute('rowid') || ''
8723
9171
  const rest = fullAllDataRowIdData[rowid]
@@ -8729,11 +9177,11 @@ export default defineComponent({
8729
9177
  const { dragRow } = reactData
8730
9178
  const offsetY = evnt.clientY - trEl.getBoundingClientRect().y
8731
9179
  const dragPos = offsetY < trEl.clientHeight / 2 ? 'top' : 'bottom'
8732
- internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && hasCtrlKey)
9180
+ internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && isControlKey)
8733
9181
  internalData.prevDragRow = row
8734
9182
  internalData.prevDragPos = dragPos
8735
9183
  if ($xeTable.eqRow(dragRow, row) ||
8736
- (hasCtrlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
9184
+ (isControlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
8737
9185
  (!isCrossDrag && treeConfig && transform && (isPeerDrag ? dragRow[parentField] !== row[parentField] : rest.level))
8738
9186
  ) {
8739
9187
  showDropTip(evnt, trEl, null, false, dragPos)
@@ -8992,7 +9440,7 @@ export default defineComponent({
8992
9440
  evnt.preventDefault()
8993
9441
  return
8994
9442
  }
8995
- const hasCtrlKey = evnt.ctrlKey
9443
+ const isControlKey = hasControlKey(evnt)
8996
9444
  const thEl = evnt.currentTarget as HTMLElement
8997
9445
  const colid = thEl.getAttribute('colid')
8998
9446
  const column = $xeTable.getColumnById(colid)
@@ -9001,7 +9449,7 @@ export default defineComponent({
9001
9449
  const { clientX } = evnt
9002
9450
  const offsetX = clientX - thEl.getBoundingClientRect().x
9003
9451
  const dragPos = offsetX < thEl.clientWidth / 2 ? 'left' : 'right'
9004
- internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && hasCtrlKey)
9452
+ internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && isControlKey)
9005
9453
  internalData.prevDragCol = column
9006
9454
  internalData.prevDragPos = dragPos
9007
9455
  if (column.fixed ||
@@ -9526,17 +9974,19 @@ export default defineComponent({
9526
9974
  */
9527
9975
  scrollToTreeRow (row) {
9528
9976
  const { treeConfig } = props
9977
+ const { isRowGroupStatus } = reactData
9529
9978
  const { tableFullData } = internalData
9530
9979
  const rests: Promise<any>[] = []
9531
- if (treeConfig) {
9980
+ if (treeConfig || isRowGroupStatus) {
9981
+ const rowGroupOpts = computeRowGroupOpts.value
9532
9982
  const treeOpts = computeTreeOpts.value
9533
9983
  const childrenField = treeOpts.children || treeOpts.childrenField
9534
- const matchObj = XEUtils.findTree(tableFullData, item => $xeTable.eqRow(item, row), { children: childrenField })
9984
+ const matchObj = XEUtils.findTree(tableFullData, item => $xeTable.eqRow(item, row), { children: isRowGroupStatus ? rowGroupOpts.mapChildrenField : childrenField })
9535
9985
  if (matchObj) {
9536
9986
  const nodes = matchObj.nodes
9537
9987
  nodes.forEach((row, index) => {
9538
- if (index < nodes.length - 1 && !tableMethods.isTreeExpandByRow(row)) {
9539
- rests.push(tableMethods.setTreeExpand(row, true))
9988
+ if (index < nodes.length - 1 && !$xeTable.isTreeExpandByRow(row)) {
9989
+ rests.push($xeTable.setTreeExpand(row, true))
9540
9990
  }
9541
9991
  })
9542
9992
  }
@@ -9965,7 +10415,7 @@ export default defineComponent({
9965
10415
 
9966
10416
  const renderRowExpandedVNs = () => {
9967
10417
  const { treeConfig } = props
9968
- const { expandColumn } = reactData
10418
+ const { expandColumn, isRowGroupStatus } = reactData
9969
10419
  const tableRowExpandedList = computeTableRowExpandedList.value
9970
10420
  const expandOpts = computeExpandOpts.value
9971
10421
  const { mode } = expandOpts
@@ -9982,13 +10432,15 @@ export default defineComponent({
9982
10432
  const { handleGetRowId } = createHandleGetRowId($xeTable)
9983
10433
  tableRowExpandedList.forEach((row) => {
9984
10434
  const expandOpts = computeExpandOpts.value
9985
- const { height: expandHeight, padding } = expandOpts
9986
- const { fullAllDataRowIdData } = internalData
10435
+ const { height: expandHeight, padding, indent } = expandOpts
10436
+ const { fullAllDataRowIdData, fullColumnIdData } = internalData
9987
10437
  const treeOpts = computeTreeOpts.value
9988
10438
  const { transform, seqMode } = treeOpts
9989
10439
  const cellStyle: Record<string, string> = {}
9990
10440
  const rowid = handleGetRowId(row)
9991
10441
  const rowRest = fullAllDataRowIdData[rowid]
10442
+ const colid = expandColumn.id
10443
+ const colRest = fullColumnIdData[colid] || {}
9992
10444
  let rowLevel = 0
9993
10445
  let seq: string | number = -1
9994
10446
  let _rowIndex = -1
@@ -9996,7 +10448,7 @@ export default defineComponent({
9996
10448
  let $rowIndex = -1
9997
10449
  if (rowRest) {
9998
10450
  rowLevel = rowRest.level
9999
- if (treeConfig && transform && seqMode === 'increasing') {
10451
+ if (isRowGroupStatus || (treeConfig && transform && seqMode === 'increasing')) {
10000
10452
  seq = rowRest._index + 1
10001
10453
  } else {
10002
10454
  seq = rowRest.seq
@@ -10008,10 +10460,39 @@ export default defineComponent({
10008
10460
  if (expandHeight) {
10009
10461
  cellStyle.height = `${expandHeight}px`
10010
10462
  }
10011
- if (treeConfig) {
10012
- cellStyle.paddingLeft = `${(rowLevel * treeOpts.indent) + 30}px`
10463
+ if (isRowGroupStatus || treeConfig) {
10464
+ cellStyle.paddingLeft = `${(rowLevel * (XEUtils.isNumber(indent) ? indent : treeOpts.indent)) + 30}px`
10465
+ }
10466
+ let columnIndex = -1
10467
+ let $columnIndex = -1
10468
+ let _columnIndex = -1
10469
+ if (colRest) {
10470
+ columnIndex = colRest.index
10471
+ $columnIndex = colRest.$index
10472
+ _columnIndex = colRest._index
10473
+ }
10474
+ const expandParams: VxeTableDefines.CellRenderDataParams = {
10475
+ $grid: $xeGrid,
10476
+ $table: $xeTable,
10477
+ seq,
10478
+ column: expandColumn,
10479
+ columnIndex,
10480
+ $columnIndex,
10481
+ _columnIndex,
10482
+ fixed: '',
10483
+ type: 'body',
10484
+ level: rowLevel,
10485
+ rowid,
10486
+ row,
10487
+ rowIndex,
10488
+ $rowIndex,
10489
+ _rowIndex,
10490
+ isHidden: false,
10491
+ isEdit: false,
10492
+ visibleData: [],
10493
+ data: [],
10494
+ items: []
10013
10495
  }
10014
- const expandParams = { $table: $xeTable, seq, column: expandColumn, fixed: '', type: 'body', level: rowLevel, row, rowIndex, $rowIndex, _rowIndex }
10015
10496
  expandVNs.push(
10016
10497
  h('div', {
10017
10498
  key: rowid,
@@ -10164,7 +10645,7 @@ export default defineComponent({
10164
10645
 
10165
10646
  const renderVN = () => {
10166
10647
  const { loading, stripe, showHeader, height, treeConfig, mouseConfig, showFooter, highlightCell, highlightHoverRow, highlightHoverColumn, editConfig, editRules } = props
10167
- const { isGroup, overflowX, overflowY, scrollXLoad, scrollYLoad, tableData, initStore, columnStore, filterStore, customStore } = reactData
10648
+ const { isGroup, overflowX, overflowY, scrollXLoad, scrollYLoad, tableData, initStore, isRowGroupStatus, columnStore, filterStore, customStore } = reactData
10168
10649
  const { leftList, rightList } = columnStore
10169
10650
  const loadingSlot = slots.loading
10170
10651
  const tableTipConfig = computeTableTipConfig.value
@@ -10205,6 +10686,7 @@ export default defineComponent({
10205
10686
  'is--header': showHeader,
10206
10687
  'is--footer': showFooter,
10207
10688
  'is--group': isGroup,
10689
+ 'is-row-group': isRowGroupStatus,
10208
10690
  'is--tree-line': treeConfig && (treeOpts.showLine || treeOpts.line),
10209
10691
  'is--fixed-left': leftList.length,
10210
10692
  'is--fixed-right': rightList.length,
@@ -10587,6 +11069,10 @@ export default defineComponent({
10587
11069
  })
10588
11070
  })
10589
11071
 
11072
+ watch(computeRowGroupFields, (val) => {
11073
+ handleUpdateRowGroup(val)
11074
+ })
11075
+
10590
11076
  if ($xeTabs) {
10591
11077
  watch(() => $xeTabs ? $xeTabs.reactData.resizeFlag : null, () => {
10592
11078
  handleGlobalResizeEvent()
@@ -10621,11 +11107,15 @@ export default defineComponent({
10621
11107
  const columnOpts = computeColumnOpts.value
10622
11108
  const rowOpts = computeRowOpts.value
10623
11109
  const customOpts = computeCustomOpts.value
11110
+ const rowGroupOpts = computeRowGroupOpts.value
11111
+ const { groupFields } = rowGroupOpts
10624
11112
 
10625
11113
  if (columnOpts.drag || rowOpts.drag || customOpts.allowSort) {
10626
11114
  initTpImg()
10627
11115
  }
10628
11116
 
11117
+ handleUpdateRowGroup(groupFields)
11118
+
10629
11119
  nextTick(() => {
10630
11120
  const { data, exportConfig, importConfig, treeConfig, showOverflow, highlightCurrentRow, highlightCurrentColumn } = props
10631
11121
  const { scrollXStore, scrollYStore } = internalData
@@ -10641,8 +11131,6 @@ export default defineComponent({
10641
11131
  const importOpts = computeImportOpts.value
10642
11132
  const currentRowOpts = computeCurrentRowOpts.value
10643
11133
  const currentColumnOpts = computeCurrentColumnOpts.value
10644
- const virtualXOpts = computeVirtualXOpts.value
10645
- const virtualYOpts = computeVirtualYOpts.value
10646
11134
  const keyboardOpts = computeKeyboardOpts.value
10647
11135
 
10648
11136
  if (props.rowId) {
@@ -10769,19 +11257,19 @@ export default defineComponent({
10769
11257
  }
10770
11258
 
10771
11259
  // 如果不支持虚拟滚动
10772
- if (props.spanMethod) {
10773
- if (virtualXOpts.enabled) {
10774
- warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-x-config.enabled=false'])
10775
- }
10776
- if (virtualYOpts.enabled) {
10777
- warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-y-config.enabled=false'])
10778
- }
10779
- }
10780
- if (props.footerSpanMethod) {
10781
- if (virtualXOpts.enabled) {
10782
- warnLog('vxe.error.notConflictProp', ['footer-span-method', 'virtual-x-config.enabled=false'])
10783
- }
10784
- }
11260
+ // if (props.spanMethod) {
11261
+ // if (virtualXOpts.enabled) {
11262
+ // warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-x-config.enabled=false'])
11263
+ // }
11264
+ // if (virtualYOpts.enabled) {
11265
+ // warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-y-config.enabled=false'])
11266
+ // }
11267
+ // }
11268
+ // if (props.footerSpanMethod) {
11269
+ // if (virtualXOpts.enabled) {
11270
+ // warnLog('vxe.error.notConflictProp', ['footer-span-method', 'virtual-x-config.enabled=false'])
11271
+ // }
11272
+ // }
10785
11273
 
10786
11274
  // 检查是否有安装需要的模块
10787
11275
  if (props.editConfig && !$xeTable.insert) {