flowable集成

This commit is contained in:
459816669@qq.com 2020-12-13 19:39:55 +08:00
parent d7a1af6d84
commit 8ff2486ac1
24 changed files with 677 additions and 143 deletions

View File

@ -1,17 +1,22 @@
package com.snow.web.controller.flowable;
import com.alibaba.fastjson.JSON;
import com.snow.common.core.controller.BaseController;
import com.snow.common.core.domain.AjaxResult;
import com.snow.common.core.page.PageModel;
import com.snow.common.core.page.TableDataInfo;
import com.snow.common.exception.BusinessException;
import com.snow.common.utils.StringUtils;
import com.snow.flowable.common.constants.FlowConstants;
import com.snow.flowable.domain.*;
import com.snow.flowable.domain.leave.SysOaLeaveForm;
import com.snow.flowable.service.AppFormService;
import com.snow.flowable.service.impl.FlowableServiceImpl;
import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.SysOaLeave;
import com.snow.system.domain.SysUser;
import com.snow.system.service.ISysOaLeaveService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.Task;
@ -33,6 +38,7 @@ import java.util.List;
**/
@Controller
@RequestMapping("/flow")
@Slf4j
public class FlowController extends BaseController {
private String prefix = "flow";
@ -40,6 +46,8 @@ public class FlowController extends BaseController {
private ISysOaLeaveService sysOaLeaveService;
@Autowired
private FlowableServiceImpl flowableService;
@Autowired
private AppFormService appFormService;
/**
@ -97,9 +105,31 @@ public class FlowController extends BaseController {
SysUser sysUser = ShiroUtils.getSysUser();
processInstanceDTO.setStartedUserId(String.valueOf(sysUser.getUserId()));
PageModel<ProcessInstanceVO> historicProcessInstance = flowableService.getHistoricProcessInstance(processInstanceDTO);
log.info(JSON.toJSONString(historicProcessInstance.getPagedRecords()));
return getFlowDataTable(historicProcessInstance);
}
/**
* 跳转我发起的流程详情
*/
@GetMapping("/myStartProcessDetail")
@RequiresPermissions("system:flow:myStartProcessDetail")
public String myStartProcessDetail(String processInstanceId,ModelMap modelMap)
{
//已审批的
HistoricTaskInstanceDTO historicTaskInstanceDTO=new HistoricTaskInstanceDTO();
historicTaskInstanceDTO.setProcessInstanceId(processInstanceId);
//historicTaskInstanceDTO.setProcessStatus(1);
List<HistoricTaskInstanceVO> historicTaskInstanceList= flowableService.getHistoricTaskInstanceNoPage(historicTaskInstanceDTO);
AppForm appFrom = appFormService.getAppFromBySerializable(processInstanceId);
modelMap.put("historicTaskInstanceList",historicTaskInstanceList);
modelMap.put("processInstanceId",processInstanceId);
modelMap.put("busVarUrl",appFrom.getBusVarUrl());
return prefix +"/myStartProcessDetail";
}
@RequiresPermissions("flow:process:getMyTakePartInProcess")
@GetMapping("/toMyTakePartInProcess")
public String getMyTakePartInProcess()

View File

@ -125,12 +125,10 @@ public class FlowModelerController extends BaseController
*/
@RequiresPermissions("modeler:flow:getProcessDiagram")
@GetMapping("/getProcessDiagram")
@ResponseBody
public void getProcessDiagram(String processInstanceId,HttpServletResponse response)
public void getProcessDiagram(String processInstanceId,HttpServletResponse response,ModelMap modelMap)
{
flowableService.getFlowableProcessImage(processInstanceId,response);
flowableService.getFlowableProcessImage(processInstanceId, response);
}
/**
* 删除发布
*/

View File

@ -10,13 +10,12 @@ import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.snow.common.constant.SequenceContants;
import com.snow.common.enums.ProcessStatus;
import com.snow.common.utils.StringUtils;
import com.snow.flowable.common.constants.FlowConstants;
import com.snow.flowable.common.enums.FlowDefEnum;
import com.snow.flowable.domain.*;
import com.snow.flowable.domain.leave.LeaveFinishTaskDTO;
import com.snow.flowable.domain.leave.SysOaLeaveForm;
import com.snow.flowable.service.AppFormService;
import com.snow.flowable.service.impl.FlowableServiceImpl;
import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.SysUser;
@ -29,11 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import com.snow.common.annotation.Log;
import com.snow.common.enums.BusinessType;
import com.snow.system.domain.SysOaLeave;
@ -63,6 +58,9 @@ public class SysOaLeaveController extends BaseController
@Autowired
private ISysSequenceService sequenceService;
@Autowired
private AppFormService appFormService;
@RequiresPermissions("system:leave:view")
@GetMapping()
@ -174,8 +172,9 @@ public class SysOaLeaveController extends BaseController
BeanUtils.copyProperties(sysOaLeave,sysOaLeaveForm);
sysOaLeaveForm.setBusinessKey(newSysOaLeave.getLeaveNo());
sysOaLeaveForm.setStartUserId(String.valueOf(sysUser.getUserId()));
sysOaLeaveForm.setBusVarJson(com.alibaba.fastjson.JSON.toJSONString(newSysOaLeave));
sysOaLeaveForm.setBusVarJson(com.alibaba.fastjson.JSON.toJSONString(sysOaLeaveForm));
sysOaLeaveForm.setClassPackName(SysOaLeaveForm.class.getCanonicalName());
sysOaLeaveForm.setBusVarUrl("/system/leave/leaveDetail");
ProcessInstance processInstance = flowableService.startProcessInstanceByAppForm(sysOaLeaveForm);
//提交
CompleteTaskDTO completeTaskDTO=new CompleteTaskDTO();
@ -207,6 +206,16 @@ public class SysOaLeaveController extends BaseController
return prefix + "/detail";
}
/**
* 请假单详情
*/
@GetMapping("/leaveDetail")
public String leaveDetail(@RequestParam("processInstanceId") String processInstanceId, ModelMap mmap)
{
SysOaLeaveForm appFrom = appFormService.getAppFromBySerializable(processInstanceId);
mmap.put("sysOaLeave", appFrom);
return prefix + "/leaveDetail";
}
/**
* 删除请假单
*/

View File

@ -0,0 +1,76 @@
(function ($) {
/**
* Register ajax transports for blob send/recieve and array buffer send/receive via XMLHttpRequest Level 2
* within the comfortable framework of the jquery ajax request, with full support for promises.
*
* Notice the +* in the dataType string? The + indicates we want this transport to be prepended to the list
* of potential transports (so it gets first dibs if the request passes the conditions within to provide the
* ajax transport, preventing the standard transport from hogging the request), and the * indicates that
* potentially any request with any dataType might want to use the transports provided herein.
*
* Remember to specify 'processData:false' in the ajax options when attempting to send a blob or arraybuffer -
* otherwise jquery will try (and fail) to convert the blob or buffer into a query string.
*
* This revision now includes sending headers, resolves the stack overflow in abort(), and sets the status text
* into the response if the request is unsuccessful.
*/
$.ajaxTransport("+*", function (options, originalOptions, jqXHR) {
// Test for the conditions that mean we can/want to send/receive blobs or arraybuffers - we need XMLHttpRequest
// level 2 (so feature-detect against window.FormData), feature detect against window.Blob or window.ArrayBuffer,
// and then check to see if the dataType is blob/arraybuffer or the data itself is a Blob/ArrayBuffer
if (window.FormData && ((options.dataType && (options.dataType == 'blob' || options.dataType == 'arraybuffer')) ||
(options.data && ((window.Blob && options.data instanceof Blob) ||
(window.ArrayBuffer && options.data instanceof ArrayBuffer)))
)) {
var xhr;
return {
/**
* Return a transport capable of sending and/or receiving blobs - in this case, we instantiate
* a new XMLHttpRequest and use it to actually perform the request, and funnel the result back
* into the jquery complete callback (such as the success function, done blocks, etc.)
*
* @param headers
* @param completeCallback
*/
send: function (headers, completeCallback) {
var url = options.url || window.location.href,
type = options.type || 'GET',
dataType = options.dataType || 'text',
data = options.data || null,
async = options.async || true;
xhr = new XMLHttpRequest();
xhr.addEventListener('load', function () {
var res = {},
success = xhr.status >= 200 && xhr.status < 300 || xhr.status === 304;
if (success) {
res[dataType] = xhr.response;
} else {
res.text = xhr.statusText;
}
completeCallback(xhr.status, xhr.statusText, res, xhr.getAllResponseHeaders());
});
xhr.open(type, url, async);
xhr.responseType = dataType;
for (var key in headers) {
if (headers.hasOwnProperty(key)) {
xhr.setRequestHeader(key, headers[key]);
}
}
xhr.send(data);
},
abort: function () {
if (xhr) {
xhr.abort();
}
}
};
}
});
})(jQuery);

View File

@ -41,6 +41,8 @@
<script th:inline="javascript">
var removeFlag = [[${@permission.hasPermi('system:flow:remove')}]];
var detailFlag = [[${@permission.hasPermi('system:flow:myStartProcessDetail')}]];
var processInstanceStatusDatas = [[${@dict.getType('process_instance_status')}]];
var prefix = ctx + "modeler";
var prefixFlow = ctx + "flow";
@ -55,7 +57,6 @@
showColumns: false, // 是否显示隐藏某列下拉框
showToggle: false,
showSearch: false, // 是否显示检索信息
// rowStyle:rowStyle,//通过自定义函数设置行样式
columns: [
{
title: '序号',
@ -70,8 +71,11 @@
{
field: 'businessKey',
title: '单号'
title: '单号',
formatter: function(value, row, index) {
var fromDetailUrl= row.fromDetailUrl;
return '<a class="success" href="' + fromDetailUrl+ '" >'+value+'</a> ';
}
},
{
field: 'startUserName',
@ -102,7 +106,7 @@
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="getProcessDiagram(\'' + row.id + '\')"><i class="fa fa-eye"></i>流程图</a>');
actions.push('<a class="btn btn-info btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="getProcessDiagram(\'' + row.id + '\')"><i class="fa fa-eye"></i>详情</a>');
return actions.join('');
}
}]
@ -111,19 +115,10 @@
});
function getProcessDiagram(processInstanceId) {
var preViewUrl=prefixFlow+'/myStartProcessDetail?processInstanceId='+processInstanceId;
$.modal.openTab("详情", preViewUrl);
}
var preViewUrl=prefix+'/getProcessDiagram?processInstanceId='+processInstanceId;
$.modal.openTab("流程图", preViewUrl);
}
function rowStyle(row, index) {
var classes = [ 'success', 'info', 'warning', 'danger'];
if (index % 2 === 0 && index / 2 < classes.length) {
return {
classes: classes[index / 2]
};
}
return {};
}
</script>
</body>
</html>

