EKP表单自定义宝典 - 图文

更新时间:2023-11-18 04:41:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

蓝凌EKP-J

表单自定义宝典

文档控制/Document Control

修改记录

审阅人

分发

日期 作者 版本 备注 2010/8/31 叶中奇 1.0 第一个版本

日期 审阅人 版本 备注

日期 分发人 分发对象 备注

目 录

第一章

导读......................................................... 4

从什么地方开始 ................................................... 4 相关资料 ......................................................... 4

1.1 1.2 第二章

快速入门 ..................................................... 4

第一次使用表单自定义 ............................................. 4

表单自定义可以做什么 ............................................. 5 表单自定义可以用在什么地方 ....................................... 6 表单自定义不能做什么 ............................................. 6

2.1

2.2 2.3 2.4 第三章

使用表单自定义 ................................................ 6

使用表单自定义工具 ............................................... 6

表单自定义的版本功能 ............................................ 14 理解表单自定义的数据存储 ........................................ 15 使用表单自定义的高级控件 ........................................ 17

3.1

3.2 3.3 3.4 第四章

扩展表单自定义 ............................................... 26

扩展表单自定义中的存储事件 ...................................... 26

扩展表单自定义工具中的控件(未展开说明) ........................ 32

4.1

4.2 第五章

在应用中部署表单自定义 ........................................ 32

部署说明 ........................................................ 32 部署表单模板 .................................................... 33

部署表单主文档 .................................................. 35 部署表单存储映射 ................................................ 41

5.1 5.2

5.3 5.4

第一章 导读 1.1 从什么地方开始

? 若您对表单自定义完全不了解,建议您先查阅“快速入门”章节。

? 若您了解表单自定义的基本概念,想使用表单自定义来完成您的业务需求,那建议您查

阅“使用表单自定义”的章节。

温馨提醒:“使用表单自定义”的章节将由浅入深,告诉您如何使用表单自定义,当然,深一点的内容需要有一定的编程基础。

? 当您发现现有的表单自定义满足不了您的业务需求的时候,您期望做一些扩展,那您可

以查阅“扩展表单自定义”章节。

温馨提醒:该章节需要有一定的EKP-J编程基础。

? 若您期望在一个新的模块能使用表单自定义的功能,那请查阅“在应用中部署表单自定

义”章节。

温馨提醒:该章节需要有一定的EKP-J编程基础。

? 若您是一个表单自定义的使用者,一个非开发人员,建议您查阅本文的所有案例,了解

通过表单自定义可以做到什么程度,若您是一个开发人员,建议您通读全文。

1.2 相关资料

本文涉及到公式定义器的相关知识,请参阅详见《公式定义器宝典》 涉及到流程部分的知识,请参阅详见《流程宝典》

第二章 快速入门 2.1 第一次使用表单自定义

我们在费用报销的时候经常会碰到一个这样的需求,当报销金额大于10000元的时候,需要高一层的领导进行审批,然后再交给财务审批。

在不开发新模块的情况下,我们一般会用审批流程来完成这个需求。然而,由于我们需要在流程里面获取到报销金额的字段,所以我们不能采用RTF作为审批的内容,而借助表单自定义的功能,可以很好地解决该问题。 自定义表单定义:

打开审批流程模块模板定义的界面,切换到审批内容标签,我们可以看到表单自定义工具:

操作按钮区

内容编辑区

我们很快就可以定义出这样的界面:

由于报销金额是数字类型,所以我们在字段的属性中,设置“数据类型”为“数字”。

流程定义:

在流程定义里面,我们增加了一个条件分支的节点,通过定义公式:“$报销金额$>10000”作为条件分支的条件公式,实现当报销金额大于10000元的时候,需要高一层的领导进行审批,然后再交给财务审批的需求。

2.2 表单自定义可以做什么

在普通的应用中,每种类型的文档(或记录)都会有自己固有的属性(如标题、创建时间等),若期望添加而外的属性,就必须通过修改代码的方式实现,而EKP-J的表单自定义的功能就是为了打破该限制而产生的。通过表单自定义,我们可以不通过修改代码,灵活得添加额外的属性,并对界面进行排版。而这些额外添加的属性,可能会被使用到其它的地方,如流程的判定、统计查询等,因此这些数据的存储必须是结构化的(而不是像RTF一样全部保存)。

此外,客户可能已经知道针对不久的将来,当公司制度发生改革的时候,某些特定表单的内容也会随之改变,客户期望这些表单是“活”的,是可以自己配置的。而这个时候,表单自定义将是客户需求的最好解决方案。

2.3 表单自定义可以用在什么地方

目前在我们的系统中最常使用表单自定义的是审批流程模块,在该模块中,用户根据不同的业务场景,定义不同的表单,满足各种业务需求。

另外,比如公文模块,大部分客户对公文模块的需求基本上都一致,许多基础的字段基本上都一致,后台的业务逻辑也大同小异,最不一样的地方可能就是公文的展现方式,每个企业可能会有自己的公文表单展现习惯,或者有几个定制化的字段。若我们可以在公文模块中启用表单自定义的功能,就可以屏蔽掉企业间的差异,用一个标准的公文模块通杀所有企业的公文需求。

还有HR的员工信息等,各个企业都会有一些差异化的字段,这也是一个表单自定义很好的实战场景。

当然,您可以根据您的实际业务需求,把表单自定义“发扬光大”。

2.4 表单自定义不能做什么

从前面的用途我们基本上发现,目前我们的表单自定义都是依附于某个模块实体的(比如审批流程、公文等),通过表单自定义的功能,我们可以在上面灵活地进行属性的扩充,但它并不包含增删查改的功能,也不包含视图展现等,更没有在上面直接部署机制。所以我们无法通过自定义表单直接“开发”出一个全新的模块。

该限制可能在将来的版本中会有所改动,但至少现在的版本是无法这样做的。

第三章 使用表单自定义 3.1 使用表单自定义工具

我们在审批流程的模块 – 模板设置 – 审批内容标签中,可以找到表单自定义的工具界面,如下图:

操作按钮区

内容编辑区

3.1.1 表单自定义使用的小窍门

1、 使用百分比定义控件宽度。

当我们定义一个控件的宽度的时候,通过拖拉的方式定义,单位往往是像素,但这样定义往往适应不了终端用户的屏幕分辨率,就会导致宽屏终端显示内容太少,或者窄屏用户出现横向滚动条等现象,为了解决该问题,您可以在属性框中按百分比定义宽度(如: “90%”),这样就可以适应各种终端显示器了。

