layui表格合并

news2024/11/15 10:40:09

先看一下最终合并之后的效果,能对单选、复选框进行按照某一列的合并

在这里插入图片描述
最开始的解决方案来自于这篇博客介绍的方法:https://blog.csdn.net/guishifoxin/article/details/81480136
但是还是存在没能解决的问题。
在完善之后达到的效果:

一:单选、复选
原来加入开启了单选或者多选之后会将全部的单选按钮都合并了。
在这里插入图片描述
也传入合并列名field,layui默认是0。
在这里插入图片描述
其实这个时候就需要结合业务去控制了,需要知道是根据哪一个字段将整个表格分为几个单选的行,使用之前的代码会将全部的单选按钮合并。
改造之后效果:

1、按照不同的字段进行合并


在这里插入图片描述
在这里插入图片描述

2、checkbox也能合并


在这里插入图片描述
二、多表格混乱或不显示
layui的每一个表格都会有一个index作为标识,并且是01234…这样的顺序。所以在使用的时候指定需要进行行合并的表格序号。
在这里插入图片描述

全部代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>表格合并行工具</title>
<script type="text/javascript" src="你的layui等静态文件地址"></script>
	<script>
	var teatTable1Data = [
		{"location":"西南","cityName":"昆明","province":"云南","area":"100平方千米","prople":"300万"},
        {"location":"西南","cityName":"曲靖","province":"云南","area":"100平方千米","prople":"700万"},
        {"location":"西南","cityName":"玉溪","province":"云南","area":"100平方千米","prople":"600万"},
        {"location":"西南","cityName":"成都","province":"四川","area":"100平方千米","prople":"400万"},
        {"location":"西南","cityName":"宜宾","province":"四川","area":"100平方千米","prople":"400万"},
        {"location":"西北","cityName":"银川","province":"宁夏","area":"100平方千米","prople":"500万"},
        {"location":"西北","cityName":"乌鲁木齐","province":"新疆","area":"100平方千米","prople":"600万"},
        {"location":"西北","cityName":"喀什","province":"新疆","area":"100平方千米","prople":"600万"},
        {"location":"西北","cityName":"西宁","province":"青海","area":"100平方千米","prople":"500万"},
        {"location":"西北","cityName":"兰州","province":"甘肃","area":"100平方千米","prople":"400万"},
        {"location":"西北","cityName":"酒泉","province":"甘肃","area":"100平方千米","prople":"300万"},
	];
    var teatTable2Data = [
        {"location2":"亚洲","cityName22":"北京","province2":"中国","area2":"100平方千米","prople2":"300万"},
        {"location2":"亚洲","cityName2":"孟买","province2":"印度","area2":"100平方千米","prople2":"700万"},
        {"location2":"亚洲","cityName2":"东京","province2":"日本","area2":"100平方千米","prople2":"600万"},
        {"location2":"欧洲","cityName2":"巴黎","province2":"法国","area2":"100平方千米","prople2":"400万"},
        {"location2":"欧洲","cityName2":"伦敦","province2":"英国","area2":"100平方千米","prople2":"400万"},
        {"location2":"欧洲","cityName2":"伦敦2","province2":"英国","area2":"100平方千米","prople2":"500万"},
        {"location2":"欧洲","cityName2":"柏林","province2":"德国","area2":"100平方千米","prople2":"600万"},
        {"location2":"美洲","cityName2":"纽约","province2":"美国","area2":"100平方千米","prople2":"600万"},
        {"location2":"美洲","cityName2":"纽约2","province2":"美国","area2":"100平方千米","prople2":"500万"},
        {"location2":"美洲","cityName2":"华盛顿","province2":"美国","area2":"100平方千米","prople2":"400万"},
        {"location2":"美洲","cityName2":"多伦多","province2":"加拿大","area2":"100平方千米","prople2":"300万"},
    ];
    var teatTable3Data = [
        {"location3":"银河系","cityName3":"地球","province3":"太阳系","area3":"100平方千米","prople3":"300万"},
        {"location3":"银河系","cityName3":"月球","province3":"太阳系","area3":"100平方千米","prople3":"700万"},
        {"location3":"银河系","cityName3":"土星","province3":"太阳系","area3":"100平方千米","prople3":"600万"},
        {"location3":"银河系","cityName3":"水星","province3":"太阳系","area3":"100平方千米","prople3":"400万"},
        {"location3":"银河系","cityName3":"金星","province3":"太阳系","area3":"100平方千米","prople3":"400万"},
        {"location3":"银河系","cityName3":"旅行者1号","province3":"太阳系","area3":"100平方千米","prople3":"500万"},
        {"location3":"银河系","cityName3":"旅行者2号","province3":"太阳系","area3":"100平方千米","prople3":"600万"},
        {"location3":"银河系","cityName3":"天王星","province3":"太阳系","area3":"100平方千米","prople3":"600万"},
        {"location3":"三体星系","cityName3":"三体星1","province3":"半人马座三星","area3":"100平方千米","prople3":"500万"},
        {"location3":"三体星系","cityName3":"三体星2","province3":"半人马座三星","area3":"100平方千米","prople3":"400万"},
        {"location3":"三体星系","cityName3":"三体星2","province3":"半人马座三星","area3":"100平方千米","prople3":"300万"},
    ];

    layui.use('table', function(){
        var table = layui.table;
        table.render({
            data:teatTable1Data,
            title: '测试表格1',
            elem: '#test-table1',
            defaultToolbar: false,
            page: false,
            cols: [[
                {type: 'radio', align: 'center'},
                {field: 'location', title: '位置区域', align: 'center'},
                {field: 'province', title: '省份', align: 'center'},
                {field: 'area', title: '面积', align: 'center'},
                {field: 'cityName', title: '城市', align: 'center'},
                {field: 'prople', title: '人口数量', align: 'center'}
            ]],
            done:function () {
                /**
                 * 参数1  需要合并列的数组,0代表的是合并单选按钮或者是复选框 radio/checkbox 后端需要将这些字段进行排序
                 * 参数2  当前表格的index (用于在一个页面中有使用了多个表格的情况,如果只有一个表格填0就行
                 * 		  index这个值是表格加载的顺序,从0开始,如果页面上表格很多建议debug用 $(".layui-table-body")[index]看一下就拿到了)
                 * 参数3  是按照html元素合并,还是按照标签中的text内容合并,建议填true
                 * 参数4  radio/checkbox根据哪一行去合并
                 */
                layuiRowspan(['0','location', 'province', 'prople'],"0",true,"location");
            }
        });

        table.render({
            data:teatTable2Data,
            title: '测试表格2',
            elem: '#test-table2',
            defaultToolbar: false,
            page: false,
            cols: [[
                {type: 'checkbox', align: 'center'},
                {field: 'location2', title: '位置区域', align: 'center'},
                {field: 'province2', title: '省份', align: 'center'},
                {field: 'area2', title: '面积', align: 'center'},
                {field: 'cityName2', title: '城市', align: 'center'},
                {field: 'prople2', title: '人口数量', align: 'center'}
            ]],
            done:function () {
                /**
                 * 参数1  需要合并列的数组,0代表的是合并单选按钮或者是复选框 radio/checkbox 后端需要将这些字段进行排序
                 * 参数2  当前表格的index (用于在一个页面中有使用了多个表格的情况,如果只有一个表格填0就行
                 * 		  index这个值是表格加载的顺序,从0开始,如果页面上表格很多建议debug用 $(".layui-table-body")[index]看一下就拿到了)
                 * 参数3  是按照html元素合并,还是按照标签中的text内容合并,建议填true
                 * 参数4  radio/checkbox根据哪一行去合并
                 */
                layuiRowspan(['0','location2', 'province2', 'prople2'],"1",true,"location2");
            }
        });

        table.render({
            data:teatTable3Data,
            title: '测试表格3',
            elem: '#test-table3',
            defaultToolbar: false,
            page: false,
            cols: [[
                {type: 'radio', align: 'center'},
                {field: 'location3', title: '位置区域', align: 'center'},
                {field: 'province3', title: '省份', align: 'center'},
                {field: 'area3', title: '面积', align: 'center'},
                {field: 'cityName3', title: '城市', align: 'center'},
                {field: 'prople3', title: '人口数量', align: 'center'}
            ]],
            done:function(){
                /**
                 * 参数1  需要合并列的数组,0代表的是合并单选按钮或者是复选框 radio/checkbox 后端需要将这些字段进行排序
                 * 参数2  当前表格的index (用于在一个页面中有使用了多个表格的情况,如果只有一个表格填0就行
				 * 		  index这个值是表格加载的顺序,从0开始,如果页面上表格很多建议debug用 $(".layui-table-body")[index]看一下就拿到了)
                 * 参数3  是按照html元素合并,还是按照标签中的text内容合并,建议填true
                 * 参数4  radio/checkbox根据哪一行去合并
                 */
                layuiRowspan(['0','location3', 'province3', 'prople3'],"2",true,"location3");
            }
        });
    });


    //行合并 start
    function execRadioRows(childFilterArr,ckChildFilterArr,flag){
        //获取td的个数和种类
        var chChildFilterTextObj = {};
        var chText = [];
        var chIndex = [];

        for(var i = 0; i < ckChildFilterArr.length; i++){
            var chChildText = flag?ckChildFilterArr[i].innerHTML:ckChildFilterArr[i].textContent;
            if(chChildFilterTextObj[chChildText] == undefined){
                chChildFilterTextObj[chChildText] = 1;
                chText.push(chChildText);
            }else{
                var num = chChildFilterTextObj[chChildText];
                chChildFilterTextObj[chChildText] = num*1 + 1;
            }
        }
        for (var i = 0; i < chText.length; i++) {
            var chNum = 0;
            for (var j = 0; j < ckChildFilterArr.length ; j++) {
                var chChildText = flag?ckChildFilterArr[j].innerHTML:ckChildFilterArr[j].textContent;
                if(chText[i] == chChildText){
                    chNum = chNum +1
                }
            }
            chIndex.push(chNum);
        }
        var newIndex = [];
        for (var i = 0; i < chIndex.length; i++) {
            if(i == 0){
                newIndex.push(0);
            }else {
                var newNum = 0;
                for (var j = 0; j < chIndex.length; j++) {
                    if(j<i){
                        newNum = newNum +chIndex[j];
                    }
                }
                newIndex.push(newNum);
            }
        }
        chIndex = newIndex;

        for (var j = 0; j < childFilterArr.length; j++) {
            var findFlag = false;
            for (var k = 0; k < chIndex.length; k++) {
                if(j == chIndex[k]){
                    findFlag = true;
                    if(chIndex[k+1] != null){
                        childFilterArr[j].setAttribute("rowspan",chIndex[k+1] - j);
                        $(childFilterArr[j]).find("div.rowspan").parent("div.layui-table-cell").addClass("rowspanParent");
                        $(childFilterArr[j]).find("div.layui-table-cell")[0].style.height= (chIndex[k+1] - j)*38-10 +"px";

                    }else {
                        childFilterArr[j].setAttribute("rowspan",childFilterArr.length - j);
                        $(childFilterArr[j]).find("div.rowspan").parent("div.layui-table-cell").addClass("rowspanParent");
                        $(childFilterArr[j]).find("div.layui-table-cell")[0].style.height= (childFilterArr.length - j)*38-10 +"px";
                    }
                }
            }
            if(findFlag == false){
                childFilterArr[j].style.display = "none";
            }
        }
    }
    function execRowspan (fieldName,index,flag,ckRows){
        var fixedNode = $(".layui-table-body")[index];
        var child = $(fixedNode).find("td");
        var childFilterArr = [];
        for(var j = 0; j < child.length; j++){
            child[j].getAttribute('data-field')
            if(child[j].getAttribute("data-field") == fieldName){
                childFilterArr.push(child[j]);
            }
        }

        var ckChildFilterArr = [];
        if(fieldName == "0"){
            for(var j = 0; j < child.length; j++){
                child[j].getAttribute('data-field')
                if(child[j].getAttribute("data-field") == ckRows){
                    ckChildFilterArr.push(child[j]);
                }
            }
            execRadioRows(childFilterArr,ckChildFilterArr,flag);
            return;
        }

        //获取td的个数和种类
        var childFilterTextObj = {};
        for(var i = 0; i < childFilterArr.length; i++){
            var childText = flag?childFilterArr[i].innerHTML:childFilterArr[i].textContent;
            if(childFilterTextObj[childText] == undefined){
                childFilterTextObj[childText] = 1;
            }else{
                var num = childFilterTextObj[childText];
                childFilterTextObj[childText] = num*1 + 1;
            }
        }
        var canRowspan = true;
        var maxNum;//以前列单元格为基础获取的最大合并数
        var finalNextIndex;//获取其下第一个不合并单元格的index
        var finalNextKey;//获取其下第一个不合并单元格的值
        for(var i = 0; i < childFilterArr.length; i++){
            (maxNum >9000 || !maxNum)&&(maxNum = $(childFilterArr[i]).prev().attr("rowspan")&&fieldName!="8"?$(childFilterArr[i]).prev().attr("rowspan"):9999);
            var key = flag?childFilterArr[i].innerHTML:childFilterArr[i].textContent;//获取下一个单元格的值
            var nextIndex = i+1;
            var tdNum = childFilterTextObj[key];
            var curNum = maxNum<tdNum?maxNum:tdNum;
            if(canRowspan){
                for(var j =1;j<=curNum&&(i+j<childFilterArr.length);){//循环获取最终合并数及finalNext的index和key
                    finalNextKey = flag?childFilterArr[i+j].innerHTML:childFilterArr[i+j].textContent;
                    finalNextIndex = i+j;
                    if((key!=finalNextKey&&curNum>1)||maxNum == j){
                        canRowspan = true;
                        curNum = j;
                        break;
                    }
                    j++;
                    if((i+j)==childFilterArr.length){
                        finalNextKey=undefined;
                        finalNextIndex=i+j;
                        break;
                    }
                }
                childFilterArr[i].setAttribute("rowspan",curNum);
                if($(childFilterArr[i]).find("div.rowspan").length>0){//设置td内的div.rowspan高度适应合并后的高度
                    $(childFilterArr[i]).find("div.rowspan").parent("div.layui-table-cell").addClass("rowspanParent");
                    $(childFilterArr[i]).find("div.layui-table-cell")[0].style.height= curNum*38-10 +"px";
                }
                canRowspan = false;
            }else{
                childFilterArr[i].style.display = "none";
            }
            if( --childFilterTextObj[key] == 0 | --maxNum==0 | --curNum==0 | (finalNextKey!=undefined && nextIndex==finalNextIndex)){
                canRowspan = true;
            }
        }
    }
    function layuiRowspan(fieldNameTmp,index,flag,ckRows){
        var fieldName = [];
        if(typeof fieldNameTmp == "string"){
            fieldName.push(fieldNameTmp);
        }else{
            fieldName = fieldName.concat(fieldNameTmp);
        }
        for(var i = 0;i<fieldName.length;i++){
            execRowspan(fieldName[i],index,flag,ckRows);
        }
    }
    //行合并 end
