EasyUI Datagrid跨行跨列的需求

article/2025/9/13 20:55:03

常规开发后台管理系统中遇到的列表查询,都是用到最基本的数据网格,不包括单元格合并,多列页眉,冻结列和页脚等需求。类似如下这个列表

实现也很简单,引入相关的js、css文件,html标签定义展示的列,通过js脚本初始化渲染。

<table id="datagrid"><thead><tr><th data-options="field:'realName'" width=10% sortable="true">姓名</th><th data-options="field:'userName'" width=10%  sortable="true" >账号</th><th data-options="field:'loginType'" width=15%>登录方式</th><th data-options="field:'loginTime',formatter:formatLoginTime" width=15% sortable="true">登录时间</th><th data-options="field:'logoutTime',formatter:formatLogoutTime" width=15% sortable="true">登出时间</th><th data-options="field:'requestIp'" width=15%>客户端IP</th><th data-options="field:'loginResult'" width=20%>登录结果</th></tr></thead>
</table><script>function formatLoginTime(val,row){return row.loginTimeStr;
}function formatLogoutTime(val,row){return row.logoutTimeStr;
}//表格查询参数
var queryParams = function () {return {searchInput: $("#searchInput").val() || "",loginTimes :$("#loginTimes").val()};
}// 加载表格
var options = {url:'${webContext}/basic/loginLog/getAll.json',queryParams:queryParams,sortName:'loginTime',sortOrder:"DESC"
};
var datagrid = new DataGrid("datagrid",options);
function callback(){datagrid.refresh();
}//常规用法
var laydate = layui.laydate;
laydate.render({elem: '#loginTimes',type: 'datetime',range: true
});
</script>

再复杂一点遇到的需求都是表头的跨行跨列、首列冻结,类似下面这样,大都用于统计报表的需求。

这样的数据网格,我们常用的写法;