View File

@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
<head>
<th:block th:include="include :: header('我发起的流程详情')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-sequence-edit" >
<input name="processInstanceId" id="processInstanceId" th:value="${processInstanceId}" type="hidden" >
<input name="busVarUrl" id="busVarUrl" th:value="${busVarUrl}" type="hidden" >
<div class="ibox float-e-margins">
<h4 class="form-header h4">流程图</h4>
<div class="vertical-timeline-block" >
<img class="imgcode" width="85%"/>
</div>
</div>
<div class="ibox float-e-margins form-horizontal">
<h4 class="form-header h4">审批节点</h4>
<div id="ibox-content">
<div id="vertical-timeline" class="vertical-container light-timeline light-dark">
<div class="vertical-timeline-block" th:each="task,iterStat : ${historicTaskInstanceList}">
<div class="vertical-timeline-icon navy-bg">
<i class="fa fa-tasks"></i>
</div>
<div class="vertical-timeline-content ">
<h2 th:text="${task.taskName }"></h2>
<br class="form-group">
<div class="row">
<div class="col-md-4">
<label >审批结果:</label>
<label th:switch="${task.isPass}">
<span class="btn-outline btn-danger" th:case="'false'">驳回</span>
<span class="btn-outline btn-success" th:case="'true'">通过</span>
<span class="btn-outline btn-info" th:case=" ''">待审核</span>
</label>
</div>
<div class="col-md-4" th:if="${task.assigneeName} != null">
<label >审批人:</label>
<span th:text="${task.assigneeName}"></span>
</div>
<div class="col-md-4" th:if="${task.handleTaskTime} != null">
<label>任务历时:</label>
<label>
<span th:text="${task.handleTaskTime}"></span>
</label>
</div>
</div>
</br>
<div class="row" >
<div class="col-md-12">
<label>可审批人:</label>
<span th:each="userName:${task.handleUserList}">
<label th:if="${userName} ne ''">&nbsp;&nbsp
<span th:text="${userName}"></span>
</label>
</span>
</div>
</div>
</br>
<div class="row">
<div class="col-md-12">
<span class="vertical-date">
<label>任务时间:</label> <small th:text="${#dates.format(task.startTime, 'yyyy-MM-dd HH:mm:ss')}"></small>
<label>~</label> <small th:text="${#dates.format(task.completeTime, 'yyyy-MM-dd HH:mm:ss')}"></small>
</span>
</div>
</div>
</br>
<div class="row">
<div class="col-md-12">
<div th:each="comment:${task.commentList}">
<label>审批意见:</label>
<label th:if="${comment.fullMessage} ne ''">
<span th:text="${comment.fullMessage}"></span>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="ibox float-e-margins">
<h4 class="form-header h4">业务数据</h4>
<p>
<div class="row">
<div class="col-sm-offset-1 col-sm-10">
<a class="btn btn-info btn-large" href="javascript:void(0)" onclick="getProcessDiagram()"><i class="fa fa-eye"></i>获取业务单</a>
</div>
</div>
</p>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
$(function () {
var processInstanceId= $("#processInstanceId").val();
var url ="/modeler/getProcessDiagram?processInstanceId="+processInstanceId;
$(".imgcode").attr("src", url);
});
function getProcessDiagram() {
var processInstanceId= $("#processInstanceId").val();
var busVarUrl= $("#busVarUrl").val();
$.modal.open('业务单', busVarUrl+"?processInstanceId="+processInstanceId);
}
</script>
</body>
</html>