</script>
</head>
<body>
<div class="layui-fluid">
	<div class="layui-row layui-col-space10">
		<div class="layui-col-sm4">
			<div class="grid-demo grid-demo-bg1">
				<table class="layui-table" id="test-table1" lay-filter="test-table1"></table>
			</div>
		</div>
		<div class="layui-col-sm4">
			<div class="grid-demo">
				<table class="layui-table" id="test-table2" lay-filter="test-table2"></table>
			</div>
		</div>
		<div class="layui-col-sm4">
			<div class="grid-demo">
				<table class="layui-table" id="test-table3" lay-filter="test-table3"></table>
			</div>
		</div>

	</div>
</div>
</body>
</html>

依然存在的问题(但不影响使用):

1、radio或者是checkbox按钮没有垂直居中。
2、选中样式或者是鼠标移动样式没有调整(还是会蛇皮拐弯)。
在这里插入图片描述





本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/400945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

移动硬盘格式化?想要恢复硬盘那就看这里!

案例&#xff1a;移动硬盘无法打开&#xff0c;提示格式化&#xff1f; “怎么办啊&#xff01;&#xff01;&#xff01;今天下午给同学重装系统&#xff0c;插上自己的移动硬盘&#xff0c;却发现读不出来&#xff0c;提示需要格式化&#xff01;里面有很多东西&#xff0c;…