2、 选择界面控件。

通过Ctrl+左键,可以选择多个控件。

当是界面的控件很多,难以点选的时候,还可以点击定位到相应的控件。

3、 快速创建多个同类型的控件。

若需要创建一个单行文本输入框,我们需要在操作按钮区中选择了单行文本输入框,然后点击内容编辑区。当我们期望创建多个输入框的时候,我们可以在操作按钮区中选择单行文本输入框,然后按住shift键不放,在内容编辑区的不同地方点击,这样就可以连续创建多个编辑框了,若期望取消,按下Esc就可以了。

4、 拷贝整个表单。

若我们前面做好了一个表单,我们可能期望在一个新的表单中使用原来的表单,然后在

新表单里面稍微修改一下,做为新的表单使用。显然,界面里面一个个控件的拷贝太繁琐,我们可以这样操作。点击显示高级控件:

,旁边会显示“编辑表单HTML展现控件树,在控件树中快速

代码”的按钮,点击该按钮,在编辑区域里面就会显示整个表单的HTML代码,这时候,我们可以将所有代码拷贝到另外一个表单中使用,拷贝完毕后,记得点击“设置HTML”按钮,使您拷贝的HTML代码生效。

注意:除非您对表单的HTML代码非常熟悉,否则不建议您直接通过修改HTML代码的方式修改表单。

3.1.2 控件的属性

在我们双击控件的时候,会弹出控件的属性窗口,下面是一个单行文本输入框的属性:

在属性界面中,需要注意的有几个地方:

1、 数据类型

表单中每个被存储的数据项都是有数据类型的,数据类型对于后面的公式计算等方面起

到了非常重要的地位。下表列出了表单自定义中的各种控件的数据类型: 自定义表单元素 单行输入框 多行输入框 单选按钮 多选按钮 下拉菜单 富文本框 附件 地址本选择框 日期选择框 隐藏字段 字符型 由该控件的“数据类型”属性确定是字符型还是数字型。 字符型,多值用;分隔 由该控件的“数据类型”属性确定是字符型还是数字型。 字符型 不参与任何公式计算 组织架构对象类型(SysOrgElement) 日期时间型(Date) 由该控件的“数据类型”属性确定是字符型、数字型、日期型。 类型确定 由该控件的“数据类型”属性确定是字符型还是数字型。 前端计算控件 数字型 看完了这张表以后,您可能会对日期时间型(Date)、组织架构对象类型(SysOrgElement)

的概念还比较模糊,没关系,在您往后的使用中,我们会详细地介绍它:若您需要在公式定义器中使用,那《公式定义器宝典》会有详细描述;若您在扩展表单自定义的章节中使用它,那该章节也会为您进行描述。

2、 初始值

您可以在初始值输入框中,输入该字段的初始值。直接手工输入的内容不进行公式计算,若期望初始值通过公式来进行计算,请点击“公式定义”的按钮,在弹出框中输入公式,公式输入完毕后,属性框中的初始值被锁定,不能直接输入,同时下面出现“更新时重新计算”的选项。若您期望修改为非公式计算的模式,那请再次点击“公式定义”按钮,将公式清空后即可。公式定义器的使用,详见《公式定义器宝典》。

初始值的计算是有顺序的,顺序是按照界面从上到下,从左到右的顺序执行。

案例1:初始值计算顺序

我们在表单自定义中定义了以下几个字段:

在实际运行中,总额1的初始值计算结果为0(原因是由于在计算总额1的时候,单价和数量的初始值并未初始化),总额2的计算结果为200。

案例2:更新时重新计算

在案例1中,我们可能期望总额是不能让用户自己输入的,而且当单价和数量发生改变的时候,需要重新计算总额这个字段,那我们就可以在总额字段的属性框中将该字段设定为“只读”,而且是“更新时重新计算” 3、 ID

ID是该控件的唯一标识,修改时请谨慎,否则可能导致引用地方的错误。

案例1:字段改名对公式的影响

问:我在流程中使用了公式:“$金额$>1000”,后来我把“金额”这个字段名称修改为了“报销金额”,可是我忘记修改了流程中的公式,这时公式的计算是否还能正常运行? 答:公式计算时候引用的是字段的ID,只要ID没有发生改变,公式是能够正常运行的。但在流程定义的界面中,公式显示的地方可能还是出现“$金额$”这个变量,这只是显示没有更新而已,重新打开公式定义器的页面就会自动更新名称。但是若您把金额这个字段删除了,那公式运行时就会报错。

案例2:更换控件的展现形式

问:我开始用单行文本输入框定义了一个报销内容的字段,可用了一段时间后,发现单行文本输入框太小了,我想把它换成多行文本输入框,我该如何操作才能兼容以前的数据显示?

答:若您直接删除了单行文本输入框,然后再添加一个单行文本输入框,这个时候系统会认为这两个是不同的字段,所以旧数据是无法显示在新的多行文本输入框中。要解决该问题,您可以先将单行文本输入框的ID记录下来,再删除单行文本输入框,创建多行文本输入框后,将原来的ID写入到多行文本输入框中,这样系统就会认为这两个字段是同一个。

3.1.3 控制表单字段级权限

在一个标准的EKP产品模块中,主文档的数据基本上都是由起草人进行所有字段的信息输入,审批人若有“编辑主文档”的权限,那他就可以进入编辑页面,对文档字段进行修改,但往往在审批过程中,需要控制到字段级的权限。 下面举个员工转正申请的例子说明表单的权限。

3.1.3.1 案例需求

表单内容大概定义如下:

我们需要实现申请人能填写“申请人填写”部分内容,流程中的“部门经理审批”节点处理

人可以填写“部门经理填写”部分内容,流程中的“HR经理审批”节点处理人可填写“HR经理填写”部分内容。另外,我们还期望HR经理填写的意见,人力资源部和总裁办的所有人可以查阅,其它人不可查阅。

3.1.3.2 案例实现

第一步:插入权限区段

为了实现这个需求,我们需要插入权限区段后的表单的样子如下:

,将特殊权限的区域放入权限区段中。插入

注意上图的红色小方块就是权限区段的作用范围。其中,申请人填写部分,由于跟标准的权限一致,所以可以不设置权限区段。

第二步:设置默认权限

定义好区段后,点击显示权限设置

按钮,进入权限设置界面:

