!6 同步develop分支

* sync -- 同步develop分支
This commit is contained in:
KonBAI
2022-01-18 13:16:15 +00:00
parent a649962696
commit 5676316380
338 changed files with 10957 additions and 9551 deletions

View File

@@ -0,0 +1,55 @@
package com.ruoyi.workflow.service;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.workflow.domain.bo.FlowCategoryBo;
import com.ruoyi.workflow.domain.vo.FlowCategoryVo;
import java.util.Collection;
import java.util.List;
/**
* 流程分类Service接口
*
* @author KonBAI
* @date 2022-01-15
*/
public interface IFlowCategoryService {
/**
* 查询单个
* @return
*/
FlowCategoryVo queryById(Long categoryId);
/**
* 查询列表
*/
TableDataInfo<FlowCategoryVo> queryPageList(FlowCategoryBo bo, PageQuery pageQuery);
/**
* 查询列表
*/
List<FlowCategoryVo> queryList(FlowCategoryBo bo);
/**
* 根据新增业务对象插入【请填写功能名称】
* @param bo 【请填写功能名称】新增业务对象
* @return
*/
Boolean insertByBo(FlowCategoryBo bo);
/**
* 根据编辑业务对象修改【请填写功能名称】
* @param bo 【请填写功能名称】编辑业务对象
* @return
*/
Boolean updateByBo(FlowCategoryBo bo);
/**
* 校验并删除数据
* @param ids 主键集合
* @param isValid 是否校验,true-删除前校验,false-不校验
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,79 @@
package com.ruoyi.workflow.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.workflow.domain.dto.FlowProcDefDto;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
/**
* @author XuanXuan
* @date 2021-04-03 14:41
*/
public interface IFlowDefinitionService {
boolean exist(String processDefinitionKey);
/**
* 流程定义列表
*
* @param pageNum 当前页码
* @param pageSize 每页条数
* @return 流程定义分页列表数据
*/
Page<FlowProcDefDto> list(Integer pageNum, Integer pageSize);
/**
* 导入流程文件
*
* @param name
* @param category
* @param in
*/
void importFile(String name, String category, InputStream in);
/**
* 读取xml
* @param deployId
* @return
*/
R readXml(String deployId) throws IOException;
/**
* 根据流程定义ID启动流程实例
*
* @param procDefId
* @param variables
* @return
*/
R startProcessInstanceById(String procDefId, Map<String, Object> variables);
/**
* 激活或挂起流程定义
*
* @param state 状态
* @param deployId 流程部署ID
*/
void updateState(Integer state, String deployId);
/**
* 删除流程定义
*
* @param deployId 流程部署ID act_ge_bytearray 表中 deployment_id值
*/
void delete(String deployId);
/**
* 读取图片文件
* @param deployId
* @return
*/
InputStream readImage(String deployId);
}

View File

@@ -0,0 +1,58 @@
package com.ruoyi.workflow.service;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.workflow.domain.vo.FlowTaskVo;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.Task;
import java.util.List;
import java.util.Map;
/**
* @author XuanXuan
* @date 2021-04-03 14:40
*/
public interface IFlowInstanceService {
List<Task> queryListByInstanceId(String instanceId);
/**
* 结束流程实例
*
* @param vo
*/
void stopProcessInstance(FlowTaskVo vo);
/**
* 激活或挂起流程实例
*
* @param state 状态
* @param instanceId 流程实例ID
*/
void updateState(Integer state, String instanceId);
/**
* 删除流程实例ID
*
* @param instanceId 流程实例ID
* @param deleteReason 删除原因
*/
void delete(String instanceId, String deleteReason);
/**
* 根据实例ID查询历史实例数据
*
* @param processInstanceId
* @return
*/
HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId);
/**
* 根据流程定义ID启动流程实例
*
* @param procDefId 流程定义Id
* @param variables 流程变量
* @return
*/
R startProcessInstanceById(String procDefId, Map<String, Object> variables);
}

View File

@@ -0,0 +1,166 @@
package com.ruoyi.workflow.service;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.workflow.domain.vo.FlowTaskVo;
import org.flowable.task.api.Task;
import java.io.InputStream;
/**
* @author XuanXuan
* @date 2021-04-03 14:42
*/
public interface IFlowTaskService {
/**
* 审批任务
*
* @param task 请求实体参数
*/
R complete(FlowTaskVo task);
/**
* 驳回任务
*
* @param flowTaskVo
*/
void taskReject(FlowTaskVo flowTaskVo);
/**
* 退回任务
*
* @param flowTaskVo 请求实体参数
*/
void taskReturn(FlowTaskVo flowTaskVo);
/**
* 获取所有可回退的节点
*
* @param flowTaskVo
* @return
*/
R findReturnTaskList(FlowTaskVo flowTaskVo);
/**
* 删除任务
*
* @param flowTaskVo 请求实体参数
*/
void deleteTask(FlowTaskVo flowTaskVo);
/**
* 认领/签收任务
*
* @param flowTaskVo 请求实体参数
*/
void claim(FlowTaskVo flowTaskVo);
/**
* 取消认领/签收任务
*
* @param flowTaskVo 请求实体参数
*/
void unClaim(FlowTaskVo flowTaskVo);
/**
* 委派任务
*
* @param flowTaskVo 请求实体参数
*/
void delegateTask(FlowTaskVo flowTaskVo);
/**
* 转办任务
*
* @param flowTaskVo 请求实体参数
*/
void assignTask(FlowTaskVo flowTaskVo);
/**
* 我发起的流程
* @param pageNum
* @param pageSize
* @return
*/
R myProcess(Integer pageNum, Integer pageSize);
/**
* 取消申请
* @param flowTaskVo
* @return
*/
R stopProcess(FlowTaskVo flowTaskVo);
/**
* 撤回流程
* @param flowTaskVo
* @return
*/
R revokeProcess(FlowTaskVo flowTaskVo);
/**
* 代办任务列表
*
* @param pageNum 当前页码
* @param pageSize 每页条数
* @return
*/
R todoList(Integer pageNum, Integer pageSize);
/**
* 已办任务列表
*
* @param pageNum 当前页码
* @param pageSize 每页条数
* @return
*/
R finishedList(Integer pageNum, Integer pageSize);
/**
* 流程历史流转记录
*
* @param procInsId 流程实例Id
* @return
*/
R flowRecord(String procInsId,String deployId);
/**
* 根据任务ID查询挂载的表单信息
*
* @param taskId 任务Id
* @return
*/
Task getTaskForm(String taskId);
/**
* 获取流程过程图
* @param processId
* @return
*/
InputStream diagram(String processId);
/**
* 获取流程执行过程
* @param procInsId
* @return
*/
R getFlowViewer(String procInsId);
/**
* 获取流程变量
* @param taskId
* @return
*/
R processVariables(String taskId);
/**
* 获取下一节点
* @param flowTaskVo 任务
* @return
*/
R getNextFlowNode(FlowTaskVo flowTaskVo);
}