第十四章 opengl之高级OpenGL(深度测试)

OpenGL深度测试深度测试函数深度值精度深度缓冲的可视化深度冲突防止深度冲突深度测试 前面我们渲染一个3D图片中运用了深度缓冲&#xff1a;防止被阻挡的面渲染到其他面的前面。 深度缓冲就像颜色缓冲(Color Buffer)&#xff08;储存所有的片段颜色&#xff1a;视觉输出&…

JAVA开发(JAVA中的异常)

在java开发与代码运行过程中&#xff0c;我们经常会遇到需要处理异常的时候。有时候是在用编辑器写代码&#xff0c;点击保存的时候&#xff0c;编辑器就提示我们某块代码有异常&#xff0c;强制需要处理。有时候是我们启动&#xff0c;运行JAVA代码的时候的&#xff0c;日志里…

案例06-没有复用思想的接口和sql--mybatis,spring

目录一、背景二、思路&方案问题1优化问题2优化三、总结四、升华一、背景 写这篇文章的目的是通过对没有复用思想接口的代码例子优化告诉大家&#xff0c;没有复用思想的代码不要写&#xff0c;用这种思维方式和习惯来指导我们写代码。 项目中有两处没有复用思想代码&#…

R语言基础(三):运算

接前文 R语言基础(一)&#xff1a;注释、变量 R语言基础(二)&#xff1a;常用函数 4.运算 4.1 数学运算 R语言中支持加减乘除四则运算、乘方运算、求余数(取模)运算&#xff1a; 符号含义示例加法11 结果是2-减法2-1 结果是1*乘法4*5 结果是20/除法4/5 结果是0.8%/%整除(只要…

