【5.0苍穹源码浅析】三、接口详解之加载单据列表原创
金蝶云社区-丁梦洋
丁梦洋
0人赞赏了该文章 264次浏览 未经作者许可,禁止转载编辑于2024年07月07日 13:02:05

本文紧接【5.0苍穹源码浅析】二、接口详解(上篇) (kingdee.com),点击菜单后,会接着发起如下请求:

image.png

showForm打开表单,当然得去加载这个表单,其逻辑就在loadData接口,本篇重点解析

urlhttp://127.0.0.1:8881/ierp/form/batchInvokeAction.do?appId=a2h6_testapp&f=a2h6_test_basedata&ac=loadData
请求体pageId: 1844121403830305792root07d825e480e44b9bbd7345f67f8ebc5c

appId: a2h6_testapp

params: [{"key":"","methodName":"loadData","args":[],"postData":[]}]

响应体image.png

咱们来瞅瞅这个响应:

1、setVisible

之前举例过了,又是哪个插件里用了this.getView().setVisible()方法,没啥好说的

2、updateControlMetadata

字面意思像是更新控件元数据,其实也就是更新前端控件样式,如是否折叠、列表是否滚动加载、最大页数等

image.png

这些标识还挺熟悉的,filtercontainerap是列表过滤控件的标识,gridview是单据列表的表格视图标识,其实都是列表模板bos_list里的控件名

image.png

3、InvokeControlMethod

上篇中也出现过,即触发前端控件的相应方法,第一个InvokeControlMethod根据key和方法名大概推断是给表格视图、轻分析视图添加列,给卡片视图创建视图,点开args里的columns,能看到列名,是否支持过滤、排序等配置信息

image.png

第二个InvokeControlMethod能推断是给过滤控件添加过滤字段、设置折叠等,给单据列表设置选中行,焦点等

image.png

4、u

这个u得点开来看,会发现里面有真正的业务数据data通过前面几个接口,前端已经拿到如过滤组件和列表表头等页面信息,能展示这个列表了,就差填充数据了,原来是在这个返回里,这就完整了!

格式有点像我们以前开发的分页接口,如总数datacount,总页数pagecount,页码pageindex,每页页数pagerows,dataindex里是列标识与序号的映射,rows里是序号与列值的映射,要结合着看,比如number对应的值是rows里的第三个

image.png

下面我们从源码分析这个loadData请求,其实主要就是这些内容

image.png

先看createModelData(model)方法,实际会调用AbstractFormDataModel#createNewData方法,逻辑还是比较清晰的:先触发插件的createNewData方法,如果插件方法给入参里的dataEntity赋了值,就用这个作为model里的,否则new一个 DynamicObject来作为,createDefaultEntity方法会给主业务组织赋默认值和给单据体添加缺省行数。

最后再触发插件的afterCreateNewData方法,这么看其实逻辑并不多,都在插件里。

image.png

平台默认自带的插件和列表自带的插件(下图前三个,Hide那个是我二开的),beforeCreateNewData和afterCreateNewData方法没啥逻辑,所以核心逻辑还在后面

image.png

再看看this.view.updateView()方法,我们这是打开列表,会进到kd.bos.mvc.list.ListView#updateView方法:这方法很长,先是对过滤控件做处理,再设置排序相关,最后是刷新视图,刷新轻分析视图等,这里主要看核心逻辑super.updateView(),即kd.bos.mvc.list.AbstractListView#updateView

image.png

这里主要是对单据列表控件设置一些权限filter,核心逻辑还得往super找,即kd.bos.mvc.form.FormView#updateView()

image.png

欸,这里逻辑有点意思了,居然在触发插件的beforeBindData方法和afterBindData方法(标品自带插件里这两方法同样没啥逻辑),看来获取业务数据的逻辑就在这中间的IFormDataBinder.updateView()!!!

其实仔细想下,逻辑在这并不奇怪,因为不管是打开表单(FormView)还是列表(ListView),都需要获取业务数据,当然得放在父类里

