el-table动态生成多级表头的表格(js + ts)

展示形式:

详细代码:

(js)

javascript 复制代码
<template>
    <div>
      <el-table :data="tableData" style="width: 100%">
        <el-table-column label="题目信息" align="center">
          <el-table-column prop="questionName" label="题目名称"></el-table-column>
          <el-table-column prop="fullScore" label="满分"></el-table-column>
          <el-table-column prop="gradeAvg" label="年级均分"></el-table-column>
          <el-table-column prop="gradeScoreRate" label="年级分数线"></el-table-column>
        </el-table-column>
        <el-table-column v-for="classInfo in classHeaders" :key="classInfo.classScoreId">
          <template #header>
            {{ classInfo.className }}
          </template>
          <el-table-column label="班级均分" align="center">
            <template #default="{ row }">{{ getCellValue(row, classInfo, 'classAvg') }}</template>
          </el-table-column>
          <el-table-column label="班级分数线" align="center">
            <template #default="{ row }">{{ getCellValue(row, classInfo, 'classScoreRate') }}</template>
          </el-table-column>
        </el-table-column>
      </el-table>
    </div>
  </template>
  
  <script>
  import { reactive } from 'vue';
  
  export default {
    data() {
      return {
        tableData: reactive([
  {
    id: 1,
    questionId: 1,
    questionName: '填空题',
    fullScore: 10,
    gradeAvg: 8,
    gradeScoreRate: 0.8,
    questionClassVOList: [{
      classScoreId: 1,
      className: '一班',
      classAvg: 7,
      classScoreRate: 0.7
    }, {
      classScoreId: 2,
      className: '二班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 3,
      className: '三班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 4,
      className: '四班',
      classAvg: 8,
      classScoreRate: 0.8
    }]
  }, {
    id: 2,
    questionId: 2,
    questionName: '选择题',
    fullScore: 10,
    gradeAvg: 8,
    gradeScoreRate: 0.8,
    questionClassVOList: [{
      classScoreId: 1,
      className: '一班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 2,
      className: '二班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 3,
      className: '三班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 4,
      className: '四班',
      classAvg: 8,
      classScoreRate: 0.8
    }]
  }, {
    id: 3,
    questionId: 3,
    questionName: '判断题',
    fullScore: 10,
    gradeAvg: 8,
    gradeScoreRate: 0.8,
    questionClassVOList: [{
      classScoreId: 1,
      className: '一班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 2,
      className: '二班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 3,
      className: '三班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 4,
      className: '四班',
      classAvg: 8,
      classScoreRate: 0.8
    }]
  }, {
    id: 4,
    questionId: 4,
    questionName: '填空题',
    fullScore: 10,
    gradeAvg: 8,
    gradeScoreRate: 0.8,
    questionClassVOList: [{
      classScoreId: 1,
      className: '一班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 2,
      className: '二班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 3,
      className: '三班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 4,
      className: '四班',
      classAvg: 8,
      classScoreRate: 0.8
    }]
  }, {
    id: 5,
    questionId: 5,
    questionName: '简答题',
    fullScore: 10,
    gradeAvg: 8,
    gradeScoreRate: 0.8,
    questionClassVOList: [{
      classScoreId: 1,
      className: '一班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 2,
      className: '二班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 3,
      className: '三班',
      classAvg: 8,
      classScoreRate: 0.8
    }, {
      classScoreId: 4,
      className: '四班',
      classAvg: 8,
      classScoreRate: 0.8
    }]
  }
])  // 你的数据结构
      };
    },
    computed: {
      classHeaders() {
        // 假设每个问题类型下的班级信息结构是一样的,取第一个问题类型下的班级信息来生成表头
        const firstQuestion = this.tableData[0];
        if (firstQuestion) {
          return firstQuestion.questionClassVOList;
        }
        return [];
      }
    },
    methods: {
      getCellValue(row, classInfo, prop) {
        const classData = row.questionClassVOList.find(item => item.classScoreId === classInfo.classScoreId);
        return classData ? classData[prop] : '';
      }
    }
  };
  </script>
  
  <style>
  /* 样式可以根据你的需求进行调整 */
  </style>
  

(ts)

typescript 复制代码
<template>
    <div>
        <el-table :data="tableData" style="width: 100%">
            <el-table-column label="题目信息" align="center">
                <el-table-column prop="questionName" label="题目名称"></el-table-column>
                <el-table-column prop="fullScore" label="满分"></el-table-column>
                <el-table-column prop="gradeAvg" label="年级均分"></el-table-column>
                <el-table-column prop="gradeScoreRate" label="年级分数线"></el-table-column>
            </el-table-column>
            <el-table-column v-for="classInfo in classHeaders" :key="classInfo.classScoreId">
                <template #header>
                    {{ classInfo.className }}
                </template>
                <el-table-column label="班级均分" align="center">
                    <template #default="{ row }">{{ getCellValue(row, classInfo, 'classAvg') }}</template>
                </el-table-column>
                <el-table-column label="班级分数线" align="center">
                    <template #default="{ row }">{{ getCellValue(row, classInfo, 'classScoreRate') }}</template>
                </el-table-column>
            </el-table-column>
        </el-table>
    </div>