View File

@ -41,6 +41,10 @@
<script th:inline="javascript"> var ctx = [[@{/}]]; </script>
</div>
<!--图片显示JS-->
<div th:fragment="jquery-ajax-blob-arraybuffer">
<script th:href="@{/ruoyi/js/jquery-ajax-blob-arraybuffer.js}" ></script>
</div>
<!-- ztree树插件 -->
<div th:fragment="ztree-css">
<link th:href="@{/ajax/libs/jquery-ztree/3.5/css/metro/zTreeStyle.css}" rel="stylesheet"/>

View File

@ -66,7 +66,7 @@
<div class="vertical-timeline-content">
<h2 th:text="${task.name }"></h2>
<h2 th:text="${task.taskName }"></h2>
<p th:if="${task.isPass} ne ''">
<label >审批结果:</label>
<span style="color: red" th:if="${#strings.trim(task.isPass)} eq 'false'">驳回</span>
@ -74,15 +74,15 @@
</p>
<p><label>操作人:</label> <span th:text="${task.assigneeName}"></span></p>
<p><label>任务历时:</label> <span th:text="${task.spendTime}"></span></p>
<p><label>任务历时:</label> <span th:text="${task.handleTaskTime}"></span></p>
<div th:each="comment:${task.commentList}">
<p th:if="${comment.fullMessage} ne ''">
<label>审批意见:</label> <span th:text="${comment.fullMessage}"></span>
</p>
</div>
<span class="vertical-date">
<label>时间:</label> <small th:text="${#dates.format(task.createTime, 'yyyy-MM-dd HH:mm:ss')}"></small>
<label>~</label> <small th:text="${#dates.format(task.endTime, 'yyyy-MM-dd HH:mm:ss')}"></small>
<label>时间:</label> <small th:text="${#dates.format(task.startTime, 'yyyy-MM-dd HH:mm:ss')}"></small>
<label>~</label> <small th:text="${#dates.format(task.completeTime, 'yyyy-MM-dd HH:mm:ss')}"></small>
</span>
</div>

View File

