useGroupingHeaders.ts 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import { addClass, hasClass, query, queryAll } from '@/utils/frontend/dom';
  2. // 表头分组
  3. export default function useGroupingHeaders(tableWrapper: HTMLElement, cellGrid: number[][], fixedColumnsLeft = 0) {
  4. const generateGroupHeaders = () => {
  5. const heighten = ($th: Element, count: number) => {
  6. addClass($th, 'real-th');
  7. const $relative = query($th, '.relative') as HTMLElement;
  8. $relative.style.height = `${count * 26 - 1}px`;
  9. $relative.style.lineHeight = `${count * 26}px`;
  10. };
  11. const grouping = ($thead: HTMLElement, rowNums: number, colNums: number) => {
  12. const $trList = Array.from(queryAll($thead, 'tr'));
  13. if ($trList.length <= 1) return;
  14. const $thList = [] as Element[][];
  15. $trList.forEach($tr => {
  16. const $rowThList = Array.from(queryAll($tr, 'th'));
  17. // 去掉左上角的 th
  18. $rowThList.shift();
  19. $thList.push($rowThList);
  20. });
  21. // 二维数组,记录每个 th 是否已被它正下方的 th 覆盖,初始化为 false 代表没有被覆盖
  22. const coveredGrid = new Array(rowNums).fill(null).map(() => new Array(colNums).fill(false));
  23. for (let i = rowNums - 1; i >= 0; i--) {
  24. for (let j = 0; j < colNums; j++) {
  25. const $th = $thList[i][j];
  26. if (!$th) return;
  27. // coveredGrid[i][j] 为 true 说明这个单元格被它下面的单元格覆盖了,不用再考虑了
  28. if (coveredGrid[i][j] || hasClass($th, 'hiddenHeader')) continue;
  29. coveredGrid[i][j] = true;
  30. // 将当前单元格上面的拥有相同 id 的单元格(这些单元格属于同一个合并单元格)标记为已覆盖:coveredGrid[k][j] = true
  31. let k;
  32. for (k = i - 1; k >= 0; k--) {
  33. if (cellGrid[k][j] !== cellGrid[i][j]) break;
  34. coveredGrid[k][j] = true;
  35. }
  36. // 从当前单元格开始往上数,有几个单元格属于同一个合并单元格
  37. const count = i - k;
  38. if (count > 1) {
  39. heighten($th, count);
  40. }
  41. }
  42. }
  43. };
  44. // handsontable clone top 部分
  45. const $thead = query(tableWrapper, '.ht_clone_top .wtHolder .htCore thead') as HTMLElement;
  46. grouping($thead, cellGrid.length, cellGrid[0].length);
  47. // handsontable clone top left corner 部分
  48. const $topLeftHead = query(tableWrapper, '.ht_clone_top_left_corner .wtHolder .htCore thead') as HTMLElement;
  49. grouping($topLeftHead, cellGrid.length, fixedColumnsLeft);
  50. // 设置左上角的单元格合并为一个单元格
  51. const $topLeftLastTr = Array.from(queryAll($topLeftHead, 'tr')).pop() as HTMLElement;
  52. const $topLeftLastTh = query($topLeftLastTr, 'th') as HTMLElement;
  53. heighten($topLeftLastTh, cellGrid.length);
  54. };
  55. return {
  56. generateGroupHeaders,
  57. };
  58. }