正常情况下table都是一行展示一条数据,但不幸的是遇到个sb的需求需要按列展示数据。 于是被迫的,无奈的写了个转换方法。 以vue,ant design vue的aTable为例,最终效果如下:
代码如下,因为用手机发的,懒得排版了🤔
<template>
<div class='container'>
<a-table :columns="cols" :dataSource="dataSource" rowKey="a">
</a-table>
</div>
</template>
<script lang="ts">export default { name: "hhh" }</script>
<script lang="ts" setup>
import { ref } from 'vue';
const defaultDataSource = [
{a: 1, b:2, c:3, d: 4, e: 5, header: 'header1'},
{a: 6, b:7, c:8, d: 9, e: 10, header: 'header2'},
{a: 11, b:12, c:13, d: 14, e: 15, header: 'header3' },
{a: 16, b:17, c:18, d: 19, e: 20, header: 'header4'},
{a: 21, b:22, c:23, d: 24, e: 25, header: 'header5'},
{a: 26, b:27, c:28, d: 29, e: 30, header: 'header6'},
{a: 31, b:32, c:33, d: 34, e: 35, header: 'header7'},
{a: 36, b:37, c:38, d: 39, e: 40, header: 'header8'},
];
const defaultCols = [
{ title: 'Header', dataIndex: 'header', key: 'header', display: false },
{ title: 'A', dataIndex: 'a', key: 'a', display: true },
{ title: 'B', dataIndex: 'b', key: 'b', display: true },
{ title: 'C', dataIndex: 'c', key: 'c', display: true },
{ title: 'D', dataIndex: 'd', key: 'd', display: true },
{ title: 'E', dataIndex: 'e', key: 'e', display: true },
]
const dataSource = ref([] as any[])
const cols = ref([] as ColsType[]);
const result = convertToColDisplayConfig(defaultDataSource, defaultCols, {valColLabel: {field: 'header'}});
dataSource.value = result.colDisplayDataSource;
cols.value = result.invisibleCols;
///helpers
/**
* 将原先按行展示的数据转换为按列展示的, 处理完后将invisibleCols作为columns展示, colDisplayDataSource作为DataSource显示
* 并隐藏默认的tableHeader
* @param dataSource
* @param cols
*/
function convertToColDisplayConfig(dataSource: any[], cols: ColsType[], others?: ConvertToColDisplayParams): ColDisplayConvertResult {
/// 按照dataSource和cols, 将DataSource改为按列展示的行数据
const invisibleCols: ColsType[] = [{ title: '', key: '__RowName', dataIndex: '__RowName' }];
const newDataSource: any[] = [];
let headerFirstRowCol: XMaybe<ColsType>;
if (others?.valColLabel?.field) {
headerFirstRowCol = cols.find(each => each.key === others?.valColLabel?.field);
}
if (headerFirstRowCol) {
invisibleCols[0].title = headerFirstRowCol.title;
}
const valCols: ColsType[] = dataSource.map((item, index) => {
const name = '_#colHdn#_' + index;
let title = '';
if (headerFirstRowCol) {
title = item[headerFirstRowCol.dataIndex];
}
return { title, key: name, dataIndex: name };
});
for (let each of cols) {
if (each.display === false) {
continue;
}
const newRow: any = { '__RowName': each.title, '__col__': each };
newDataSource.push(newRow);
}
for (let each of newDataSource) {
setValuesForNewRow(valCols, each, dataSource, others);
delete each.__col__;
}
return { invisibleCols: [...invisibleCols, ...valCols], colDisplayDataSource: newDataSource };
}
function setValuesForNewRow(cols: ColsType[], newData: any, oldDataSource: any[], others?: ConvertToColDisplayParams) {
const rawCol = newData.__col__ as ColsType;
for (let i = 0; i < cols.length; i++) {
const col = cols[i];
const dataRow = oldDataSource[i];
if (rawCol.type === 'rowNumber' && others?.autoSetRowNumber) {
newData[col.key] = i + 1;
}
else {
newData[col.key] = dataRow[rawCol.dataIndex]
}
}
}
///types
type XMaybe<T> = undefined|T;
type ColsType = {
key: string,
title: string,
dataIndex: string,
display?: boolean,
type?: string
}
type ColDisplayConvertResult = {
invisibleCols: ColsType[],
colDisplayDataSource: any[],
}
type ConvertToColDisplayParams = {
/**
* col type 是rowNumber的是否自动按index赋值
*/
autoSetRowNumber?: boolean,
/**
* 列字段取值配置
*/
valColLabel?: {
field: string
}
}
</script>
<style scoped lang="scss"></style>