flowable 配置自定义表单_Flowable用代码自定义流程
項目集成flowable有段時間了,發現行業的流程業務全是一條直線加3,4個人工審核的節點,并沒有分支網關等其它節點。因此原來用的model設計器組件多參數復雜,客戶現場的體驗不是很好。所以根據現場的實際業務自己調api的方式實現個簡單的流程設計器。
最終的實現的效果是由開始節點[StartEvent]和結束結點[EndEvent]及用戶任務節點[UserTask]組成的直線審核流程,并兼容用原生的流程設計器打開編輯。最終的效果如下圖所示:
最終的效果
前端界面設計介紹,用戶界面可以增加節點,刪除節點。對節點命名,定義節點的審核用戶[普通用戶或角色],具體效果圖如下所示:
用戶界面
定義收集前端參數的對象,具體代碼如下所示
@Data
public class ProcessParam {
//流程ID
private String modelId;
//流程定義key
private String key;
//流程名字
private String name;
//流程節點
private List tasks;
//開始結點名稱
private String startNodeName;
//結束節點名稱
private String endNodeName;
}
@Data
public class TaskParam {
public TaskParam(){
}
public TaskParam(String name,String no,String userType,List userOrRoleIds,String userOrRoleName){
this.name = name;
this.no = no;
this.userType = userType;
this.userOrRoleIds = userOrRoleIds;
this.userOrRoleName = userOrRoleName;
}
//節點名稱
private String name;
//節點編號
private String no;
//審核用戶類型 用戶(user)或角色(role)
private String userType;
//審核用戶或角色id
private List userOrRoleIds;
//用戶或角色名稱
private String userOrRoleName;
}
保存流程設計器的數據,具體的代媽如下:
大體思路是,構建一個BpmnModel對象,構建出各節點對象并設置好相關的參數,如名稱,編號,審核人等,用SequenceFlow對象按順序連接各節點對象,特別注意要設置各節點對象的outgoing屬性網上很多教程沒有提到這個,不設置會導致連接不正確。最后用BpmnAutoLayout對象自動設置好節點的坐標信息,不然也會導致流程在原生設計器顯示不正常。
public void saveModelData(ProcessParam processParam){
Model model = modelService.getModel(processParam.getModelId());
Process process = new Process();
process.setId(model.getKey());
process.setName(model.getName());
BpmnModel bpmnModelNew = new BpmnModel();
bpmnModelNew.addProcess(process);
List nodeList = processParam.getTasks();
//開始事件
StartEvent startEvent = new StartEvent();
startEvent.setId("start");
startEvent.setName(processParam.getStartNodeName());
process.addFlowElement(startEvent);
FlowElement waitNode = startEvent;
int i = 0;
for ( ;i < nodeList.size(); i++) {
TaskParam taskParam = nodeList.get(i);
UserTask userTask = new UserTask();
userTask.setId((i+1)+"");
userTask.setName(taskParam.getName());
if("user".equals(taskParam.getUserType())){
userTask.setCandidateUsers(taskParam.getUserOrRoleIds());
}
if("role".equals(taskParam.getUserType())){
userTask.setCandidateGroups(taskParam.getUserOrRoleIds());
}
process.addFlowElement(userTask);
SequenceFlow sequenceFlow = new SequenceFlow(waitNode.getId(), userTask.getId());
process.addFlowElement(sequenceFlow);
//設置當前節點的出口這個很關鍵,不設置這個的話生的流程圖會錯亂,網上很多教程也沒有提到
if(i==0){
((StartEvent) waitNode).setOutgoingFlows(ListUtil.toList(sequenceFlow));
}else {
((UserTask) waitNode).setOutgoingFlows(ListUtil.toList(sequenceFlow));
}
waitNode = userTask;
}
//結束事件
EndEvent completeEvent = new EndEvent();
completeEvent.setId("complete");
completeEvent.setName(processParam.getEndNodeName());
process.addFlowElement(completeEvent);
SequenceFlow endSequenceFlow = new SequenceFlow(waitNode.getId(), completeEvent.getId());
((UserTask) waitNode).setOutgoingFlows(ListUtil.toList(endSequenceFlow));
process.addFlowElement(endSequenceFlow);
//這句很關鍵讓程序自動部局各節點的位置,網上很多教程沒有提到
new BpmnAutoLayout(bpmnModelNew).execute();
//把BpmnModel轉成json格式進行保存
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
ObjectNode jsonNode = jsonConverter.convertToJson(bpmnModelNew);
modelService.saveModel(model.getId(),model.getName(),model.getKey(),model.getDescription(),jsonNode.toString(),true,"",new UserWf());
}
從數據庫獲取流程設計數據給到前端,具體代碼如下:
大體思路是:調用api獲取model對象,從model對象獲取流程的json字符串然后用工具類轉成BpmnModel對象,然后根據他們的關系生成ProcessParam對象傳到前端去。
public ProcessParam getModelData(String modelId){
ProcessParam processParam = new ProcessParam();
List tasks = new ArrayList<>();
processParam.setTasks(tasks);
Model model = modelService.getModel(modelId);
processParam.setModelId(model.getId());
processParam.setKey(model.getKey());
processParam.setName(model.getName());
//獲取流程設計器的json數據
String modelEditorJson = model.getModelEditorJson();
ObjectNode editorJsonNode = null;
try {
editorJsonNode = (ObjectNode) objectMapper.readTree(modelEditorJson);
} catch (IOException e) {
e.printStackTrace();
return processParam;
}
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
//把json轉成bpmnModel對象
BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorJsonNode);
Process process = bpmnModel.getMainProcess();
Map allNode = process.getFlowElementMap();
if(allNode==null||allNode.size()<1){//沒有節點信息直接返回
return processParam;
}
List startEventList = process.findFlowElementsOfType(StartEvent.class);
StartEvent startEvent = startEventList.get(0);
processParam.setStartNodeName(startEvent.getName());
String nextNodeId = startEvent.getOutgoingFlows().get(0).getTargetRef();
while (allNode.get(nextNodeId)!=null){
FlowElement fe = allNode.get(nextNodeId);
if(fe instanceof UserTask){
UserTask userTask = (UserTask) fe;
List userOrRoleIds = null;
String userOrRoleInfo = "";
String userType = null;
if(StrUtil.isNotBlank(userTask.getAssignee())){
userOrRoleIds = ListUtil.toList(userTask.getAssignee());
userType = "user";
}
if(userTask.getCandidateUsers()!=null&&userTask.getCandidateUsers().size()>0){
userOrRoleIds = userTask.getCandidateUsers();
userType = "user";
}
if(userTask.getCandidateGroups()!=null&&userTask.getCandidateGroups().size()>0){
userOrRoleIds = userTask.getCandidateGroups();
userType = "role";
}
//查詢用戶或角色名稱
if ("user".equals(userType)) {
userOrRoleInfo = this.getUserInfo(userOrRoleIds);
}
if ("role".equals(userType)) {
userOrRoleInfo = this.getRoleInfo(userOrRoleIds);
}
if(userTask.getOutgoingFlows().size()>1){
throw new RuntimeException("不支持多個分支流程數據,請使用高級流程設計器");
}
tasks.add(new TaskParam(userTask.getName(),userTask.getId(),userType,userOrRoleIds,userOrRoleInfo));
nextNodeId = userTask.getOutgoingFlows().get(0).getTargetRef();
}else if(fe instanceof EndEvent){
EndEvent endEvent = (EndEvent) fe;
processParam.setEndNodeName(endEvent.getName());
nextNodeId = "";
break;
}else {
throw new RuntimeException("不支持當前流程數據,請使用高級流程設計器");
}
}
return processParam;
}
總結
以上是生活随笔為你收集整理的flowable 配置自定义表单_Flowable用代码自定义流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 傅里叶分析斯坦恩中文版pdf_实分析(英
- 下一篇: python 反向传值_Django中r