@ -0,0 +1,80 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('人事审批')" />
<th:block th:include="include :: jsonview-css" />
<th:block th:include="include :: bootstrap-fileinput-css"/>
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m-t" id="signupForm">
<input class="form-control" type="hidden" name="businessKey" th:value="${sysOaLeave.leaveNo}"/>
<h4 class="form-header h4">请假信息</h4>
<div class="form-group">
<label class="col-sm-3 control-label">单号:</label>
<div class="form-control-static" th:text="${sysOaLeave.leaveNo}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">标题:</label>
<div class="form-control-static" th:text="${sysOaLeave.name}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">请假理由:</label>
<div class="form-control-static"><pre id="reason"></pre></div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">开始时间:</label>
<div class="form-control-static" th:text="${#dates.format(sysOaLeave.startTime, 'yyyy-MM-dd hh:mm:ss')}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">结束时间:</label>
<div class="form-control-static" th:text="${#dates.format(sysOaLeave.endTime, 'yyyy-MM-dd HH:mm:ss')}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">申请人:</label>
<div class="form-control-static" th:text="${sysOaLeave.applyPerson}">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: jsonview-js" />
<th:block th:include="include :: bootstrap-fileinput-js"/>
<script th:inline="javascript">
$(function() {
var reason = [[${sysOaLeave.reason}]];
console.log(reason);
if ($.common.isNotEmpty(reason) && reason.length < 2000) {
$("#reason").text(reason);
} else {
$("#reason").text(reason);
}
});
$(".file-upload").each(function (i) {
var val = $("input[name='" + this.id + "']").val();
$(this).fileinput({
'uploadUrl': '/common/upload',
initialPreviewAsData: true,
initialPreview: [val],
maxFileCount: 1,
autoReplace: true
}).on('fileuploaded', function (event, data, previewId, index) {
$("input[name='" + event.currentTarget.id + "']").val(data.response.url)
}).on('fileremoved', function (event, id, index) {
$("input[name='" + event.currentTarget.id + "']").val('')
})
$(this).fileinput('_initFileActions');
});
</script>
</body>
</html>

View File

