antd Table組件,实现三次表格嵌套;

文章目录

    • 概要
    • 示例
    • 代码
    • 技术细节
      • 小结

概要

本次学习到使用antd里table组件实现三级表格嵌套;
父级点击+号出现子表;
子级点击+号出现孙表;

示例

table表格录制

代码

import React, { useEffect, useState, useMemo } from "react";
import { Table, Divider } from "antd";

const MultiLevelTable = () => {
    const [expandedRowKeys, setExpandedRowKeys] = useState([]);

    // 父表列配置
    const parentColumns = [
        { title: "會員編號", dataIndex: "memberTeamNum", key: "memberTeamNum" },
        { title: "會員姓名", dataIndex: "memberName", key: "memberName" },
        { title: "總收費", dataIndex: "totalAmount", key: "totalAmount" },
    ];

    // 子表列配置(可共用)
    const subTableColumns = [
        { title: "繳費收款類型", dataIndex: "feeType", key: "type" },
        { title: "數量", dataIndex: "number", key: "number" },
        { title: "單價", dataIndex: "price", key: "price" },
        { title: "小計", dataIndex: "total", key: "total" },
    ];

    // 孙表列配置(可自定义)
    const grandChildTableColumns1 = [
        { title: "簽署的服務類別", dataIndex: "type", key: "type1" },
        { title: "開始日期", dataIndex: "startDate", key: "startDate1" },
        { title: "開始時間", dataIndex: "startTime", key: "startTime1" },
        { title: "結束日期", dataIndex: "endDate", key: "endDate1" },
        { title: "結束時間", dataIndex: "endTime", key: "endTime1" },
        { title: "服務狀況", dataIndex: "status", key: "status1" },
    ];
    // 孙表列配置(可自定义)
    const grandChildTableColumns2 = [
        { title: "收款服務名稱", dataIndex: "itemName", key: "itemName22" },
        { title: "日期", dataIndex: "date", key: "date22" },
        { title: "數量", dataIndex: "number", key: "number22" },
        { title: "單價", dataIndex: "price", key: "price22" },
        { title: "小計", dataIndex: "total", key: "total22" },
        { title: "備註", dataIndex: "remark", key: "remark22" },
    ];
    // 孙表列配置(可自定义)
    const grandChildTableColumns3 = [
        { title: "使用的服務物料", dataIndex: "itemName", key: "itemName33" },
        { title: "日期", dataIndex: "date", key: "date33" },
        { title: "數量", dataIndex: "number", key: "number33" },
        { title: "物料費", dataIndex: "price", key: "price33" },
        { title: "小計", dataIndex: "total", key: "total33" },
        { title: "備註", dataIndex: "remark", key: "remark33" },
    ];
    // 孙表列配置(可自定义)
    const grandChildTableColumns4 = [
        { title: "活動編號", dataIndex: "activityId", key: "activityId44" },
        { title: "活動名稱", dataIndex: "activityName", key: "activityName44" },
        { title: "開始日期", dataIndex: "startDate", key: "startDate44" },
        { title: "開始時間", dataIndex: "startTime", key: "startTime44" },
        { title: "結束日期", dataIndex: "endDate", key: "endDate44" },
        { title: "結束時間", dataIndex: "endTime", key: "endTime44" },
        { title: "活動類別", dataIndex: "activityType", key: "activityType44" },
        { title: "數量", dataIndex: "number", key: "number44" },
        { title: "單價", dataIndex: "price", key: "price44" },
        { title: "小計", dataIndex: "total", key: "total44" },
        { title: "備註", dataIndex: "remark", key: "remark44" },
    ];
    const getGrandChildTableColumns = (data) => {
        switch (data.type) {
            case '1':
                return grandChildTableColumns1;
            case '2':
                return grandChildTableColumns2;
            case '3':
                return grandChildTableColumns3;
            case '4':
                return grandChildTableColumns4;
            default:
                return null;
        }
    }

    const getGrandChildTableData = (type) => {
        switch (type) {
            case '1':
                return [
                    { type: "膳食費用", startDate: "02-05-2025", startTime: "12:15", endDate: "N/A", endTime: "", status: "已完成" }
                ]

            case '2':
                return [
                    {
                        itemName: "大件",
                        date: "2023-01-01",
                        number: 1,
                        price: 100,
                        remark: "1"
                    },
                    {
                        itemName: "小件",
                        date: "2023-01-01",
                        number: 1,
                        price: 120,
                        remark: "32",
                    }
                ];

            case '3':
                return [
                    {
                        itemName: "驗血糖物料",
                        date: "2023-01-01",
                        number: 1,
                        price: 140,
                        remark: "臨時展示"
                    }
                ];

            case '4':
                return [
                    {
                        activityId: "UUU/25/05/01",
                        activityName: "中秋展覽",
                        startDate: "2023-01-01",
                        startTime: "9:00",
                        endDate: "2023-01-01",
                        endTime: "17:00",
                        place: "臨時展示",
                        remark: "",
                    }
                ];

            default:
                return null
        }
    }

    // 模拟数据(包含父表、子表1、子表2、孙表)
    const source = useMemo(() => {

        const parentSourceData = [
            {
                key: "1",
                memberTeamNum: "EEE12/0332/23/04",
                memberName: "蔡名杰",
                totalAmount: "269.5",
            },
            {
                key: "2",
                memberTeamNum: "EEE12/03322/23/05",
                memberName: "張小喬",
                totalAmount: "280.8",
            }
        ]
        const childrenSourceData = [
            {
                feeType: "1.膳食費用",
                price: "10.4",
                number: "5",
                type: "1"
            },
            {
                feeType: "2.各類服務收費-膳食送遞費",
                number: "5",
                price: "2.6",
                type: "1"
            },
            {
                feeType: "3.各類服務收費-家居照顧/護理服務費",
                number: "11",
                price: "5.5",
                type: "1"
            },
            {
                feeType: "4.物料費",
                number: "1",
                price: "10.4",
                type: "3"
            },
            {
                feeType: "5.護送交通費",
                number: "5",
                price: "2.6",
                type: "3"
            },
            {
                feeType: "6.其他費用",
                number: "11",
                price: "5.5",
                type: "2"
            },
            {
                feeType: "7.活動收費",
                number: "10",
                price: "300.4",
                type: "4"
            },
        ]

        const combineData = parentSourceData.map((parentItem) => {

            const combineChildrenSourceData = (childrenItem, childrenKey) => {

                const list = getGrandChildTableData(childrenItem?.type)?.map((item, index) => {
                    return {
                        ...item,
                        key: `${childrenKey}-GrandChild${index}`,
                        // total: 123330,
                    }
                })
                console.log("得到的數據是=childrenSourceData=》", list)
                return list ?? []
            }
            return {
                ...parentItem,
                subTable1: childrenSourceData.map((childrenItem, index) => {
                    const childrenKey = `${parentItem.key}-children${index}`
                    return {
                        ...childrenItem,
                        total: childrenItem.number * childrenItem.price,
                        key: childrenKey,
                        childrenList: combineChildrenSourceData(childrenItem, childrenKey),
                        // children: [{}]
                        // children: [{
                        //     key: `${childrenKey}-GrandChild1`,
                        //     price: "測試價格"
                        // }]
                    }
                })
            }

        })
        return combineData
    })

    // 渲染子表(可展开孙表)
    const renderSubTable = (data, tableName) => {
        if (!data || data.length === 0) {
            return <p>{tableName} 无数据</p>;
        }

        const expandedRowRender = (record) => {
            return (
                <div style={{ background: "#fafafa", padding: "16px" }}>
                    {/* <h4>孫表</h4> */}
                    <Table
                        columns={getGrandChildTableColumns(record)}
                        dataSource={record.childrenList}
                        // expandable={null}
                        pagination={false}
                        size="small"
                    />

                </div>
            );
        };
        return (
            <Table
                columns={subTableColumns}
                dataSource={data}
                pagination={false}
                size="small"
                expandable={{
                    expandedRowRender,
                    rowExpandable: (record) => record.childrenList?.length > 0
                }}
            />
        );
    };

    // 父表展开时渲染多个子表
    const expandedRowRender = (record) => {
        return (
            <div style={{ background: "#fafafa", padding: "16px" }}>
                {/* <h4>子表</h4> */}
                {renderSubTable(record.subTable1, "子表1")}


            </div>
        );
    };
    return (
        <Table
            columns={parentColumns}
            dataSource={source}
            expandable={{
                expandedRowRender,
                expandedRowKeys,
                onExpand: (expanded, record) => {
                    const keys = expanded
                        ? [...expandedRowKeys, record.key]
                        : expandedRowKeys.filter((key) => key !== record.key);
                    setExpandedRowKeys(keys);
                },
                rowExpandable: (record) =>
                    record.subTable1.length > 0 || record.subTable2.length > 0,
            }}
        />
    );
};

export default MultiLevelTable;

技术细节

在模拟数据中,不要使用的children字段传入子(孙)表数据;
如果使用了,会出现以下画面:
antd Table組件,实现三次表格嵌套;_第1张图片
代码:

// 省去了部分代码...
  return {
                ...parentItem,
                subTable1: childrenSourceData.map((childrenItem, index) => {
                    const childrenKey = `${parentItem.key}-children${index}`
                    return {
                        ...childrenItem,
                        total: childrenItem.number * childrenItem.price,
                        key: childrenKey,
                        childrenList: combineChildrenSourceData(childrenItem, childrenKey),
                        // children: [{}]
                        // 會有不合理的數據展示
                        children: [{
                            key: `${childrenKey}-GrandChild1`,
                            price: "測試價格"
                        }]
                    }
                })
            }

小结

antd 的官网上没有具体提到dataSource里children的使用;但是我们可以根据事件可以猜出来。当父表有存在子表的时候(有配置expandable属性)且dataSource有存在children数据,那么children会和上一层级一同展示;

你可能感兴趣的:(react.js,javascript,前端)