テーブルの要件が奇妙な場合があります。私が最近作業していたテーブルでは、同じ内容を持つ特定の列の隣接するレコードの行要素をマージする必要がありました。それらが同じでない場合、それらはマージされません。テーブルデータの順序を変更する必要がない場合、これは非常に簡単に行うことができます (同じ要素がすべて出現する回数を数えるだけで、それらが互いに隣り合っているかどうかを考慮する必要はありません)。変更できますが、現時点では少し問題があります。表現が少しわかりにくいかもしれませんが、下の図を見て問題を説明しましょう。
推奨チュートリアル: Bootstrap 入門チュートリアル
# 具体的な要件。現在 3 つのレコードがあると仮定し、背景は次の順序に従います。 x 配置後、トップページに渡されて表示されます。
ページがデータを取得して同じ行を結合すると、右側の図のような効果が得られます。ただし、ページ上の並べ替えボタンを選択すると、 、現在の仕分けはできなくなりますが、混乱が生じた場合、どのようにして合併を達成できるのでしょうか?
ここで考慮する価値があるのは、後続の各列のマージの最大数は前の列のマージの数に基づいているため、ここが出発点であるということです。最初の列のすべての隣接する同一行の出現数を記録し、次に 2 列目のすべての隣接する同一行の出現をカウントし、次に 3 列目のすべての隣接する同一行の出現をトラバースしてカウントします。コンテンツが表示される回数は降順です。 。 。 。 。各列で同じ要素が隣り合っている回数を記録し、その回数を取得して、最後に bootstrapTable に付属する mergeCells メソッドを使用してマージします。データ構造とアルゴリズムの重要性をますます感じています。最近、私が書くプログラムには論理的なアルゴリズムが含まれることが多すぎます。この 2 つは学校でしっかりと学んだ方が良いです~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~コードを見てください:
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2018/6/20 Time: 14:21 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% String scheme = request.getScheme(); String serverName = request.getServerName(); String contextPath = request.getContextPath(); int port = request.getServerPort(); //网站的访问跟路径 String baseURL = scheme + "://" + serverName + ":" + port + contextPath; request.setAttribute("baseURL", baseURL); %> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <%--设置IE渲染方式(文档)默认为最高(这部分可以选择添加也可以不添加)--%> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> <title>实现表格同名合并</title> <!--图标样式--> <link rel="stylesheet" type="text/css" href="${baseURL}/Bootstrap/bootstrap/css/bootstrap.min.css" /> <link href="${baseURL}/Bootstrap/bootstrap-table/bootstrap-table.css" rel="stylesheet" /> <script src="${baseURL}/Bootstrap/bootstrap/assets/js/jquery-1.10.2.min.js"></script> <script src="${baseURL}/Bootstrap/bootstrap/assets/js/bootstrap.min.js"></script> <script src="${baseURL}/Bootstrap/bootstrap-table/bootstrap-table.js"></script> <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="${baseURL}/Bootstrap/bootstrap/assets/js/html5shiv.js"></script> <script src="${baseURL}/Bootstrap/bootstrap/assets/js/respond.min.js"></script> <![endif]--> <style type="text/css"> </style> </head> <body> <div> <table id="table"></table> </div> </body> <script type="text/javascript"> $(function () { //初始化Table $('#table').bootstrapTable({ url: '${baseURL}/Views/cc.json',//请求后台的URL(*) 这里我用的是一个json文件 method: 'get',//请求方式(*) toolbar: '#toolbar',//工具按钮用哪个容器 striped: true,//是否显示行间隔色 cache: false,//是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*) pagination: true,//是否显示分页(*) sortable: false,//是否启用排序 sortOrder: "asc",//排序方式 //queryParams: queryParams,//传递参数(*) sidePagination: "server",//分页方式:client客户端分页,server服务端分页(*) pageNumber: 1,//初始化加载第一页,默认第一页 pageSize: 10,//每页的记录行数(*) pageList: [10, 25, 50, 100],//可供选择的每页的行数(*) // search: true,//是否显示表格搜索,此搜索是客户端搜索,不会进服务端 contentType: "application/x-www-form-urlencoded", strictSearch: true, showColumns: true,//是否显示内容列下拉框 showRefresh: true,//是否显示刷新按钮 minimumCountColumns: 2,//最少允许的列数 clickToSelect: true,//是否启用点击选中行 //这里如果要固定表头的话 就把height开启 //height: 700,//行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度 width:'50%', uniqueId: "id",//每一行的唯一标识,一般为主键列 showToggle: true,//是否显示详细视图和列表视图的切换按钮 cardView: false,//是否显示详细视图 detailView: false,//是否显示父子表 onLoadSuccess: function (data) { //数据加载成功后 进行合并 这里我只是同名合并projName subProj phase 如果需要合并更多的字段 仿照添加对应的代码就可以了 mergeTable(data,"table"); }, columns: [ { field: 'projName', title: 'projName', }, { field: 'subProj', title: 'subProj' }, { field: 'phase', title: 'phase' }, { field: 'workItem', title: 'workItem', }, { field: 'completion', title: 'completion', }, ], }); }); //全局变量 ***如果每次只是发送ajax请求对table进行局部更新,则每次要合并前前都应该清空这三个变量 不然全局变量会一值追加结果 var projNameCount=""; var subProjNameCount=""; var phaseCount=""; //合并表格 function mergeTable(data,tableId){ //每次合并表格前 都要将全局变量清空 projNameCount=""; subProjNameCount=""; phaseCount=""; mergeCells(data.rows,0,data.rows.length,"projName",$('#'+tableId)); //对projName,subProjName,phase的次数进行分割 //去掉末尾的逗号 有时候也可以不用去掉 还是去掉了我这里 projNameCount = projNameCount.substring(0,projNameCount.length-1); subProjNameCount = subProjNameCount.substring(0,subProjNameCount.length-1); phaseCount = phaseCount.substring(0,phaseCount.length-1); //console.log(projNameCount+"+"+subProjNameCount+"+"+phaseCount); var strArr1 = projNameCount.split(","); var strArr2 = subProjNameCount.split(","); var strArr3 = phaseCount.split(","); //根据次数进行表格合并 //合并projName var index = 0; for(var i=0;i<strArr1.length;i++){ var count = strArr1[i] * 1; $('#'+tableId).bootstrapTable('mergeCells',{index:index, field:"projName", colspan: 1, rowspan: count}); index += count; } //合并subProjName var index = 0; for(var i=0;i<strArr2.length;i++){ var count = strArr2[i] * 1; $('#'+tableId).bootstrapTable('mergeCells',{index:index, field:"subProjName", colspan: 1, rowspan: count}); index += count; } //合并phaseName var index = 0; for(var i=0;i<strArr3.length;i++){ var count = strArr3[i] * 1; $('#'+tableId).bootstrapTable('mergeCells',{index:index, field:"phaseName", colspan: 1, rowspan: count}); index += count; } } //排序后紧挨在一起 进行同名合并 /** * 对于表格合并,首先要进行排序,即将同名的属性的记录排序紧挨在一起,这样才能最好的显示出合并想要的效果。 * 因为此方法是拿第一个数据与后面的数据依次比较, * 例如,第一条记录的projName与第二条记录的projName来进行比较,两者相同,则继续第一条记录的projName与第三条记录的projName来进行比较, * 当不相同时,记录下此projName对应的值出现的次数,然后再开始从第三条记录的projName与第四条记录的projName来进行比较,依次循环下去,记 * 录下相同内容的值出现的次数,到时候,再根据这些次数来进行合并 * * 此方法主要是先拿到每个同名属性的值的相等次数,把次数利用全局变量存下来 * * @param datas --表格数据,一般为表格的rows数据 * @param startIndex --开始下标 * @param size --从开始下标起,到size结束,遍历合并多少个 * @param fieldName --计算算哪个列 * @param target --table表格对象 */ function mergeCells(datas,startIndex,size,fieldName,target) { //console.log("startIndex:"+startIndex+"size:"+size+"---合并列:"+fieldName) //声明一个数组计算相同属性值在data对象出现的次数和 //这里不能使用map,因为如果涉及到排序后,相同的属性并不是紧挨在一起,那么后面的次数会覆盖前面的次数,故这里用数组 var sortArr = new Array(); for (var i = startIndex; i < size ; i++) { for (var j = i + 1; j < size; j++) { if (datas[i][fieldName] != datas[j][fieldName]){ //相同属性值不同 if (j - i > 1) { sortArr.push(j - i); i = j - 1; //如果是最后一个元素 把最后一个元素的次数也装进去 if(i == size-1-1){ sortArr.push(1); } }else{ sortArr.push(j - i); //如果j是最后一个元素 把最后一个元素的次数装进去 if(j == size - 1){ sortArr.push(1); } } break; }else { //相同属性值相同 直到最后一次的时候才会装 否则在他们的值不同时再装进去 if (j == size - 1) { sortArr.push(j - i+1); //这里的赋值感觉有点多余 算了现就这个样子吧 不影响功能 i = j; } } } } //遍历数组,将值装追加到对应的字符串后面 for(var prop in sortArr){ /*这里在ie8上运行的时候 出现坑 最好遍历数组不要用for in 这里我用了就懒得换了 下面加上如果prop是indexOf就停止 就解决了ie8出现的问题*/ if(prop == "indexOf"){ continue; } if(fieldName == "projName"){ var count = sortArr[prop] * 1; projNameCount += count +","; } if(fieldName == "subProjName"){ var count = sortArr[prop] * 1; subProjNameCount += count +","; } if(fieldName == "phaseName"){ var count = sortArr[prop] * 1; phaseCount += count +","; } } for(var prop in sortArr){ if(prop == "indexOf"){ continue; } if(fieldName == "projName"){ //console.log("进入projName--此时开始index-"+startIndex+"--结束index--"+(startIndex+sortArr[prop])*1); startIndex = 0; //subProjName每次进去的startIndex为前面次数的和 if(subProjNameCount.length>0){ //console.log("subProjNameCount-"+subProjNameCount); var temp = subProjNameCount.substring(0,subProjNameCount.length-1); var strArr1 = temp.split(","); for(var i=0;i<strArr1.length;i++){ var count = strArr1[i] * 1; startIndex += count; } } if(sortArr[prop] >1){ mergeCells(datas,startIndex,startIndex+sortArr[prop],"subProjName",target); }else{ //当projName的次数为1就不进入循环 subProjNameCount +=1+","; phaseCount +=1+","; } } if(fieldName == "subProjName"){ startIndex = 0; if(phaseCount.length>0){ //console.log("phaseCount-"+phaseCount); var temp = phaseCount.substring(0,phaseCount.length-1); //phaseCount = phaseCount + ","; var strArr1 = temp.split(","); for(var i=0;i<strArr1.length;i++){ var count = strArr1[i] * 1; startIndex += count; } } if(sortArr[prop] >1){ //console.log("进入subProj--此时开始index-"+startIndex+"--结束index--"+(startIndex+sortArr[prop])*1); mergeCells(datas,startIndex,startIndex+sortArr[prop],"phaseName",target) }else{ phaseCount +=1+","; } } } } </script> </html>
上記は完全なコードであり、レンダリングは次のようになります: (このコードは、projName、subProj、およびフェーズのマージを計算する必要があるだけです。作業項目を計算する必要はありません。バックグラウンド クエリ (つまり各作業項目レコード) のため、後でマージされます)
#ブートストラップ テーブルに付属のセルをマージするメソッドも非常に便利で、以下に基づいてのみ完了できます。この基礎。 rree
以上がBootstrap-table は、同じ行の動的マージを実装します (同じ名前のテーブルをマージします)。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。