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, 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) {
2443
2551
  if (checked) {
2444
2552
  /**
2445
- * 如果是树勾选
2446
- * 如果方法成立,则添加到临时集合中
2447
- */
2448
- XEUtils.eachTree(afterFullData, (row) => {
2449
- if (isForce || (!checkMethod || checkMethod({ row }))) {
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) {
2577
+ if (checked) {
2578
+ /**
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,7 +3117,13 @@ 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
@@ -2915,7 +3137,8 @@ export default defineComponent({
2915
3137
  reactData.isDragRowMove = false
2916
3138
  // 全量数据
2917
3139
  internalData.tableFullData = fullData
2918
- internalData.tableFullTreeData = treeData
3140
+ internalData.tableFullTreeData = isRGroup ? [] : treeData
3141
+ internalData.tableFullGroupData = isRGroup ? treeData : []
2919
3142
  // 缓存数据
2920
3143
  $xeTable.cacheRowMap(isReset)
2921
3144
  // 原始数据
@@ -3287,7 +3510,7 @@ export default defineComponent({
3287
3510
  */
3288
3511
  const handleBaseTreeExpand = (rows: any[], expanded: boolean) => {
3289
3512
  const { treeNodeColumn } = reactData
3290
- const { fullAllDataRowIdData, tableFullData, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData
3513
+ const { fullAllDataRowIdData, tableFullTreeData, treeExpandedMaps, treeExpandLazyLoadedMaps } = internalData
3291
3514
  const treeOpts = computeTreeOpts.value
3292
3515
  const { reserve, lazy, accordion, toggleMethod } = treeOpts
3293
3516
  const childrenField = treeOpts.children || treeOpts.childrenField
@@ -3300,7 +3523,7 @@ export default defineComponent({
3300
3523
  if (accordion) {
3301
3524
  validRows = validRows.length ? [validRows[validRows.length - 1]] : []
3302
3525
  // 同一级只能展开一个
3303
- const matchObj = XEUtils.findTree(tableFullData, item => item === validRows[0], { children: childrenField })
3526
+ const matchObj = XEUtils.findTree(tableFullTreeData, item => item === validRows[0], { children: childrenField })
3304
3527
  if (matchObj) {
3305
3528
  matchObj.items.forEach(item => {
3306
3529
  const rowid = handleGetRowId(item)
@@ -3355,6 +3578,80 @@ export default defineComponent({
3355
3578
  return handleBaseTreeExpand(rows, expanded).then(() => {
3356
3579
  handleVirtualTreeToList()
3357
3580
  $xeTable.handleTableData()
3581
+ reactData.treeExpandedFlag++
3582
+ updateAfterDataIndex()
3583
+ return nextTick()
3584
+ }).then(() => {
3585
+ return $xeTable.recalculate(true)
3586
+ }).then(() => {
3587
+ setTimeout(() => {
3588
+ $xeTable.updateCellAreas()
3589
+ }, 30)
3590
+ })
3591
+ }
3592
+
3593
+ /**
3594
+ * 展开与收起行分组节点
3595
+ * @param rows
3596
+ * @param expanded
3597
+ * @returns
3598
+ */
3599
+ const handleRowGroupBaseExpand = (rows: any[], expanded: boolean) => {
3600
+ const { fullAllDataRowIdData, tableFullGroupData, rowGroupExpandedMaps } = internalData
3601
+ const rowGroupOpts = computeRowGroupOpts.value
3602
+ const { mapChildrenField, accordion } = rowGroupOpts
3603
+ const { handleGetRowId } = createHandleGetRowId($xeTable)
3604
+ let validRows = rows
3605
+ if (mapChildrenField) {
3606
+ if (accordion) {
3607
+ validRows = validRows.length ? [validRows[validRows.length - 1]] : []
3608
+ // 同一级只能展开一个
3609
+ const matchObj = XEUtils.findTree(tableFullGroupData, item => getRowid($xeTable, item) === getRowid($xeTable, validRows[0]), { children: mapChildrenField })
3610
+ if (matchObj) {
3611
+ matchObj.items.forEach(item => {
3612
+ const rowid = handleGetRowId(item)
3613
+ if (rowGroupExpandedMaps[rowid]) {
3614
+ delete rowGroupExpandedMaps[rowid]
3615
+ }
3616
+ })
3617
+ }
3618
+ }
3619
+ if (expanded) {
3620
+ validRows.forEach((row) => {
3621
+ const rowid = handleGetRowId(row)
3622
+ if (!rowGroupExpandedMaps[rowid]) {
3623
+ const rowRest = fullAllDataRowIdData[rowid]
3624
+ if (rowRest) {
3625
+ if (row[mapChildrenField] && row[mapChildrenField].length) {
3626
+ rowGroupExpandedMaps[rowid] = row
3627
+ }
3628
+ }
3629
+ }
3630
+ })
3631
+ } else {
3632
+ validRows.forEach(item => {
3633
+ const rowid = handleGetRowId(item)
3634
+ if (rowGroupExpandedMaps[rowid]) {
3635
+ delete rowGroupExpandedMaps[rowid]
3636
+ }
3637
+ })
3638
+ }
3639
+ }
3640
+ reactData.rowGroupExpandedFlag++
3641
+ return $xeTable.recalculate()
3642
+ }
3643
+
3644
+ /**
3645
+ * 行分组的展开与收起
3646
+ * @param rows
3647
+ * @param expanded
3648
+ * @returns
3649
+ */
3650
+ const handleRowGroupVirtualExpand = (rows: any[], expanded: boolean) => {
3651
+ return handleRowGroupBaseExpand(rows, expanded).then(() => {
3652
+ handleVirtualTreeToList()
3653
+ $xeTable.handleTableData()
3654
+ reactData.rowGroupExpandedFlag++
3358
3655
  updateAfterDataIndex()
3359
3656
  return nextTick()
3360
3657
  }).then(() => {
@@ -4122,7 +4419,7 @@ export default defineComponent({
4122
4419
  if (!column) {
4123
4420
  return null
4124
4421
  }
4125
- const formatter = column.formatter
4422
+ const { formatter } = column
4126
4423
  const cellValue = getCellValue(row, column)
4127
4424
  let cellLabel = cellValue
4128
4425
  if (formatter) {
@@ -5364,7 +5661,7 @@ export default defineComponent({
5364
5661
  })
5365
5662
  if (isUpdate) {
5366
5663
  if (!remote) {
5367
- tablePrivateMethods.handleTableData(true)
5664
+ $xeTable.handleTableData(true)
5368
5665
  }
5369
5666
  $xeTable.handleColumnSortEvent(new Event('click'), firstColumn)
5370
5667
  }
@@ -5391,7 +5688,7 @@ export default defineComponent({
5391
5688
  clearAllSort()
5392
5689
  }
5393
5690
  if (!sortOpts.remote) {
5394
- tablePrivateMethods.handleTableData(true)
5691
+ $xeTable.handleTableData(true)
5395
5692
  }
5396
5693
  return nextTick().then(updateStyle)
5397
5694
  },
@@ -5536,8 +5833,8 @@ export default defineComponent({
5536
5833
  const expandOpts = computeExpandOpts.value
5537
5834
  const { reserve, lazy, accordion, toggleMethod } = expandOpts
5538
5835
  const lazyRests: any[] = []
5539
- const columnIndex = $xeTable.getColumnIndex(expandColumn)
5540
- const $columnIndex = $xeTable.getVMColumnIndex(expandColumn)
5836
+ const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1
5837
+ const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1
5541
5838
  if (rows) {
5542
5839
  if (!XEUtils.isArray(rows)) {
5543
5840
  rows = [rows]
@@ -5548,9 +5845,9 @@ export default defineComponent({
5548
5845
  internalData.rowExpandedMaps = rowExpandedMaps
5549
5846
  rows = rows.slice(rows.length - 1, rows.length)
5550
5847
  }
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
5848
+ 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
5849
  if (expanded) {
5553
- validRows.forEach((row: any) => {
5850
+ validRows.forEach((row) => {
5554
5851
  const rowid = handleGetRowId(row)
5555
5852
  if (!rowExpandedMaps[rowid]) {
5556
5853
  const rowRest = fullAllDataRowIdData[rowid]
@@ -5639,6 +5936,70 @@ export default defineComponent({
5639
5936
  })
5640
5937
  return rest
5641
5938
  },
5939
+ setRowGroups (fieldOrColumns) {
5940
+ const { rowGroupConfig } = props
5941
+ if (!rowGroupConfig) {
5942
+ errLog('vxe.error.reqProp', ['row-group-config'])
5943
+ return nextTick()
5944
+ }
5945
+ if (fieldOrColumns) {
5946
+ handleUpdateRowGroup((XEUtils.isArray(fieldOrColumns) ? fieldOrColumns : [fieldOrColumns]).map(fieldOrColumn => {
5947
+ return XEUtils.isString(fieldOrColumn) ? fieldOrColumn : fieldOrColumn.field
5948
+ }))
5949
+ return loadTableData(internalData.tableSynchData, true)
5950
+ }
5951
+ return nextTick()
5952
+ },
5953
+ clearRowGroups () {
5954
+ const { rowGroupConfig } = props
5955
+ if (!rowGroupConfig) {
5956
+ errLog('vxe.error.reqProp', ['row-group-config'])
5957
+ return nextTick()
5958
+ }
5959
+ handleUpdateRowGroup([])
5960
+ return loadTableData(internalData.tableSynchData, true)
5961
+ },
5962
+ isRowGroupRecord (row) {
5963
+ const { isRowGroupStatus } = reactData
5964
+ return isRowGroupStatus && row.isAggregate
5965
+ },
5966
+ isRowGroupExpandByRow (row) {
5967
+ const { rowGroupExpandedFlag } = reactData
5968
+ const { rowGroupExpandedMaps } = internalData
5969
+ return !!rowGroupExpandedFlag && !!rowGroupExpandedMaps[getRowid($xeTable, row)]
5970
+ },
5971
+ setRowGroupExpand (rows, expanded) {
5972
+ if (rows) {
5973
+ if (!XEUtils.isArray(rows)) {
5974
+ rows = [rows]
5975
+ }
5976
+ return handleRowGroupVirtualExpand(rows, expanded)
5977
+ }
5978
+ return nextTick()
5979
+ },
5980
+ setAllRowGroupExpand (expanded) {
5981
+ const { tableFullGroupData } = internalData
5982
+ const rowGroupOpts = computeRowGroupOpts.value
5983
+ const { mapChildrenField } = rowGroupOpts
5984
+ const rgExpandedMaps: Record<string, any> = {}
5985
+ if (expanded && mapChildrenField) {
5986
+ XEUtils.eachTree(tableFullGroupData, (row) => {
5987
+ if (row[mapChildrenField] && row[mapChildrenField].length) {
5988
+ rgExpandedMaps[getRowid($xeTable, row)] = row
5989
+ }
5990
+ }, { children: mapChildrenField })
5991
+ }
5992
+ internalData.rowGroupExpandedMaps = rgExpandedMaps
5993
+ handleVirtualTreeToList()
5994
+ reactData.rowGroupExpandedFlag++
5995
+ return $xeTable.handleTableData()
5996
+ },
5997
+ clearRowGroupExpand () {
5998
+ internalData.rowGroupExpandedMaps = {}
5999
+ handleVirtualTreeToList()
6000
+ reactData.rowGroupExpandedFlag++
6001
+ return $xeTable.handleTableData()
6002
+ },
5642
6003
  getTreeExpandRecords () {
5643
6004
  const rest: any[] = []
5644
6005
  XEUtils.each(internalData.treeExpandedMaps, item => {
@@ -5681,11 +6042,11 @@ export default defineComponent({
5681
6042
  })
5682
6043
  }
5683
6044
  internalData.treeExpandedMaps = {}
5684
- reactData.treeExpandedFlag++
5685
6045
  if (transform) {
5686
6046
  handleVirtualTreeToList()
5687
- return $xeTable.handleTableData()
6047
+ $xeTable.handleTableData()
5688
6048
  }
6049
+ reactData.treeExpandedFlag++
5689
6050
  return nextTick()
5690
6051
  },
5691
6052
  /**
@@ -5699,15 +6060,16 @@ export default defineComponent({
5699
6060
  const { transform, lazy } = treeOpts
5700
6061
  const rowid = getRowid($xeTable, row)
5701
6062
  if (lazy && row[hasChildField] && !treeExpandLazyLoadedMaps[rowid]) {
5702
- return tableMethods.clearTreeExpandLoaded(row).then(() => {
6063
+ return $xeTable.clearTreeExpandLoaded(row).then(() => {
5703
6064
  return handleAsyncTreeExpandChilds(row)
5704
6065
  }).then(() => {
5705
6066
  if (transform) {
5706
6067
  handleVirtualTreeToList()
5707
- return tablePrivateMethods.handleTableData()
6068
+ $xeTable.handleTableData()
5708
6069
  }
6070
+ reactData.treeExpandedFlag++
5709
6071
  }).then(() => {
5710
- return tableMethods.recalculate()
6072
+ return $xeTable.recalculate()
5711
6073
  })
5712
6074
  }
5713
6075
  return nextTick()
@@ -5717,13 +6079,13 @@ export default defineComponent({
5717
6079
  warnLog('vxe.error.delFunc', ['reloadTreeChilds', 'reloadTreeExpand'])
5718
6080
  }
5719
6081
  // 即将废弃
5720
- return tableMethods.reloadTreeExpand(row)
6082
+ return $xeTable.reloadTreeExpand(row)
5721
6083
  },
5722
6084
  /**
5723
6085
  * 切换/展开树节点
5724
6086
  */
5725
6087
  toggleTreeExpand (row) {
5726
- return tableMethods.setTreeExpand(row, !tableMethods.isTreeExpandByRow(row))
6088
+ return $xeTable.setTreeExpand(row, !$xeTable.isTreeExpandByRow(row))
5727
6089
  },
5728
6090
  /**
5729
6091
  * 设置所有树节点的展开与否
@@ -5741,10 +6103,11 @@ export default defineComponent({
5741
6103
  expandeds.push(row)
5742
6104
  }
5743
6105
  }, { children: childrenField })
5744
- return tableMethods.setTreeExpand(expandeds, expanded).then(() => {
6106
+ return $xeTable.setTreeExpand(expandeds, expanded).then(() => {
5745
6107
  if (transform) {
5746
6108
  handleVirtualTreeToList()
5747
- return tableMethods.recalculate()
6109
+ reactData.treeExpandedFlag++
6110
+ return $xeTable.recalculate()
5748
6111
  }
5749
6112
  })
5750
6113
  },
@@ -5792,15 +6155,15 @@ export default defineComponent({
5792
6155
  const { transform, reserve } = treeOpts
5793
6156
  const expList = $xeTable.getTreeExpandRecords()
5794
6157
  internalData.treeExpandedMaps = {}
5795
- reactData.treeExpandedFlag++
5796
6158
  if (reserve) {
5797
6159
  XEUtils.eachTree(tableFullTreeData, row => handleTreeExpandReserve(row, false), { children: childrenField })
5798
6160
  }
5799
6161
  return $xeTable.handleTableData().then(() => {
5800
6162
  if (transform) {
5801
6163
  handleVirtualTreeToList()
5802
- return $xeTable.handleTableData()
6164
+ $xeTable.handleTableData()
5803
6165
  }
6166
+ reactData.treeExpandedFlag++
5804
6167
  }).then(() => {
5805
6168
  if (expList.length) {
5806
6169
  return $xeTable.recalculate()
@@ -6115,7 +6478,7 @@ export default defineComponent({
6115
6478
  hasResizable = 1
6116
6479
  resizableData[colKey] = column.renderWidth
6117
6480
  }
6118
- if (isCustomVisible && (!checkMethod || checkMethod({ column }))) {
6481
+ if (isCustomVisible && (!checkMethod || checkMethod({ $table: $xeTable, column }))) {
6119
6482
  if (!column.visible && column.defaultVisible) {
6120
6483
  hasVisible = 1
6121
6484
  visibleData[colKey] = false
@@ -6391,8 +6754,7 @@ export default defineComponent({
6391
6754
  const hasDeleteKey = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.DELETE)
6392
6755
  const isF2 = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.F2)
6393
6756
  const isContextMenu = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.CONTEXT_MENU)
6394
- const hasMetaKey = evnt.metaKey
6395
- const hasCtrlKey = evnt.ctrlKey
6757
+ const isControlKey = hasControlKey(evnt)
6396
6758
  const hasShiftKey = evnt.shiftKey
6397
6759
  const isAltKey = evnt.altKey
6398
6760
  const operArrow = isLeftArrow || isUpArrow || isRightArrow || isDwArrow
@@ -6452,7 +6814,7 @@ export default defineComponent({
6452
6814
  } else if (isEnter && !isAltKey && keyboardConfig && keyboardOpts.isEnter && (selected.row || actived.row || (treeConfig && (rowOpts.isCurrent || highlightCurrentRow) && currentRow))) {
6453
6815
  const { isLastEnterAppendRow, beforeEnterMethod, enterMethod } = keyboardOpts
6454
6816
  // 退出选中
6455
- if (hasCtrlKey) {
6817
+ if (isControlKey) {
6456
6818
  // 如果是激活编辑状态,则取消编辑
6457
6819
  if (actived.row) {
6458
6820
  const params = actived.args
@@ -6617,7 +6979,7 @@ export default defineComponent({
6617
6979
  .then(() => $xeTable.scrollToRow(parentRow))
6618
6980
  .then(() => $xeTable.triggerCurrentRowEvent(evnt, params))
6619
6981
  }
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))) {
6982
+ } 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
6983
  const { editMode, editMethod } = keyboardOpts
6622
6984
  // 启用编辑后,空格键功能将失效
6623
6985
  // if (isSpacebar) {
@@ -6770,9 +7132,11 @@ export default defineComponent({
6770
7132
  const rTooltipMethod = tooltipMethod || (dragConfig ? dragConfig.rowTooltipMethod : null)
6771
7133
  let tipContent = ''
6772
7134
  if (rTooltipMethod) {
6773
- tipContent = `${rTooltipMethod({
7135
+ const rtParams = {
7136
+ $table: $xeTable,
6774
7137
  row: dragRow
6775
- }) || ''}`
7138
+ }
7139
+ tipContent = `${rTooltipMethod(rtParams) || ''}`
6776
7140
  } else {
6777
7141
  tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || ''])
6778
7142
  }
@@ -6810,9 +7174,11 @@ export default defineComponent({
6810
7174
  const { tooltipMethod } = columnDragOpts
6811
7175
  let tipContent = ''
6812
7176
  if (tooltipMethod) {
6813
- tipContent = `${tooltipMethod({
7177
+ const dtParams = {
7178
+ $table: $xeTable,
6814
7179
  column: dragCol as VxeTableDefines.ColumnInfo
6815
- }) || ''}`
7180
+ }
7181
+ tipContent = `${tooltipMethod(dtParams) || ''}`
6816
7182
  } else {
6817
7183
  tipContent = getI18n('vxe.table.dragTip', [tdEl.textContent || ''])
6818
7184
  }
@@ -7092,11 +7458,8 @@ export default defineComponent({
7092
7458
  */
7093
7459
  cacheRowMap (isReset) {
7094
7460
  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
7461
+ const { isRowGroupStatus } = reactData
7462
+ const { fullAllDataRowIdData, tableFullData, tableFullTreeData, tableFullGroupData, treeExpandedMaps } = internalData
7100
7463
  const fullAllDataRowIdMaps: Record<string, VxeTableDefines.RowCacheItem> = isReset ? {} : { ...fullAllDataRowIdData } // 存在已删除数据
7101
7464
  const fullDataRowIdMaps: Record<string, VxeTableDefines.RowCacheItem> = {}
7102
7465
 
@@ -7123,6 +7486,10 @@ export default defineComponent({
7123
7486
  }
7124
7487
 
7125
7488
  if (treeConfig) {
7489
+ const treeOpts = computeTreeOpts.value
7490
+ const { lazy } = treeOpts
7491
+ const childrenField = treeOpts.children || treeOpts.childrenField
7492
+ const hasChildField = treeOpts.hasChild || treeOpts.hasChildField
7126
7493
  XEUtils.eachTree(tableFullTreeData, (row, index, items, path, parentRow, nodes) => {
7127
7494
  const rowid = handleUpdateRowId(row)
7128
7495
  if (treeConfig && lazy) {
@@ -7137,6 +7504,13 @@ export default defineComponent({
7137
7504
  }
7138
7505
  handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path))
7139
7506
  }, { children: childrenField })
7507
+ } else if (isRowGroupStatus) {
7508
+ const rowGroupOpts = computeRowGroupOpts.value
7509
+ const { mapChildrenField } = rowGroupOpts
7510
+ XEUtils.eachTree(tableFullGroupData, (row, index, items, path, parentRow, nodes) => {
7511
+ const rowid = handleUpdateRowId(row)
7512
+ handleRowCache(row, index, items, parentRow ? -1 : index, parentRow, rowid, nodes.length - 1, toTreePathSeq(path))
7513
+ }, { children: mapChildrenField })
7140
7514
  } else {
7141
7515
  tableFullData.forEach((row, index, items) => {
7142
7516
  handleRowCache(row, index, items, index, null, handleUpdateRowId(row), 0, index + 1)
@@ -7567,6 +7941,7 @@ export default defineComponent({
7567
7941
  : tableMethods.getCustomStoreData()
7568
7942
  if (updateStore) {
7569
7943
  return updateStore({
7944
+ $table: $xeTable,
7570
7945
  id: tableId,
7571
7946
  type,
7572
7947
  storeData
@@ -7637,29 +8012,47 @@ export default defineComponent({
7637
8012
  },
7638
8013
  updateCheckboxStatus () {
7639
8014
  const { treeConfig } = props
7640
- const { selectCheckboxMaps, treeIndeterminateRowMaps } = internalData
8015
+ const { isRowGroupStatus } = reactData
8016
+ const { afterTreeFullData, afterGroupFullData, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData
8017
+ const rowGroupOpts = computeRowGroupOpts.value
7641
8018
  const treeOpts = computeTreeOpts.value
7642
- const { transform, mapChildrenField } = treeOpts
7643
8019
  const childrenField = treeOpts.children || treeOpts.childrenField
7644
8020
  const checkboxOpts = computeCheckboxOpts.value
7645
8021
  const { checkField, checkStrictly, checkMethod } = checkboxOpts
7646
- const { afterTreeFullData } = internalData
7647
8022
  if (checkStrictly) {
7648
8023
  return
7649
8024
  }
7650
- // 树结构
7651
- if (treeConfig) {
8025
+ if (isRowGroupStatus || treeConfig) {
7652
8026
  const { handleGetRowId } = createHandleGetRowId($xeTable)
7653
8027
  const childRowMaps: Record<string, number> = {}
7654
8028
  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])
8029
+
8030
+ if (isRowGroupStatus) {
8031
+ // 行分组
8032
+ const mapChildrenField = rowGroupOpts.mapChildrenField
8033
+ if (mapChildrenField) {
8034
+ XEUtils.eachTree(afterGroupFullData, (row) => {
8035
+ const rowid = handleGetRowId(row)
8036
+ const childList = row[mapChildrenField]
8037
+ if (childList && childList.length && !childRowMaps[rowid]) {
8038
+ childRowMaps[rowid] = 1
8039
+ childRowList.unshift([row, rowid, childList])
8040
+ }
8041
+ }, { children: mapChildrenField })
7661
8042
  }
7662
- }, { children: transform ? mapChildrenField : childrenField })
8043
+ } else if (treeConfig) {
8044
+ // 树结构
8045
+ const { transform, mapChildrenField } = treeOpts
8046
+ XEUtils.eachTree(afterTreeFullData, (row) => {
8047
+ const rowid = handleGetRowId(row)
8048
+ const childList = row[transform ? mapChildrenField : childrenField]
8049
+ if (childList && childList.length && !childRowMaps[rowid]) {
8050
+ childRowMaps[rowid] = 1
8051
+ childRowList.unshift([row, rowid, childList])
8052
+ }
8053
+ }, { children: transform ? mapChildrenField : childrenField })
8054
+ }
8055
+
7663
8056
  childRowList.forEach(vals => {
7664
8057
  const row: string = vals[0]
7665
8058
  const rowid: string = vals[1]
@@ -7672,7 +8065,7 @@ export default defineComponent({
7672
8065
  ? (item) => {
7673
8066
  const childRowid = handleGetRowId(item)
7674
8067
  const isSelect = checkField ? XEUtils.get(item, checkField) : selectCheckboxMaps[childRowid]
7675
- if (checkMethod({ row: item })) {
8068
+ if (checkMethod({ $table: $xeTable, row: item })) {
7676
8069
  if (isSelect) {
7677
8070
  sLen++
7678
8071
  } else if (treeIndeterminateRowMaps[childRowid]) {
@@ -7730,7 +8123,8 @@ export default defineComponent({
7730
8123
  },
7731
8124
  updateAllCheckboxStatus () {
7732
8125
  const { treeConfig } = props
7733
- const { afterFullData, afterTreeFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData
8126
+ const { isRowGroupStatus } = reactData
8127
+ const { afterFullData, afterTreeFullData, afterGroupFullData, checkboxReserveRowMap, selectCheckboxMaps, treeIndeterminateRowMaps } = internalData
7734
8128
  const checkboxOpts = computeCheckboxOpts.value
7735
8129
  const { checkField, checkMethod, showReserveStatus } = checkboxOpts
7736
8130
  const { handleGetRowId } = createHandleGetRowId($xeTable)
@@ -7739,12 +8133,12 @@ export default defineComponent({
7739
8133
  let hLen = 0 // 半选
7740
8134
  let vLen = 0 // 有效行
7741
8135
 
7742
- const rootList = (treeConfig ? afterTreeFullData : afterFullData)
8136
+ const rootList = (treeConfig ? afterTreeFullData : (isRowGroupStatus ? afterGroupFullData : afterFullData))
7743
8137
  rootList.forEach(checkMethod
7744
8138
  ? row => {
7745
8139
  const childRowid = handleGetRowId(row)
7746
8140
  const selected = checkField ? XEUtils.get(row, checkField) : selectCheckboxMaps[childRowid]
7747
- if (checkMethod({ row })) {
8141
+ if (checkMethod({ $table: $xeTable, row })) {
7748
8142
  if (selected) {
7749
8143
  sLen++
7750
8144
  } else if (treeIndeterminateRowMaps[childRowid]) {
@@ -7791,7 +8185,9 @@ export default defineComponent({
7791
8185
  */
7792
8186
  handleBatchSelectRows (rows, checked, isForce) {
7793
8187
  const { treeConfig } = props
8188
+ const { isRowGroupStatus } = reactData
7794
8189
  const { selectCheckboxMaps } = internalData
8190
+ const rowGroupOpts = computeRowGroupOpts.value
7795
8191
  const treeOpts = computeTreeOpts.value
7796
8192
  const { transform, mapChildrenField } = treeOpts
7797
8193
  const childrenField = treeOpts.children || treeOpts.childrenField
@@ -7802,10 +8198,10 @@ export default defineComponent({
7802
8198
  const indeterminateField = checkboxOpts.indeterminateField || checkboxOpts.halfField
7803
8199
  if (checkField) {
7804
8200
  // 树结构
7805
- if (treeConfig && !checkStrictly) {
8201
+ if ((treeConfig || isRowGroupStatus) && !checkStrictly) {
7806
8202
  // 更新子节点状态
7807
8203
  XEUtils.eachTree(rows, (row) => {
7808
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8204
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7809
8205
  XEUtils.set(row, checkField, checked)
7810
8206
  if (indeterminateField) {
7811
8207
  XEUtils.set(row, indeterminateField, false)
@@ -7818,7 +8214,7 @@ export default defineComponent({
7818
8214
  }
7819
8215
  // 列表
7820
8216
  rows.forEach(row => {
7821
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8217
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7822
8218
  XEUtils.set(row, checkField, checked)
7823
8219
  handleCheckboxReserveRow(row, checked)
7824
8220
  }
@@ -7828,29 +8224,48 @@ export default defineComponent({
7828
8224
  }
7829
8225
 
7830
8226
  // 树结构
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]
8227
+ if (!checkStrictly) {
8228
+ if (isRowGroupStatus) {
8229
+ // 更新行分组节点状态
8230
+ XEUtils.eachTree(rows, (row) => {
8231
+ const rowid = handleGetRowId(row)
8232
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
8233
+ if (checked) {
8234
+ selectCheckboxMaps[rowid] = row
8235
+ } else {
8236
+ if (selectCheckboxMaps[rowid]) {
8237
+ delete selectCheckboxMaps[rowid]
8238
+ }
7841
8239
  }
8240
+ handleCheckboxReserveRow(row, checked)
7842
8241
  }
7843
- handleCheckboxReserveRow(row, checked)
7844
- }
7845
- }, { children: transform ? mapChildrenField : childrenField })
7846
- reactData.updateCheckboxFlag++
7847
- return
8242
+ }, { children: rowGroupOpts.mapChildrenField })
8243
+ reactData.updateCheckboxFlag++
8244
+ return
8245
+ } else if (treeConfig) {
8246
+ // 更新子节点状态
8247
+ XEUtils.eachTree(rows, (row) => {
8248
+ const rowid = handleGetRowId(row)
8249
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
8250
+ if (checked) {
8251
+ selectCheckboxMaps[rowid] = row
8252
+ } else {
8253
+ if (selectCheckboxMaps[rowid]) {
8254
+ delete selectCheckboxMaps[rowid]
8255
+ }
8256
+ }
8257
+ handleCheckboxReserveRow(row, checked)
8258
+ }
8259
+ }, { children: transform ? mapChildrenField : childrenField })
8260
+ reactData.updateCheckboxFlag++
8261
+ return
8262
+ }
7848
8263
  }
7849
8264
 
7850
8265
  // 列表
7851
8266
  rows.forEach(row => {
7852
8267
  const rowid = handleGetRowId(row)
7853
- if (isForce || (!checkMethod || checkMethod({ row }))) {
8268
+ if (isForce || (!checkMethod || checkMethod({ $table: $xeTable, row }))) {
7854
8269
  if (checked) {
7855
8270
  if (!selectCheckboxMaps[rowid]) {
7856
8271
  selectCheckboxMaps[rowid] = row
@@ -8021,20 +8436,22 @@ export default defineComponent({
8021
8436
  const radioOpts = computeRadioOpts.value
8022
8437
  const checkboxOpts = computeCheckboxOpts.value
8023
8438
  const keyboardOpts = computeKeyboardOpts.value
8439
+ const rowGroupOpts = computeRowGroupOpts.value
8024
8440
  const rowOpts = computeRowOpts.value
8025
8441
  const columnOpts = computeColumnOpts.value
8026
8442
  const currentColumnOpts = computeCurrentColumnOpts.value
8027
8443
  const { actived, focused } = editStore
8028
8444
  const { row, column } = params
8029
- const { type, treeNode } = column
8445
+ const { type, treeNode, rowGroupNode } = column
8030
8446
  const isRadioType = type === 'radio'
8031
8447
  const isCheckboxType = type === 'checkbox'
8032
8448
  const isExpandType = type === 'expand'
8033
8449
  const cell = evnt.currentTarget as HTMLDivElement
8034
8450
  const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag
8035
8451
  const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag
8036
- const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag
8452
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag
8037
8453
  const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag
8454
+ const triggerRowGroupNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-row-group--node-btn').flag
8038
8455
  params = Object.assign({ cell, triggerRadio, triggerCheckbox, triggerTreeNode, triggerExpandNode }, params)
8039
8456
  if (!triggerCheckbox && !triggerRadio) {
8040
8457
  // 如果是展开行
@@ -8045,10 +8462,14 @@ export default defineComponent({
8045
8462
  if ((treeOpts.trigger === 'row' || (treeNode && treeOpts.trigger === 'cell'))) {
8046
8463
  $xeTable.triggerTreeExpandEvent(evnt, params)
8047
8464
  }
8465
+ // 如果是行分组
8466
+ if ((rowGroupOpts.trigger === 'row' || (rowGroupNode && rowGroupOpts.trigger === 'cell'))) {
8467
+ $xeTable.triggerRowGroupExpandEvent(evnt, params)
8468
+ }
8048
8469
  }
8049
8470
  // 如果点击了树节点
8050
8471
  if (!triggerTreeNode) {
8051
- if (!triggerExpandNode) {
8472
+ if (!triggerExpandNode && !triggerRowGroupNode) {
8052
8473
  // 如果是当前行
8053
8474
  if (rowOpts.isCurrent || highlightCurrentRow) {
8054
8475
  if (!triggerCheckbox && !triggerRadio) {
@@ -8163,7 +8584,9 @@ export default defineComponent({
8163
8584
  }
8164
8585
  },
8165
8586
  triggerCheckRowEvent (evnt: MouseEvent, params, checked) {
8587
+ const { treeConfig } = props
8166
8588
  const { row } = params
8589
+ const { isRowGroupStatus } = reactData
8167
8590
  const { afterFullData } = internalData
8168
8591
  const checkboxOpts = computeCheckboxOpts.value
8169
8592
  const { checkMethod, trigger } = checkboxOpts
@@ -8171,7 +8594,7 @@ export default defineComponent({
8171
8594
  return
8172
8595
  }
8173
8596
  evnt.stopPropagation()
8174
- if (checkboxOpts.isShiftKey && evnt.shiftKey && !props.treeConfig) {
8597
+ if (checkboxOpts.isShiftKey && evnt.shiftKey && !(treeConfig || isRowGroupStatus)) {
8175
8598
  const checkboxRecords = $xeTable.getCheckboxRecords()
8176
8599
  if (checkboxRecords.length) {
8177
8600
  const firstRow = checkboxRecords[0]
@@ -8188,7 +8611,7 @@ export default defineComponent({
8188
8611
  }
8189
8612
  }
8190
8613
  }
8191
- if (!checkMethod || checkMethod({ row })) {
8614
+ if (!checkMethod || checkMethod({ $table: $xeTable, row })) {
8192
8615
  $xeTable.handleBatchSelectRows([row], checked)
8193
8616
  $xeTable.checkSelectionStatus()
8194
8617
  dispatchEvent('checkbox-change', Object.assign({
@@ -8286,7 +8709,7 @@ export default defineComponent({
8286
8709
  * 展开行事件
8287
8710
  */
8288
8711
  triggerRowExpandEvent (evnt, params) {
8289
- const { expandColumn: column } = reactData
8712
+ const { expandColumn } = reactData
8290
8713
  const { rowExpandLazyLoadedMaps } = internalData
8291
8714
  const expandOpts = computeExpandOpts.value
8292
8715
  const { row } = params
@@ -8298,12 +8721,12 @@ export default defineComponent({
8298
8721
  const rowid = getRowid($xeTable, row)
8299
8722
  if (!lazy || !rowExpandLazyLoadedMaps[rowid]) {
8300
8723
  const expanded = !$xeTable.isRowExpandByRow(row)
8301
- const columnIndex = $xeTable.getColumnIndex(column)
8302
- const $columnIndex = $xeTable.getVMColumnIndex(column)
8724
+ const columnIndex = expandColumn ? $xeTable.getColumnIndex(expandColumn) : -1
8725
+ const $columnIndex = expandColumn ? $xeTable.getVMColumnIndex(expandColumn) : -1
8303
8726
  $xeTable.setRowExpand(row, expanded)
8304
8727
  dispatchEvent('toggle-row-expand', {
8305
8728
  expanded,
8306
- column,
8729
+ column: expandColumn,
8307
8730
  columnIndex,
8308
8731
  $columnIndex,
8309
8732
  row,
@@ -8312,6 +8735,25 @@ export default defineComponent({
8312
8735
  }, evnt)
8313
8736
  }
8314
8737
  },
8738
+ /**
8739
+ * 行分组事件
8740
+ */
8741
+ triggerRowGroupExpandEvent (evnt, params) {
8742
+ const { rowGroupExpandedMaps } = internalData
8743
+ const rowGroupOpts = computeRowGroupOpts.value
8744
+ const { row, column } = params
8745
+ const { trigger } = rowGroupOpts
8746
+ if (trigger === 'manual') {
8747
+ return
8748
+ }
8749
+ evnt.stopPropagation()
8750
+ const rowid = getRowid($xeTable, row)
8751
+ const expanded = !rowGroupExpandedMaps[rowid]
8752
+ const columnIndex = $xeTable.getColumnIndex(column)
8753
+ const $columnIndex = $xeTable.getVMColumnIndex(column)
8754
+ $xeTable.setRowGroupExpand(row, expanded)
8755
+ dispatchEvent('toggle-row-group-expand', { expanded, column, columnIndex, $columnIndex, row }, evnt)
8756
+ },
8315
8757
  /**
8316
8758
  * 展开树节点事件
8317
8759
  */
@@ -8447,7 +8889,7 @@ export default defineComponent({
8447
8889
  const triggerInput = cell && cell.tagName && cell.tagName.toLowerCase() === 'input'
8448
8890
  const triggerRadio = isRadioType && getEventTargetNode(evnt, cell, 'vxe-cell--radio').flag
8449
8891
  const triggerCheckbox = isCheckboxType && getEventTargetNode(evnt, cell, 'vxe-cell--checkbox').flag
8450
- const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-tree--btn-wrapper').flag
8892
+ const triggerTreeNode = treeNode && getEventTargetNode(evnt, cell, 'vxe-cell--tree-btn').flag
8451
8893
  const triggerExpandNode = isExpandType && getEventTargetNode(evnt, cell, 'vxe-table--expanded').flag
8452
8894
  let isColDragCell = false
8453
8895
  if (rowOpts.drag) {
@@ -8717,7 +9159,7 @@ export default defineComponent({
8717
9159
  evnt.preventDefault()
8718
9160
  return
8719
9161
  }
8720
- const hasCtrlKey = evnt.ctrlKey
9162
+ const isControlKey = hasControlKey(evnt)
8721
9163
  const trEl = evnt.currentTarget as HTMLElement
8722
9164
  const rowid = trEl.getAttribute('rowid') || ''
8723
9165
  const rest = fullAllDataRowIdData[rowid]
@@ -8729,11 +9171,11 @@ export default defineComponent({
8729
9171
  const { dragRow } = reactData
8730
9172
  const offsetY = evnt.clientY - trEl.getBoundingClientRect().y
8731
9173
  const dragPos = offsetY < trEl.clientHeight / 2 ? 'top' : 'bottom'
8732
- internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && hasCtrlKey)
9174
+ internalData.prevDragToChild = !!(treeConfig && transform && (isCrossDrag && isToChildDrag) && isControlKey)
8733
9175
  internalData.prevDragRow = row
8734
9176
  internalData.prevDragPos = dragPos
8735
9177
  if ($xeTable.eqRow(dragRow, row) ||
8736
- (hasCtrlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
9178
+ (isControlKey && treeConfig && lazy && row[hasChildField] && rowRest && !rowRest.treeLoaded) ||
8737
9179
  (!isCrossDrag && treeConfig && transform && (isPeerDrag ? dragRow[parentField] !== row[parentField] : rest.level))
8738
9180
  ) {
8739
9181
  showDropTip(evnt, trEl, null, false, dragPos)
@@ -8992,7 +9434,7 @@ export default defineComponent({
8992
9434
  evnt.preventDefault()
8993
9435
  return
8994
9436
  }
8995
- const hasCtrlKey = evnt.ctrlKey
9437
+ const isControlKey = hasControlKey(evnt)
8996
9438
  const thEl = evnt.currentTarget as HTMLElement
8997
9439
  const colid = thEl.getAttribute('colid')
8998
9440
  const column = $xeTable.getColumnById(colid)
@@ -9001,7 +9443,7 @@ export default defineComponent({
9001
9443
  const { clientX } = evnt
9002
9444
  const offsetX = clientX - thEl.getBoundingClientRect().x
9003
9445
  const dragPos = offsetX < thEl.clientWidth / 2 ? 'left' : 'right'
9004
- internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && hasCtrlKey)
9446
+ internalData.prevDragToChild = !!((isCrossDrag && isToChildDrag) && isControlKey)
9005
9447
  internalData.prevDragCol = column
9006
9448
  internalData.prevDragPos = dragPos
9007
9449
  if (column.fixed ||
@@ -9526,17 +9968,19 @@ export default defineComponent({
9526
9968
  */
9527
9969
  scrollToTreeRow (row) {
9528
9970
  const { treeConfig } = props
9971
+ const { isRowGroupStatus } = reactData
9529
9972
  const { tableFullData } = internalData
9530
9973
  const rests: Promise<any>[] = []
9531
- if (treeConfig) {
9974
+ if (treeConfig || isRowGroupStatus) {
9975
+ const rowGroupOpts = computeRowGroupOpts.value
9532
9976
  const treeOpts = computeTreeOpts.value
9533
9977
  const childrenField = treeOpts.children || treeOpts.childrenField
9534
- const matchObj = XEUtils.findTree(tableFullData, item => $xeTable.eqRow(item, row), { children: childrenField })
9978
+ const matchObj = XEUtils.findTree(tableFullData, item => $xeTable.eqRow(item, row), { children: isRowGroupStatus ? rowGroupOpts.mapChildrenField : childrenField })
9535
9979
  if (matchObj) {
9536
9980
  const nodes = matchObj.nodes
9537
9981
  nodes.forEach((row, index) => {
9538
- if (index < nodes.length - 1 && !tableMethods.isTreeExpandByRow(row)) {
9539
- rests.push(tableMethods.setTreeExpand(row, true))
9982
+ if (index < nodes.length - 1 && !$xeTable.isTreeExpandByRow(row)) {
9983
+ rests.push($xeTable.setTreeExpand(row, true))
9540
9984
  }
9541
9985
  })
9542
9986
  }
@@ -9965,7 +10409,7 @@ export default defineComponent({
9965
10409
 
9966
10410
  const renderRowExpandedVNs = () => {
9967
10411
  const { treeConfig } = props
9968
- const { expandColumn } = reactData
10412
+ const { expandColumn, isRowGroupStatus } = reactData
9969
10413
  const tableRowExpandedList = computeTableRowExpandedList.value
9970
10414
  const expandOpts = computeExpandOpts.value
9971
10415
  const { mode } = expandOpts
@@ -9982,13 +10426,15 @@ export default defineComponent({
9982
10426
  const { handleGetRowId } = createHandleGetRowId($xeTable)
9983
10427
  tableRowExpandedList.forEach((row) => {
9984
10428
  const expandOpts = computeExpandOpts.value
9985
- const { height: expandHeight, padding } = expandOpts
9986
- const { fullAllDataRowIdData } = internalData
10429
+ const { height: expandHeight, padding, indent } = expandOpts
10430
+ const { fullAllDataRowIdData, fullColumnIdData } = internalData
9987
10431
  const treeOpts = computeTreeOpts.value
9988
10432
  const { transform, seqMode } = treeOpts
9989
10433
  const cellStyle: Record<string, string> = {}
9990
10434
  const rowid = handleGetRowId(row)
9991
10435
  const rowRest = fullAllDataRowIdData[rowid]
10436
+ const colid = expandColumn.id
10437
+ const colRest = fullColumnIdData[colid] || {}
9992
10438
  let rowLevel = 0
9993
10439
  let seq: string | number = -1
9994
10440
  let _rowIndex = -1
@@ -9996,7 +10442,7 @@ export default defineComponent({
9996
10442
  let $rowIndex = -1
9997
10443
  if (rowRest) {
9998
10444
  rowLevel = rowRest.level
9999
- if (treeConfig && transform && seqMode === 'increasing') {
10445
+ if (isRowGroupStatus || (treeConfig && transform && seqMode === 'increasing')) {
10000
10446
  seq = rowRest._index + 1
10001
10447
  } else {
10002
10448
  seq = rowRest.seq
@@ -10008,10 +10454,39 @@ export default defineComponent({
10008
10454
  if (expandHeight) {
10009
10455
  cellStyle.height = `${expandHeight}px`
10010
10456
  }
10011
- if (treeConfig) {
10012
- cellStyle.paddingLeft = `${(rowLevel * treeOpts.indent) + 30}px`
10457
+ if (isRowGroupStatus || treeConfig) {
10458
+ cellStyle.paddingLeft = `${(rowLevel * (XEUtils.isNumber(indent) ? indent : treeOpts.indent)) + 30}px`
10459
+ }
10460
+ let columnIndex = -1
10461
+ let $columnIndex = -1
10462
+ let _columnIndex = -1
10463
+ if (colRest) {
10464
+ columnIndex = colRest.index
10465
+ $columnIndex = colRest.$index
10466
+ _columnIndex = colRest._index
10467
+ }
10468
+ const expandParams: VxeTableDefines.CellRenderDataParams = {
10469
+ $grid: $xeGrid,
10470
+ $table: $xeTable,
10471
+ seq,
10472
+ column: expandColumn,
10473
+ columnIndex,
10474
+ $columnIndex,
10475
+ _columnIndex,
10476
+ fixed: '',
10477
+ type: 'body',
10478
+ level: rowLevel,
10479
+ rowid,
10480
+ row,
10481
+ rowIndex,
10482
+ $rowIndex,
10483
+ _rowIndex,
10484
+ isHidden: false,
10485
+ isEdit: false,
10486
+ visibleData: [],
10487
+ data: [],
10488
+ items: []
10013
10489
  }
10014
- const expandParams = { $table: $xeTable, seq, column: expandColumn, fixed: '', type: 'body', level: rowLevel, row, rowIndex, $rowIndex, _rowIndex }
10015
10490
  expandVNs.push(
10016
10491
  h('div', {
10017
10492
  key: rowid,
@@ -10164,7 +10639,7 @@ export default defineComponent({
10164
10639
 
10165
10640
  const renderVN = () => {
10166
10641
  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
10642
+ const { isGroup, overflowX, overflowY, scrollXLoad, scrollYLoad, tableData, initStore, isRowGroupStatus, columnStore, filterStore, customStore } = reactData
10168
10643
  const { leftList, rightList } = columnStore
10169
10644
  const loadingSlot = slots.loading
10170
10645
  const tableTipConfig = computeTableTipConfig.value
@@ -10205,6 +10680,7 @@ export default defineComponent({
10205
10680
  'is--header': showHeader,
10206
10681
  'is--footer': showFooter,
10207
10682
  'is--group': isGroup,
10683
+ 'is-row-group': isRowGroupStatus,
10208
10684
  'is--tree-line': treeConfig && (treeOpts.showLine || treeOpts.line),
10209
10685
  'is--fixed-left': leftList.length,
10210
10686
  'is--fixed-right': rightList.length,
@@ -10587,6 +11063,10 @@ export default defineComponent({
10587
11063
  })
10588
11064
  })
10589
11065
 
11066
+ watch(computeRowGroupFields, (val) => {
11067
+ handleUpdateRowGroup(val)
11068
+ })
11069
+
10590
11070
  if ($xeTabs) {
10591
11071
  watch(() => $xeTabs ? $xeTabs.reactData.resizeFlag : null, () => {
10592
11072
  handleGlobalResizeEvent()
@@ -10621,11 +11101,15 @@ export default defineComponent({
10621
11101
  const columnOpts = computeColumnOpts.value
10622
11102
  const rowOpts = computeRowOpts.value
10623
11103
  const customOpts = computeCustomOpts.value
11104
+ const rowGroupOpts = computeRowGroupOpts.value
11105
+ const { groupFields } = rowGroupOpts
10624
11106
 
10625
11107
  if (columnOpts.drag || rowOpts.drag || customOpts.allowSort) {
10626
11108
  initTpImg()
10627
11109
  }
10628
11110
 
11111
+ handleUpdateRowGroup(groupFields)
11112
+
10629
11113
  nextTick(() => {
10630
11114
  const { data, exportConfig, importConfig, treeConfig, showOverflow, highlightCurrentRow, highlightCurrentColumn } = props
10631
11115
  const { scrollXStore, scrollYStore } = internalData
@@ -10641,8 +11125,6 @@ export default defineComponent({
10641
11125
  const importOpts = computeImportOpts.value
10642
11126
  const currentRowOpts = computeCurrentRowOpts.value
10643
11127
  const currentColumnOpts = computeCurrentColumnOpts.value
10644
- const virtualXOpts = computeVirtualXOpts.value
10645
- const virtualYOpts = computeVirtualYOpts.value
10646
11128
  const keyboardOpts = computeKeyboardOpts.value
10647
11129
 
10648
11130
  if (props.rowId) {
@@ -10769,19 +11251,19 @@ export default defineComponent({
10769
11251
  }
10770
11252
 
10771
11253
  // 如果不支持虚拟滚动
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
- }
11254
+ // if (props.spanMethod) {
11255
+ // if (virtualXOpts.enabled) {
11256
+ // warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-x-config.enabled=false'])
11257
+ // }
11258
+ // if (virtualYOpts.enabled) {
11259
+ // warnLog('vxe.error.notConflictProp', ['span-method', 'virtual-y-config.enabled=false'])
11260
+ // }
11261
+ // }
11262
+ // if (props.footerSpanMethod) {
11263
+ // if (virtualXOpts.enabled) {
11264
+ // warnLog('vxe.error.notConflictProp', ['footer-span-method', 'virtual-x-config.enabled=false'])
11265
+ // }
11266
+ // }
10785
11267
 
10786
11268
  // 检查是否有安装需要的模块
10787
11269
  if (props.editConfig && !$xeTable.insert) {