View File

@@ -0,0 +1,70 @@
package com.ruoyi.workflow.service;
import com.ruoyi.system.domain.SysDeployForm;
import com.ruoyi.system.domain.SysForm;
import java.util.List;
/**
* 流程实例关联表单Service接口
*
* @author XuanXuan
* @date 2021-04-03
*/
public interface ISysDeployFormService {
/**
* 查询流程实例关联表单
*
* @param id 流程实例关联表单ID
* @return 流程实例关联表单
*/
SysDeployForm selectSysDeployFormById(Long id);
/**
* 查询流程实例关联表单列表
*
* @param sysDeployForm 流程实例关联表单
* @return 流程实例关联表单集合
*/
List<SysDeployForm> selectSysDeployFormList(SysDeployForm sysDeployForm);
/**
* 新增流程实例关联表单
*
* @param sysDeployForm 流程实例关联表单
* @return 结果
*/
int insertSysDeployForm(SysDeployForm sysDeployForm);
/**
* 修改流程实例关联表单
*
* @param sysDeployForm 流程实例关联表单
* @return 结果
*/
int updateSysDeployForm(SysDeployForm sysDeployForm);
/**
* 批量删除流程实例关联表单
*
* @param ids 需要删除的流程实例关联表单ID
* @return 结果
*/
int deleteSysDeployFormByIds(Long[] ids);
/**
* 删除流程实例关联表单信息
*
* @param id 流程实例关联表单ID
* @return 结果
*/
int deleteSysDeployFormById(Long id);
/**
* 查询流程挂着的表单
*
* @param deployId
* @return
*/
SysForm selectSysDeployFormByDeployId(String deployId);
}

View File

@@ -0,0 +1,71 @@
package com.ruoyi.workflow.service;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.SysForm;
import java.util.List;
/**
* 表单
*
* @author XuanXuan Xuan
* @date 2021-04-03
*/
public interface ISysFormService {
/**
* 查询流程表单
*
* @param formId 流程表单ID
* @return 流程表单
*/
SysForm selectSysFormById(Long formId);
/**
* 查询流程表单列表
*
* @param sysForm 流程表单
* @return 流程表单集合
*/
TableDataInfo<SysForm> selectSysFormPage(SysForm sysForm, PageQuery pageQuery);
/**
* 查询流程表单列表
*
* @param sysForm 流程表单
* @return 流程表单集合
*/
List<SysForm> selectSysFormList(SysForm sysForm);
/**
* 新增流程表单
*
* @param sysForm 流程表单
* @return 结果
*/
int insertSysForm(SysForm sysForm);
/**
* 修改流程表单
*
* @param sysForm 流程表单
* @return 结果
*/
int updateSysForm(SysForm sysForm);
/**
* 批量删除流程表单
*
* @param formIds 需要删除的流程表单ID
* @return 结果
*/
int deleteSysFormByIds(Long[] formIds);
/**
* 删除流程表单信息
*
* @param formId 流程表单ID
* @return 结果
*/
int deleteSysFormById(Long formId);
}

View File

@@ -0,0 +1,62 @@
package com.ruoyi.workflow.service;
import com.ruoyi.system.domain.SysTaskForm;
import java.util.List;
/**
* 流程任务关联单Service接口
*
* @author XuanXuan
* @date 2021-04-03
*/
@Deprecated
public interface ISysTaskFormService {
/**
* 查询流程任务关联单
*
* @param id 流程任务关联单ID
* @return 流程任务关联单
*/
SysTaskForm selectSysTaskFormById(Long id);
/**
* 查询流程任务关联单列表
*
* @param sysTaskForm 流程任务关联单
* @return 流程任务关联单集合
*/
List<SysTaskForm> selectSysTaskFormList(SysTaskForm sysTaskForm);
/**
* 新增流程任务关联单
*
* @param sysTaskForm 流程任务关联单
* @return 结果
*/
int insertSysTaskForm(SysTaskForm sysTaskForm);
/**
* 修改流程任务关联单
*
* @param sysTaskForm 流程任务关联单
* @return 结果
*/
int updateSysTaskForm(SysTaskForm sysTaskForm);
/**
* 批量删除流程任务关联单
*
* @param ids 需要删除的流程任务关联单ID
* @return 结果
*/
int deleteSysTaskFormByIds(Long[] ids);
/**
* 删除流程任务关联单信息
*
* @param id 流程任务关联单ID
* @return 结果
*/
int deleteSysTaskFormById(Long id);
}

View File

