分页查询
列表查询是最基本的信息管理手段。所以jxTMS提供了一个基本的列表查询、条件搜索的工作框架,以最大限度的简化列表查询的工作量。
这个工作框架包括:
- 数据源,一个在sql文件定义的类sql查询语句
- web界面,一般包括两部分,一个用来设置搜索条件的容器表,一个用来显示数据的分页数据表
- jxTMS已经实现了两个基本的查询函数:search调用该数据源从数据库中查询数据,reSearch用来根据用户输入来添加或设置各种搜索条件
- 查询出来的数据,有时并不能直接发送到前端进行显示,例如,为了减少数据库的存储量,我们用整数来表示状态等信息,这就需要在显示给用户看时,将其转换为用户可识别的文字。这就需要开发者提供一个相应的数据显示函数
- 条件查询时要根据用户的输入来设置相应的查询条件
- 该框架自动支持分页功能,即开发者通过在数据表的定义中指定pagination=true,则自动实现分页
数据源的定义,请参考编程手册中的相应说明。
web界面请参考demo中listSalesOrder的定义,其中数据表一般需有如下的三个参数:
pagination=true,query=search,queryParam={'listTable':'listSalesOrdert2'}
分别指示启用分页、查询命令是search【指定后分页会自动加载数据源进行查询工作】,查询出来的数据显示到哪个数据表中。
然后打开该页面的入口定义中应指定如下参数:
json.disp('listSalesOrder')
#要使用自动工作的分页数据表,必须为其指定dispType=list
json.setParam('dispType','list')
#指定sql文件中定义的数据源
json.setParam('dataSource','sales.listOrder')
#指示查询出来的数据作为extOrder类型的数据对象
json.setParam('objType','extOrder')
一般来说,查询出来的数据多为orm数据对象,其数据属性是主要考虑如何减少存储量、便于数据库高速搜索的,但用户看到的是最好是业务相关的信息描述,这两者很多时候是冲突的,所以就需要查询出数据后将其转换为用户便于理解的业务信息,然后将处理结果生成一个json再发送到前端。如果数据非常简单,不需要做数据转换,那么在sql定义时,直接定义好需要的输出,然后指定resultType=json,就不要再用objType指示系统将其作为一个orm数据对象进行处理了。
如果需要进行数据转换,则开发者重载dispAffairInfo函数即可:
def dispAffairInfo(self,db,ctx,json, jo):
json.set("orderID", jo.ID)
json.set("orderType", jo.Type)
json.set("orderName", jo.Name)
json.set("custom", jo.Custom)
#从数据库中读本订单的销售名
json.set("sales",Relation.getObj(db.getDBConn(),jo.ID,'relSales2Order','people').Name)
#如果前面保存了sales的名字,则就减少了读数据库的操作,由于这个是显示一条就读一次数据库
#而jxTMS默认的分页表每页的行数是15行,这就是说,按上面的方式,列表查询销售订单每页要读16次数据库
#而额外保存的方式则只需要读一次,使用者需自己衡量这两种方式的开销
#json.set("sales",jo.Info.get('sales'))
json.set('orderState',jo.State)
json.set('amount',jo.Amount)
#生成一个动态的a串以供用户点击查看该订单的信息
json.set("op1",self.getViewA(ctx,jo))
由于一般情况下,用户在用列表查询出摘要信息后,可能还会进一步的查看详情或其它操作,所以就需要如最后一行这样动态生成为供用户执行相应操作的a串【可以理解为后台就该行对入口进行了动态的定制】,一般最好还是生成orm数据对象后,用dispAffairInfo进行转换为好,虽然这样的开销有些大。
条件查询包括两种:
1、根据用户输入动态增加查询条件时,使用:
def setSearchCondition(self, db, ctx):
cn = self.getInputString('customName')
if not utils.isNull(cn):
#当用户输入了客户名,设置查询条件,请注意由于用户名支持全文搜索,所以这里用的是match
self.sql.addContion('salesOrder', 'Custom', jxCompare.Match,cn)
2、如果数据源是一个通用查询,在执行时根据上下文的具体情况通过变量来实现针对性的查询时,使用:
def setSearchConditionVarValue(self, db, ctx):
if self.dataSource == 'sales.listMyOrder':
#不同人查我的订单,自然是不同,这就需要用上下文中的执行者ID来为数据源中的变量赋值
self.infoSearch.setVar('salesID',ctx.getCaller().id())
最后,我们总结一下分页查询的工作机制:
- 开发者定义数据源;定义web界面,指定pagination=true等;定义入口
- 用户在点击该入口后,jxTMS发送界面描述到web端,web端显示该界面,并为数据表自动生成一个分页控件
- 后台在该界面的prepareDisp事件中,加载该数据源,并使用该数据源执行一个总数查询,将行数刷新到web端
- web端的分页控件用此总行数进行初始化,包括生成各页面脚标,每页的limit数默认是15,开发者可以知道数据表的该参数来进行调整
- 分页控件以offset=0/limit=15向后台请求search事件,jxTMS即执行相应的查询返回第一页的数据
- 数据表用返回的数据刷新页面,即完成了第一页数据的显示
- 用户点击分页控件的某脚表,如5【即想显示第5页】,则分页控件以offset=60/limit=15向后台请求search事件,jxTMS即执行相应的查询返回第5页的数据,分页控件的页号是从0开始的,所以用户希望显示的页号需要减去1
- 数据表用返回的数据刷新页面,即完成了第5页数据的显示
- 如果用户在搜索条件中进行了各种输入,然后点击了查询按钮,则jxTMS会调用setSearchCondition来根据用户的输入来重置数据源,然后重新执行一个总数查询,刷新到前端后重置分页控件和数据表
- 如果数据源带有特殊参数,如各种我的销售订单、我的报销申请等等,则jxTMS会调用setSearchConditionVarValue来动态的根据上下文设置这些参数以重置数据源,然后重新执行一个总数查询,刷新到前端后重置分页控件和数据表
目前,jxTMS已经打包为云服务器镜像,开发者开箱即用:
jxTMS-腾讯云市场market.cloud.tencent.com