grouping-header.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <template>
  2. <el-table-v2
  3. fixed
  4. :columns="fixedColumns"
  5. :data="data"
  6. :header-height="[50, 40, 50]"
  7. :header-class="headerClass"
  8. :width="700"
  9. :height="400"
  10. >
  11. <template #header="props">
  12. <customized-header v-bind="props" />
  13. </template>
  14. </el-table-v2>
  15. </template>
  16. <script lang="tsx" setup>
  17. import { TableV2FixedDir, TableV2Placeholder } from 'element-plus'
  18. import type { FunctionalComponent } from 'vue'
  19. import type {
  20. HeaderClassNameGetter,
  21. TableV2CustomizedHeaderSlotParam,
  22. } from 'element-plus'
  23. const generateColumns = (length = 10, prefix = 'column-', props?: any) =>
  24. Array.from({ length }).map((_, columnIndex) => ({
  25. ...props,
  26. key: `${prefix}${columnIndex}`,
  27. dataKey: `${prefix}${columnIndex}`,
  28. title: `Column ${columnIndex}`,
  29. width: 150,
  30. }))
  31. const generateData = (
  32. columns: ReturnType<typeof generateColumns>,
  33. length = 200,
  34. prefix = 'row-'
  35. ) =>
  36. Array.from({ length }).map((_, rowIndex) => {
  37. return columns.reduce(
  38. (rowData, column, columnIndex) => {
  39. rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`
  40. return rowData
  41. },
  42. {
  43. id: `${prefix}${rowIndex}`,
  44. parentId: null,
  45. }
  46. )
  47. })
  48. const columns = generateColumns(15)
  49. const data = generateData(columns, 200)
  50. const fixedColumns = columns.map((column, columnIndex) => {
  51. let fixed: TableV2FixedDir | undefined = undefined
  52. if (columnIndex < 3) fixed = TableV2FixedDir.LEFT
  53. if (columnIndex > 12) fixed = TableV2FixedDir.RIGHT
  54. return { ...column, fixed, width: 100 }
  55. })
  56. const CustomizedHeader: FunctionalComponent<
  57. TableV2CustomizedHeaderSlotParam
  58. > = ({ cells, columns, headerIndex }) => {
  59. if (headerIndex === 2) return cells
  60. const groupCells = [] as typeof cells
  61. let width = 0
  62. let idx = 0
  63. columns.forEach((column, columnIndex) => {
  64. if (column.placeholderSign === TableV2Placeholder)
  65. groupCells.push(cells[columnIndex])
  66. else {
  67. width += cells[columnIndex].props!.column.width
  68. idx++
  69. const nextColumn = columns[columnIndex + 1]
  70. if (
  71. columnIndex === columns.length - 1 ||
  72. nextColumn.placeholderSign === TableV2Placeholder ||
  73. idx === (headerIndex === 0 ? 4 : 2)
  74. ) {
  75. groupCells.push(
  76. <div
  77. class="flex items-center justify-center custom-header-cell"
  78. role="columnheader"
  79. style={{
  80. ...cells[columnIndex].props!.style,
  81. width: `${width}px`,
  82. }}
  83. >
  84. Group width {width}
  85. </div>
  86. )
  87. width = 0
  88. idx = 0
  89. }
  90. }
  91. })
  92. return groupCells
  93. }
  94. const headerClass = ({
  95. headerIndex,
  96. }: Parameters<HeaderClassNameGetter<any>>[0]) => {
  97. if (headerIndex === 1) return 'el-primary-color'
  98. return ''
  99. }
  100. </script>
  101. <style>
  102. .el-el-table-v2__header-row .custom-header-cell {
  103. border-right: 1px solid var(--el-border-color);
  104. }
  105. .el-el-table-v2__header-row .custom-header-cell:last-child {
  106. border-right: none;
  107. }
  108. .el-primary-color {
  109. background-color: var(--el-color-primary);
  110. color: var(--el-color-white);
  111. font-size: 14px;
  112. font-weight: bold;
  113. }
  114. .el-primary-color .custom-header-cell {
  115. padding: 0 4px;
  116. }
  117. </style>