@@ -0,0 +1,94 @@
package com.ruoyi.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.workflow.domain.FlowCategory;
import com.ruoyi.workflow.domain.bo.FlowCategoryBo;
import com.ruoyi.workflow.domain.vo.FlowCategoryVo;
import com.ruoyi.workflow.mapper.FlowCategoryMapper;
import com.ruoyi.workflow.service.IFlowCategoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 流程分类Service业务层处理
*
* @author KonBAI
* @date 2022-01-15
*/
@RequiredArgsConstructor
@Service
public class FlowCategoryServiceImpl implements IFlowCategoryService {
private final FlowCategoryMapper baseMapper;
@Override
public FlowCategoryVo queryById(Long categoryId){
return baseMapper.selectVoById(categoryId);
}
@Override
public TableDataInfo<FlowCategoryVo> queryPageList(FlowCategoryBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<FlowCategory> lqw = buildQueryWrapper(bo);
Page<FlowCategoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<FlowCategoryVo> queryList(FlowCategoryBo bo) {
LambdaQueryWrapper<FlowCategory> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<FlowCategory> buildQueryWrapper(FlowCategoryBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<FlowCategory> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), FlowCategory::getCategoryName, bo.getCategoryName());
lqw.eq(StringUtils.isNotBlank(bo.getCode()), FlowCategory::getCode, bo.getCode());
return lqw;
}
@Override
public Boolean insertByBo(FlowCategoryBo bo) {
FlowCategory add = BeanUtil.toBean(bo, FlowCategory.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setCategoryId(add.getCategoryId());
}
return flag;
}
@Override
public Boolean updateByBo(FlowCategoryBo bo) {
FlowCategory update = BeanUtil.toBean(bo, FlowCategory.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*
* @param entity 实体类数据
*/
private void validEntityBeforeSave(FlowCategory entity){
//TODO 做一些数据校验,如唯一约束
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,225 @@
package com.ruoyi.workflow.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.LoginUtils;
import com.ruoyi.flowable.common.constant.ProcessConstants;
import com.ruoyi.flowable.common.enums.FlowComment;
import com.ruoyi.workflow.domain.dto.FlowProcDefDto;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.workflow.service.IFlowDefinitionService;
import com.ruoyi.workflow.service.ISysDeployFormService;
import com.ruoyi.system.domain.SysForm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* 流程定义
*
* @author XuanXuan
* @date 2021-04-03
*/
@Service
@Slf4j
public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFlowDefinitionService {
@Resource
private ISysDeployFormService sysDeployFormService;
private static final String BPMN_FILE_SUFFIX = ".bpmn";
@Override
public boolean exist(String processDefinitionKey) {
ProcessDefinitionQuery processDefinitionQuery
= repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey);
long count = processDefinitionQuery.count();
return count > 0;
}
/**
* 流程定义列表
*
* @param pageNum 当前页码
* @param pageSize 每页条数
* @return 流程定义分页列表数据
*/
@Override
public Page<FlowProcDefDto> list(Integer pageNum, Integer pageSize) {
Page<FlowProcDefDto> page = new Page<>();
// 流程定义列表数据查询
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
// .latestVersion()
.orderByProcessDefinitionKey().asc();
page.setTotal(processDefinitionQuery.count());
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage(pageNum - 1, pageSize);
List<FlowProcDefDto> dataList = new ArrayList<>();
for (ProcessDefinition processDefinition : processDefinitionList) {
String deploymentId = processDefinition.getDeploymentId();
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
FlowProcDefDto reProcDef = new FlowProcDefDto();
BeanUtils.copyProperties(processDefinition, reProcDef);
SysForm sysForm = sysDeployFormService.selectSysDeployFormByDeployId(deploymentId);
if (Objects.nonNull(sysForm)) {
reProcDef.setFormName(sysForm.getFormName());
reProcDef.setFormId(sysForm.getFormId());
}
// 流程定义时间
reProcDef.setDeploymentTime(deployment.getDeploymentTime());
dataList.add(reProcDef);
}
page.setRecords(dataList);
return page;
}
/**
* 导入流程文件
*
* @param name
* @param category
* @param in
*/
@Override
public void importFile(String name, String category, InputStream in) {
Deployment deploy = repositoryService.createDeployment().addInputStream(name + BPMN_FILE_SUFFIX, in).name(name).category(category).deploy();
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
repositoryService.setProcessDefinitionCategory(definition.getId(), category);
}
/**
* 读取xml
*
* @param deployId
* @return
*/
@Override
public R readXml(String deployId) throws IOException {
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName());
String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name());
return R.success("", result);
}
/**
* 读取xml
*
* @param deployId
* @return
*/
@Override
public InputStream readImage(String deployId) {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
//获得图片流
DefaultProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
//输出为图片
return diagramGenerator.generateDiagram(
bpmnModel,
"png",
Collections.emptyList(),
Collections.emptyList(),
"宋体",
"宋体",
"宋体",
null,
1.0,
false);
}
/**
* 根据流程定义ID启动流程实例
*
* @param procDefId 流程定义Id
* @param variables 流程变量
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public R startProcessInstanceById(String procDefId, Map<String, Object> variables) {
try {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId)
.latestVersion().singleResult();
if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
return R.error("流程已被挂起,请先激活流程");
}
// variables.put("skip", true);
// variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);
// 设置流程发起人Id到流程中
String UserIdStr = LoginUtils.getUserId().toString();
identityService.setAuthenticatedUserId(UserIdStr);
variables.put(ProcessConstants.PROCESS_INITIATOR, UserIdStr);
ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
// 给第一步申请人节点设置任务执行人和意见 todo:第一个节点不设置为申请人节点有点问题?
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
if (Objects.nonNull(task)) {
if (!StrUtil.equalsAny(task.getAssignee(), UserIdStr)) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return R.error("数据验证失败,该工作流第一个用户任务的指派人并非当前用户,不能执行该操作!");
}
taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), LoginUtils.getNickName() + "发起流程申请");
// taskService.setAssignee(task.getId(), UserIdStr);
taskService.complete(task.getId(), variables);
}
return R.success("流程启动成功");
} catch (Exception e) {
e.printStackTrace();
return R.error("流程启动错误");
}
}
/**
* 激活或挂起流程定义
*
* @param state 状态
* @param deployId 流程部署ID
*/
@Override
public void updateState(Integer state, String deployId) {
ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
// 激活
if (state == 1) {
repositoryService.activateProcessDefinitionById(procDef.getId(), true, null);
}
// 挂起
if (state == 2) {
repositoryService.suspendProcessDefinitionById(procDef.getId(), true, null);
}
}
/**
* 删除流程定义
*
* @param deployId 流程部署ID act_ge_bytearray 表中 deployment_id值
*/
@Override
public void delete(String deployId) {
// true 允许级联删除 ,不设置会导致数据库外键关联异常
repositoryService.deleteDeployment(deployId, true);
}
}

View File

@@ -0,0 +1,127 @@
package com.ruoyi.workflow.service.impl;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.LoginUtils;
import com.ruoyi.workflow.domain.vo.FlowTaskVo;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.workflow.service.IFlowInstanceService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* <p>工作流流程实例管理<p>
*
* @author XuanXuan
* @date 2021-04-03
*/
@Service
@Slf4j
public class FlowInstanceServiceImpl extends FlowServiceFactory implements IFlowInstanceService {
@Override
public List<Task> queryListByInstanceId(String instanceId) {
return taskService.createTaskQuery().processInstanceId(instanceId).active().list();
}
/**
* 结束流程实例
*
* @param vo
*/
@Override
public void stopProcessInstance(FlowTaskVo vo) {
String taskId = vo.getTaskId();
}
/**
* 激活或挂起流程实例
*
* @param state 状态
* @param instanceId 流程实例ID
*/
@Override
public void updateState(Integer state, String instanceId) {
// 激活
if (state == 1) {
runtimeService.activateProcessInstanceById(instanceId);
}
// 挂起
if (state == 2) {
runtimeService.suspendProcessInstanceById(instanceId);
}
}
/**
* 删除流程实例ID
*
* @param instanceId 流程实例ID
* @param deleteReason 删除原因
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(String instanceId, String deleteReason) {
// 查询历史数据
HistoricProcessInstance historicProcessInstance = getHistoricProcessInstanceById(instanceId);
if (historicProcessInstance.getEndTime() != null) {
historyService.deleteHistoricProcessInstance(historicProcessInstance.getId());
return;
}
// 删除流程实例
runtimeService.deleteProcessInstance(instanceId, deleteReason);
// 删除历史流程实例
historyService.deleteHistoricProcessInstance(instanceId);
}
/**
* 根据实例ID查询历史实例数据
*
* @param processInstanceId
* @return
*/
@Override
public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) {
HistoricProcessInstance historicProcessInstance =
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
if (Objects.isNull(historicProcessInstance)) {
throw new FlowableObjectNotFoundException("流程实例不存在: " + processInstanceId);
}
return historicProcessInstance;
}
/**
* 根据流程定义ID启动流程实例
*
* @param procDefId 流程定义Id
* @param variables 流程变量
* @return
*/
@Override
public R startProcessInstanceById(String procDefId, Map<String, Object> variables) {
try {
// 设置流程发起人Id到流程中
Long userId = LoginUtils.getUserId();
// identityService.setAuthenticatedUserId(userId.toString());
variables.put("initiator", userId);
variables.put("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true);
runtimeService.startProcessInstanceById(procDefId, variables);
return R.success("流程启动成功");
} catch (Exception e) {
e.printStackTrace();
return R.error("流程启动错误");
}
}
}

View File

@@ -0,0 +1,948 @@
package com.ruoyi.workflow.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.LoginUtils;
import com.ruoyi.flowable.common.constant.ProcessConstants;
import com.ruoyi.flowable.common.enums.FlowComment;
import com.ruoyi.workflow.domain.dto.FlowCommentDto;
import com.ruoyi.workflow.domain.dto.FlowNextDto;
import com.ruoyi.workflow.domain.dto.FlowTaskDto;
import com.ruoyi.workflow.domain.vo.FlowTaskVo;
import com.ruoyi.workflow.domain.vo.FlowViewerVo;
import com.ruoyi.flowable.factory.FlowServiceFactory;
import com.ruoyi.flowable.flow.CustomProcessDiagramGenerator;
import com.ruoyi.flowable.flow.FindNextNodeUtil;
import com.ruoyi.flowable.flow.FlowableUtils;
import com.ruoyi.workflow.service.IFlowTaskService;
import com.ruoyi.workflow.service.ISysDeployFormService;
import com.ruoyi.system.domain.SysForm;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricActivityInstanceQuery;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @author XuanXuan
* @date 2021-04-03
**/
@Service
@Slf4j
public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTaskService {
@Resource
private ISysUserService sysUserService;
@Resource
private ISysRoleService sysRoleService;
@Resource
private ISysDeployFormService sysInstanceFormService;
/**
* 完成任务
*
* @param taskVo 请求实体参数
*/
@Transactional(rollbackFor = Exception.class)
@Override
public R complete(FlowTaskVo taskVo) {
Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
if (Objects.isNull(task)){
return R.error("任务不存在");
}
if (DelegationState.PENDING.equals(task.getDelegationState())) {
taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment());
taskService.resolveTask(taskVo.getTaskId(), taskVo.getValues());
} else {
taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment());
Long userId = LoginUtils.getUserId();
taskService.setAssignee(taskVo.getTaskId(), userId.toString());
if (ObjectUtil.isNotEmpty(taskVo.getValues())) {
taskService.complete(taskVo.getTaskId(), taskVo.getValues());
} else {
taskService.complete(taskVo.getTaskId());
}
}
return R.success();
}
/**
* 驳回任务
*
* @param flowTaskVo
*/
@Override
public void taskReject(FlowTaskVo flowTaskVo) {
if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
throw new RuntimeException("任务处于挂起状态");
}
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取所有节点信息
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
// 获取全部节点列表,包含子节点
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
// 获取当前任务节点元素
FlowElement source = null;
if (allElements != null) {
for (FlowElement flowElement : allElements) {
// 类型为用户节点
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
// 获取节点信息
source = flowElement;
}
}
}
// 目的获取所有跳转到的节点 targetIds
// 获取当前节点的所有父级用户任务节点
// 深度优先算法思想:延边迭代深入
List<UserTask> parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null);
if (parentUserTaskList == null || parentUserTaskList.size() == 0) {
throw new RuntimeException("当前节点为初始任务节点,不能驳回");
}
// 获取活动 ID 即节点 Key
List<String> parentUserTaskKeyList = new ArrayList<>();
parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId()));
// 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序
List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list();
// 数据清洗,将回滚导致的脏数据清洗掉
List<String> lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList);
// 此时历史任务实例为倒序,获取最后走的节点
List<String> targetIds = new ArrayList<>();
// 循环结束标识,遇到当前目标节点的次数
int number = 0;
StringBuilder parentHistoricTaskKey = new StringBuilder();
for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) {
// 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过
if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) {
continue;
}
parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey);
if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) {
number++;
}
// 在数据清洗后,历史节点就是唯一一条从起始到当前节点的历史记录,理论上每个点只会出现一次
// 在流程中如果出现循环,那么每次循环中间的点也只会出现一次,再出现就是下次循环
// number == 1第一次遇到当前节点
// number == 2第二次遇到代表最后一次的循环范围
if (number == 2) {
break;
}
// 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点
if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) {
targetIds.add(historicTaskInstanceKey);
}
}
// 目的获取所有需要被跳转的节点 currentIds
// 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路
UserTask oneUserTask = parentUserTaskList.get(0);
// 获取所有正常进行的任务节点 Key这些任务不能直接使用需要找出其中需要撤回的任务
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
List<String> runTaskKeyList = new ArrayList<>();
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
// 需驳回任务列表
List<String> currentIds = new ArrayList<>();
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null);
currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
// 规定:并行网关之前节点必须需存在唯一用户任务节点,如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况
if (targetIds.size() > 1 && currentIds.size() > 1) {
throw new RuntimeException("任务出现多对多情况,无法撤回");
}
// 循环获取那些需要被撤回的节点的ID用来设置驳回原因
List<String> currentTaskIds = new ArrayList<>();
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
if (currentId.equals(runTask.getTaskDefinitionKey())) {
currentTaskIds.add(runTask.getId());
}
}));
// 设置驳回意见
currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment()));
try {
// 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况
if (targetIds.size() > 1) {
// 1 对 多任务跳转currentIds 当前节点(1)targetIds 跳转到的节点(多)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId()).
moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState();
}
// 如果父级任务只有一个,因此当前任务可能为网关中的任务
if (targetIds.size() == 1) {
// 1 对 1 或 多 对 1 情况currentIds 当前要跳转的节点列表(1或多)targetIds.get(0) 跳转到的节点(1)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState();
}
} catch (FlowableObjectNotFoundException e) {
throw new RuntimeException("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
throw new RuntimeException("无法取消或开始活动");
}
}
/**
* 退回任务
*
* @param flowTaskVo 请求实体参数
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void taskReturn(FlowTaskVo flowTaskVo) {
if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
throw new RuntimeException("任务处于挂起状态");
}
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取所有节点信息
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
// 获取全部节点列表,包含子节点
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
// 获取当前任务节点元素
FlowElement source = null;
// 获取跳转的节点元素
FlowElement target = null;
if (allElements != null) {
for (FlowElement flowElement : allElements) {
// 当前任务节点元素
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
source = flowElement;
}
// 跳转的节点元素
if (flowElement.getId().equals(flowTaskVo.getTargetKey())) {
target = flowElement;
}
}
}
// 从当前节点向前扫描
// 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转
// 否则目标节点相对于当前节点,属于串行
Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null);
if (!isSequential) {
throw new RuntimeException("当前节点相对于目标节点,不属于串行关系,无法回退");
}
// 获取所有正常进行的任务节点 Key这些任务不能直接使用需要找出其中需要撤回的任务
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
List<String> runTaskKeyList = new ArrayList<>();
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
// 需退回任务列表
List<String> currentIds = new ArrayList<>();
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
currentUserTaskList.forEach(item -> currentIds.add(item.getId()));
// 循环获取那些需要被撤回的节点的ID用来设置驳回原因
List<String> currentTaskIds = new ArrayList<>();
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
if (currentId.equals(runTask.getTaskDefinitionKey())) {
currentTaskIds.add(runTask.getId());
}
}));
// 设置回退意见
for (String currentTaskId : currentTaskIds) {
taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment());
}
try {
// 1 对 1 或 多 对 1 情况currentIds 当前要跳转的节点列表(1或多)targetKey 跳转到的节点(1)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(task.getProcessInstanceId())
.moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState();
} catch (FlowableObjectNotFoundException e) {
throw new RuntimeException("未找到流程实例,流程可能已发生变化");
} catch (FlowableException e) {
throw new RuntimeException("无法取消或开始活动");
}
}
/**
* 获取所有可回退的节点
*
* @param flowTaskVo
* @return
*/
@Override
public R findReturnTaskList(FlowTaskVo flowTaskVo) {
// 当前任务 task
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
// 获取流程定义信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
// 获取所有节点信息,暂不考虑子流程情况
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
Collection<FlowElement> flowElements = process.getFlowElements();
// 获取当前任务节点元素
UserTask source = null;
if (flowElements != null) {
for (FlowElement flowElement : flowElements) {
// 类型为用户节点
if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
source = (UserTask) flowElement;
}
}
}
// 获取节点的所有路线
List<List<UserTask>> roads = FlowableUtils.findRoad(source, null, null, null);
// 可回退的节点列表
List<UserTask> userTaskList = new ArrayList<>();
for (List<UserTask> road : roads) {
if (userTaskList.size() == 0) {
// 还没有可回退节点直接添加
userTaskList = road;
} else {
// 如果已有回退节点,则比对取交集部分
userTaskList.retainAll(road);
}
}
return R.success(userTaskList);
}
/**
* 删除任务
*
* @param flowTaskVo 请求实体参数
*/
@Override
public void deleteTask(FlowTaskVo flowTaskVo) {
// todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过?
taskService.deleteTask(flowTaskVo.getTaskId(),flowTaskVo.getComment());
}
/**
* 认领/签收任务
*
* @param flowTaskVo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void claim(FlowTaskVo flowTaskVo) {
taskService.claim(flowTaskVo.getTaskId(), flowTaskVo.getUserId());
}
/**
* 取消认领/签收任务
*
* @param flowTaskVo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void unClaim(FlowTaskVo flowTaskVo) {
taskService.unclaim(flowTaskVo.getTaskId());
}
/**
* 委派任务
*
* @param flowTaskVo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void delegateTask(FlowTaskVo flowTaskVo) {
taskService.delegateTask(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
}
/**
* 转办任务
*
* @param flowTaskVo 请求实体参数
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void assignTask(FlowTaskVo flowTaskVo) {
taskService.setAssignee(flowTaskVo.getTaskId(),flowTaskVo.getComment());
}
/**
* 我发起的流程
*
* @param pageNum
* @param pageSize
* @return
*/
@Override
public R myProcess(Integer pageNum, Integer pageSize) {
Page<FlowTaskDto> page = new Page<>();
Long userId = LoginUtils.getUserId();
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
.startedBy(userId.toString())
.orderByProcessInstanceStartTime()
.desc();
List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.listPage(pageNum - 1, pageSize);
page.setTotal(historicProcessInstanceQuery.count());
List<FlowTaskDto> flowList = new ArrayList<>();
for (HistoricProcessInstance hisIns : historicProcessInstances) {
FlowTaskDto flowTask = new FlowTaskDto();
flowTask.setCreateTime(hisIns.getStartTime());
flowTask.setFinishTime(hisIns.getEndTime());
flowTask.setProcInsId(hisIns.getId());
// 计算耗时
if (Objects.nonNull(hisIns.getEndTime())) {
long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime();
flowTask.setDuration(getDate(time));
} else {
long time = System.currentTimeMillis() - hisIns.getStartTime().getTime();
flowTask.setDuration(getDate(time));
}
// 流程定义信息
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(hisIns.getProcessDefinitionId())
.singleResult();
flowTask.setDeployId(pd.getDeploymentId());
flowTask.setProcDefName(pd.getName());
flowTask.setProcDefVersion(pd.getVersion());
flowTask.setCategory(pd.getCategory());
flowTask.setProcDefVersion(pd.getVersion());
// 当前所处流程 todo: 本地启动放开以下注释
// List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list();
// if (CollectionUtils.isNotEmpty(taskList)) {
// flowTask.setTaskId(taskList.get(0).getId());
// } else {
// List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
// flowTask.setTaskId(historicTaskInstance.get(0).getId());
// }
flowList.add(flowTask);
}
page.setRecords(flowList);
return R.success(page);
}
/**
* 取消申请
*
* @param flowTaskVo
* @return
*/
@Override
public R stopProcess(FlowTaskVo flowTaskVo) {
List<Task> task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).list();
if (CollectionUtils.isEmpty(task)) {
throw new RuntimeException("流程未启动或已执行完成,取消申请失败");
}
ProcessInstance processInstance =
runtimeService.createProcessInstanceQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
if (Objects.nonNull(bpmnModel)) {
Process process = bpmnModel.getMainProcess();
List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
if (CollectionUtils.isNotEmpty(endNodes)) {
Authentication.setAuthenticatedUserId(LoginUtils.getUserId().toString());
// taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.STOP.getType(),
// StringUtils.isBlank(flowTaskVo.getComment()) ? "取消申请" : flowTaskVo.getComment());
String endId = endNodes.get(0).getId();
List<Execution> executions =
runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
List<String> executionIds = new ArrayList<>();
executions.forEach(execution -> executionIds.add(execution.getId()));
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds,
endId).changeState();
}
}
return R.success();
}
/**
* 撤回流程 目前存在错误
*
* @param flowTaskVo
* @return
*/
@Override
public R revokeProcess(FlowTaskVo flowTaskVo) {
Task task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult();
if (task == null) {
throw new RuntimeException("流程未启动或已执行完成,无法撤回");
}
List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.orderByTaskCreateTime()
.asc()
.list();
String myTaskId = null;
HistoricTaskInstance myTask = null;
for (HistoricTaskInstance hti : htiList) {
if (LoginUtils.getUserId().toString().equals(hti.getAssignee())) {
myTaskId = hti.getId();
myTask = hti;
break;
}
}
if (null == myTaskId) {
throw new RuntimeException("该任务非当前用户提交,无法撤回");
}
String processDefinitionId = myTask.getProcessDefinitionId();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//变量
// Map<String, VariableInstance> variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
String myActivityId = null;
List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
.executionId(myTask.getExecutionId()).finished().list();
for (HistoricActivityInstance hai : haiList) {
if (myTaskId.equals(hai.getTaskId())) {
myActivityId = hai.getActivityId();
break;
}
}
FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
//记录原活动方向
List<SequenceFlow> oriSequenceFlows = new ArrayList<>(flowNode.getOutgoingFlows());
return R.success();
}
/**
* 代办任务列表
*
* @param pageNum 当前页码
* @param pageSize 每页条数
* @return
*/
@Override
public R todoList(Integer pageNum, Integer pageSize) {
Page<FlowTaskDto> page = new Page<>();
Long userId = LoginUtils.getUserId();
TaskQuery taskQuery = taskService.createTaskQuery()
.active()
.includeProcessVariables()
.taskAssignee(userId.toString())
.orderByTaskCreateTime().desc();
page.setTotal(taskQuery.count());
List<Task> taskList = taskQuery.listPage(pageNum - 1, pageSize);
List<FlowTaskDto> flowList = new ArrayList<>();
for (Task task : taskList) {
FlowTaskDto flowTask = new FlowTaskDto();
// 当前流程信息
flowTask.setTaskId(task.getId());
flowTask.setTaskDefKey(task.getTaskDefinitionKey());
flowTask.setCreateTime(task.getCreateTime());
flowTask.setProcDefId(task.getProcessDefinitionId());
flowTask.setTaskName(task.getName());
// 流程定义信息
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(task.getProcessDefinitionId())
.singleResult();
flowTask.setDeployId(pd.getDeploymentId());
flowTask.setProcDefName(pd.getName());
flowTask.setProcDefVersion(pd.getVersion());
flowTask.setProcInsId(task.getProcessInstanceId());
// 流程发起人信息
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.singleResult();
SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
// SysUser startUser = sysUserService.selectUserById(Long.parseLong(task.getAssignee()));
flowTask.setStartUserId(startUser.getNickName());
flowTask.setStartUserName(startUser.getNickName());
flowTask.setStartDeptName(startUser.getDept().getDeptName());
flowList.add(flowTask);
}
page.setRecords(flowList);
return R.success(page);
}
/**
* 已办任务列表
*
* @param pageNum 当前页码
* @param pageSize 每页条数
* @return
*/
@Override
public R finishedList(Integer pageNum, Integer pageSize) {
Page<FlowTaskDto> page = new Page<>();
Long userId = LoginUtils.getUserId();
HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
.includeProcessVariables()
.finished()
.taskAssignee(userId.toString())
.orderByHistoricTaskInstanceEndTime()
.desc();
List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(pageNum - 1, pageSize);
List<FlowTaskDto> hisTaskList = Lists.newArrayList();
for (HistoricTaskInstance histTask : historicTaskInstanceList) {
FlowTaskDto flowTask = new FlowTaskDto();
// 当前流程信息
flowTask.setTaskId(histTask.getId());
// 审批人员信息
flowTask.setCreateTime(histTask.getCreateTime());
flowTask.setFinishTime(histTask.getEndTime());
flowTask.setDuration(getDate(histTask.getDurationInMillis()));
flowTask.setProcDefId(histTask.getProcessDefinitionId());
flowTask.setTaskDefKey(histTask.getTaskDefinitionKey());
flowTask.setTaskName(histTask.getName());
// 流程定义信息
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
.processDefinitionId(histTask.getProcessDefinitionId())
.singleResult();
flowTask.setDeployId(pd.getDeploymentId());
flowTask.setProcDefName(pd.getName());
flowTask.setProcDefVersion(pd.getVersion());
flowTask.setProcInsId(histTask.getProcessInstanceId());
flowTask.setHisProcInsId(histTask.getProcessInstanceId());
// 流程发起人信息
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(histTask.getProcessInstanceId())
.singleResult();
SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
flowTask.setStartUserId(startUser.getNickName());
flowTask.setStartUserName(startUser.getNickName());
flowTask.setStartDeptName(startUser.getDept().getDeptName());
hisTaskList.add(flowTask);
}
page.setTotal(hisTaskList.size());
page.setRecords(hisTaskList);
// Map<String, Object> result = new HashMap<>();
// result.put("result",page);
// result.put("finished",true);
return R.success(page);
}
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
/**
* 流程历史流转记录
*
* @param procInsId 流程实例Id
* @return
*/
@Override
public R flowRecord(String procInsId, String deployId) {
Map<String, Object> map = new HashMap<String, Object>();
if (StringUtils.isNotBlank(procInsId)) {
List<HistoricActivityInstance> list = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId)
.orderByHistoricActivityInstanceStartTime()
.desc().list();
List<FlowTaskDto> hisFlowList = new ArrayList<>();
for (HistoricActivityInstance histIns : list) {
if (StringUtils.isNotBlank(histIns.getTaskId())) {
FlowTaskDto flowTask = new FlowTaskDto();
flowTask.setTaskId(histIns.getTaskId());
flowTask.setTaskName(histIns.getActivityName());
flowTask.setCreateTime(histIns.getStartTime());
flowTask.setFinishTime(histIns.getEndTime());
if (StringUtils.isNotBlank(histIns.getAssignee())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(histIns.getAssignee()));
flowTask.setAssigneeId(sysUser.getUserId());
flowTask.setAssigneeName(sysUser.getNickName());
flowTask.setDeptName(sysUser.getDept().getDeptName());
}
// 展示审批人员
List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId());
StringBuilder stringBuilder = new StringBuilder();
for (HistoricIdentityLink identityLink : linksForTask) {
if ("candidate".equals(identityLink.getType())) {
if (StringUtils.isNotBlank(identityLink.getUserId())) {
SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
stringBuilder.append(sysUser.getNickName()).append(",");
}
if (StringUtils.isNotBlank(identityLink.getGroupId())) {
SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
stringBuilder.append(sysRole.getRoleName()).append(",");
}
}
}
if (StringUtils.isNotBlank(stringBuilder)) {
flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
}
flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis()));
// 获取意见评论内容
List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId());
commentList.forEach(comment -> {
if (histIns.getTaskId().equals(comment.getTaskId())) {
flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build());
}
});
hisFlowList.add(flowTask);
}
}
map.put("flowList", hisFlowList);
// // 查询当前任务是否完成
// List<Task> taskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
// if (CollectionUtils.isNotEmpty(taskList)) {
// map.put("finished", true);
// } else {
// map.put("finished", false);
// }
}
// 第一次申请获取初始化表单
if (StringUtils.isNotBlank(deployId)) {
SysForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId);
if (Objects.isNull(sysForm)) {
return R.error("请先配置流程表单");
}
map.put("formData", JSONObject.parseObject(sysForm.getFormContent()));
}
return R.success(map);
}
/**
* 根据任务ID查询挂载的表单信息
*
* @param taskId 任务Id
* @return
*/
@Override
public Task getTaskForm(String taskId) {
return taskService.createTaskQuery().taskId(taskId).singleResult();
}
/**
* 获取流程过程图
*
* @param processId
* @return
*/
@Override
public InputStream diagram(String processId) {
String processDefinitionId;
// 获取当前的流程实例
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
// 如果流程已经结束,则得到结束节点
if (Objects.isNull(processInstance)) {
HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
processDefinitionId = pi.getProcessDefinitionId();
} else {// 如果流程没有结束,则取当前活动节点
// 根据流程实例ID获得当前处于活动状态的ActivityId合集
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
processDefinitionId = pi.getProcessDefinitionId();
}
// 获得活动的节点
List<HistoricActivityInstance> highLightedFlowList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();
List<String> highLightedFlows = new ArrayList<>();
List<String> highLightedNodes = new ArrayList<>();
//高亮线
for (HistoricActivityInstance tempActivity : highLightedFlowList) {
if ("sequenceFlow".equals(tempActivity.getActivityType())) {
//高亮线
highLightedFlows.add(tempActivity.getActivityId());
} else {
//高亮节点
highLightedNodes.add(tempActivity.getActivityId());
}
}
//获取流程图
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration();
//获取自定义图片生成器
ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator();
InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(),
configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true);
return in;
}
/**
* 获取流程执行过程
*
* @param procInsId
* @return
*/
@Override
public R getFlowViewer(String procInsId) {
// 构建查询条件
HistoricActivityInstanceQuery query = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInsId);
// 获取流程实例已完成的节点
List<String> finishedTaskList = query.finished().list()
.stream().distinct().map(HistoricActivityInstance::getActivityId)
.collect(Collectors.toList());
// 获取流程实例正在待办的节点
List<String> unfinishedTaskList = query.unfinished().list()
.stream().distinct().map(HistoricActivityInstance::getActivityId)
.collect(Collectors.toList());
// 构建视图类
return R.success(new FlowViewerVo(finishedTaskList, unfinishedTaskList));
}
/**
* 获取流程变量
*
* @param taskId
* @return
*/
@Override
public R processVariables(String taskId) {
// 流程变量
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
if (Objects.nonNull(historicTaskInstance)) {
return R.success(historicTaskInstance.getProcessVariables());
} else {
Map<String, Object> variables = taskService.getVariables(taskId);
return R.success(variables);
}
}
/**
* 获取下一节点
*
* @param flowTaskVo 任务
* @return
*/
@Override
public R getNextFlowNode(FlowTaskVo flowTaskVo) {
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
FlowNextDto flowNextDto = new FlowNextDto();
if (Objects.nonNull(task)) {
List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, new HashMap<>());
if (CollectionUtils.isNotEmpty(nextUserTask)) {
for (UserTask userTask : nextUserTask) {
MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics();
// 会签节点
if (Objects.nonNull(multiInstance)) {
List<SysUser> list = sysUserService.selectUserList(new SysUser());
flowNextDto.setVars(ProcessConstants.PROCESS_MULTI_INSTANCE_USER);
flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
flowNextDto.setUserList(list);
} else {
// 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
if (ProcessConstants.DATA_TYPE.equals(dataType)) {
// 指定单个人员
if (ProcessConstants.USER_TYPE_ASSIGNEE.equals(userType)) {
List<SysUser> list = sysUserService.selectUserList(new SysUser());
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(ProcessConstants.USER_TYPE_ASSIGNEE);
flowNextDto.setUserList(list);
}
// 候选人员(多个)
if (ProcessConstants.USER_TYPE_USERS.equals(userType)) {
List<SysUser> list = sysUserService.selectUserList(new SysUser());
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(ProcessConstants.USER_TYPE_USERS);
flowNextDto.setUserList(list);
}
// 候选组
if (ProcessConstants.USER_TYPE_ROUPS.equals(userType)) {
List<SysRole> sysRoles = sysRoleService.selectRoleAll();
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
flowNextDto.setType(ProcessConstants.USER_TYPE_ROUPS);
flowNextDto.setRoleList(sysRoles);
}
}
}
}
} else {
return R.success("流程已完结", null);
}
}
return R.success(flowNextDto);
}
/**
* 流程完成时间处理
*
* @param ms
* @return
*/
private String getDate(long ms) {
long day = ms / (24 * 60 * 60 * 1000);
long hour = (ms / (60 * 60 * 1000) - day * 24);
long minute = ((ms / (60 * 1000)) - day * 24 * 60 - hour * 60);
long second = (ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);
if (day > 0) {
return day + "" + hour + "小时" + minute + "分钟";
}
if (hour > 0) {
return hour + "小时" + minute + "分钟";
}
if (minute > 0) {
return minute + "分钟";
}
if (second > 0) {
return second + "";
} else {
return 0 + "";
}
}
}

