158 changed files with 16963 additions and 1 deletions
@ -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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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