MySQL 事务隔离

MySQL 事务隔离事务隔离实现事务的启动ACID : 原子(Atomicity)、一致(Consistency)、隔离(Isolation)、永久(Durability) 多个事务可能出现问题 : 脏读 (dirty read) , 不可重复读 (non-repeatable read) , 幻读 (phantom read) 事务隔离级别 : 读未提交 (read uncommitted)…

一篇学习ES

文章目录ES简介1.什么是ElasticSearch2.ElasticSearch的使用案例3.ElasticSearch对比SolrElasticSearch环境搭建1. 下载ES压缩包2. 安装ES服务3. 启动ES服务3. 安装ES的图形化界面插件ES术语1.概述2.索引 index3.类型 type4.字段Field5.映射 mapping6.文档 document7. 接近实时…

制造业数字化转型要注重哪些方面?

近年来&#xff0c;制造业企业数字化转型的话题一直处于行业高热位置。中央经济工作会议作出“大力发展数字经济”的部署&#xff0c;工信部提出要深化产业数字化转型&#xff0c;建设一批全球领先的智能工厂、智慧供应链&#xff0c;并向中小企业场景化、标准化复制推广。 随…

监控体系划分

按采集类型划分 1.基于 Metrics 的监控 基于 Metrics 的监控&#xff0c;背后对应的是度量&#xff08;指标监控&#xff09;系统&#xff0c;监控机器在某段时间内的 CPU 使用率、系统负载&#xff1b; HTTP 请求访问量等。 1.Skywalking 开源地址 &#xff08;既能做调用链监…