View File

@@ -0,0 +1,106 @@
package com.ruoyi.workflow.service.impl;
import com.ruoyi.workflow.service.ISysDeployFormService;
import com.ruoyi.system.domain.SysDeployForm;
import com.ruoyi.system.domain.SysForm;
import com.ruoyi.system.mapper.SysDeployFormMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
/**
* 流程实例关联表单Service业务层处理
*
* @author XuanXuan Xuan
* @date 2021-04-03
*/
@Service
public class SysDeployFormServiceImpl implements ISysDeployFormService {
@Autowired
private SysDeployFormMapper sysDeployFormMapper;
/**
* 查询流程实例关联表单
*
* @param id 流程实例关联表单ID
* @return 流程实例关联表单
*/
@Override
public SysDeployForm selectSysDeployFormById(Long id) {
return sysDeployFormMapper.selectSysDeployFormById(id);
}
/**
* 查询流程实例关联表单列表
*
* @param sysDeployForm 流程实例关联表单
* @return 流程实例关联表单
*/
@Override
public List<SysDeployForm> selectSysDeployFormList(SysDeployForm sysDeployForm) {
return sysDeployFormMapper.selectSysDeployFormList(sysDeployForm);
}
/**
* 新增流程实例关联表单
*
* @param sysDeployForm 流程实例关联表单
* @return 结果
*/
@Override
public int insertSysDeployForm(SysDeployForm sysDeployForm) {
SysForm sysForm = sysDeployFormMapper.selectSysDeployFormByDeployId(sysDeployForm.getDeployId());
if (Objects.isNull(sysForm)) {
return sysDeployFormMapper.insertSysDeployForm(sysDeployForm);
} else {
return 1;
}
}
/**
* 修改流程实例关联表单
*
* @param sysDeployForm 流程实例关联表单
* @return 结果
*/
@Override
public int updateSysDeployForm(SysDeployForm sysDeployForm) {
return sysDeployFormMapper.updateSysDeployForm(sysDeployForm);
}
/**
* 批量删除流程实例关联表单
*
* @param ids 需要删除的流程实例关联表单ID
* @return 结果
*/
@Override
public int deleteSysDeployFormByIds(Long[] ids) {
return sysDeployFormMapper.deleteSysDeployFormByIds(ids);
}
/**
* 删除流程实例关联表单信息
*
* @param id 流程实例关联表单ID
* @return 结果
*/
@Override
public int deleteSysDeployFormById(Long id) {
return sysDeployFormMapper.deleteSysDeployFormById(id);
}
/**
* 查询流程挂着的表单
*
* @param deployId
* @return
*/
@Override
public SysForm selectSysDeployFormByDeployId(String deployId) {
return sysDeployFormMapper.selectSysDeployFormByDeployId(deployId);
}
}

