Happy3w

参照开发详解

2017.02.10
说明:此文收集自一个未知名的作者文档资料,如作者看到,可以过来认领署名 参照是在NC框架下开发中非常常见的一个专项,本质就是在编辑某字段时通过触发参照时获得的一些信息(集团、组织、用户等),临时拼成SQL语句,到数据库中指定的单张或联查多张表,过滤出所有备选项,展现在页面参照选择对话框中供用户选择。目的是统一提供基本档案的录入,防止手工录入产生的错误。NC系统中的参照大致分为两种:系统参照(物料、集团等预制好的)和自定义参照。 一、 系统参照开发 1、单据模板参照 对于这些平台预置好的参照,开发过程十分简单。只要把元数据中相应字段的类型样式设置为“REF”,类型设置为平台预置的众多参照中的一个即可,不过仍须注意有的参照类型选定后没有自动带出参照名称,这个是需要手动补上的,否则作为查询参照时可能取不到值(如下图红框处)。 ref1 另外,在单据模板初始化里,对于参照字段,在高级属性里面还可以对参照进行具体的设置,比如离开焦点显示名称、是否启用数据权限等。 有一些较为复杂的参照,还需要人为的在编辑前事件中传入一些参数,这样才能准确的过滤出想要的数据,下面以离散订单表头产品字段为例,在它的编辑前事件中需要先取出它的参照model,设置集团等信息,再进行参照过滤。 ref2 2、查询模板参照 查询模板中的参照字段可以设置的选项比较少,只有参照是否包含下级可以设置,这些查询模板上的参照字段往往也需要设置过滤条件,其本质也是在查询面板中得到参照字段的参照model然后设置过滤条件,但是由于查询模板编辑时不像单据模板可以得到编辑前后事件,所以参照的过滤和字段间的联动关系,设置都稍微复杂一些。 查询模板上的参照设置都需要在平台预留给各个节点的IQueryConditionDLGInitializer接口中进行设置,在此接口中的初始化查询对话框方法里,平台会把查询模板对话框代理QueryConditionDLGDelegator作为参数传入,它包含了查询面板,所以可以在其上进行查询模板上字段的参照设置。下图以部门参照过滤设置演示最简单的查询参照过滤。 ref3 可以看到,直接调用得到的QueryConditionDLGDelegator对象的setRefFilter方法即可设置字段参照,传入参数指定要设置的字段名和过滤器。过滤器为平台IRefFilter的对象,写法固定,只是根据具体需要替换掉上图红框中内容即可。上例中展示的是通过封装好的工具实现过滤逻辑,部门公共框架中也提供了不少预置好的过滤工具。当然这里也可以直接写过滤逻辑,通常是通过已经得到的refPann得到参照model,并且像单据模板设置参照那样设置查询条件,也可以直接拼接SQL语句的where部分,设置给参照model,这样可以实现随心所欲的过滤。 另外,有的时候一个字段的过滤条件需要根据另一个字段的值追加过滤,比如物料需要根据前面的主组织字段追加过滤条件。在单据模板上可以在物料的编辑前事件得到主组织的值,但是查询模板就没有这么方便了。需要我们手动给QueryConditionDLGDelegator配置字段的监听来实现。首先需要继承平台提供的AbstractLinkageColumnListener类,它是专门处理查询条件值联动的,在其内部进行联动事件的添加,重写它的抽象方法processLinkageLogic,在此方法中可以得到联动中的上级字段值和下级字段的editor,进而就可以得到下级字段的参照面板和参照model,之后的参照过滤设置就和之前的一样了。 ref4 上例中可以看到,继承平台的AbstractLinkageColumnListener子类中定义了一个添加监听的方法,设置上级字段名(即被监听是否改变的字段)和下级字段名(即此事件触发时需要改变参照过滤的字段,支持传入List,可以一个字段改变影响多个下级字段),再调用传入的QueryConditionDLGDelegator对象的registerCriteriaEditorListener方法,将自已本身作为参数传入,就完成了这个查询面板上的上下级参照值联动事件的注册。此类中还需实现上面提到的processLinkageLogic方法,以具体定义上级字段值改变时下级字段参照值改变逻辑。 二、 自定义参照开发 1、 最简单的自定义参照 自定义参照是平台提供的参照之外用户自己定义的参照,其本质和平台预置的参照是一样的,基本都是具体业务单据如生产订单,给其他单据提供出参照,用以在其它单据的某字段上过滤选择自己的单据。下面以流程生产订单表头参照,来演示一个最简洁的自定义参照有哪几个必要组成部分,以及开发流程。 首先自定义参照不像系统参照,都是UAP或其它部门档案提供好了参照模型(RefModel),指定好了过滤数据的SQL拼接规则,自定义的参照需要自己进行参照模型的定义(注意:该参照对应的表在元数据实体定义时一定要实现IBDObject,用于设置参照返回值)。这也是自定义参照最重要的工作量,一个最简单的参照模型定义有如下几个部分: ref5 如图,普通的自定义参照需要继承平台提供的参照基类nc.ui.bd.ref.AbstractRefModel,然后是参照标题(参照对话框的标题文字)以及参照对应的数据库表(即参照SQL的from部分,如果是多表联查的复杂情况,这里就需要返回SQL语句中的表连接部分)。这些定义以及下面提到的在基类中都有对应方法定义,在子类中重写基类中方法,返回正确值即可。 ref6 接着是所有会默认在参照对话框显示字段的定义,包括字段的显示名(在参照对话框中此字段显示的名称)和字段编码(此字段对应的数据库表中的名称)。这里编码部分给字段名加上表名前缀是为了支持可能有多表联查的情况。上图最后的方法是返回一个INT值,指定默认显示字段前几个有效,一般定义在这里的都是要显示的,返回默认显示字段数组的大小即可。 ref7 之后是参照中默认隐藏的字段定义,这些字段和上面说的默认显示字段和在一起就是查询数据表时得到字段的全集(即拼接SQL语句的select部分)。隐藏字段在参照模型从指定表中查数据时也会查询出来,但是不会在参照对话框中显示出来,其意义在于一些参照的复杂业务逻辑(例如表主键字段等,在参照选择时显示没有意义,但是主键值作为参照的数据唯一性校验标准、其它字段也可能在参照的复杂的编辑后事件中用到)。 ref8 接下来是三个比较重要的方法的重写,这三个方法都要求返回一个字符串,意义可能比较容易混淆。如上图所示,第一个方法返回的是参照的主键字段名,参照模型从表中取值不能有数据重复、用户手动输入的参照值在表中不存在需要消除掉等都是以此字段作为唯一性依据的;第二个方法返回参照名称字段,第三个方法返回参照编码字段,顾名思义分别指定了参照模型众多字段中的名称属性和编码属性。其用处就是我们在单据模板对这个参照设置离开焦点是否名称时体现了,离开焦点显示名称则会在该参照编辑后显示这里定义的名称字段属性的值,否则显示编码字段属性的值。离开焦点前则统一显示这里定义的编码字段属性的值。 ref9 最后一部分,也是最重要相对最复杂的一部分,指定参照查询数据的过滤条件(即参照SQL语句中的where部分)。一般最简单的参照至少也需要按集团、组织和DR进行过滤,当前的集团和组织都可以从参照基类里面取到,方法是:this.getPk_group()、this.getPk_org(),十分方便。不过即使这最简单的参照过滤条件的设置中也暗藏危险,注意上图红框中部分,一般情况下我们去重载基类中的方法,尤其是像AbstractRefModel这样的抽象类,我们就会忽略基类中具体的方法实现,完全去重写它。但是如上图所示一定要加上基类中该方法的实现,因为基类该方法默认实现了参照模型中消除用户手动不存在输入的逻辑,这个逻辑有些隐蔽。 以上所有截图合并起来就是一个最简单的参照模型的实现了,当然参照逻辑复杂起来可以相当的复杂,基类中也提供了大量高级属性和方法供调用和重写,比如distinct子句、order by子句、group by子句、多表关联查询、是否支持多选、字段值映射转换、参照值改变时事件监听的重写等等,这些尽量在后面的复杂自定义参照中介绍。 参照模型定义完毕后,需要注册这条参照信息,这个目前没有相应工具,需要我们手动在参照注册表(bd_refinfo)中插入一条数据。如下图,一般的字段参照表中其它数据填写就好,注意REFCLASS属性里填入定义的参照模型的路径名+类名;REFTYPE属性代表参照的类型,我们普通的参照就填0(列表型)即可;CODE属性一般填写参照所属功能节点编号;NAME属性便于辨认就好。 ref10 之后需要在相应的元数据上对该参照进行设置,因为参照是通过把字段类型设为对应节点的元数据,然后从它提供的所有参照中再继续选择引用的。首先启动中间件,然后在该参照对应的元数据具体实体上设置该参照(对本例来说就是流程生产订单的主表实体)。在该实体属性页的参照页签,右键->设置参照,如下图把新注册的参照选中确定即可。 ref11 以上参照提供方(按示例来说就是流程生产订单方面)的工作就完成,需要引用这个参照的单据,只需在自已模板的相应字段上设置字段类型为REF,类型为流程生产订单的表头元数据实体,参照类型为新定义的流程生产订单参照即可。下图以流程投放计划对此参照的引用为例。 ref12 这样下来,一个最简单的参照开发流程就结束了,之后在参照字段具体使用时,单据模板中的参照属性设置、编辑前事件传入过滤条件值、编辑后事件处理多选分行、参照字段最为查询条件的相关设置等,就都同开始时介绍的系统默认参照部分一样了。最后加上一张参照整体框架的结构图,便于从整体上认识参照: ref13 2、 复杂自定义参照 待续。 3、 其它自定义参照 上面描述的自定义参照都是列表型自定义参照,我们绝大部分自定义参照和系统参照都是列表型参照,即所有备选项在下拉列表中显示。另外还有树型参照(有级次关系的档案,如业务单元档案)、数表型参照(左树右表,对于有级次和分类关系的档案,如物料多版本档案)。不过这两种参照只是个别系统参照中有使用,我们只需引用即可,自定义参照开发中基本不会用到,所以此处不做详细描述,请参看系统提供的业务单元档案和物料档案参照。