前言
功能解释:遇到的一个需求,是表格的tabledata数组。里面有科室医生还有很多消费指标等数据。然后需要我排序后把科室放在一起。然后在每个科室下面添加一行数据,是小计行。用于计算上面相同科室的所有数据汇总。然后最下面再来个合计行,加上所有的小计。
效果图
刚排序后是这样的表格样子,数据是我模拟的
然后插入小计行后是这样的。
实现方法
逻辑流程:
1,请求拿到表格的数据tableData
2,把数组排序,让科室都在一起,然后合并单元格
3,循环数组,找出对应科室的角标保存到一个数组中,并用科室命名。
4,反转数组,从后面往前面插入,因为从前面开始插入会导致角标变化
5,计算好小计行直接插入就完事了。
代码
可以直接复制查看效果,改改字段就可以用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- 公共css文件 -->
<script src="./ceshi.js"></script>
<link rel="stylesheet" href="/statics/css/common/common.css">
<!-- 公共js文件 -->
<script type="text/javascript" src="/statics/vue_element/common.js"></script>
<!-- vue方面文件 -->
<script src="/statics/vue_element/vue.js"></script>
<script src="/statics/vue_element/element.js"></script>
<link rel="stylesheet" href="/statics/vue_element/element.css">
<script src="/statics/vue_element/axios.js"></script>
<script src="/mixins/quanxian.js"></script>
<title>测试页</title>
</head>
<body>
<div id="app" style="padding:10px;">
<el-table :data="tableDatas" border style="width: 100%" ref="configurationTable" :row-style="rowstyle"
:span-method="objectSpanMethod">
<el-table-column v-for="(arrd,index) in headers" :key="index" :label="arrd.name" align="center" width='100'
show-overflow-tooltip>
<!-- 有子级 -->
<el-table-column v-for="(arrd2,index2) in arrd.child" align="center" :label="arrd2.name"
show-overflow-tooltip>
<template slot-scope="{row, $index}">
<span>{{row[arrd2.key]}}</span>
</template>
</el-table-column>
<!-- 无子级 -->
<template slot-scope="{row, $index}">
<span>{{row[arrd.key]}}</span>
</template>
</el-table-column>
</el-table>
</div>
</body>
<script type="text/javascript">
let v = new Vue({
el: '#app',
data() {
return {
tableDatas: [],//表体
headers: [],//表头
spanArr: []//合并单元格
}
},
mounted() {
this.searchList()
},
methods: {
// 模拟发送请求,拿到表格数据
searchList() {
let that = this
that.tableShow = false
// 模拟数据
that.headers = [{
child: [],
key: "ks",
name: "科室"
},
{
child: [],
key: "doctor",
name: "医生"
},
{
child: [],
key: "ghl",
name: "挂号"
},
{
child: [],
key: "jzl",
name: "就诊"
},
{
child: [],
key: "jz",
name: "体检"
}
],
that.tableDatas = [{
ks: "中医科",
doctor: '中医科医生1',
ghl: 6,
jzl: 5,
jz: 2,
}, {
ks: "中医科",
doctor: '中医科医生2',
ghl: 9,
jzl: 4,
jz: 3,
}, {
ks: "外科",
doctor: '外科医生2',
ghl: 7,
jzl: 3,
jz: 4,
}, {
ks: "外科",
doctor: '外科医生1',
ghl: 5,
jzl: 1,
jz: 5,
}, {
ks: "内科",
doctor: '内科医生3',
ghl: 2,
jzl: 1,
jz: 6,
}, {
ks: "内科",
doctor: '内科医生1',
ghl: 2,
jzl: 12,
jz: 7,
}]
this.tableDatas.sort(this.mysort);
this.groupHandle(that.tableDatas)
let hj = this.hj(that.tableDatas)
this.tableDatas.push(hj)
this.setdates()
},
// 根据科室排序
mysort(a, b) {
if (a.ks !== b.ks) {
if (a.ks !== null && a.ks !== undefined) {
return a.ks < b.ks ? -1 : 1;
} else {
return -1;
}
}
},
// 计算小计行插入位置
groupHandle(Human) {
let doctorMap = {};
for (let i = 0; i < Human.length; i++) {
//找出相同名称的行数
let doctorName = Human[i].ks
if (doctorMap[doctorName] !== undefined) {
doctorMap[doctorName].push(i);
} else {
doctorMap[doctorName] = [i];
}
}
let keyArr = [];
for (let k in doctorMap) {
//取出key并倒序,防止正序插入会影响行下标
keyArr.unshift(k);
}
keyArr.forEach((ele, index) => {
let lastIndex = doctorMap[ele][doctorMap[ele].length - 1]; //找出相同名称最后一行插入合计数据
let obj = this.xj(Human, ele) //计算出小计行数据
Human.splice(lastIndex + 1, 0, obj) //插入
})
},
// 小计行计算
xj(data, name) {
let obj = {
ks: name, //科室名字,用于合并单元格
doctor: '小计',
ghl: 0,
jzl: 0,
jz: 0,
}
data.forEach(item => {
// 科室相同的加起来
if (item.ks == name) {
obj.ghl += (item.ghl ? parseFloat(item.ghl) : 0)
obj.jzl += (item.jzl ? parseFloat(item.jzl) : 0)
obj.jz += (item.jz ? parseFloat(item.jz) : 0)
}
})
return obj
},
// 合计行计算
hj(data) {
let hj = {
ks: '合计',
doctor: '-',
ghl: 0,
jzl: 0,
jz: 0,
}
data.forEach(item => {
// 小计行加起来就是合计
if (item.doctor == '小计') {
hj.ghl += (item.ghl ? parseFloat(item.ghl) : 0)
hj.jzl += (item.jzl ? parseFloat(item.jzl) : 0)
hj.jz += (item.jz ? parseFloat(item.jz) : 0)
}
})
return hj
},
// 行底纹
rowstyle({
row,
rowindex,
}) {
if (row.ks == '合计') {
return "background:#afdfe4;color:#34738f"
}
if (row.doctor == '小计') {
return "background: #D9EDF7;color:#34738f;border-bottom:1px solid #409eff !important;"
}
},
// 合并单元格
objectSpanMethod({
row,
column,
rowIndex,
columnIndex
}) {
if (columnIndex === 0) {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col
};
}
},
// 计算要合并的单元格
setdates() {
let contactDot = 0;
this.spanArr = []
this.tableDatas.forEach((item, index) => {
item.index = index;
if (index === 0) {
this.spanArr.push(1);
} else {
// 根据相同科室来合并
if (item.ks === this.tableDatas[index - 1].ks) {
this.spanArr[contactDot] += 1;
this.spanArr.push(0);
} else {
contactDot = index;
this.spanArr.push(1);
}
}
});
},
}
})
</script>
<style scoped>
</style>
</html>