完善流程

This commit is contained in:
jinqiming 2021-07-23 15:46:43 +08:00
parent d7ed69a79a
commit 005d15165f
11 changed files with 171 additions and 79 deletions

View File

@ -16,6 +16,7 @@ import com.snow.framework.util.ShiroUtils;
import com.snow.system.domain.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -145,14 +146,16 @@ public class FlowController extends BaseController {
@GetMapping("/myStartProcessDetail")
@RequiresPermissions("system:flow:myStartProcessDetail")
public String myStartProcessDetail(String processInstanceId,ModelMap modelMap) {
//已审批的
ProcessInstanceVO processInstanceVo = flowableService.getProcessInstanceVoById(processInstanceId);
//已审批的任务
HistoricTaskInstanceDTO historicTaskInstanceDTO=new HistoricTaskInstanceDTO();
historicTaskInstanceDTO.setProcessInstanceId(processInstanceId);
//historicTaskInstanceDTO.setProcessStatus(1);
List<HistoricTaskInstanceVO> historicTaskInstanceList= flowableService.getHistoricTaskInstanceNoPage(historicTaskInstanceDTO);
//获取业务数据
AppForm appFrom = appFormService.getAppFrom(processInstanceId);
modelMap.put("historicTaskInstanceList",historicTaskInstanceList);
modelMap.put("processInstanceId",processInstanceId);
modelMap.put("processInstance",processInstanceVo);
modelMap.put("busVarUrl",appFrom.getBusVarUrl());
modelMap.put("appId",ReflectUtil.getFieldValue(appFrom,"id"));
return prefix +"/myStartProcessDetail";
@ -259,17 +262,17 @@ public class FlowController extends BaseController {
}
/**
* 删除流程
* @param id
* @param reason
* 取消流程
* @param id 流程实例id
* @param reason 理由
* @return
*/
@PostMapping("/deleteProcessInstance")
@RequiresPermissions("flow:process:deleteProcessInstance")
@PostMapping("/cancelProcessInstance")
@RequiresPermissions("flow:process:cancelProcessInstance")
@ResponseBody
@RepeatSubmit
public AjaxResult suspendProcessInstance(String id,String reason) {
flowableService.deleteProcessInstance(id,reason);
public AjaxResult cancelProcessInstanceFlag(String id,String reason) {
flowableService.cancelProcessInstance(id,reason);
return AjaxResult.success();
}

View File

@ -6,9 +6,9 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://rm-bp1j1554xv1qs04295o.mysql.rds.aliyuncs.com:3306/snow-dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
username: cloud_root
password: Jin!152377
url: jdbc:mysql://localhost:3306/snow?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
# 从库数据源
slave:
# 从数据源开关/默认关闭

View File

@ -44,7 +44,7 @@
var processInstanceStatusDatas = [[${@dict.getType('process_instance_status')}]];
var activeProcessInstanceFlag = [[${@permission.hasPermi('system:flow:activeProcessInstance')}]];
var suspendProcessInstanceFlag = [[${@permission.hasPermi('system:flow:suspendProcessInstance')}]];
var deleteProcessInstanceFlag = [[${@permission.hasPermi('system:flow:deleteProcessInstance')}]];
var cancelProcessInstanceFlag = [[${@permission.hasPermi('system:flow:cancelProcessInstance')}]];
var prefixFlow = ctx + "flow";
$(function() {
@ -119,7 +119,7 @@
actions.push('<a class="btn btn-success btn-xs ' + activeProcessInstanceFlag + '" href="javascript:void(0)" onclick="$.operate.activeProcessInstance(\'' + row.id + '\')"><i class="fa fa-eye"></i>激活</a> ');
}
if(isFinished==0) {
actions.push('<a class="btn btn-warning btn-xs ' + deleteProcessInstanceFlag + '" href="javascript:void(0)" onclick="deleteProcessInstance(\'' + row.id + '\')"><i class="fa fa-delicious"></i>删除</a> ');
actions.push('<a class="btn btn-warning btn-xs ' + cancelProcessInstanceFlag + '" href="javascript:void(0)" onclick="cancelProcessInstance(\'' + row.id + '\')"><i class="fa fa-delicious"></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('');
@ -140,8 +140,8 @@
$.modal.openTab("详情", detailUrl);
}
// 导入数据
function deleteProcessInstance(id) {
// 取消流程
function cancelProcessInstance(id) {
layer.open({
type: 1,
area: ['500px', '350px'],
@ -149,7 +149,7 @@
//不固定
maxmin: false,
shade: 0.3,
title: '删除流程',
title: '取消流程',
content: $('#deleteProcessInstanceTpl').html(),
btn: ['<i class="fa fa-check"></i>提交', '<i class="fa fa-remove"></i> 取消'],
// 弹层外区域关闭
@ -157,7 +157,7 @@
btn1: function(index, layero){
var reason = layero.find('#reason').val();
if(reason==''||reason==null){
$.modal.msgWarning("删除理由不能为空");
$.modal.msgWarning("取消理由不能为空");
return false;
}
var index = layer.load(2, {shade: false});
@ -194,9 +194,9 @@
<div class="col-xs-offset-1">
<div class="row">
<div class="form-group">
<label class="col-sm-3 control-label">删除理由:</label>
<label class="col-sm-3 control-label">取消理由:</label>
<div class="col-sm-8">
<textarea name="reason" id="reason" class="form-control" rows="7" placeholder="请输入删除理由..." required></textarea>
<textarea name="reason" id="reason" class="form-control" rows="7" placeholder="请输入取消理由..." required></textarea>
</div>
</div>
</div>

View File

@ -10,16 +10,73 @@
<input name="busVarUrl" id="busVarUrl" th:value="${busVarUrl}" type="hidden" >
<input name="appId" id="appId" th:value="${appId}" type="hidden" >
<div class="ibox float-e-margins" id="busPage">
<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 class="ibox float-e-margins">
<h4 class="form-header h4">流程概况</h4>
<div class="vertical-timeline-block" >
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">流程名称:</label>
<div class="form-control-static" th:text="${processInstance.processDefinitionName}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">流程状态:</label>
<div class="form-control-static" th:if="${processInstance.isFinished==0}">
<span class="badge badge-info">进行中</span>
</div>
<div class="form-control-static" th:if="${processInstance.isFinished==1}">
<span class="badge badge-success">结束</span>
</div>
<div class="form-control-static" th:if="${processInstance.isFinished==2}">
<span class="badge badge-warning">取消</span>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">发起人:</label>
<div class="form-control-static" th:text="${processInstance.startUserName}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">流程已用时:</label>
<div class="form-control-static" th:text="${processInstance.processSpendTime}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">开始时间:</label>
<div class="form-control-static" th:text="${#dates.format(processInstance.startTime, 'yyyy-MM-dd hh:mm:ss')}">
</div>
</div>
<div class="col-xs-4 col-sm-5">
<label class="col-sm-3 control-label">结束时间:</label>
<div class="form-control-static" th:text="${#dates.format(processInstance.endTime, 'yyyy-MM-dd hh:mm:ss')}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1" th:if="${processInstance.isFinished==2}">
<label class="col-sm-3 control-label">取消原因:</label>
<div class="form-control-static" th:text="${processInstance.deleteReason}">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 col-sm-5 col-md-offset-1">
<label class="col-sm-3 control-label">业务单详情:</label>
<div class="form-control-static" >
<a href="javascript:void(0)" onclick="getProcessDiagram()">
[[${processInstance.businessKey}]]
</a>
</div>
</div>
</div>
</div>
</p>
</div>
<div class="ibox float-e-margins">
<h4 class="form-header h4">流程图</h4>
<div class="vertical-timeline-block" >

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('人事审批')" />
<th:block th:include="include :: header('请假详情')" />
<th:block th:include="include :: jsonview-css" />
<th:block th:include="include :: bootstrap-fileinput-css"/>
</head>
@ -48,7 +48,6 @@
</div>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />

View File

@ -31,7 +31,7 @@ public abstract class AppForm implements Serializable {
/**
* 业务数URL
* 业务据详情页URL
*/
private String busVarUrl;

View File

@ -1,7 +1,6 @@
package com.snow.flowable.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@ -75,5 +74,4 @@ public class ProcessInstanceDTO extends FlowBaseDTO implements Serializable {
public String nameLikeIgnoreCase;
}

View File

@ -112,7 +112,7 @@ public class ProcessInstanceVO implements Serializable {
*/
private String businessKey;
/**
* 是否结束(0--进行中1--结束)
* 是否结束(0--进行中1--结束,2--取消)
*/
private Integer isFinished;
@ -131,14 +131,17 @@ public class ProcessInstanceVO implements Serializable {
*/
private Integer processInstanceStatus;
@Deprecated
public static List<ProcessInstanceVO> warpList(List<HistoricProcessInstance> historicProcessInstanceList){
return historicProcessInstanceList.stream().map(t->{
ProcessInstanceVO processInstanceVO=new ProcessInstanceVO();
BeanUtils.copyProperties(t,processInstanceVO);
if(StringUtils.isEmpty(t.getEndActivityId())){
processInstanceVO.setIsFinished(0);
}else {
if(StringUtils.isEmpty(t.getEndActivityId())&&StringUtils.isNotEmpty(t.getDeleteReason())){
processInstanceVO.setIsFinished(2);
}else if(StringUtils.isNotEmpty(t.getEndActivityId())){
processInstanceVO.setIsFinished(1);
}else {
processInstanceVO.setIsFinished(0);
}
Map<String, Object> processVariables = t.getProcessVariables();
processInstanceVO.setProcessVariables(processVariables);

View File

@ -120,6 +120,14 @@ public interface FlowableService {
*/
HistoricProcessInstance getHistoricProcessInstanceById(String id);
/**
* 获取组装后的流程实例
* @param id 流程实例id
* @return 组装后的实例对象
*/
ProcessInstanceVO getProcessInstanceVoById(String id);
/**
* 根据流程实例ID查询任务
* @param id
@ -184,11 +192,11 @@ public interface FlowableService {
void suspendOrActiveProcessInstance(String instanceId, Integer suspendState);
/**
* 删除流程
* @param instanceId
* @param reason
* 取消流程
* @param instanceId 流程实例id
* @param reason 理由
*/
void deleteProcessInstance(String instanceId, String reason);
void cancelProcessInstance(String instanceId, String reason);
/**
* 获取流程定义实体信息
*

View File

@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.BetweenFormater;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
@ -490,6 +491,18 @@ public class FlowableServiceImpl implements FlowableService {
.singleResult();
}
@Override
public ProcessInstanceVO getProcessInstanceVoById(String id) {
ProcessInstanceVO processInstanceVO=new ProcessInstanceVO();
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(id)
.includeProcessVariables()
.singleResult();
BeanUtils.copyProperties(historicProcessInstance,processInstanceVO);
//组装参数
warpProcessInstanceVo(processInstanceVO);
return processInstanceVO;
}
@Override
public Task getTaskProcessInstanceById(String id){
@ -661,7 +674,6 @@ public class FlowableServiceImpl implements FlowableService {
PageModel<ProcessInstanceVO> pageModel = new PageModel<> ();
pageModel.setTotalCount((int)count);
pageModel.setPagedRecords(processInstanceVOS);
//List<ProcessInstanceVO> processInstanceVOS = com.snow.common.utils.bean.BeanUtils.transformList(pageInfo.getList(), ProcessInstanceVO.class);
return pageModel;
}
@ -705,42 +717,7 @@ public class FlowableServiceImpl implements FlowableService {
* @param processInstanceVOS
*/
private void setProcessInstanceVOs(List<ProcessInstanceVO> processInstanceVOS){
processInstanceVOS.parallelStream().forEach(t->{
Map<String, Object> processVariables = t.getProcessVariables();
String url= Optional.ofNullable(String.valueOf(processVariables.get(FlowConstants.BUS_VAR_URL))).orElse("");
//设置返回详情页
if(!StringUtils.isEmpty(url)){
if(!StringUtils.isEmpty(processVariables.get("id")))
t.setFromDetailUrl(url+"/"+processVariables.get("id"));
}
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);
t.setProcessSpendTime(spendTime);
}else {
String spendTime = DateUtil.formatBetween(t.getStartTime(), t.getEndTime(), BetweenFormater.Level.SECOND);
t.setProcessSpendTime(spendTime);
}
String startUserId = t.getStartUserId();
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(startUserId));
t.setStartUserName(sysUser.getUserName());
//流程状态查询 ACT_RU_EXECUTION
List<Execution> list = runtimeService.createExecutionQuery().processInstanceId(t.getId()).list();
if(CollectionUtils.isEmpty(list)){
t.setProcessInstanceStatus(FlowInstanceEnum.ACTIVATE.getCode());
}else {
Execution execution=list.get(0);
if(execution.isSuspended()){
t.setProcessInstanceStatus(FlowInstanceEnum.SUSPEND.getCode());
}else {
t.setProcessInstanceStatus(FlowInstanceEnum.ACTIVATE.getCode());
}
}
});
processInstanceVOS.parallelStream().forEach(t-> warpProcessInstanceVo(t));
}
@Override
@ -1095,7 +1072,7 @@ public class FlowableServiceImpl implements FlowableService {
}
@Override
public void deleteProcessInstance(String instanceId, String reason) {
public void cancelProcessInstance(String instanceId, String reason) {
//调用这个方法会把历史数据全部删除
// historyService.deleteHistoricProcessInstance();
//调用该方法
@ -1210,4 +1187,47 @@ public class FlowableServiceImpl implements FlowableService {
return Sets.newHashSet(values);
}
/**
* 构建ProcessInstanceVO对象
* @param processInstanceVO
*/
private void warpProcessInstanceVo(ProcessInstanceVO processInstanceVO){
Map<String, Object> processVariables = processInstanceVO.getProcessVariables();
String url= Optional.ofNullable(String.valueOf(processVariables.get(FlowConstants.BUS_VAR_URL))).orElse("");
//设置返回详情页
if(ObjectUtil.isNotNull(url)&&ObjectUtil.isNotNull(processVariables.get("id"))){
processInstanceVO.setFromDetailUrl(url+"/"+processVariables.get("id"));
}
//设置表单数据
AppForm appForm=(AppForm)processVariables.get(FlowConstants.APP_FORM);
processInstanceVO.setAppForm(appForm);
//计算流程已用时间
String spendTime = StringUtils.isEmpty(processInstanceVO.getEndTime())?DateUtil.formatBetween(processInstanceVO.getStartTime(), new Date(), BetweenFormater.Level.SECOND):DateUtil.formatBetween(processInstanceVO.getStartTime(), processInstanceVO.getEndTime(), BetweenFormater.Level.SECOND);
processInstanceVO.setProcessSpendTime(spendTime);
//设置流程发起人
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(processInstanceVO.getStartUserId()));
processInstanceVO.setStartUserName(sysUser.getUserName());
//流程状态查询 ACT_RU_EXECUTION
List<Execution> list = runtimeService.createExecutionQuery().processInstanceId(processInstanceVO.getId()).list();
if(CollectionUtils.isEmpty(list)){
processInstanceVO.setProcessInstanceStatus(FlowInstanceEnum.ACTIVATE.getCode());
}else {
Execution execution=list.get(0);
if(execution.isSuspended()){
processInstanceVO.setProcessInstanceStatus(FlowInstanceEnum.SUSPEND.getCode());
}else {
processInstanceVO.setProcessInstanceStatus(FlowInstanceEnum.ACTIVATE.getCode());
}
}
//设置流程状态
if(ObjectUtil.isEmpty(processInstanceVO.getEndActivityId())&& ObjectUtil.isNotEmpty(processInstanceVO.getDeleteReason())){
processInstanceVO.setIsFinished(2);
}else if(ObjectUtil.isNotEmpty(processInstanceVO.getEndActivityId())){
processInstanceVO.setIsFinished(1);
}else {
processInstanceVO.setIsFinished(0);
}
}
}

View File

@ -18,4 +18,8 @@ INSERT INTO `sys_dict_data`( `dict_sort`, `dict_label`, `dict_value`, `dict_type
INSERT INTO `sys_message_template`( `template_code`, `template_name`, `template_body`, `template_desc`, `template_type`, `pc_url`, `app_url`, `icon_class`, `template_status`, `is_delete`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ( '1411568525448978432', '拜访日志', '${userName}于${nowTime}向您推送了一条【${enterprice}】的拜访日志,请您及时前往客户管理查看。', '拜访日志', 4, '/system/customer/messageDetail/${id}', '', 'fa fa-modx', 0, 0, '1', NOW(), '1', NOW());
INSERT INTO `sys_message_template`( `template_code`, `template_name`, `template_body`, `template_desc`, `template_type`, `pc_url`, `app_url`, `icon_class`, `template_status`, `is_delete`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ( '1415927384573616128', '任务待办', '${startUser}于${startTime}发起的【${processInstance}】审批流程到达【${taskName}】审批节点,现需要您去协助处理。请点击详情前往处理。', '任务待办', 4, '/flow/toTaskDetail?taskId=${taskId}', '', 'fa fa-bullhorn', 0, 0, '1', '2021-07-17 10:09:37', '1', '2021-07-17 19:54:55');
INSERT INTO `sys_message_template`( `template_code`, `template_name`, `template_body`, `template_desc`, `template_type`, `pc_url`, `app_url`, `icon_class`, `template_status`, `is_delete`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ( '1416370192572882944', '流程完结', '您于${startTime}发起的业务单号为【${businessKey}】的【${processInstance}】审批流程现已完结,流程总用时:【${spendTime}】。请点击详情前往查看。', '流程完结', 4, '/flow/myStartProcessDetail?processInstanceId=${processInstanceId}', '', 'fa fa-hourglass-start', 0, 0, '1', '2021-07-17 20:18:23', '1', '2021-07-17 23:07:39');
INSERT INTO `sys_message_template`( `template_code`, `template_name`, `template_body`, `template_desc`, `template_type`, `pc_url`, `app_url`, `icon_class`, `template_status`, `is_delete`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ( '1416370192572882944', '流程完结', '您于${startTime}发起的业务单号为【${businessKey}】的【${processInstance}】审批流程现已完结,流程总用时:【${spendTime}】。请点击详情前往查看。', '流程完结', 4, '/flow/myStartProcessDetail?processInstanceId=${processInstanceId}', '', 'fa fa-hourglass-start', 0, 0, '1', '2021-07-17 20:18:23', '1', '2021-07-17 23:07:39');
#2021-07-23
INSERT INTO `sys_dict_data`( `dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES ( 3, '取消', '2', 'process_instance_status', NULL, 'warning', 'N', '0', 'admin', NOW(), '', NOW(), '取消');
INSERT INTO `sys_menu`( `menu_name`, `parent_id`, `order_num`, `url`, `target`, `menu_type`, `visible`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `is_refresh`, `menu_source`) VALUES ('取消流程', 2043, 3, '#', 'menuItem', 'F', '0', 'cancelProcessInstance', '#', 'admin', NOW(), '', NULL, '', 1, 0);