158 changed files with 16963 additions and 1 deletions
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<parent> |
||||
<artifactId>common</artifactId> |
||||
<groupId>apelet</groupId> |
||||
<version>1.0.0</version> |
||||
</parent> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<artifactId>common-flow</artifactId> |
||||
<version>1.0.0</version> |
||||
<name>common-flow</name> |
||||
<packaging>jar</packaging> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>apelet</groupId> |
||||
<artifactId>common-datafilter</artifactId> |
||||
<version>1.0.0</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>apelet</groupId> |
||||
<artifactId>common-sequence</artifactId> |
||||
<version>1.0.0</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>apelet</groupId> |
||||
<artifactId>common-log</artifactId> |
||||
<version>1.0.0</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>apelet</groupId> |
||||
<artifactId>common-swagger</artifactId> |
||||
<version>1.0.0</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.flowable</groupId> |
||||
<artifactId>flowable-spring-boot-starter-basic</artifactId> |
||||
<version>${flowable.version}</version> |
||||
</dependency> |
||||
</dependencies> |
||||
</project> |
||||
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
package apelet.common.flow.Plugin; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class AbstractAssigneePlugin { |
||||
|
||||
public List<String> userStr = new ArrayList<>(); |
||||
|
||||
public void getFlowNodeUser(String parame){} |
||||
} |
||||
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
package apelet.common.flow.Plugin; |
||||
|
||||
public class DemoFlowNodePlugin extends AbstractAssigneePlugin{ |
||||
|
||||
@Override |
||||
public void getFlowNodeUser(String parame) { |
||||
System.out.println("-----------DemoFlowNodePlugin:"+parame); |
||||
this.userStr.add("650"); |
||||
} |
||||
} |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
package apelet.common.flow.Plugin; |
||||
|
||||
import com.alibaba.fastjson.JSONArray; |
||||
import com.alibaba.fastjson.JSONObject; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* |
||||
* 流程实例中表达式解析工具 |
||||
*/ |
||||
@Component |
||||
@Slf4j |
||||
public class FlowNodeExpressionUtil { |
||||
|
||||
public String getAssigneeByPlugin( String parame){ |
||||
|
||||
List<String> list = new ArrayList<>(); |
||||
String returnStr=","; |
||||
try { |
||||
//parame = URLDecoder.decode(parame,"UTF-8");
|
||||
JSONArray josnarr = JSONArray.parseArray(parame); |
||||
for(int i=0;i<josnarr.size();i++){ |
||||
JSONObject jsono = josnarr.getJSONObject(i); |
||||
Class<?> aClass = Class.forName(jsono.getString("pluginType")); |
||||
Method method = aClass.getMethod("getFlowNodeUser", String.class); |
||||
Object object = aClass.newInstance(); |
||||
method.invoke(object, jsono.toString()); |
||||
list.addAll((List<String>) aClass.getSuperclass().getDeclaredField("userStr").get(object)); |
||||
} |
||||
if(list.size()>0){ |
||||
for(int i=0;i<list.size();i++){ |
||||
returnStr=returnStr+list.get(i); |
||||
} |
||||
} |
||||
returnStr = returnStr.substring(1); |
||||
|
||||
|
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return returnStr; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
package apelet.common.flow.advice; |
||||
|
||||
import apelet.common.core.constant.ErrorCodeEnum; |
||||
import apelet.common.core.object.ResponseResult; |
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.core.util.ContextUtil; |
||||
import apelet.common.flow.exception.FlowEmptyUserException; |
||||
import apelet.common.flow.model.FlowTaskComment; |
||||
import apelet.common.flow.service.FlowTaskCommentService; |
||||
import com.alibaba.fastjson.JSON; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.common.engine.api.FlowableException; |
||||
import org.springframework.core.annotation.Order; |
||||
import org.springframework.web.bind.annotation.ExceptionHandler; |
||||
import org.springframework.web.bind.annotation.RestControllerAdvice; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
|
||||
/** |
||||
* 流程业务层的异常处理类。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
@Order(1) |
||||
@RestControllerAdvice("apelet") |
||||
public class FlowExceptionHandler { |
||||
|
||||
private final transient FlowTaskCommentService flowTaskCommentService = |
||||
ApplicationContextHolder.getBean(FlowTaskCommentService.class); |
||||
|
||||
@ExceptionHandler(value = FlowableException.class) |
||||
public ResponseResult<Void> exceptionHandle(FlowableException ex, HttpServletRequest request) { |
||||
FlowEmptyUserException flowEmptyUserException = this.findCause(ex, FlowEmptyUserException.class); |
||||
if (flowEmptyUserException != null) { |
||||
FlowTaskComment comment = JSON.parseObject(flowEmptyUserException.getMessage(), FlowTaskComment.class); |
||||
flowTaskCommentService.saveNew(comment); |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, "下一个任务节点的审批人为空,提交被自动驳回!"); |
||||
} |
||||
log.error("Unhandled FlowException from URL [" + request.getRequestURI() + "]", ex); |
||||
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); |
||||
return ResponseResult.error(ErrorCodeEnum.UNHANDLED_EXCEPTION, ex.getMessage()); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private <T extends Exception> T findCause(Throwable ex, Class<T> clazz) { |
||||
if (ex.getCause() == null) { |
||||
return null; |
||||
} |
||||
if (ex.getCause().getClass().equals(clazz)) { |
||||
return (T) ex.getCause(); |
||||
} else { |
||||
return this.findCause(ex.getCause(), clazz); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
package apelet.common.flow.base.service; |
||||
|
||||
import apelet.common.flow.model.FlowWorkOrder; |
||||
|
||||
/** |
||||
* 工作流在线表单的服务接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface BaseFlowOnlineService { |
||||
|
||||
/** |
||||
* 更新在线表单主表数据的流程状态字段值。 |
||||
* |
||||
* @param workOrder 工单对象。 |
||||
*/ |
||||
void updateFlowStatus(FlowWorkOrder workOrder); |
||||
|
||||
/** |
||||
* 根据工单对象级联删除业务数据。 |
||||
* |
||||
* @param workOrder 工单对象。 |
||||
*/ |
||||
void deleteBusinessData(FlowWorkOrder workOrder); |
||||
} |
||||
@ -0,0 +1,273 @@
@@ -0,0 +1,273 @@
|
||||
package apelet.common.flow.base.service; |
||||
|
||||
import apelet.common.core.base.service.BaseService; |
||||
import apelet.common.core.exception.MyRuntimeException; |
||||
import apelet.common.core.object.CallResult; |
||||
import apelet.common.core.object.MyRelationParam; |
||||
import apelet.common.core.util.MyDateUtil; |
||||
import apelet.common.core.util.MyModelUtil; |
||||
import apelet.common.flow.constant.FlowApprovalType; |
||||
import apelet.common.flow.constant.FlowConstant; |
||||
import apelet.common.flow.constant.FlowTaskStatus; |
||||
import apelet.common.flow.exception.FlowOperationException; |
||||
import apelet.common.flow.model.FlowTaskComment; |
||||
import apelet.common.flow.model.FlowWorkOrder; |
||||
import apelet.common.flow.model.FlowWorkOrderExt; |
||||
import apelet.common.flow.service.FlowApiService; |
||||
import apelet.common.flow.service.FlowWorkOrderService; |
||||
import apelet.common.flow.vo.FlowWorkOrderVo; |
||||
import apelet.common.redis.cache.SessionCacheHelper; |
||||
import cn.hutool.core.bean.BeanUtil; |
||||
import cn.hutool.core.collection.CollUtil; |
||||
import cn.hutool.core.map.MapUtil; |
||||
import cn.hutool.core.text.StrFormatter; |
||||
import cn.hutool.core.util.ReflectUtil; |
||||
import com.alibaba.fastjson.JSON; |
||||
import com.alibaba.fastjson.JSONObject; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.runtime.ProcessInstance; |
||||
import org.flowable.task.api.Task; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.transaction.annotation.Transactional; |
||||
|
||||
import java.io.Serializable; |
||||
import java.lang.reflect.Field; |
||||
import java.util.*; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* 路由表单工作流服务抽象类。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public abstract class BaseFlowService<M, K extends Serializable> extends BaseService<M, K> { |
||||
|
||||
@Autowired |
||||
private FlowApiService flowApiService; |
||||
@Autowired |
||||
private FlowWorkOrderService flowWorkOrderService; |
||||
@Autowired |
||||
private SessionCacheHelper cacheHelper; |
||||
|
||||
@Transactional(rollbackFor = Exception.class) |
||||
public void startWithBusinessKey(String processDefinitionId, K dataId) { |
||||
ProcessInstance instance = flowApiService.start(processDefinitionId, dataId); |
||||
flowWorkOrderService.saveNew(instance, dataId, null, super.tableName); |
||||
} |
||||
|
||||
@Transactional(rollbackFor = Exception.class) |
||||
public void startAndTakeFirst( |
||||
String processDefinitionId, K dataId, FlowTaskComment comment, JSONObject variables) { |
||||
ProcessInstance instance = flowApiService.start(processDefinitionId, dataId); |
||||
flowWorkOrderService.saveNew(instance, dataId, null, super.tableName); |
||||
flowApiService.takeFirstTask(instance.getProcessInstanceId(), comment, variables); |
||||
// 这里需要在创建工单后再次更新一下工单状态,在flowApiService.completeTask中的更新,
|
||||
// 因为当时没有创建工单对象,更新会不起任何作用,所以这里要补偿一下。
|
||||
Integer approvalStatus = MapUtil.getInt(variables, FlowConstant.LATEST_APPROVAL_STATUS_KEY); |
||||
flowWorkOrderService.updateLatestApprovalStatusByProcessInstanceId(instance.getId(), approvalStatus); |
||||
} |
||||
|
||||
@Transactional(rollbackFor = Exception.class) |
||||
public FlowWorkOrder saveNewDraftAndStartProcess(String processDefinitionId, String masterData, String slaveData) { |
||||
ProcessInstance instance = flowApiService.start(processDefinitionId, null); |
||||
Map<String, Object> variableMap = flowApiService.initAndGetProcessInstanceVariables(processDefinitionId); |
||||
flowApiService.setProcessInstanceVariables(instance.getProcessInstanceId(), variableMap); |
||||
return flowWorkOrderService.saveNewWithDraft(instance, null, super.tableName, masterData, slaveData); |
||||
} |
||||
|
||||
@Transactional(rollbackFor = Exception.class) |
||||
public void takeFirstTask( |
||||
String processInstanceId, String taskId, K dataId, FlowTaskComment comment, JSONObject variables) { |
||||
Task task = flowApiService.getProcessInstanceActiveTask(processInstanceId, taskId); |
||||
flowApiService.setBusinessKeyForProcessInstance(processInstanceId, dataId); |
||||
ProcessInstance instance = flowApiService.getProcessInstance(processInstanceId); |
||||
FlowWorkOrder flowWorkOrder = |
||||
flowWorkOrderService.getFlowWorkOrderByProcessInstanceId(instance.getProcessInstanceId()); |
||||
if (flowWorkOrder == null) { |
||||
flowWorkOrderService.saveNew(instance, dataId, null, super.tableName); |
||||
} else { |
||||
flowWorkOrder.setBusinessKey(dataId.toString()); |
||||
flowWorkOrder.setUpdateTime(new Date()); |
||||
flowWorkOrder.setFlowStatus(FlowTaskStatus.SUBMITTED); |
||||
flowWorkOrderService.updateById(flowWorkOrder); |
||||
} |
||||
flowApiService.completeTask(task, comment, variables, null); |
||||
} |
||||
|
||||
@Transactional(rollbackFor = Exception.class) |
||||
public void takeTask(Task task, K dataId, FlowTaskComment comment, JSONObject variables) { |
||||
int flowStatus = FlowTaskStatus.APPROVING; |
||||
if (comment.getApprovalType().equals(FlowApprovalType.REFUSE)) { |
||||
flowStatus = FlowTaskStatus.REFUSED; |
||||
} else if (comment.getApprovalType().equals(FlowApprovalType.STOP)) { |
||||
flowStatus = FlowTaskStatus.FINISHED; |
||||
} |
||||
if (comment.getApprovalType().equals(FlowApprovalType.STOP)) { |
||||
Integer s = MapUtil.getInt(variables, FlowConstant.LATEST_APPROVAL_STATUS_KEY); |
||||
flowWorkOrderService.updateLatestApprovalStatusByProcessInstanceId(task.getProcessInstanceId(), s); |
||||
CallResult stopResult = flowApiService.stopProcessInstance( |
||||
task.getProcessInstanceId(), comment.getTaskComment(), flowStatus); |
||||
if (!stopResult.isSuccess()) { |
||||
throw new FlowOperationException(stopResult.getErrorMessage()); |
||||
} |
||||
} else { |
||||
flowWorkOrderService.updateFlowStatusByProcessInstanceId(task.getProcessInstanceId(), flowStatus); |
||||
flowApiService.completeTask(task, comment, variables, null); |
||||
} |
||||
} |
||||
|
||||
public void buildDraftData(List<FlowWorkOrderVo> draftWorkOrderList) { |
||||
if (CollUtil.isEmpty(draftWorkOrderList)) { |
||||
return; |
||||
} |
||||
Set<Long> workOrderIdSet = draftWorkOrderList.stream() |
||||
.map(FlowWorkOrderVo::getWorkOrderId).collect(Collectors.toSet()); |
||||
Map<Long, FlowWorkOrderExt> workOrderExtMap = |
||||
flowWorkOrderService.getFlowWorkOrderExtByWorkOrderIds(workOrderIdSet) |
||||
.stream().collect(Collectors.toMap(FlowWorkOrderExt::getWorkOrderId, c -> c)); |
||||
for (FlowWorkOrderVo workOrder : draftWorkOrderList) { |
||||
FlowWorkOrderExt workOrderExt = workOrderExtMap.get(workOrder.getWorkOrderId()); |
||||
if (workOrderExt == null) { |
||||
continue; |
||||
} |
||||
JSONObject draftData = JSON.parseObject(workOrderExt.getDraftData()); |
||||
JSONObject masterData = draftData.getJSONObject(FlowConstant.MASTER_DATA_KEY); |
||||
JSONObject slaveData = draftData.getJSONObject(FlowConstant.SLAVE_DATA_KEY); |
||||
M model; |
||||
if (masterData != null) { |
||||
model = masterData.toJavaObject(modelClass); |
||||
super.buildRelationForData(model, MyRelationParam.dictOnly()); |
||||
} else { |
||||
model = ReflectUtil.newInstance(modelClass); |
||||
} |
||||
this.bindLocalOneToOneSlaveData(model, slaveData); |
||||
super.buildLocalOneToOneDictOnly(model); |
||||
workOrder.setMasterData(BeanUtil.beanToMap(model)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 在流程实例审批结束后,需要进行审批表到发布表数据同步的服务实现子类,需要实现该方法。 |
||||
* |
||||
* @param workOrder 工单对象。 |
||||
*/ |
||||
public void syncBusinessData(FlowWorkOrder workOrder) { |
||||
// 请自行在子类中实现当前service的数据同步逻辑。
|
||||
} |
||||
|
||||
/** |
||||
* 在流程实例审批结束后,需要进行业务表的状态更新,业务Service需要实现该方法。 |
||||
* |
||||
* @param workOrder 工单对象。 |
||||
*/ |
||||
public void updateFlowStatus(FlowWorkOrder workOrder) { |
||||
if (flowStatusField == null && flowLatestApprovalStatusField == null) { |
||||
return; |
||||
} |
||||
Serializable id = this.convertToKeyValue(workOrder.getBusinessKey()); |
||||
M data = this.getById(id); |
||||
if (data == null) { |
||||
String msg = StrFormatter.format( |
||||
"WorkOrderId [{}] don't find business data by key [{}] while calling [updateFlowStatus].", |
||||
workOrder.getWorkOrderId(), workOrder.getBusinessKey()); |
||||
log.warn(msg); |
||||
return; |
||||
} |
||||
if (flowStatusField != null) { |
||||
ReflectUtil.setFieldValue(data, flowStatusField, workOrder.getFlowStatus()); |
||||
} |
||||
if (flowLatestApprovalStatusField != null) { |
||||
ReflectUtil.setFieldValue(data, flowLatestApprovalStatusField, workOrder.getLatestApprovalStatus()); |
||||
} |
||||
mapper().updateById(data); |
||||
} |
||||
|
||||
/** |
||||
* 根据工单对象删除流程业务数据。 |
||||
* |
||||
* @param workOrder 工单对象。 |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public void removeByWorkOrder(FlowWorkOrder workOrder) { |
||||
Serializable id = this.convertToKeyValue(workOrder.getBusinessKey()); |
||||
M data = this.getById(id); |
||||
if (data == null) { |
||||
String msg = StrFormatter.format( |
||||
"WorkOrderId [{}] don't find business data by key [{}] while calling [removeByWorkOrder].", |
||||
workOrder.getWorkOrderId(), workOrder.getBusinessKey()); |
||||
log.warn(msg); |
||||
return; |
||||
} |
||||
// 级联删除业务数据,调用的是橙单默认生成的remove方法,参数类型为主键类型,如Long、String等。
|
||||
// 进一步补充说明,橙单默认生成的remove方法,会根据在生成器中的配置,生成关联从表数据的级联删除代码。
|
||||
this.remove((K) id); |
||||
} |
||||
|
||||
/** |
||||
* 获取业务详情数据。 |
||||
* |
||||
* @param processInstanceId 流程实例Id。 |
||||
* @param businessKey 业务主键Id。如果与实际主键值类型不同,需要在子类中自行完成类型转换。 |
||||
* @return 业务主表数据,以及关联从表数据。 |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public String getBusinessData(String processInstanceId, String businessKey) { |
||||
Serializable id = this.convertToKeyValue(businessKey); |
||||
M data = this.getByIdWithRelation((K) id, MyRelationParam.full()); |
||||
return JSON.toJSONStringWithDateFormat(data, MyDateUtil.COMMON_SHORT_DATETIME_FORMAT); |
||||
} |
||||
|
||||
/** |
||||
* 规格化工单扩展表中保存的草稿数据。如果仅仅包含主表数据,可以使用当前的缺省实现。 |
||||
* |
||||
* @param processInstanceId 流程实例Id。 |
||||
* @param masterData 草稿中的主表数据。 |
||||
* @param slaveData 草稿中的全部关联从表数据。 |
||||
* @return 格式化后用于前端显示的业务草稿数据。 |
||||
*/ |
||||
public String getNormalizedDraftData(String processInstanceId, JSONObject masterData, JSONObject slaveData) { |
||||
// 看到这个异常千万别慌,这是及时的提示您,如果草稿中包含了关联从表数据,就一定要在业务的ServiceImpl中实现该方法。
|
||||
// 在子类中实现主表和关联从表数据的数据组装。通用的方法中,只能解析主表数据,关联从表各式各样,所以需要在子类中实现。
|
||||
if (slaveData != null) { |
||||
throw new UnsupportedOperationException( |
||||
"Please implement getNormalizedDraftData by self, because draft data includes related slaveData"); |
||||
} |
||||
if (masterData == null) { |
||||
return JSON.toJSONString(ReflectUtil.newInstance(modelClass)); |
||||
} |
||||
M model = BeanUtil.toBean(masterData, modelClass); |
||||
// 这里会缺省缓存主表中上传字段的下载地址,以便在显示草稿数据时,这些上传字段对应的download方法,不会被数据权限过滤。
|
||||
Set<String> cachedDownableFilename = |
||||
new HashSet<>(MyModelUtil.extractDownloadFileName(model, modelClass)); |
||||
cacheHelper.putSessionDownloadableFileNameSet(cachedDownableFilename); |
||||
return JSON.toJSONStringWithDateFormat(model, MyDateUtil.COMMON_SHORT_DATETIME_FORMAT); |
||||
} |
||||
|
||||
private Serializable convertToKeyValue(String businessKey) { |
||||
if (idFieldClass.equals(String.class)) { |
||||
return businessKey; |
||||
} else if (idFieldClass.equals(Long.class)) { |
||||
return Long.valueOf(businessKey); |
||||
} else if (idFieldClass.equals(Integer.class)) { |
||||
return Integer.valueOf(businessKey); |
||||
} else { |
||||
throw new MyRuntimeException("Unsupported Primary Key Field Type."); |
||||
} |
||||
} |
||||
|
||||
private void bindLocalOneToOneSlaveData(M model, JSONObject slaveData) { |
||||
if (slaveData == null) { |
||||
return; |
||||
} |
||||
for (BaseService.RelationStruct relationStruct : super.localRelationOneToOneStructList) { |
||||
Field relationField = relationStruct.getRelationField(); |
||||
JSONObject slaveObject = slaveData.getJSONObject(relationField.getName()); |
||||
if (slaveObject != null) { |
||||
ReflectUtil.setFieldValue(model, relationField, |
||||
slaveObject.toJavaObject(relationStruct.getRelationOneToOne().slaveModelClass())); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
package apelet.common.flow.cmd; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import org.flowable.common.engine.api.delegate.Expression; |
||||
import org.flowable.common.engine.api.variable.VariableContainer; |
||||
import org.flowable.common.engine.impl.el.VariableContainerWrapper; |
||||
import org.flowable.common.engine.impl.interceptor.Command; |
||||
import org.flowable.common.engine.impl.interceptor.CommandContext; |
||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; |
||||
import org.flowable.engine.impl.util.CommandContextUtil; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* EL表达式解析和执行的命令。 |
||||
* |
||||
* @author guifc |
||||
* @date 2024-08-27 |
||||
*/ |
||||
@AllArgsConstructor |
||||
public class ExpressionCmd implements Command<Object> { |
||||
|
||||
private String executionId; |
||||
private String exp; |
||||
|
||||
@Override |
||||
public Object execute(CommandContext commandContext) { |
||||
ProcessEngineConfigurationImpl cfg = CommandContextUtil.getProcessEngineConfiguration(commandContext); |
||||
Expression expression = cfg.getExpressionManager().createExpression(exp); |
||||
Map<String, Object> variables = cfg.getRuntimeService().getVariables(executionId); |
||||
VariableContainer variableContainer = new VariableContainerWrapper(variables); |
||||
return cfg.getManagementService().executeCommand(cc -> expression.getValue(variableContainer)); |
||||
} |
||||
} |
||||
@ -0,0 +1,162 @@
@@ -0,0 +1,162 @@
|
||||
package apelet.common.flow.cmd; |
||||
|
||||
import cn.hutool.core.collection.CollUtil; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import com.alibaba.fastjson.JSON; |
||||
import lombok.AllArgsConstructor; |
||||
import org.flowable.bpmn.model.BpmnModel; |
||||
import org.flowable.bpmn.model.Process; |
||||
import org.flowable.bpmn.model.StartEvent; |
||||
import org.flowable.common.engine.api.FlowableException; |
||||
import org.flowable.common.engine.api.FlowableIllegalArgumentException; |
||||
import org.flowable.common.engine.impl.interceptor.Command; |
||||
import org.flowable.common.engine.impl.interceptor.CommandContext; |
||||
import org.flowable.engine.HistoryService; |
||||
import org.flowable.engine.ProcessEngineConfiguration; |
||||
import org.flowable.engine.history.HistoricProcessInstance; |
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity; |
||||
import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntityImpl; |
||||
import org.flowable.engine.impl.util.CommandContextUtil; |
||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil; |
||||
import org.flowable.engine.repository.ProcessDefinition; |
||||
import org.flowable.engine.runtime.ChangeActivityStateBuilder; |
||||
import org.flowable.engine.runtime.ProcessInstance; |
||||
import org.flowable.variable.api.history.HistoricVariableInstance; |
||||
|
||||
import java.util.*; |
||||
|
||||
/** |
||||
* 流程复活命令对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@AllArgsConstructor |
||||
public class RestartProcessInstanceCmd implements Command<ProcessInstance> { |
||||
|
||||
/** |
||||
* 待复活的流程实例编号 |
||||
*/ |
||||
protected String processInstanceId; |
||||
/** |
||||
* 要复活到的节点列表 |
||||
*/ |
||||
protected List<String> activityIds; |
||||
/** |
||||
* 流程任务标识和变量数据的Map。 |
||||
*/ |
||||
protected Map<String, String> variableMap; |
||||
|
||||
@Override |
||||
public ProcessInstance execute(CommandContext commandContext) { |
||||
ProcessEngineConfiguration engineConfig = CommandContextUtil.getProcessEngineConfiguration(commandContext); |
||||
HistoryService historyService = engineConfig.getHistoryService(); |
||||
//校验和查询历史流程实例
|
||||
HistoricProcessInstance historicProcessInstance = this.checkAndGetHistoricProcessInstance(historyService); |
||||
//校验待复活节点
|
||||
this.checkActivityIds(historicProcessInstance.getProcessDefinitionId()); |
||||
//校验流程定义
|
||||
ProcessDefinition processDefinition = |
||||
ProcessDefinitionUtil.getProcessDefinition(historicProcessInstance.getProcessDefinitionId()); |
||||
if (processDefinition == null) { |
||||
throw new FlowableException("流程定义不存在"); |
||||
} |
||||
//获取流程启动节点
|
||||
Process process = ProcessDefinitionUtil.getProcess(processDefinition.getId()); |
||||
StartEvent initialFlowElement = (StartEvent) process.getInitialFlowElement(); |
||||
//重建运行时流程实例的主执行实例
|
||||
ExecutionEntity processInstance = |
||||
this.recreateProcessInstance(processDefinition, initialFlowElement, historicProcessInstance); |
||||
//创建子执行实例
|
||||
ExecutionEntity childExecution = |
||||
CommandContextUtil.getExecutionEntityManager().createChildExecution(processInstance); |
||||
childExecution.setCurrentFlowElement(initialFlowElement); |
||||
//重建运行时流程变量
|
||||
//设置历史流程实例结束节点和结束时间为空
|
||||
((HistoricProcessInstanceEntityImpl) historicProcessInstance).setEndActivityId(null); |
||||
((HistoricProcessInstanceEntityImpl) historicProcessInstance).setEndTime(null); |
||||
Map<String, Object> gloablVariables = this.collectVariables(historyService, historicProcessInstance); |
||||
//执行动态跳转
|
||||
ChangeActivityStateBuilder builder = engineConfig.getRuntimeService() |
||||
.createChangeActivityStateBuilder() |
||||
.processInstanceId(processInstance.getProcessInstanceId()) |
||||
.moveSingleExecutionToActivityIds(childExecution.getId(), activityIds) |
||||
.processVariables(gloablVariables); |
||||
for (String activityId : activityIds) { |
||||
String variableData = variableMap.get(activityId); |
||||
if (StrUtil.isNotBlank(variableData)) { |
||||
builder.localVariables(activityId, JSON.parseObject(variableData)); |
||||
} |
||||
} |
||||
builder.changeState(); |
||||
return engineConfig.getRuntimeService() |
||||
.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult(); |
||||
} |
||||
|
||||
private HistoricProcessInstance checkAndGetHistoricProcessInstance(HistoryService historyService) { |
||||
if (StrUtil.isBlank(processInstanceId)) { |
||||
throw new FlowableIllegalArgumentException("processInstanceId不能为空"); |
||||
} |
||||
HistoricProcessInstance historicProcessInstance = historyService |
||||
.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); |
||||
if (historicProcessInstance == null) { |
||||
throw new FlowableException("id为" + processInstanceId + "的流程实例不存在"); |
||||
} else if (historicProcessInstance != null && historicProcessInstance.getEndTime() == null) { |
||||
throw new FlowableException("id为" + processInstanceId + "的流程实例没有结束"); |
||||
} |
||||
return historicProcessInstance; |
||||
} |
||||
|
||||
private void checkActivityIds(String processDefinitionId) { |
||||
if (CollUtil.isEmpty(activityIds)) { |
||||
throw new FlowableIllegalArgumentException("activityIds不能为空"); |
||||
} |
||||
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId); |
||||
List<String> notExistedFlowElements = new ArrayList<>(); |
||||
for (String activityId : activityIds) { |
||||
if (!bpmnModel.getMainProcess().containsFlowElementId(activityId)) { |
||||
notExistedFlowElements.add(activityId); |
||||
} |
||||
} |
||||
if (!CollUtil.isEmpty(notExistedFlowElements)) { |
||||
throw new FlowableIllegalArgumentException("Id为" + String.join("、", notExistedFlowElements) + "节点不存在"); |
||||
} |
||||
} |
||||
|
||||
private ExecutionEntity recreateProcessInstance( |
||||
ProcessDefinition processDefinition, |
||||
StartEvent initialFlowElement, |
||||
HistoricProcessInstance historicProcessInstance) { |
||||
//创建流程实例
|
||||
ExecutionEntity executionEntity = CommandContextUtil.getExecutionEntityManager() |
||||
.createProcessInstanceExecution(processDefinition, |
||||
historicProcessInstance.getId(), |
||||
historicProcessInstance.getBusinessKey(), |
||||
historicProcessInstance.getBusinessStatus(), |
||||
historicProcessInstance.getName(), |
||||
historicProcessInstance.getCallbackId(), |
||||
historicProcessInstance.getCallbackType(), |
||||
historicProcessInstance.getReferenceId(), |
||||
historicProcessInstance.getReferenceType(), |
||||
null, |
||||
historicProcessInstance.getTenantId(), |
||||
initialFlowElement.getInitiator(), |
||||
historicProcessInstance.getStartActivityId()); |
||||
//重设流程开始事件
|
||||
executionEntity.setStartTime(historicProcessInstance.getStartTime()); |
||||
return executionEntity; |
||||
} |
||||
|
||||
private Map<String, Object> collectVariables( |
||||
HistoryService historyService, HistoricProcessInstance historicProcessInstance) { |
||||
Map<String, Object> variables = new HashMap<>(10); |
||||
List<HistoricVariableInstance> historicVariables = historyService |
||||
.createHistoricVariableInstanceQuery() |
||||
.processInstanceId(historicProcessInstance.getId()) |
||||
.executionId(historicProcessInstance.getId()).list(); |
||||
for (HistoricVariableInstance historicVariable : historicVariables) { |
||||
variables.put(historicVariable.getVariableName(), historicVariable.getValue()); |
||||
} |
||||
return variables; |
||||
} |
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
package apelet.common.flow.config; |
||||
|
||||
import apelet.common.core.config.DynamicDataSource; |
||||
import apelet.common.core.constant.ApplicationConstant; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.common.engine.impl.AbstractEngineConfiguration; |
||||
import org.flowable.common.engine.impl.EngineConfigurator; |
||||
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; |
||||
|
||||
import javax.sql.DataSource; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 服务启动过程中动态切换flowable引擎内置表所在的数据源。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class CustomEngineConfigurator implements EngineConfigurator { |
||||
|
||||
@Override |
||||
public void beforeInit(AbstractEngineConfiguration engineConfiguration) { |
||||
DataSource dataSource = engineConfiguration.getDataSource(); |
||||
if (dataSource instanceof TransactionAwareDataSourceProxy) { |
||||
TransactionAwareDataSourceProxy proxy = (TransactionAwareDataSourceProxy) dataSource; |
||||
DataSource targetDataSource = proxy.getTargetDataSource(); |
||||
if (targetDataSource instanceof DynamicDataSource) { |
||||
DynamicDataSource dynamicDataSource = (DynamicDataSource) targetDataSource; |
||||
Map<Object, DataSource> dynamicDataSourceMap = dynamicDataSource.getResolvedDataSources(); |
||||
DataSource flowDataSource = dynamicDataSourceMap.get(ApplicationConstant.COMMON_FLOW_AND_ONLINE_DATASOURCE_TYPE); |
||||
if (flowDataSource != null) { |
||||
engineConfiguration.setDataSource(flowDataSource); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void configure(AbstractEngineConfiguration engineConfiguration) { |
||||
// 默认实现。
|
||||
} |
||||
|
||||
@Override |
||||
public int getPriority() { |
||||
return 0; |
||||
} |
||||
} |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
package apelet.common.flow.config; |
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; |
||||
|
||||
/** |
||||
* common-flow模块的自动配置引导类。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@EnableConfigurationProperties({FlowProperties.class}) |
||||
public class FlowAutoConfig { |
||||
} |
||||
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
package apelet.common.flow.config; |
||||
|
||||
import lombok.Data; |
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
|
||||
/** |
||||
* 工作流的配置对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@ConfigurationProperties(prefix = "common-flow") |
||||
public class FlowProperties { |
||||
|
||||
/** |
||||
* 工作落工单操作接口的URL前缀。 |
||||
*/ |
||||
private String urlPrefix; |
||||
} |
||||
@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
|
||||
package apelet.common.flow.constant; |
||||
|
||||
/** |
||||
* 工作流任务触发BUTTON。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public final class FlowApprovalType { |
||||
|
||||
/** |
||||
* 保存。 |
||||
*/ |
||||
public static final String SAVE = "save"; |
||||
/** |
||||
* 同意。 |
||||
*/ |
||||
public static final String AGREE = "agree"; |
||||
/** |
||||
* 拒绝。 |
||||
*/ |
||||
public static final String REFUSE = "refuse"; |
||||
/** |
||||
* 驳回。 |
||||
*/ |
||||
public static final String REJECT = "reject"; |
||||
/** |
||||
* 撤销。 |
||||
*/ |
||||
public static final String REVOKE = "revoke"; |
||||
/** |
||||
* 指派。 |
||||
*/ |
||||
public static final String TRANSFER = "transfer"; |
||||
/** |
||||
* 多实例会签。 |
||||
*/ |
||||
public static final String MULTI_SIGN = "multi_sign"; |
||||
/** |
||||
* 会签同意。 |
||||
*/ |
||||
public static final String MULTI_AGREE = "multi_agree"; |
||||
/** |
||||
* 会签拒绝。 |
||||
*/ |
||||
public static final String MULTI_REFUSE = "multi_refuse"; |
||||
/** |
||||
* 会签弃权。 |
||||
*/ |
||||
public static final String MULTI_ABSTAIN = "multi_abstain"; |
||||
/** |
||||
* 多实例加签。 |
||||
*/ |
||||
public static final String MULTI_CONSIGN = "multi_consign"; |
||||
/** |
||||
* 多实例减签。 |
||||
*/ |
||||
public static final String MULTI_MINUS_SIGN = "multi_minus_sign"; |
||||
/** |
||||
* 中止。 |
||||
*/ |
||||
public static final String STOP = "stop"; |
||||
/** |
||||
* 干预。 |
||||
*/ |
||||
public static final String INTERVENE = "intervene"; |
||||
/** |
||||
* 自由跳转。 |
||||
*/ |
||||
public static final String FREE_JUMP = "free_jump"; |
||||
/** |
||||
* 流程复活。 |
||||
*/ |
||||
public static final String REUSED = "reused"; |
||||
/** |
||||
* 流程复活。 |
||||
*/ |
||||
public static final String REVIVE = "revive"; |
||||
/** |
||||
* 超时自动审批。 |
||||
*/ |
||||
public static final String TIMEOUT_AUTO_COMPLETE = "timeout_auto_complete"; |
||||
/** |
||||
* 空审批人自动审批。 |
||||
*/ |
||||
public static final String EMPTY_USER_AUTO_COMPLETE = "empty_user_auto_complete"; |
||||
/** |
||||
* 空审批人自动退回。 |
||||
*/ |
||||
public static final String EMPTY_USER_AUTO_REJECT = "empty_user_auto_reject"; |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowApprovalType() { |
||||
} |
||||
} |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
package apelet.common.flow.constant; |
||||
|
||||
/** |
||||
* 待办任务回退类型。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public final class FlowBackType { |
||||
|
||||
/** |
||||
* 驳回。 |
||||
*/ |
||||
public static final int REJECT = 0; |
||||
/** |
||||
* 撤回。 |
||||
*/ |
||||
public static final int REVOKE = 1; |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowBackType() { |
||||
} |
||||
} |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
package apelet.common.flow.constant; |
||||
|
||||
/** |
||||
* 内置的流程审批状态。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public class FlowBuiltinApprovalStatus { |
||||
|
||||
/** |
||||
* 同意。 |
||||
*/ |
||||
public static final int AGREED = 1; |
||||
/** |
||||
* 拒绝。 |
||||
*/ |
||||
public static final int REFUSED = 2; |
||||
/** |
||||
* 会签同意。 |
||||
*/ |
||||
public static final int MULTI_AGREED = 3; |
||||
/** |
||||
* 会签拒绝。 |
||||
*/ |
||||
public static final int MULTI_REFUSED = 4; |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowBuiltinApprovalStatus() { |
||||
} |
||||
} |
||||
@ -0,0 +1,266 @@
@@ -0,0 +1,266 @@
|
||||
package apelet.common.flow.constant; |
||||
|
||||
/** |
||||
* 工作流中的常量数据。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public class FlowConstant { |
||||
|
||||
/** |
||||
* 标识流程实例启动用户的变量名。 |
||||
*/ |
||||
public static final String START_USER_NAME_VAR = "${startUserName}"; |
||||
|
||||
/** |
||||
* 流程实例发起人变量名。 |
||||
*/ |
||||
public static final String PROC_INSTANCE_INITIATOR_VAR = "initiator"; |
||||
|
||||
/** |
||||
* 流程实例中发起人用户的变量名。 |
||||
*/ |
||||
public static final String PROC_INSTANCE_START_USER_NAME_VAR = "startUserName"; |
||||
|
||||
/** |
||||
* 流程任务的指定人变量。 |
||||
*/ |
||||
public static final String TASK_APPOINTED_ASSIGNEE_VAR = "appointedAssignee"; |
||||
|
||||
/** |
||||
* 操作类型变量。 |
||||
*/ |
||||
public static final String OPERATION_TYPE_VAR = "operationType"; |
||||
|
||||
/** |
||||
* 提交用户。 |
||||
*/ |
||||
public static final String SUBMIT_USER_VAR = "submitUser"; |
||||
|
||||
/** |
||||
* 多任务拒绝数量变量。 |
||||
*/ |
||||
public static final String MULTI_REFUSE_COUNT_VAR = "multiRefuseCount"; |
||||
|
||||
/** |
||||
* 多任务同意数量变量。 |
||||
*/ |
||||
public static final String MULTI_AGREE_COUNT_VAR = "multiAgreeCount"; |
||||
|
||||
/** |
||||
* 多任务弃权数量变量。 |
||||
*/ |
||||
public static final String MULTI_ABSTAIN_COUNT_VAR = "multiAbstainCount"; |
||||
|
||||
/** |
||||
* 会签发起任务。 |
||||
*/ |
||||
public static final String MULTI_SIGN_START_TASK_VAR = "multiSignStartTask"; |
||||
|
||||
/** |
||||
* 会签任务总数量。 |
||||
*/ |
||||
public static final String MULTI_SIGN_NUM_OF_INSTANCES_VAR = "multiNumOfInstances"; |
||||
|
||||
/** |
||||
* 会签任务执行的批次Id。 |
||||
*/ |
||||
public static final String MULTI_SIGN_TASK_EXECUTION_ID_VAR = "taskExecutionId"; |
||||
|
||||
/** |
||||
* 多实例实例数量变量。 |
||||
*/ |
||||
public static final String NUMBER_OF_INSTANCES_VAR = "nrOfInstances"; |
||||
|
||||
/** |
||||
* 多实例已完成实例数量变量。 |
||||
*/ |
||||
public static final String NUMBER_OF_COMPLETED_INSTANCES_VAR = "nrOfCompletedInstances"; |
||||
|
||||
/** |
||||
* 多任务指派人列表变量。 |
||||
*/ |
||||
public static final String MULTI_ASSIGNEE_LIST_VAR = "assigneeList"; |
||||
|
||||
/** |
||||
* 上级部门领导审批变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_UP_DEPT_POST_LEADER_VAR = "upDeptPostLeader"; |
||||
|
||||
/** |
||||
* 本部门领导审批变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_DEPT_POST_LEADER_VAR = "deptPostLeader"; |
||||
|
||||
/** |
||||
* 所有部门岗位审批变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_ALL_DEPT_POST_VAR = "allDeptPost"; |
||||
|
||||
/** |
||||
* 本部门岗位审批变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_SELF_DEPT_POST_VAR = "selfDeptPost"; |
||||
|
||||
/** |
||||
* 同级部门岗位审批变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_SIBLING_DEPT_POST_VAR = "siblingDeptPost"; |
||||
|
||||
/** |
||||
* 上级部门岗位审批变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_UP_DEPT_POST_VAR = "upDeptPost"; |
||||
|
||||
/** |
||||
* 任意部门关联的岗位审批变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_DEPT_POST_VAR = "deptPost"; |
||||
|
||||
/** |
||||
* 指定角色分组变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_ROLE_VAR = "role"; |
||||
|
||||
/** |
||||
* 指定部门分组变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_DEPT_VAR = "dept"; |
||||
|
||||
/** |
||||
* 指定用户分组变量。 |
||||
*/ |
||||
public static final String GROUP_TYPE_USER_VAR = "user"; |
||||
|
||||
/** |
||||
* 指定审批人。 |
||||
*/ |
||||
public static final String GROUP_TYPE_ASSIGNEE = "ASSIGNEE"; |
||||
|
||||
/** |
||||
* 岗位。 |
||||
*/ |
||||
public static final String GROUP_TYPE_POST = "POST"; |
||||
|
||||
/** |
||||
* 上级部门领导审批。 |
||||
*/ |
||||
public static final String GROUP_TYPE_UP_DEPT_POST_LEADER = "UP_DEPT_POST_LEADER"; |
||||
|
||||
/** |
||||
* 本部门岗位领导审批。 |
||||
*/ |
||||
public static final String GROUP_TYPE_DEPT_POST_LEADER = "DEPT_POST_LEADER"; |
||||
|
||||
/** |
||||
* 本部门岗位前缀。 |
||||
*/ |
||||
public static final String SELF_DEPT_POST_PREFIX = "SELF_DEPT_"; |
||||
|
||||
/** |
||||
* 上级部门岗位前缀。 |
||||
*/ |
||||
public static final String UP_DEPT_POST_PREFIX = "UP_DEPT_"; |
||||
|
||||
/** |
||||
* 同级部门岗位前缀。 |
||||
*/ |
||||
public static final String SIBLING_DEPT_POST_PREFIX = "SIBLING_DEPT_"; |
||||
|
||||
/** |
||||
* 当前流程实例所有任务的抄送数据前缀。 |
||||
*/ |
||||
public static final String COPY_DATA_MAP_PREFIX = "copyDataMap_"; |
||||
|
||||
/** |
||||
* 作为临时变量存入任务变量JSONObject对象时的key。 |
||||
*/ |
||||
public static final String COPY_DATA_KEY = "copyDataKey"; |
||||
|
||||
/** |
||||
* 流程中业务快照数据中,主表数据的Key。 |
||||
*/ |
||||
public static final String MASTER_DATA_KEY = "masterData"; |
||||
|
||||
/** |
||||
* 流程中业务快照数据中,关联从表数据的Key。 |
||||
*/ |
||||
public static final String SLAVE_DATA_KEY = "slaveData"; |
||||
|
||||
/** |
||||
* 流程任务的最近更新状态的Key。 |
||||
*/ |
||||
public static final String LATEST_APPROVAL_STATUS_KEY = "latestApprovalStatus"; |
||||
|
||||
/** |
||||
* 流程用户任务待办之前的通知类型的Key。 |
||||
*/ |
||||
public static final String USER_TASK_NOTIFY_TYPES_KEY = "flowNotifyTypeList"; |
||||
|
||||
/** |
||||
* 流程用户任务自动跳过类型的Key。 |
||||
*/ |
||||
public static final String USER_TASK_AUTO_SKIP_KEY = "autoSkipType"; |
||||
|
||||
/** |
||||
* 流程用户任务驳回类型的Key。 |
||||
*/ |
||||
public static final String USER_TASK_REJECT_TYPE_KEY = "rejectType"; |
||||
|
||||
/** |
||||
* 驳回时携带的变量数据。 |
||||
*/ |
||||
public static final String REJECT_TO_SOURCE_DATA_VAR = "rejectData"; |
||||
|
||||
/** |
||||
* 驳回时携带的变量数据。 |
||||
*/ |
||||
public static final String REJECT_BACK_TO_SOURCE_DATA_VAR = "rejectBackData"; |
||||
|
||||
/** |
||||
* 指定审批人。 |
||||
*/ |
||||
public static final String DELEGATE_ASSIGNEE_VAR = "defaultAssignee"; |
||||
|
||||
/** |
||||
* 业务主表对象的键。目前仅仅用户在线表单工作流。 |
||||
*/ |
||||
public static final String MASTER_TABLE_KEY = "masterTable"; |
||||
|
||||
/** |
||||
* 不删除任务超时作业。 |
||||
*/ |
||||
public static final String NOT_DELETE_TIMEOUT_TASK_JOB_KEY = "notDeleteTimeoutTaskJob"; |
||||
|
||||
/** |
||||
* 用户任务超时小时数。 |
||||
*/ |
||||
public static final String TASK_TIMEOUT_HOURS = "timeoutHours"; |
||||
|
||||
/** |
||||
* 用户任务超时处理方式。 |
||||
*/ |
||||
public static final String TASK_TIMEOUT_HANDLE_WAY = "timeoutHandleWay"; |
||||
|
||||
/** |
||||
* 用户任务超时指定审批人。 |
||||
*/ |
||||
public static final String TASK_TIMEOUT_DEFAULT_ASSIGNEE = "defaultAssignee"; |
||||
|
||||
/** |
||||
* 空处理人处理方式。 |
||||
*/ |
||||
public static final String EMPTY_USER_HANDLE_WAY = "emptyUserHandleWay"; |
||||
|
||||
/** |
||||
* 空处理人时指定的审批人。 |
||||
*/ |
||||
public static final String EMPTY_USER_TO_ASSIGNEE = "emptyUserToAssignee"; |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowConstant() { |
||||
} |
||||
} |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
package apelet.common.flow.constant; |
||||
|
||||
/** |
||||
* 工作流任务类型。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public final class FlowTaskStatus { |
||||
|
||||
/** |
||||
* 已提交。 |
||||
*/ |
||||
public static final int SUBMITTED = 0; |
||||
/** |
||||
* 审批中。 |
||||
*/ |
||||
public static final int APPROVING = 1; |
||||
/** |
||||
* 被拒绝。 |
||||
*/ |
||||
public static final int REFUSED = 2; |
||||
/** |
||||
* 已结束。 |
||||
*/ |
||||
public static final int FINISHED = 3; |
||||
/** |
||||
* 提前停止。 |
||||
*/ |
||||
public static final Integer STOPPED = 4; |
||||
/** |
||||
* 已取消。 |
||||
*/ |
||||
public static final Integer CANCELLED = 5; |
||||
/** |
||||
* 保存草稿。 |
||||
*/ |
||||
public static final Integer DRAFT = 6; |
||||
/** |
||||
* 流程复活。 |
||||
*/ |
||||
public static final Integer REVIVE = 7; |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowTaskStatus() { |
||||
} |
||||
} |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
package apelet.common.flow.constant; |
||||
|
||||
/** |
||||
* 工作流任务类型。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public final class FlowTaskType { |
||||
|
||||
/** |
||||
* 其他类型任务。 |
||||
*/ |
||||
public static final int OTHER_TYPE = 0; |
||||
/** |
||||
* 用户任务。 |
||||
*/ |
||||
public static final int USER_TYPE = 1; |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowTaskType() { |
||||
} |
||||
} |
||||
@ -0,0 +1,229 @@
@@ -0,0 +1,229 @@
|
||||
package apelet.common.flow.controller; |
||||
|
||||
import apelet.common.core.annotation.MyRequestBody; |
||||
import apelet.common.core.constant.ErrorCodeEnum; |
||||
import apelet.common.core.object.*; |
||||
import apelet.common.core.util.MyCommonUtil; |
||||
import apelet.common.core.util.MyModelUtil; |
||||
import apelet.common.core.util.MyPageUtil; |
||||
import apelet.common.core.validator.UpdateGroup; |
||||
import apelet.common.flow.dto.FlowCategoryDto; |
||||
import apelet.common.flow.model.FlowCategory; |
||||
import apelet.common.flow.model.FlowEntry; |
||||
import apelet.common.flow.model.constant.FlowEntryStatus; |
||||
import apelet.common.flow.service.FlowCategoryService; |
||||
import apelet.common.flow.service.FlowEntryService; |
||||
import apelet.common.flow.vo.FlowCategoryVo; |
||||
import apelet.common.log.annotation.OperationLog; |
||||
import apelet.common.log.model.constant.SysOperationLogType; |
||||
import cn.hutool.core.collection.CollUtil; |
||||
import cn.hutool.core.util.ObjectUtil; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import com.github.pagehelper.page.PageMethod; |
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; |
||||
import io.swagger.v3.oas.annotations.tags.Tag; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springdoc.api.annotations.ParameterObject; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import javax.validation.groups.Default; |
||||
import java.util.HashSet; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 工作流流程分类接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Tag(name = "工作流流程分类接口") |
||||
@Slf4j |
||||
@RestController |
||||
@RequestMapping("${common-flow.urlPrefix}/flowCategory") |
||||
@ConditionalOnProperty(name = "common-flow.operationEnabled", havingValue = "true") |
||||
public class FlowCategoryController { |
||||
|
||||
@Autowired |
||||
private FlowCategoryService flowCategoryService; |
||||
@Autowired |
||||
private FlowEntryService flowEntryService; |
||||
|
||||
/** |
||||
* 新增FlowCategory数据。 |
||||
* |
||||
* @param flowCategoryDto 新增对象。 |
||||
* @return 应答结果对象,包含新增对象主键Id。 |
||||
*/ |
||||
@ApiOperationSupport(ignoreParameters = {"flowCategoryDto.categoryId"}) |
||||
@OperationLog(type = SysOperationLogType.ADD) |
||||
@PostMapping("/add") |
||||
public ResponseResult<Long> add(@MyRequestBody FlowCategoryDto flowCategoryDto) { |
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowCategoryDto); |
||||
if (errorMessage != null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
FlowCategory flowCategory = MyModelUtil.copyTo(flowCategoryDto, FlowCategory.class); |
||||
if (flowCategoryService.existByCode(flowCategory.getCode())) { |
||||
return ResponseResult.error(ErrorCodeEnum.DUPLICATED_UNIQUE_KEY, "数据验证失败,当前流程分类已经存在!"); |
||||
} |
||||
flowCategory = flowCategoryService.saveNew(flowCategory); |
||||
return ResponseResult.success(flowCategory.getCategoryId()); |
||||
} |
||||
|
||||
/** |
||||
* 更新FlowCategory数据。 |
||||
* |
||||
* @param flowCategoryDto 更新对象。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.UPDATE) |
||||
@PostMapping("/update") |
||||
public ResponseResult<Void> update(@MyRequestBody FlowCategoryDto flowCategoryDto) { |
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowCategoryDto, Default.class, UpdateGroup.class); |
||||
if (errorMessage != null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
FlowCategory flowCategory = MyModelUtil.copyTo(flowCategoryDto, FlowCategory.class); |
||||
ResponseResult<FlowCategory> verifyResult = this.doVerifyAndGet(flowCategory.getCategoryId()); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowCategory originalFlowCategory = verifyResult.getData(); |
||||
if (!StrUtil.equals(flowCategory.getCode(), originalFlowCategory.getCode())) { |
||||
FlowEntry filter = new FlowEntry(); |
||||
filter.setCategoryId(flowCategory.getCategoryId()); |
||||
filter.setStatus(FlowEntryStatus.PUBLISHED); |
||||
List<FlowEntry> flowEntryList = flowEntryService.getListByFilter(filter); |
||||
if (CollUtil.isNotEmpty(flowEntryList)) { |
||||
errorMessage = "数据验证失败,当前流程分类存在已经发布的流程数据,因此分类标识不能修改!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (flowCategoryService.existByCode(flowCategory.getCode())) { |
||||
errorMessage = "数据验证失败,当前流程分类已经存在!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DUPLICATED_UNIQUE_KEY, errorMessage); |
||||
} |
||||
} |
||||
if (!flowCategoryService.update(flowCategory, originalFlowCategory)) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); |
||||
} |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 删除FlowCategory数据。 |
||||
* |
||||
* @param categoryId 删除对象主键Id。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.DELETE) |
||||
@PostMapping("/delete") |
||||
public ResponseResult<Void> delete(@MyRequestBody Long categoryId) { |
||||
String errorMessage; |
||||
ResponseResult<FlowCategory> verifyResult = this.doVerifyAndGet(categoryId); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowEntry filter = new FlowEntry(); |
||||
filter.setCategoryId(categoryId); |
||||
List<FlowEntry> flowEntryList = flowEntryService.getListByFilter(filter); |
||||
if (CollUtil.isNotEmpty(flowEntryList)) { |
||||
errorMessage = "数据验证失败,请先删除当前流程分类关联的流程数据!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (!flowCategoryService.remove(categoryId)) { |
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 列出符合过滤条件的FlowCategory列表。 |
||||
* |
||||
* @param flowCategoryDtoFilter 过滤对象。 |
||||
* @param orderParam 排序参数。 |
||||
* @param pageParam 分页参数。 |
||||
* @return 应答结果对象,包含查询结果集。 |
||||
*/ |
||||
@PostMapping("/list") |
||||
public ResponseResult<MyPageData<FlowCategoryVo>> list( |
||||
@MyRequestBody FlowCategoryDto flowCategoryDtoFilter, |
||||
@MyRequestBody MyOrderParam orderParam, |
||||
@MyRequestBody MyPageParam pageParam) { |
||||
if (pageParam != null) { |
||||
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); |
||||
} |
||||
FlowCategory flowCategoryFilter = MyModelUtil.copyTo(flowCategoryDtoFilter, FlowCategory.class); |
||||
String orderBy = MyOrderParam.buildOrderBy(orderParam, FlowCategory.class); |
||||
List<FlowCategory> flowCategoryList = flowCategoryService.getFlowCategoryListWithRelation(flowCategoryFilter, orderBy); |
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowCategoryList, FlowCategory.INSTANCE)); |
||||
} |
||||
|
||||
/** |
||||
* 查看指定FlowCategory对象详情。 |
||||
* |
||||
* @param categoryId 指定对象主键Id。 |
||||
* @return 应答结果对象,包含对象详情。 |
||||
*/ |
||||
@GetMapping("/view") |
||||
public ResponseResult<FlowCategoryVo> view(@RequestParam Long categoryId) { |
||||
ResponseResult<FlowCategory> verifyResult = this.doVerifyAndGet(categoryId); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowCategoryVo flowCategoryVo = FlowCategory.INSTANCE.fromModel(verifyResult.getData()); |
||||
return ResponseResult.success(flowCategoryVo); |
||||
} |
||||
|
||||
/** |
||||
* 以字典形式返回全部FlowCategory数据集合。字典的键值为[categoryId, name]。 |
||||
* 白名单接口,登录用户均可访问。 |
||||
* |
||||
* @param filter 过滤对象。 |
||||
* @return 应答结果对象,包含的数据为 List<Map<String, String>>,map中包含两条记录,key的值分别是id和name,value对应具体数据。 |
||||
*/ |
||||
@GetMapping("/listDict") |
||||
public ResponseResult<List<Map<String, Object>>> listDict(@ParameterObject FlowCategoryVo filter) { |
||||
List<FlowCategory> resultList = |
||||
flowCategoryService.getFlowCategoryList(MyModelUtil.copyTo(filter, FlowCategory.class), null); |
||||
return ResponseResult.success( |
||||
MyCommonUtil.toDictDataList(resultList, FlowCategory::getCategoryId, FlowCategory::getName)); |
||||
} |
||||
|
||||
/** |
||||
* 根据字典Id集合,获取查询后的字典数据。 |
||||
* |
||||
* @param dictIds 字典Id集合。 |
||||
* @return 应答结果对象,包含字典形式的数据集合。 |
||||
*/ |
||||
@GetMapping("/listDictByIds") |
||||
public ResponseResult<List<Map<String, Object>>> listDictByIds(@RequestParam List<Long> dictIds) { |
||||
List<FlowCategory> resultList = flowCategoryService.getInList(new HashSet<>(dictIds)); |
||||
return ResponseResult.success( |
||||
MyCommonUtil.toDictDataList(resultList, FlowCategory::getCategoryId, FlowCategory::getName)); |
||||
} |
||||
|
||||
private ResponseResult<FlowCategory> doVerifyAndGet(Long categoryId) { |
||||
String errorMessage; |
||||
if (MyCommonUtil.existBlankArgument(categoryId)) { |
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); |
||||
} |
||||
FlowCategory flowCategory = flowCategoryService.getById(categoryId); |
||||
if (flowCategory == null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); |
||||
} |
||||
TokenData tokenData = TokenData.takeFromRequest(); |
||||
if (!StrUtil.equals(flowCategory.getAppCode(), tokenData.getAppCode())) { |
||||
errorMessage = "数据验证失败,当前应用并不存在该流程分类的定义!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (ObjectUtil.notEqual(flowCategory.getTenantId(), tokenData.getTenantId())) { |
||||
errorMessage = "数据验证失败,当前租户并不存在该流程分类的定义!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
return ResponseResult.success(flowCategory); |
||||
} |
||||
} |
||||
@ -0,0 +1,469 @@
@@ -0,0 +1,469 @@
|
||||
package apelet.common.flow.controller; |
||||
|
||||
import apelet.common.core.annotation.MyRequestBody; |
||||
import apelet.common.core.constant.ErrorCodeEnum; |
||||
import apelet.common.core.object.*; |
||||
import apelet.common.core.util.MyCommonUtil; |
||||
import apelet.common.core.util.MyModelUtil; |
||||
import apelet.common.core.util.MyPageUtil; |
||||
import apelet.common.core.validator.UpdateGroup; |
||||
import apelet.common.flow.constant.FlowTaskType; |
||||
import apelet.common.flow.dto.FlowEntryDto; |
||||
import apelet.common.flow.model.FlowEntry; |
||||
import apelet.common.flow.model.FlowEntryPublish; |
||||
import apelet.common.flow.model.constant.FlowEntryStatus; |
||||
import apelet.common.flow.service.*; |
||||
import apelet.common.flow.vo.FlowEntryPublishVo; |
||||
import apelet.common.flow.vo.FlowEntryVo; |
||||
import apelet.common.flow.vo.TaskInfoVo; |
||||
import apelet.common.log.annotation.OperationLog; |
||||
import apelet.common.log.model.constant.SysOperationLogType; |
||||
import cn.hutool.core.map.MapUtil; |
||||
import cn.hutool.core.util.BooleanUtil; |
||||
import cn.hutool.core.util.ObjectUtil; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import com.alibaba.fastjson.JSON; |
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.github.pagehelper.page.PageMethod; |
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; |
||||
import io.swagger.v3.oas.annotations.tags.Tag; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.bpmn.model.Process; |
||||
import org.flowable.bpmn.model.*; |
||||
import org.springdoc.api.annotations.ParameterObject; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import javax.validation.groups.Default; |
||||
import javax.xml.stream.XMLStreamException; |
||||
import java.util.*; |
||||
|
||||
/** |
||||
* 工作流流程定义接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Tag(name = "工作流流程定义接口") |
||||
@Slf4j |
||||
@RestController |
||||
@RequestMapping("${common-flow.urlPrefix}/flowEntry") |
||||
@ConditionalOnProperty(name = "common-flow.operationEnabled", havingValue = "true") |
||||
public class FlowEntryController { |
||||
|
||||
@Autowired |
||||
private FlowEntryService flowEntryService; |
||||
@Autowired |
||||
private FlowCategoryService flowCategoryService; |
||||
@Autowired |
||||
private FlowEntryVariableService flowEntryVariableService; |
||||
@Autowired |
||||
private FlowApiService flowApiService; |
||||
@Autowired |
||||
private FlowTaskExtService flowTaskExtService; |
||||
|
||||
/** |
||||
* 新增工作流对象数据。 |
||||
* |
||||
* @param flowEntryDto 新增对象。 |
||||
* @return 应答结果对象,包含新增对象主键Id。 |
||||
*/ |
||||
@ApiOperationSupport(ignoreParameters = {"flowEntryDto.entryId"}) |
||||
@OperationLog(type = SysOperationLogType.ADD) |
||||
@PostMapping("/add") |
||||
public ResponseResult<Long> add(@MyRequestBody FlowEntryDto flowEntryDto) { |
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowEntryDto); |
||||
if (errorMessage != null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
FlowEntry flowEntry = MyModelUtil.copyTo(flowEntryDto, FlowEntry.class); |
||||
if (flowEntryService.existByProcessDefinitionKey(flowEntry.getProcessDefinitionKey())) { |
||||
errorMessage = "数据验证失败,该流程定义标识已存在!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
// 验证关联Id的数据合法性
|
||||
CallResult callResult = flowEntryService.verifyRelatedData(flowEntry, null); |
||||
if (!callResult.isSuccess()) { |
||||
errorMessage = callResult.getErrorMessage(); |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
flowEntry = flowEntryService.saveNew(flowEntry); |
||||
return ResponseResult.success(flowEntry.getEntryId()); |
||||
} |
||||
|
||||
/** |
||||
* 更新工作流对象数据。 |
||||
* |
||||
* @param flowEntryDto 更新对象。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.UPDATE) |
||||
@PostMapping("/update") |
||||
public ResponseResult<Void> update(@MyRequestBody FlowEntryDto flowEntryDto) { |
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowEntryDto, Default.class, UpdateGroup.class); |
||||
if (errorMessage != null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
FlowEntry flowEntry = MyModelUtil.copyTo(flowEntryDto, FlowEntry.class); |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(flowEntry.getEntryId()); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowEntry originalFlowEntry = verifyResult.getData(); |
||||
if (ObjectUtil.notEqual(flowEntry.getProcessDefinitionKey(), originalFlowEntry.getProcessDefinitionKey())) { |
||||
if (originalFlowEntry.getStatus().equals(FlowEntryStatus.PUBLISHED)) { |
||||
errorMessage = "数据验证失败,当前流程为发布状态,流程标识不能修改!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (flowEntryService.existByProcessDefinitionKey(flowEntry.getProcessDefinitionKey())) { |
||||
errorMessage = "数据验证失败,该流程定义标识已存在!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
} |
||||
// 验证关联Id的数据合法性
|
||||
CallResult callResult = flowEntryService.verifyRelatedData(flowEntry, originalFlowEntry); |
||||
if (!callResult.isSuccess()) { |
||||
errorMessage = callResult.getErrorMessage(); |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (!flowEntryService.update(flowEntry, originalFlowEntry)) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); |
||||
} |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 删除工作流对象数据。 |
||||
* |
||||
* @param entryId 删除对象主键Id。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.DELETE) |
||||
@PostMapping("/delete") |
||||
public ResponseResult<Void> delete(@MyRequestBody Long entryId) { |
||||
String errorMessage; |
||||
if (MyCommonUtil.existBlankArgument(entryId)) { |
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); |
||||
} |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(entryId); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowEntry originalFlowEntry = verifyResult.getData(); |
||||
if (originalFlowEntry.getStatus().equals(FlowEntryStatus.PUBLISHED)) { |
||||
errorMessage = "数据验证失败,当前流程为发布状态,不能删除!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (!flowEntryService.remove(entryId)) { |
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 发布工作流。 |
||||
* |
||||
* @param entryId 流程主键Id。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.PUBLISH) |
||||
@PostMapping("/publish") |
||||
public ResponseResult<Void> publish(@MyRequestBody(required = true) Long entryId) throws XMLStreamException { |
||||
String errorMessage; |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(entryId); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowEntry flowEntry = verifyResult.getData(); |
||||
if (StrUtil.isBlank(flowEntry.getBpmnXml())) { |
||||
errorMessage = "数据验证失败,该流程没有流程图不能被发布!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
ResponseResult<TaskInfoVo> taskInfoResult = this.verifyAndGetInitialTaskInfo(flowEntry); |
||||
if (!taskInfoResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(taskInfoResult); |
||||
} |
||||
String taskInfo = taskInfoResult.getData() == null ? null : JSON.toJSONString(taskInfoResult.getData()); |
||||
flowEntryService.publish(flowEntry, taskInfo); |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 列出符合过滤条件的工作流列表。 |
||||
* |
||||
* @param flowEntryDtoFilter 过滤对象。 |
||||
* @param orderParam 排序参数。 |
||||
* @param pageParam 分页参数。 |
||||
* @return 应答结果对象,包含查询结果集。 |
||||
*/ |
||||
@PostMapping("/list") |
||||
public ResponseResult<MyPageData<FlowEntryVo>> list( |
||||
@MyRequestBody FlowEntryDto flowEntryDtoFilter, |
||||
@MyRequestBody MyOrderParam orderParam, |
||||
@MyRequestBody MyPageParam pageParam) { |
||||
if (pageParam != null) { |
||||
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); |
||||
} |
||||
FlowEntry flowEntryFilter = MyModelUtil.copyTo(flowEntryDtoFilter, FlowEntry.class); |
||||
String orderBy = MyOrderParam.buildOrderBy(orderParam, FlowEntry.class); |
||||
List<FlowEntry> flowEntryList = flowEntryService.getFlowEntryListWithRelation(flowEntryFilter, orderBy); |
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowEntryList, FlowEntry.INSTANCE)); |
||||
} |
||||
|
||||
/** |
||||
* 查看指定工作流对象详情。 |
||||
* |
||||
* @param entryId 指定对象主键Id。 |
||||
* @return 应答结果对象,包含对象详情。 |
||||
*/ |
||||
@GetMapping("/view") |
||||
public ResponseResult<FlowEntryVo> view(@RequestParam Long entryId) { |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(entryId); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowEntry flowEntry = flowEntryService.getByIdWithRelation(entryId, MyRelationParam.full()); |
||||
if (flowEntry == null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); |
||||
} |
||||
FlowEntryVo flowEntryVo = FlowEntry.INSTANCE.fromModel(flowEntry); |
||||
flowEntryVo.setStartConditions(flowEntry.getStartConditions()); |
||||
return ResponseResult.success(flowEntryVo); |
||||
} |
||||
|
||||
/** |
||||
* 列出指定流程的发布版本列表。 |
||||
* |
||||
* @param entryId 流程主键Id。 |
||||
* @return 应答结果对象,包含流程发布列表数据。 |
||||
*/ |
||||
@GetMapping("/listFlowEntryPublish") |
||||
public ResponseResult<List<FlowEntryPublishVo>> listFlowEntryPublish(@RequestParam Long entryId) { |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(entryId); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
List<FlowEntryPublish> flowEntryPublishList = flowEntryService.getFlowEntryPublishList(entryId); |
||||
return ResponseResult.success(MyModelUtil.copyCollectionTo(flowEntryPublishList, FlowEntryPublishVo.class)); |
||||
} |
||||
|
||||
/** |
||||
* 以字典形式返回全部FlowEntry数据集合。字典的键值为[entryId, procDefinitionName]。 |
||||
* 白名单接口,登录用户均可访问。 |
||||
* |
||||
* @param filter 过滤对象。 |
||||
* @return 应答结果对象,包含的数据为 List<Map<String, String>>,map中包含两条记录,key的值分别是id和name,value对应具体数据。 |
||||
*/ |
||||
@GetMapping("/listDict") |
||||
public ResponseResult<List<Map<String, Object>>> listDict(@ParameterObject FlowEntryVo filter) { |
||||
List<FlowEntry> resultList = |
||||
flowEntryService.getFlowEntryList(MyModelUtil.copyTo(filter, FlowEntry.class), null); |
||||
return ResponseResult.success( |
||||
MyCommonUtil.toDictDataList(resultList, FlowEntry::getEntryId, FlowEntry::getProcessDefinitionName)); |
||||
} |
||||
|
||||
/** |
||||
* 获取所有流程分类和流程定义的列表。白名单接口。 |
||||
* |
||||
* @return 所有流程分类和流程定义的列表 |
||||
*/ |
||||
@GetMapping("/listAll") |
||||
public ResponseResult<JSONObject> listAll() { |
||||
JSONObject jsonObject = new JSONObject(); |
||||
jsonObject.put("flowEntryList", flowEntryService.getFlowEntryList(null, null)); |
||||
jsonObject.put("flowCategoryList", flowCategoryService.getFlowCategoryList(null, null)); |
||||
return ResponseResult.success(jsonObject); |
||||
} |
||||
|
||||
/** |
||||
* 白名单接口,根据流程Id,获取流程引擎需要的流程标识和流程名称。 |
||||
* |
||||
* @param entryId 流程Id。 |
||||
* @return 流程的部分数据。 |
||||
*/ |
||||
@GetMapping("/viewDict") |
||||
public ResponseResult<Map<String, Object>> viewDict(@RequestParam Long entryId) { |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(entryId); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowEntry flowEntry = verifyResult.getData(); |
||||
Map<String, Object> resultMap = new HashMap<>(2); |
||||
resultMap.put("processDefinitionKey", flowEntry.getProcessDefinitionKey()); |
||||
resultMap.put("processDefinitionName", flowEntry.getProcessDefinitionName()); |
||||
return ResponseResult.success(resultMap); |
||||
} |
||||
|
||||
/** |
||||
* 切换指定工作的发布主版本。 |
||||
* |
||||
* @param entryId 工作流主键Id。 |
||||
* @param newEntryPublishId 新的工作流发布主版本对象的主键Id。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.UPDATE) |
||||
@PostMapping("/updateMainVersion") |
||||
public ResponseResult<Void> updateMainVersion( |
||||
@MyRequestBody(required = true) Long entryId, |
||||
@MyRequestBody(required = true) Long newEntryPublishId) { |
||||
String errorMessage; |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(entryId); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
FlowEntryPublish flowEntryPublish = flowEntryService.getFlowEntryPublishFromCache(newEntryPublishId); |
||||
if (flowEntryPublish == null) { |
||||
errorMessage = "数据验证失败,当前流程发布版本并不存在,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
if (ObjectUtil.notEqual(entryId, flowEntryPublish.getEntryId())) { |
||||
errorMessage = "数据验证失败,当前工作流并不包含该工作流发布版本数据,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (BooleanUtil.isTrue(flowEntryPublish.getMainVersion())) { |
||||
errorMessage = "数据验证失败,该版本已经为当前工作流的发布主版本,不能重复设置!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
flowEntryService.updateFlowEntryMainVersion(flowEntryService.getById(entryId), flowEntryPublish); |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 挂起工作流的指定发布版本。 |
||||
* |
||||
* @param entryPublishId 工作发布Id。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.SUSPEND) |
||||
@PostMapping("/suspendFlowEntryPublish") |
||||
public ResponseResult<Void> suspendFlowEntryPublish(@MyRequestBody(required = true) Long entryPublishId) { |
||||
String errorMessage; |
||||
FlowEntryPublish flowEntryPublish = flowEntryService.getFlowEntryPublishFromCache(entryPublishId); |
||||
if (flowEntryPublish == null) { |
||||
errorMessage = "数据验证失败,当前流程发布版本并不存在,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(flowEntryPublish.getEntryId()); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
if (BooleanUtil.isFalse(flowEntryPublish.getActiveStatus())) { |
||||
errorMessage = "数据验证失败,当前流程发布版本已处于挂起状态!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
flowEntryService.suspendFlowEntryPublish(flowEntryPublish); |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 激活工作流的指定发布版本。 |
||||
* |
||||
* @param entryPublishId 工作发布Id。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.RESUME) |
||||
@PostMapping("/activateFlowEntryPublish") |
||||
public ResponseResult<Void> activateFlowEntryPublish(@MyRequestBody(required = true) Long entryPublishId) { |
||||
String errorMessage; |
||||
FlowEntryPublish flowEntryPublish = flowEntryService.getFlowEntryPublishFromCache(entryPublishId); |
||||
if (flowEntryPublish == null) { |
||||
errorMessage = "数据验证失败,当前流程发布版本并不存在,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
ResponseResult<FlowEntry> verifyResult = this.doVerifyAndGet(flowEntryPublish.getEntryId()); |
||||
if (!verifyResult.isSuccess()) { |
||||
return ResponseResult.errorFrom(verifyResult); |
||||
} |
||||
if (BooleanUtil.isTrue(flowEntryPublish.getActiveStatus())) { |
||||
errorMessage = "数据验证失败,当前流程发布版本已处于激活状态!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
flowEntryService.activateFlowEntryPublish(flowEntryPublish); |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
private ResponseResult<FlowEntry> doVerifyAndGet(Long entryId) { |
||||
String errorMessage; |
||||
if (MyCommonUtil.existBlankArgument(entryId)) { |
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); |
||||
} |
||||
FlowEntry flowEntry = flowEntryService.getById(entryId); |
||||
if (flowEntry == null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); |
||||
} |
||||
TokenData tokenData = TokenData.takeFromRequest(); |
||||
if (!StrUtil.equals(flowEntry.getAppCode(), tokenData.getAppCode())) { |
||||
errorMessage = "数据验证失败,当前应用并不存在该流程定义!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (ObjectUtil.notEqual(flowEntry.getTenantId(), tokenData.getTenantId())) { |
||||
errorMessage = "数据验证失败,当前租户并不存在该流程定义!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
return ResponseResult.success(flowEntry); |
||||
} |
||||
|
||||
private ResponseResult<TaskInfoVo> verifyAndGetInitialTaskInfo(FlowEntry flowEntry) throws XMLStreamException { |
||||
String errorMessage; |
||||
BpmnModel bpmnModel = flowApiService.convertToBpmnModel(flowEntry.getBpmnXml()); |
||||
Process process = bpmnModel.getMainProcess(); |
||||
if (process == null) { |
||||
errorMessage = "数据验证失败,当前流程标识 [" + flowEntry.getProcessDefinitionKey() + "] 关联的流程模型并不存在!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
Collection<FlowElement> elementList = process.getFlowElements(); |
||||
FlowElement startEvent = null; |
||||
// 这里我们只定位流程模型中的第二个节点。
|
||||
for (FlowElement flowElement : elementList) { |
||||
if (flowElement instanceof StartEvent) { |
||||
startEvent = flowElement; |
||||
break; |
||||
} |
||||
} |
||||
if (startEvent == null) { |
||||
errorMessage = "数据验证失败,当前流程图没有包含 [开始事件] 节点,请修改流程图!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
FlowElement firstTask = this.findFirstTask(elementList, startEvent); |
||||
if (firstTask == null) { |
||||
errorMessage = "数据验证失败,当前流程图没有包含 [开始事件] 节点没有任何连线,请修改流程图!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
TaskInfoVo taskInfoVo; |
||||
if (firstTask instanceof UserTask) { |
||||
UserTask userTask = (UserTask) firstTask; |
||||
String formKey = userTask.getFormKey(); |
||||
if (StrUtil.isNotBlank(formKey)) { |
||||
taskInfoVo = JSON.parseObject(formKey, TaskInfoVo.class); |
||||
} else { |
||||
taskInfoVo = new TaskInfoVo(); |
||||
} |
||||
taskInfoVo.setAssignee(userTask.getAssignee()); |
||||
taskInfoVo.setTaskKey(userTask.getId()); |
||||
taskInfoVo.setTaskType(FlowTaskType.USER_TYPE); |
||||
Map<String, List<ExtensionElement>> extensionMap = userTask.getExtensionElements(); |
||||
if (MapUtil.isNotEmpty(extensionMap)) { |
||||
taskInfoVo.setOperationList(flowTaskExtService.buildOperationListExtensionElement(extensionMap)); |
||||
taskInfoVo.setVariableList(flowTaskExtService.buildVariableListExtensionElement(extensionMap)); |
||||
} |
||||
} else { |
||||
taskInfoVo = new TaskInfoVo(); |
||||
taskInfoVo.setTaskType(FlowTaskType.OTHER_TYPE); |
||||
} |
||||
return ResponseResult.success(taskInfoVo); |
||||
} |
||||
|
||||
private FlowElement findFirstTask(Collection<FlowElement> elementList, FlowElement startEvent) { |
||||
for (FlowElement flowElement : elementList) { |
||||
if (flowElement instanceof SequenceFlow) { |
||||
SequenceFlow sequenceFlow = (SequenceFlow) flowElement; |
||||
if (sequenceFlow.getSourceFlowElement().equals(startEvent)) { |
||||
return sequenceFlow.getTargetFlowElement(); |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
@ -0,0 +1,156 @@
@@ -0,0 +1,156 @@
|
||||
package apelet.common.flow.controller; |
||||
|
||||
import apelet.common.core.annotation.MyRequestBody; |
||||
import apelet.common.core.constant.ErrorCodeEnum; |
||||
import apelet.common.core.object.*; |
||||
import apelet.common.core.util.MyCommonUtil; |
||||
import apelet.common.core.util.MyModelUtil; |
||||
import apelet.common.core.util.MyPageUtil; |
||||
import apelet.common.core.validator.UpdateGroup; |
||||
import apelet.common.flow.dto.FlowEntryVariableDto; |
||||
import apelet.common.flow.model.FlowEntryVariable; |
||||
import apelet.common.flow.service.FlowEntryVariableService; |
||||
import apelet.common.flow.vo.FlowEntryVariableVo; |
||||
import apelet.common.log.annotation.OperationLog; |
||||
import apelet.common.log.model.constant.SysOperationLogType; |
||||
import com.github.pagehelper.page.PageMethod; |
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; |
||||
import io.swagger.v3.oas.annotations.tags.Tag; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import javax.validation.groups.Default; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 工作流流程变量接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Tag(name = "工作流流程变量接口") |
||||
@Slf4j |
||||
@RestController |
||||
@RequestMapping("${common-flow.urlPrefix}/flowEntryVariable") |
||||
@ConditionalOnProperty(name = "common-flow.operationEnabled", havingValue = "true") |
||||
public class FlowEntryVariableController { |
||||
|
||||
@Autowired |
||||
private FlowEntryVariableService flowEntryVariableService; |
||||
|
||||
/** |
||||
* 新增流程变量数据。 |
||||
* |
||||
* @param flowEntryVariableDto 新增对象。 |
||||
* @return 应答结果对象,包含新增对象主键Id。 |
||||
*/ |
||||
@ApiOperationSupport(ignoreParameters = {"flowEntryVariableDto.variableId"}) |
||||
@OperationLog(type = SysOperationLogType.ADD) |
||||
@PostMapping("/add") |
||||
public ResponseResult<Long> add(@MyRequestBody FlowEntryVariableDto flowEntryVariableDto) { |
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowEntryVariableDto); |
||||
if (errorMessage != null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
FlowEntryVariable flowEntryVariable = MyModelUtil.copyTo(flowEntryVariableDto, FlowEntryVariable.class); |
||||
flowEntryVariable = flowEntryVariableService.saveNew(flowEntryVariable); |
||||
return ResponseResult.success(flowEntryVariable.getVariableId()); |
||||
} |
||||
|
||||
/** |
||||
* 更新流程变量数据。 |
||||
* |
||||
* @param flowEntryVariableDto 更新对象。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.UPDATE) |
||||
@PostMapping("/update") |
||||
public ResponseResult<Void> update(@MyRequestBody FlowEntryVariableDto flowEntryVariableDto) { |
||||
String errorMessage = MyCommonUtil.getModelValidationError(flowEntryVariableDto, Default.class, UpdateGroup.class); |
||||
if (errorMessage != null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
FlowEntryVariable flowEntryVariable = MyModelUtil.copyTo(flowEntryVariableDto, FlowEntryVariable.class); |
||||
FlowEntryVariable originalFlowEntryVariable = flowEntryVariableService.getById(flowEntryVariable.getVariableId()); |
||||
if (originalFlowEntryVariable == null) { |
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
if (!flowEntryVariableService.update(flowEntryVariable, originalFlowEntryVariable)) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); |
||||
} |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 删除流程变量数据。 |
||||
* |
||||
* @param variableId 删除对象主键Id。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@OperationLog(type = SysOperationLogType.DELETE) |
||||
@PostMapping("/delete") |
||||
public ResponseResult<Void> delete(@MyRequestBody Long variableId) { |
||||
String errorMessage; |
||||
if (MyCommonUtil.existBlankArgument(variableId)) { |
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); |
||||
} |
||||
// 验证关联Id的数据合法性
|
||||
FlowEntryVariable originalFlowEntryVariable = flowEntryVariableService.getById(variableId); |
||||
if (originalFlowEntryVariable == null) { |
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
if (!flowEntryVariableService.remove(variableId)) { |
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); |
||||
} |
||||
return ResponseResult.success(); |
||||
} |
||||
|
||||
/** |
||||
* 列出符合过滤条件的流程变量列表。 |
||||
* |
||||
* @param flowEntryVariableDtoFilter 过滤对象。 |
||||
* @param orderParam 排序参数。 |
||||
* @param pageParam 分页参数。 |
||||
* @return 应答结果对象,包含查询结果集。 |
||||
*/ |
||||
@PostMapping("/list") |
||||
public ResponseResult<MyPageData<FlowEntryVariableVo>> list( |
||||
@MyRequestBody FlowEntryVariableDto flowEntryVariableDtoFilter, |
||||
@MyRequestBody MyOrderParam orderParam, |
||||
@MyRequestBody MyPageParam pageParam) { |
||||
if (pageParam != null) { |
||||
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); |
||||
} |
||||
FlowEntryVariable flowEntryVariableFilter = MyModelUtil.copyTo(flowEntryVariableDtoFilter, FlowEntryVariable.class); |
||||
String orderBy = MyOrderParam.buildOrderBy(orderParam, FlowEntryVariable.class); |
||||
List<FlowEntryVariable> flowEntryVariableList = |
||||
flowEntryVariableService.getFlowEntryVariableListWithRelation(flowEntryVariableFilter, orderBy); |
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowEntryVariableList, FlowEntryVariable.INSTANCE)); |
||||
} |
||||
|
||||
/** |
||||
* 查看指定流程变量对象详情。 |
||||
* |
||||
* @param variableId 指定对象主键Id。 |
||||
* @return 应答结果对象,包含对象详情。 |
||||
*/ |
||||
@GetMapping("/view") |
||||
public ResponseResult<FlowEntryVariableVo> view(@RequestParam Long variableId) { |
||||
if (MyCommonUtil.existBlankArgument(variableId)) { |
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); |
||||
} |
||||
FlowEntryVariable flowEntryVariable = flowEntryVariableService.getByIdWithRelation(variableId, MyRelationParam.full()); |
||||
if (flowEntryVariable == null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); |
||||
} |
||||
FlowEntryVariableVo flowEntryVariableVo = FlowEntryVariable.INSTANCE.fromModel(flowEntryVariable); |
||||
return ResponseResult.success(flowEntryVariableVo); |
||||
} |
||||
} |
||||
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
package apelet.common.flow.controller; |
||||
|
||||
import apelet.common.core.annotation.MyRequestBody; |
||||
import apelet.common.core.constant.ErrorCodeEnum; |
||||
import apelet.common.core.object.MyPageData; |
||||
import apelet.common.core.object.MyPageParam; |
||||
import apelet.common.core.object.ResponseResult; |
||||
import apelet.common.core.util.MyPageUtil; |
||||
import apelet.common.flow.model.FlowMessage; |
||||
import apelet.common.flow.model.constant.FlowMessageType; |
||||
import apelet.common.flow.service.FlowMessageService; |
||||
import apelet.common.flow.vo.FlowMessageVo; |
||||
import com.alibaba.fastjson.JSONObject; |
||||
import com.github.pagehelper.page.PageMethod; |
||||
import io.swagger.v3.oas.annotations.tags.Tag; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 工作流消息接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Tag(name = "工作流消息接口") |
||||
@Slf4j |
||||
@RestController |
||||
@RequestMapping("${common-flow.urlPrefix}/flowMessage") |
||||
@ConditionalOnProperty(name = "common-flow.operationEnabled", havingValue = "true") |
||||
public class FlowMessageController { |
||||
|
||||
@Autowired |
||||
private FlowMessageService flowMessageService; |
||||
|
||||
/** |
||||
* 获取当前用户的未读消息总数。 |
||||
* NOTE:白名单接口。 |
||||
* |
||||
* @return 应答结果对象,包含当前用户的未读消息总数。 |
||||
*/ |
||||
@GetMapping("/getMessageCount") |
||||
public ResponseResult<JSONObject> getMessageCount() { |
||||
JSONObject resultData = new JSONObject(); |
||||
resultData.put("remindingMessageCount", flowMessageService.countRemindingMessageListByUser()); |
||||
resultData.put("copyMessageCount", flowMessageService.countCopyMessageByUser()); |
||||
resultData.put("sysMessageCount", flowMessageService.countSysMessageByUser()); |
||||
return ResponseResult.success(resultData); |
||||
} |
||||
|
||||
/** |
||||
* 获取当前用户的催办消息列表。 |
||||
* 不仅仅包含,其中包括当前用户所属角色、部门和岗位的候选组催办消息。 |
||||
* NOTE:白名单接口。 |
||||
* |
||||
* @return 应答结果对象,包含查询结果集。 |
||||
*/ |
||||
@PostMapping("/listRemindingTask") |
||||
public ResponseResult<MyPageData<FlowMessageVo>> listRemindingTask(@MyRequestBody MyPageParam pageParam) { |
||||
if (pageParam != null) { |
||||
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize(), pageParam.getCount()); |
||||
} |
||||
List<FlowMessage> flowMessageList = flowMessageService.getRemindingMessageListByUser(); |
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowMessageList, FlowMessage.INSTANCE)); |
||||
} |
||||
|
||||
/** |
||||
* 获取当前用户的抄送消息列表。 |
||||
* 不仅仅包含,其中包括当前用户所属角色、部门和岗位的候选组抄送消息。 |
||||
* NOTE:白名单接口。 |
||||
* |
||||
* @param read true表示已读,false表示未读。 |
||||
* @return 应答结果对象,包含查询结果集。 |
||||
*/ |
||||
@PostMapping("/listCopyMessage") |
||||
public ResponseResult<MyPageData<FlowMessageVo>> listCopyMessage( |
||||
@MyRequestBody MyPageParam pageParam, @MyRequestBody Boolean read) { |
||||
if (pageParam != null) { |
||||
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize(), pageParam.getCount()); |
||||
} |
||||
List<FlowMessage> flowMessageList = flowMessageService.getCopyMessageListByUser(read); |
||||
return ResponseResult.success(MyPageUtil.makeResponseData(flowMessageList, FlowMessage.INSTANCE)); |
||||
} |
||||
|
||||
/** |
||||
* 读取抄送消息,同时更新当前用户对指定抄送消息的读取状态。 |
||||
* |
||||
* @param messageId 消息Id。 |
||||
* @return 应答结果对象。 |
||||
*/ |
||||
@PostMapping("/readCopyTask") |
||||
public ResponseResult<Void> readCopyTask(@MyRequestBody Long messageId) { |
||||
String errorMessage; |
||||
// 验证流程任务的合法性。
|
||||
FlowMessage flowMessage = flowMessageService.getById(messageId); |
||||
if (flowMessage == null) { |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); |
||||
} |
||||
if (flowMessage.getMessageType() != FlowMessageType.COPY_TYPE) { |
||||
errorMessage = "数据验证失败,当前消息不是抄送类型消息!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
if (!flowMessageService.isCandidateIdentityOnMessage(messageId)) { |
||||
errorMessage = "数据验证失败,当前用户没有权限访问该消息!"; |
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage); |
||||
} |
||||
flowMessageService.readCopyTask(messageId); |
||||
return ResponseResult.success(); |
||||
} |
||||
} |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
package apelet.common.flow.controller; |
||||
|
||||
import apelet.common.core.annotation.MyRequestBody; |
||||
import apelet.common.core.object.ResponseResult; |
||||
import apelet.common.flow.model.FlowNodeTasks; |
||||
import apelet.common.flow.service.FlowNodeTasksService; |
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
import io.swagger.v3.oas.annotations.tags.Tag; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.web.bind.annotation.*; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 工作流审核设置接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Tag(name = "工作流审核设置接口") |
||||
@Slf4j |
||||
@RestController |
||||
@RequestMapping("${common-flow.urlPrefix}/flowNodeTasks") |
||||
@ConditionalOnProperty(name = "common-flow.operationEnabled", havingValue = "true") |
||||
public class FlowNodeTasksController { |
||||
|
||||
@Autowired |
||||
FlowNodeTasksService flowNodeTasksService; |
||||
|
||||
|
||||
@PostMapping("/add") |
||||
public ResponseResult<?> add(@RequestBody FlowNodeTasks flowNodeTasks) { |
||||
flowNodeTasksService.save(flowNodeTasks); |
||||
return ResponseResult.success(flowNodeTasks.getId()); |
||||
} |
||||
|
||||
@GetMapping("/list") |
||||
public ResponseResult<?> getList(@RequestParam String flowId,@RequestParam String taskKey) { |
||||
LambdaQueryWrapper<FlowNodeTasks> wrapper = new LambdaQueryWrapper<>(); |
||||
wrapper.eq(FlowNodeTasks::getFlowId, flowId); |
||||
wrapper.eq(FlowNodeTasks::getTaskKey, taskKey); |
||||
List<FlowNodeTasks> list = flowNodeTasksService.list(wrapper); |
||||
return ResponseResult.success(list); |
||||
} |
||||
|
||||
|
||||
|
||||
@PostMapping("/delete") |
||||
public ResponseResult<?> delete(@MyRequestBody Long id) { |
||||
boolean b = flowNodeTasksService.removeById(id); |
||||
return ResponseResult.success(b); |
||||
} |
||||
|
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowCategory; |
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* FlowCategory数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowCategoryMapper extends BaseDaoMapper<FlowCategory> { |
||||
|
||||
/** |
||||
* 获取过滤后的对象列表。 |
||||
* |
||||
* @param flowCategoryFilter 主表过滤对象。 |
||||
* @param orderBy 排序字符串,order by从句的参数。 |
||||
* @return 对象列表。 |
||||
*/ |
||||
List<FlowCategory> getFlowCategoryList( |
||||
@Param("flowCategoryFilter") FlowCategory flowCategoryFilter, @Param("orderBy") String orderBy); |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowEntry; |
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* FlowEntry数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowEntryMapper extends BaseDaoMapper<FlowEntry> { |
||||
|
||||
/** |
||||
* 获取过滤后的对象列表。 |
||||
* |
||||
* @param flowEntryFilter 主表过滤对象。 |
||||
* @param orderBy 排序字符串,order by从句的参数。 |
||||
* @return 对象列表。 |
||||
*/ |
||||
List<FlowEntry> getFlowEntryList( |
||||
@Param("flowEntryFilter") FlowEntry flowEntryFilter, @Param("orderBy") String orderBy); |
||||
} |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowEntryPublish; |
||||
|
||||
/** |
||||
* 数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowEntryPublishMapper extends BaseDaoMapper<FlowEntryPublish> { |
||||
} |
||||
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowEntryPublishVariable; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowEntryPublishVariableMapper extends BaseDaoMapper<FlowEntryPublishVariable> { |
||||
|
||||
/** |
||||
* 批量插入流程发布的变量列表。 |
||||
* |
||||
* @param entryPublishVariableList 流程发布的变量列表。 |
||||
*/ |
||||
void insertList(List<FlowEntryPublishVariable> entryPublishVariableList); |
||||
} |
||||
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowEntryVariable; |
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 流程变量数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowEntryVariableMapper extends BaseDaoMapper<FlowEntryVariable> { |
||||
|
||||
/** |
||||
* 获取过滤后的对象列表。 |
||||
* |
||||
* @param flowEntryVariableFilter 主表过滤对象。 |
||||
* @param orderBy 排序字符串,order by从句的参数。 |
||||
* @return 对象列表。 |
||||
*/ |
||||
List<FlowEntryVariable> getFlowEntryVariableList( |
||||
@Param("flowEntryVariableFilter") FlowEntryVariable flowEntryVariableFilter, |
||||
@Param("orderBy") String orderBy); |
||||
} |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowMessageCandidateIdentity; |
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
/** |
||||
* 流程任务消息的候选身份数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowMessageCandidateIdentityMapper extends BaseDaoMapper<FlowMessageCandidateIdentity> { |
||||
|
||||
/** |
||||
* 删除指定流程实例的消息关联数据。 |
||||
* |
||||
* @param processInstanceId 流程实例Id。 |
||||
*/ |
||||
void deleteByProcessInstanceId(@Param("processInstanceId") String processInstanceId); |
||||
} |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowMessageIdentityOperation; |
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
/** |
||||
* 流程任务消息所属用户的操作数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowMessageIdentityOperationMapper extends BaseDaoMapper<FlowMessageIdentityOperation> { |
||||
|
||||
/** |
||||
* 删除指定流程实例的消息关联数据。 |
||||
* |
||||
* @param processInstanceId 流程实例Id。 |
||||
*/ |
||||
void deleteByProcessInstanceId(@Param("processInstanceId") String processInstanceId); |
||||
} |
||||
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowMessage; |
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* 工作流消息数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowMessageMapper extends BaseDaoMapper<FlowMessage> { |
||||
|
||||
/** |
||||
* 获取指定用户和身份分组Id集合的催办消息列表。 |
||||
* |
||||
* @param tenantId 租户Id。 |
||||
* @param appCode 应用编码。 |
||||
* @param loginName 用户的登录名。与流程任务的assignee精确匹配。 |
||||
* @param groupIdSet 用户身份分组Id集合。 |
||||
* @return 查询后的催办消息列表。 |
||||
*/ |
||||
List<FlowMessage> getRemindingMessageListByUser( |
||||
@Param("tenantId") Long tenantId, |
||||
@Param("appCode") String appCode, |
||||
@Param("loginName") String loginName, |
||||
@Param("groupIdSet") Set<String> groupIdSet); |
||||
|
||||
/** |
||||
* 获取指定用户和身份分组Id集合的抄送消息列表。 |
||||
* |
||||
* @param tenantId 租户Id。 |
||||
* @param appCode 应用编码。 |
||||
* @param loginName 用户登录名。 |
||||
* @param groupIdSet 用户身份分组Id集合。 |
||||
* @param read true表示已读,false表示未读。 |
||||
* @return 查询后的抄送消息列表。 |
||||
*/ |
||||
List<FlowMessage> getCopyMessageListByUser( |
||||
@Param("tenantId") Long tenantId, |
||||
@Param("appCode") String appCode, |
||||
@Param("loginName") String loginName, |
||||
@Param("groupIdSet") Set<String> groupIdSet, |
||||
@Param("read") Boolean read); |
||||
|
||||
/** |
||||
* 计算当前用户催办消息的数量。 |
||||
* |
||||
* @param tenantId 租户Id。 |
||||
* @param appCode 应用编码。 |
||||
* @param loginName 用户登录名。 |
||||
* @param groupIdSet 用户身份分组Id集合。 |
||||
* @return 数据数量。 |
||||
*/ |
||||
int countRemindingMessageListByUser( |
||||
@Param("tenantId") Long tenantId, |
||||
@Param("appCode") String appCode, |
||||
@Param("loginName") String loginName, |
||||
@Param("groupIdSet") Set<String> groupIdSet); |
||||
|
||||
/** |
||||
* 计算当前用户未读抄送消息的数量。 |
||||
* |
||||
* @param tenantId 租户Id。 |
||||
* @param appCode 应用编码。 |
||||
* @param loginName 用户登录名。 |
||||
* @param groupIdSet 用户身份分组Id集合。 |
||||
* @return 数据数量 |
||||
*/ |
||||
int countCopyMessageListByUser( |
||||
@Param("tenantId") Long tenantId, |
||||
@Param("appCode") String appCode, |
||||
@Param("loginName") String loginName, |
||||
@Param("groupIdSet") Set<String> groupIdSet); |
||||
/** |
||||
* 计算当前用户未读抄送消息的数量。 |
||||
* |
||||
* @param userId 用户Id。 |
||||
* @return 数据数量 |
||||
*/ |
||||
int countSysMessageListByUser(Long userId); |
||||
} |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowMultiInstanceTrans; |
||||
|
||||
/** |
||||
* 流程多实例任务执行流水访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowMultiInstanceTransMapper extends BaseDaoMapper<FlowMultiInstanceTrans> { |
||||
} |
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowNodeTasks; |
||||
|
||||
|
||||
public interface FlowNodeTasksMapper extends BaseDaoMapper<FlowNodeTasks> { |
||||
|
||||
} |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowTaskComment; |
||||
|
||||
/** |
||||
* 流程任务批注数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowTaskCommentMapper extends BaseDaoMapper<FlowTaskComment> { |
||||
} |
||||
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowTaskExt; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 流程任务扩展数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowTaskExtMapper extends BaseDaoMapper<FlowTaskExt> { |
||||
|
||||
/** |
||||
* 批量插入流程任务扩展信息列表。 |
||||
* |
||||
* @param flowTaskExtList 流程任务扩展信息列表。 |
||||
*/ |
||||
void insertList(List<FlowTaskExt> flowTaskExtList); |
||||
} |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowTaskTimeoutJob; |
||||
|
||||
/** |
||||
* 超时任务作业操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowTaskTimeoutJobMapper extends BaseDaoMapper<FlowTaskTimeoutJob> { |
||||
|
||||
} |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowTransProducer; |
||||
|
||||
/** |
||||
* 事务性业务数据生产者访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowTransProducerMapper extends BaseDaoMapper<FlowTransProducer> { |
||||
} |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowVariableLog; |
||||
|
||||
/** |
||||
* 流程请求变量操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowVariableLogMapper extends BaseDaoMapper<FlowVariableLog> { |
||||
|
||||
} |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowWorkOrderExt; |
||||
|
||||
/** |
||||
* 工作流工单扩展数据操作访问接口。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public interface FlowWorkOrderExtMapper extends BaseDaoMapper<FlowWorkOrderExt> { |
||||
|
||||
} |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
package apelet.common.flow.dao; |
||||
|
||||
import apelet.common.core.annotation.EnableDataPerm; |
||||
import apelet.common.core.base.dao.BaseDaoMapper; |
||||
import apelet.common.flow.model.FlowWorkOrder; |
||||
import org.apache.ibatis.annotations.Param; |
||||
import org.apache.ibatis.annotations.Select; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 工作流工单表数据操作访问接口。 |
||||
* 如果当前系统支持数据权限过滤,当前用户必须要能看自己的工单数据,所以需要把EnableDataPerm |
||||
* 的mustIncludeUserRule参数设置为true,即便当前用户的数据权限中并不包含DataPermRuleType.TYPE_USER_ONLY, |
||||
* 数据过滤拦截组件也会自动补偿该类型的数据权限,以便当前用户可以看到自己发起的工单。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@EnableDataPerm(mustIncludeUserRule = true) |
||||
public interface FlowWorkOrderMapper extends BaseDaoMapper<FlowWorkOrder> { |
||||
|
||||
/** |
||||
* 获取过滤后的对象列表。 |
||||
* |
||||
* @param flowWorkOrderFilter 主表过滤对象。 |
||||
* @param orderBy 排序字符串,order by从句的参数。 |
||||
* @return 对象列表。 |
||||
*/ |
||||
List<FlowWorkOrder> getFlowWorkOrderList( |
||||
@Param("flowWorkOrderFilter") FlowWorkOrder flowWorkOrderFilter, @Param("orderBy") String orderBy); |
||||
|
||||
/** |
||||
* 计算指定前缀工单编码的最大值。 |
||||
* |
||||
* @param prefix 工单编码前缀。 |
||||
* @return 该工单编码前缀的最大值。 |
||||
*/ |
||||
@Select("SELECT MAX(work_order_code) FROM zz_flow_work_order WHERE work_order_code LIKE '${prefix}'") |
||||
String getMaxWorkOrderCodeByPrefix(@Param("prefix") String prefix); |
||||
|
||||
/** |
||||
* 根据工单编码查询指定工单,查询过程也会考虑逻辑删除的数据。 |
||||
* @param workOrderCode 工单编码。 |
||||
* @return |
||||
*/ |
||||
@Select("SELECT COUNT(*) FROM zz_flow_work_order WHERE work_order_code = #{workOrderCode}") |
||||
int getCountByWorkOrderCode(@Param("workOrderCode") String workOrderCode); |
||||
} |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowCategoryMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowCategory"> |
||||
<id column="category_id" jdbcType="BIGINT" property="categoryId"/> |
||||
<result column="tenant_id" jdbcType="BIGINT" property="tenantId"/> |
||||
<result column="app_code" jdbcType="VARCHAR" property="appCode"/> |
||||
<result column="name" jdbcType="VARCHAR" property="name"/> |
||||
<result column="code" jdbcType="VARCHAR" property="code"/> |
||||
<result column="show_order" jdbcType="INTEGER" property="showOrder"/> |
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> |
||||
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/> |
||||
</resultMap> |
||||
|
||||
<!-- 如果有逻辑删除字段过滤,请写到这里 --> |
||||
<sql id="filterRef"> |
||||
<!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 --> |
||||
<include refid="apelet.common.flow.dao.FlowCategoryMapper.inputFilterRef"/> |
||||
</sql> |
||||
|
||||
<!-- 这里仅包含调用接口输入的主表过滤条件 --> |
||||
<sql id="inputFilterRef"> |
||||
<if test="flowCategoryFilter != null"> |
||||
<if test="flowCategoryFilter.tenantId == null"> |
||||
AND zz_flow_category.tenant_id IS NULL |
||||
</if> |
||||
<if test="flowCategoryFilter.tenantId != null"> |
||||
AND zz_flow_category.tenant_id = #{flowCategoryFilter.tenantId} |
||||
</if> |
||||
<if test="flowCategoryFilter.appCode == null"> |
||||
AND zz_flow_category.app_code IS NULL |
||||
</if> |
||||
<if test="flowCategoryFilter.appCode != null"> |
||||
AND zz_flow_category.app_code = #{flowCategoryFilter.appCode} |
||||
</if> |
||||
<if test="flowCategoryFilter.name != null and flowCategoryFilter.name != ''"> |
||||
AND zz_flow_category.name = #{flowCategoryFilter.name} |
||||
</if> |
||||
<if test="flowCategoryFilter.code != null and flowCategoryFilter.code != ''"> |
||||
AND zz_flow_category.code = #{flowCategoryFilter.code} |
||||
</if> |
||||
</if> |
||||
</sql> |
||||
|
||||
<select id="getFlowCategoryList" resultMap="BaseResultMap" parameterType="apelet.common.flow.model.FlowCategory"> |
||||
SELECT * FROM zz_flow_category |
||||
<where> |
||||
<include refid="filterRef"/> |
||||
</where> |
||||
<if test="orderBy != null and orderBy != ''"> |
||||
ORDER BY ${orderBy} |
||||
</if> |
||||
</select> |
||||
</mapper> |
||||
@ -0,0 +1,95 @@
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowEntryMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowEntry"> |
||||
<id column="entry_id" jdbcType="BIGINT" property="entryId"/> |
||||
<result column="tenant_id" jdbcType="BIGINT" property="tenantId"/> |
||||
<result column="app_code" jdbcType="VARCHAR" property="appCode"/> |
||||
<result column="process_definition_name" jdbcType="VARCHAR" property="processDefinitionName"/> |
||||
<result column="process_definition_key" jdbcType="VARCHAR" property="processDefinitionKey"/> |
||||
<result column="category_id" jdbcType="BIGINT" property="categoryId"/> |
||||
<result column="main_entry_publish_id" jdbcType="BIGINT" property="mainEntryPublishId"/> |
||||
<result column="latest_publish_time" jdbcType="TIMESTAMP" property="latestPublishTime"/> |
||||
<result column="status" jdbcType="INTEGER" property="status"/> |
||||
<result column="bpmn_xml" jdbcType="LONGVARCHAR" property="bpmnXml"/> |
||||
<result column="diagram_type" jdbcType="INTEGER" property="diagramType"/> |
||||
<result column="bind_form_type" jdbcType="INTEGER" property="bindFormType"/> |
||||
<result column="page_id" jdbcType="BIGINT" property="pageId"/> |
||||
<result column="default_form_id" jdbcType="BIGINT" property="defaultFormId"/> |
||||
<result column="default_router_name" jdbcType="VARCHAR" property="defaultRouterName"/> |
||||
<result column="encoded_rule" jdbcType="VARCHAR" property="encodedRule"/> |
||||
<result column="extension_data" jdbcType="VARCHAR" property="extensionData"/> |
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> |
||||
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/> |
||||
</resultMap> |
||||
|
||||
<!-- 如果有逻辑删除字段过滤,请写到这里 --> |
||||
<sql id="filterRef"> |
||||
<!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 --> |
||||
<include refid="apelet.common.flow.dao.FlowEntryMapper.inputFilterRef"/> |
||||
</sql> |
||||
|
||||
<!-- 这里仅包含调用接口输入的主表过滤条件 --> |
||||
<sql id="inputFilterRef"> |
||||
<if test="flowEntryFilter != null"> |
||||
<if test="flowEntryFilter.tenantId == null"> |
||||
AND zz_flow_entry.tenant_id IS NULL |
||||
</if> |
||||
<if test="flowEntryFilter.tenantId != null"> |
||||
AND zz_flow_entry.tenant_id = #{flowEntryFilter.tenantId} |
||||
</if> |
||||
<if test="flowEntryFilter.appCode == null"> |
||||
AND zz_flow_entry.app_code IS NULL |
||||
</if> |
||||
<if test="flowEntryFilter.appCode != null"> |
||||
AND zz_flow_entry.app_code = #{flowEntryFilter.appCode} |
||||
</if> |
||||
<if test="flowEntryFilter.processDefinitionName != null and flowEntryFilter.processDefinitionName != ''"> |
||||
AND zz_flow_entry.process_definition_name = #{flowEntryFilter.processDefinitionName} |
||||
</if> |
||||
<if test="flowEntryFilter.processDefinitionKey != null and flowEntryFilter.processDefinitionKey != ''"> |
||||
AND zz_flow_entry.process_definition_key = #{flowEntryFilter.processDefinitionKey} |
||||
</if> |
||||
<if test="flowEntryFilter.categoryId != null"> |
||||
AND zz_flow_entry.category_id = #{flowEntryFilter.categoryId} |
||||
</if> |
||||
<if test="flowEntryFilter.status != null"> |
||||
AND zz_flow_entry.status = #{flowEntryFilter.status} |
||||
</if> |
||||
</if> |
||||
</sql> |
||||
|
||||
<select id="getFlowEntryList" resultMap="BaseResultMap" parameterType="apelet.common.flow.model.FlowEntry"> |
||||
SELECT |
||||
entry_id, |
||||
app_code, |
||||
process_definition_name, |
||||
process_definition_key, |
||||
category_id, |
||||
main_entry_publish_id, |
||||
latest_publish_time, |
||||
status, |
||||
diagram_type, |
||||
bind_form_type, |
||||
page_id, |
||||
default_form_id, |
||||
default_router_name, |
||||
encoded_rule, |
||||
extension_data, |
||||
update_time, |
||||
update_user_id, |
||||
create_time, |
||||
create_user_id, |
||||
start_conditions |
||||
FROM |
||||
zz_flow_entry |
||||
<where> |
||||
<include refid="filterRef"/> |
||||
</where> |
||||
<if test="orderBy != null and orderBy != ''"> |
||||
ORDER BY ${orderBy} |
||||
</if> |
||||
</select> |
||||
</mapper> |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowEntryPublishMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowEntryPublish"> |
||||
<id column="entry_publish_id" jdbcType="BIGINT" property="entryPublishId"/> |
||||
<result column="entry_id" jdbcType="BIGINT" property="entryId"/> |
||||
<result column="deploy_id" jdbcType="VARCHAR" property="deployId"/> |
||||
<result column="process_definition_id" jdbcType="VARCHAR" property="processDefinitionId"/> |
||||
<result column="publish_version" jdbcType="INTEGER" property="publishVersion"/> |
||||
<result column="active_status" jdbcType="BOOLEAN" property="activeStatus"/> |
||||
<result column="main_version" jdbcType="BOOLEAN" property="mainVersion"/> |
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/> |
||||
<result column="publish_time" jdbcType="TIMESTAMP" property="publishTime"/> |
||||
<result column="init_task_info" jdbcType="VARCHAR" property="initTaskInfo"/> |
||||
<result column="analyzed_node_json" jdbcType="VARCHAR" property="analyzedNodeJson"/> |
||||
<result column="extension_data" jdbcType="VARCHAR" property="extensionData"/> |
||||
</resultMap> |
||||
</mapper> |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowEntryPublishVariableMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowEntryPublishVariable"> |
||||
<id column="variable_id" jdbcType="BIGINT" property="variableId"/> |
||||
<result column="entry_publish_id" jdbcType="BIGINT" property="entryPublishId"/> |
||||
<result column="variable_name" jdbcType="VARCHAR" property="variableName"/> |
||||
<result column="show_name" jdbcType="VARCHAR" property="showName"/> |
||||
<result column="variable_type" jdbcType="INTEGER" property="variableType"/> |
||||
<result column="bind_datasource_id" jdbcType="BIGINT" property="bindDatasourceId"/> |
||||
<result column="bind_relation_id" jdbcType="BIGINT" property="bindRelationId"/> |
||||
<result column="bind_column_id" jdbcType="BIGINT" property="bindColumnId"/> |
||||
<result column="builtin" jdbcType="BOOLEAN" property="builtin"/> |
||||
</resultMap> |
||||
|
||||
<insert id="insertList"> |
||||
INSERT INTO zz_flow_entry_publish_variable VALUES |
||||
<foreach collection="list" index="index" item="item" separator="," > |
||||
(#{item.variableId}, |
||||
#{item.entryPublishId}, |
||||
#{item.variableName}, |
||||
#{item.showName}, |
||||
#{item.variableType}, |
||||
#{item.bindDatasourceId}, |
||||
#{item.bindRelationId}, |
||||
#{item.bindColumnId}, |
||||
#{item.builtin}) |
||||
</foreach> |
||||
</insert> |
||||
</mapper> |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowEntryVariableMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowEntryVariable"> |
||||
<id column="variable_id" jdbcType="BIGINT" property="variableId"/> |
||||
<result column="entry_id" jdbcType="BIGINT" property="entryId"/> |
||||
<result column="variable_name" jdbcType="VARCHAR" property="variableName"/> |
||||
<result column="show_name" jdbcType="VARCHAR" property="showName"/> |
||||
<result column="variable_type" jdbcType="INTEGER" property="variableType"/> |
||||
<result column="bind_datasource_id" jdbcType="BIGINT" property="bindDatasourceId"/> |
||||
<result column="bind_relation_id" jdbcType="BIGINT" property="bindRelationId"/> |
||||
<result column="bind_column_id" jdbcType="BIGINT" property="bindColumnId"/> |
||||
<result column="builtin" jdbcType="BOOLEAN" property="builtin"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
</resultMap> |
||||
|
||||
<!-- 如果有逻辑删除字段过滤,请写到这里 --> |
||||
<sql id="filterRef"> |
||||
<!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 --> |
||||
<include refid="apelet.common.flow.dao.FlowEntryVariableMapper.inputFilterRef"/> |
||||
</sql> |
||||
|
||||
<!-- 这里仅包含调用接口输入的主表过滤条件 --> |
||||
<sql id="inputFilterRef"> |
||||
<if test="flowEntryVariableFilter != null"> |
||||
<if test="flowEntryVariableFilter.entryId != null"> |
||||
AND zz_flow_entry_variable.entry_id = #{flowEntryVariableFilter.entryId} |
||||
</if> |
||||
</if> |
||||
</sql> |
||||
|
||||
<select id="getFlowEntryVariableList" resultMap="BaseResultMap" parameterType="apelet.common.flow.model.FlowEntryVariable"> |
||||
SELECT * FROM zz_flow_entry_variable |
||||
<where> |
||||
<include refid="filterRef"/> |
||||
</where> |
||||
<if test="orderBy != null and orderBy != ''"> |
||||
ORDER BY ${orderBy} |
||||
</if> |
||||
</select> |
||||
</mapper> |
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowMessageCandidateIdentityMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowMessageCandidateIdentity"> |
||||
<id column="id" jdbcType="BIGINT" property="id"/> |
||||
<result column="message_id" jdbcType="BIGINT" property="messageId"/> |
||||
<result column="candidate_type" jdbcType="VARCHAR" property="candidateType"/> |
||||
<result column="candidate_id" jdbcType="VARCHAR" property="candidateId"/> |
||||
</resultMap> |
||||
|
||||
<delete id="deleteByProcessInstanceId"> |
||||
DELETE FROM zz_flow_msg_candidate_identity a |
||||
WHERE EXISTS (SELECT * FROM zz_flow_message b |
||||
WHERE a.message_id = b.message_id AND b.process_instance_id = #{processInstanceId}) |
||||
</delete> |
||||
</mapper> |
||||
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowMessageIdentityOperationMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowMessageIdentityOperation"> |
||||
<id column="id" jdbcType="BIGINT" property="id"/> |
||||
<result column="message_id" jdbcType="BIGINT" property="messageId"/> |
||||
<result column="login_name" jdbcType="VARCHAR" property="loginName"/> |
||||
<result column="operation_type" jdbcType="INTEGER" property="operationType"/> |
||||
<result column="operation_time" jdbcType="TIMESTAMP" property="operationTime"/> |
||||
</resultMap> |
||||
|
||||
<delete id="deleteByProcessInstanceId"> |
||||
DELETE FROM zz_flow_msg_identity_operation a |
||||
WHERE EXISTS (SELECT * FROM zz_flow_message b |
||||
WHERE a.message_id = b.message_id AND b.process_instance_id = #{processInstanceId}) |
||||
</delete> |
||||
</mapper> |
||||
@ -0,0 +1,119 @@
@@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowMessageMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowMessage"> |
||||
<id column="message_id" jdbcType="BIGINT" property="messageId"/> |
||||
<result column="tenant_id" jdbcType="BIGINT" property="tenantId"/> |
||||
<result column="app_code" jdbcType="VARCHAR" property="appCode"/> |
||||
<result column="message_type" jdbcType="TINYINT" property="messageType"/> |
||||
<result column="message_content" jdbcType="VARCHAR" property="messageContent"/> |
||||
<result column="remind_count" jdbcType="INTEGER" property="remindCount"/> |
||||
<result column="work_order_id" jdbcType="BIGINT" property="workOrderId"/> |
||||
<result column="process_definition_id" jdbcType="VARCHAR" property="processDefinitionId"/> |
||||
<result column="process_definition_key" jdbcType="VARCHAR" property="processDefinitionKey"/> |
||||
<result column="process_definition_name" jdbcType="VARCHAR" property="processDefinitionName"/> |
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/> |
||||
<result column="process_instance_initiator" jdbcType="VARCHAR" property="processInstanceInitiator"/> |
||||
<result column="task_id" jdbcType="VARCHAR" property="taskId"/> |
||||
<result column="task_definition_key" jdbcType="VARCHAR" property="taskDefinitionKey"/> |
||||
<result column="task_name" jdbcType="VARCHAR" property="taskName"/> |
||||
<result column="task_start_time" jdbcType="TIMESTAMP" property="taskStartTime"/> |
||||
<result column="task_assignee" jdbcType="VARCHAR" property="taskAssignee"/> |
||||
<result column="task_finished" jdbcType="BOOLEAN" property="taskFinished"/> |
||||
<result column="business_data_shot" jdbcType="LONGVARCHAR" property="businessDataShot"/> |
||||
<result column="online_form_data" jdbcType="BOOLEAN" property="onlineFormData"/> |
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> |
||||
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/> |
||||
<result column="create_username" jdbcType="VARCHAR" property="createUsername"/> |
||||
</resultMap> |
||||
|
||||
<sql id="filterRef"> |
||||
<if test="tenantId == null"> |
||||
AND a.tenant_id IS NULL |
||||
</if> |
||||
<if test="tenantId != null"> |
||||
AND a.tenant_id = #{tenantId} |
||||
</if> |
||||
<if test="appCode == null"> |
||||
AND a.app_code IS NULL |
||||
</if> |
||||
<if test="appCode != null"> |
||||
AND a.app_code = #{appCode} |
||||
</if> |
||||
</sql> |
||||
|
||||
<select id="getRemindingMessageListByUser" resultMap="BaseResultMap"> |
||||
SELECT a.* FROM zz_flow_message a |
||||
<where> |
||||
<include refid="filterRef"/> |
||||
AND a.task_finished = false |
||||
AND a.message_type = 0 |
||||
AND (a.task_assignee = #{loginName} OR EXISTS (SELECT * FROM zz_flow_msg_candidate_identity b |
||||
WHERE a.message_id = b.message_id AND b.candidate_id IN |
||||
<foreach collection="groupIdSet" index="index" item="item" separator="," open="(" close=")"> |
||||
#{item} |
||||
</foreach>)) |
||||
</where> |
||||
ORDER BY a.update_time DESC |
||||
</select> |
||||
|
||||
<select id="getCopyMessageListByUser" resultMap="BaseResultMap"> |
||||
SELECT a.* FROM zz_flow_message a |
||||
<where> |
||||
<include refid="filterRef"/> |
||||
AND a.message_type = 1 |
||||
AND EXISTS (SELECT * FROM zz_flow_msg_candidate_identity b |
||||
WHERE a.message_id = b.message_id AND b.candidate_id IN |
||||
<foreach collection="groupIdSet" index="index" item="item" separator="," open="(" close=")"> |
||||
#{item} |
||||
</foreach>) |
||||
<if test="!read"> |
||||
AND NOT EXISTS (SELECT * FROM zz_flow_msg_identity_operation c |
||||
WHERE a.message_id = c.message_id AND c.login_name = #{loginName}) |
||||
</if> |
||||
<if test="read"> |
||||
AND EXISTS (SELECT * FROM zz_flow_msg_identity_operation c |
||||
WHERE a.message_id = c.message_id AND c.login_name = #{loginName}) |
||||
</if> |
||||
</where> |
||||
ORDER BY a.update_time DESC |
||||
</select> |
||||
|
||||
<select id="countRemindingMessageListByUser" resultType="java.lang.Integer"> |
||||
SELECT COUNT(1) FROM zz_flow_message a |
||||
<where> |
||||
<include refid="filterRef"/> |
||||
AND a.task_finished = false |
||||
AND a.message_type = 0 |
||||
AND (a.task_assignee = #{loginName} OR EXISTS (SELECT * FROM zz_flow_msg_candidate_identity b |
||||
WHERE a.message_id = b.message_id AND b.candidate_id IN |
||||
<foreach collection="groupIdSet" index="index" item="item" separator="," open="(" close=")"> |
||||
#{item} |
||||
</foreach>)) |
||||
</where> |
||||
</select> |
||||
|
||||
<select id="countCopyMessageListByUser" resultType="java.lang.Integer"> |
||||
SELECT COUNT(1) FROM zz_flow_message a |
||||
<where> |
||||
<include refid="filterRef"/> |
||||
AND a.message_type = 1 |
||||
AND EXISTS (SELECT * FROM zz_flow_msg_candidate_identity b |
||||
WHERE a.message_id = b.message_id AND b.candidate_id IN |
||||
<foreach collection="groupIdSet" index="index" item="item" separator="," open="(" close=")"> |
||||
#{item} |
||||
</foreach>) |
||||
AND NOT EXISTS (SELECT * FROM zz_flow_msg_identity_operation c |
||||
WHERE a.message_id = c.message_id AND c.login_name = #{loginName}) |
||||
</where> |
||||
</select> |
||||
<select id="countSysMessageListByUser" resultType="java.lang.Integer"> |
||||
SELECT COUNT(1) FROM sys_message_entry a |
||||
<where> |
||||
AND a.read_status = 0 |
||||
and a.receive_user_id=#{userId} |
||||
</where> |
||||
</select> |
||||
</mapper> |
||||
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowMultiInstanceTransMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowMultiInstanceTrans"> |
||||
<id column="id" jdbcType="BIGINT" property="id"/> |
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/> |
||||
<result column="task_id" jdbcType="VARCHAR" property="taskId"/> |
||||
<result column="task_key" jdbcType="VARCHAR" property="taskKey"/> |
||||
<result column="multi_instance_exec_id" jdbcType="VARCHAR" property="multiInstanceExecId"/> |
||||
<result column="execution_id" jdbcType="VARCHAR" property="executionId"/> |
||||
<result column="assignee_list" jdbcType="LONGVARCHAR" property="assigneeList"/> |
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/> |
||||
<result column="create_login_name" jdbcType="VARCHAR" property="createLoginName"/> |
||||
<result column="create_username" jdbcType="VARCHAR" property="createUsername"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
</resultMap> |
||||
</mapper> |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowTaskCommentMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowTaskComment"> |
||||
<id column="id" jdbcType="BIGINT" property="id"/> |
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/> |
||||
<result column="task_id" jdbcType="VARCHAR" property="taskId"/> |
||||
<result column="task_key" jdbcType="VARCHAR" property="taskKey"/> |
||||
<result column="task_name" jdbcType="VARCHAR" property="taskName"/> |
||||
<result column="target_task_key" jdbcType="VARCHAR" property="targetTaskKey"/> |
||||
<result column="execution_id" jdbcType="VARCHAR" property="executionId"/> |
||||
<result column="multi_instance_exec_id" jdbcType="VARCHAR" property="multiInstanceExecId"/> |
||||
<result column="approval_type" jdbcType="VARCHAR" property="approvalType"/> |
||||
<result column="delegate_assignee" jdbcType="VARCHAR" property="delegateAssignee"/> |
||||
<result column="custom_business_data" jdbcType="LONGVARCHAR" property="customBusinessData"/> |
||||
<result column="task_comment" jdbcType="VARCHAR" property="taskComment"/> |
||||
<result column="head_image_url" jdbcType="VARCHAR" property="headImageUrl"/> |
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/> |
||||
<result column="create_login_name" jdbcType="VARCHAR" property="createLoginName"/> |
||||
<result column="create_username" jdbcType="VARCHAR" property="createUsername"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
</resultMap> |
||||
</mapper> |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowTaskExtMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowTaskExt"> |
||||
<result column="process_definition_id" jdbcType="VARCHAR" property="processDefinitionId"/> |
||||
<result column="task_id" jdbcType="VARCHAR" property="taskId"/> |
||||
<result column="operation_list_json" jdbcType="LONGVARCHAR" property="operationListJson"/> |
||||
<result column="variable_list_json" jdbcType="LONGVARCHAR" property="variableListJson"/> |
||||
<result column="assignee_list_json" jdbcType="LONGVARCHAR" property="assigneeListJson"/> |
||||
<result column="group_type" jdbcType="VARCHAR" property="groupType"/> |
||||
<result column="dept_post_list_json" jdbcType="VARCHAR" property="deptPostListJson"/> |
||||
<result column="role_ids" jdbcType="VARCHAR" property="roleIds"/> |
||||
<result column="dept_ids" jdbcType="VARCHAR" property="deptIds"/> |
||||
<result column="candidate_usernames" jdbcType="VARCHAR" property="candidateUsernames"/> |
||||
<result column="copy_list_json" jdbcType="VARCHAR" property="copyListJson"/> |
||||
<result column="extra_data_json" jdbcType="VARCHAR" property="extraDataJson"/> |
||||
</resultMap> |
||||
|
||||
<insert id="insertList"> |
||||
INSERT INTO zz_flow_task_ext VALUES |
||||
<foreach collection="list" index="index" item="item" separator="," > |
||||
(#{item.processDefinitionId}, |
||||
#{item.taskId}, |
||||
#{item.operationListJson}, |
||||
#{item.variableListJson}, |
||||
#{item.assigneeListJson}, |
||||
#{item.groupType}, |
||||
#{item.deptPostListJson}, |
||||
#{item.roleIds}, |
||||
#{item.deptIds}, |
||||
#{item.candidateUsernames}, |
||||
#{item.copyListJson}, |
||||
#{item.extraDataJson}) |
||||
</foreach> |
||||
</insert> |
||||
</mapper> |
||||
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowTaskTimeoutJobMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowTaskTimeoutJob"> |
||||
<id column="id" jdbcType="BIGINT" property="id"/> |
||||
<result column="process_definition_id" jdbcType="VARCHAR" property="processDefinitionId"/> |
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/> |
||||
<result column="task_key" jdbcType="VARCHAR" property="taskKey"/> |
||||
<result column="task_id" jdbcType="VARCHAR" property="taskId"/> |
||||
<result column="timeout_hours" jdbcType="INTEGER" property="timeoutHours"/> |
||||
<result column="handle_way" jdbcType="VARCHAR" property="handleWay"/> |
||||
<result column="default_assignee" jdbcType="VARCHAR" property="defaultAssignee"/> |
||||
<result column="status" jdbcType="INTEGER" property="status"/> |
||||
<result column="error_message" jdbcType="LONGVARCHAR" property="errorMessage"/> |
||||
<result column="exec_time" jdbcType="TIMESTAMP" property="execTime"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> |
||||
</resultMap> |
||||
</mapper> |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowTransProducerMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowTransProducer"> |
||||
<id column="trans_id" jdbcType="BIGINT" property="transId"/> |
||||
<result column="app_code" jdbcType="VARCHAR" property="appCode"/> |
||||
<result column="dblink_id" jdbcType="BIGINT" property="dblinkId"/> |
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/> |
||||
<result column="task_id" jdbcType="VARCHAR" property="taskId"/> |
||||
<result column="task_key" jdbcType="VARCHAR" property="taskKey"/> |
||||
<result column="task_name" jdbcType="VARCHAR" property="taskName"/> |
||||
<result column="task_comment" jdbcType="VARCHAR" property="taskComment"/> |
||||
<result column="url" jdbcType="VARCHAR" property="url"/> |
||||
<result column="init_method" jdbcType="VARCHAR" property="initMethod"/> |
||||
<result column="trace_id" jdbcType="VARCHAR" property="traceId"/> |
||||
<result column="sql_data" jdbcType="LONGVARCHAR" property="sqlData"/> |
||||
<result column="try_times" jdbcType="INTEGER" property="tryTimes"/> |
||||
<result column="error_reason" jdbcType="LONGVARCHAR" property="errorReason"/> |
||||
<result column="create_login_name" jdbcType="VARCHAR" property="createUsername"/> |
||||
<result column="create_username" jdbcType="VARCHAR" property="createLoginName"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
</resultMap> |
||||
</mapper> |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowVariableLogMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowVariableLog"> |
||||
<id column="id" jdbcType="BIGINT" property="id"/> |
||||
<result column="process_definition_key" jdbcType="VARCHAR" property="processDefinitionKey"/> |
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/> |
||||
<result column="task_key" jdbcType="VARCHAR" property="taskKey"/> |
||||
<result column="variable_data" jdbcType="LONGVARCHAR" property="variableData"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
<result column="expired_time" jdbcType="TIMESTAMP" property="expiredTime"/> |
||||
</resultMap> |
||||
</mapper> |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowWorkOrderExtMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowWorkOrderExt"> |
||||
<id column="id" jdbcType="BIGINT" property="id"/> |
||||
<result column="work_order_id" jdbcType="BIGINT" property="workOrderId"/> |
||||
<result column="draft_data" jdbcType="LONGVARCHAR" property="draftData"/> |
||||
<result column="business_data" jdbcType="LONGVARCHAR" property="businessData"/> |
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> |
||||
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/> |
||||
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/> |
||||
</resultMap> |
||||
</mapper> |
||||
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
<mapper namespace="apelet.common.flow.dao.FlowWorkOrderMapper"> |
||||
<resultMap id="BaseResultMap" type="apelet.common.flow.model.FlowWorkOrder"> |
||||
<id column="work_order_id" jdbcType="BIGINT" property="workOrderId"/> |
||||
<result column="tenant_id" jdbcType="BIGINT" property="tenantId"/> |
||||
<result column="app_code" jdbcType="VARCHAR" property="appCode"/> |
||||
<result column="work_order_code" jdbcType="VARCHAR" property="workOrderCode"/> |
||||
<result column="process_definition_key" jdbcType="VARCHAR" property="processDefinitionKey"/> |
||||
<result column="process_definition_name" jdbcType="VARCHAR" property="processDefinitionName"/> |
||||
<result column="process_definition_id" jdbcType="VARCHAR" property="processDefinitionId"/> |
||||
<result column="process_instance_id" jdbcType="VARCHAR" property="processInstanceId"/> |
||||
<result column="online_table_id" jdbcType="BIGINT" property="onlineTableId"/> |
||||
<result column="table_name" jdbcType="VARCHAR" property="tableName"/> |
||||
<result column="business_key" jdbcType="VARCHAR" property="businessKey"/> |
||||
<result column="latest_approval_status" jdbcType="INTEGER" property="latestApprovalStatus"/> |
||||
<result column="flow_status" jdbcType="INTEGER" property="flowStatus"/> |
||||
<result column="submit_username" jdbcType="VARCHAR" property="submitUsername"/> |
||||
<result column="dept_id" jdbcType="BIGINT" property="deptId"/> |
||||
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/> |
||||
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/> |
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> |
||||
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/> |
||||
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/> |
||||
</resultMap> |
||||
|
||||
<!-- 如果有逻辑删除字段过滤,请写到这里 --> |
||||
<sql id="filterRef"> |
||||
<!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 --> |
||||
<include refid="apelet.common.flow.dao.FlowWorkOrderMapper.inputFilterRef"/> |
||||
AND zz_flow_work_order.deleted_flag = ${@apelet.common.core.constant.GlobalDeletedFlag@NORMAL} |
||||
</sql> |
||||
|
||||
<!-- 这里仅包含调用接口输入的主表过滤条件 --> |
||||
<sql id="inputFilterRef"> |
||||
<if test="flowWorkOrderFilter != null"> |
||||
<if test="flowWorkOrderFilter.tenantId == null"> |
||||
AND zz_flow_work_order.tenant_id IS NULL |
||||
</if> |
||||
<if test="flowWorkOrderFilter.tenantId != null"> |
||||
AND zz_flow_work_order.tenant_id = #{flowWorkOrderFilter.tenantId} |
||||
</if> |
||||
<if test="flowWorkOrderFilter.appCode == null"> |
||||
AND zz_flow_work_order.app_code IS NULL |
||||
</if> |
||||
<if test="flowWorkOrderFilter.appCode != null"> |
||||
AND zz_flow_work_order.app_code = #{flowWorkOrderFilter.appCode} |
||||
</if> |
||||
<if test="flowWorkOrderFilter.workOrderCode != null and flowWorkOrderFilter.workOrderCode != ''"> |
||||
AND zz_flow_work_order.work_order_code = #{flowWorkOrderFilter.workOrderCode} |
||||
</if> |
||||
<if test="flowWorkOrderFilter.processDefinitionKey != null and flowWorkOrderFilter.processDefinitionKey != ''"> |
||||
AND zz_flow_work_order.process_definition_key = #{flowWorkOrderFilter.processDefinitionKey} |
||||
</if> |
||||
<if test="flowWorkOrderFilter.latestApprovalStatus != null"> |
||||
AND zz_flow_work_order.latest_approval_status = #{flowWorkOrderFilter.latestApprovalStatus} |
||||
</if> |
||||
<if test="flowWorkOrderFilter.flowStatus != null"> |
||||
AND zz_flow_work_order.flow_status = #{flowWorkOrderFilter.flowStatus} |
||||
</if> |
||||
<if test="flowWorkOrderFilter.createTimeStart != null and flowWorkOrderFilter.createTimeStart != ''"> |
||||
AND zz_flow_work_order.create_time >= #{flowWorkOrderFilter.createTimeStart} |
||||
</if> |
||||
<if test="flowWorkOrderFilter.createTimeEnd != null and flowWorkOrderFilter.createTimeEnd != ''"> |
||||
AND zz_flow_work_order.create_time <= #{flowWorkOrderFilter.createTimeEnd} |
||||
</if> |
||||
<if test="flowWorkOrderFilter.createUserId != null"> |
||||
AND zz_flow_work_order.create_user_id = #{flowWorkOrderFilter.createUserId} |
||||
</if> |
||||
</if> |
||||
</sql> |
||||
|
||||
<select id="getFlowWorkOrderList" resultMap="BaseResultMap" parameterType="apelet.common.flow.model.FlowWorkOrder"> |
||||
SELECT * FROM zz_flow_work_order |
||||
<where> |
||||
<include refid="filterRef"/> |
||||
</where> |
||||
<if test="orderBy != null and orderBy != ''"> |
||||
ORDER BY ${orderBy} |
||||
</if> |
||||
</select> |
||||
</mapper> |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
package apelet.common.flow.dto; |
||||
|
||||
import apelet.common.core.validator.UpdateGroup; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
import javax.validation.constraints.NotBlank; |
||||
import javax.validation.constraints.NotNull; |
||||
|
||||
/** |
||||
* 流程分类的Dto对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Schema(description = "流程分类的Dto对象") |
||||
@Data |
||||
public class FlowCategoryDto { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@Schema(description = "主键Id") |
||||
@NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class}) |
||||
private Long categoryId; |
||||
|
||||
/** |
||||
* 显示名称。 |
||||
*/ |
||||
@Schema(description = "显示名称") |
||||
@NotBlank(message = "数据验证失败,显示名称不能为空!") |
||||
private String name; |
||||
|
||||
/** |
||||
* 分类编码。 |
||||
*/ |
||||
@Schema(description = "分类编码") |
||||
@NotBlank(message = "数据验证失败,分类编码不能为空!") |
||||
private String code; |
||||
|
||||
/** |
||||
* 实现顺序。 |
||||
*/ |
||||
@Schema(description = "实现顺序") |
||||
@NotNull(message = "数据验证失败,实现顺序不能为空!") |
||||
private Integer showOrder; |
||||
} |
||||
@ -0,0 +1,114 @@
@@ -0,0 +1,114 @@
|
||||
package apelet.common.flow.dto; |
||||
|
||||
import apelet.common.core.validator.ConstDictRef; |
||||
import apelet.common.core.validator.UpdateGroup; |
||||
import apelet.common.flow.model.constant.FlowBindFormType; |
||||
import apelet.common.flow.model.constant.FlowEntryStatus; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
import javax.validation.constraints.NotBlank; |
||||
import javax.validation.constraints.NotNull; |
||||
|
||||
/** |
||||
* 流程的Dto对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Schema(description = "流程的Dto对象") |
||||
@Data |
||||
public class FlowEntryDto { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@Schema(description = "主键Id") |
||||
@NotNull(message = "数据验证失败,主键不能为空!", groups = {UpdateGroup.class}) |
||||
private Long entryId; |
||||
|
||||
/** |
||||
* 流程名称。 |
||||
*/ |
||||
@Schema(description = "流程名称") |
||||
@NotBlank(message = "数据验证失败,流程名称不能为空!") |
||||
private String processDefinitionName; |
||||
|
||||
/** |
||||
* 流程标识Key。 |
||||
*/ |
||||
@Schema(description = "流程标识Key") |
||||
@NotBlank(message = "数据验证失败,流程标识Key不能为空!") |
||||
private String processDefinitionKey; |
||||
|
||||
/** |
||||
* 流程分类。 |
||||
*/ |
||||
@Schema(description = "流程分类") |
||||
@NotNull(message = "数据验证失败,流程分类不能为空!") |
||||
private Long categoryId; |
||||
|
||||
/** |
||||
* 流程状态。 |
||||
*/ |
||||
@Schema(description = "流程状态") |
||||
@ConstDictRef(constDictClass = FlowEntryStatus.class, message = "数据验证失败,工作流状态为无效值!") |
||||
private Integer status; |
||||
|
||||
/** |
||||
* 流程定义的xml。 |
||||
*/ |
||||
@Schema(description = "流程定义的xml") |
||||
private String bpmnXml; |
||||
|
||||
/** |
||||
* 流程图类型。0: 普通流程图,1: 钉钉风格的流程图。 |
||||
*/ |
||||
@Schema(description = "流程图类型。0: 普通流程图,1: 钉钉风格的流程图。") |
||||
private Integer diagramType; |
||||
|
||||
/** |
||||
* 绑定表单类型。 |
||||
*/ |
||||
@Schema(description = "绑定表单类型") |
||||
@ConstDictRef(constDictClass = FlowBindFormType.class, message = "数据验证失败,工作流绑定表单类型为无效值!") |
||||
@NotNull(message = "数据验证失败,工作流绑定表单类型不能为空!") |
||||
private Integer bindFormType; |
||||
|
||||
/** |
||||
* 在线表单的页面Id。 |
||||
*/ |
||||
@Schema(description = "在线表单的页面Id") |
||||
private Long pageId; |
||||
|
||||
/** |
||||
* 在线表单的缺省路由名称。 |
||||
*/ |
||||
@Schema(description = "在线表单的缺省路由名称") |
||||
private String defaultRouterName; |
||||
|
||||
/** |
||||
* 在线表单Id。 |
||||
*/ |
||||
@Schema(description = "在线表单Id") |
||||
private Long defaultFormId; |
||||
|
||||
/** |
||||
* 工单表编码字段的编码规则,如果为空则不计算工单编码。 |
||||
*/ |
||||
@Schema(description = "工单表编码字段的编码规则") |
||||
private String encodedRule; |
||||
|
||||
/** |
||||
* 流程的自定义扩展数据(JSON格式)。 |
||||
*/ |
||||
@Schema(description = "流程的自定义扩展数据") |
||||
private String extensionData; |
||||
|
||||
|
||||
/** |
||||
* 流程启动条件 |
||||
*/ |
||||
@Schema(description = "流程启动条件") |
||||
private String startConditions; |
||||
} |
||||
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
package apelet.common.flow.dto; |
||||
|
||||
import apelet.common.core.validator.ConstDictRef; |
||||
import apelet.common.core.validator.UpdateGroup; |
||||
import apelet.common.flow.model.constant.FlowVariableType; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
import javax.validation.constraints.NotBlank; |
||||
import javax.validation.constraints.NotNull; |
||||
|
||||
/** |
||||
* 流程变量Dto对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Schema(description = "流程变量Dto对象") |
||||
@Data |
||||
public class FlowEntryVariableDto { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@Schema(description = "主键Id") |
||||
@NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class}) |
||||
private Long variableId; |
||||
|
||||
/** |
||||
* 流程Id。 |
||||
*/ |
||||
@Schema(description = "流程Id") |
||||
@NotNull(message = "数据验证失败,流程Id不能为空!") |
||||
private Long entryId; |
||||
|
||||
/** |
||||
* 变量名。 |
||||
*/ |
||||
@Schema(description = "变量名") |
||||
@NotBlank(message = "数据验证失败,变量名不能为空!") |
||||
private String variableName; |
||||
|
||||
/** |
||||
* 显示名。 |
||||
*/ |
||||
@Schema(description = "显示名") |
||||
@NotBlank(message = "数据验证失败,显示名不能为空!") |
||||
private String showName; |
||||
|
||||
/** |
||||
* 流程变量类型。 |
||||
*/ |
||||
@Schema(description = "流程变量类型") |
||||
@ConstDictRef(constDictClass = FlowVariableType.class, message = "数据验证失败,流程变量类型为无效值!") |
||||
@NotNull(message = "数据验证失败,流程变量类型不能为空!") |
||||
private Integer variableType; |
||||
|
||||
/** |
||||
* 绑定数据源Id。 |
||||
*/ |
||||
@Schema(description = "绑定数据源Id") |
||||
private Long bindDatasourceId; |
||||
|
||||
/** |
||||
* 绑定数据源关联Id。 |
||||
*/ |
||||
@Schema(description = "绑定数据源关联Id") |
||||
private Long bindRelationId; |
||||
|
||||
/** |
||||
* 绑定字段Id。 |
||||
*/ |
||||
@Schema(description = "绑定字段Id") |
||||
private Long bindColumnId; |
||||
|
||||
/** |
||||
* 是否内置。 |
||||
*/ |
||||
@Schema(description = "是否内置") |
||||
@NotNull(message = "数据验证失败,是否内置不能为空!") |
||||
private Boolean builtin; |
||||
} |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
package apelet.common.flow.dto; |
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 工作流通知消息Dto对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Schema(description = "工作流通知消息Dto对象") |
||||
@Data |
||||
public class FlowMessageDto { |
||||
|
||||
/** |
||||
* 消息类型。 |
||||
*/ |
||||
@Schema(description = "消息类型") |
||||
private Integer messageType; |
||||
|
||||
/** |
||||
* 工单Id。 |
||||
*/ |
||||
@Schema(description = "工单Id") |
||||
private Long workOrderId; |
||||
|
||||
/** |
||||
* 流程名称。 |
||||
*/ |
||||
@Schema(description = "流程名称") |
||||
private String processDefinitionName; |
||||
|
||||
/** |
||||
* 流程任务名称。 |
||||
*/ |
||||
@Schema(description = "流程任务名称") |
||||
private String taskName; |
||||
|
||||
/** |
||||
* 更新时间范围过滤起始值(>=)。 |
||||
*/ |
||||
@Schema(description = "updateTime 范围过滤起始值") |
||||
private String updateTimeStart; |
||||
|
||||
/** |
||||
* 更新时间范围过滤结束值(<=)。 |
||||
*/ |
||||
@Schema(description = "updateTime 范围过滤结束值") |
||||
private String updateTimeEnd; |
||||
} |
||||
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
package apelet.common.flow.dto; |
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
import javax.validation.constraints.NotBlank; |
||||
import javax.validation.constraints.NotNull; |
||||
|
||||
/** |
||||
* 流程任务的批注。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Schema(description = "流程任务的批注") |
||||
@Data |
||||
public class FlowTaskCommentDto { |
||||
|
||||
/** |
||||
* 流程任务触发按钮类型,内置值可参考FlowTaskButton。 |
||||
*/ |
||||
@Schema(description = "流程任务触发按钮类型") |
||||
@NotNull(message = "数据验证失败,任务的审批类型不能为空!") |
||||
private String approvalType; |
||||
|
||||
/** |
||||
* 流程任务的批注内容。 |
||||
*/ |
||||
@Schema(description = "流程任务的批注内容") |
||||
@NotBlank(message = "数据验证失败,任务审批内容不能为空!") |
||||
private String taskComment; |
||||
|
||||
/** |
||||
* 委托指定人,比如加签、转办等。 |
||||
*/ |
||||
@Schema(description = "委托指定人,比如加签、转办等") |
||||
private String delegateAssignee; |
||||
} |
||||
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
package apelet.common.flow.dto; |
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 工作流工单Dto对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Schema(description = "工作流工单Dto对象") |
||||
@Data |
||||
public class FlowWorkOrderDto { |
||||
|
||||
/** |
||||
* 工单编码。 |
||||
*/ |
||||
@Schema(description = "工单编码") |
||||
private String workOrderCode; |
||||
|
||||
/** |
||||
* 流程状态。参考FlowTaskStatus常量值对象。 |
||||
*/ |
||||
@Schema(description = "流程状态") |
||||
private Integer flowStatus; |
||||
|
||||
/** |
||||
* createTime 范围过滤起始值(>=)。 |
||||
*/ |
||||
@Schema(description = "createTime 范围过滤起始值") |
||||
private String createTimeStart; |
||||
|
||||
/** |
||||
* createTime 范围过滤结束值(<=)。 |
||||
*/ |
||||
@Schema(description = "createTime 范围过滤结束值") |
||||
private String createTimeEnd; |
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
package apelet.common.flow.exception; |
||||
|
||||
/** |
||||
* 流程空用户异常。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public class FlowEmptyUserException extends RuntimeException { |
||||
|
||||
/** |
||||
* 构造函数。 |
||||
*/ |
||||
public FlowEmptyUserException() { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 构造函数。 |
||||
* |
||||
* @param throwable 引发异常对象。 |
||||
*/ |
||||
public FlowEmptyUserException(Throwable throwable) { |
||||
super(throwable); |
||||
} |
||||
|
||||
/** |
||||
* 构造函数。 |
||||
* |
||||
* @param msg 错误信息。 |
||||
*/ |
||||
public FlowEmptyUserException(String msg) { |
||||
super(msg); |
||||
} |
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
package apelet.common.flow.exception; |
||||
|
||||
/** |
||||
* 流程操作异常。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public class FlowOperationException extends RuntimeException { |
||||
|
||||
/** |
||||
* 构造函数。 |
||||
*/ |
||||
public FlowOperationException() { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 构造函数。 |
||||
* |
||||
* @param throwable 引发异常对象。 |
||||
*/ |
||||
public FlowOperationException(Throwable throwable) { |
||||
super(throwable); |
||||
} |
||||
|
||||
/** |
||||
* 构造函数。 |
||||
* |
||||
* @param msg 错误信息。 |
||||
*/ |
||||
public FlowOperationException(String msg) { |
||||
super(msg); |
||||
} |
||||
} |
||||
@ -0,0 +1,161 @@
@@ -0,0 +1,161 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.object.TokenData; |
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.constant.FlowApprovalType; |
||||
import apelet.common.flow.constant.FlowConstant; |
||||
import apelet.common.flow.model.FlowTaskComment; |
||||
import apelet.common.flow.model.FlowTaskExt; |
||||
import apelet.common.flow.service.FlowApiService; |
||||
import apelet.common.flow.service.FlowTaskCommentService; |
||||
import apelet.common.flow.service.FlowTaskExtService; |
||||
import cn.hutool.core.collection.CollUtil; |
||||
import cn.hutool.core.text.StrFormatter; |
||||
import cn.hutool.core.util.ObjectUtil; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.bpmn.model.ExtensionAttribute; |
||||
import org.flowable.bpmn.model.UserTask; |
||||
import org.flowable.engine.delegate.DelegateExecution; |
||||
import org.flowable.engine.delegate.ExecutionListener; |
||||
|
||||
import java.util.*; |
||||
|
||||
/** |
||||
* 流程任务自动审批跳过的监听器。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class AutoSkipListener implements ExecutionListener { |
||||
|
||||
private final transient FlowTaskCommentService flowTaskCommentService = |
||||
ApplicationContextHolder.getBean(FlowTaskCommentService.class); |
||||
private final transient FlowApiService flowApiService = |
||||
ApplicationContextHolder.getBean(FlowApiService.class); |
||||
private final transient FlowTaskExtService flowTaskExtService = |
||||
ApplicationContextHolder.getBean(FlowTaskExtService.class); |
||||
|
||||
/** |
||||
* 流程的发起者等于当前任务的Assignee。 |
||||
*/ |
||||
private static final String EQ_START_USER = "0"; |
||||
/** |
||||
* 上一步的提交者等于当前任务的Assignee。 |
||||
*/ |
||||
private static final String EQ_PREV_SUBMIT_USER = "1"; |
||||
/** |
||||
* 当前任务的Assignee之前提交过审核。 |
||||
*/ |
||||
private static final String EQ_HISTORIC_SUBMIT_USER = "2"; |
||||
|
||||
@Override |
||||
public void notify(DelegateExecution execution) { |
||||
UserTask userTask = (UserTask) execution.getCurrentFlowElement(); |
||||
List<ExtensionAttribute> attributes = userTask.getAttributes().get(FlowConstant.USER_TASK_AUTO_SKIP_KEY); |
||||
Set<String> skipTypes = new HashSet<>(StrUtil.split(attributes.get(0).getValue(), ",")); |
||||
String assignedUser = this.getAssignedUser(execution); |
||||
if (StrUtil.isBlank(assignedUser)) { |
||||
return; |
||||
} |
||||
for (String skipType : skipTypes) { |
||||
if (this.verifyAndHandle(execution, skipType, assignedUser)) { |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private boolean verifyAndHandle(DelegateExecution execution, String skipType, String assignedUser) { |
||||
FlowTaskComment comment = null; |
||||
switch (skipType) { |
||||
case EQ_START_USER: |
||||
Object v = execution.getVariable(FlowConstant.PROC_INSTANCE_START_USER_NAME_VAR); |
||||
if (ObjectUtil.equal(v, assignedUser)) { |
||||
comment = flowTaskCommentService.getFirstFlowTaskComment(execution.getProcessInstanceId()); |
||||
} |
||||
break; |
||||
case EQ_PREV_SUBMIT_USER: |
||||
Object v2 = execution.getVariable(FlowConstant.SUBMIT_USER_VAR); |
||||
if (ObjectUtil.equal(v2, assignedUser)) { |
||||
TokenData tokenData = TokenData.takeFromRequest(); |
||||
comment = new FlowTaskComment(); |
||||
comment.setCreateUserId(tokenData.getUserId()); |
||||
comment.setCreateLoginName(tokenData.getLoginName()); |
||||
comment.setCreateUsername(tokenData.getShowName()); |
||||
} |
||||
break; |
||||
case EQ_HISTORIC_SUBMIT_USER: |
||||
List<FlowTaskComment> comments = |
||||
flowTaskCommentService.getFlowTaskCommentList(execution.getProcessInstanceId()); |
||||
List<FlowTaskComment> resultComments = new LinkedList<>(); |
||||
for (FlowTaskComment c : comments) { |
||||
if (StrUtil.equals(c.getCreateLoginName(), assignedUser)) { |
||||
resultComments.add(c); |
||||
} |
||||
} |
||||
if (CollUtil.isNotEmpty(resultComments)) { |
||||
comment = resultComments.get(0); |
||||
} |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
UserTask userTask = (UserTask) execution.getCurrentFlowElement(); |
||||
if (comment != null) { |
||||
execution.setVariable("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true); |
||||
userTask.setSkipExpression("${1==1}"); |
||||
comment.setTaskId(userTask.getId()); |
||||
comment.setTaskKey(userTask.getId()); |
||||
comment.setTaskName(userTask.getName()); |
||||
comment.setProcessInstanceId(execution.getProcessInstanceId()); |
||||
comment.setExecutionId(execution.getId()); |
||||
comment.setApprovalType(FlowApprovalType.AGREE); |
||||
comment.setTaskComment(StrFormatter.format("自动跳过审批。审批人 [{}], 跳过原因 [{}]。", |
||||
userTask.getAssignee(), this.getMessageBySkipType(skipType))); |
||||
flowTaskCommentService.saveNew(comment); |
||||
} |
||||
return comment != null; |
||||
} |
||||
|
||||
private String getAssignedUser(DelegateExecution execution) { |
||||
UserTask userTask = (UserTask) execution.getCurrentFlowElement(); |
||||
String assignedUser = userTask.getAssignee(); |
||||
if (StrUtil.isNotBlank(assignedUser)) { |
||||
if (assignedUser.startsWith("${") && assignedUser.endsWith("}")) { |
||||
String variableName = assignedUser.substring(2, assignedUser.length() - 1); |
||||
assignedUser = flowApiService.getExecutionVariableStringWithSafe(execution.getId(), variableName); |
||||
} |
||||
} else { |
||||
FlowTaskExt flowTaskExt = flowTaskExtService |
||||
.getByProcessDefinitionIdAndTaskId(execution.getProcessDefinitionId(), userTask.getId()); |
||||
List<String> candidateUsernames; |
||||
if (StrUtil.isBlank(flowTaskExt.getCandidateUsernames())) { |
||||
candidateUsernames = Collections.emptyList(); |
||||
} else if (!StrUtil.equals(flowTaskExt.getCandidateUsernames(), "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { |
||||
candidateUsernames = StrUtil.split(flowTaskExt.getCandidateUsernames(), ","); |
||||
} else { |
||||
String value = flowApiService |
||||
.getExecutionVariableStringWithSafe(execution.getId(), FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); |
||||
candidateUsernames = value == null ? null : StrUtil.split(value, ","); |
||||
} |
||||
if (candidateUsernames != null && candidateUsernames.size() == 1) { |
||||
assignedUser = candidateUsernames.get(0); |
||||
} |
||||
} |
||||
return assignedUser; |
||||
} |
||||
|
||||
private String getMessageBySkipType(String skipType) { |
||||
switch (skipType) { |
||||
case EQ_PREV_SUBMIT_USER: |
||||
return "审批人与上一审批节点处理人相同"; |
||||
case EQ_START_USER: |
||||
return "审批人为发起人"; |
||||
case EQ_HISTORIC_SUBMIT_USER: |
||||
return "审批人审批过"; |
||||
default: |
||||
return ""; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,156 @@
@@ -0,0 +1,156 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.object.TokenData; |
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.constant.FlowApprovalType; |
||||
import apelet.common.flow.constant.FlowConstant; |
||||
import apelet.common.flow.model.FlowTaskComment; |
||||
import apelet.common.flow.model.FlowTaskExt; |
||||
import apelet.common.flow.service.FlowApiService; |
||||
import apelet.common.flow.service.FlowTaskCommentService; |
||||
import apelet.common.flow.service.FlowTaskExtService; |
||||
import cn.hutool.core.collection.CollUtil; |
||||
import cn.hutool.core.text.StrFormatter; |
||||
import cn.hutool.core.util.ObjectUtil; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.bpmn.model.ExtensionAttribute; |
||||
import org.flowable.bpmn.model.UserTask; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.task.api.Task; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
import java.util.*; |
||||
|
||||
/** |
||||
* 流程任务自动审批跳过的监听器。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class AutoSkipTaskListener implements TaskListener { |
||||
|
||||
private final transient FlowTaskCommentService flowTaskCommentService = |
||||
ApplicationContextHolder.getBean(FlowTaskCommentService.class); |
||||
private final transient FlowApiService flowApiService = |
||||
ApplicationContextHolder.getBean(FlowApiService.class); |
||||
private final transient FlowTaskExtService flowTaskExtService = |
||||
ApplicationContextHolder.getBean(FlowTaskExtService.class); |
||||
|
||||
/** |
||||
* 流程的发起者等于当前任务的Assignee。 |
||||
*/ |
||||
private static final String EQ_START_USER = "0"; |
||||
/** |
||||
* 上一步的提交者等于当前任务的Assignee。 |
||||
*/ |
||||
private static final String EQ_PREV_SUBMIT_USER = "1"; |
||||
/** |
||||
* 当前任务的Assignee之前提交过审核。 |
||||
*/ |
||||
private static final String EQ_HISTORIC_SUBMIT_USER = "2"; |
||||
|
||||
@Override |
||||
public void notify(DelegateTask t) { |
||||
UserTask userTask = flowApiService.getUserTask(t.getProcessDefinitionId(), t.getTaskDefinitionKey()); |
||||
List<ExtensionAttribute> attributes = userTask.getAttributes().get(FlowConstant.USER_TASK_AUTO_SKIP_KEY); |
||||
Set<String> skipTypes = new HashSet<>(StrUtil.split(attributes.get(0).getValue(), ",")); |
||||
String assignedUser = this.getAssignedUser(userTask, t.getProcessDefinitionId(), t.getExecutionId()); |
||||
if (StrUtil.isBlank(assignedUser)) { |
||||
return; |
||||
} |
||||
for (String skipType : skipTypes) { |
||||
if (this.verifyAndHandle(userTask, t, skipType, assignedUser)) { |
||||
return; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
private boolean verifyAndHandle(UserTask userTask, DelegateTask task, String skipType, String assignedUser) { |
||||
FlowTaskComment comment = null; |
||||
switch (skipType) { |
||||
case EQ_START_USER: |
||||
Object v = task.getVariable(FlowConstant.PROC_INSTANCE_START_USER_NAME_VAR); |
||||
if (ObjectUtil.equal(v, assignedUser)) { |
||||
comment = flowTaskCommentService.getFirstFlowTaskComment(task.getProcessInstanceId()); |
||||
} |
||||
break; |
||||
case EQ_PREV_SUBMIT_USER: |
||||
Object v2 = task.getVariable(FlowConstant.SUBMIT_USER_VAR); |
||||
if (ObjectUtil.equal(v2, assignedUser)) { |
||||
TokenData tokenData = TokenData.takeFromRequest(); |
||||
comment = new FlowTaskComment(); |
||||
comment.setCreateUserId(tokenData.getUserId()); |
||||
comment.setCreateLoginName(tokenData.getLoginName()); |
||||
comment.setCreateUsername(tokenData.getShowName()); |
||||
} |
||||
break; |
||||
case EQ_HISTORIC_SUBMIT_USER: |
||||
List<FlowTaskComment> comments = |
||||
flowTaskCommentService.getFlowTaskCommentList(task.getProcessInstanceId()); |
||||
List<FlowTaskComment> resultComments = new LinkedList<>(); |
||||
for (FlowTaskComment c : comments) { |
||||
if (StrUtil.equals(c.getCreateLoginName(), assignedUser)) { |
||||
resultComments.add(c); |
||||
} |
||||
} |
||||
if (CollUtil.isNotEmpty(resultComments)) { |
||||
comment = resultComments.get(0); |
||||
} |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
if (comment != null) { |
||||
Task t = flowApiService.getTaskById(task.getId()); |
||||
comment.fillWith(t); |
||||
comment.setApprovalType(FlowApprovalType.AGREE); |
||||
comment.setTaskComment(StrFormatter.format("自动跳过审批。审批人 [{}], 跳过原因 [{}]。", |
||||
userTask.getAssignee(), this.getMessageBySkipType(skipType))); |
||||
flowApiService.completeTask(t, comment, null, null); |
||||
} |
||||
return comment != null; |
||||
} |
||||
|
||||
private String getAssignedUser(UserTask userTask, String processDefinitionId, String executionId) { |
||||
String assignedUser = userTask.getAssignee(); |
||||
if (StrUtil.isNotBlank(assignedUser)) { |
||||
if (assignedUser.startsWith("${") && assignedUser.endsWith("}")) { |
||||
String variableName = assignedUser.substring(2, assignedUser.length() - 1); |
||||
assignedUser = flowApiService.getExecutionVariableStringWithSafe(executionId, variableName); |
||||
} |
||||
} else { |
||||
FlowTaskExt flowTaskExt = flowTaskExtService |
||||
.getByProcessDefinitionIdAndTaskId(processDefinitionId, userTask.getId()); |
||||
List<String> candidateUsernames; |
||||
if (StrUtil.isBlank(flowTaskExt.getCandidateUsernames())) { |
||||
candidateUsernames = Collections.emptyList(); |
||||
} else if (!StrUtil.equals(flowTaskExt.getCandidateUsernames(), "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { |
||||
candidateUsernames = StrUtil.split(flowTaskExt.getCandidateUsernames(), ","); |
||||
} else { |
||||
String value = flowApiService |
||||
.getExecutionVariableStringWithSafe(executionId, FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); |
||||
candidateUsernames = value == null ? null : StrUtil.split(value, ","); |
||||
} |
||||
if (candidateUsernames != null && candidateUsernames.size() == 1) { |
||||
assignedUser = candidateUsernames.get(0); |
||||
} |
||||
} |
||||
return assignedUser; |
||||
} |
||||
|
||||
private String getMessageBySkipType(String skipType) { |
||||
switch (skipType) { |
||||
case EQ_PREV_SUBMIT_USER: |
||||
return "审批人与上一审批节点处理人相同"; |
||||
case EQ_START_USER: |
||||
return "审批人为发起人"; |
||||
case EQ_HISTORIC_SUBMIT_USER: |
||||
return "审批人审批过"; |
||||
default: |
||||
return ""; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.flow.constant.FlowConstant; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 当用户任务的候选组为本部门领导岗位时,该监听器会在任务创建时,获取当前流程实例发起人的部门领导。 |
||||
* 并将其指派为当前任务的候选组。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class DeptPostLeaderListener implements TaskListener { |
||||
|
||||
@Override |
||||
public void notify(DelegateTask delegateTask) { |
||||
Map<String, Object> variables = delegateTask.getVariables(); |
||||
if (variables.get(FlowConstant.GROUP_TYPE_DEPT_POST_LEADER_VAR) == null) { |
||||
delegateTask.setAssignee(variables.get(FlowConstant.PROC_INSTANCE_START_USER_NAME_VAR).toString()); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.constant.FlowApprovalType; |
||||
import apelet.common.flow.exception.FlowEmptyUserException; |
||||
import apelet.common.flow.model.FlowTaskComment; |
||||
import apelet.common.flow.model.FlowTaskExt; |
||||
import apelet.common.flow.object.FlowUserTaskExtData; |
||||
import apelet.common.flow.service.FlowApiService; |
||||
import apelet.common.flow.service.FlowTaskExtService; |
||||
import apelet.common.flow.vo.FlowUserInfoVo; |
||||
import cn.hutool.core.collection.CollUtil; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import com.alibaba.fastjson.JSON; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.task.api.Task; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 空审批人处理监听器。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class FlowEmptyUserHandleListener implements TaskListener { |
||||
|
||||
private final transient FlowTaskExtService flowTaskExtService = |
||||
ApplicationContextHolder.getBean(FlowTaskExtService.class); |
||||
private final transient FlowApiService flowApiService = |
||||
ApplicationContextHolder.getBean(FlowApiService.class); |
||||
|
||||
@Override |
||||
public void notify(DelegateTask t) { |
||||
FlowTaskExt flowTaskExt = flowTaskExtService.getByProcessDefinitionIdAndTaskId( |
||||
t.getProcessDefinitionId(), t.getTaskDefinitionKey()); |
||||
Task task = flowApiService.getTaskById(t.getId()); |
||||
List<FlowUserInfoVo> userInfoVoList = |
||||
flowTaskExtService.getCandidateUserInfoList(t.getProcessInstanceId(), flowTaskExt, task, |
||||
flowApiService.isMultiInstanceTask(t.getProcessDefinitionId(), t.getTaskDefinitionKey()), false); |
||||
if (CollUtil.isNotEmpty(userInfoVoList)) { |
||||
return; |
||||
} |
||||
FlowUserTaskExtData taskExtData = |
||||
JSON.parseObject(flowTaskExt.getExtraDataJson(), FlowUserTaskExtData.class); |
||||
if (StrUtil.isBlank(taskExtData.getEmptyUserHandleWay())) { |
||||
return; |
||||
} |
||||
switch (taskExtData.getEmptyUserHandleWay()) { |
||||
case FlowUserTaskExtData.EMPTY_USER_TO_ASSIGNEE: |
||||
t.setAssignee(taskExtData.getEmptyUserToAssignee()); |
||||
break; |
||||
case FlowUserTaskExtData.EMPTY_USER_AUTO_REJECT: |
||||
case FlowUserTaskExtData.EMPTY_USER_AUTO_COMPLETE: |
||||
FlowTaskComment comment = new FlowTaskComment(); |
||||
comment.fillWith(task); |
||||
if (taskExtData.getEmptyUserHandleWay().equals(FlowUserTaskExtData.EMPTY_USER_AUTO_REJECT)) { |
||||
comment.setApprovalType(FlowApprovalType.EMPTY_USER_AUTO_REJECT); |
||||
comment.setTaskComment("空审批人自动回退审批。"); |
||||
throw new FlowEmptyUserException(JSON.toJSONString(comment)); |
||||
} else { |
||||
comment.setApprovalType(FlowApprovalType.EMPTY_USER_AUTO_COMPLETE); |
||||
comment.setTaskComment("空审批人自动跳过审批。"); |
||||
flowApiService.completeTask(task, comment, null, null); |
||||
} |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.object.GlobalThreadLocal; |
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.constant.FlowTaskStatus; |
||||
import apelet.common.flow.model.FlowWorkOrder; |
||||
import apelet.common.flow.service.FlowTaskTimeoutJobService; |
||||
import apelet.common.flow.service.FlowWorkOrderService; |
||||
import apelet.common.flow.util.FlowCustomExtFactory; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.DelegateExecution; |
||||
import org.flowable.engine.delegate.ExecutionListener; |
||||
|
||||
/** |
||||
* 流程实例监听器,在流程实例结束的时候,需要完成一些自定义的业务行为。如: |
||||
* 1. 更新流程工单表的审批状态字段。 |
||||
* 2. 业务数据同步。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class FlowFinishedListener implements ExecutionListener { |
||||
|
||||
private final transient FlowWorkOrderService flowWorkOrderService = |
||||
ApplicationContextHolder.getBean(FlowWorkOrderService.class); |
||||
private final transient FlowCustomExtFactory flowCustomExtFactory = |
||||
ApplicationContextHolder.getBean(FlowCustomExtFactory.class); |
||||
private final transient FlowTaskTimeoutJobService flowTaskTimeoutJobService = |
||||
ApplicationContextHolder.getBean(FlowTaskTimeoutJobService.class); |
||||
|
||||
@Override |
||||
public void notify(DelegateExecution execution) { |
||||
if (!StrUtil.equals("end", execution.getEventName())) { |
||||
return; |
||||
} |
||||
boolean enabled = GlobalThreadLocal.setDataFilter(false); |
||||
try { |
||||
String processInstanceId = execution.getProcessInstanceId(); |
||||
FlowWorkOrder workOrder = flowWorkOrderService.getFlowWorkOrderByProcessInstanceId(processInstanceId); |
||||
if (workOrder == null) { |
||||
return; |
||||
} |
||||
int flowStatus = FlowTaskStatus.FINISHED; |
||||
if (workOrder.getFlowStatus().equals(FlowTaskStatus.CANCELLED) |
||||
|| workOrder.getFlowStatus().equals(FlowTaskStatus.STOPPED)) { |
||||
flowStatus = workOrder.getFlowStatus(); |
||||
} |
||||
workOrder.setFlowStatus(flowStatus); |
||||
// 更新流程工单中的流程状态。
|
||||
flowWorkOrderService.updateFlowStatusByProcessInstanceId(processInstanceId, flowStatus); |
||||
if (workOrder.getOnlineTableId() != null) { |
||||
// 处理在线表单工作流的自定义状态更新。
|
||||
flowCustomExtFactory.getOnlineBusinessDataExtHelper().updateFlowStatus(workOrder); |
||||
} else { |
||||
// 处理路由表单工作里的自定义状态更新。
|
||||
flowCustomExtFactory.getBusinessDataExtHelper().updateFlowStatus(workOrder); |
||||
} |
||||
if (flowStatus == FlowTaskStatus.FINISHED) { |
||||
// 在线表单不支持该功能,仅限于路由表单工作流可用。
|
||||
// 可以自行实现审批完成后,将审批中已经通过的数据,同步到业务发布表。
|
||||
flowCustomExtFactory.getBusinessDataExtHelper().triggerSync(workOrder); |
||||
} |
||||
flowTaskTimeoutJobService.deleteByProcessInstanceId(execution.getProcessInstanceId()); |
||||
} finally { |
||||
GlobalThreadLocal.setDataFilter(enabled); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.constant.FlowConstant; |
||||
import apelet.common.flow.model.FlowTaskExt; |
||||
import apelet.common.flow.object.FlowUserTaskExtData; |
||||
import apelet.common.flow.service.FlowApiService; |
||||
import apelet.common.flow.service.FlowTaskExtService; |
||||
import apelet.common.flow.util.BaseFlowNotifyExtHelper; |
||||
import apelet.common.flow.util.FlowCustomExtFactory; |
||||
import apelet.common.flow.vo.FlowTaskVo; |
||||
import apelet.common.flow.vo.FlowUserInfoVo; |
||||
import cn.hutool.core.collection.CollUtil; |
||||
import cn.hutool.core.lang.Assert; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import com.alibaba.fastjson.JSON; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.engine.runtime.ProcessInstance; |
||||
import org.flowable.task.api.Task; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 任务进入待办状态时的通知监听器。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class FlowTaskNotifyListener implements TaskListener { |
||||
|
||||
private final transient FlowTaskExtService flowTaskExtService = |
||||
ApplicationContextHolder.getBean(FlowTaskExtService.class); |
||||
private final transient FlowApiService flowApiService = |
||||
ApplicationContextHolder.getBean(FlowApiService.class); |
||||
private final transient FlowCustomExtFactory flowCustomExtFactory = |
||||
ApplicationContextHolder.getBean(FlowCustomExtFactory.class); |
||||
|
||||
@Override |
||||
public void notify(DelegateTask delegateTask) { |
||||
String definitionId = delegateTask.getProcessDefinitionId(); |
||||
String instanceId = delegateTask.getProcessInstanceId(); |
||||
String taskId = delegateTask.getId(); |
||||
String taskKey = delegateTask.getTaskDefinitionKey(); |
||||
FlowTaskExt taskExt = flowTaskExtService.getByProcessDefinitionIdAndTaskId(definitionId, taskKey); |
||||
if (StrUtil.isBlank(taskExt.getExtraDataJson())) { |
||||
return; |
||||
} |
||||
FlowUserTaskExtData extData = JSON.parseObject(taskExt.getExtraDataJson(), FlowUserTaskExtData.class); |
||||
if (CollUtil.isEmpty(extData.getFlowNotifyTypeList())) { |
||||
return; |
||||
} |
||||
ProcessInstance instance = flowApiService.getProcessInstance(instanceId); |
||||
Object initiator = flowApiService.getProcessInstanceVariable(instanceId, FlowConstant.PROC_INSTANCE_INITIATOR_VAR); |
||||
boolean isMultiInstanceTask = flowApiService.isMultiInstanceTask(definitionId, taskKey); |
||||
Task task = flowApiService.getProcessInstanceActiveTask(instanceId, taskId); |
||||
List<FlowUserInfoVo> userInfoList = |
||||
flowTaskExtService.getCandidateUserInfoList(instanceId, taskExt, task, isMultiInstanceTask, false); |
||||
if (CollUtil.isEmpty(userInfoList)) { |
||||
log.warn("ProcessDefinition [{}] Task [{}] don't find the candidate users for notification.", |
||||
instance.getProcessDefinitionName(), task.getName()); |
||||
return; |
||||
} |
||||
BaseFlowNotifyExtHelper helper = flowCustomExtFactory.getFlowNotifyExtHelper(); |
||||
Assert.notNull(helper); |
||||
for (String notifyType : extData.getFlowNotifyTypeList()) { |
||||
FlowTaskVo flowTaskVo = new FlowTaskVo(); |
||||
flowTaskVo.setProcessDefinitionId(definitionId); |
||||
flowTaskVo.setProcessInstanceId(instanceId); |
||||
flowTaskVo.setTaskKey(taskKey); |
||||
flowTaskVo.setTaskName(delegateTask.getName()); |
||||
flowTaskVo.setTaskId(delegateTask.getId()); |
||||
flowTaskVo.setBusinessKey(instance.getBusinessKey()); |
||||
flowTaskVo.setProcessInstanceInitiator(initiator.toString()); |
||||
helper.doNotify(notifyType, userInfoList, flowTaskVo); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.flow.constant.FlowConstant; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 任务驳回后重新提交到该任务的通知监听器。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class FlowTaskRejectBackListener implements TaskListener { |
||||
|
||||
@Override |
||||
public void notify(DelegateTask delegateTask) { |
||||
Map<String, Object> variables = delegateTask.getVariables(); |
||||
if (variables.get(FlowConstant.REJECT_BACK_TO_SOURCE_DATA_VAR) != null) { |
||||
delegateTask.setAssignee(variables.get(FlowConstant.REJECT_BACK_TO_SOURCE_DATA_VAR).toString()); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.model.FlowEntryPublish; |
||||
import apelet.common.flow.model.FlowVariableLog; |
||||
import apelet.common.flow.object.FlowEntryExtensionData; |
||||
import apelet.common.flow.service.FlowEntryService; |
||||
import apelet.common.flow.service.FlowVariableLogService; |
||||
import cn.hutool.core.collection.CollUtil; |
||||
import cn.hutool.core.date.DateField; |
||||
import cn.hutool.core.date.DateUtil; |
||||
import cn.hutool.core.map.MapUtil; |
||||
import com.alibaba.fastjson.JSON; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 支持流程复活的任务监听器。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class FlowTaskReviveListener implements TaskListener { |
||||
|
||||
private final transient FlowVariableLogService flowVariableLogService = |
||||
ApplicationContextHolder.getBean(FlowVariableLogService.class); |
||||
private final transient FlowEntryService flowEntryService = |
||||
ApplicationContextHolder.getBean(FlowEntryService.class); |
||||
|
||||
@Override |
||||
public void notify(DelegateTask delegateTask) { |
||||
Map<String, Object> variables = delegateTask.getVariables(); |
||||
if (MapUtil.isNotEmpty(variables)) { |
||||
List<FlowEntryPublish> flowEntryPublishList = |
||||
flowEntryService.getFlowEntryPublishList(CollUtil.newHashSet(delegateTask.getProcessDefinitionId())); |
||||
FlowEntryExtensionData flowEntryExtensionData = |
||||
JSON.parseObject(flowEntryPublishList.get(0).getExtensionData(), FlowEntryExtensionData.class); |
||||
FlowVariableLog o = new FlowVariableLog(); |
||||
if (flowEntryExtensionData.getKeptReviveDays() > 0) { |
||||
o.setExpiredTime(DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, flowEntryExtensionData.getKeptReviveDays())); |
||||
} |
||||
o.setProcessDefinitionKey(delegateTask.getProcessDefinitionId()); |
||||
o.setProcessInstanceId(delegateTask.getProcessInstanceId()); |
||||
o.setTaskKey(delegateTask.getTaskDefinitionKey()); |
||||
o.setVariableData(JSON.toJSONString(variables)); |
||||
flowVariableLogService.saveNew(o); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.model.FlowTaskExt; |
||||
import apelet.common.flow.model.FlowTaskTimeoutJob; |
||||
import apelet.common.flow.object.FlowUserTaskExtData; |
||||
import apelet.common.flow.service.FlowTaskExtService; |
||||
import apelet.common.flow.service.FlowTaskTimeoutJobService; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import com.alibaba.fastjson.JSON; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
/** |
||||
* 流程任务超时监听器。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class FlowTaskTimeoutListener implements TaskListener { |
||||
|
||||
private final transient FlowTaskExtService flowTaskExtService = |
||||
ApplicationContextHolder.getBean(FlowTaskExtService.class); |
||||
private final transient FlowTaskTimeoutJobService flowTaskTimeoutJobService = |
||||
ApplicationContextHolder.getBean(FlowTaskTimeoutJobService.class); |
||||
|
||||
@Override |
||||
public void notify(DelegateTask delegateTask) { |
||||
FlowTaskExt taskExt = flowTaskExtService.getByProcessDefinitionIdAndTaskId( |
||||
delegateTask.getProcessDefinitionId(), delegateTask.getTaskDefinitionKey()); |
||||
if (StrUtil.isNotBlank(taskExt.getExtraDataJson())) { |
||||
FlowUserTaskExtData taskExtData = JSON.parseObject(taskExt.getExtraDataJson(), FlowUserTaskExtData.class); |
||||
if (StrUtil.isNotBlank(taskExtData.getTimeoutHandleWay())) { |
||||
FlowTaskTimeoutJob job = new FlowTaskTimeoutJob(); |
||||
job.setProcessDefinitionId(delegateTask.getProcessDefinitionId()); |
||||
job.setProcessInstanceId(delegateTask.getProcessInstanceId()); |
||||
job.setTaskKey(delegateTask.getTaskDefinitionKey()); |
||||
job.setTaskId(delegateTask.getId()); |
||||
job.setTimeoutHours(taskExtData.getTimeoutHours()); |
||||
job.setHandleWay(taskExtData.getTimeoutHandleWay()); |
||||
job.setDefaultAssignee(taskExtData.getDefaultAssignee()); |
||||
flowTaskTimeoutJobService.saveNew(job); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.constant.FlowConstant; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.RuntimeService; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 流程任务通用监听器。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class FlowUserTaskListener implements TaskListener { |
||||
|
||||
private final transient RuntimeService runtimeService = |
||||
ApplicationContextHolder.getBean(RuntimeService.class); |
||||
|
||||
@Override |
||||
public void notify(DelegateTask delegateTask) { |
||||
Map<String, Object> variables = delegateTask.getVariables(); |
||||
if (variables.get(FlowConstant.DELEGATE_ASSIGNEE_VAR) != null) { |
||||
delegateTask.setAssignee(variables.get(FlowConstant.DELEGATE_ASSIGNEE_VAR).toString()); |
||||
runtimeService.removeVariableLocal(delegateTask.getExecutionId(), FlowConstant.DELEGATE_ASSIGNEE_VAR); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.flow.constant.FlowConstant; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.TaskListener; |
||||
import org.flowable.task.service.delegate.DelegateTask; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 当用户任务的候选组为上级部门领导岗位时,该监听器会在任务创建时,获取当前流程实例发起人的部门领导。 |
||||
* 并将其指派为当前任务的候选组。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class UpDeptPostLeaderListener implements TaskListener { |
||||
|
||||
@Override |
||||
public void notify(DelegateTask delegateTask) { |
||||
Map<String, Object> variables = delegateTask.getVariables(); |
||||
if (variables.get(FlowConstant.GROUP_TYPE_UP_DEPT_POST_LEADER_VAR) == null) { |
||||
delegateTask.setAssignee(variables.get(FlowConstant.PROC_INSTANCE_START_USER_NAME_VAR).toString()); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
package apelet.common.flow.listener; |
||||
|
||||
import apelet.common.core.util.ApplicationContextHolder; |
||||
import apelet.common.flow.model.FlowWorkOrder; |
||||
import apelet.common.flow.service.FlowWorkOrderService; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.flowable.engine.delegate.DelegateExecution; |
||||
import org.flowable.engine.delegate.ExecutionListener; |
||||
import org.flowable.engine.impl.el.FixedValue; |
||||
|
||||
/** |
||||
* 更新流程的最后审批状态的监听器,目前用于排他网关到任务结束节点的连线上, |
||||
* 以便于准确的判断流程实例的最后审批状态。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Slf4j |
||||
public class UpdateLatestApprovalStatusListener implements ExecutionListener { |
||||
|
||||
private FixedValue latestApprovalStatus; |
||||
|
||||
private final transient FlowWorkOrderService flowWorkOrderService = |
||||
ApplicationContextHolder.getBean(FlowWorkOrderService.class); |
||||
|
||||
public void setAutoStoreVariablesExp(FixedValue approvalStatus) { |
||||
this.latestApprovalStatus = approvalStatus; |
||||
} |
||||
|
||||
@Override |
||||
public void notify(DelegateExecution execution) { |
||||
if (StrUtil.isNotBlank(latestApprovalStatus.getExpressionText())) { |
||||
FlowWorkOrder workOrder = |
||||
flowWorkOrderService.getFlowWorkOrderByProcessInstanceId(execution.getProcessInstanceId()); |
||||
if (workOrder == null) { |
||||
return; |
||||
} |
||||
Integer approvalStatus = Integer.valueOf(latestApprovalStatus.getExpressionText()); |
||||
String processInstanceId = execution.getProcessInstanceId(); |
||||
flowWorkOrderService.updateLatestApprovalStatusByProcessInstanceId(processInstanceId, approvalStatus); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import apelet.common.core.base.mapper.BaseModelMapper; |
||||
import apelet.common.flow.vo.FlowCategoryVo; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
import org.mapstruct.Mapper; |
||||
import org.mapstruct.factory.Mappers; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程分类的实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_category") |
||||
public class FlowCategory { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "category_id") |
||||
private Long categoryId; |
||||
|
||||
/** |
||||
* 租户Id。 |
||||
*/ |
||||
@TableField(value = "tenant_id") |
||||
private Long tenantId; |
||||
|
||||
/** |
||||
* 应用编码。为空时,表示非第三方应用接入。 |
||||
*/ |
||||
@TableField(value = "app_code") |
||||
private String appCode; |
||||
|
||||
/** |
||||
* 显示名称。 |
||||
*/ |
||||
@TableField(value = "name") |
||||
private String name; |
||||
|
||||
/** |
||||
* 分类编码。 |
||||
*/ |
||||
@TableField(value = "code") |
||||
private String code; |
||||
|
||||
/** |
||||
* 实现顺序。 |
||||
*/ |
||||
@TableField(value = "show_order") |
||||
private Integer showOrder; |
||||
|
||||
/** |
||||
* 更新时间。 |
||||
*/ |
||||
@TableField(value = "update_time") |
||||
private Date updateTime; |
||||
|
||||
/** |
||||
* 更新者Id。 |
||||
*/ |
||||
@TableField(value = "update_user_id") |
||||
private Long updateUserId; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
/** |
||||
* 创建者Id。 |
||||
*/ |
||||
@TableField(value = "create_user_id") |
||||
private Long createUserId; |
||||
|
||||
@Mapper |
||||
public interface FlowCategoryModelMapper extends BaseModelMapper<FlowCategoryVo, FlowCategory> { |
||||
} |
||||
public static final FlowCategoryModelMapper INSTANCE = Mappers.getMapper(FlowCategoryModelMapper.class); |
||||
} |
||||
@ -0,0 +1,192 @@
@@ -0,0 +1,192 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import apelet.common.core.annotation.RelationOneToOne; |
||||
import apelet.common.core.base.mapper.BaseModelMapper; |
||||
import apelet.common.flow.vo.FlowEntryVo; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
import org.mapstruct.Mapper; |
||||
import org.mapstruct.Mapping; |
||||
import org.mapstruct.factory.Mappers; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程的实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_entry") |
||||
public class FlowEntry { |
||||
|
||||
/** |
||||
* 主键。 |
||||
*/ |
||||
@TableId(value = "entry_id") |
||||
private Long entryId; |
||||
|
||||
/** |
||||
* 租户Id。 |
||||
*/ |
||||
@TableField(value = "tenant_id") |
||||
private Long tenantId; |
||||
|
||||
/** |
||||
* 应用编码。为空时,表示非第三方应用接入。 |
||||
*/ |
||||
@TableField(value = "app_code") |
||||
private String appCode; |
||||
|
||||
/** |
||||
* 流程名称。 |
||||
*/ |
||||
@TableField(value = "process_definition_name") |
||||
private String processDefinitionName; |
||||
|
||||
/** |
||||
* 流程标识Key。 |
||||
*/ |
||||
@TableField(value = "process_definition_key") |
||||
private String processDefinitionKey; |
||||
|
||||
/** |
||||
* 流程分类。 |
||||
*/ |
||||
@TableField(value = "category_id") |
||||
private Long categoryId; |
||||
|
||||
/** |
||||
* 工作流部署的发布主版本Id。 |
||||
*/ |
||||
@TableField(value = "main_entry_publish_id") |
||||
private Long mainEntryPublishId; |
||||
|
||||
/** |
||||
* 最新发布时间。 |
||||
*/ |
||||
@TableField(value = "latest_publish_time") |
||||
private Date latestPublishTime; |
||||
|
||||
/** |
||||
* 流程状态。 |
||||
*/ |
||||
@TableField(value = "status") |
||||
private Integer status; |
||||
|
||||
/** |
||||
* 流程定义的xml。 |
||||
*/ |
||||
@TableField(value = "bpmn_xml") |
||||
private String bpmnXml; |
||||
|
||||
/** |
||||
* 流程图类型。0: 普通流程图,1: 钉钉风格的流程图。 |
||||
*/ |
||||
@TableField(value = "diagram_type") |
||||
private Integer diagramType; |
||||
|
||||
/** |
||||
* 绑定表单类型。 |
||||
*/ |
||||
@TableField(value = "bind_form_type") |
||||
private Integer bindFormType; |
||||
|
||||
/** |
||||
* 在线表单的页面Id。 |
||||
*/ |
||||
@TableField(value = "page_id") |
||||
private Long pageId; |
||||
|
||||
/** |
||||
* 在线表单Id。 |
||||
*/ |
||||
@TableField(value = "default_form_id") |
||||
private Long defaultFormId; |
||||
|
||||
/** |
||||
* 静态表单的缺省路由名称。 |
||||
*/ |
||||
@TableField(value = "default_router_name") |
||||
private String defaultRouterName; |
||||
|
||||
/** |
||||
* 工单表编码字段的编码规则,如果为空则不计算工单编码。 |
||||
*/ |
||||
@TableField(value = "encoded_rule") |
||||
private String encodedRule; |
||||
|
||||
/** |
||||
* 流程的自定义扩展数据(JSON格式)。 |
||||
*/ |
||||
@TableField(value = "extension_data") |
||||
private String extensionData; |
||||
|
||||
/** |
||||
* 更新时间。 |
||||
*/ |
||||
@TableField(value = "update_time") |
||||
private Date updateTime; |
||||
|
||||
/** |
||||
* 更新者Id。 |
||||
*/ |
||||
@TableField(value = "update_user_id") |
||||
private Long updateUserId; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
/** |
||||
* 创建者Id。 |
||||
*/ |
||||
@TableField(value = "create_user_id") |
||||
private Long createUserId; |
||||
|
||||
/** |
||||
* 流程启动条件 |
||||
*/ |
||||
@TableField(value = "start_conditions") |
||||
private String startConditions; |
||||
|
||||
@TableField(exist = false) |
||||
private FlowEntryPublish mainFlowEntryPublish; |
||||
|
||||
@RelationOneToOne( |
||||
masterIdField = "categoryId", |
||||
slaveModelClass = FlowCategory.class, |
||||
slaveIdField = "categoryId") |
||||
@TableField(exist = false) |
||||
private FlowCategory flowCategory; |
||||
|
||||
@Mapper |
||||
public interface FlowEntryModelMapper extends BaseModelMapper<FlowEntryVo, FlowEntry> { |
||||
/** |
||||
* 转换Vo对象到实体对象。 |
||||
* |
||||
* @param flowEntryVo 域对象。 |
||||
* @return 实体对象。 |
||||
*/ |
||||
@Mapping(target = "mainFlowEntryPublish", expression = "java(mapToBean(flowEntryVo.getMainFlowEntryPublish(), apelet.common.flow.model.FlowEntryPublish.class))") |
||||
@Mapping(target = "flowCategory", expression = "java(mapToBean(flowEntryVo.getFlowCategory(), apelet.common.flow.model.FlowCategory.class))") |
||||
@Override |
||||
FlowEntry toModel(FlowEntryVo flowEntryVo); |
||||
/** |
||||
* 转换实体对象到VO对象。 |
||||
* |
||||
* @param flowEntry 实体对象。 |
||||
* @return 域对象。 |
||||
*/ |
||||
@Mapping(target = "mainFlowEntryPublish", expression = "java(beanToMap(flowEntry.getMainFlowEntryPublish(), false))") |
||||
@Mapping(target = "flowCategory", expression = "java(beanToMap(flowEntry.getFlowCategory(), false))") |
||||
@Override |
||||
FlowEntryVo fromModel(FlowEntry flowEntry); |
||||
} |
||||
public static final FlowEntryModelMapper INSTANCE = Mappers.getMapper(FlowEntryModelMapper.class); |
||||
} |
||||
@ -0,0 +1,98 @@
@@ -0,0 +1,98 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程发布数据的实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_entry_publish") |
||||
public class FlowEntryPublish { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "entry_publish_id") |
||||
private Long entryPublishId; |
||||
|
||||
/** |
||||
* 流程Id。 |
||||
*/ |
||||
@TableField(value = "entry_id") |
||||
private Long entryId; |
||||
|
||||
/** |
||||
* 流程引擎的部署Id。 |
||||
*/ |
||||
@TableField(value = "deploy_id") |
||||
private String deployId; |
||||
|
||||
/** |
||||
* 流程引擎中的流程定义Id。 |
||||
*/ |
||||
@TableField(value = "process_definition_id") |
||||
private String processDefinitionId; |
||||
|
||||
/** |
||||
* 发布版本。 |
||||
*/ |
||||
@TableField(value = "publish_version") |
||||
private Integer publishVersion; |
||||
|
||||
/** |
||||
* 激活状态。 |
||||
*/ |
||||
@TableField(value = "active_status") |
||||
private Boolean activeStatus; |
||||
|
||||
/** |
||||
* 是否为主版本。 |
||||
*/ |
||||
@TableField(value = "main_version") |
||||
private Boolean mainVersion; |
||||
|
||||
/** |
||||
* 创建者Id。 |
||||
*/ |
||||
@TableField(value = "create_user_id") |
||||
private Long createUserId; |
||||
|
||||
/** |
||||
* 发布时间。 |
||||
*/ |
||||
@TableField(value = "publish_time") |
||||
private Date publishTime; |
||||
|
||||
/** |
||||
* 第一个非开始节点任务的附加信息。 |
||||
*/ |
||||
@TableField(value = "init_task_info") |
||||
private String initTaskInfo; |
||||
|
||||
/** |
||||
* 分析后的节点JSON信息。 |
||||
*/ |
||||
@TableField(value = "analyzed_node_json") |
||||
private String analyzedNodeJson; |
||||
|
||||
/** |
||||
* 流程的自定义扩展数据(JSON格式)。 |
||||
*/ |
||||
@TableField(value = "extension_data") |
||||
private String extensionData; |
||||
|
||||
|
||||
/** |
||||
* 流程启动条件 |
||||
*/ |
||||
@TableField(value = "start_conditions") |
||||
private String startConditions; |
||||
} |
||||
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* FlowEntryPublishVariable实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_entry_publish_variable") |
||||
public class FlowEntryPublishVariable { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "variable_id") |
||||
private Long variableId; |
||||
|
||||
/** |
||||
* 流程Id。 |
||||
*/ |
||||
@TableField(value = "entry_publish_id") |
||||
private Long entryPublishId; |
||||
|
||||
/** |
||||
* 变量名。 |
||||
*/ |
||||
@TableField(value = "variable_name") |
||||
private String variableName; |
||||
|
||||
/** |
||||
* 显示名。 |
||||
*/ |
||||
@TableField(value = "show_name") |
||||
private String showName; |
||||
|
||||
/** |
||||
* 变量类型。 |
||||
*/ |
||||
@TableField(value = "variable_type") |
||||
private Integer variableType; |
||||
|
||||
/** |
||||
* 是否内置。 |
||||
*/ |
||||
@TableField(value = "builtin") |
||||
private Boolean builtin; |
||||
|
||||
/** |
||||
* 绑定数据源Id。 |
||||
*/ |
||||
@TableField(value = "bind_datasource_id") |
||||
private Long bindDatasourceId; |
||||
|
||||
/** |
||||
* 绑定数据源关联Id。 |
||||
*/ |
||||
@TableField(value = "bind_relation_id") |
||||
private Long bindRelationId; |
||||
|
||||
/** |
||||
* 绑定字段Id。 |
||||
*/ |
||||
@TableField(value = "bind_column_id") |
||||
private Long bindColumnId; |
||||
} |
||||
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import apelet.common.core.base.mapper.BaseModelMapper; |
||||
import apelet.common.flow.vo.FlowEntryVariableVo; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
import org.mapstruct.Mapper; |
||||
import org.mapstruct.factory.Mappers; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程变量实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_entry_variable") |
||||
public class FlowEntryVariable { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "variable_id") |
||||
private Long variableId; |
||||
|
||||
/** |
||||
* 流程Id。 |
||||
*/ |
||||
@TableField(value = "entry_id") |
||||
private Long entryId; |
||||
|
||||
/** |
||||
* 变量名。 |
||||
*/ |
||||
@TableField(value = "variable_name") |
||||
private String variableName; |
||||
|
||||
/** |
||||
* 显示名。 |
||||
*/ |
||||
@TableField(value = "show_name") |
||||
private String showName; |
||||
|
||||
/** |
||||
* 流程变量类型。 |
||||
*/ |
||||
@TableField(value = "variable_type") |
||||
private Integer variableType; |
||||
|
||||
/** |
||||
* 绑定数据源Id。 |
||||
*/ |
||||
@TableField(value = "bind_datasource_id") |
||||
private Long bindDatasourceId; |
||||
|
||||
/** |
||||
* 绑定数据源关联Id。 |
||||
*/ |
||||
@TableField(value = "bind_relation_id") |
||||
private Long bindRelationId; |
||||
|
||||
/** |
||||
* 绑定字段Id。 |
||||
*/ |
||||
@TableField(value = "bind_column_id") |
||||
private Long bindColumnId; |
||||
|
||||
/** |
||||
* 是否内置。 |
||||
*/ |
||||
@TableField(value = "builtin") |
||||
private Boolean builtin; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
@Mapper |
||||
public interface FlowEntryVariableModelMapper extends BaseModelMapper<FlowEntryVariableVo, FlowEntryVariable> { |
||||
} |
||||
public static final FlowEntryVariableModelMapper INSTANCE = Mappers.getMapper(FlowEntryVariableModelMapper.class); |
||||
} |
||||
@ -0,0 +1,178 @@
@@ -0,0 +1,178 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import apelet.common.core.base.mapper.BaseModelMapper; |
||||
import apelet.common.flow.vo.FlowMessageVo; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
import org.mapstruct.Mapper; |
||||
import org.mapstruct.factory.Mappers; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 工作流通知消息实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_message") |
||||
public class FlowMessage { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "message_id") |
||||
private Long messageId; |
||||
|
||||
/** |
||||
* 租户Id。 |
||||
*/ |
||||
@TableField(value = "tenant_id") |
||||
private Long tenantId; |
||||
|
||||
/** |
||||
* 应用编码。为空时,表示非第三方应用接入。 |
||||
*/ |
||||
@TableField(value = "app_code") |
||||
private String appCode; |
||||
|
||||
/** |
||||
* 消息类型。 |
||||
*/ |
||||
@TableField(value = "message_type") |
||||
private Integer messageType; |
||||
|
||||
/** |
||||
* 消息内容。 |
||||
*/ |
||||
@TableField(value = "message_content") |
||||
private String messageContent; |
||||
|
||||
/** |
||||
* 催办次数。 |
||||
*/ |
||||
@TableField(value = "remind_count") |
||||
private Integer remindCount; |
||||
|
||||
/** |
||||
* 工单Id。 |
||||
*/ |
||||
@TableField(value = "work_order_id") |
||||
private Long workOrderId; |
||||
|
||||
/** |
||||
* 流程定义Id。 |
||||
*/ |
||||
@TableField(value = "process_definition_id") |
||||
private String processDefinitionId; |
||||
|
||||
/** |
||||
* 流程定义标识。 |
||||
*/ |
||||
@TableField(value = "process_definition_key") |
||||
private String processDefinitionKey; |
||||
|
||||
/** |
||||
* 流程名称。 |
||||
*/ |
||||
@TableField(value = "process_definition_name") |
||||
private String processDefinitionName; |
||||
|
||||
/** |
||||
* 流程实例Id。 |
||||
*/ |
||||
@TableField(value = "process_instance_id") |
||||
private String processInstanceId; |
||||
|
||||
/** |
||||
* 流程实例发起者。 |
||||
*/ |
||||
@TableField(value = "process_instance_initiator") |
||||
private String processInstanceInitiator; |
||||
|
||||
/** |
||||
* 流程任务Id。 |
||||
*/ |
||||
@TableField(value = "task_id") |
||||
private String taskId; |
||||
|
||||
/** |
||||
* 流程任务定义标识。 |
||||
*/ |
||||
@TableField(value = "task_definition_key") |
||||
private String taskDefinitionKey; |
||||
|
||||
/** |
||||
* 流程任务名称。 |
||||
*/ |
||||
@TableField(value = "task_name") |
||||
private String taskName; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "task_start_time") |
||||
private Date taskStartTime; |
||||
|
||||
/** |
||||
* 任务指派人登录名。 |
||||
*/ |
||||
@TableField(value = "task_assignee") |
||||
private String taskAssignee; |
||||
|
||||
/** |
||||
* 任务是否已完成。 |
||||
*/ |
||||
@TableField(value = "task_finished") |
||||
private Boolean taskFinished; |
||||
|
||||
/** |
||||
* 业务数据快照。 |
||||
*/ |
||||
@TableField(value = "business_data_shot") |
||||
private String businessDataShot; |
||||
|
||||
/** |
||||
* 是否为在线表单消息数据。 |
||||
*/ |
||||
@TableField(value = "online_form_data") |
||||
private Boolean onlineFormData; |
||||
|
||||
/** |
||||
* 更新时间。 |
||||
*/ |
||||
@TableField(value = "update_time") |
||||
private Date updateTime; |
||||
|
||||
/** |
||||
* 更新者Id。 |
||||
*/ |
||||
@TableField(value = "update_user_id") |
||||
private Long updateUserId; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
/** |
||||
* 创建者Id。 |
||||
*/ |
||||
@TableField(value = "create_user_id") |
||||
private Long createUserId; |
||||
|
||||
/** |
||||
* 创建者显示名。 |
||||
*/ |
||||
@TableField(value = "create_username") |
||||
private String createUsername; |
||||
|
||||
@Mapper |
||||
public interface FlowMessageModelMapper extends BaseModelMapper<FlowMessageVo, FlowMessage> { |
||||
} |
||||
public static final FlowMessage.FlowMessageModelMapper INSTANCE = Mappers.getMapper(FlowMessage.FlowMessageModelMapper.class); |
||||
} |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 流程任务消息的候选身份实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_msg_candidate_identity") |
||||
public class FlowMessageCandidateIdentity { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "id") |
||||
private Long id; |
||||
|
||||
/** |
||||
* 任务消息Id。 |
||||
*/ |
||||
@TableField(value = "message_id") |
||||
private Long messageId; |
||||
|
||||
/** |
||||
* 候选身份类型。 |
||||
*/ |
||||
@TableField(value = "candidate_type") |
||||
private String candidateType; |
||||
|
||||
/** |
||||
* 候选身份Id。 |
||||
*/ |
||||
@TableField(value = "candidate_id") |
||||
private String candidateId; |
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程任务消息所属用户的操作表。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_msg_identity_operation") |
||||
public class FlowMessageIdentityOperation { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "id") |
||||
private Long id; |
||||
|
||||
/** |
||||
* 任务消息Id。 |
||||
*/ |
||||
@TableField(value = "message_id") |
||||
private Long messageId; |
||||
|
||||
/** |
||||
* 用户登录名。 |
||||
*/ |
||||
@TableField(value = "login_name") |
||||
private String loginName; |
||||
|
||||
/** |
||||
* 操作类型。 |
||||
* 常量值参考FlowMessageOperationType对象。 |
||||
*/ |
||||
@TableField(value = "operation_type") |
||||
private Integer operationType; |
||||
|
||||
/** |
||||
* 操作时间。 |
||||
*/ |
||||
@TableField(value = "operation_time") |
||||
private Date operationTime; |
||||
} |
||||
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
import org.flowable.task.api.TaskInfo; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程多实例任务执行流水对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@NoArgsConstructor |
||||
@TableName(value = "zz_flow_multi_instance_trans") |
||||
public class FlowMultiInstanceTrans { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "id") |
||||
private Long id; |
||||
|
||||
/** |
||||
* 流程实例Id。 |
||||
*/ |
||||
@TableField(value = "process_instance_id") |
||||
private String processInstanceId; |
||||
|
||||
/** |
||||
* 任务Id。 |
||||
*/ |
||||
@TableField(value = "task_id") |
||||
private String taskId; |
||||
|
||||
/** |
||||
* 任务标识。 |
||||
*/ |
||||
@TableField(value = "task_key") |
||||
private String taskKey; |
||||
|
||||
/** |
||||
* 会签任务的执行Id。 |
||||
*/ |
||||
@TableField(value = "multi_instance_exec_id") |
||||
private String multiInstanceExecId; |
||||
|
||||
/** |
||||
* 任务的执行Id。 |
||||
*/ |
||||
@TableField(value = "execution_id") |
||||
private String executionId; |
||||
|
||||
/** |
||||
* 会签指派人列表。 |
||||
*/ |
||||
@TableField(value = "assignee_list") |
||||
private String assigneeList; |
||||
|
||||
/** |
||||
* 创建者Id。 |
||||
*/ |
||||
@TableField(value = "create_user_id") |
||||
private Long createUserId; |
||||
|
||||
/** |
||||
* 创建者登录名。 |
||||
*/ |
||||
@TableField(value = "create_login_name") |
||||
private String createLoginName; |
||||
|
||||
/** |
||||
* 创建者显示名。 |
||||
*/ |
||||
@TableField(value = "create_username") |
||||
private String createUsername; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
public FlowMultiInstanceTrans(TaskInfo task) { |
||||
this.fillWith(task); |
||||
} |
||||
|
||||
public void fillWith(TaskInfo task) { |
||||
this.taskId = task.getId(); |
||||
this.taskKey = task.getTaskDefinitionKey(); |
||||
this.processInstanceId = task.getProcessInstanceId(); |
||||
this.executionId = task.getExecutionId(); |
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* 工作流 审批设置。 |
||||
* |
||||
* @author |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_node_tasks") |
||||
public class FlowNodeTasks implements Serializable { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "id") |
||||
private Long id; |
||||
|
||||
/** |
||||
* 流程ID |
||||
*/ |
||||
@TableField(value = "flow_id") |
||||
private Long flowId; |
||||
|
||||
/** |
||||
* 执行时机 |
||||
*/ |
||||
@TableField(value = "execution_timing") |
||||
private String executionTiming; |
||||
|
||||
/** |
||||
* 类型 |
||||
*/ |
||||
@TableField(value = "type") |
||||
private Integer type; |
||||
|
||||
/** |
||||
* 操作。 |
||||
*/ |
||||
@TableField(value = "operation") |
||||
private String operation; |
||||
|
||||
/** |
||||
* task_key。 |
||||
*/ |
||||
@TableField(value = "task_key") |
||||
private String taskKey; |
||||
} |
||||
@ -0,0 +1,161 @@
@@ -0,0 +1,161 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import apelet.common.core.base.mapper.BaseModelMapper; |
||||
import apelet.common.core.util.ContextUtil; |
||||
import apelet.common.flow.vo.FlowTaskCommentVo; |
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
import org.flowable.task.api.TaskInfo; |
||||
import org.mapstruct.Mapper; |
||||
import org.mapstruct.factory.Mappers; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* FlowTaskComment实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@NoArgsConstructor |
||||
@TableName(value = "zz_flow_task_comment") |
||||
public class FlowTaskComment { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "id") |
||||
private Long id; |
||||
|
||||
/** |
||||
* 流程实例Id。 |
||||
*/ |
||||
@TableField(value = "process_instance_id") |
||||
private String processInstanceId; |
||||
|
||||
/** |
||||
* 任务Id。 |
||||
*/ |
||||
@TableField(value = "task_id") |
||||
private String taskId; |
||||
|
||||
/** |
||||
* 任务标识。 |
||||
*/ |
||||
@TableField(value = "task_key") |
||||
private String taskKey; |
||||
|
||||
/** |
||||
* 任务名称。 |
||||
*/ |
||||
@TableField(value = "task_name") |
||||
private String taskName; |
||||
|
||||
/** |
||||
* 用于驳回和自由跳的目标任务标识。 |
||||
*/ |
||||
@TableField(value = "target_task_key") |
||||
private String targetTaskKey; |
||||
|
||||
/** |
||||
* 任务的执行Id。 |
||||
*/ |
||||
@TableField(value = "execution_id") |
||||
private String executionId; |
||||
|
||||
/** |
||||
* 会签任务的执行Id。 |
||||
*/ |
||||
@TableField(value = "multi_instance_exec_id") |
||||
private String multiInstanceExecId; |
||||
|
||||
/** |
||||
* 审批类型。 |
||||
*/ |
||||
@TableField(value = "approval_type") |
||||
private String approvalType; |
||||
|
||||
/** |
||||
* 批注内容。 |
||||
*/ |
||||
@TableField(value = "task_comment") |
||||
private String taskComment; |
||||
|
||||
/** |
||||
* 委托指定人,比如加签、转办等。 |
||||
*/ |
||||
@TableField(value = "delegate_assignee") |
||||
private String delegateAssignee; |
||||
|
||||
/** |
||||
* 自定义数据。开发者可自行扩展,推荐使用JSON格式数据。 |
||||
*/ |
||||
@TableField(value = "custom_business_data") |
||||
private String customBusinessData; |
||||
|
||||
/** |
||||
* 审批人头像。 |
||||
*/ |
||||
@TableField(value = "head_image_url") |
||||
private String headImageUrl; |
||||
|
||||
/** |
||||
* 创建者Id。 |
||||
*/ |
||||
@TableField(value = "create_user_id") |
||||
private Long createUserId; |
||||
|
||||
/** |
||||
* 创建者登录名。 |
||||
*/ |
||||
@TableField(value = "create_login_name") |
||||
private String createLoginName; |
||||
|
||||
/** |
||||
* 创建者显示名。 |
||||
*/ |
||||
@TableField(value = "create_username") |
||||
private String createUsername; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
private static final String REQ_ATTRIBUTE_KEY = "flowTaskComment"; |
||||
|
||||
public FlowTaskComment(TaskInfo task) { |
||||
this.fillWith(task); |
||||
} |
||||
|
||||
public static void setToRequest(FlowTaskComment comment) { |
||||
if (ContextUtil.getHttpRequest() != null) { |
||||
ContextUtil.getHttpRequest().setAttribute(REQ_ATTRIBUTE_KEY, comment); |
||||
} |
||||
} |
||||
|
||||
public static FlowTaskComment getFromRequest() { |
||||
if (ContextUtil.getHttpRequest() == null) { |
||||
return null; |
||||
} |
||||
return (FlowTaskComment) ContextUtil.getHttpRequest().getAttribute(REQ_ATTRIBUTE_KEY); |
||||
} |
||||
|
||||
public void fillWith(TaskInfo task) { |
||||
this.taskId = task.getId(); |
||||
this.taskKey = task.getTaskDefinitionKey(); |
||||
this.taskName = task.getName(); |
||||
this.processInstanceId = task.getProcessInstanceId(); |
||||
this.executionId = task.getExecutionId(); |
||||
} |
||||
|
||||
@Mapper |
||||
public interface FlowTaskCommentModelMapper extends BaseModelMapper<FlowTaskCommentVo, FlowTaskComment> { |
||||
} |
||||
public static final FlowTaskCommentModelMapper INSTANCE = Mappers.getMapper(FlowTaskCommentModelMapper.class); |
||||
} |
||||
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* 流程任务扩展实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_task_ext") |
||||
public class FlowTaskExt { |
||||
|
||||
/** |
||||
* 流程引擎的定义Id。 |
||||
*/ |
||||
@TableField(value = "process_definition_id") |
||||
private String processDefinitionId; |
||||
|
||||
/** |
||||
* 流程引擎任务Id。 |
||||
*/ |
||||
@TableField(value = "task_id") |
||||
private String taskId; |
||||
|
||||
/** |
||||
* 操作列表JSON。 |
||||
*/ |
||||
@TableField(value = "operation_list_json") |
||||
private String operationListJson; |
||||
|
||||
/** |
||||
* 变量列表JSON。 |
||||
*/ |
||||
@TableField(value = "variable_list_json") |
||||
private String variableListJson; |
||||
|
||||
/** |
||||
* 存储多实例的assigneeList的JSON。 |
||||
*/ |
||||
@TableField(value = "assignee_list_json") |
||||
private String assigneeListJson; |
||||
|
||||
/** |
||||
* 分组类型。 |
||||
*/ |
||||
@TableField(value = "group_type") |
||||
private String groupType; |
||||
|
||||
/** |
||||
* 保存岗位相关的数据。 |
||||
*/ |
||||
@TableField(value = "dept_post_list_json") |
||||
private String deptPostListJson; |
||||
|
||||
/** |
||||
* 逗号分隔的角色Id。 |
||||
*/ |
||||
@TableField(value = "role_ids") |
||||
private String roleIds; |
||||
|
||||
/** |
||||
* 逗号分隔的部门Id。 |
||||
*/ |
||||
@TableField(value = "dept_ids") |
||||
private String deptIds; |
||||
|
||||
/** |
||||
* 逗号分隔候选用户名。 |
||||
*/ |
||||
@TableField(value = "candidate_usernames") |
||||
private String candidateUsernames; |
||||
|
||||
/** |
||||
* 抄送相关的数据。 |
||||
*/ |
||||
@TableField(value = "copy_list_json") |
||||
private String copyListJson; |
||||
|
||||
/** |
||||
* 用户任务的扩展属性,存储为JSON的字符串格式。 |
||||
*/ |
||||
@TableField(value = "extra_data_json") |
||||
private String extraDataJson; |
||||
} |
||||
@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 超时任务作业实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_task_timeout_job") |
||||
public class FlowTaskTimeoutJob { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "id") |
||||
private Long id; |
||||
|
||||
/** |
||||
* 流程定义Id。 |
||||
*/ |
||||
@TableField(value = "process_definition_id") |
||||
private String processDefinitionId; |
||||
|
||||
/** |
||||
* 流程实例Id。 |
||||
*/ |
||||
@TableField(value = "process_instance_id") |
||||
private String processInstanceId; |
||||
|
||||
/** |
||||
* 流程任务标识。 |
||||
*/ |
||||
@TableField(value = "task_key") |
||||
private String taskKey; |
||||
|
||||
/** |
||||
* 流程任务Id。 |
||||
*/ |
||||
@TableField(value = "task_id") |
||||
private String taskId; |
||||
|
||||
/** |
||||
* 超时的小时数。 |
||||
*/ |
||||
@TableField(value = "timeout_hours") |
||||
private Integer timeoutHours; |
||||
|
||||
/** |
||||
* 超时处理方式。 |
||||
*/ |
||||
@TableField(value = "handle_way") |
||||
private String handleWay; |
||||
|
||||
/** |
||||
* 超时处理缺省用户名。 |
||||
*/ |
||||
@TableField(value = "default_assignee") |
||||
private String defaultAssignee; |
||||
|
||||
/** |
||||
* 处理错误信息。 |
||||
*/ |
||||
@TableField(value = "error_message") |
||||
private String errorMessage; |
||||
|
||||
/** |
||||
* 执行状态。参考常量类FlowTaskTimeoutJobStatus的值。 |
||||
*/ |
||||
@TableField(value = "status") |
||||
private Integer status; |
||||
|
||||
/** |
||||
* 执行时间。 |
||||
*/ |
||||
@TableField(value = "exec_time") |
||||
private Date execTime; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
/** |
||||
* 更新时间。 |
||||
*/ |
||||
@TableField(value = "update_time") |
||||
private Date updateTime; |
||||
} |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程处理事务事件消费者流水实体。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@AllArgsConstructor |
||||
@TableName(value = "zz_flow_trans_consumer") |
||||
public class FlowTransConsumer { |
||||
|
||||
/** |
||||
* 流水Id。 |
||||
*/ |
||||
@TableId(value = "trans_id") |
||||
private Long transId; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
} |
||||
@ -0,0 +1,121 @@
@@ -0,0 +1,121 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程处理事务事件生产者流水实体。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_trans_producer") |
||||
public class FlowTransProducer { |
||||
|
||||
/** |
||||
* 流水Id。 |
||||
*/ |
||||
@TableId(value = "trans_id") |
||||
private Long transId; |
||||
|
||||
/** |
||||
* 应用编码。为空时,表示非第三方应用接入。 |
||||
*/ |
||||
@TableField(value = "app_code") |
||||
private String appCode; |
||||
|
||||
/** |
||||
* 业务数据库链接Id。 |
||||
*/ |
||||
@TableField(value = "dblink_id") |
||||
private Long dblinkId; |
||||
|
||||
/** |
||||
* 流程实例Id。 |
||||
*/ |
||||
@TableField(value = "process_instance_id") |
||||
private String processInstanceId; |
||||
|
||||
/** |
||||
* 任务Id。 |
||||
*/ |
||||
@TableField(value = "task_id") |
||||
private String taskId; |
||||
|
||||
/** |
||||
* 任务标识。 |
||||
*/ |
||||
@TableField(value = "task_key") |
||||
private String taskKey; |
||||
|
||||
/** |
||||
* 任务名称。 |
||||
*/ |
||||
@TableField(value = "task_name") |
||||
private String taskName; |
||||
|
||||
/** |
||||
* 审批批注。 |
||||
*/ |
||||
@TableField(value = "task_comment") |
||||
private String taskComment; |
||||
|
||||
/** |
||||
* 当前请求的url。 |
||||
*/ |
||||
@TableField(value = "url") |
||||
private String url; |
||||
|
||||
/** |
||||
* 创建该事务性事件对象的初始方法。格式为:方法名(参数类型1,参数类型2)。 |
||||
*/ |
||||
@TableField(value = "init_method") |
||||
private String initMethod; |
||||
|
||||
/** |
||||
* 当前请求的traceId。 |
||||
*/ |
||||
@TableField(value = "trace_id") |
||||
private String traceId; |
||||
|
||||
/** |
||||
* 和SQL操作相关的数据。值类型为TransactionalBusinessData.BusinessSqlData对象。 |
||||
*/ |
||||
@TableField(value = "sql_data") |
||||
private String sqlData; |
||||
|
||||
/** |
||||
* 尝试次数。默认的插入值为1。 |
||||
*/ |
||||
@TableField(value = "try_times") |
||||
private Integer tryTimes; |
||||
|
||||
/** |
||||
* 提交业务数据时的错误信息。如果正常提交,该值为空。 |
||||
*/ |
||||
@TableField(value = "error_reason") |
||||
private String errorReason; |
||||
|
||||
/** |
||||
* 创建者登录名。 |
||||
*/ |
||||
@TableField(value = "create_login_name") |
||||
private String createLoginName; |
||||
|
||||
/** |
||||
* 创建者中文用户名。 |
||||
*/ |
||||
@TableField(value = "create_username") |
||||
private String createUsername; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
} |
||||
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField; |
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 流程变量日志实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_variable_log") |
||||
public class FlowVariableLog { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "id") |
||||
private Long id; |
||||
|
||||
/** |
||||
* 流程定义键。 |
||||
*/ |
||||
@TableField(value = "process_definition_key") |
||||
private String processDefinitionKey; |
||||
|
||||
/** |
||||
* 流程实例Id。 |
||||
*/ |
||||
@TableField(value = "process_instance_id") |
||||
private String processInstanceId; |
||||
|
||||
/** |
||||
* 流程任务标识。 |
||||
*/ |
||||
@TableField(value = "task_key") |
||||
private String taskKey; |
||||
|
||||
/** |
||||
* 全部变量数据。 |
||||
*/ |
||||
@TableField(value = "variable_data") |
||||
private String variableData; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
/** |
||||
* 过期时间。 |
||||
*/ |
||||
@TableField(value = "expired_time") |
||||
private Date expiredTime; |
||||
} |
||||
@ -0,0 +1,172 @@
@@ -0,0 +1,172 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import apelet.common.core.annotation.DeptFilterColumn; |
||||
import apelet.common.core.annotation.RelationConstDict; |
||||
import apelet.common.core.annotation.UserFilterColumn; |
||||
import apelet.common.core.base.mapper.BaseModelMapper; |
||||
import apelet.common.flow.constant.FlowTaskStatus; |
||||
import apelet.common.flow.vo.FlowWorkOrderVo; |
||||
import com.baomidou.mybatisplus.annotation.*; |
||||
import lombok.Data; |
||||
import org.mapstruct.Mapper; |
||||
import org.mapstruct.factory.Mappers; |
||||
|
||||
import java.util.Date; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 工作流工单实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_work_order") |
||||
public class FlowWorkOrder { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "work_order_id") |
||||
private Long workOrderId; |
||||
|
||||
/** |
||||
* 租户Id。 |
||||
*/ |
||||
@TableField(value = "tenant_id") |
||||
private Long tenantId; |
||||
|
||||
/** |
||||
* 应用编码。为空时,表示非第三方应用接入。 |
||||
*/ |
||||
@TableField(value = "app_code") |
||||
private String appCode; |
||||
|
||||
/** |
||||
* 工单编码字段。 |
||||
*/ |
||||
@TableField(value = "work_order_code") |
||||
private String workOrderCode; |
||||
|
||||
/** |
||||
* 流程定义标识。 |
||||
*/ |
||||
@TableField(value = "process_definition_key") |
||||
private String processDefinitionKey; |
||||
|
||||
/** |
||||
* 流程名称。 |
||||
*/ |
||||
@TableField(value = "process_definition_name") |
||||
private String processDefinitionName; |
||||
|
||||
/** |
||||
* 流程引擎的定义Id。 |
||||
*/ |
||||
@TableField(value = "process_definition_id") |
||||
private String processDefinitionId; |
||||
|
||||
/** |
||||
* 流程实例Id。 |
||||
*/ |
||||
@TableField(value = "process_instance_id") |
||||
private String processInstanceId; |
||||
|
||||
/** |
||||
* 在线表单的主表Id。 |
||||
*/ |
||||
@TableField(value = "online_table_id") |
||||
private Long onlineTableId; |
||||
|
||||
/** |
||||
* 静态表单所使用的数据表名。 |
||||
*/ |
||||
@TableField(value = "table_name") |
||||
private String tableName; |
||||
|
||||
/** |
||||
* 业务主键值。 |
||||
*/ |
||||
@TableField(value = "business_key") |
||||
private String businessKey; |
||||
|
||||
/** |
||||
* 最近的审批状态。 |
||||
*/ |
||||
@TableField(value = "latest_approval_status") |
||||
private Integer latestApprovalStatus; |
||||
|
||||
/** |
||||
* 流程状态。参考FlowTaskStatus常量值对象。 |
||||
*/ |
||||
@TableField(value = "flow_status") |
||||
private Integer flowStatus; |
||||
|
||||
/** |
||||
* 提交用户登录名称。 |
||||
*/ |
||||
@TableField(value = "submit_username") |
||||
private String submitUsername; |
||||
|
||||
/** |
||||
* 提交用户所在部门Id。 |
||||
*/ |
||||
@DeptFilterColumn |
||||
@TableField(value = "dept_id") |
||||
private Long deptId; |
||||
|
||||
/** |
||||
* 更新时间。 |
||||
*/ |
||||
@TableField(value = "update_time") |
||||
private Date updateTime; |
||||
|
||||
/** |
||||
* 更新者Id。 |
||||
*/ |
||||
@TableField(value = "update_user_id") |
||||
private Long updateUserId; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
/** |
||||
* 创建者Id。 |
||||
*/ |
||||
@UserFilterColumn |
||||
@TableField(value = "create_user_id") |
||||
private Long createUserId; |
||||
|
||||
/** |
||||
* 逻辑删除标记字段(1: 正常 -1: 已删除)。 |
||||
*/ |
||||
@TableLogic |
||||
@TableField(value = "deleted_flag") |
||||
private Integer deletedFlag; |
||||
|
||||
/** |
||||
* createTime 范围过滤起始值(>=)。 |
||||
*/ |
||||
@TableField(exist = false) |
||||
private String createTimeStart; |
||||
|
||||
/** |
||||
* createTime 范围过滤结束值(<=)。 |
||||
*/ |
||||
@TableField(exist = false) |
||||
private String createTimeEnd; |
||||
|
||||
@RelationConstDict( |
||||
masterIdField = "flowStatus", |
||||
constantDictClass = FlowTaskStatus.class) |
||||
@TableField(exist = false) |
||||
private Map<String, Object> flowStatusDictMap; |
||||
|
||||
@Mapper |
||||
public interface FlowWorkOrderModelMapper extends BaseModelMapper<FlowWorkOrderVo, FlowWorkOrder> { |
||||
} |
||||
public static final FlowWorkOrderModelMapper INSTANCE = Mappers.getMapper(FlowWorkOrderModelMapper.class); |
||||
} |
||||
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
package apelet.common.flow.model; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.*; |
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* 工作流工单扩展数据实体对象。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
@Data |
||||
@TableName(value = "zz_flow_work_order_ext") |
||||
public class FlowWorkOrderExt { |
||||
|
||||
/** |
||||
* 主键Id。 |
||||
*/ |
||||
@TableId(value = "id") |
||||
private Long id; |
||||
|
||||
/** |
||||
* 流程工单Id。 |
||||
*/ |
||||
@TableField(value = "work_order_id") |
||||
private Long workOrderId; |
||||
|
||||
/** |
||||
* 草稿数据。 |
||||
*/ |
||||
@TableField(value = "draft_data") |
||||
private String draftData; |
||||
|
||||
/** |
||||
* 业务数据。 |
||||
*/ |
||||
@TableField(value = "business_data") |
||||
private String businessData; |
||||
|
||||
/** |
||||
* 更新时间。 |
||||
*/ |
||||
@TableField(value = "update_time") |
||||
private Date updateTime; |
||||
|
||||
/** |
||||
* 更新者Id。 |
||||
*/ |
||||
@TableField(value = "update_user_id") |
||||
private Long updateUserId; |
||||
|
||||
/** |
||||
* 创建时间。 |
||||
*/ |
||||
@TableField(value = "create_time") |
||||
private Date createTime; |
||||
|
||||
/** |
||||
* 创建者Id。 |
||||
*/ |
||||
@TableField(value = "create_user_id") |
||||
private Long createUserId; |
||||
|
||||
/** |
||||
* 逻辑删除标记字段(1: 正常 -1: 已删除)。 |
||||
*/ |
||||
@TableLogic |
||||
@TableField(value = "deleted_flag") |
||||
private Integer deletedFlag; |
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
package apelet.common.flow.model.constant; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 工作流绑定表单类型。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public final class FlowBindFormType { |
||||
|
||||
/** |
||||
* 在线表单。 |
||||
*/ |
||||
public static final int ONLINE_FORM = 0; |
||||
/** |
||||
* 路由表单。 |
||||
*/ |
||||
public static final int ROUTER_FORM = 1; |
||||
|
||||
private static final Map<Object, String> DICT_MAP = new HashMap<>(2); |
||||
static { |
||||
DICT_MAP.put(ONLINE_FORM, "在线表单"); |
||||
DICT_MAP.put(ROUTER_FORM, "路由表单"); |
||||
} |
||||
|
||||
/** |
||||
* 判断参数是否为当前常量字典的合法值。 |
||||
* |
||||
* @param value 待验证的参数值。 |
||||
* @return 合法返回true,否则false。 |
||||
*/ |
||||
public static boolean isValid(Integer value) { |
||||
return value != null && DICT_MAP.containsKey(value); |
||||
} |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowBindFormType() { |
||||
} |
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
package apelet.common.flow.model.constant; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 工作流状态。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public final class FlowEntryStatus { |
||||
|
||||
/** |
||||
* 未发布。 |
||||
*/ |
||||
public static final int UNPUBLISHED = 0; |
||||
/** |
||||
* 已发布。 |
||||
*/ |
||||
public static final int PUBLISHED = 1; |
||||
|
||||
private static final Map<Object, String> DICT_MAP = new HashMap<>(2); |
||||
static { |
||||
DICT_MAP.put(UNPUBLISHED, "未发布"); |
||||
DICT_MAP.put(PUBLISHED, "已发布"); |
||||
} |
||||
|
||||
/** |
||||
* 判断参数是否为当前常量字典的合法值。 |
||||
* |
||||
* @param value 待验证的参数值。 |
||||
* @return 合法返回true,否则false。 |
||||
*/ |
||||
public static boolean isValid(Integer value) { |
||||
return value != null && DICT_MAP.containsKey(value); |
||||
} |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowEntryStatus() { |
||||
} |
||||
} |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
package apelet.common.flow.model.constant; |
||||
|
||||
/** |
||||
* 工作流消息操作类型。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public final class FlowMessageOperationType { |
||||
|
||||
/** |
||||
* 已读操作。 |
||||
*/ |
||||
public static final int READ_FINISHED = 0; |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowMessageOperationType() { |
||||
} |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
package apelet.common.flow.model.constant; |
||||
|
||||
/** |
||||
* 工作流消息类型。 |
||||
* |
||||
* @author guifc |
||||
* @date 2023-08-04 |
||||
*/ |
||||
public final class FlowMessageType { |
||||
|
||||
/** |
||||
* 催办消息。 |
||||
*/ |
||||
public static final int REMIND_TYPE = 0; |
||||
|
||||
/** |
||||
* 抄送消息。 |
||||
*/ |
||||
public static final int COPY_TYPE = 1; |
||||
|
||||
/** |
||||
* 私有构造函数,明确标识该常量类的作用。 |
||||
*/ |
||||
private FlowMessageType() { |
||||
} |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue