SQL分页模板,解决百万行数据展示卡顿问题

楼主
我是社区第79919位番薯,欢迎点我头像关注我哦~

分页前模板

数据来源于 FRDemo的S人员花名册表,数据量为23199,如果简单显示几个字段的情况,不会触发内存报警,但是全部显示,打开很慢,触发数据报警,关闭内存预警后,页面数据加载数调整到300000条,系统加载该页面在十几秒钟。

主要问题:

1、数据加载触发最大行数报警

2、解除报警后数据加载慢

3、涉及到数据更新后重新加载不能默认为当前页面,除非写js,将页面参数传过去,如果有查询参数,又有页码参数的情况下,js代码复杂度增加很多倍。

为了解决以上问题,对页面进行分页改造。

具体步骤和js代码如下:

1.数据集改造

1.1数据类容集改造

将原来的数据集ds1

SELECT * FROM S人员花名册 WHERE id is not null 
${if(LEN(name)=0,""," AND 人员姓名 LIKE '%"+name+"%'")} 

调整为新的数据集ds1

SELECT * FROM (
----------原SQL开始------
SELECT *, 
ROW_NUMBER() OVER(ORDER BY id DESC)  AS 行号
FROM S人员花名册 WHERE id is not null 
${if(LEN(name)=0,""," AND 人员姓名 LIKE '%"+name+"%'")} 
----------原SQL结束------
)A
WHERE 行号 between ${pageSize}*(${pageIndex}-1)+1 and ${pageSize}*${pageIndex}

1.2新增总行数的数据集count

SELECT count(id) counts FROM (
----------原SQL开始------
SELECT id
FROM S人员花名册 WHERE id is not null 
${if(LEN(name)=0,""," AND 人员姓名 LIKE '%"+name+"%'")} 
----------原SQL结束------
)A

1.3新增每页显示行数数据集page

select 1 xh,10 page union
select 2 xh,20 page union
select 3 xh,50 page union
select 4 xh,100 page
order by xh asc

2.初始化参数控件

pageIndex:为当前页,默认值为1

pageSize:  为每页行数,默认值为10,使用page数据集,可以选择10、20、50、100等选项

由于数据行数比较多,此处需要对页面大小进行设置,建议高度为1000毫米,具体高度可根据最大数据行数进行设置,本人一般给的是1000。

3.修改预览页面 首页、上一页、当前页、下一页、尾页、导出、刷新等按钮

其中:当前页选择邮件,去掉所有✓选内容

3.1页面自动加载总页数 js代码:

var pageSize = FR.remoteEvaluate('=$pagesize');
var pageIndex = FR.remoteEvaluate('=$pageIndex');
var qty = FR.remoteEvaluate('=value("count",1,1)');
var total = Math.ceil(qty / pageSize);
//contentPane.toolbar.options.items[2].setValue("第 " + pageIndex + " / " + total + " 页");

// 当前页
var currentpageStr = "";
// 数据总量
var totalcntStr = " 数据总量:" + qty + "";
// 总页
var pagesizeStr = "每页显示条数:" + pageSize + "";

// 工具栏内容设置
$("#fr-btn-Email").replaceWith(currentpageStr); // 邮件
$("#fr-btn-Word").replaceWith(totalcntStr); // Word格式
$("#fr-btn-PDF").replaceWith(pagesizeStr); // PDF
$("m").replaceWith(currentpageStr); // 邮件

$("#currentpage").val(pageIndex);
$("#currentpage").attr("max", total);
$("#currentpage").attr("val", pageIndex);
$("#totalpage").text(" / " + total);
//$("#pagesize").val(pagesize);

// 切换页码
$("#currentpage").change(function() {
	var val = $(this).val();
	// alert(val);
	if (val < 1 || val > total) {
		$(this).val(pageIndex);
	} else {
		// 查询
		//_g().getParameterContainer().getWidgetByName("pageIndex").setValue(val);
		//_g().parameterCommit();
		contentPane.parameterEl.getWidgetByName("pageIndex").setValue(val);
		_g().parameterCommit();
	}
});

3.2、首页js:

contentPane.parameterEl.getWidgetByName("pageIndex").setValue(1);
_g().parameterCommit();

3.3、上一页js:

var pageSize = FR.remoteEvaluate('=$pagesize');
var pageIndex = FR.remoteEvaluate('=$pageIndex-1');
var qty = FR.remoteEvaluate('=value("count",1,1)');
if(pageIndex==0){
	this.setEnable(false);}
	else{
		contentPane.parameterEl.getWidgetByName("pageIndex").setValue(pageIndex);
		_g().parameterCommit();
}

3.4、下一页js:

var pageSize = FR.remoteEvaluate('=$pagesize');
var pageIndex = FR.remoteEvaluate('=$pageIndex+1');
var qty = FR.remoteEvaluate('=value("count",1,1)');
var total=Math.ceil(qty/pageSize);
 if(parseInt(pageIndex) > parseInt(total)){
 	this.setEnable(false);} 
 	else{ contentPane.parameterEl.getWidgetByName("pageIndex").setValue(pageIndex);
		_g().parameterCommit();
 	}