Spring-AOP简介案例

Spring-AOP简介&案例 1&#xff0c;AOP简介 Spring有两个核心的概念&#xff0c;一个是IOC/DI&#xff0c;一个是AOP。 对于AOP,我们前面提过一句话是:AOP是在不改原有代码的前提下对其进行增强。 1.1 什么是AOP? AOP(Aspect Oriented Programming)面向切面编程&…

java Spring5 xml配置文件方式实现声明式事务

在java Spring5通过声明式事务(注解方式)完成一个简单的事务操作中 我们通过注解方式完成了一个事务操作 那么 下面 我还是讲一下 基于xml实现声明式事务的操作 其实在开发过程中 大家肯定都喜欢用注解 因为他方便 这篇文章中的xml方式 大家做个了解就好 还是 我们的这张表 记…

ECharts数据可视化--常用图表类型

目录 一.柱状图 1.基本柱状图 1.1最简单的柱状图 ​编辑 1.2多系列柱状图 1.3柱状图的样式 &#xff08;1&#xff09;柱条样式 &#xff08;2&#xff09;柱条的宽度和高度 &#xff08;3&#xff09;柱条间距 &#xff08;4&#xff09;为柱条添加背景颜色 ​编辑 2.堆…

SpringBoot创建和使用

目录 什么是SpringBoot SpringBoot的优点 SpringBoot项目的创建 1、使用idea创建 2、项目目录介绍和运行 Spring Boot配置文件 1、配置文件 2、配置文件的格式 3、properties 3.1、properties基本语法 3.2、读取配置文件 3.3、缺点 4、yml 4.1、优点 4.2、yml基本…