双击这里可以修改区段名称 点击这里可以切换场景 点击这里控制阅读状态的可访问权限,针对所有场景生效 点击这里切换本场景下的隐藏/阅读/编辑权限

场景说明:

默认权限:除起草节点外,所有的节点都默认使用“默认权限”的设定,流程审批通过以后也使用“默认权限”的设定。

流程场景-起草节点:该场景下,所有权限区段默认都为编辑权限。

由于我们期望HR经理填写的意见,人力资源部和总裁办的所有人可以查阅,其它人不可查阅,所以我们可以点击HR经理意见区左边的第一个小图标,设置该区段的查看人为人力资

源部和总裁办。

第三步:设置起草节点的权限

需求:起草节点不能修改“部门经理填写区”和“HR经理填写区”的内容。

操作:切换到“流程场景 – 起草节点”场景,将所有区段设置为阅读权限,如下图:

小技巧:在流程场景中,权限区段会出现第三个小图标:随默认权限。由于这几个区段的默认权限都是阅读权限,所以我们可以将第三个图标点亮,这样,将来修改默认权限的时候,起草节点的权限也会随之改变,减少维护工作量。

第四步:设置“部门经理审批”节点权限

需求:部门经理可以填写“部门经理填写区”的内容。

操作:切换到“流程场景 – 部门经理审批”场景,将“部门经理填写区”的权限修改为编辑。

第五步:设置“HR人事经理审批”节点权限

需求:HR经理可以填写“HR经理填写区” 和“HR经理意见区”的内容。

操作:切换到“流程场景 – HR人事经理审批”场景,将“HR经理填写区”和“HR经理意见区”的权限修改为编辑。

3.1.3.3 案例总结

从上面的案例,总结一下权限设置的思路:

1、 在EKP的标准应用中,所有的字段都是起草节点可编辑,审批节点不可编辑。 2、 即使您插入了一个权限区段,这个权限区段默认的设置也遵循上一条规则。

3、 您可以通过切换场景的方式,对特殊的场景加以描述,满足实际的需求。如切换到起草

节点场景,将区段的权限设定为阅读,切换到某个审批节点场景,将某个区段设定为编

辑。 另外:

1、 通过修改“默认权限”的场景,您可以修改所有场景的默认权限状态,包括流程结束后的状态。

2、 通过修改可阅读者,您可以限制某个区段的可阅读者范围(为空则不约束可阅读者范围),

可阅读者仅仅是对阅读权限的扩充,编辑和隐藏权限不受此范围影响。可阅读者将作用于所有的场景。 3、 权限区段可以控制单个字段(如:“HR经理意见区”),也可以控制整个表格(如:“HR

经理填写区”)。 4、 权限区段是可以进行嵌套的,在上面的案例中,“HR经理意见区”就嵌入在了“HR经理填写区”里面,若“HR经理填写区”不可见,那“HR经理意见区”也相应的隐藏了,

但“HR经理填写区”一旦可见,那“HR经理意见区”的具体权限就由该区段的设置决定。

3.1.3.4 明细表的权限控制

我们来看两个例子:

案例1:

由于明细表的行是动态添加的,所以当权限区段设定在某个字段的时候,该权限将扩展到明细表的该列的所有同类字段。从上面的案例看,您可以编辑明细表中所有行的“采购数量”字段。

案例2:

同样的明细表,但这次我们把权限区段扩展到了整个明细表,这时候,您除了可以编辑明细表的所有字段外,还可以进行增加、删除、移动行的操作。

3.2 表单自定义的版本功能

当您对一份已经定义好的表单进行了修改,再次保存的时候会弹出以下提示框:

虽然版本号没有在界面中进行体现,为了描述的方便,我还是加上版本号进行说明。假如该表单第一次保存的时候,版本号为V1,然后进行了一次修改,选择了保存为新版本,这时候版本号为V2,现在又做了一次修改,最新版本的版本号为V3。表单展现的情况如下表:

执行操作 保存为新版本 保存为原版本

举个例子:

我们在自定义表单中定义了一个名字为“金额”的字段,然后创建了一份文档A,接下来我们对表单进行修改,将“金额”字段修改为“报销金额”,这时候,若我们执行的操作是“保存为新版本”,那打开文档A看到的还是“金额”这个名字,但若我们执行的操作是“保存为原版本”,那打开文档A看到的就是“报销金额”这个名字。

一个不能保存为原版本的案例:

我们在自定义表单里面定义了一个名字为“金额”的字段,由于一开始的疏忽,所以将金额的字段设置成了字符串类型,结果在创建文档的时候,不少用户可能就在金额字段里面直接写入了“10万”、“10万元”这样的数据。后面我们发现这个金额字段无法用于计算,于是我们期望把金额字段修改为数字类型,在输入框后面,我们再加了个“万元”作为单位,提醒用户的输入,若此时保存为原版本,那系统在打开旧文档的时候,会将“10万”这样的数据转换成数字类型,这种转换明显是无法成功的,系统只能抛出错误,在这种情况下,只能通过“保存为新版本”方式进行保存。

综上所述:

当您期望所做的修改对于旧文档生效的时候,执行“保存为原版本”的操作,否则执行“保存为新版本”的操作,然而当您对数据进行了类型变化的时候,建议还是“保存为新版本”,以便兼容旧数据。

基于V1创建的文档 使用V1表单 使用V1表单 基于V2创建的文档 使用V2表单 使用V3表单 当然,以后新建的文档都会基于V3创建。

3.3 理解表单自定义的数据存储

温馨提醒:本章节内容需要有一定编程技术。

3.3.1 表单自定义数据存储方式介绍

在默认的情况下,表单的数据将以XML(详见3.3.2章节)的方式,存储到主文档的表中。这种存储方式虽然为可以保证表单的变动不会影响到数据库表结构,但同时也带来了查询的困难。具体的内容详见3.3.2章节。

为了解决查询的问题,表单自定义提供了另外一种存储的扩展:表单数据映射(详见3.3.3章节)。表单数据映射允许您将表单的字段跟EKP-J使用的关系数据库的某张表的字段一一对应,从而解决了数据的查询问题。

表单数据映射是应查询的需求而产生的,所以加了与EKP-J同一数据库的限制。为了突破这个限制,系统还提供了另外两种扩展:表单存储事件(详见4.1章节)和流程机器人节点(详见《流程宝典》相关章节),这两种方式可以通过编程或写SQL语句的方式,往异构系统或其它数据库中写入表单数据。其中表单存储事件是随表单保存触发的,必须通过编程方式实现;流程机器人节点则在流程流转过程中触发,适用于在某种特定条件下写入数据的场景,流程机器人节点可以使用编程或SQL语句方式,往其它系统中写入表单数据。