View File

@@ -0,0 +1,104 @@
package com.ruoyi.workflow.service.impl;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.workflow.service.ISysFormService;
import com.ruoyi.system.domain.SysForm;
import com.ruoyi.system.mapper.SysFormMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 流程表单Service业务层处理
*
* @author XuanXuan Xuan
* @date 2021-04-03
*/
@Service
public class SysFormServiceImpl implements ISysFormService {
@Autowired
private SysFormMapper sysFormMapper;
/**
* 查询流程表单
*
* @param formId 流程表单ID
* @return 流程表单
*/
@Override
public SysForm selectSysFormById(Long formId) {
return sysFormMapper.selectSysFormById(formId);
}
/**
* 查询流程表单列表
*
* @param sysForm 流程表单
* @return 流程表单
*/
@Override
public TableDataInfo<SysForm> selectSysFormPage(SysForm sysForm, PageQuery pageQuery) {
return TableDataInfo.build(sysFormMapper.selectSysFormPage(pageQuery.build(), sysForm));
}
/**
* 查询流程表单列表
*
* @param sysForm 流程表单
* @return 流程表单
*/
@Override
public List<SysForm> selectSysFormList(SysForm sysForm) {
return sysFormMapper.selectSysFormList(sysForm);
}
/**
* 新增流程表单
*
* @param sysForm 流程表单
* @return 结果
*/
@Override
public int insertSysForm(SysForm sysForm) {
sysForm.setCreateTime(DateUtils.getNowDate());
return sysFormMapper.insertSysForm(sysForm);
}
/**
* 修改流程表单
*
* @param sysForm 流程表单
* @return 结果
*/
@Override
public int updateSysForm(SysForm sysForm) {
sysForm.setUpdateTime(DateUtils.getNowDate());
return sysFormMapper.updateSysForm(sysForm);
}
/**
* 批量删除流程表单
*
* @param formIds 需要删除的流程表单ID
* @return 结果
*/
@Override
public int deleteSysFormByIds(Long[] formIds) {
return sysFormMapper.deleteSysFormByIds(formIds);
}
/**
* 删除流程表单信息
*
* @param formId 流程表单ID
* @return 结果
*/
@Override
public int deleteSysFormById(Long formId) {
return sysFormMapper.deleteSysFormById(formId);
}
}

