这篇文章是请假工作流中遇到的坑和对这一阶段的工作的总结。
先对工作流进行简单的说明,工作流是OA中常用的专业名词,通常用在请假,报销等需要多级领导的审核,执行的规范化,java中常用的工作流组件有jbpm,activiti,在此项目中,我们选用activiti.activiti有23张表,但是重要的表有下面几张。
- act_ge_bytearray二进制表,用于存放bpmn和png图片,如果要查询文件,须知道部署Id(deploymentId)。
- act_re_deployment:部署表,要使用一个流程图时第一步就是部署流程图。该表的重要字段有:id_:pdid:pdkey:pdversion:随机数,name:名称,key:名称,version:版本号。如果名称不变,每次部署,版本号加1,如果名称改变,则版本号从1开始计算
- act_hi_act:流程图中正在执行或者已经执行完的节点。重要字段有:pro_def_id:流程定义的id(pdid),没有单独的流程实例表,如果没有分支,流程实例Id和执行Id相同,如果有分支,则不同,proc_inst_id:流程实例Id,execution_id:执行Id
- act_hi_procinst:历史的流程定义实例,正在执行的任务也在其中。如果end_time为null说明正在执行
-
act_ru_execution:代表正在执行的流程实例表
如果当期正在执行的流程实例结束以后,该行在这张表中就被删除掉了,所以该表也是一个临时表,重要字段有:proc_inst_id:piid流程实例id,在不存在并发的情况下流程实例id和流程执行id相同,act_id:当前正在执行的流程实例的正在执行的节点 - act_ru_task:正在执行的任务表,临时表,重要字段有:id_:主键,任务Id,execution_id:执行Id,根据该id查询出来的任务肯定是一个,proc_inst_id:piid:如果没有并发,则是一个,如果有并发,则是多个,name_:任务的名称,assignee:任务的执行人。
介绍完表以后,我来描述下一套工作流执行下来的几大步骤,
- 第一步:画图,画图是很重要的准备工作,我们需要根据业务需求画流程图。
- 第二步:部署流程图。
- 第三步:开启一个流程实例,例如请假,一个人提交了一个请假申请,即开启了一个请假流程实例。
- 第四步:执行任务,任务的接收人可以在图中定义,也可以在程序中执行,流程图进行到那一步,该接收人就要执行任务,根据执行的条件,程序自动选择下一步的路线。当一个流程走到最后一步,结束task的时候,一个流程就算是运行完毕。好的,下面我会对每一步进行图文说明。
画图
这是这次请假的流程图,先说明下此次请假老师给的需求,需求如下
-
四类人,教学人员,教学人员兼班主任,行政人员,教学人员兼班主任。
主要有两个条件,人员类型,请假天数。
图的几处细节:
- 定义每处节点时,该节点的id即该审核老师的英文,例:teachingLeader
-
节点的候选人定义为变量,为了好区分,也定义为该老师的英文,例:#{teachingLeaders}
-
该箭头条件:${staffType==1 || staffType == 3 || staffType == 4 }教职工类型为1或3或4
-
该箭头条件为:${!teachingDirectorPass},教学处主任老师未通过
-
该箭头条件为:${leaveTime <= 1 && staffType =3},天数<=1并且职工类型为3
图画好了,接下来就是写程序了。
准备工作
- 引入jar包,ant工程,所有我们先把jar包放入BODL-DIST工程中,新建了一个文件夹activiti5. 22,我们使用5.22版本的activiti
-
我们需要在SRV项目中的res根目录中添加activiti的配置文件activiti.cfg.xml(注:文件名不能写错,位置也不能错,默认位置,默认文件名), processEngineConfiguration最重要,与数据库连接,
private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
生成流程引擎,如果数据库中没有23张,第一次启动时,会自动生成23张表
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 配置工作流的bean -->
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcDriver" value="org.postgresql.Driver"></property>
<property name="jdbcUrl" value="jdbc:postgresql://192.168.0.115:5432/boas_oa"></property>
<property name="jdbcUsername" value="postgres"></property>
<property name="jdbcPassword" value="root123"></property>
<!-- 创建表的策略 -->
<property name="databaseSchemaUpdate" value="true"></property>
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration"/>
</bean>
<!-- 7大接口 -->
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
<bean id="formService" factory-bean="processEngine" factory-method="getFormService"/>
<bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService"/>
</beans>
-
生成leaveFlow表,表结构如下
代码部分
- 准备工作做好后,就该写代码了,结构如下
- 部署,方法如下
@Action(value = "deploy", results = { @Result(name = "deploy", type = "json", params = {"root", "jsonResult" }) })
public String deploy() throws FileNotFoundException {
//部署流程定义
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获得上传文件的输入流程
InputStream in = this.getClass().getClassLoader().getResourceAsStream("deployments/leave.zip");
ZipInputStream zipInputStream = new ZipInputStream(in);
//获取仓库服务,从类路径下部署
Deployment deploy = processEngine.getRepositoryService().createDeployment().name("请假流程").addZipInputStream(zipInputStream).deploy();
System.out.println(deploy.getName());
return "deploy";
}
-
提交申请,页面如图,代码略
后台代码:
@Action(value = "start", results = { @Result(name = "leaveSubmit", type = "json", params = {"root", "jsonResult" }) })
public String leaveSubmit() {
SysUser sysUser = (SysUser) getSession().get(EBacsConstant.SESSION_LOGIN_USER.getTextValue());
String startTime = getParameter("startTime");
String endTime = getParameter("endTime");
String reason = getParameter("reason");
String leaveType = getParameter("leaveType");
LeaveFlowInfo leave = new LeaveFlowInfo();
try {
//开始时间
leave.setStartTime(sdf.parse(startTime));
//结束时间
leave.setEndTime(sdf.parse(endTime));
//申请时间
leave.setApplyTime(new Date(System.currentTimeMillis()));
} catch (ParseException e) {
log.error("日期转换失败:" + e.getMessage());
}
//请假类型
leave.setLeaveType(leaveType);
//请假原因
leave.setReason(reason);
leave.setUserUuid(sysUser.getUuid());
leave.setUserName(sysUser.getRealName());
boolean flag = false;
try {
StringBuilder message = new StringBuilder();
Map<String, Object> variables = new HashMap<String, Object>();
flag = setVariables(message, endTime, startTime,variables);
if(flag) {
workflowService.startWorkflow(leave, variables);
jsonResult = QueryResult.create().success(flag).msgDesc("启动请假流程成功");
} else {
jsonResult = QueryResult.create().success(flag).msgDesc(message.toString());
log.error("启动请假流程失败,失败原因:" + message.toString());
}
} catch (Exception e) {
jsonResult = QueryResult.create().success(flag).msgDesc("启动请假流程失败");
log.error("启动请假流程失败,失败原因:" + e.getMessage());
} finally {
}
return "leaveSubmit"; }
在这一步,要做两件事
- 1,添加一条请假记录
- 2,启动一个请假流程,在启动请假流程之前,需要将变量设置进去,请假时间,职工类型,每个审核人员的uuid,具体如下:(注:教研组长和处室主任的uuid通过调用接口获得,在权限系统中设置每个部门的领导,该领导即教研组长或处室主任。其他审核人员都是单个人,可以从staff表中的officiate中获得,这些变量都是必须设置的,如果有一项未设置,则请假流程无法启动)
private boolean setVariables(StringBuilder message,String endTime,String startTime,Map<String, Object> variables) throws Exception{
//设置staffType,请假天数
//1:教学人员,2:行政人员,3:教学人员兼班主任,4:教学兼行政人员
Map<String, Object> paramObj = new HashMap<String, Object>();
paramObj.put("idNo", sysUser.getUserName());
StaffVO staffVO = getOutInterfaceCommonService().queryStaffInfoByIdNo(paramObj);
String staffType = staffVO.getStaffType();
if(StringUtils.isBlank(staffType) || Integer.parseInt(staffType) == 0 || Integer.parseInt(staffType) == -99 ) {
message.append("教职工类型未设置");
return false;
}
variables.put("staffType", staffType);
//设置请假天数
long end = sdf.parse(endTime).getTime();
long start = sdf.parse(startTime).getTime();
float leaveTime = (float)(end - start)/ (1000 * 60 * 60 * 24);
variables.put("leaveTime", leaveTime);
//清空
paramObj.clear();
paramObj.put("userUuid", sysUser.getUuid());
List<DepartmentInfo> dptList = getOutInterfaceCommonService().queryDepartmentCommander(paramObj);
//设置教研组长和处室主任
if(dptList != null && dptList.size() !=0) {
if(dptList.size() == 1) {
variables.put("teachingLeaders", dptList.get(0).getDptCommanderUuid()); //教研组长
variables.put("officeLeader", dptList.get(0).getDptCommanderUuid()); //处室主任
}else if(dptList.size() >= 2) {
for(int i = 0;i < dptList.size(); i ++) {
if(dptList.get(i).getDptName().contains("组")) {
variables.put("teachingLeaders", dptList.get(0).getDptCommanderUuid()); //教研组长
dptList.remove(i);
}
}
variables.put("officeLeader", dptList.get(0).getDptCommanderUuid()); //处室主任
}else {
message.append(" 该职工未被分配处室或教研组长,或教研组长,处室主任未指定");
return false;
}
}else {
message.append(" 该职工未分配处室或教研组长,或教研组长,处室主任未指定");
return false;
}
//教学处主任
String teachingDirector = getStaffBuOfficiate("2");
if(StringUtils.isNotBlank(teachingDirector)) {
variables.put("teachingDirector", teachingDirector);
}else {
message.append(" 教学处主任未指定");
return false;
}
//学生处主任
String studentDirector = getStaffBuOfficiate("37");
if(StringUtils.isNotBlank(studentDirector)) {
variables.put("studentDirector", studentDirector);
}else {
message.append(" 学生处主任未指定");
return false;
}
//教学副校长
String teachingPresident = getStaffBuOfficiate("38");
if(StringUtils.isNotBlank(teachingPresident)) {
variables.put("teachingPresident", teachingPresident);
}else {
message.append(" 教学副校长未指定");
return false;
}
//德育副校长
String educationPresident = getStaffBuOfficiate("39");
if(StringUtils.isNotBlank(educationPresident)) {
variables.put("educationPresident", educationPresident);
}else {
message.append(" 德育副校长未指定");
return false;
}
//行政副校长
String executivePrecident = getStaffBuOfficiate("40");
if(StringUtils.isNotBlank(executivePrecident)) {
variables.put("executivePrecident", executivePrecident);
}else {
message.append(" 行政副校长未指定");
return false;
}
//行政副校长
String president = getStaffBuOfficiate("3");
if(StringUtils.isNotBlank(president)) {
variables.put("president", president);
}else {
message.append(" 校长未指定");
return false;
}
variables.put("applyUser", sysUser.getUuid());
return true;
}
启动流程的代码如下
public ProcessInstance startWorkflow(LeaveFlowInfo entity, Map<String, Object> variables) throws Exception{
getLeaveFlowDao().insert(entity);
logger.debug("save entity: {}", entity);
int businessKey = entity.getId();
ProcessInstance processInstance = null;
try {
// 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中 processEngine.getIdentityService().setAuthenticatedUserId(entity.getUserUuid());
processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("leave", String.valueOf(businessKey), variables);
String processInstanceId = processInstance.getId();
entity.setProcessInstanceId(processInstanceId);
//更新leaveInfo,添加processInstanceId
getLeaveFlowDao().update(entity);
logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"leave", businessKey, processInstanceId, variables});
} finally {
processEngine.getIdentityService().setAuthenticatedUserId(null);
}
return processInstance;
}
请假审核
- 流程实例启动以后,根据设置的条件,可以得到下一个审核人员,下面是任务列表后台代码
@Action(value = "taskListPage", results = {@Result(name = "taskListPage", location = "/WEB-INF/pages/office$automatic/leaveflow/task_list.jsp")})
public String taskList() {
String userId = sysUser.getUuid();
List<LeaveFlowInfo> leaveFlowInfos = new ArrayList<>();
List<Task> taskList = processEngine.getTaskService().createTaskQuery().taskCandidateOrAssigned(userId).list();
Map<String, Object> typeCode = new HashMap<String, Object>();
try {
if(taskList != null && taskList.size() != 0) {
for (Task task : taskList) {
String processInstanceId = task.getProcessInstanceId();
ProcessInstance processInstance = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
if (processInstance == null) {
continue;
}
String businessKey = processInstance.getBusinessKey();
if (businessKey == null) {
continue;
}
LeaveFlowInfo leaveInfo = workflowService.getLeaveById(Integer.parseInt(businessKey));
leaveInfo.setTask(task);
leaveInfo.setProcessInstance(processInstance);
leaveInfo.setProcessDefinition(workflowService.getProcessDefinition(processInstance.getProcessDefinitionId()));
leaveFlowInfos.add(leaveInfo);
}
}
Map<String, Object> paramObj = new HashMap<String, Object>();
paramObj.put("typeCode", "qjlb");
//查询所有请假类别
typeCode = getOutInterfaceCommonService().queryByDictTypeCode(paramObj);
} catch (Exception e) {
log.error("任务查询失败,失败原因:" + e.getMessage());
}
getRequest().setAttribute("result", leaveFlowInfos);
getRequest().setAttribute("typeCode", typeCode);
return "taskListPage";
}
- 前台代码
<div class="search">
<div>
<label>申请人姓名:</label>
<input type="text" id="leaveApplyName" placeholder="申请人姓名" style="width:180px;height:30px;"/>
<label>审核状态:</label>
<select id="leaveCheckStatus">
<option value="-99" >全部</option>
<c:forEach items="${qjshzt.result }" var="typeCodeMap">
<c:if test="${typeCodeMap.dictKey == 0}">
<option selected value="${typeCodeMap.dictKey }" >${ typeCodeMap.dictName }</option>
</c:if>
<c:if test="${typeCodeMap.dictKey != 0}">
<option value="${typeCodeMap.dictKey }" >${ typeCodeMap.dictName }</option>
</c:if>
</c:forEach>
</select>
</div>
<input id="selectBtn" class="btn bg_blue" type="button" value="查询" />
</div>
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="table_1 mar_T10">
<thead>
<th class="fixed_width_4_id">序号</th>
<th class="same_percent_width_of_2_6_column">假种</th>
<th class="same_percent_width_of_2_6_column">申请人</th>
<th class="same_percent_width_of_2_6_column">申请时间</th>
<th class="same_percent_width_of_2_6_column">开始时间</th>
<th class="same_percent_width_of_2_6_column">结束时间</th>
<th class="same_percent_width_of_2_6_column">当前节点</th>
<th class="same_percent_width_of_2_6_column">任务创建时间</th>
<th class="same_percent_width_of_2_6_column">流程状态</th>
<th class="same_percent_width_of_2_6_column">操作</th>
</thead>
<tbody id="queryLeaveInfoList">
<c:forEach items="${result }" var="leave" varStatus="status" >
<c:set var="task" value="${leave.task }" />
<c:set var="pi" value="${leave.processInstance }" />
<tr id="${leave.id }" tid="${task.id }">
<td>${status.count }</td>
<c:forEach items="${typeCode.result}" var="leaveTypeMap">
<c:if test="${leaveTypeMap.dictKey == leave.leaveType}">
<td>${leaveTypeMap.dictName }</td>
</c:if>
</c:forEach>
<%-- <td>${leave.leaveType }</td> --%>
<td>${leave.userName }</td>
<td><fmt:formatDate value="${leave.applyTime }" pattern="yyyy-MM-dd HH:mm" /> </td>
<td><fmt:formatDate value="${leave.startTime }" pattern="yyyy-MM-dd HH:mm" /></td>
<td><fmt:formatDate value="${leave.endTime }" pattern="yyyy-MM-dd HH:mm" /></td>
<td>
<a class="trace" href='#' pid="${pi.id }" eid="${task.executionId}" pdid="${pi.processDefinitionId}" title="点击查看流程图"><font color="red">${task.name }</font></a>
</td>
<%--<td><a target="_blank" href='${ctx }/workflow/resource/process-instance?pid=${pi.id }&type=xml'>${task.name }</a></td> --%>
<td><fmt:formatDate value="${task.createTime }" pattern="yyyy-MM-dd HH:mm" /></td>
<td>${pi.suspended ? "已挂起" : "正常" };<b title='流程版本号'>V: ${leave.processDefinition.version }</b></td>
<td>
<c:if test="${empty task.assignee }">
<a class="claim" href="${ctx }/oa/leave/task/claim/${task.id}">签收</a>
</c:if>
<c:if test="${not empty task.assignee }">
<%-- 此处用tkey记录当前节点的名称 --%>
<a class="handle" tkey='${task.taskDefinitionKey }' tname='${task.name }' href="#">办理</a>
</c:if>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<!-- 下面是每个节点的模板,用来定义每个节点显示的内容 -->
<!-- 使用DIV包裹,每个DIV的ID以节点名称命名,如果不同的流程版本需要使用同一个可以自己扩展(例如:在DIV添加属性,标记支持的版本) -->
<!-- 教研组组长审批 -->
<div id="teachingLeader" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
</div>
<!-- 教学处主任审批 -->
<div id="teachingDirector" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
</div>
<!-- 处室主任 -->
<div id="officeLeader" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
</div>
<!-- 学生处主任 -->
<div id="studentDirector" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
</div>
<!-- 教学副校长 -->
<div id="teachingPresident" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
</div>
<!-- 德育副校长 -->
<div id="educationPresident" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
</div>
<!-- 行政副校长 -->
<div id="executivePrecident" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
</div>
<!-- 校长 -->
<div id="president" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
</div>
<!-- 申请调整 -->
<div class="mar_LR10">
<div id="modifyApply" style="display: none">
<div class="info" style="display: none"></div>
<div id="radio">
<input type="radio" id="radio1" name="reApply" value="true" /><label for="radio1">调整申请</label>
<input type="radio" id="radio2" name="reApply" checked="checked" value="false" /><label for="radio2">取消申请</label>
</div>
<hr />
<table id="modifyApplyContent" style="display: none" class="s_add">
<input type="hidden" id="leaveId" name="leaveId" />
<tr>
<td>请假类型:</td>
<td>
<select id="leaveType" name="leaveType">
<c:forEach items="${typeCode.result }" var="leaveTypeMap">
<option value="${leaveTypeMap.dictKey }" >${leaveTypeMap.dictName }</option>
</c:forEach>
</select>
</td>
</tr>
<tr>
<td>开始时间:</td>
<td><input type="text" id="startTime" name="startTime" /></td>
</tr>
<tr>
<td>结束时间:</td>
<td><input type="text" id="endTime" name="endTime" /></td>
</tr>
<tr>
<td>请假原因:</td>
<td>
<textarea id="reason" name="reason" style="width: 250px;height: 50px"></textarea>
</td>
</tr>
</table>
</div>
</div>
<!-- 销假 -->
<div id="reportBack" style="display: none">
<!-- table用来显示信息,方便办理任务 -->
<%@include file="view-form.jsp" %>
<hr/>
<table>
<tr>
<td>实际请假开始时间:</td>
<td>
<input id="realityStartTime" />
</td>
</tr>
<tr>
<td>实际请假开始时间:</td>
<td>
<input id="realityEndTime" />
</td>
</tr>
</table>
</div>
代码分为几部分
:1,对获取的task数据遍历,2每个节点定义一个div,在点击办理的时候可以打开对应的div,其中申请调整的div和其他的div不同。
请假办理
- 前台代码
function handle() {
// 当前节点的英文名称
var tkey = $(this).attr('tkey');
// 当前节点的中文名称
var tname = $(this).attr('tname');
// 请假记录ID
var rowId = $(this).parents('tr').attr('id');
// 任务ID
var taskId = $(this).parents('tr').attr('tid');
// 使用对应的模板
$('#' + tkey).data({
taskId: taskId
}).dialog({
title: '流程办理[' + tname + ']',
modal: true,
width: handleOpts[tkey].width,
height: handleOpts[tkey].height,
open: function() {
handleOpts[tkey].open.call(this, rowId, taskId);
},
buttons: handleOpts[tkey].btns
});
}
//定义多个节点的处理页面,下面仅是教研组长,其他类似
var handleOpts = {
//教研组长
teachingLeader: {
width: 300,
height: 300,
open: function(id) {
// 打开对话框的时候读取请假内容
loadDetail.call(this, id);
},
btns: [{
text: '同意',
click: function() {
var taskId = $(this).data('taskId');
// 设置流程变量
complete(taskId, [{
key: 'teachingLeadersPass',
value: true,
type: 'B'
}]);
}
}, {
text: '驳回',
click: function() {
var taskId = $(this).data('taskId');
$('<div/>', {
title: '填写驳回理由',
html: "<textarea id='teachingLeaderBackReason' style='width: 250px; height: 60px;'></textarea>"
}).dialog({
modal: true,
buttons: [{
text: '驳回',
click: function() {
var teachingLeaderBackReason = $('#teachingLeaderBackReason').val();
if (teachingLeaderBackReason == '') {
alert('请输入驳回理由!');
return;
}
// 设置流程变量
complete(taskId, [{
key: 'teachingLeadersPass',
value: false,
type: 'B'
}, {
key: 'teachingLeaderBackReason',
value: teachingLeaderBackReason,
type: 'S'
}]);
}
}, {
text: '取消',
click: function() {
$(this).dialog('close');
$('#teachingLeader').dialog('close');
}
}]
});
}
}, {
text: '取消',
click: function() {
$(this).dialog('close');
}
}]
}
- 可以看到设置的变量有’teachingLeaderBackReason’,’teachingLeadersPass’等
- 后台代码
@Action(value = "complete", results = { @Result(name = "complete", type = "json", params = {"root", "jsonResult" }) })
public String complete() {
String taskId = getParameter("taskId");
String keys = getParameter("keys");
String values = getParameter("values");
String types = getParameter("types");
try {
Variable variables = new Variable(keys, values, types);
Map<String, Object> variableMap = variables.getVariableMap();
if(variableMap.get("leaveId") != null) {
workflowService.update(variableMap);
}
processEngine.getTaskService().complete(taskId, variableMap);
jsonResult = QueryResult.create().success(true).msgDesc("办理成功");
} catch (Exception e) {
log.error("办理任务失败,失败原因:" + e.getMessage());
jsonResult = QueryResult.create().success(false).msgDesc("办理失败");
}
return "complete";
}
查询运行中的请假流程
@Action(value = "runningList", results = { @Result(name = "runningList", location = "/WEB-INF/pages/office$automatic/leaveflow/running_list.jsp") })
public String runningList() {
Map<String, Object> typeCode = new HashMap<String, Object>();
try {
List<LeaveFlowInfo> list = workflowService.findRunningProcessInstaces();
getRequest().setAttribute("leaveList", list);
Map<String, Object> paramObj = new HashMap<String, Object>();
paramObj.put("typeCode", "qjlb");
//查询所有请假类别
typeCode = getOutInterfaceCommonService().queryByDictTypeCode(paramObj);
getRequest().setAttribute("typeCode", typeCode);
} catch (Exception e) {
log.error("查询运行中的流程实例失败:" + e.getMessage());
}
return "runningList";
}
#### 查询已结束的请假流程
@Action(value = "finishedList", results = { @Result(name = "finishedList", location = "/WEB-INF/pages/office$automatic/leaveflow/finished_list.jsp") })
public String finishedList() {
Map<String, Object> typeCode = new HashMap<String, Object>();
try {
List<LeaveFlowInfo> list = workflowService.findFinishedProcessInstaces();
getRequest().setAttribute("leaveList", list);
Map<String, Object> paramObj = new HashMap<String, Object>();
paramObj.put("typeCode", "qjlb");
//查询所有请假类别
typeCode = getOutInterfaceCommonService().queryByDictTypeCode(paramObj);
getRequest().setAttribute("typeCode", typeCode);
} catch (Exception e) {
log.error("查询已结束的流程实例失败:" + e.getMessage());
}
return "finishedList";
}
···
注:此文借鉴咖啡兔的工作流项目,感谢!
版权声明:本文为fireaco原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。