3.5、尾页js:

var pageSize = FR.remoteEvaluate('=$pagesize');
var pageIndex = FR.remoteEvaluate('=$pageIndex');
var qty = FR.remoteEvaluate('=value("count",1,1)');
var total=Math.ceil(qty/pageSize);
contentPane.parameterEl.getWidgetByName("pageIndex").setValue(total);
_g().parameterCommit();  

3.6、导出按钮js(全参数自动传参):

//获取它的原始值
var bl=_g().parameterEl.getWidgetByName("pageIndex").getValue();

var para = contentPane.parameterEl.getWidgetByName("PARA"); //获取参数面板
var urls = '';
//设置成1开始
contentPane.parameterEl.getWidgetByName("pageIndex").setValue(1);

for (var i = 0; i < para.options.items.length; i++) {
	var widgetName = para.options.items[i].widgetName; //参数面板下控件的widgetName
	var type = para.options.items[i].type; //参数面板下控件的类型
	var value = contentPane.parameterEl.getWidgetByName(widgetName).getValue();
	var pagesize = FR.remoteEvaluate('=value("count",1,1)');
	urls = urls + "&" + widgetName + "=" + value;
}
var reportname = '${=reportname}';
var REPORT_URL = '${servletURL}?viewlet=' + reportname + urls + '&pagesize=' + pagesize + '&format=excel&extype=simple';
setTimeout(function() {
  window.location = (encodeURI(encodeURI(REPORT_URL)));  }, 300);

//再把页码改回去
contentPane.parameterEl.getWidgetByName("pageIndex").setValue(bl);

备注:感谢 CD20160914  对导出存在BUG的修复。

3.7、刷新按钮js:

location.reload();

3.8、查询按钮新增js:

this.options.form.getWidgetByName("pageIndex").setValue(1);
parent.window._g().parameterCommit();

这里需要加入该代码的原因是 当到第N(N大于1)页的时候,再进行其他参数查询时,肯能存在数据比较少的情况,入只有1页数据集,但是当前页还在N页,导致数据显示不出来的问题。

 

备注:如果系统“此调用存在安全风险,如需使用请在安全管理中修改脚本调用公式限制”,由于总页数使用了FR.remoteEvaluate('=value("count",1,1)')

请关闭脚本调用公式限制。

页面运行效果如下,①数据秒出,②对于N页内某一数据修改后,关闭修改子页面,重新刷新父页面,依旧还在第N页,所有的参数也被保留下来了,体验性比较好。③如果要加入其他查询控件,可以在ds1和count数据集中加入
${if(LEN(name)=0,""," AND 人员姓名 LIKE '%"+name+"%'")} 类似的参数即可,页面维护简单。

 

参考模板:分页模板.zip (6.82 K)

最后的建议:

1、隐藏当前页的控件,保留和隐藏每页对应行数。

2、页面可以作为模板使用,只需要修改对应数据集即可。

分享扩散:
参与人数 +2 F豆 +600 理由
CD20160914 + 300 骚年,我看好你哦
很困想睡觉 + 300 太棒了,给你32个赞,么么哒

查看全部评分

沙发
发表于 2025-2-15 09:45:07

这个有一个bug,就是比如我没有录入任何姓名,它显示了所有数据,比如现在我翻页到第3页了,然后点击导出的话,没有数据,只有停在第一页的时候点击导出才会导出所有的数据。因为停留在非第一页的时候,最后的参数传入会导出所有分页的行出错比如停留在第三页,得到的sql语句就是:条数*(3-1)+1 and 条数*3   这样是不对的,可以把里面导出的js语句修改如下,不管用户停留在哪一页,那么肯定都有第一页,那么直接从第一页开始传入即可

//获取它的原始值
var bl=_g().parameterEl.getWidgetByName("pageIndex").getValue();

var para = contentPane.parameterEl.getWidgetByName("PARA"); //获取参数面板
var urls = '';
//设置成1开始
contentPane.parameterEl.getWidgetByName("pageIndex").setValue(1);

for (var i = 0; i < para.options.items.length; i++) {
	var widgetName = para.options.items[i].widgetName; //参数面板下控件的widgetName
	var type = para.options.items[i].type; //参数面板下控件的类型
	var value = contentPane.parameterEl.getWidgetByName(widgetName).getValue();
	var pagesize = FR.remoteEvaluate('=value("count",1,1)');
	urls = urls + "&" + widgetName + "=" + value;
}
var reportname = '${=reportname}';
var REPORT_URL = '${servletURL}?viewlet=' + reportname + urls + '&pagesize=' + pagesize + '&format=excel&extype=simple';
setTimeout(function() {
  window.location = (encodeURI(encodeURI(REPORT_URL)));  }, 300);

//再把页码改回去
contentPane.parameterEl.getWidgetByName("pageIndex").setValue(bl);

 

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

返回顶部 返回列表