3.3.2 默认存储方式:XML

表单自定义的数据始终会在主文档表中一个大文本字段中以XML的格式保存。为了方便数据的读写,系统提供了“com.landray.kmss.sys.metadata.interfaces.ISysMetadataParser”接口,屏蔽了对XML数据操作的复杂性,具体的操作可参阅“扩展表单自定义中的存储事件”章节的案例。

3.3.3 表单数据映射

前面我们已经知道,表单数据映射是为查询而产生的需求。通过表单映射,我们可以方便地通过SQL语句,查询到表单自定义中的数据,并进行统计分析。

此外,EKP-J将来会推出自定义表单数据的查询功能,可以查询到表单中进行了数据映射的字段。

什么样的数据适合做数据映射?

一般的,当我们需要进行查询统计的数据,建议进行数据映射。比如:报销总额、所属区域等。对一些描述性的字段,如:出差原因等,不建议做数据映射。

虽然数据映射可以方便查询,但一旦将数据写入到数据库表中,就会受到数据库的字段类型、长度等约束,为数据的修改带来很大的困难,所以建议针对“合适”的字段进行映射,对于可能经常发生变动的字段,不做数据映射。

如何做数据映射?

案例:将一个项目报销单的所有字段进行数据映射。 报销单如下:

其中,项目成员是多值字段,是多对多的关系。

步骤:

1、 我们得在数据库中创建表,由于上面的表单中有明细表,还有一个多对多的字段,所以

我们需要创建三张表来进行数据映射,表结构如下: 主表:cf_project_cost

字段描述 主键 项目名称 项目经理 报销时间 报销金额 字段描述 主文档ID 项目成员ID 字段名 fd_id fd_name 字段类型 vchar(36) vchar(200) 备注 唯一主键,跟主文档ID对应 存储人员的ID,可以设置为外键,连接到sys_org_element的fd_id 备注 主键+外键,存储主文档的ID,关联到cf_project_cost的fd_id字段 fd_member_id vchar(36) 主键+外键,存储项目成员的ID,关联到sys_org_element的fd_id字段 备注 唯一主键 外键,存储主文档ID,连接到cf_project_cost的fd_id字段 细项名称 报销金额 fd_item_name vchar(200) fd_money double fd_manager_id vchar(36) fd_time fd_money 字段名 fd_main_id timestamp double 字段类型 vchar(36) 项目成员多对多表:cf_project_menber

报销明细表:cf_project_cost_detail 字段描述 主键 主文档ID 字段名 fd_id fd_main_id 字段类型 vchar(36) vchar(36) 2、 进入表单自定义所在模板的阅读界面,点击“表单数据映射”按钮,进行数据映射,具

体操作步骤略。

整个操作中比较麻烦的是建表的动作,上述的案例中,已经包含了字符型、数字型、日期型、组织架构(单值、多值)、明细表字段的建表。

在后续的流程表单版本中,会提供自动创建表结构的功能,您只需要在IE界面里面填写表名和字段名,系统会自动帮您在数据库中创建相应的表结构。由于数据库对字段的类型和长度的管理非常严格,删除字段、修改字段类型或长度这些操作可能会导致数据的丢失问题,所以系统不提供删除字段、修改字段类型或长度的功能,若需要执行这些操作,只能是到数据库中直接操作数据库了。

3.4 使用表单自定义的高级控件

3.4.1 使用前端计算控件

前端计算控件一般用来做前端的简单计算,如:总额=单价*数量,当单价和数量发生改

变的时候,总额将马上重新计算。

虽然前端计算控件的公式跟公式定义器非常类似,但相比起公式定义器来说,前端计算控件的功能要弱很多:参与计算的值只能是日期型和数字型的值(对于日期型的数据,系统会自动转换成毫秒数),而且返回的结果也只能是数字类型的值。但由于前端计算控件能即时地将运算结果展现给最终用户,而公式定义器只能在数据提交后才能计算,所以前端计算控件给最终用户带来了更好的体验。

前端计算控件的语法完全是JavaScript的语法,不过即使您对JavaScript语法不熟悉,您同样可以使用里面的简单功能。

案例1:使用前端计算控件,计算开始时间和结束时间的时间差,返回天数。 ( $结束时间$ - $开始时间$ ) / ( 1000 * 3600 * 24 ) 说明:开始时间和结束时间在公式运算时会转换成毫秒,所以两者相减就是时间差,单位为毫秒,再转换为天就可以了。

案例2:下面是一个采购申请单的样例,使用了明细表控件。

其中:小计=单价*数量,总额为所有小计的总和。

根据上面的要求,小计字段的计算表达式: $明细表1.单价$*$明细表1.数量$ 总额字段的计算表达式: $列表.求总和$($明细表1.小计$)

要理解这两个公式,首先得理解运行的上下文。

第一个公式,小计字段是在明细表里面的,所以“$明细表1.单价$”的值取的是同一行记录中的单价字段,是单值。

第二个公式,总额字段是在明细表外面的,所以“$明细表1.小计$”的取值不是针对单行记录而言,是针对所有记录而言,是多值。故通过“$列表.求总和$()”函数可以将所有的小计进行求和。

这个案例摘自《公式定义器宝典》,其实前端计算控件的语法和原理基本上一样,只是小计和总额的控件换成前端计算控件而已。

案例3:表单中有个分数的字段,期望通过分数自动计算出等级,等级和分数的对应关系为: 90~100:等级1 80~90:等级2 60~80:等级3 40~60:等级4 40以下:等级5

表达式:

function(){ if ( $分数$>=90 ) return 1; if ( $分数$>=80 ) }() 其实这就是一段简单的JavaScript,外面套一层function(){??}()是为了能写return语句。

return 2; if ( $分数$>=60 ) return 3; if ( $分数$>=40 ) return 4; return 5; 3.4.2 JSP片段和隐藏字段简介

小提示:在表单自定义的操作按钮区中点击,就可以看到JSP控件和隐藏字段的

按钮。

表单中的大部分控件都是面向非程序员设计的,这些控件是无法写代码的,但有些复杂的业务需求只能通过写部分代码来实现。为了解决这个问题,表单自定义提供了一个JSP片段的控件,允许您在表单中写入JSP代码,系统会将您的这些代码原封不动地放在最终展现的JSP

