下拉表关联异步加载不是事儿 - 参数动态过滤

对于报表,简单来说就是用表格、图表等格式来动态显示数据以及数据之间的关系,同时,经常伴随的,也是很重要的一个功能就是给报表增加各种条件,对数据进行筛选,以便找出用户最关心的数据。

筛选条件常常不止一项,也就是我们常说的多条件查询,同时这些条件之间可能还有关联关系,比如最常见的“省份”和“城市”之间,在选择了“省份”后,“城市”选项应该只显示当前省下的列表。这种情况,我们一般会用关联过滤来进行处理。

对于省份和城市,这个例子本身数据量就不大(一个省份下城市多的也就 4、50,全国也不过千把个城市),采用报表工具编辑风格内的关联过滤(数据全内存,页面操作时再去过滤)解决也就是分分钟的事儿。

但是问题来了,如果数据大到一定程度呢?

比如,同样很常见的“产品类别”与“产品名称”之间的关联过滤,想象一个全国性的海鲜交易集散地,单拿出一个类别“水产品”来说,仅仅叫 xx 鱼的就会有 2 万余种,要是再加贝类、甲壳类等呢?! 如果再算上农副产品,更不要说还有酒类、饮料类、调味品类……

于是,结果就是:

1gif

您没看错,就只能等待、等待……再等待!因为下拉框要加载半天,只能等页面加载完再操作。对于报表用户来说,看得到的是报表系统效率极低,而看不到的则是内存占用极大,导致整个系统受到影响。这样,仅仅因为想看一眼可能会用到的某个产品,就需要把所有的拿出来等待“出台”……所以,经常是还没看到报表呢,页面卡死了,然后就没有然后了,只能开始骂人了。

所幸,对于程序猿来说,知道有个好玩意叫异步加载,也就是可以根据选的值动态去数据库里或其他数据源查后再页面加载(也就是不用全查出来放在内存“备用”了)。

还是拿产品类别和名称的联动举例,用上异步加载,初始加载参数表单时只需加载产品类别就可以了,选定哪个类别后再去库里查对应的产品名称列表,这样就做到了用谁查谁、页面加载谁,从此内存用起来也不那么心疼了、页面加载也不再力不从心了。

好了,啰嗦这么些,在润乾报表中到底是怎么实现异步加载的呢?

官方功能说明:

1、设计器设计参数表单,假如有两个下拉数据表 A、B,分别对应参数 arg1、arg2,选择 A 以后过滤 B。设计时 A 设计完整,B 可以设计时加一个过滤条件让它取不到数或数据特少。

2、在显示参数表单的 jsp 里,用户写一个下面这样的 js 函数,这是下拉表选择后会调用的 js 函数,cellId 是下拉控件所在单元格 id,newValue 是新的下拉值, argName 是参数名

   function _selectValueChanged( cellId,newValue, argName ) {
       if(argName == "productTypes" ) {
             varparams = { "arg1": newValue };
             $.post(url, params, function( data ) {
                   data= eval( "(" + data.trim() + ")" );
                   $("#arg2").combobox("loadData", data ); //将新的节点数据设置到arg2
             },"text");
       }}

示例中的 url 是服务器上的一个 servlet 或 jsp 等服务程序, 根据 ajax 传上去的参数 params,为 arg2 取回新的数据,数据的格式如下:

[{v:“v1”,d:“选项 1”},{v:“v2”,d:“选项 2”},……,{v:“vn”,d:“选项 n”}]

v 表示真实值,d 表示显示值

接下来结合实例来看下具体的做法:

1、准备一个参数表单和结果报表

(1)参数表单:产品类别(web 名:productTypes)、产品名称(productName)

1png

选择产品类别 (如 1- 饮料;2- 调味品;3- 其他) 后, 后台计算对应的可选产品名称列表并返回给下拉列表

(2)结果报表仅演示接收两个条件值

2png

2、Jsp 内定义上面 2(功能说明)中的方法

function_selectValueChanged( cellId, newValue, argName ) {

//如果是productTypes下拉,则触发
if( argName == "productTypes" ) {
     varurl = "rv.jsp";//异步请求的服务器文件,此处为jsp
        var params = { "productTypes":newValue };
        $.post( url, params, function( data ) {
               alert(data);
               data = eval( "(" +data.trim() + ")" );
               $("#productName").combobox("loadData", data ); //将新的节点数据设置到productName下拉项

        }, "text");
}
}

3、定义异步处理数据的服务地址(jsp 或 servlet 等)

看上一步 url 为 rv.jsp(与展现报表的 jsp 同目录),核心代码:

<%@ page contentType="text/html;charset=UTF-8" %>
<%
        String proType = request.getParameter("productTypes");
        String strv = "";
 if("1".equals(proType)){
                strv = "\[{v:'1',d:'纯净水'},{v:'1',d:'矿泉水'},{v:'1',d:'橙汁'},{v:'1',d:'桃汁'}\]";

        }else if("2".equals(proType)){
                strv = "\[{v:'2',d:'米醋'},{v:'2',d:'精盐'},{v:'2',d:'味精'},{v:'2',d:'花椒粉'}\]";
        }else if("3".equals(proType)){
                strv = "\[{v:'3',d:'3333'}\]";
        }else{
                strv = "\[{v:'10010',d:'other ans'}\]";
        }     
        out.print(strv);
%>

<!—代码可以看出,根据接收类别的不同,返回不同数据列表。同理,如果是要经过数据库查询,按条件执行不同sql即可-->

4、看效果

通过上面的替换,从而实现当“产品类别”选择为“1”(饮料)时,则“产品名称”仅可选择 “纯净水”、“矿泉水”等饮料类产品。

3png

产品类别为“2”(调味品)时,则只能选择“精盐”、“醋”等。

4png

通过这个例子可以看到,在润乾报表中实现异步加载数据并不是很复杂的事情,而通过这种方式可以有效地提高关联过滤的输入效率,为用户提供更好的体验,延长了鼠标、键盘的使用寿命,减少了开发者被问候而打喷嚏的机会……

当然,除了这种“高大上”的关联过滤方式,润乾报表本身也提供了相对简单、不用考虑太多因素(比如数据量过大,造成内存过多占用等)的关联过滤功能,以及基于 sql 就可以处理的异步加载功能。

至于怎么选么??答案是:看实际情况(这个回答不会挨揍吧),或者咨询支持人员(企业 QQ:800025723)。

更多参数及编辑风格相关问题请查看:参数相关问题分类导航
* 轻松 get 报表模糊查询技能
* 多值模糊查询报表的制作
* 报表查询条件的 N 种使用方式
* 参数使用小技巧
* 利用动态参数默认不查询任何数据
* 润乾报表 V2018 手机端展现参数模板下拉数据集样式问题
* 如何实现参数级联查询
* 润乾报表下拉日历关联过滤下拉数据集实例