table按列展示一条数据

155 阅读2分钟

正常情况下table都是一行展示一条数据,但不幸的是遇到个sb的需求需要按列展示数据。 于是被迫的,无奈的写了个转换方法。 以vue,ant design vue的aTable为例,最终效果如下:

Weixin Image_20240517185903.png

代码如下,因为用手机发的,懒得排版了🤔

<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>