为了实现上图效果,最开始打算用el-row、el-col去实现,但发现把表头和数据分成两大列时,数据太多时会导致所在格高度变高。但由于每一格数据肯定不一样,为保持高度样式一致,就需要我们手动去获取最高格的高度之后再设置给其他格,很麻烦..
改写el-table相对来说更简单。关键点:
1、设置:show-header="false"隐藏原本的表头;
2、将纵向表头当成数据,放在table的最前列;
3、如果有多级表头,就得通过设置:span-method="objectSpanMethod"去合并行或列;
4、处理后端返回的数据格式。
一、el-table大致框架:
<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、表头:
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'])
})
多级表头数据:
const moldData = ref([
{
"id": 2,
"name": "知识技能"
},
{
"id": 3,
"name": "硬性条件"
},
{
"id": 4,
"name": "能力素质"
},
{
"id": 104,
"name": "组织贡献"
}
])
处理表头合并行:
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、处理后端返回数据:
后端返回格式:
const readinessList = ref([
{
"groupName": "测试222",
"xuqNum": 200,
"passNum": 0,
"perpare": "0.0%",
"duty": {
"硬性条件": [],
"知识技能": [
{
"name": "知识技能",
"responsibility": "法规政策"
},
{
"name": "知识技能",
"responsibility": "日常办公软件操作"
},
{
"name": "知识技能",
"responsibility": "客户关系与维护"
}
],
"组织贡献": [],
"能力素质": [
{
"name": "能力素质",
"responsibility": "办公软件1"
},
{
"name": "能力素质",
"responsibility": "特别能吃苦"
}
]
}
}
])
处理数据的函数:
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 []
}
}
处理后的数据格式: