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>
  
相关推荐
打野赵怀真几秒前
react父子组件如何通信?
前端·javascript
Jalor2 分钟前
Flutter 与 HarmonyOS NEXT | IAPKit(应用内支付服务)避坑指南
前端·flutter·harmonyos
市民中心的蟋蟀3 分钟前
第六章 :介绍全局状态管理库
前端·javascript·react.js
uhakadotcom5 分钟前
Figma入门指南:协作设计的新时代
前端·javascript·面试
欲儿7 分钟前
在线记事本——支持Markdown
前端·javascript·程序人生·sqlite·php·轻量级在线记事本
艾克马斯奎普特10 分钟前
Vue.js 3 渐进式实现之响应式系统——第六节:嵌套的 effect 与 effect 栈
前端·vue.js
Nickname肖知寒12 分钟前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·chrome·chrome devtools
FanetheDivine16 分钟前
发现一个Solid中的坑
前端·javascript·react.js
Cache技术分享27 分钟前
40. Java 使用 `switch` 语句进行分支选择
前端·后端
zzkrix33 分钟前
浏览器插件 - kimi 历史会话清理助手
前端