思路:首先利用DataTables的重构功能,后台计算出td跨多少行
1.先看看效果
2.html代码,含js代码
2.1 common.js
/**
* Created by hdwang on 2017/6/23.
*/
var language = { "search": "", "sSearch" : "搜索", "sUrl" : "", "sProcessing" : "正在加载数据...", "sLengthMenu" : "显示_MENU_条 ", "sZeroRecords" : "没有您要搜索的内容",
"sInfo" : "从_START_ 到 _END_ 条记录——总记录数为 _TOTAL_ 条", "sInfoEmpty" : "记录数为0", "sInfoFiltered" : "(全部记录数 _MAX_ 条)", "sInfoPostFix" : "",
"oPaginate": { "sFirst" : "第一页", "sPrevious" : " 上一页 ", "sNext" : " 下一页 ", "sLast" : " 最后一页 " }
};
/**
* 将参数对象转换成url查询参数
* @param params 参数对象
* @returns {string} url查询参数
*/
function getUrlParams(params) {
var queryStr = '';
var isFirstParam = true;
for(var key in params){
if(isFirstParam){
queryStr += key + '=' + params[key];
isFirstParam = false;
}else{
queryStr += '&' + key + '=' + params[key];
}
}
return queryStr;
}
2.2 home.ftl
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>cpm system</title>
<!-- Bootstrap -->
<link href="/thirdlib/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- datatables -->
<link href="/thirdlib/datatables/css/jquery.dataTables.min.css" rel="stylesheet"/>
<link href="/css/common.css" rel="stylesheet" />
</head>
<body>
<div id="tableArea" style="padding: 100px;">
<div>
<a href="/home/export">导出</a>
</div>
<table id="rowspanTable" class="table table-bordered">
<thead>
<th>地区</th>
<th>公司</th>
<th>部门</th>
<th>员工姓名</th>
</thead>
</table>
</div>
</body>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/thirdlib/jquery/jquery-2.0.3.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/thirdlib/bootstrap/js/bootstrap.min.js"></script>
<!-- datatables -->
<script src="/thirdlib/datatables/js/jquery.dataTables.min.js"></script>
<script src="/js/common.js"></script>
<script type="text/javascript">
$(function(){
$('#rowspanTable').dataTable( {
"paging": true,
"processing": true,
"serverSide": true,
"searching":false, //搜索栏
"lengthChange" : false, //是否允许改变每页显示的数据条数
"pageLength": 10, //每行显示记录数
"info":true, //开启Datatables信息显示(记录数等)
"ordering":false, //全局定义是否启用排序,优先级比columns.orderable高
"language": language,
"ajax": {
"url": "/home/query",
"type": "POST"
},
"columns": [
{"data":"area", "orderable": false,"searchable": false},
{ "data": "company", "orderable": false ,"searchable": false},
{ "data": "department", "orderable": false,"searchable": false },
{ "data": "userName", "orderable": false ,"searchable": false}
],
"columnDefs": [{
targets: [0,1,2], //第1,2,3列
createdCell: function (td, cellData, rowData, row, col) {
var rowspan = 1;
if(col == 0){
rowspan = rowData.areaRowSpan;
}
if(col ==1){
rowspan = rowData.companyRowSpan;
}
if(col ==2){
rowspan = rowData.departmentRowSpan;
}
if (rowspan > 1) {
$(td).attr('rowspan', rowspan)
}
if (rowspan == 0) {
$(td).remove();
}
}
}]
} );
});
</script>
</html>
3.1数据实体对象
package com.xincheng.cpm.common;
import java.io.Serializable;
/**
* Created by hdwang on 2017/7/14.
*/
public class Member{
private String area;
private String company;
private String department;
private String userName;
private Integer areaRowSpan;
private Integer companyRowSpan;
private Integer departmentRowSpan;
public Member(String area,String company,String department,String userName){
this.area = area;
this.company = company;
this.department = department;
this.userName = userName;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAreaRowSpan() {
return areaRowSpan;
}
public void setAreaRowSpan(Integer areaRowSpan) {
this.areaRowSpan = areaRowSpan;
}
public Integer getCompanyRowSpan() {
return companyRowSpan;
}
public void setCompanyRowSpan(Integer companyRowSpan) {
this.companyRowSpan = companyRowSpan;
}
public Integer getDepartmentRowSpan() {
return departmentRowSpan;
}
public void setDepartmentRowSpan(Integer departmentRowSpan) {
this.departmentRowSpan = departmentRowSpan;
}
}
3.2 controller层(核心代码)
package com.xincheng.cpm.controller;
import com.chenrd.common.excel.ExportExcel;
import com.xincheng.cpm.common.*;
import com.xincheng.cpm.entity.cpm.User;
import com.xincheng.cpm.service.UserService;
import com.xincheng.cpm.vo.IncomeDailyVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.*;
/**
* Created by hdwang on 2017/6/19.
*/
@Controller
@RequestMapping("/home")
public class HomeController {
@Autowired
UserService userService;
@RequestMapping("")
public String index(HttpSession session, ModelMap map, HttpServletRequest request){
User user = (User) session.getAttribute("user");
map.put("user",user);
return "home";
}
private Page<Member> getMembers(PageParam pageParam) {
//1.模拟数据库查询
Pageable pageable = new PageRequest(pageParam.getPage(), pageParam.getLength());
long count = 6;
List<Member> members = getMembersFromDb();
//2.计算rowspan
this.countRowspan(members);
Page<Member> memberPage = new PageImpl<Member>(members,pageable,count);
return memberPage;
}
private void countRowspan(List<Member> members) {
Map<String,Integer> propertyCountMap = this.countPropertyCount(members);
List<String> hadGetKeys = new ArrayList<>(); //曾经取过的key
for(Member member:members){
String areaKey = member.getArea();
String companyKey = areaKey+member.getCompany();
String departmentKey = companyKey+ member.getDepartment();
Integer areaCount = propertyCountMap.get(areaKey);
if(areaCount == null){
member.setAreaRowSpan(1);
}else{
if(hadGetKeys.contains(areaKey)){
member.setAreaRowSpan(0); //曾经取过
}else{
member.setAreaRowSpan(areaCount); //第一次取
hadGetKeys.add(areaKey);
}
}
Integer companyCount = propertyCountMap.get(companyKey);
if(companyCount == null){
member.setCompanyRowSpan(1);
}else {
if(hadGetKeys.contains(companyKey)){
member.setCompanyRowSpan(0);
}else{
member.setCompanyRowSpan(companyCount);
hadGetKeys.add(companyKey);
}
}
Integer departmentCount = propertyCountMap.get(departmentKey);
if(companyCount == null){
member.setDepartmentRowSpan(1);
}else {
if(hadGetKeys.contains(departmentKey)){
member.setDepartmentRowSpan(0);
}else{
member.setDepartmentRowSpan(departmentCount);
hadGetKeys.add(departmentKey);
}
}
}
}
private List<Member> getMembersFromDb() {
Member member1 = new Member("安徽","A","人力资源部"," 小红");
Member member2 = new Member("安徽","B","人力资源部"," 小明");
Member member3 = new Member("浙江","C","人力资源部"," 小君");
Member member4 = new Member("浙江","C","技术部"," 小王");
Member member5 = new Member("浙江","D","技术部"," 小李");
Member member6 = new Member("浙江","D","人力资源部"," 小刚");
List<Member> members = new ArrayList<>();
members.add(member1);
members.add(member2);
members.add(member3);
members.add(member4);
members.add(member5);
members.add(member6);
return members;
}
/**
* 统计每个字段的每组成员个数
* @param rows 记录
* @return 每个字段的每组成员个数
*/
private Map<String,Integer> countPropertyCount(List<Member> rows){
Map<String,Integer> propertyCountMap = new HashMap<>();
for(Member member:rows){
// "area": 无父级分组
String area = member.getArea();
if(propertyCountMap.get(area) == null){
propertyCountMap.put(area,1);
}else{
int count = propertyCountMap.get(area);
propertyCountMap.put(area,count+1);
}
// "company":有area父组
String company = member.getCompany();
String uniqueParent = member.getArea();
String key = uniqueParent + company;
if(propertyCountMap.get(key) == null){
propertyCountMap.put(key,1);
}else{
int count = propertyCountMap.get(key);
propertyCountMap.put(key,count+1);
}
// "department": 有area,company这两个父组
String department = member.getDepartment();
uniqueParent = member.getArea()+member.getCompany();
key = uniqueParent + department;
if(propertyCountMap.get(key) == null){
propertyCountMap.put(key,1);
}else{
int count = propertyCountMap.get(key);
propertyCountMap.put(key,count+1);
}
}
return propertyCountMap;
}
}
原文:http://www.cnblogs.com/hdwang/p/7169255.html?utm_source=itdadao&utm_medium=referral