image.png

kd.bos.mvc.form.FormDataBinder#updateView()方法逻辑如下

image.png

会先收集触发时机为【创建】的界面规则和业务规则,然后触发FormRoot的bindData方法

image.png

FormRoot类继承自Container类,表示整个表单的根容器(对照下图更好理解),未重写bindData方法。

image.png

Container类可以理解为元数据设计时用的flex容器,包含许多控件(即下图items),其bindData方法就是遍历执行下级控件的bindData方法

image.png

这里我们打断点逐一查看items,很容易发现有个BillList类型的控件,这不就是单据列表的标识,去看它的bindData方法!

image.png

此方法先是触发注册的beforeBindDataListeners,再调用bindData方法真正去获取数据,然后调用super.bindData方法,即继续遍历执行itemsbindData方法,最后触发注册的afterBindDataListeners(所以可以利用这两个listener做一些二次开发

image.png

继续看this.bindData方法:还是先调用getListData方法拿到data,再通过clientViewProxy类把data返回给前端(此处setEntryProperty最终会添加到u里返回)

image.png

getListData方法会先判断分页用到的limit(即第几条,多少条),终于看到熟悉的操作,看来这个getData方法要查询数据了

image.png

这个方法特别长,咱们长话短说,就是拿到ListModel(列表数据模型),设置过滤条件,需要查询的字段,此次查询的最大数据量,然后通过model.getData方法去查询数据,最后按u的格式组装数据(注意这里分页数据会存放在model里)

image.png

进入model.getData方法,再次发现是调用provider的getData方法,这个provider就是我们在列表插件beforeCreateListDataProvider方法里设置的那个ListDataProvider,没设置时默认用kd.bos.mvc.list.ListDataProvider

image.png

进入kd.bos.mvc.list.ListDataProvider#getData方法,又是交给query对象去处理,这个query取决于列表查询方式配置是IdQuery还是SqlQuery,QueryBuilder对象存放了过滤条件,limit等

image.png

后面的代码就不继续往下看了,等后面专门出一篇文章细讲。


现在知道u是从哪来的了,updateControlMetadata,InvokeControlMethod还不知道,我们从ClientViewProxy打条件断点重新调一次接口(怎么打断点上一篇有讲),触发的代码太多,找几个看下就行。

比如updateControlMetadata都是在控件bindData时触发

image.png

image.png

createClientConfig方法就是取各种属性组装返回

image.png

InvokeControlMethod会比较绕一点,一般都是从这几个calls,states1转换而来的,_premethodCalls和_methodCalls其实用法相同,都是操作控件某些方法,只是_premethodCalls里的会放在前面,优先于_methodCalls里的被前端执行,下面两个states1会在setVisible,给单据体字段设置setEnable时添加值

image.png

5、总结

loadData请求主要就是触发view的updateView()方法,打开列表时view是ListView,这里override逻辑里比较重要的是会设置权限qfilter,然后走父类FormView#updateView()方法,逻辑分这几步(下一篇讲加载表单时逻辑相似):

  1. 触发插件的beforeBindData方法

  2. 拿到表单的根控件(可以直接理解为元数据设计列表时的根节点),调用其bindData方法,继而遍历其下级控件的bindData方法,很多控件会在此时通过updateControlMetadata把自身的配置信息传递给前端,通过InvokeControlMethod让前端执行控件的一些方法,如过滤控件会添加过滤字段等

  3. 重点是会触发单据列表控件BillList的bindData方法,会收集过滤条件,需要查询的字段,此次查询的最大数据量limit等,然后用具体的查询方式,如IdQuery、SqlQuery去查询数据(最终也是通过ORM.queryDataSet查询的数据库,然后转换成DynamicObjectCollection),数据会存放在BillList的ListModel里,最后按分页接口的格式组装数据返回给前端

  4. 触发插件的afterBindData方法



赞 0