spans.vue 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. <template>
  2. <el-table-v2 fixed :columns="columns" :data="data" :width="700" :height="400">
  3. <template #row="props">
  4. <Row v-bind="props" />
  5. </template>
  6. </el-table-v2>
  7. </template>
  8. <script lang="tsx" setup>
  9. import { cloneVNode } from 'vue'
  10. const generateColumns = (length = 10, prefix = 'column-', props?: any) =>
  11. Array.from({ length }).map((_, columnIndex) => ({
  12. ...props,
  13. key: `${prefix}${columnIndex}`,
  14. dataKey: `${prefix}${columnIndex}`,
  15. title: `Column ${columnIndex}`,
  16. width: 150,
  17. }))
  18. const generateData = (
  19. columns: ReturnType<typeof generateColumns>,
  20. length = 200,
  21. prefix = 'row-'
  22. ) =>
  23. Array.from({ length }).map((_, rowIndex) => {
  24. return columns.reduce(
  25. (rowData, column, columnIndex) => {
  26. rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`
  27. return rowData
  28. },
  29. {
  30. id: `${prefix}${rowIndex}`,
  31. parentId: null,
  32. }
  33. )
  34. })
  35. const columns = generateColumns(10)
  36. const data = generateData(columns, 200)
  37. const colSpanIndex = 1
  38. columns[colSpanIndex].colSpan = ({ rowIndex }) => (rowIndex % 4) + 1
  39. columns[colSpanIndex].align = 'center'
  40. const rowSpanIndex = 0
  41. columns[rowSpanIndex].rowSpan = ({ rowIndex }) =>
  42. rowIndex % 2 === 0 && rowIndex <= data.length - 2 ? 2 : 1
  43. const Row = ({ rowData, rowIndex, cells, columns }) => {
  44. const colSpan = columns[colSpanIndex].colSpan({ rowData, rowIndex })
  45. if (colSpan > 1) {
  46. let width = Number.parseInt(cells[colSpanIndex].props.style.width)
  47. for (let i = 1; i < colSpan; i++) {
  48. width += Number.parseInt(cells[colSpanIndex + i].props.style.width)
  49. cells[colSpanIndex + i] = null
  50. }
  51. const style = {
  52. ...cells[colSpanIndex].props.style,
  53. width: `${width}px`,
  54. backgroundColor: 'var(--el-color-primary-light-3)',
  55. }
  56. cells[colSpanIndex] = cloneVNode(cells[colSpanIndex], { style })
  57. }
  58. const rowSpan = columns[rowSpanIndex].rowSpan({ rowData, rowIndex })
  59. if (rowSpan > 1) {
  60. const cell = cells[rowSpanIndex]
  61. const style = {
  62. ...cell.props.style,
  63. backgroundColor: 'var(--el-color-danger-light-3)',
  64. height: `${rowSpan * 50}px`,
  65. alignSelf: 'flex-start',
  66. zIndex: 1,
  67. }
  68. cells[rowSpanIndex] = cloneVNode(cell, { style })
  69. } else {
  70. const style = cells[rowSpanIndex].props.style
  71. // override the cell here for creating a pure node without pollute the style
  72. cells[rowSpanIndex] = (
  73. <div style={{ ...style, width: `${style.width}px` }} />
  74. )
  75. }
  76. return cells
  77. }
  78. </script>