2022-04-29 17:57:39 +08:00
|
|
|
<template>
|
2022-05-05 00:54:49 +08:00
|
|
|
<el-table-v2 fixed :columns="columns" :data="data" :width="700" :height="400">
|
2022-04-29 17:57:39 +08:00
|
|
|
<template #row="props">
|
|
|
|
<Row v-bind="props" />
|
|
|
|
</template>
|
2022-05-05 00:54:49 +08:00
|
|
|
</el-table-v2>
|
2022-04-29 17:57:39 +08:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="tsx" setup>
|
|
|
|
import { cloneVNode } from 'vue'
|
|
|
|
|
|
|
|
const generateColumns = (length = 10, prefix = 'column-', props?: any) =>
|
|
|
|
Array.from({ length }).map((_, columnIndex) => ({
|
|
|
|
...props,
|
|
|
|
key: `${prefix}${columnIndex}`,
|
|
|
|
dataKey: `${prefix}${columnIndex}`,
|
|
|
|
title: `Column ${columnIndex}`,
|
|
|
|
width: 150,
|
|
|
|
}))
|
|
|
|
|
|
|
|
const generateData = (
|
|
|
|
columns: ReturnType<typeof generateColumns>,
|
|
|
|
length = 200,
|
|
|
|
prefix = 'row-'
|
|
|
|
) =>
|
|
|
|
Array.from({ length }).map((_, rowIndex) => {
|
|
|
|
return columns.reduce(
|
|
|
|
(rowData, column, columnIndex) => {
|
|
|
|
rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`
|
|
|
|
return rowData
|
|
|
|
},
|
|
|
|
{
|
|
|
|
id: `${prefix}${rowIndex}`,
|
|
|
|
parentId: null,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
const columns = generateColumns(10)
|
|
|
|
const data = generateData(columns, 200)
|
|
|
|
|
|
|
|
const colSpanIndex = 1
|
|
|
|
columns[colSpanIndex].colSpan = ({ rowIndex }) => (rowIndex % 4) + 1
|
|
|
|
columns[colSpanIndex].align = 'center'
|
|
|
|
|
|
|
|
const rowSpanIndex = 0
|
|
|
|
columns[rowSpanIndex].rowSpan = ({ rowIndex }) =>
|
|
|
|
rowIndex % 2 === 0 && rowIndex <= data.length - 2 ? 2 : 1
|
|
|
|
|
|
|
|
const Row = ({ rowData, rowIndex, cells, columns }) => {
|
|
|
|
const colSpan = columns[colSpanIndex].colSpan({ rowData, rowIndex })
|
|
|
|
if (colSpan > 1) {
|
|
|
|
let width = Number.parseInt(cells[colSpanIndex].props.style.width)
|
|
|
|
for (let i = 1; i < colSpan; i++) {
|
|
|
|
width += Number.parseInt(cells[colSpanIndex + i].props.style.width)
|
|
|
|
cells[colSpanIndex + i] = null
|
|
|
|
}
|
|
|
|
const style = {
|
|
|
|
...cells[colSpanIndex].props.style,
|
|
|
|
width: `${width}px`,
|
|
|
|
backgroundColor: 'var(--el-color-primary-light-3)',
|
|
|
|
}
|
|
|
|
cells[colSpanIndex] = cloneVNode(cells[colSpanIndex], { style })
|
|
|
|
}
|
|
|
|
|
|
|
|
const rowSpan = columns[rowSpanIndex].rowSpan({ rowData, rowIndex })
|
|
|
|
if (rowSpan > 1) {
|
|
|
|
const cell = cells[rowSpanIndex]
|
|
|
|
const style = {
|
|
|
|
...cell.props.style,
|
|
|
|
backgroundColor: 'var(--el-color-danger-light-3)',
|
|
|
|
height: `${rowSpan * 50}px`,
|
|
|
|
alignSelf: 'flex-start',
|
|
|
|
zIndex: 1,
|
|
|
|
}
|
|
|
|
cells[rowSpanIndex] = cloneVNode(cell, { style })
|
|
|
|
} else {
|
|
|
|
const style = cells[rowSpanIndex].props.style
|
|
|
|
// override the cell here for creating a pure node without pollute the style
|
|
|
|
cells[rowSpanIndex] = (
|
|
|
|
<div style={{ ...style, width: `${style.width}px` }} />
|
|
|
|
)
|
|
|
|
}
|
|
|
|
return cells
|
|
|
|
}
|
|
|
|
</script>
|