bodyFoundation.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import BaseFoundation, { DefaultAdapter } from '../base/foundation';
  2. import { get, includes, isMap, findLastIndex, isObject } from 'lodash-es';
  3. import { strings } from './constants';
  4. import { getRecordKey, genExpandedRowKey, getRecordChildren, expandBtnShouldInRow } from './utils';
  5. export interface BodyAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
  6. setVirtualizedData: (virtualizedData: any[], cb: () => void) => void;
  7. setCachedExpandBtnShouldInRow: (cachedExpandBtnShouldInRow: boolean) => void;
  8. setCachedExpandRelatedProps: (cachedExpandRelatedProps: string[]) => void;
  9. observeBodyResize: (bodyWrapDOM: any) => void;
  10. unobserveBodyResize: () => void;
  11. }
  12. export default class TableBodyFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<BodyAdapter<P, S>, P, S> {
  13. init() {
  14. this.initVirtualizedData();
  15. this.initExpandBtnShouldInRow();
  16. /**
  17. * Use ResizeObserver to monitor changes in the size of the body content area, and notify Table to recalculate if it changes. columns #1219
  18. * (Only monitor the scroll.y scene, other scenes are not monitored, because the header of the scroll.y scene is a separate table, and a scrollbar column will be inserted)
  19. */
  20. const { scroll } = this.getProps(); // TODO check: this._adapter.getProps -> this.getProps
  21. if (get(scroll, 'y')) {
  22. this.observeBodyResize();
  23. }
  24. }
  25. destroy() {
  26. this.unobserveBodyResize();
  27. }
  28. initVirtualizedData(cb?: (...args: any[]) => void) {
  29. this._adapter.setVirtualizedData(this.flattenData(this.getProp('dataSource')), cb);
  30. }
  31. initExpandBtnShouldInRow(newExpandRelatedProps?: any[]) {
  32. const props = this.getProps(); // TODO check: this._adapter.getProps -> this.getProps
  33. const cachedExpandBtnShouldInRow = expandBtnShouldInRow(props);
  34. this._adapter.setCachedExpandBtnShouldInRow(cachedExpandBtnShouldInRow);
  35. if (!isObject(newExpandRelatedProps) && !newExpandRelatedProps) {
  36. const expandRelatedProps = strings.EXPAND_RELATED_PROPS;
  37. // eslint-disable-next-line no-param-reassign
  38. newExpandRelatedProps = expandRelatedProps.map(key => get(props, key, undefined));
  39. }
  40. this._adapter.setCachedExpandRelatedProps(newExpandRelatedProps);
  41. }
  42. flattenData(dataSource: any[] = [], level = 0, parentKeys: any[] = [], childrenKeys: any[] = []) {
  43. const flattenData: Array<FlattenData | GroupFlattenData> = [];
  44. const { rowKey, childrenRecordName, expandedRowRender, expandedRowKeys, groups } = this.getProps();
  45. if (level === 0 && isMap(groups)) {
  46. groups.forEach((set, key) => {
  47. const firstIndex = dataSource.findIndex(record => set.has(getRecordKey(record, rowKey)));
  48. if (firstIndex > -1) {
  49. const lastIndex = findLastIndex(dataSource, record => set.has(getRecordKey(record, rowKey)));
  50. const expanded = includes(expandedRowKeys, key);
  51. flattenData.push({
  52. key,
  53. level,
  54. sectionRow: true,
  55. group: set,
  56. groupKey: key,
  57. expanded,
  58. });
  59. if (expanded) {
  60. flattenData.push(
  61. ...this.flattenData(
  62. dataSource.slice(firstIndex, lastIndex + 1),
  63. level + 1,
  64. [...parentKeys],
  65. [...childrenKeys]
  66. )
  67. );
  68. }
  69. }
  70. });
  71. } else {
  72. dataSource.forEach((record, index) => {
  73. const recordKey = getRecordKey(record, rowKey);
  74. const children = getRecordChildren(record, childrenRecordName);
  75. if (level) {
  76. childrenKeys.push(recordKey);
  77. }
  78. const item = {
  79. key: recordKey,
  80. record,
  81. level,
  82. parentKeys: [...parentKeys],
  83. childrenKeys: [...childrenKeys],
  84. };
  85. flattenData.push(item);
  86. const extras = [];
  87. if (includes(expandedRowKeys, recordKey)) {
  88. if (Array.isArray(children) && children.length) {
  89. extras.push(
  90. ...this.flattenData(children, level + 1, [...item.parentKeys], [...item.childrenKeys])
  91. );
  92. } else if (expandedRowRender) {
  93. extras.push({
  94. key: genExpandedRowKey(recordKey),
  95. level,
  96. expandedRow: true,
  97. record,
  98. });
  99. }
  100. flattenData.push(...extras);
  101. }
  102. });
  103. }
  104. return flattenData;
  105. }
  106. /**
  107. * Use ResizeObserver to monitor changes in the size of the body content area, and notify Table to recalculate if it changes. columns #1219
  108. * (Only monitor the scroll.y scene, other scenes are not monitored, because the header of the scroll.y scene is a separate table, and a scrollbar column will be inserted)
  109. * @param {any} bodyDOM
  110. */
  111. observeBodyResize(bodyDOM?: any) {
  112. const { scroll } = this.getProps(); // TODO check: this._adapter.getProps -> this.getProps
  113. if (get(scroll, 'y')) {
  114. return this._adapter.observeBodyResize(bodyDOM);
  115. }
  116. }
  117. unobserveBodyResize() {
  118. return this._adapter.unobserveBodyResize();
  119. }
  120. }
  121. export interface GroupFlattenData {
  122. key: number | string;
  123. level: number;
  124. sectionRow: boolean;
  125. group: Map<string, Record<string, any>[]>;
  126. groupKey: number;
  127. expanded: boolean;
  128. }
  129. export interface FlattenData {
  130. key: number | string;
  131. record: Record<string, any>;
  132. level: number;
  133. parentKeys?: any[];
  134. childrenKeys?: any[];
  135. expandedRow?: boolean;
  136. sectionRow?: boolean;
  137. }