<table id="datagrid"><thead></thead>
</table>
<script>var queryParams = function () {return {year:$('#yearselect').val(),halfyear:$('#halfyearselect').val(),jd:$('#jdselect').val(),mon:$('#monthselect').val(),tjsj: $("#ywsj").val()};}function options(){return {url: "${webContext}/mydc/stats/ybfltj.json?",fit: true,striped: true,autoRowHeight: true,nowrap: true,pagination: false, //false取消分页rownumbers: true,pageSize: 20,pageList: [10, 20, 30, 40, 50],loadMsg: "数据加载中....",queryParams:queryParams(),onLoadSuccess:function(data){if(data.total==0){//$.messager.alert('提示','查无数据!');}},frozenColumns:[[{"field":"dwmc","title":"单位",width:'13%'}]],columns:[[//设置一个隐藏列,用于导出Excel{"field":"dwmcyc","title":"单位","rowspan":2,hidden:true},{"field":"xb","title":"性别","colspan":2},{"field":"nljd","title":"年龄阶段","colspan":4},{"field":"hj","title":"户籍","colspan":3},{"field":"jycd","title":"教育程度","colspan":5},{"field":"zy","title":"职业分类","colspan":11}],[{"field":"xb1","title":"男","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'xb1';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"xb2","title":"女","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'xb2';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"nljd1","title":"16-25岁","rowspan":1,width:'5%',formatter: function(value,row,index){row.fieldKey = 'nljd1';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"nljd2","title":"26-40岁","rowspan":1,width:'5%',formatter: function(value,row,index){row.fieldKey = 'nljd2';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"nljd3","title":"41-60岁","rowspan":1,width:'5%',formatter: function(value,row,index){row.fieldKey = 'nljd3';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"nljd4","title":"60岁以上","rowspan":1,width:'5%',formatter: function(value,row,index){row.fieldKey = 'nljd4';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"hj1","title":"本地市","rowspan":1,width:'4%',formatter: function(value,row,index){row.fieldKey = 'hj1';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"hj2","title":"本省其他地市","rowspan":1,width:'5%',formatter: function(value,row,index){row.fieldKey = 'hj2';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"hj3","title":"外省","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'hj3';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"jycd1","title":"不识字","rowspan":1,width:'4%',formatter: function(value,row,index){row.fieldKey = 'jycd1';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"jycd2","title":"小学","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'jycd2';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"jycd3","title":"中学(含中专、职高、技校)","rowspan":1,width:'6%',formatter: function(value,row,index){row.fieldKey = 'jycd3';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"jycd4","title":"大专","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'jycd4';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"jycd5","title":"本科及以上","rowspan":1,width:'5%',formatter: function(value,row,index){row.fieldKey = 'jycd5';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy1","title":"无业","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'zy1';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy2","title":"学生","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'zy2';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy3","title":"务工","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'zy3';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy4","title":"务农","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'zy4';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy5","title":"服务业","rowspan":1,width:'4%',formatter: function(value,row,index){row.fieldKey = 'zy5';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy6","title":"私营业主","rowspan":1,width:'4%',formatter: function(value,row,index){row.fieldKey = 'zy6';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy7","title":"企事业单位","rowspan":1,width:'5%',formatter: function(value,row,index){row.fieldKey = 'zy7';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy8","title":"公务员","rowspan":1,width:'4%',formatter: function(value,row,index){row.fieldKey = 'zy8';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy9","title":"自由职业者","rowspan":1,width:'5%',formatter: function(value,row,index){row.fieldKey = 'zy9';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy10","title":"离退休","rowspan":1,width:'4%',formatter: function(value,row,index){row.fieldKey = 'zy10';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}},{"field":"zy11","title":"其他","rowspan":1,width:'3%',formatter: function(value,row,index){row.fieldKey = 'zy11';return '<span class="num-click-span" Onclick="clickNum('+JSON.stringify(row).replace(/\"/g,"'")+')">'+ value +'</span>'}}]]};}var datagrid = $('#datagrid').datagrid(options());function clickNum(row) {var year = $('#yearselect').val();var halfyear = $('#halfyearselect').val();var jd = $('#jdselect').val();var mon = $('#monthselect').val();var tjsj = $("#ywsj").val();layer.open({type : 2,title : "问卷调查记录列表",shadeClose : false,shade : 0.3,area : ['90%',"90%" ],btn : [ '关闭'],btnAlign : 'c',content : "${webContext}/monitor/mydc/stats/tjwjjl-list.htm?ybfltj=ywfltj&pcscode="+row.pcscode+"&fieldKey="+row.fieldKey+"&yearselect="+year+"&halfyearselect="+halfyear+"&jdselect="+jd+"&monthselect="+mon+"&ywsj="+tjsj,end:function(index, layero){layer.close(index);}});}//导出excelfunction exportExcel() {$('#datagrid').datagrid('toExcel', '样本分类统计.xls');}function refresh() {$('#datagrid').datagrid('reload',queryParams());}
</script>

最近给客户做一个统计,这个报表要求除表头外,数据行如果特征类型一样,就合并行显示。

我百度找到了类似的案例https://www.pianshen.com/article/25421489926/,上面这个表格的代码如下:

<table id="datagrid"><thead></thead>
</table><script>var queryParams = function () {return {year:$('#yearselect').val(),halfyear:$('#halfyearselect').val(),jd:$('#jdselect').val(),mon:$('#monthselect').val(),tjsj: $("#ywsj").val()};}function options(){return {url: "${webContext}/mydc/stats/ybflmydtj.json?",fit: true,striped: true,autoRowHeight: true,nowrap: true,pagination: false, //false取消分页rownumbers: true,pageSize: 20,pageList: [10, 20, 30, 40, 50],loadMsg: "数据加载中....",queryParams:queryParams(),columns:[[{"field":"tz","title":"特征",width:'12%'},{"field":"tzz","title":"特征分类",width:'16%'},{"field":"shzamyd","title":"社会治安满意度",width:'18%'},{"field":"gadwmyd","title":"公安队伍满意度",width:'18%'},{"field":"gackfwmyd","title":"公安窗口服务满意度",width:'18%'},{"field":"sqmjmyd","title":"社区民警熟悉度",width:'18%'}]],  onLoadSuccess: function (data) {if(data.rows.length > 0) {//调用mergeCellsByField()合并单元格mergeCellsByField("datagrid", "tz");}}};}var datagrid = $('#datagrid').datagrid(options());function refresh() {$('#datagrid').datagrid('reload',queryParams());}/*** EasyUI DataGrid根据字段动态合并单元格*   参数 tableID 要合并table的id*   参数 colList 要合并的列,用逗号分隔(例如:"name,department,office");*/function mergeCellsByField(tableID, colList) {var ColArray = colList.split(",");var tTable = $("#" + tableID);var TableRowCnts = tTable.datagrid("getRows").length;var tmpA;var tmpB;var PerTxt = "";var CurTxt = "";var alertStr = "";for (j = ColArray.length - 1; j >= 0; j--) {PerTxt = "";tmpA = 1;tmpB = 0;for (i = 0; i <= TableRowCnts; i++) {if (i == TableRowCnts) {CurTxt = "";}else {CurTxt = tTable.datagrid("getRows")[i][ColArray[j]];}if (PerTxt == CurTxt) {tmpA += 1;}else {tmpB += tmpA;tTable.datagrid("mergeCells", {index: i - tmpA,field: ColArray[j],  //合并字段rowspan: tmpA,colspan: null});tmpA = 1;}PerTxt = CurTxt;}}}//导出excelfunction exportExcel() {//$('#datagrid').datagrid('toExcel', '样本分类满意度统计.xls');var index = layer.confirm('确认导出列表数据吗?', {btn: ['确认','取消'] //按钮}, function(){layer.msg('正在导出,请稍后....', {icon: 1,time:1000});var params = queryParams();postExcelFile(params, "${webContext}/mydc/stats/ybflmydtj/exportExcel.json");layer.close(index);}, function(){layer.close(index);});}function postExcelFile(params, url) {var form = document.createElement("form");form.style.display = 'none';form.action = url;form.method = "post";document.body.appendChild(form);for(var key in params){if(params[key] instanceof Array){var arr = params[key];for(var i=0;i<arr.length;i++){var input = document.createElement("input");input.type = "hidden";input.name = key+"[]";input.value = arr[i];form.appendChild(input);}}else{var input = document.createElement("input");input.type = "hidden";input.name = key;input.value = params[key];form.appendChild(input);}}form.submit();form.remove();}
</script>

数据的跨行合并,是在Datagrid数据加载成功时触发onLoadSuccess函数。

当我尝试将表头第一列和第二列合并时,遇到了样式错误问题。

我也是在onLoadSuccess函数进行操作的代码如下:

onLoadSuccess: function (data) {if(data.rows.length > 0) {//调用mergeCellsByField()合并单元格mergeCellsByField("datagrid", "tz");var celltzwidth = $(".datagrid-cell-c1-tz").width();var celltzzwidth = $(".datagrid-cell-c1-tzz").width();//表头特征跨两列操作$(".datagrid-header-row td").each(function(){var field = $(this).attr("field");if(field == 'tz'){$(this).attr("rowspan",1);$(this).attr("colspan",2);$(this).attr("class","datagrid-td-merged");$(this).find("div").css('width',celltzwidth+celltzzwidth+17+'px');}else if(field == 'tzz'){$(this).css('display','none');//隐藏} });}
}

我这种方法,不管怎么调,就算我当前使用的浏览器显示正常了,不不能保证其他显示器、浏览器不会错误。这个问题暂时没有想到办法,如果你恰好看到我这篇文章,有思路解决这个问题,欢迎给我留言,谢谢。


http://chatgpt.dhexx.cn/article/Syw7vQmL.shtml

相关文章

html布局 跨行,3种方案实现跨行或跨列布局

今天要讲解的这个问题是之前一位小伙伴在群里请教的提问,是关于跨行跨列的布局,如下图是他要实现的具体布局,看似是最简单的二维布局,实际透露出整个CSS的发展方向。向前可以考察对兼容性的处理功底,向后可以考察对CSS新特性的洞察能力。可攻可受,攻守兼备。 如果对此问题…

HTML表格属性跨列,HTML表格的使用 与 跨行跨列

表格的基本语法&#xff1a; 第一个单元格的内容第二个单元格的内容第一个单元格的内容第二个单元格的内容 创建表格一般分为下面四个步骤 1.创建表格标签table 2.在表格标签table创建行标签tr可以有多行 3.在第一行标签tr里创建单元格标签th可以创建表格标题 4.在行标签tr里创…

EXCEL 跨列居中

居中到箭头所指的位置。 先选中三个单元格&#xff0c;打开格式&#xff0c;找到对齐里的跨列居中就行。 结果&#xff1a;

redis数据结构应用

介绍redis数据结构应用场景

redis底层都有哪些数据结构?带你了解redis是如何存储数据的

文章目录 写在前面键值对的存储——哈希哈希冲突redis解决哈希冲突过多的方式——rehash 双向链表数组压缩链表压缩链表的连锁更新压缩列表的缺陷整数数组和压缩列表在查找时间复杂度方面并没有很大的优势&#xff0c;那为什么 Redis 还会把它们作为底层数据结构呢&#xff1f;…

redis底层数据结构(redis底层存储结构、源码分析)

文章目录 前言一、redis为什么快&#xff1f;二、redis的底层数据结构2.1、redis的底层存储的扩容机制2.1.1、扩容时间2.1.2、扩容多大2.1.3、扩容后的rehash2.1.4、何时进行rehash2.1.5、俩hashtable访问那个呢&#xff1f; 2.2、redis的key的底层数据类型(sds)2.2.1、sds(Sim…

redis底层数据结构 -String

redis包含5种常用数据结构 String 、List、Hash、Set 、Zset 基础铺垫 以set为例 redis其实可以理解为 K-V数据库&#xff0c;因此对每个键值对都会有一个 dictEntry&#xff0c;里面存储了指向 Key 和 Value 的指针&#xff1b;next 指向下一个 dictEntry&#xff0c;与本 …

Redis-常用数据结构

Redis常用数据结构 Redis提供了一些数据结构供我们往Redis中存取数据&#xff0c;最常用的的有5种&#xff0c;字符串&#xff08;String&#xff09;、哈希(Hash)、列表&#xff08;list&#xff09;、集合&#xff08;set&#xff09;、有序集合&#xff08;ZSET&#xff09…

「Redis数据结构」集合对象(Set)

「Redis数据结构」集合对象&#xff08;Set&#xff09; 文章目录 「Redis数据结构」集合对象&#xff08;Set&#xff09;一、概述二、结构三、编码转换四、小结 一、概述 Set是Redis中的单列集合&#xff0c;其特点为不保证有序性、保证元素唯一、可以求交集、并集、差集。 …

图解redis五种数据结构底层实现

redis有五种基本数据结构&#xff1a;字符串、hash、set、zset、list。但是你知道构成这五种结构的底层数据结构是怎样的吗&#xff1f;今天我们来花费五分钟的时间了解一下。(目前redis版本为3.0.6) 动态字符串SDS SDS是"simple dynamic string"的缩写。redis中所…

redis底层数据结构-List

举例分析 创建列表对象 numbers 列表对象有两种底层实现结构 1.压缩列表(zipList)实现的列表对象 压缩列表(zipList)是Redis为了节省内存而开发的&#xff0c;是由一系列特殊编码的连续内存块组成的顺序型数据结构&#xff0c;一个压缩列表可以包含任意多个节点&#xff08;e…

redis中hash数据结构

目录 hash的数据结构ziplist底层实现字典底层实现扩容缩容 引用 hash的数据结构 hash底层数据结构的实现包括两种&#xff1a;ziplist和字典当保存的所有键值对字符串长度小于 64 字节并且键值对数量小于 512 时使用ziplist &#xff0c;否则使用字典的方式 ziplist底层实现 …

redis的五种数据结构

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、字符串&#xff08;String&#xff09; 1.SDS的定义 2.SDS与C语言中字符串的区别&#xff08;优点&#xff09; 2.1 获取字符串长度 2.2 防止缓冲区的溢…

「Redis数据结构」哈希对象(Hash)

「Redis数据结构」哈希对象&#xff08;Hash&#xff09; 文章目录 「Redis数据结构」哈希对象&#xff08;Hash&#xff09;一、概述二、编码ZipListHashTable 三、编码转换 一、概述 Redis中hash对象是一个string类型的field和value的映射表&#xff0c;hash特别适合用于存储…

Redis底层数据结构(图文详解)

目录 前言 Redis为什么要使用2个对象&#xff1f;两个对象的好处 redisObject对象解析 String 类型 1、int 整数值实现 2、embstr 3、raw List 类型 1、压缩链表&#xff1a;ziplist 2、双向链表&#xff1a;linkedlist 3、快速列表&#xff1a;quicklist Hash …

Redis数据结构之hash

对象类数据的存储如果具有较频繁的更新需求操作会显得笨重&#xff0c;这里我们可以用redis的hash数据类型解决。 一、hash类型 新的存储需求&#xff1a;对一系列存储的数据进行编组&#xff0c;方便管理&#xff0c;典型应用存储对象信息 需要的存储结构&#xff1a;一个存储…

Redis数据结构之Zset

文章目录 一、zset数据结构二、跳表skipList什么是跳表&#xff1f;1.跳表的查找2.跳表的插入3.跳表的删除4.跳表的更新 一、zset数据结构 相比于set&#xff0c;sorted set 增加了一个权重参数 score&#xff0c;使得集合中的元素能够按 score 进行有序排列&#xff0c;还可以…

Redis数据结构有哪些

Redis数据结构有哪些 一、Redis数据结构 一、Redis数据结构 Redis是一种基于内存的数据库&#xff0c;并且提供一定的持久化功能&#xff0c;它是一种键值&#xff08;key-value&#xff09;数据库&#xff0c;使用 key 作为 索引找到当前缓存的数据&#xff0c;并且返回给程序…

「Redis数据结构」压缩列表(ZipList)

「Redis数据结构」压缩列表&#xff08;ZipList&#xff09; 文章目录 「Redis数据结构」压缩列表&#xff08;ZipList&#xff09;一、概述二、结构三、连锁更新问题四、压缩列表的缺陷五、小结参考 ZipList 是一种特殊的“双端链表” &#xff0c;由一系列特殊编码的连续内存…

redis数据结构hash

Redis数据结构之hash Hash存储结构 Hash是一个string 类型的field和value的映射表。Hash特别适合存储对象&#xff0c;相对于将对象的每个字段存成单个string 类型。一个对象存储在Hash类型中会占用更少的内存&#xff0c;并且可以更方便的存取整个对象。 我们简单举个实例来…