页面中。理论上,您可以通过JSP片段的功能,实现任何界面编程能实现的功能。

表单自定义中的每个字段都会有名字和类型。虽然您可以通过JSP片段来定义一个界面里面无法实现的字段,但由于JSP片段是直接交由J2EE容器解释的,所以我们无法辨别您在表单中定义了什么样的字段,字段的类型是什么,也就导致了这些字段无法正常保存,也无法正常参与公式运算。隐藏字段正是为了这个矛盾而设计的,隐藏字段不会在最终的JSP中生成任何代码,但它可以告诉系统有这个字段,字段的类型是什么,刚好拟补了前面提到的不足。通过JSP片段+隐藏字段,您就可以方便地对扩展界面的字段了。

3.4.3 在JSP片段中编写JavaScript

温馨提醒:本小节需要有一定的EKP-J的开发基础。

3.4.3.1 JSP片段中的JavaScript简介

既然JSP片段是将代码原封不动地输出到最终的JSP页面中,所以您可以借助JSP片段来编写JavaScript代码。

在大部分情况下,您可以通过事件的方式触发您的JS代码,常用的事件捕获的方法有:

JS代码样例 Com_AddEventListener(window, \ function(){ alert(\加载事件\说明 在窗口加载的时候触发事件。 }); Com_Parameter.event[\表单提交事件,您可以在这里编写数据校 alert(\表单提交事件\验的方法,返回false则阻止表单正常提交。 return true; }); XFormOnValueChangeFuns.push(function(value, domElement){ alert(\字段值变化事件\}); 当任意字段值发生变化的时候触发,您可以通过domElement对象获取到发生变化的字段对象(若为checkbox或radio时候为dom数组),通过value获取到改变后的值。 AttachXFormValueChangeEventById(\字段ID\当id为“字段ID”的字段的值发生变化的function(value, domElement){ 时候,触发该事件,比上一个方法更加常 alert(\指定字段值变化事件\用。 });

此外,表单自定义为您提供了一系列实用的JavaScript函数,您可以通过点击JSP片段输入框右下角的

按钮,查看这些函数的说明。

某些JavaScript可能需要在编辑状态下加载,另外一些可能需要在阅读状态下加载,遇到这种情况,请使用xform:editShow标签或xform:viewShow标签。如: 说明:

上面代码中,定义了一个changeHotelEnabled的函数,该函数判断若“否需要订酒店”的字段存在(注意:阅读状态下该字段对象会不存在),若存在则修改“酒店名称”的disabled属性。其中,函数GetXFormFieldById返回的值为数组。

通过Com_AddEventListener函数将处理方法绑定到页面加载事件中,通过AttachXFormValueChangeEventById函数绑定到“否需要订酒店”的值改变事件中。

3.4.3.3 案例2:获取明细表中的字段

需求:在明细表中,小计=单价*数量,合计=小计的总和,表单样例如下:

实现:其实这个功能可以通过前端计算控件非常容易地实现,但我们现在通过JSP片段的JS来实现这个功能。

几个字段的ID为: 单价:fd_2d964f6ba33a40 数量:fd_2d964f6cf8747c 小计:fd_2d964f6e658cfa 合计:fd_2d964f77cd6c6e

JSP片段的代码如下:

说明:

GetXFormSameRowFieldById获取跟发生变化的元素的同一行指定id的字段。 GetXFormFieldById则获取所有行的字段。

通过AttachXFormValueChangeEventById绑定单价和数量两个字段改变的事件。

注意:JSP片段的位置(见图片),请不要将JSP片段写入到明细表的第二行(即动态行)!

3.4.4 使用JSP片段扩展字段

温馨提醒:本小节需要有一定的EKP-J的开发基础。

3.4.4.1 案例1:从数据库中获取下拉选择框选项

需求:表单中需要定义一个区域的字段,该字段为一个下拉选择框,选项来自客户的另外一

套CRM系统,CRM系统给我们暴露了一个表,我们可以直接通过SQL语句查询到相关数据。

实现:

1、 创建数据源

由于需要访问到其它数据库的表,所以我们需要配置一个名称为“CRM”的数据源,配置地方见下图。

2、 创建隐藏字段,拷贝隐藏字段的ID,供后面使用

3、 在隐藏字段右边创建一个JSP片段控件,在里面插入代码: 说明:在xform:select的property属性中将ID粘贴进来。xform:SQLDataSource为select提供了选项数据,sql语句的返回值中,第一个值为选项id,第二个值为选项名字(可不返回第二个值,说明id和名字一致),忽略后面的值。xform标签的详细参数,请查阅xform标签的使用帮助手册。

3.4.4.2 案例2:使用对话选择框

需求:在另外一个模块中已经定义了项目信息,我们需要在表单自定义中定义一个“所属项

目”的字段,该字段能够通过选择按钮选择到项目信息。

分析:要保存所属项目信息,我们需要借助一个不显示的字段来保存项目的ID,再需要一个显示的字段来保存项目的名称,此外,还需要一个超链接,点击后弹出项目现在框。 实现:

1、 创建一个“所属项目ID”的字段,去掉“显示”的选项,如下图:

2、 创建一个“所属项目”的字段,勾中“只读”,如下图:

3、 创建一个JSP片段,在片段中输入代码: 说明: 这里加入了xform:editShow标签,是为了让选择按钮仅在编辑状态下显示,而不在阅读状态下显示。

函数Dialog_Tree是EKP-J中标准的对话框的JS调用,就不在此多加描述了。

3.4.4.3 案例3:明细表中的JSP片段

需求:同案例1的需求,只是将下拉选择框放入到明细表中。

实现:

假设我们已经完成了案例1的所有步骤。接下来,我们创建一个明细表,并将案例1中定义好的隐藏字段和JSP片段拖动到明细表中。接下来我们需要对JSP片段进行一些小修改,在此之前,我们需要获取到明细表的ID,为此,我们可以打开控件树,双击明细表控件,查看明细表,查看明细表控件属性,将ID记录下来,如下图:

修改JSP片段代码,如下: 说明:

在明细表中编写JSP片段,字段的property属性格式应该修改为: “extendDataFormInfo.value(明细表ID.!{index}.字段ID)” 其余的地方跟不在明细表一样。

另外,不建议在明细表中添加JavaScript代码,因为明细表添加行的时候,会动态将每行的信息进行复制,若添加了JavaScript代码可能会导致运行时的错误。

3.4.5 控制JSP片段的权限

若您还不了解表单自定义如何控制字段级权限,请查阅“控制表单字段级权限”章节。

表单自定义中字段级的权限是通过权限区段进行控制的,因此若您可以将JSP片段放入权限区段中,那JSP片段也将受到权限的控制。

权限区段可以控制整个区段的隐藏、阅读和编辑三种权限。当区段的权限为隐藏的时候,整个JSP片段将不输出到页面中;当区段的权限为阅读或编辑的时候,JSP片段会完整地输出到页面中。所以,进一步的阅读和编辑权限需要在JSP片段代码中进行控制。对于xform标签的定义的控件,如案例1中的xform:select等,xform标签在输出的时候自动依据权限输出阅读状态或编辑状态的HTML。对于无法使用xform标签的地方,如:3.4.3中的JavaScript代码,还有3.4.4.2中的选择超链等,我们可以使用以下标签,区分编辑或阅读状态下需要显示的代码:

<%-- 在这里编写仅编辑状态下使用的代码 --%> <%-- 在这里编写仅阅读状态下使用的代码 --%>

第四章 扩展表单自定义

温馨提醒:本章节内容需要有一定的EKP-J的开发基础。

4.1 扩展表单自定义中的存储事件

4.1.1 表单自定义的存储事件简介

表单自定义提供了四个触发事件,您可以通过编写代码的方式,在这四个事件触发的时候执行您的代码程序。

事件名称 onInit onAdd onUpdate onDelete

事件描述 初始化事件,在表单的所有初始值初始化完毕后触发。 添加事件,在表单数据第一次写入数据库时触发。 更新事件,在表单除第一次写入数据库外其它更新数据时触发。 删除事件,在表单数据即将被删除之前触发。 4.1.2 一个综合案例

4.1.2.1 需求描述

客户现有一个销售订单管理的系统,由于该系统的流程功能相对比较弱,所以期望对与某些

订单,能够启用EKP-J的流程进行流转。启动流程时会将销售订单号传递过来,并期望能通过订单号获取到订单的相关信息。在流程审批通过以后能将一些结果数据写回到销售订单系统中。表单的样例如下:

订单号:启动流程时传递。

客户名称、订单日期、产品名称、原价、购买数量:根据订单号从销售订单系统获取。 销售人员默认为当前用户,实际购买价格默认等于原价。

实际购买价格可以在流转中填写,审批通过后写回销售订单管理系统。

4.1.2.2 思路分析

这是一个系统整合的需求,若需要从后台启动一个流程,那难度有点高,可以通过另外一种

简单的方式实现客户需求。

首先,在EKP-J的审批流程模块中,定义一个销售订单审批的模板,假设通过该模板创建一个审批文档的URL为:

http://ekp.landray.com.cn/km/review/km_review_main/kmReviewMain.do?method=add&fdTemplateId=12345678901234567890123456789012

接下来,我们需要改造一下客户的订单系统,当某个销售订单需要启动流程的时候,出现一个按钮,点击按钮后,跳转到:

http://ekp.landray.com.cn/km/review/km_review_main/kmReviewMain.do?method=add&fdTemplateId=12345678901234567890123456789012&orderNum=123456 (在原有链接中添加一个订单号的参数)

点击链接后进入到我们的系统打开表单,这时候,我们可以通过表单的onInit事件获取到订单号,同时调用销售订单系统的接口,获取到其它信息,并写入到表单中,这样就可以启动一个EKP-J的流程。

当流程进行流转的时候,我们可以通过机器人节点,或通过捕获流程通过/驳回事件的方式,将流转的数据回写到销售订单系统中。至于这个动作该如何进行,请参考《流程宝典》的相关章节。

4.1.2.3 实现步骤

基于前面的实现思路,我们开始通过编程方式实现客户需求。

第一步:创建流程模板,设置自定义表单内容

按照需求样例创建表单,为了方便程序编写,我们可以将表单中的ID修改为: 订单号:fd_order_num 客户名称:fd_client_name 订单日期:fd_order_date 销售人员:fd_sales

产品名称:fd_prod_name 原价:fd_org_price 实际购买价格:fd_act_price 购买数量:fd_quantity 小计:fd_sub_total 总额:fd_all_sum

明细表ID:prod_detail_table

第二步:编写事件执行代码 创建一个java类,实现接口:

com.landray.kmss.sys.metadata.interfaces.IExtendDataEvent

样例代码如下:

package com.landray.kmss.km.reviewex; import java.util.ArrayList; import java.util.Date; import java.util.List; import com.landray.kmss.common.actions.RequestContext; import com.landray.kmss.sys.metadata.interfaces.IExtendDataEvent; import com.landray.kmss.sys.metadata.interfaces.IExtendDataModel; import com.landray.kmss.sys.metadata.interfaces.ISysMetadataParser; import com.landray.kmss.util.UserUtil; public class KmReviewOrderFormEvent implements IExtendDataEvent { // 计算小计和总额 List subTotalList = new ArrayList(); // TODO 在这里编写根据订单号从销售订单系统获取相关数据的代码 String clientName = null; // 客户名称 Date orderDate = null; // 订单日期 List prodNameList = null; // 产品名称列表 List priceList = null; // 原价列表 List quantityList = null; // 购买数量列表 public void onInit(RequestContext request, IExtendDataModel model, ISysMetadataParser dataParser) throws Exception { // 从URL中获取订单号 String orderNum = request.getParameter(\); public void onDelete(IExtendDataModel model, ISysMetadataParser } throws Exception { dataParser) public void onAdd(IExtendDataModel model, ISysMetadataParser } throws Exception { dataParser) double sum = 0; for (int i = 0; i < priceList.size(); i++) { } // 初始化主表的值 dataParser.setFieldValue(model, \, orderNum); dataParser.setFieldValue(model, \, clientName); dataParser.setFieldValue(model, \, orderDate); dataParser.setFieldValue(model, \, double subTotal = priceList.get(i) * quantityList.get(i); subTotalList.add(subTotal); sum += subTotal; UserUtil.getUser()); dataParser.setFieldValue(model, \, sum); } public void onUpdate(IExtendDataModel model, ISysMetadataParser } throws Exception { dataParser) } // 初始化明细表的值 dataParser.setFieldValue(model, prodNameList); \, dataParser.setFieldValue(model, priceList); \, dataParser.setFieldValue(model, priceList); \, dataParser.setFieldValue(model, quantityList); \, dataParser.setFieldValue(model, subTotalList); \, 说明:

1、 在onInit事件中,您可以通过request.getParameter的方式,获取到URL的参数。 2、 使用dataParser.setFieldValue方法,可以方便地对字段进行赋初始值。设值的时候,需

要注意数据类型,日期控件为java.util.Date类型,地址本为SysOrgElement类型(单值)或List类型(多值)。

3、 dataParser.setFieldValue的方法,允许您直接写明细表的数据,明细表的字段名字为“明细表ID.字段ID”,所设的值是一个数组,数组的第一个值为第一行记录的值,以此类推。同样的dataParser.getFieldValue的方法也允许您读取明细表的数据,字段名字为“明细表ID.字段ID”,返回值为列表。

4、 由于onInit事件是在初始值计算完毕后触发的,所以您需要重新对小计和总额两个字段的值重新计算赋值。

5、 为了避免升级困难,请将代码放在一个独立的模块,而不是直接写在审批流程模块,本

案例中使用的模块为km/reviewex

第三步:在spring.xml中添加类声明

创建/打开WebContent/WEB-INF/KmssConfig/km/reviewex/spring.xml注册对应的bean,样例代码:

第四步:在plugin.xml中注册扩展

创建/打开WebContent/WEB-INF/KmssConfig/km/reviewex/plugin.xml注册对应的bean,样例代码:

第五步:编辑第一步创建的流程模板,绑定事件

在表单定义工具下面勾选“显示高级选项”,选择表单存储事件。

4.1.2.4 进一步需求

前面我们实现了跟销售订单系统集成的需求,在销售订单系统中点击创建流程的按钮后,流程虽然能正常启动了,但流程启动以后,销售订单系统并无法知道这个流程已经启动,还可以再次点击创建流程的按钮。因此,我们期望流程启动以后,回写流程链接到销售订单系统,这样销售订单系统就可以出现另外一个按钮,点击后进入正在运行的流程。另外,若启动的流程删除了以后,我们还需要通知销售订单系统,恢复创建流程的按钮。

为此,我们只需要在前面的com.landray.kmss.km.reviewex.KmReviewOrderFormEvent类中添加onAdd和onDelete方法,代码片段如下:

public void onDelete(IExtendDataModel model, ISysMetadataParser throws Exception { \, true); dataParser) String orderNum = (String) dataParser.getFieldValue(model, public void onAdd(IExtendDataModel model, ISysMetadataParser } throws Exception { dataParser) String url = ModelUtil.getModelUrl(model); url = StringUtil.formatUrl(url); String orderNum = (String) dataParser.getFieldValue(model, \, true); // TODO 在这里编写将URL写入销售订单系统的代码 } // TODO 在这里编写清空销售订单系统的URL链接代码 说明:onAdd方法中,使用StringUtil.formatUrl的方式,是为了补充url中DNS。

4.2 扩展表单自定义工具中的控件(未展开说明)

目前的表单自定义编辑工具中提供了单行文本、多行文本、单选按钮、多选按钮等等页面控件,而这些控件都是基于表单自定义的扩展点进行扩展的。

理论上,您可以通过扩展这个扩展点,添加新的控件。但要实现这个扩展,需要有很强的JavaScript和EKP-J的开发功底,需要理解表单自定义的基础设计原理,了解多个EKP-J的底层机制,而这些知识并不是一两句话能说得清楚的,所以在本文档中暂时不详细展开,仅告诉大家控件是可以扩展的。

第五章 在应用中部署表单自定义

温馨提醒:

本章节内容需要有一定的EKP-J的开发基础;

表单机制的部署是所有机制部署中最复杂的,几乎需要修改了所有层的代码;若您还不了解EKP-J的机制部署,建议您先查看其它文档。

若您还不了解表单自定义的功能,建议您先查看前面的章节。

5.1 部署说明

5.1.1 名词解释

fdKey – 部署时各机组都采用的关键字,如果与流程相关,请保证fdKey相同 fdModelName – 类名,在模板和主文档部署时,表示的意思可能不同。 fdMainModelName – 主文档的类名。 fdTemplateModel – 模板的类名。

formName – Form在request中的名称。

5.1.2 机制部署步骤简述

根据表单的使用,我们可以知道,部署表单自定义的功能包括两部分内容,一部分是表单的定义,另外一部分是表单的运行。

通常的,我们会在分类或模板中部署表单定义部分,而在主文档中部署表单的运行部分。然而,有些应用中可能会没有分类或模板,目前暂未提供这种模式的部署。

5.2 部署表单模板

5.2.1 Model类的部署

修改模板Model类,在模板的Model类中实现接口: com.landray.kmss.sys.xform.interfaces.ISysFormTemplateModel 样例代码(请直接拷贝):

public class ExampleMechanismFormTemplate extends BaseModel implements ISysFormTemplateModel{ ?? }

public void setSysFormTemplateModels(List sysFormTemplateModels) { } this.sysFormTemplateModels = sysFormTemplateModels; // ********** 以下的代码为表单模板需要的代码,请直接拷贝 ********** private List sysFormTemplateModels; public List getSysFormTemplateModels() { return sysFormTemplateModels; } // ********** 以上的代码为流程表单需要的代码,请直接拷贝 ********** 5.2.2 Form类的部署

修改模板Form,在模板的Form中实现接口:

com.landray.kmss.sys.xform.interfaces.ISysFormTemplateForm 同时reset方法中添加初使化变量的代码。 样例代码(请直接拷贝): public class ExampleMechanismFormTemplateForm extends ExtendForm implements ISysFormTemplateForm{ ?? // ********** 以下的代码为表单模板需要的代码,请直接拷贝 ********** private AutoHashMap sysFormTemplateForms = new AutoHashMap( SysFormTemplateForm.class); public AutoHashMap getSysFormTemplateForms() { } return sysFormTemplateForms; } private String fdExtFilePath; public String getFdExtFilePath() { return fdExtFilePath; } public void setFdExtFilePath(String filePath) { } fdExtFilePath = filePath; // ********** 以上的代码为表单模板需要的代码,请直接拷贝 ********** public void reset(ActionMapping mapping, HttpServletRequest request) { } ?? // 请注意需要在此处加上流程模板的初始化动作 fdExtFilePath = null; sysFormTemplateForms.clear(); super.reset(mapping, request); 5.2.3 JSP页面的部署

1、 导航页面的部署

修改需要部署流程的业务模块的导航树页面(tree.jsp),添加流程模板的菜单项。 样例代码(请修改部分参数后拷贝): //表单模板设置 n2.AppendURLChild( ); 其中URL链接参数fdModelName的值为文档模板的Model类名称,fdKey为模板使用的Key值,必须与将流程模板跟分类模板进行绑定的部署模式中引入流程模板的参数fdKey保持一致,fdMainModelName是业务主文档的类名称。

\\ \

2、 edit页面的部署

修改模板的edit页面,在页面中采用标签嵌入表单的JSP页面。

样例代码(请修改部分参数后拷贝):

?? 其他可选参数: messageKey 用于提供覆盖默认标签页标题文字的消息Key。

useLabel 标识是否使用标签页,true为使用,false为不使用,默认为true。

3、 view页面的部署

修改模板的view页面,在页面中采用标签嵌入流程的JSP页面,添加lable,将流程模板的主页面套入lable中。

样例代码(请修改部分参数后拷贝):

?? 其他可选参数: messageKey 用于提供覆盖默认标签页标题文字的消息Key。

useLabel 标识是否使用标签页,true为使用,false为不使用,默认为true。

5.3 部署表单主文档

5.3.1 Model类的部署

修改业务模块的Model类,在该Model类中实现元数据接口: com.landray.kmss.sys.metadata.interfaces.IExtendDataModel 以及Hibernate的延时加载接口:

net.sf.cglib.transform.impl.InterceptFieldEnabled 样例代码(请直接拷贝):

public class ExampleMechanismMain extends BaseModel implements IextendDataModel, InterceptFieldEnabled { ?? } 以上字段都需要主文档存储,因此需要在hbm.xml文件中添加(请直接拷贝):

修改业务模块的Form类,在该Form中实现接口: com.landray.kmss.sys.metadata.interfaces.IExtendDataForm 此外,在Form中的reset方法中添加初使化变量的代码。 样例代码(请直接拷贝):

public class ExampleMechanismMainForm extends ExtendForm implements IExtendDataForm{ ?? // ********** 以下的代码为表单需要的代码,请直接拷贝 ********** private ExtendDataFormInfo extendDataFormInfo = new ExtendDataFormInfo(); public ExtendDataFormInfo getExtendDataFormInfo() { } return extendDataFormInfo; } // ********** 以上的代码为表单需要的代码,请直接拷贝 ********** public void reset(ActionMapping mapping, HttpServletRequest request) { } …… // 请注意需要在此处加上表单初始化动作 extendDataFormInfo = new ExtendDataFormInfo(); super.reset(mapping, request); 5.3.3 DAO类部署

在DAO实现类继承:

com.landray.kmss.sys.metadata.interfaces.ExtendDataDaoImp 样例代码(请直接拷贝):

public class ExampleMechanismMainDaoImp extends ExtendDataDaoImp implements } 修改spring.xml对DAO实现的声明(请修改部分参数后拷贝): 5.3.4 Service类部署

思路说明:

以前的EKP-J应用中,在创建主文档的时候,我们会在Action中通过createNewFrom的方法,初始化Form的数据。然而表单自定义的部署需要另外一种创建主文档的模式:先创建一个model,然后通过modelToForm的方法转成form。为此,系统提供了ExtendDataServiceImp基类给您集成,减少开发工作量。

修改步骤:

1、 在Service接口类继承:

com.landray.kmss.sys.metadata.interfaces.IExtendDataService 样例代码(请直接拷贝): public interface IExampleMechanismMainService extends IExtendDataService{ ?? } 2、 在Service实现类继承:

com.landray.kmss.sys.metadata.interfaces.ExtendDataServiceImp

覆盖initBizModelSetting,在该方法中实现创建文档时,model数据的初始化。

覆盖initCoreServiceFormSetting方法,实现相关机制数据的初始话。 样例代码(请根据实际业务逻辑编写):

public class ExampleMechanismMainServiceImp extends ExtendDataServiceImp implements IExampleMechanismMainService { } @Override protected void initCoreServiceFormSetting(IExtendForm form, } IBaseModel model, RequestContext requestContext) throws Exception { //调用dispatchCoreService,实现机制数据初始化 ExampleMechanismMain main = (ExampleMechanismMain) model; dispatchCoreService.initFormSetting(form, \ .getFdTemplate(), \?? @Override protected IBaseModel initBizModelSetting(RequestContext requestContext) } throws Exception { //获取模板信息 String templateId = requestContext.getParameter(\if (!StringUtil.isNotNull(templateId)) { return null; } ExampleMechanismTemplate template = (ExampleMechanismTemplate) getExampleMechanismTemplateService() .findByPrimaryKey(templateId); //初始化model数据 ExampleMechanismMain model = new ExampleMechanismMain (); //在这里写入model初始化的代码 ?? //给自定义表单的数据字典路径赋值 model.setExtendFilePath(XFormUtil.getFileName(template, \return model;

修改spring.xml中对Service实现的声明(请修改部分参数后拷贝): ?? 5.3.5 Action类的部署

修改业务模块的Action类的createNewForm方法,修改为调用Service的initFormSetting的方法初始化新创建的form。

样例代码(请修改部分参数后拷贝):

protected ActionForm createNewForm(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) } throws Exception { super.createNewForm(mapping, form, request, response); // 初始化数据 ((IExampleMechanismMainService) getServiceImp(request)).initFormSetting( (IExtendForm) form, new RequestContext(request)); return form; 5.3.6 JSP页面的部署

1、edit页面的部署

修改需要部署流程的edit页面,在页面中采用标签嵌入流程的JSP页面。 样例代码(请修改部分参数后拷贝):

?? 其他可选参数:

messageKey 用于提供覆盖默认标签页标题文字的消息Key。

useTab 标识是否使用标签页,true为使用,false为不使用,默认为true。

2、view页面的部署

修改需要部署流程的view页面,在页面中采用标签嵌入流程的JSP页面。 样例代码(请修改部分参数后拷贝): ?? 其他参数

messageKey 用于提供覆盖默认标签页标题文字的消息Key。

useTab 标识是否使用标签页,true为使用,false为不使用,默认为true。

5.4 部署表单存储映射

修改导航树页面。

样例代码(请修改部分参数后拷贝):

// 表单存储设置 n2.AppendURLChild( \ \

===[全文完]===

\

本文来源:https://www.bwwdw.com/article/kpvv.html

Top