..
This commit is contained in:
@@ -20,6 +20,7 @@ import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.flow.enums.ProcessEventTypeEnum;
|
||||
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.flow.vo.HighLightVO;
|
||||
import com.budwk.app.flow.vo.ProcessInstanceVO;
|
||||
import com.budwk.app.flow.vo.ProcessTaskVO;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
@@ -137,11 +138,23 @@ public class FlowCommonController {
|
||||
List<ProcessTaskVO> res = new ArrayList<>();
|
||||
processTaskList.forEach(processTask -> {
|
||||
ProcessTaskVO vo = BeanUtil.toBean(processTask, ProcessTaskVO.class);
|
||||
if (vo.getTaskState().equals(ProcessTaskStateEnum.FINISHED.getCode()) && StrUtil.isNotBlank(vo.getOperator())) {
|
||||
|
||||
}
|
||||
|
||||
res.add(vo);
|
||||
});
|
||||
return Result.success(res);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@ApiOperation("流程图高亮")
|
||||
public Result instanceHighLight(@Param("instanceId") Long instanceId) {
|
||||
HighLightVO highLightVO = flowEngine.processInstanceService().highLight(instanceId);
|
||||
return Result.success(highLightVO);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@@ -209,6 +222,7 @@ public class FlowCommonController {
|
||||
@At("/executeTask")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("执行任务")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result executeTask(@Param("data") String param) {
|
||||
Dict args = Json.fromJson(Dict.class, param);
|
||||
Long processTaskId = args.getLong(FlowConst.PROCESS_TASK_ID_KEY);
|
||||
|
||||
@@ -43,7 +43,8 @@ public class FlowDefineController {
|
||||
@Ok("beetl:/platform/flow/define/preview.html")
|
||||
@SaCheckLogin
|
||||
public void preview(HttpServletRequest request) {
|
||||
request.setAttribute("id", request.getParameter("id"));
|
||||
request.setAttribute("defineId", request.getParameter("defineId"));
|
||||
request.setAttribute("instanceId", request.getParameter("instanceId"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@ public class FlowDesignController {
|
||||
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("icon", processDesign.getIcon());
|
||||
jsonObject.set("description", processDesign.getDescription());
|
||||
processDesign.setContent(jsonObject);
|
||||
dao.insert(processDesign);
|
||||
return Result.success();
|
||||
@@ -143,6 +144,7 @@ public class FlowDesignController {
|
||||
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("icon", processDesign.getIcon());
|
||||
jsonObject.set("description", processDesign.getDescription());
|
||||
processDesign.setContent(jsonObject);
|
||||
processDesignService.update(processDesign);
|
||||
return Result.success();
|
||||
@@ -161,12 +163,12 @@ public class FlowDesignController {
|
||||
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("icon", processDesign.getIcon());
|
||||
jsonObject.set("description", processDesign.getDescription());
|
||||
processDesign.setContent(jsonObject);
|
||||
processDesignService.update(processDesign);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@ApiOperation("删除流程设计")
|
||||
|
||||
@@ -13,8 +13,8 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* 流程模型
|
||||
*
|
||||
* @author mldong
|
||||
* @date 2023/4/25
|
||||
*/
|
||||
@@ -24,6 +24,8 @@ public class ProcessModel extends BaseModel {
|
||||
private String type; // 流程定义分类
|
||||
private String icon; // 流程定义图标
|
||||
private String category; // 流程定义分类
|
||||
private String remark; // 流程备注
|
||||
private String description; // 流程说明
|
||||
private String instanceUrl; // 启动实例要填写的表单key
|
||||
private String h5InstanceUrl; // 启动实例要填写的手机端表单key
|
||||
private String instanceViewUrl;
|
||||
@@ -39,13 +41,14 @@ public class ProcessModel extends BaseModel {
|
||||
|
||||
/**
|
||||
* 获取开始节点
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public StartModel getStart() {
|
||||
StartModel startModel = null;
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
NodeModel nodeModel = nodes.get(i);
|
||||
if(nodeModel instanceof StartModel) {
|
||||
if (nodeModel instanceof StartModel) {
|
||||
startModel = (StartModel) nodeModel;
|
||||
break;
|
||||
}
|
||||
@@ -55,12 +58,13 @@ public class ProcessModel extends BaseModel {
|
||||
|
||||
/**
|
||||
* 获取process定义的指定节点名称的节点模型
|
||||
*
|
||||
* @param nodeName 节点名称
|
||||
* @return
|
||||
*/
|
||||
public NodeModel getNode(String nodeName) {
|
||||
for(NodeModel node : nodes) {
|
||||
if(node.getName().equals(nodeName)) {
|
||||
for (NodeModel node : nodes) {
|
||||
if (node.getName().equals(nodeName)) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -69,23 +73,24 @@ public class ProcessModel extends BaseModel {
|
||||
|
||||
/**
|
||||
* 获取下一个任务节点模型集合
|
||||
*
|
||||
* @param nodeName
|
||||
* @return
|
||||
*/
|
||||
public List<TaskModel> getNextTaskModels(String nodeName) {
|
||||
List<TaskModel> res = new ArrayList<>();
|
||||
NodeModel nodeModel = getNode(nodeName);
|
||||
if(nodeModel == null) return res;
|
||||
if (nodeModel == null) return res;
|
||||
// 获取所有输出边的目标节点
|
||||
List<NodeModel> nextNodeModelList = nodeModel.getOutputs().stream().map(TransitionModel::getTarget).toList();
|
||||
nextNodeModelList.forEach(item->{
|
||||
if(item instanceof TaskModel) {
|
||||
nextNodeModelList.forEach(item -> {
|
||||
if (item instanceof TaskModel) {
|
||||
res.add((TaskModel) item);
|
||||
}
|
||||
});
|
||||
if(res.isEmpty()) {
|
||||
if (res.isEmpty()) {
|
||||
// 如果下一个节点不存在任务节点,递归往下找
|
||||
nextNodeModelList.forEach(item->{
|
||||
nextNodeModelList.forEach(item -> {
|
||||
List<TaskModel> taskModelList = getNextTaskModels(item.getName());
|
||||
res.addAll(taskModelList);
|
||||
});
|
||||
@@ -95,19 +100,22 @@ public class ProcessModel extends BaseModel {
|
||||
|
||||
/**
|
||||
* 获取下一个任务节点的候选人
|
||||
*
|
||||
* @param nodeName
|
||||
* @return
|
||||
*/
|
||||
public List<Candidate> getNextTaskModelCandidates(String nodeName) {
|
||||
List<Candidate> res = new ArrayList<>();
|
||||
List<TaskModel> nextTaskModels = getNextTaskModels(nodeName);
|
||||
nextTaskModels.forEach(item->{
|
||||
nextTaskModels.forEach(item -> {
|
||||
res.addAll(getCandidates(item));
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据任务模型获取候选人
|
||||
*
|
||||
* @param taskModel
|
||||
* @return
|
||||
*/
|
||||
@@ -115,29 +123,31 @@ public class ProcessModel extends BaseModel {
|
||||
List<Candidate> res = new ArrayList<>();
|
||||
// 从上下文中查找候选人处理人
|
||||
List<CandidateHandler> handlerList = ServiceContext.findList(CandidateHandler.class);
|
||||
handlerList.forEach(handler->{
|
||||
handlerList.forEach(handler -> {
|
||||
// 通过候选从处理类获取候选人集合
|
||||
List<Candidate> candidateList = handler.handle(taskModel);
|
||||
if(candidateList!=null) {
|
||||
if (candidateList != null) {
|
||||
res.addAll(candidateList);
|
||||
}
|
||||
});
|
||||
// 通过候选人处理类获取修选人
|
||||
String candidateHandler = taskModel.getCandidateHandler();
|
||||
if(StrUtil.isNotEmpty(candidateHandler)) {
|
||||
if (StrUtil.isNotEmpty(candidateHandler)) {
|
||||
CandidateHandler candidateHandlerClass = ReflectUtil.newInstance(candidateHandler);
|
||||
List<Candidate> candidateList = candidateHandlerClass.handle(taskModel);
|
||||
if(candidateList!=null) {
|
||||
if (candidateList != null) {
|
||||
res.addAll(candidateList);
|
||||
}
|
||||
}
|
||||
// 去重
|
||||
return res.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定的节点类型返回流程定义中所有模型对象
|
||||
*
|
||||
* @param clazz 节点类型
|
||||
* @param <T> 泛型
|
||||
* @param <T> 泛型
|
||||
* @return 节点列表
|
||||
*/
|
||||
public <T> List<T> getModels(Class<T> clazz) {
|
||||
@@ -147,10 +157,10 @@ public class ProcessModel extends BaseModel {
|
||||
}
|
||||
|
||||
private <T> void buildModels(List<T> models, List<T> nextModels, Class<T> clazz) {
|
||||
for(T nextModel : nextModels) {
|
||||
if(!models.contains(nextModel)) {
|
||||
for (T nextModel : nextModels) {
|
||||
if (!models.contains(nextModel)) {
|
||||
models.add(nextModel);
|
||||
buildModels(models, ((NodeModel)nextModel).getNextModels(clazz), clazz);
|
||||
buildModels(models, ((NodeModel) nextModel).getNextModels(clazz), clazz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.List;
|
||||
public class LfModel extends BaseModel {
|
||||
private String type; // 流程定义分类
|
||||
private String category;
|
||||
private String description; // 流程描述
|
||||
private String expireTime;// 过期时间(常量或变量)
|
||||
private String instanceUrl; // 启动实例的url,前后端分离后,定义为路由名或或路由地址
|
||||
private String h5InstanceUrl;
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
package com.budwk.app.flow.engine.parser;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.flow.engine.core.ServiceContext;
|
||||
import com.budwk.app.flow.engine.model.NodeModel;
|
||||
import com.budwk.app.flow.engine.model.ProcessModel;
|
||||
import com.budwk.app.flow.engine.model.TaskModel;
|
||||
import com.budwk.app.flow.engine.model.TransitionModel;
|
||||
import com.budwk.app.flow.engine.model.logicflow.*;
|
||||
import com.budwk.app.flow.engine.model.logicflow.LfEdge;
|
||||
import com.budwk.app.flow.engine.model.logicflow.LfModel;
|
||||
import com.budwk.app.flow.engine.model.logicflow.LfNode;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class ModelParser {
|
||||
private ModelParser(){}
|
||||
private ModelParser() {
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 将json定义文件解析成流程模型对象
|
||||
@@ -71,7 +72,7 @@ public class ModelParser {
|
||||
ProcessModel processModel = new ProcessModel();
|
||||
List<LfNode> nodes = lfModel.getNodes();
|
||||
List<LfEdge> edges = lfModel.getEdges();
|
||||
if(CollectionUtil.isEmpty(nodes) || CollectionUtil.isEmpty(edges) ) {
|
||||
if (CollectionUtil.isEmpty(nodes) || CollectionUtil.isEmpty(edges)) {
|
||||
return processModel;
|
||||
}
|
||||
// 流程定义基本信息
|
||||
@@ -79,6 +80,7 @@ public class ModelParser {
|
||||
processModel.setDisplayName(lfModel.getDisplayName());
|
||||
processModel.setType(lfModel.getType());
|
||||
processModel.setCategory(lfModel.getCategory());
|
||||
processModel.setDescription(lfModel.getDescription());
|
||||
processModel.setInstanceUrl(lfModel.getInstanceUrl());
|
||||
processModel.setH5InstanceUrl(lfModel.getH5InstanceUrl());
|
||||
processModel.setInstanceViewUrl(lfModel.getInstanceViewUrl());
|
||||
@@ -87,10 +89,10 @@ public class ModelParser {
|
||||
processModel.setPostInterceptors(lfModel.getPostInterceptors());
|
||||
processModel.setPreInterceptors(lfModel.getPreInterceptors());
|
||||
// 流程节点信息
|
||||
nodes.forEach(node->{
|
||||
String type = node.getType().replace(NodeParser.NODE_NAME_PREFIX,"");
|
||||
NodeParser nodeParser = ServiceContext.findByName(type,NodeParser.class);
|
||||
if(nodeParser!=null) {
|
||||
nodes.forEach(node -> {
|
||||
String type = node.getType().replace(NodeParser.NODE_NAME_PREFIX, "");
|
||||
NodeParser nodeParser = ServiceContext.findByName(type, NodeParser.class);
|
||||
if (nodeParser != null) {
|
||||
nodeParser.parse(node, edges);
|
||||
NodeModel nodeModel = nodeParser.getModel();
|
||||
processModel.getNodes().add(nodeParser.getModel());
|
||||
@@ -100,11 +102,11 @@ public class ModelParser {
|
||||
}
|
||||
});
|
||||
// 循环节点模型,构造输入边、输出边的source、target
|
||||
for(NodeModel node : processModel.getNodes()) {
|
||||
for(TransitionModel transition : node.getOutputs()) {
|
||||
for (NodeModel node : processModel.getNodes()) {
|
||||
for (TransitionModel transition : node.getOutputs()) {
|
||||
String to = transition.getTo();
|
||||
for(NodeModel node2 : processModel.getNodes()) {
|
||||
if(to.equalsIgnoreCase(node2.getName())) {
|
||||
for (NodeModel node2 : processModel.getNodes()) {
|
||||
if (to.equalsIgnoreCase(node2.getName())) {
|
||||
node2.getInputs().add(transition);
|
||||
transition.setTarget(node2);
|
||||
}
|
||||
|
||||
@@ -73,9 +73,14 @@ public class ProcessDefine extends BaseModel {
|
||||
@Column
|
||||
private Integer version;
|
||||
|
||||
@Comment
|
||||
@Comment("首字母")
|
||||
@Column
|
||||
@ColDefine(type = ColType.CHAR)
|
||||
private Character pinyinName;
|
||||
|
||||
@Comment("流程描述")
|
||||
@Column
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
private String description;
|
||||
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ import org.nutz.dao.entity.annotation.*;
|
||||
@Comment("流程设计")
|
||||
public class ProcessDesign extends BaseModel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Comment("主键")
|
||||
@Id
|
||||
private Long id;
|
||||
@@ -70,6 +68,11 @@ public class ProcessDesign extends BaseModel {
|
||||
@Column
|
||||
private String remark;
|
||||
|
||||
@Comment("流程描述")
|
||||
@Column
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
private String description;
|
||||
|
||||
@Comment("流程定义")
|
||||
@Column
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
|
||||
@@ -219,12 +219,6 @@ public interface ProcessInstanceService extends BaseService<ProcessInstance> {
|
||||
* @param actorId
|
||||
*/
|
||||
void updateCCStatus(Long processInstanceId, String actorId);
|
||||
/**
|
||||
* 自定义分页查询我的抄送
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
// CommonPage<ProcessInstanceVO> ccInstancePage(ProcessInstancePageParam param);
|
||||
|
||||
/**
|
||||
* 获取流程参与人回显文本数据
|
||||
|
||||
@@ -117,6 +117,7 @@ public class ProcessDefineServiceImpl extends BaseServiceImpl<ProcessDefine> imp
|
||||
define.setH5InstanceViewUrl(processModel.getH5InstanceViewUrl());
|
||||
define.setIcon(processModel.getIcon());
|
||||
define.setPinyinName(PinyinUtil.getFirstLetter(define.getDisplayName().charAt(0)));
|
||||
define.setDescription(processModel.getDescription());
|
||||
|
||||
define.setState(1);
|
||||
define.setContent(JSONUtil.parseObj(defineJsonStr));
|
||||
|
||||
@@ -175,8 +175,18 @@ public class ProcessTaskServiceImpl extends BaseServiceImpl<ProcessTask> impleme
|
||||
processTask.setTaskType(taskModel.getTaskType().getCode());
|
||||
processTask.setFormKey(taskModel.getForm());
|
||||
processTask.setProcessInstanceId(execution.getProcessInstanceId());
|
||||
execution.getArgs().put(FlowConst.IS_FIRST_TASK_NODE, FlowUtil.isFistTaskName(execution.getProcessModel(), taskModel.getName()));
|
||||
|
||||
// 增加是否为第一个任务节点标识
|
||||
execution.getArgs().put(FlowConst.IS_FIRST_TASK_NODE, FlowUtil.isFistTaskName(execution.getProcessModel(), taskModel.getName()));
|
||||
//过滤上个任务的表单数据 避免造成污染 每个任务只保存自己的表单数据
|
||||
Dict cleanArgs = Dict.create();
|
||||
execution.getArgs().forEach((k, v) -> {
|
||||
if (!k.startsWith(FlowConst.TASK_FORM_DATA_PREFIX)) {
|
||||
cleanArgs.set(k, v);
|
||||
}
|
||||
});
|
||||
execution.setArgs(cleanArgs);
|
||||
|
||||
processTask.setVariable(JSONUtil.toJsonStr(execution.getArgs()));
|
||||
processTask.setCreatedAt(now);
|
||||
processTask.setUpdatedAt(now);
|
||||
|
||||
@@ -44,6 +44,9 @@ public class ProcessTaskVO extends ProcessTask {
|
||||
|
||||
private List<JSONObject> taskActorList;
|
||||
|
||||
// 任务参与者
|
||||
private List<JSONObject> taskOperatorList;
|
||||
|
||||
// @Schema(description = "当前用户是否可执行")
|
||||
private boolean executable;
|
||||
// @Schema(description = "节点定义信息")
|
||||
|
||||
Reference in New Issue
Block a user