虚拟机下Linux系统磁盘扩容

在VM虚拟机中&#xff0c;我们经常会选择默认磁盘大小20G&#xff0c;用着用着才发现20G不够用&#xff0c;服务启动不了&#xff0c;就很尴尬&#xff0c;让我们今天一起来学习下&#xff0c;如何在虚拟机给磁盘扩容。一&#xff1a;关闭虚拟机&#xff0c;添加硬盘背景&#…

mysql Docker容器的安装(centos版)以及修改docker默认端口、解决1251问题

文章目录一、Docker的安装以及在Docker下进行mysql的安装1、安装Docker2、上传安装包并进行安装并启动docker3、 配置Docker的镜像加速器&#xff0c;这里使用阿里云的镜像4、刷新守护进程&#xff0c;并重启docker&#xff0c;检验镜像是否配置成功5、搜索并下载mysql镜像6、导…

超分扩散模型 SR3 可以做图像去雨、去雾等恢复任务吗?

文章目录前言代码及原文链接主要的点如何进行图像恢复前言 关于扩散模型以及条件扩散模型的介绍&#xff0c;大家可以前往我的上一篇博客&#xff1a;扩散模型diffusion model用于图像恢复任务详细原理 (去雨&#xff0c;去雾等皆可)&#xff0c;附实现代码。 SR3是利用扩散模…

优化Facebook广告ROI的数据驱动方法:从投放到运营

“投放广告并不是最终的目的&#xff0c;关键在于如何最大程度地利用数据驱动的方法来提高广告投放的回报率&#xff08;ROI&#xff09;”Facebook广告是现代数字营销中最为常见和重要的广告形式之一。但是&#xff0c;要让Facebook广告真正发挥作用&#xff0c;需要通过数据驱…

Allegro如何自动添加测试点操作指导

Allegro如何自动添加测试点操作指导 在做PCB设计的时候,在一些应用场合下需要给PCB上的网络添加测试点,如下图 测试点除了可以手动逐个添加之外,Allegro还支持自动添加测试点,具体操作如下 点击Manufacture点击Testprep

PlantUML画出如女神漂亮的流程图

一&#xff1a;环境准备 1&#xff0c;本地安装好vscode 2&#xff0c;vscode安装PlantUML插件 3&#xff0c;本地安装java环境&#xff0c;我本地用的是jdk-11.0.178&#xff0c;配置好环境变量 4&#xff0c;在vscode上新建一个文件以wsd结尾&#xff0c;输入以下两行&#x…

Go语言容器之数组和切片

Go语言的容器分为值类型和引用数据类型 一、数组 1.数组的声明和初始化 (1) 数组声明的语法 var 数组变量名 [数组大小]数组类型 举例&#xff1a; package main import "fmt"func main(){//数组的声明var arr[10]int//打印数组长度fmt.Println("arr的长度为…