</template>
  
<script setup lang="ts">
import { ref, reactive, computed } from 'vue';

interface ClassInfo {
    classScoreId: number;
    className: string;
    classAvg: number;
    classScoreRate: number;
}

interface QuestionClass {
    questionClassVOList: ClassInfo[];
}

interface TableRow extends QuestionClass {
    questionId: number;
    questionName: string;
    fullScore: number;
    gradeAvg: number;
    gradeScoreRate: number;
}

const tableData = reactive<TableRow[]>([
    {
        questionId: 1,
        questionName: '填空题',
        fullScore: 10,
        gradeAvg: 8,
        gradeScoreRate: 0.8,
        questionClassVOList: [{
            classScoreId: 1,
            className: '一班',
            classAvg: 7,
            classScoreRate: 0.7
        }, {
            classScoreId: 2,
            className: '二班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 3,
            className: '三班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 4,
            className: '四班',
            classAvg: 8,
            classScoreRate: 0.8
        }]
    }, {
        questionId: 2,
        questionName: '选择题',
        fullScore: 10,
        gradeAvg: 8,
        gradeScoreRate: 0.8,
        questionClassVOList: [{
            classScoreId: 1,
            className: '一班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 2,
            className: '二班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 3,
            className: '三班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 4,
            className: '四班',
            classAvg: 8,
            classScoreRate: 0.8
        }]
    }, {
        questionId: 3,
        questionName: '判断题',
        fullScore: 10,
        gradeAvg: 8,
        gradeScoreRate: 0.8,
        questionClassVOList: [{
            classScoreId: 1,
            className: '一班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 2,
            className: '二班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 3,
            className: '三班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 4,
            className: '四班',
            classAvg: 8,
            classScoreRate: 0.8
        }]
    }, {
        questionId: 4,
        questionName: '填空题',
        fullScore: 10,
        gradeAvg: 8,
        gradeScoreRate: 0.8,
        questionClassVOList: [{
            classScoreId: 1,
            className: '一班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 2,
            className: '二班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 3,
            className: '三班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 4,
            className: '四班',
            classAvg: 8,
            classScoreRate: 0.8
        }]
    }, {
        questionId: 5,
        questionName: '简答题',
        fullScore: 10,
        gradeAvg: 8,
        gradeScoreRate: 0.8,
        questionClassVOList: [{
            classScoreId: 1,
            className: '一班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 2,
            className: '二班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 3,
            className: '三班',
            classAvg: 8,
            classScoreRate: 0.8
        }, {
            classScoreId: 4,
            className: '四班',
            classAvg: 8,
            classScoreRate: 0.8
        }]
    }
])

const classHeaders = computed<ClassInfo[]>(() => {
    const firstQuestion = tableData[0];
    if (firstQuestion) {
        return firstQuestion.questionClassVOList;
    }
    return [];
});

const getCellValue = (row: TableRow, classInfo: ClassInfo, prop: keyof ClassInfo) => {
    const classData = row.questionClassVOList.find(item => item.classScoreId === classInfo.classScoreId);
    return classData ? classData[prop] : '';
};
</script>
  
<style lang="scss" scoped>
</style>
  
相关推荐
excel9 分钟前
前端加密的作用与使用场景
前端
计算机魔术师1 小时前
纽约时报版权诉讼披露:微软高管内部称训练 AI 是人类历史上最大规模劳动窃取
前端
去伪存真2 小时前
大模型的参数量为什么那么大?
前端·人工智能
IT_陈寒2 小时前
Java空指针这次真把我坑惨了
前端·人工智能·后端
高级程序源3 小时前
django大学生创新创业项目管理系统94923-计算机课程设计、毕业设计
javascript·vue.js·spring boot·后端·python·django·课程设计
八荒启·交互动画3 小时前
# Web特效020—让 Web 特效真正动起来:时间循环应该怎么接
前端·webgl·网页特效·八荒启-交互动画·八荒启
动恰客流统计3 小时前
线下零售数字化浪潮下,客流统计的3个核心发展趋势
大数据·前端·人工智能
用户938515635073 小时前
从小米前端面试题,彻底搞懂闭包、作用域链与 useState 惰性初始化
前端·面试
粥里有勺糖4 小时前
视野修炼第133期 | Native 回春了?
前端·github·agent
aichitang20245 小时前
前端小skill
前端·人工智能·算法·ai·前端框架