关于 JOffice 的业务表单与流程的整合问题
关于 JOffice 的业务表单与流程的整合问题
目前JOffice中提供三种流程表单整合方式:
一、在线制作表单,并且能完成自动的表单对应的物理表的生成
二、跟系统现在的业务表单整合,采用EXT表单模板
三、跟系统现有的业务或其他系统现有的表单整合,采用URL表单模板
三种方式都可以,但是需要根据情况来选择,第一种适用于全新的表单及流程开发,第二种适用于已经在系统中开发了业务的管理功能,但又希望可以在系统中进行流程的审批管理(可以用EXT模板进行简单及复杂化的管理功能(适用于开发人员)),第三种则适用于旧的B/S系统的业务表单跟现在的流程进行整合处理。
以下我们介绍一下最后一种:流程的开发一般都会面临一个比较大的问题就是业务表单,不同的系统的业务表单还是比较复杂,我们不得不面对以前旧系统遗留下来的业务表单。
旧系统的遗留的表单一般分为两种,一种是C/S结构的表单,一种是B/C结构的表单,对于前者,整合需要采用WebService来进行或其他对外的接口等,若为后者,目前我们提供另一种更方便的整合,以下我们先来讨论这种方式。
如上图所示,外围为流程的跳转执行,IFrame里的表单则为原系统中的业务表单,其执行还是原来的执行方式,不过加了可以调用外窗口的流程执行跳转,所以可以在里面的执行跳转那里加上一些执行跳转参数,以方便其完成业务表单的数据保存后直接调用外围窗口来执行流程的跳转。
那么,业务表单与流程如何实现关联?当在后台我们完成对流程的任务设置加载的URL后,前台启动流程的时候,我们需要把里面业务表单的数据需要跟流程作一个关联,在JBPM中,一般我们采用表单的变量来进行,但对于业务表单需要保存的业务变量,我们允许开发人员在自己的B/S表单上自己加上调用。
如我们的角色表单若需要走流程的话,可以加上一保存完成后,把保存的角色实体对应的id放在外面的表单中中,方便外围的流程进行跳转及加载表单的处理。
如我们在访问系统的url:http://localhost:8080/joffice21/pages/demo/roleForm.jsp
出现以下的表单:该表单能完成保存的操作,保存完成后,我们仅需要把其值实体的id 存至外围的流程中去即可。于是我们在以下的表单中,改造了类似的代码:
<%@page import="com.htsoft.oa.service.system.AppRoleService"%> <%@page import="com.htsoft.core.util.AppUtil"%> <%@page import="com.htsoft.oa.model.system.AppRole"%> <%@page import="org.apache.commons.lang.StringUtils"%> <%@page contentType="text/html; charset=UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <link rel="stylesheet" type="text/css" href="<%=request.getContextPath()%>/css/admin.css"/> <title>角色表单示例</title> <% AppRoleService appRoleService=(AppRoleService)AppUtil.getBean("appRoleService"); //用于提交时进行获取表单参数 AppRole appRole=new AppRole(); String roleId=request.getParameter("roleId"); //若原来已经存在,则加载 if(StringUtils.isNotEmpty(roleId)){ appRole=appRoleService.get(new Long(roleId)); } if("POST".equals(request.getMethod())){//保存提交值 String roleName=request.getParameter("roleName"); String roleDesc=request.getParameter("roleDesc"); String status=request.getParameter("status"); appRole.setRoleName(roleName); appRole.setRoleDesc(roleDesc); appRole.setStatus(new Short(status)); appRole.setIsDefaultIn((short)0); appRoleService.save(appRole); } request.setAttribute("appRole",appRole); String defId=request.getParameter("defId"); String taskId=request.getParameter("taskId"); %> <script type="text/javascript"> window.onload=function(){ //保存后,把业务实体的id保存至外窗口流程实例中 <% if("POST".equals(request.getMethod())){ if(defId!=null){ %> parent.document.getElementById('defParams<%=defId%>').value="roleId:<%=appRole.getRoleId()%>"; <% }else{ %> parent.document.getElementById('taskParams<%=taskId%>').value="roleId:<%=appRole.getRoleId()%>"; <% } } %> }; </script> </head> <body> <form action="roleForm.jsp" method="post"> <table class="table-info" cellpadding="0" cellspacing="1" width="98%"> <tr> <th align="center" colspan="2">角色详细信息</th> </tr> <tr> <th>角色名字</th> <td> <input type="hidden" name="defId" value="<%=defId%>"/> <input type="hidden" name="taskId" value="<%=taskId%>"/> <input type="hidden" name="roleId" value="${appRole.roleId}"/> <input name="roleName" type="text" width="400" value="${appRole.roleName}"/> </td> </tr> <tr> <th>角色状态</th> <td> <select name="status"> <option value="1" <c:if test="${appRole.status==1}">selected</c:if>>激活</option> <option value="0" <c:if test="${appRole.status==0}">selected</c:if>>禁用</option> </select> </td> </tr> <tr> <th> 描述 </th> <td> <textarea name="roleDesc" rows="5" cols="50">${appRole.roleDesc}</textarea> </td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="保 存 "/> </td> </tr> </table> </form> </body> </html>
<%@page import="com.htsoft.oa.service.system.AppRoleService"%> <%@page import="com.htsoft.core.util.AppUtil"%> <%@page import="com.htsoft.oa.model.system.AppRole"%> <%@page import="org.apache.commons.lang.StringUtils"%> <%@page contentType="text/html; charset=UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <link rel="stylesheet" type="text/css" href="<%=request.getContextPath()%>/css/admin.css"/> <title>角色表单示例</title> <% AppRoleService appRoleService=(AppRoleService)AppUtil.getBean("appRoleService"); //用于提交时进行获取表单参数 AppRole appRole=new AppRole(); String roleId=request.getParameter("roleId"); //若原来已经存在,则加载 if(StringUtils.isNotEmpty(roleId)){ appRole=appRoleService.get(new Long(roleId)); } if("POST".equals(request.getMethod())){//保存提交值 String roleName=request.getParameter("roleName"); String roleDesc=request.getParameter("roleDesc"); String status=request.getParameter("status"); appRole.setRoleName(roleName); appRole.setRoleDesc(roleDesc); appRole.setStatus(new Short(status)); appRole.setIsDefaultIn((short)0); appRoleService.save(appRole); } request.setAttribute("appRole",appRole); String defId=request.getParameter("defId"); String taskId=request.getParameter("taskId"); %> <script type="text/javascript"> window.onload=function(){ //保存后,把业务实体的id保存至外窗口流程实例中 <% if("POST".equals(request.getMethod())){ if(defId!=null){ %> parent.document.getElementById('defParams<%=defId%>').value="roleId:<%=appRole.getRoleId()%>"; <% }else{ %> parent.document.getElementById('taskParams<%=taskId%>').value="roleId:<%=appRole.getRoleId()%>"; <% } } %> }; </script> </head> <body> <form action="roleForm.jsp" method="post"> <table class="table-info" cellpadding="0" cellspacing="1" width="98%"> <tr> <th align="center" colspan="2">角色详细信息</th> </tr> <tr> <th>角色名字</th> <td> <input type="hidden" name="defId" value="<%=defId%>"/> <input type="hidden" name="taskId" value="<%=taskId%>"/> <input type="hidden" name="roleId" value="${appRole.roleId}"/> <input name="roleName" type="text" width="400" value="${appRole.roleName}"/> </td> </tr> <tr> <th>角色状态</th> <td> <select name="status"> <option value="1" <c:if test="${appRole.status==1}">selected</c:if>>激活</option> <option value="0" <c:if test="${appRole.status==0}">selected</c:if>>禁用</option> </select> </td> </tr> <tr> <th> 描述 </th> <td> <textarea name="roleDesc" rows="5" cols="50">${appRole.roleDesc}</textarea> </td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="保 存 "/> </td> </tr> </table> </form> </body> </html>
以上代码部分只有一功能是跟外围流程有关的,则把业务参数传至流程实例中去。
<% if("POST".equals(request.getMethod())){ if(defId!=null){ %> parent.document.getElementById('defParams<%=defId%>').value="roleId:<%=appRole.getRoleId()%>"; <% }else{ %> parent.document.getElementById('taskParams<%=taskId%>').value="roleId:<%=appRole.getRoleId()%>"; <% } } %>
<% if("POST".equals(request.getMethod())){ if(defId!=null){ %> parent.document.getElementById('defParams<%=defId%>').value="roleId:<%=appRole.getRoleId()%>"; <% }else{ %> parent.document.getElementById('taskParams<%=taskId%>').value="roleId:<%=appRole.getRoleId()%>"; <% } } %>
后台的流程设置我们则设计如下:
其表单采用了URL模块,所以需要设置其对应表单的URL,URL可以采用相对路径,如/pages/demo/roleForm.jsp
启动节点可以不用设置后续的参数,但在后续的任务节点,由于需要加载对应的流程表单业务数据,所以需要把业务表单的数据加载出来,因此其URL配置则改成
/pages/demo/roleForm.jsp?roleId=${roleId}
${roleId}则表示参数roleId为流程的参数。后续的流程任务则通过该url去加载其对应的角色出来给当前用户来进行审批。因此启动时候,其界面如下所示:
当保存完成后,我们再点上面的“提交并启动流程”按钮则可。
这种方式是先保存业务里的数据再启动流程。当流程跳至下一步时,其则类似如下:
这样就可以实现整个流程与业务表单的整合,若业务表单有其他数据需要传至流程进行计算,则也是采用类似传参数方式则可。
在外围的流程加载URL表单中,其代码则如下所示:
<%@page import="java.util.Iterator"%> <%@page import="java.util.Map"%> <%@page import="org.apache.commons.lang.StringUtils"%> <%@page import="com.htsoft.oa.model.flow.FormTemplate"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% Long taskId=(Long)request.getAttribute("taskId"); Long defId=(Long)request.getAttribute("defId"); FormTemplate formTemplate=(FormTemplate)request.getAttribute("formTemplate"); Map formVars=(Map)request.getAttribute("formVars"); String url=formTemplate.getFormUrl(); if(StringUtils.isNotEmpty(url)){ if(!url.startsWith("http")){//采用相对路径,则表示引用为本系统中的表单 url=request.getScheme() + "://" + request.getHeader("host") + request.getContextPath()+url; } } if(url.indexOf("?")==-1){ url+="?"; }else{ url+="&"; } if(defId!=null){ url+="defId="+defId; %> <input type="hidden" name="defParams" id="defParams<%=defId%>" /> <% }else{ url+="taskId="+taskId; %> <input type="hidden" name="taskParams" id="taskParams<%=taskId%>" /> <% } if(formVars!=null){ Iterator<String> it= formVars.keySet().iterator(); while(it.hasNext()){ String key=it.next(); Object value=(Object)formVars.get(key); System.out.println("key:" + key + " VALUE:"+ value); if(value!=null){ url=url.replace("${"+key+"}", value.toString()); } } } %> <iframe frameborder="0" width="100%" height="100%" src="<%=url%>" onload="this.height=this.contentWindow.document.body.scrollHeight"></iframe>
<%@page import="java.util.Iterator"%> <%@page import="java.util.Map"%> <%@page import="org.apache.commons.lang.StringUtils"%> <%@page import="com.htsoft.oa.model.flow.FormTemplate"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% Long taskId=(Long)request.getAttribute("taskId"); Long defId=(Long)request.getAttribute("defId"); FormTemplate formTemplate=(FormTemplate)request.getAttribute("formTemplate"); Map formVars=(Map)request.getAttribute("formVars"); String url=formTemplate.getFormUrl(); if(StringUtils.isNotEmpty(url)){ if(!url.startsWith("http")){//采用相对路径,则表示引用为本系统中的表单 url=request.getScheme() + "://" + request.getHeader("host") + request.getContextPath()+url; } } if(url.indexOf("?")==-1){ url+="?"; }else{ url+="&"; } if(defId!=null){ url+="defId="+defId; %> <input type="hidden" name="defParams" id="defParams<%=defId%>" /> <% }else{ url+="taskId="+taskId; %> <input type="hidden" name="taskParams" id="taskParams<%=taskId%>" /> <% } if(formVars!=null){ Iterator<String> it= formVars.keySet().iterator(); while(it.hasNext()){ String key=it.next(); Object value=(Object)formVars.get(key); System.out.println("key:" + key + " VALUE:"+ value); if(value!=null){ url=url.replace("${"+key+"}", value.toString()); } } } %> <iframe frameborder="0" width="100%" height="100%" src="<%=url%>" onload="this.height=this.contentWindow.document.body.scrollHeight"></iframe>