el-table 实现纵向多级表头

为了实现上图效果,最开始打算用el-row、el-col去实现,但发现把表头和数据分成两大列时,数据太多时会导致所在格高度变高。但由于每一格数据肯定不一样,为保持高度样式一致,就需要我们手动去获取最高格的高度之后再设置给其他格,很麻烦..

改写el-table相对来说更简单。关键点:

1、设置:show-header="false"隐藏原本的表头;

2、将纵向表头当成数据,放在table的最前列;

3、如果有多级表头,就得通过设置:span-method="objectSpanMethod"去合并行或列;

4、处理后端返回的数据格式。

一、el-table大致框架:

javascript 复制代码
<template>
    <el-table :show-header="false" :span-method="objectSpanMethod" ref="readinessRef" class="tableBox" v-loading="loading" :data="getIValues" fit border style="width: 100%" :cell-style="{'background-color': '#fafafa', 'color': 'rgba(51, 66, 97, 0.6)', 'font-weight': '300'}">
        <el-table-column v-for="(item, index) in getIHeaders" :key="index" :prop="item" align="center" :width="[0,1].indexOf(index)!=-1 ? '150px':'300px'" :min-width="[0,1].indexOf(index)==-1 ? '300px':''">
          <template #default="scope">
            <div v-if="[0,1].indexOf(index)==-1 && scope.row.title == '能力图解'" class="perpareBox">
              <ul style="text-align: left;">
                <li v-for="(liItem,liIndex) in getResList(scope.row[item][scope.row.moldTitle])" :key="liIndex">{{liItem}}</li>
              </ul>
            </div>
            <div v-if="index!=0 && scope.row.title == '人力资源准备度'" class="perpareBox">
              <div class="num">
                {{scope.row[item]}}
              </div>
              <div v-if="parseFloat(scope.row[item])<0.5" class="circleRed"></div>
              <div v-else-if="parseFloat(scope.row[item])>=0.8" class="circleGreen"></div>
              <div v-else class="circleYellow"></div>
            </div>
          </template>
        </el-table-column>
    </el-table>
</template>

二、所需数据格式:

1、表头:

javascript 复制代码
const iHeaders = ref([
  {
    prop: 'groupName',
    label: '工作群组'
  },
  {
    prop: 'duty',
    label: '能力图解'
  },
  {
    prop: 'xuqNum',
    label: '需求数量'
  },
  {
    prop: 'passNum',
    label: '合格数'
  },
  {
    prop: 'perpare',
    label: '人力资源准备度'
  }
])

const getIHeaders = computed(() => {
  return readinessList.value.reduce((pre, cur, index) => pre.concat(`value${index}`), ['title', 'moldTitle'])
})

多级表头数据:

javascript 复制代码
const moldData = ref([
                {
                    "id": 2,
                    "name": "知识技能"
                },
                {
                    "id": 3,
                    "name": "硬性条件"
                },
                {
                    "id": 4,
                    "name": "能力素质"
                },
                {
                    "id": 104,
                    "name": "组织贡献"
                }
            ])

处理表头合并行:

javascript 复制代码
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
  let moldDataIndex = moldData.value.length
  // console.log('moldDataIndex', moldDataIndex)
  if (rowIndex < 1 || rowIndex > moldDataIndex) {
    if (columnIndex === 0) {
      return [1, 2] // 一、二列表头合并
    } else if (columnIndex === 1) {
      return [0, 0]
    }
  }
  if (columnIndex === 0) {
    if (rowIndex == 1) {
      return {
        rowspan: moldDataIndex, //二、三、四、五行表头合并
        colspan: 1
      }
    } else {
      return {
        rowspan: 0,
        colspan: 0
      }
    }
  }
}

2、处理后端返回数据:

后端返回格式:

javascript 复制代码
const readinessList = ref([
        {
            "groupName": "测试222",
            "xuqNum": 200,
            "passNum": 0,
            "perpare": "0.0%",
            "duty": {
                "硬性条件": [],
                "知识技能": [
                    {
                        "name": "知识技能",
                        "responsibility": "法规政策"
                    },
                    {
                        "name": "知识技能",
                        "responsibility": "日常办公软件操作"
                    },
                    {
                        "name": "知识技能",
                        "responsibility": "客户关系与维护"
                    }
                ],
                "组织贡献": [],
                "能力素质": [
                    {
                        "name": "能力素质",
                        "responsibility": "办公软件1"
                    },
                    {
                        "name": "能力素质",
                        "responsibility": "特别能吃苦"
                    }
                ]
            }
        }
])

处理数据的函数:

javascript 复制代码
const getIValues = computed(() => {
  return handleData(readinessList.value)
})

function handleData(data) {
  let list = []
  if (data.length != 0) {
    iHeaders.value.forEach(headers => {
      let obj = {}
      if (headers.label == '能力图解') {
        moldData.value.forEach(mold => { // 处理多级表头
          obj = data.reduce((pre, cur, index) => Object.assign(pre, { ['value' + index]: cur[headers.prop] }), { title: headers.label, moldTitle: mold.name })
          list.push(obj)
        })
      } else {
        obj = data.reduce((pre, cur, index) => Object.assign(pre, { ['value' + index]: cur[headers.prop] }), { title: headers.label })
        list.push(obj)
      }
    })
    return list
  } else {
    return []
  }
}

处理后的数据格式:

相关推荐
汝生淮南吾在北2 小时前
SpringBoot+Vue饭店点餐管理系统
java·vue.js·spring boot·毕业设计·毕设
酒尘&5 小时前
JS数组不止Array!索引集合类全面解析
开发语言·前端·javascript·学习·js
学历真的很重要5 小时前
VsCode+Roo Code+Gemini 2.5 Pro+Gemini Balance AI辅助编程环境搭建(理论上通过多个Api Key负载均衡达到无限免费Gemini 2.5 Pro)
前端·人工智能·vscode·后端·语言模型·负载均衡·ai编程
用户47949283569156 小时前
"讲讲原型链" —— 面试官最爱问的 JavaScript 基础
前端·javascript·面试
用户47949283569157 小时前
2025 年 TC39 都在忙什么?Import Bytes、Iterator Chunking 来了
前端·javascript·面试
JIngJaneIL7 小时前
基于Java非遗传承文化管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot
+VX:Fegn08957 小时前
计算机毕业设计|基于springboot + vue心理健康管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
大怪v8 小时前
【Virtual World 04】我们的目标,无限宇宙!!
前端·javascript·代码规范
狂炫冰美式8 小时前
不谈技术,搞点文化 🧀 —— 从复活一句明代残诗破局产品迭代
前端·人工智能·后端
xw59 小时前
npm几个实用命令
前端·npm