View File

@@ -0,0 +1,88 @@
package com.ruoyi.workflow.service.impl;
import com.ruoyi.workflow.service.ISysTaskFormService;
import com.ruoyi.system.domain.SysTaskForm;
import com.ruoyi.system.mapper.SysTaskFormMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 流程任务关联单Service业务层处理
*
* @author XuanXuan Xuan
* @date 2021-04-03
*/
@Service
public class SysTaskFormServiceImpl implements ISysTaskFormService {
@Autowired
private SysTaskFormMapper sysTaskFormMapper;
/**
* 查询流程任务关联单
*
* @param id 流程任务关联单ID
* @return 流程任务关联单
*/
@Override
public SysTaskForm selectSysTaskFormById(Long id) {
return sysTaskFormMapper.selectSysTaskFormById(id);
}
/**
* 查询流程任务关联单列表
*
* @param sysTaskForm 流程任务关联单
* @return 流程任务关联单
*/
@Override
public List<SysTaskForm> selectSysTaskFormList(SysTaskForm sysTaskForm) {
return sysTaskFormMapper.selectSysTaskFormList(sysTaskForm);
}
/**
* 新增流程任务关联单
*
* @param sysTaskForm 流程任务关联单
* @return 结果
*/
@Override
public int insertSysTaskForm(SysTaskForm sysTaskForm) {
return sysTaskFormMapper.insertSysTaskForm(sysTaskForm);
}
/**
* 修改流程任务关联单
*
* @param sysTaskForm 流程任务关联单
* @return 结果
*/
@Override
public int updateSysTaskForm(SysTaskForm sysTaskForm) {
return sysTaskFormMapper.updateSysTaskForm(sysTaskForm);
}
/**
* 批量删除流程任务关联单
*
* @param ids 需要删除的流程任务关联单ID
* @return 结果
*/
@Override
public int deleteSysTaskFormByIds(Long[] ids) {
return sysTaskFormMapper.deleteSysTaskFormByIds(ids);
}
/**
* 删除流程任务关联单信息
*
* @param id 流程任务关联单ID
* @return 结果
*/
@Override
public int deleteSysTaskFormById(Long id) {
return sysTaskFormMapper.deleteSysTaskFormById(id);
}
}