@ -1,20 +1,26 @@
package com.snow.flowable;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.google.common.collect.Maps;
import com.snow.JunitTestApplication;
import com.snow.flowable.domain.DeploymentQueryDTO;
import com.snow.flowable.domain.StartProcessDTO;
import com.snow.flowable.domain.TaskVO;
import com.snow.flowable.service.FlowableService;
import com.snow.system.domain.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.api.IdentityLinkInfo;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author qimingjin
@ -26,6 +32,8 @@ import java.util.Map;
public class FlowableServiceTests extends JunitTestApplication {
@Autowired
private FlowableService flowableService;
@Autowired
private TaskService taskService;
@Test
public void startProcessInstanceByKey(){
@ -52,4 +60,20 @@ public class FlowableServiceTests extends JunitTestApplication {
List<TaskVO> dynamicFlowNodeInfo = flowableService.getDynamicFlowNodeInfo("38505061-2d6b-11eb-b0ec-040e3c9c6b2f");
log.info(JSON.toJSONString(dynamicFlowNodeInfo));
}
@Test
public void getTaskList(){
TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId("1337010679969882112");
List<Task> list = taskQuery.list();
list.forEach(task -> {
List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(task.getId());
flowableService.getIdentityLinksForTask(task.getId(),"");
log.info(JSON.toJSONString(identityLinksForTask));
});
log.info(JSON.toJSONString(list));
}
}

View File

@ -34,6 +34,15 @@ public class FlowConstants {
* 业务参数常量
*/
public static final String BUS_VAR="bus_var_json";
/**
* 表单数据
*/
public static final String APP_FORM="appForm";
/**
* 跳转数据详情页
*/
public static final String BUS_VAR_URL="busVarUrl";
/**
* 当前类的包名
*/

View File

@ -15,6 +15,7 @@ import java.io.Serializable;
@Data
public abstract class AppForm implements Serializable {
private static final long serialVersionUID = -4544643731565791031L;
/**
* 流程发起人
*/
@ -28,6 +29,7 @@ public abstract class AppForm implements Serializable {
@NotBlank(message = "业务参数不能为空")
private String businessKey;
/**
* 业务数据json
*/
@ -38,6 +40,10 @@ public abstract class AppForm implements Serializable {
@NotBlank(message = "当前类的包名称不能为空")
private String classPackName;
/**
* 业务参数URL
*/
private String busVarUrl;
/**
* 流程申请单需实现此方法,返回申请单对应的流程定义.

View File

@ -21,56 +21,30 @@ import java.util.stream.Collectors;
* @date 2020/11/26 16:41
*/
@Data
public class HistoricTaskInstanceVO implements Serializable {
/**
* 历史任务id
*/
private String id;
public class HistoricTaskInstanceVO extends TaskVO implements Serializable {
/**
* 流程执行ID
*/
private String executionId;
/**
* 流程实例id
*/
private String processInstanceId;
/**
*流程名称
*/
private String processName;
/**
*业务参数
*/
private String businessKey;
/**
* 任务定义ID
*/
private String taskDefinitionId;
/**
* 创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 完成时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**
* 用时
*/
private String spendTime;
/**
* 任务名称
*/
private String name;
/**
* 用户ID
*/
@ -82,13 +56,10 @@ public class HistoricTaskInstanceVO implements Serializable {
*/
private String assigneeName;
/**
* 任务描述
* 是否通过驳回
*/
private String description;
private String category;
private String isPass;
/**
@ -102,12 +73,11 @@ public class HistoricTaskInstanceVO implements Serializable {
private List<Attachment> attachmentList;
/**
* 任务变量
* 任务节点变量
*/
private Map<String, Object> taskLocalVariables;
private String formKey;
/**
* 流程变量
@ -115,30 +85,23 @@ public class HistoricTaskInstanceVO implements Serializable {
private Map<String, Object> processVariables;
/* private String scopeId;
private String subScopeId;
private String scopeType;
private String scopeDefinitionId;
private String propagatedStageInstanceId;*/
private String deleteReason;
private String localizedName;
private String parentTaskId;
private String localizedDescription;
private String owner;
private String taskDefinitionKey;
private int priority;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date dueDate;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date claimTime;
@ -148,7 +111,11 @@ public class HistoricTaskInstanceVO implements Serializable {
HistoricTaskInstanceVO historicTaskInstanceVO=new HistoricTaskInstanceVO();
BeanUtils.copyProperties(t,historicTaskInstanceVO);
historicTaskInstanceVO.setTaskLocalVariables(t.getTaskLocalVariables());
historicTaskInstanceVO.setTaskId(t.getId());
historicTaskInstanceVO.setTaskName(t.getName());
//老的createTime底层换成了time getCreateTime
historicTaskInstanceVO.setStartTime(t.getTime());
historicTaskInstanceVO.setCompleteTime(t.getEndTime());
historicTaskInstanceVO.setProcessVariables(t.getProcessVariables());
return historicTaskInstanceVO;
}).collect(Collectors.toList());

View File

@ -1,6 +1,8 @@
package com.snow.flowable.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.snow.common.utils.StringUtils;
import com.snow.common.utils.bean.BeanUtils;
import com.snow.common.utils.spring.SpringUtils;
@ -35,83 +37,92 @@ public class ProcessInstanceVO implements Serializable {
/**
* 流程定义ID
*/
public String processDefinitionId;
private String processDefinitionId;
/**
* 流程定义名称
*/
public String processDefinitionName;
private String processDefinitionName;
/**
* 流程定义key
*/
public String processDefinitionKey;
private String processDefinitionKey;
/**
* 流程版本号
*/
public Integer processDefinitionVersion;
private Integer processDefinitionVersion;
/**
* 发布ID
*/
public String deploymentId;
private String deploymentId;
/**
* 开始时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
public Date startTime;
private Date startTime;
/**
* 结束时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
public Date endTime;
private Date endTime;
public String endActivityId;
private String endActivityId;
/**
* 流程发起人ID
*/
public String startUserId;
private String startUserId;
/**
* 流程发起人
*/
public String startUserName;
private String startUserName;
public String startActivityId;
private String startActivityId;
/**
* 删除理由
*/
public String deleteReason;
private String deleteReason;
/**
* 流程用时
*/
public String processSpendTime;
private String processSpendTime;
/**
* 父流程ID
*/
public String superProcessInstanceId;
private String superProcessInstanceId;
public String tenantId;
private String tenantId;
public String description;
private String description;
public String callbackId;
public String callbackType;
private String callbackId;
private String callbackType;
/**
* 表单详情URL
*/
private String fromDetailUrl;
/**
* 业务参数
*/
public String businessKey;
private String businessKey;
/**
* 是否结束(0--进行中1--结束)
*/
public Integer isFinished;
private Integer isFinished;
Map<String, Object> processVariables;
/**
* 业务流程参数
*/
@JsonIgnoreProperties
private AppForm appForm;
public String processDefinitionCategory;
private Map<String, Object> processVariables;
private String processDefinitionCategory;
public static List<ProcessInstanceVO> warpList(List<HistoricProcessInstance> historicProcessInstanceList){
return historicProcessInstanceList.stream().map(t->{

View File

@ -1,6 +1,7 @@
package com.snow.flowable.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.snow.system.domain.SysUser;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -9,6 +10,7 @@ import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* @author qimingjin
@ -27,37 +29,79 @@ import java.util.List;
@NoArgsConstructor
public class TaskVO implements Serializable {
/**
* 任务ID
*/
private String taskId;
/**
* 任务名称
*/
private String taskName;
/**
* 流程定义名称
*/
private String processDefinitionName;
/**
* 任务描述
*/
private String description;
/**
* 委托人
*/
private String owner;
/**
* 父任务ID
*/
private String parentTaskId;
/**
* 租户ID
*/
private String tenantId;
/**
* 任务处理人
*/
private String Assignee;
/**
* 任务创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createDate;
/**
* 分类
*/
private String category;
/**
* fromKey
*/
private String formKey;
/**
* 流程实例id
*/
private String processInstanceId;
/**
* 流程发起人id
*/
private String startUserId;
/**
* 发起人名称
*/
private String startUserName;
/**
* 业务主键
*/
private String businessKey;
/**
* 任务发起时间
@ -90,6 +134,6 @@ public class TaskVO implements Serializable {
/**
* 任务待处理人
*/
private List<String> handleNameList;
private List<String> handleUserList;
}

View File

@ -27,8 +27,6 @@ public abstract class AbstractExecutionListener<T extends AppForm> implements Ex
private ThreadLocal<T> appFormLocal = new ThreadLocal<>();
private ThreadLocal<DelegateExecution> delegateExecutionLocal=new ThreadLocal();
@Autowired
private FlowableService flowableService;
@Autowired
private SysUserServiceImpl sysUserService;
@ -129,11 +127,9 @@ public abstract class AbstractExecutionListener<T extends AppForm> implements Ex
* @return
*/
public T getAppForms(){
String busVar = getVariable(FlowConstants.BUS_VAR);
String classPackName = getVariable(FlowConstants.CLASS_PACK_NAME);
T t = appFormLocal.get();
if(t==null){
appFormLocal.set(appFormService.getAppFrom(busVar,classPackName));
appFormLocal.set(appFormService.getAppFrom(getProcessInstanceId()));
t=appFormLocal.get();
}
return t;

View File

@ -11,4 +11,14 @@ import com.snow.flowable.domain.AppForm;
public interface AppFormService {
<A extends AppForm> A getAppFrom(String classInfoJson,String className);
<A extends AppForm> A getAppFrom(String classInfoJson,Class<A> className);
/**
* 从流程中获取表单数据
* @param processInstanceId
* @param <A>
* @return
*/
<A extends AppForm> A getAppFromBySerializable(String processInstanceId);
<A extends AppForm> A getAppFrom(String processInstanceId);
}

View File

@ -3,6 +3,7 @@ package com.snow.flowable.service;
import com.snow.common.core.page.PageModel;
import com.snow.flowable.domain.*;
import com.snow.system.domain.ActDeModel;
import com.snow.system.domain.SysUser;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Model;
import org.flowable.engine.runtime.ProcessInstance;
@ -12,6 +13,7 @@ import org.flowable.task.api.history.HistoricTaskInstance;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;
/**
* @author qimingjin
@ -97,6 +99,20 @@ public interface FlowableService {
*/
PageModel<TaskVO> findTasksByUserId(String userId,TaskBaseDTO taskBaseDTO);
/**
* 根据任务ID获取关联待办人活着待办组的人
* @param taskId
* @return
*/
Set<SysUser> getIdentityLinksForTask(String taskId,String type);
/**
* 获取历史的
* @param taskId
* @return
*/
Set<SysUser> getHistoricIdentityLinksForTask(String taskId);
/**
* 完成任务
* @param completeTaskDTO
@ -108,6 +124,7 @@ public interface FlowableService {
* @param httpServletResponse
* @param processId
*/
@Deprecated
void getProcessDiagram(HttpServletResponse httpServletResponse, String processId);
/**

View File

@ -2,12 +2,19 @@ package com.snow.flowable.service.impl;
import com.alibaba.fastjson.JSON;
import com.snow.flowable.common.constants.FlowConstants;
import com.snow.flowable.domain.AppForm;
import com.snow.flowable.service.AppFormService;
import com.snow.flowable.service.FlowableService;
import com.snow.system.domain.SysOaLeave;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author qimingjin
* @Title:
@ -18,6 +25,10 @@ import org.springframework.stereotype.Service;
@Slf4j
public class AppFormServiceImpl implements AppFormService {
@Autowired
private FlowableService flowableService;
@Override
public <A extends AppForm> A getAppFrom(String classInfoJson,String className) {
return JSON.parseObject(classInfoJson, getFormClass(className));
@ -28,6 +39,34 @@ public class AppFormServiceImpl implements AppFormService {
return JSON.parseObject(classInfoJson, className);
}
@Override
public <A extends AppForm> A getAppFromBySerializable(String processInstanceId) {
HistoricProcessInstance historicProcessInstance=flowableService.getHistoricProcessInstanceById(processInstanceId);
return getVariable(historicProcessInstance, FlowConstants.APP_FORM);
}
@Override
public <A extends AppForm> A getAppFrom(String processInstanceId) {
HistoricProcessInstance historicProcessInstance=flowableService.getHistoricProcessInstanceById(processInstanceId);
String classInfoJson = getVariable(historicProcessInstance, FlowConstants.BUS_VAR);
String classPackName = getVariable(historicProcessInstance, FlowConstants.CLASS_PACK_NAME);
return getAppFrom(classInfoJson, classPackName);
}
/**
* 获取流程变量
* @param key
* @param <V>
* @return
*/
protected <V> V getVariable(HistoricProcessInstance historicProcessInstance,String key){
return (V)historicProcessInstance.getProcessVariables().get(key);
}
private <A> Class<A> getFormClass(String className) {
try {
return (Class<A>) Class.forName(className);
@ -35,10 +74,4 @@ public class AppFormServiceImpl implements AppFormService {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws Exception{
Class<SysOaLeave> sysOaLeaveClass = SysOaLeave.class;
Class<?> sysOaLeaveForm = Class.forName("com.snow.flowable.domain.leave.SysOaLeaveForm");
System.out.println(sysOaLeaveForm);
}
}

View File

@ -39,6 +39,8 @@ import org.flowable.engine.repository.*;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Attachment;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
@ -55,6 +57,7 @@ import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Size;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@ -292,6 +295,7 @@ public class FlowableServiceImpl implements FlowableService {
Map<String, Object> paramMap = BeanUtil.beanToMap(appForm);
paramMap.remove("busVarJson");
identityService.setAuthenticatedUserId(startUserId);
paramMap.put(FlowConstants.APP_FORM,appForm);
paramMap.put(FlowConstants.BUS_VAR,appForm.getBusVarJson());
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(appForm.getFlowDef().getCode(),appForm.getBusinessKey(),paramMap);
@ -371,8 +375,62 @@ public class FlowableServiceImpl implements FlowableService {
return pageModel;
}
@Override
public Set<SysUser> getIdentityLinksForTask(String taskId,String type){
Set<SysUser> userList=new HashSet<>();
List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(taskId);
if(!CollectionUtils.isEmpty(identityLinksForTask)){
identityLinksForTask.stream().filter(identityLink ->
!StringUtils.isEmpty(identityLink.getGroupId())
&&identityLink.getType().equals(type)
)
.forEach(identityLink -> {
String groupId = identityLink.getGroupId();
List<SysUser> sysUsers = sysUserMapper.selectUserListByRoleId(groupId);
userList.addAll(sysUsers);
});
identityLinksForTask.stream().filter(identityLink ->
!StringUtils.isEmpty(identityLink.getUserId())
&&identityLink.getType().equals(type)
)
.forEach(identityLink -> {
String userId = identityLink.getUserId();
SysUser sysUsers = sysUserMapper.selectUserById(Long.parseLong(userId));
userList.add(sysUsers);
});
}
return userList;
}
/**
* starterUSER_ID与PROC_INST_ID_记录流程的发起者
* candidateUSER_ID_ GROUP_ID_ 其中一个必须有值TASK_ID_有值记录当前任务的指派人与指派组
* participant USER_ID与PROC_INST_ID_有值记录流程任务的参与者
* @param taskId
* @return
*/
@Override
public Set<SysUser> getHistoricIdentityLinksForTask(String taskId){
Set<SysUser> userList=new HashSet<>();
List<HistoricIdentityLink> historicIdentityLinksForTask = historyService.getHistoricIdentityLinksForTask(taskId);
if(!CollectionUtils.isEmpty(historicIdentityLinksForTask)){
historicIdentityLinksForTask.stream().filter(identityLink -> !StringUtils.isEmpty(identityLink.getGroupId())
&&identityLink.getType().equals("candidate"))
.forEach(identityLink -> {
String groupId = identityLink.getGroupId();
List<SysUser> sysUsers = sysUserMapper.selectUserListByRoleId(groupId);
userList.addAll(sysUsers);
});
historicIdentityLinksForTask.stream().filter(identityLink -> !StringUtils.isEmpty(identityLink.getUserId())
&&identityLink.getType().equals("candidate"))
.forEach(identityLink -> {
String userId = identityLink.getUserId();
SysUser sysUsers = sysUserMapper.selectUserById(Long.parseLong(userId));
userList.add(sysUsers);
});
}
return userList;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void completeTask(CompleteTaskDTO completeTaskDTO) {
@ -496,13 +554,19 @@ public class FlowableServiceImpl implements FlowableService {
public HistoricProcessInstance getHistoricProcessInstanceById(String id){
return historyService.createHistoricProcessInstanceQuery()
.processInstanceId(id)
//标识查询的时候返回流程变量参数不然取不到
.includeProcessVariables()
.singleResult();
}
@Override
public Task getTaskProcessInstanceById(String id){
return taskService.createTaskQuery()
.processInstanceId(id)
.includeTaskLocalVariables()
.includeIdentityLinks()
.includeProcessVariables()
.singleResult();
}
@ -537,7 +601,7 @@ public class FlowableServiceImpl implements FlowableService {
historicTaskInstanceQuery.finished();
}
}
historicTaskInstanceQuery.includeTaskLocalVariables().includeProcessVariables();
historicTaskInstanceQuery.includeTaskLocalVariables().includeProcessVariables().includeIdentityLinks();
List<HistoricTaskInstance> list = historicTaskInstanceQuery.orderByTaskCreateTime().asc().list();
List<HistoricTaskInstanceVO> historicTaskInstanceVOS = HistoricTaskInstanceVO.warpList(list);
setHistoricTaskInstanceVos(historicTaskInstanceVOS);
@ -547,28 +611,33 @@ public class FlowableServiceImpl implements FlowableService {
private void setHistoricTaskInstanceVos(List<HistoricTaskInstanceVO> list){
list.parallelStream().forEach(t -> {
//保存待办人
Set<SysUser> identityLinksForTask = getHistoricIdentityLinksForTask(t.getTaskId());
Optional.ofNullable(identityLinksForTask).ifPresent(m->{
List<String> userNameList = identityLinksForTask.stream().map(SysUser::getUserName).collect(Collectors.toList());
t.setHandleUserList(userNameList);
});
if (!StringUtils.isEmpty(t.getAssignee())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(t.getAssignee()));
t .setAssigneeName(sysUser.getUserName());
}else {
//下个节点
}
Optional.ofNullable( t.getTaskLocalVariables()).ifPresent(u->{
Object isPass =Optional.ofNullable(u.get(FlowConstants.IS_PASS)).orElse("");
//处理审核条件
t.setIsPass(String.valueOf(isPass));
});
List<Comment> comment = taskService.getTaskComments(t.getId(), FlowConstants.OPINION);
List<Comment> comment = taskService.getTaskComments(t.getTaskId(), FlowConstants.OPINION);
List<Attachment> taskAttachments = taskService.getTaskAttachments(t.getId());
List<Attachment> taskAttachments = taskService.getTaskAttachments(t.getTaskId());
t.setCommentList(comment);
t.setAttachmentList(taskAttachments);
//计算任务历时
if(!StringUtils.isEmpty(t.getEndTime())){
String spendTime = DateUtil.formatBetween(DateUtil.between(t.getCreateTime(), t.getEndTime(), DateUnit.SECOND));
t.setSpendTime(spendTime);
if(!StringUtils.isEmpty(t.getCompleteTime())){
String spendTime = DateUtil.formatBetween(DateUtil.between(t.getStartTime(), t.getCompleteTime(), DateUnit.SECOND));
t.setHandleTaskTime(spendTime);
}
HistoricProcessInstance historicProcessInstance = getHistoricProcessInstanceById(t.getProcessInstanceId());
t.setProcessName(historicProcessInstance.getProcessDefinitionName());
@ -594,16 +663,16 @@ public class FlowableServiceImpl implements FlowableService {
if(!CollectionUtils.isEmpty(historicTaskInstance)){
hisTaskVOList = historicTaskInstance.stream().map(t -> {
TaskVO taskVO = new TaskVO();
taskVO.setTaskName(t.getName());
taskVO.setTaskName(t.getTaskName());
taskVO.setProcessInstanceId(t.getProcessInstanceId());
taskVO.setStartUserId(processInstance.getStartUserId());
taskVO.setStartUserName(getUserNameById(processInstance.getStartUserId()));
taskVO.setTaskDefinitionKey(t.getTaskDefinitionKey());
if (!StringUtils.isEmpty(t.getCreateTime())) {
taskVO.setCreateDate(t.getCreateTime());
if (!StringUtils.isEmpty(t.getStartTime())) {
taskVO.setCreateDate(t.getStartTime());
}
if (!StringUtils.isEmpty(t.getEndTime())) {
taskVO.setCompleteTime(t.getEndTime());
if (!StringUtils.isEmpty(t.getCompleteTime())) {
taskVO.setCompleteTime(t.getCompleteTime());
}
if (!StringUtils.isEmpty(t.getAssignee())) {
@ -618,7 +687,7 @@ public class FlowableServiceImpl implements FlowableService {
List<TaskVO> futureTask = getFutureTask(processInstance);
for(int i=0;i<hisTaskVOList.size();i++){
for(int j=0;j<futureTask.size();j++){
if(hisTaskVOList.get(i).getTaskName().equals(futureTask.get(j).getTaskName())&&CollectionUtils.isEmpty(futureTask.get(j).getHandleNameList())){
if(hisTaskVOList.get(i).getTaskName().equals(futureTask.get(j).getTaskName())&&CollectionUtils.isEmpty(futureTask.get(j).getHandleUserList())){
futureTask.remove(j);
}
}
@ -677,8 +746,12 @@ public class FlowableServiceImpl implements FlowableService {
processInstanceVOS.parallelStream().forEach(t->{
Map<String, Object> processVariables = t.getProcessVariables();
t.setProcessVariables(processVariables);
String url= Optional.ofNullable(String.valueOf(processVariables.get(FlowConstants.BUS_VAR_URL))).orElse("");
if(!StringUtils.isEmpty(url)){
t.setFromDetailUrl(url+"?processInstanceId="+t.getId());
}
AppForm appForm=(AppForm)processVariables.get(FlowConstants.APP_FORM);
t.setAppForm(appForm);
//计算流程用时
if(StringUtils.isEmpty(t.getEndTime())){
String spendTime = DateUtil.formatBetween(t.getStartTime(), new Date(), BetweenFormater.Level.SECOND);
@ -722,8 +795,8 @@ public class FlowableServiceImpl implements FlowableService {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(t.getAssignee()));
historicTaskInstanceVO.setAssignee(sysUser.getUserName());
}
String spendTime = DateUtil.formatBetween(DateUtil.between(t.getCreateTime(), t.getEndTime(), DateUnit.MS));
historicTaskInstanceVO.setSpendTime(spendTime);
String spendTime = DateUtil.formatBetween(DateUtil.between(t.getCreateTime(), t.getEndTime(), DateUnit.SECOND));
historicTaskInstanceVO.setHandleTaskTime(spendTime);
HistoricProcessInstance historicProcessInstance = getHistoricProcessInstanceById(t.getProcessInstanceId());
historicTaskInstanceVO.setProcessName(historicProcessInstance.getProcessDefinitionName());
historicTaskInstanceVO.setBusinessKey(historicProcessInstance.getBusinessKey());
@ -783,7 +856,7 @@ public class FlowableServiceImpl implements FlowableService {
}
}
TaskVO.TaskVOBuilder taskVOBuilder = TaskVO.builder().taskName(userTask.getName()).
handleNameList(handleNameList).
handleUserList(handleNameList).
taskDefinitionKey(userTask.getId()).
startUserId(processInstance.getStartUserId());
@ -826,7 +899,7 @@ public class FlowableServiceImpl implements FlowableService {
}
}
TaskVO.TaskVOBuilder taskVOBuilder = TaskVO.builder().taskName(userTask.getName()).
handleNameList(handleNameList).
handleUserList(handleNameList).
taskDefinitionKey(userTask.getId()).
startUserId(processInstance.getStartUserId());
@ -863,7 +936,7 @@ public class FlowableServiceImpl implements FlowableService {
System.out.println(JSON.toJSON(values));
}
TaskVO.TaskVOBuilder taskVOBuilder = TaskVO.builder().taskName(userTask.getName()).
handleNameList(handleNameList).
handleUserList(handleNameList).
taskDefinitionKey(userTask.getId()).
startUserId(processInstance.getStartUserId());
@ -940,10 +1013,12 @@ public class FlowableServiceImpl implements FlowableService {
while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
imageStream.close();
log.info("[完成]-获取流程图图像");
os.close();
imageStream.close();
}
log.info("[完成]-获取流程图图像");
} catch (Exception e) {
log.error("【异常】-获取流程图失败!" + e.getMessage());
throw new BusinessException("获取流程图失败!" + e.getMessage());

View File

@ -19,6 +19,12 @@ public interface SysOaLeaveMapper
*/
public SysOaLeave selectSysOaLeaveById(Integer id);
/**
* 查询请求单
* @param leaveNo
* @return
*/
public SysOaLeave selectSysOaLeaveByLeaveNo(String leaveNo);
/**
* 查询请假单列表
*

View File

@ -19,6 +19,13 @@ public interface ISysOaLeaveService
*/
public SysOaLeave selectSysOaLeaveById(Integer id);
/**
*
* @param leaveNo
* @return
*/
public SysOaLeave selectSysOaLeaveByLeaveNo(String leaveNo);
/**
* 查询请假单列表
*

View File

@ -33,6 +33,16 @@ public class SysOaLeaveServiceImpl implements ISysOaLeaveService
return sysOaLeaveMapper.selectSysOaLeaveById(id);
}
/**
*
* @param leaveNo
* @return
*/
@Override
public SysOaLeave selectSysOaLeaveByLeaveNo(String leaveNo) {
return sysOaLeaveMapper.selectSysOaLeaveByLeaveNo(leaveNo);
}
/**
* 查询请假单列表
*

View File

@ -47,6 +47,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectSysOaLeaveVo"/>
where id = #{id}
</select>
<select id="selectSysOaLeaveByLeaveNo" parameterType="String" resultMap="SysOaLeaveResult">
<include refid="selectSysOaLeaveVo"/>
where leave_no = #{leaveNo}
</select>
<insert id="insertSysOaLeave" parameterType="SysOaLeave" useGeneratedKeys="true" keyProperty="id">
insert into sys_oa_leave