diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiModelController.java b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiModelController.java index 5a8a82db..556ca002 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiModelController.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiModelController.java @@ -4,10 +4,12 @@ import com.alibaba.fastjson.JSONObject; import ink.wgink.common.base.DefaultBaseController; import ink.wgink.exceptions.ParamsException; import ink.wgink.interfaces.consts.ISystemConstant; +import ink.wgink.module.activiti.pojo.dtos.ActivitiFlowNodeDTO; import ink.wgink.module.activiti.pojo.vos.ActivitiModelVO; import ink.wgink.module.activiti.service.activiti.IActivitiModelService; import ink.wgink.pojo.result.ErrorResult; import ink.wgink.pojo.result.SuccessResult; +import ink.wgink.pojo.result.SuccessResultData; import ink.wgink.util.RegexUtil; import io.swagger.annotations.*; import org.apache.commons.lang3.StringUtils; @@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.List; ; @@ -54,6 +57,16 @@ public class ActivitiModelController extends DefaultBaseController { return new SuccessResult(); } + @ApiOperation(value = "通过部署ID获取节点列表", notes = "通过部署ID获取节点列表接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "deploymentId", value = "部署ID", paramType = "path"), + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @GetMapping("list-flow-node/deployment-id/{deploymentId}") + public List listFlowNodeByDefineId(@PathVariable("deploymentId") String deploymentId) { + return activitiModelService.listFlowNodeByDeploymentId(deploymentId); + } + @ApiOperation(value = "模型json数据", notes = "模型json数据接口") @ApiImplicitParams({ @ApiImplicitParam(name = "modelId", value = "模型ID", paramType = "path") @@ -71,4 +84,15 @@ public class ActivitiModelController extends DefaultBaseController { return activitiModelService.getStencilset(); } + @ApiOperation(value = "流程XML数据", notes = "流程XML数据接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "processDefinitionId", value = "流程定义ID", paramType = "path") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @GetMapping("get-process-xml/{processDefinitionId}") + public SuccessResultData getProcessXml(@PathVariable("processDefinitionId") String processDefinitionId) { + String processXml = activitiModelService.getProcessXml(processDefinitionId); + return new SuccessResultData<>(processXml); + } + } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiProcdefController.java b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiProcdefController.java index c67b0605..e2627c21 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiProcdefController.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiProcdefController.java @@ -2,7 +2,6 @@ package ink.wgink.module.activiti.controller.api; import ink.wgink.common.base.DefaultBaseController; import ink.wgink.interfaces.consts.ISystemConstant; -import ink.wgink.module.activiti.pojo.dtos.ActivitiFlowNodeDTO; import ink.wgink.module.activiti.pojo.dtos.ActivitiProcdefDTO; import ink.wgink.module.activiti.service.activiti.IActivitiProcdefService; import ink.wgink.pojo.ListPage; @@ -52,14 +51,4 @@ public class ActivitiProcdefController extends DefaultBaseController { return activitiProcdefService.listPage(page.getPage(), page.getRows()); } - @ApiOperation(value = "通过部署ID获取任务列表", notes = "通过部署ID获取任务列表接口") - @ApiImplicitParams({ - @ApiImplicitParam(name = "deploymentId", value = "部署ID", paramType = "path"), - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @GetMapping("list-flow-node/deployment-id/{deploymentId}") - public List listFlowNodeByDefineId(@PathVariable("deploymentId") String deploymentId) { - return activitiProcdefService.listFlowNodeByDeploymentId(deploymentId); - } - } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiUserTaskController.java b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiUserTaskController.java new file mode 100644 index 00000000..1f6285b3 --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/api/ActivitiUserTaskController.java @@ -0,0 +1,40 @@ +package ink.wgink.module.activiti.controller.api; + +import ink.wgink.common.base.DefaultBaseController; +import ink.wgink.interfaces.consts.ISystemConstant; +import ink.wgink.module.activiti.service.activiti.IActivitiUserTaskService; +import ink.wgink.pojo.result.SuccessResult; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: ActivitiUserTaskController + * @Description: 流程用户任务 + * @Author: WangGeng + * @Date: 2021/7/12 21:56 + * @Version: 1.0 + **/ +@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "流程用户任务接口") +@RestController +@RequestMapping(ISystemConstant.API_PREFIX + "/activiti/user-task") +public class ActivitiUserTaskController extends DefaultBaseController { + + @Autowired + private IActivitiUserTaskService activitiUserTaskService; + + @GetMapping("get-next-user-task/{userTaskId}") + public SuccessResult getNextUserTask(@PathVariable("userTaskId") String userTaskId) { + activitiUserTaskService.getNextUserTask(userTaskId); + return new SuccessResult(); + } + +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/route/ActivitiModelRouteController.java b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/route/ActivitiModelRouteController.java new file mode 100644 index 00000000..a1e7be93 --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/route/ActivitiModelRouteController.java @@ -0,0 +1,57 @@ +package ink.wgink.module.activiti.controller.route; + +import ink.wgink.interfaces.consts.ISystemConstant; +import ink.wgink.module.activiti.service.activiti.IActivitiModelService; +import ink.wgink.pojo.result.ErrorResult; +import io.swagger.annotations.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletResponse; + +/** + * @ClassName: ActivitiModelRouteController + * @Description: 流程模型 + * @Author: wanggeng + * @Date: 2022/3/28 15:57 + * @Version: 1.0 + */ +@Api(tags = ISystemConstant.ROUTE_TAGS_PREFIX + "activiti模型") +@Controller +@RequestMapping(ISystemConstant.ROUTE_PREFIX + "/activiti/model") +public class ActivitiModelRouteController { + + @Autowired + private IActivitiModelService activitiModelService; + + @GetMapping("get-process-xml") + public ModelAndView getProcessImage() { + ModelAndView mv = new ModelAndView("activiti/model/get-process-xml"); + return mv; + } + + @ApiOperation(value = "查看流程图", notes = "查看流程图接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "deploymentId", value = "流程部署ID", paramType = "path") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @GetMapping("get-process-image/{deploymentId}") + public void getProcessImage(HttpServletResponse response, @PathVariable("deploymentId") String deploymentId) { + activitiModelService.getProcessImage(response, deploymentId); + } + + @ApiOperation(value = "查看运行流程图", notes = "查看运行流程图接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "processInstanceId", value = "流程实例ID", paramType = "path") + }) + @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) + @GetMapping("get-runtime-process-image/{processInstanceId}") + public void getRuntimeProcessImage(HttpServletResponse response, @PathVariable("processInstanceId") String processInstanceId) { + activitiModelService.getRuntimeProcessImage(response, processInstanceId); + } + +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/route/ActivitiRouteController.java b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/route/ActivitiRouteController.java index 5f9fdbb4..64090975 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/controller/route/ActivitiRouteController.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/controller/route/ActivitiRouteController.java @@ -2,17 +2,13 @@ package ink.wgink.module.activiti.controller.route; import ink.wgink.interfaces.consts.ISystemConstant; import ink.wgink.module.activiti.service.activiti.IActivitiModelService; -import ink.wgink.pojo.result.ErrorResult; -import io.swagger.annotations.*; +import io.swagger.annotations.Api; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; -import javax.servlet.http.HttpServletResponse; - /** * @ClassName: ActivitiRouteController * @Description: activiti路由 @@ -25,10 +21,6 @@ import javax.servlet.http.HttpServletResponse; @RequestMapping(ISystemConstant.ROUTE_PREFIX + "/activiti") public class ActivitiRouteController { - @Autowired - private IActivitiModelService activitiModelService; - - @GetMapping("list") public ModelAndView list() { ModelAndView mv = new ModelAndView("activiti/list"); @@ -47,24 +39,4 @@ public class ActivitiRouteController { return mv; } - @ApiOperation(value = "查看流程图", notes = "查看流程图接口") - @ApiImplicitParams({ - @ApiImplicitParam(name = "deploymentId", value = "流程部署ID", paramType = "path") - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @GetMapping("get-process-image/{deploymentId}") - public void getProcessImage(HttpServletResponse response, @PathVariable("deploymentId") String deploymentId) { - activitiModelService.getProcessImage(response, deploymentId); - } - - @ApiOperation(value = "查看运行流程图", notes = "查看运行流程图接口") - @ApiImplicitParams({ - @ApiImplicitParam(name = "processInstanceId", value = "流程实例ID", paramType = "path") - }) - @ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)}) - @GetMapping("get-runtime-process-image/{processInstanceId}") - public void getRuntimeProcessImage(HttpServletResponse response, @PathVariable("processInstanceId") String processInstanceId) { - activitiModelService.getRuntimeProcessImage(response, processInstanceId); - } - } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskAssignmentListener.java b/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskAssignmentListener.java new file mode 100644 index 00000000..16f43130 --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskAssignmentListener.java @@ -0,0 +1,32 @@ +package ink.wgink.module.activiti.listener.task; + +import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.delegate.DelegateTask; +import org.activiti.engine.delegate.JavaDelegate; +import org.activiti.engine.delegate.TaskListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * @ClassName: OaUserTaskAssignmentListener + * @Description: OA用户任务节点分配处理人监听器 + * @Author: wanggeng + * @Date: 2022/3/28 10:31 + * @Version: 1.0 + */ +@Component +public class OaUserTaskAssignmentListener implements TaskListener, JavaDelegate { + + private static final Logger LOG = LoggerFactory.getLogger(OaUserTaskAssignmentListener.class); + + @Override + public void notify(DelegateTask delegateTask) { + LOG.debug("userTask assignment"); + } + + @Override + public void execute(DelegateExecution execution) { + + } +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskCompleteListener.java b/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskCompleteListener.java new file mode 100644 index 00000000..447fbaf1 --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskCompleteListener.java @@ -0,0 +1,56 @@ +package ink.wgink.module.activiti.listener.task; + +import ink.wgink.module.activiti.service.activiti.IActivitiModelService; +import ink.wgink.module.activiti.service.oa.IOaFormReportService; +import org.activiti.bpmn.model.UserTask; +import org.activiti.engine.RuntimeService; +import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.delegate.DelegateTask; +import org.activiti.engine.delegate.JavaDelegate; +import org.activiti.engine.delegate.TaskListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @ClassName: OaUserTaskCompleteListener + * @Description: OA用户任务节点完成监听器 + * @Author: wanggeng + * @Date: 2022/3/28 10:31 + * @Version: 1.0 + */ +@Component +public class OaUserTaskCompleteListener implements TaskListener, JavaDelegate { + + private static final Logger LOG = LoggerFactory.getLogger(OaUserTaskCompleteListener.class); + + @Autowired + private RuntimeService runtimeService; + @Autowired + private IActivitiModelService activitiModelService; + @Autowired + private IOaFormReportService oaFormReportService; + + @Override + public void notify(DelegateTask delegateTask) { + LOG.debug(">>>> userTask complete"); + Map variables = runtimeService.getVariables(delegateTask.getProcessInstanceId()); + String reportUid = variables.get(IOaFormReportService.KEY_REPORT_UID).toString(); + String formCode = variables.get(IOaFormReportService.KEY_FORM_CODE).toString(); + Integer formVersion = Integer.parseInt(variables.get(IOaFormReportService.KEY_FORM_VERSION).toString()); + LOG.debug("查询表单数据:formCode: {}, formVersion: {}, reportUid: {}", formCode, formVersion, reportUid); + Map reportForm = oaFormReportService.get(formCode, formVersion, reportUid); + UserTask nextUserTask = activitiModelService.getNextUserTaskByTaskDefinitionKeyAndProcessDefinitionIdAndReportForm(delegateTask.getTaskDefinitionKey(), delegateTask.getProcessDefinitionId(), reportForm); + if (nextUserTask != null) { + nextUserTask.setAssignee("1"); + } + } + + @Override + public void execute(DelegateExecution execution) { + + } +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskCreateListener.java b/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskCreateListener.java new file mode 100644 index 00000000..ca2b3964 --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskCreateListener.java @@ -0,0 +1,31 @@ +package ink.wgink.module.activiti.listener.task; + +import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.delegate.DelegateTask; +import org.activiti.engine.delegate.JavaDelegate; +import org.activiti.engine.delegate.TaskListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * @ClassName: OaUserTaskCreateListener + * @Description: OA用户任务节点创建监听器 + * @Author: wanggeng + * @Date: 2022/3/28 10:31 + * @Version: 1.0 + */ +@Component +public class OaUserTaskCreateListener implements TaskListener, JavaDelegate { + + private static final Logger LOG = LoggerFactory.getLogger(OaUserTaskCreateListener.class); + + @Override + public void notify(DelegateTask delegateTask) { + LOG.debug("userTask create"); + } + + @Override + public void execute(DelegateExecution execution) { + } +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskDeleteListener.java b/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskDeleteListener.java new file mode 100644 index 00000000..848bbe7b --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/listener/task/OaUserTaskDeleteListener.java @@ -0,0 +1,32 @@ +package ink.wgink.module.activiti.listener.task; + +import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.delegate.DelegateTask; +import org.activiti.engine.delegate.JavaDelegate; +import org.activiti.engine.delegate.TaskListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * @ClassName: OaUserTaskDeleteListener + * @Description: OA用户任务节点删除监听器 + * @Author: wanggeng + * @Date: 2022/3/28 10:31 + * @Version: 1.0 + */ +@Component +public class OaUserTaskDeleteListener implements TaskListener, JavaDelegate { + + private static final Logger LOG = LoggerFactory.getLogger(OaUserTaskDeleteListener.class); + + @Override + public void notify(DelegateTask delegateTask) { + LOG.debug("userTask delete"); + } + + @Override + public void execute(DelegateExecution execution) { + + } +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/dtos/oa/OaTaskDTO.java b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/dtos/oa/OaTaskDTO.java index 8287b44c..64a80700 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/dtos/oa/OaTaskDTO.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/pojo/dtos/oa/OaTaskDTO.java @@ -1,6 +1,7 @@ package ink.wgink.module.activiti.pojo.dtos.oa; import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; /** * @ClassName: OaTaskDTO @@ -12,14 +13,28 @@ import io.swagger.annotations.ApiModel; @ApiModel public class OaTaskDTO { + @ApiModelProperty(name = "taskId", value = "任务ID") private String taskId; + @ApiModelProperty(name = "taskName", value = "任务名称") private String taskName; + @ApiModelProperty(name = "taskDescription", value = "任务描述") private String taskDescription; + @ApiModelProperty(name = "formCode", value = "表单编码") private String formCode; + @ApiModelProperty(name = "formVersion", value = "表单版本") private Integer formVersion; + @ApiModelProperty(name = "getFormKey", value = "动态表单ID") private String getFormKey; + @ApiModelProperty(name = "reportUid", value = "上报表单UID") private String reportUid; + @ApiModelProperty(name = "reportTitle", value = "上报表单标题") + private String reportTitle; + @ApiModelProperty(name = "owner", value = "所有者") private String owner; + @ApiModelProperty(name = "taskDefinitionKey", value = "任务定义Key") + private String taskDefinitionKey; + @ApiModelProperty(name = "processDefinitionId", value = "流程定义ID") + private String processDefinitionId; public String getTaskId() { return taskId == null ? "" : taskId.trim(); @@ -77,6 +92,14 @@ public class OaTaskDTO { this.reportUid = reportUid; } + public String getReportTitle() { + return reportTitle == null ? "" : reportTitle.trim(); + } + + public void setReportTitle(String reportTitle) { + this.reportTitle = reportTitle; + } + public String getOwner() { return owner == null ? "" : owner.trim(); } @@ -84,4 +107,20 @@ public class OaTaskDTO { public void setOwner(String owner) { this.owner = owner; } + + public String getTaskDefinitionKey() { + return taskDefinitionKey == null ? "" : taskDefinitionKey.trim(); + } + + public void setTaskDefinitionKey(String taskDefinitionKey) { + this.taskDefinitionKey = taskDefinitionKey; + } + + public String getProcessDefinitionId() { + return processDefinitionId == null ? "" : processDefinitionId.trim(); + } + + public void setProcessDefinitionId(String processDefinitionId) { + this.processDefinitionId = processDefinitionId; + } } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiModelService.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiModelService.java index 8a3b75e7..93fb9b1b 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiModelService.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiModelService.java @@ -1,10 +1,14 @@ package ink.wgink.module.activiti.service.activiti; import com.alibaba.fastjson.JSONObject; +import ink.wgink.module.activiti.pojo.dtos.ActivitiFlowNodeDTO; +import org.activiti.bpmn.model.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.List; +import java.util.Map; /** * When you feel like quitting. Think about why you started @@ -18,10 +22,111 @@ import java.io.UnsupportedEncodingException; **/ public interface IActivitiModelService { + /** + * 排他网关条件关键字 + */ + String EXCLUSIVE_GATEWAY_CONDITION_KEY = "exc"; + + /** + * 并行网关条件关键字 + */ + String PARALLEL_GATEWAY_CONDITION_KEY = "par"; + + /** + * 保存模型 + * + * @param modelId + * @param name + * @param description + * @param json_xml + * @param svg_xml + * @throws Exception + */ void saveModel(String modelId, String name, String description, String json_xml, String svg_xml) throws Exception; + /** + * 获取原生流程节点列表 + * + * @param bpmnModel + * @return + */ + List listFlowNode(BpmnModel bpmnModel); + + /** + * 获取当前流程节点 + * + * @param currentTaskDefinitionKey + * @param processDefinitionId + * @return + */ + FlowNode getCurrentFlowNode(String currentTaskDefinitionKey, String processDefinitionId); + + /** + * 获取下一个用户任务 + * + * @param currentUserTask 当前用户任务 + * @return + */ + UserTask getNextUserTaskByCurrentUserTask(UserTask currentUserTask); + + /** + * 获取下一个用户任务 + * + * @param exclusiveGateway 排他网关 + * @param reportForm 上报表单 + * @return + */ + UserTask getNextUserTaskByExclusiveGatewayAndReportForm(ExclusiveGateway exclusiveGateway, Map reportForm); + + /** + * 获取下一个用户任务 + * + * @param currentTaskDefinitionKey 当前任务定义Key + * @param processDefinitionId 流程定义ID + * @param reportForm 上报表单 + * @return + */ + UserTask getNextUserTaskByTaskDefinitionKeyAndProcessDefinitionIdAndReportForm(String currentTaskDefinitionKey, String processDefinitionId, Map reportForm); + + /** + * 获得开始节点 + * + * @param flowNodes + * @return + */ + StartEvent getStartEvent(List flowNodes); + + /** + * 获取自定义的流程节点列表 + * + * @param flowNodes + * @return + */ + List listActivitiFlowNodeByModel(List flowNodes); + + /** + * 获取流程节点列表 + * + * @param deploymentId 部署ID + * @return + */ + List listFlowNodeByDeploymentId(String deploymentId); + + /** + * 获取编辑的json数据 + * + * @param modelId + * @return + * @throws UnsupportedEncodingException + */ JSONObject getEditorJson(String modelId) throws UnsupportedEncodingException; + /** + * 获取模板套件 + * + * @return + * @throws IOException + */ JSONObject getStencilset() throws IOException; /** @@ -39,4 +144,12 @@ public interface IActivitiModelService { * @param processInstanceId */ void getRuntimeProcessImage(HttpServletResponse response, String processInstanceId); + + /** + * 获取流程xml + * + * @param processDefinitionId 流程定义ID + */ + String getProcessXml(String processDefinitionId); + } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiProcdefService.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiProcdefService.java index cbfeffe7..0d590cf4 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiProcdefService.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiProcdefService.java @@ -1,9 +1,7 @@ package ink.wgink.module.activiti.service.activiti; -import ink.wgink.module.activiti.pojo.dtos.ActivitiFlowNodeDTO; import ink.wgink.module.activiti.pojo.dtos.ActivitiProcdefDTO; import ink.wgink.pojo.result.SuccessResultList; -import org.activiti.bpmn.model.BpmnModel; import java.util.List; @@ -20,7 +18,4 @@ public interface IActivitiProcdefService { SuccessResultList> listPage(int page, int rows); - List listFlowNodeByDeploymentId(String deploymentId); - - List listFlowNodeByModel(BpmnModel bpmnModel); } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiUserTaskService.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiUserTaskService.java new file mode 100644 index 00000000..1629571f --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/IActivitiUserTaskService.java @@ -0,0 +1,14 @@ +package ink.wgink.module.activiti.service.activiti; + +/** + * @ClassName: IActivitiUserTaskService + * @Description: 流程用户任务 + * @Author: wanggeng + * @Date: 2022/3/29 17:43 + * @Version: 1.0 + */ +public interface IActivitiUserTaskService { + + void getNextUserTask(String userTaskId); + +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiModelServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiModelServiceImpl.java index e2081ded..2df2a03a 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiModelServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiModelServiceImpl.java @@ -6,11 +6,11 @@ import ink.wgink.common.base.DefaultBaseService; import ink.wgink.exceptions.SearchException; import ink.wgink.exceptions.base.SystemException; import ink.wgink.interfaces.consts.ISystemConstant; +import ink.wgink.module.activiti.pojo.dtos.ActivitiFlowNodeDTO; import ink.wgink.module.activiti.service.activiti.IActivitiModelService; import ink.wgink.util.ResourceUtil; -import org.activiti.bpmn.model.BpmnModel; -import org.activiti.bpmn.model.FlowNode; -import org.activiti.bpmn.model.SequenceFlow; +import ink.wgink.util.xml.XMLUtil; +import org.activiti.bpmn.model.*; import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; @@ -29,10 +29,7 @@ import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletResponse; import java.io.*; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; /** @@ -87,6 +84,115 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct } + @Override + public List listFlowNode(BpmnModel bpmnModel) { + return bpmnModel.getMainProcess().findFlowElementsOfType(FlowNode.class); + } + + @Override + public FlowNode getCurrentFlowNode(String currentTaskDefinitionKey, String processDefinitionId) { + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); + return (FlowNode) bpmnModel.getFlowElement(currentTaskDefinitionKey); + } + + @Override + public UserTask getNextUserTaskByCurrentUserTask(UserTask currentUserTask) { + List outgoingFlows = currentUserTask.getOutgoingFlows(); + if (outgoingFlows.size() > 1 || outgoingFlows.size() == 0) { + throw new SystemException("流程错误,下个用户任务节点数只能有1个"); + } + FlowElement targetFlowElement = outgoingFlows.get(0).getTargetFlowElement(); + if (!(targetFlowElement instanceof UserTask)) { + throw new SystemException("下个节点不是用户任务"); + } + return (UserTask) targetFlowElement; + } + + @Override + public UserTask getNextUserTaskByExclusiveGatewayAndReportForm(ExclusiveGateway exclusiveGateway, Map reportForm) { + List outgoingFlows = exclusiveGateway.getOutgoingFlows(); + for (SequenceFlow sequenceFlow : outgoingFlows) { + FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement(); + if (targetFlowElement instanceof UserTask) { + if (isExclusiveConditionPass(sequenceFlow.getConditionExpression(), reportForm)) { + return (UserTask) targetFlowElement; + } + } else if (targetFlowElement instanceof ExclusiveGateway) { + return getNextUserTaskByExclusiveGatewayAndReportForm(exclusiveGateway, reportForm); + } + } + throw new SystemException("未找到下一节点用户任务"); + } + + @Override + public UserTask getNextUserTaskByTaskDefinitionKeyAndProcessDefinitionIdAndReportForm(String currentTaskDefinitionKey, String processDefinitionId, Map reportForm) { + FlowNode currentFlowNode = getCurrentFlowNode(currentTaskDefinitionKey, processDefinitionId); + List outgoingFlows = currentFlowNode.getOutgoingFlows(); + for (SequenceFlow sequenceFlow : outgoingFlows) { + FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement(); + if (targetFlowElement instanceof UserTask) { + return (UserTask) targetFlowElement; + } else if (targetFlowElement instanceof ExclusiveGateway) { + LOG.debug("排他网关节点,继续查找"); + ExclusiveGateway exclusiveGateway = (ExclusiveGateway) targetFlowElement; + return getNextUserTaskByExclusiveGatewayAndReportForm(exclusiveGateway, reportForm); + } else if (targetFlowElement instanceof EndEvent) { + return null; + } + } + throw new SystemException("未找到下一节点用户任务"); + } + + @Override + public StartEvent getStartEvent(List flowNodes) { + if (flowNodes == null || flowNodes.isEmpty()) { + return null; + } + for (FlowNode flowNode : flowNodes) { + if (flowNode instanceof StartEvent) { + return (StartEvent) flowNode; + } + } + return null; + } + + @Override + public List listActivitiFlowNodeByModel(List flowNodes) { + List activitiFlowNodeDTOs = new ArrayList<>(); + for (FlowNode flowNode : flowNodes) { + ActivitiFlowNodeDTO activitiFlowNodeDTO = new ActivitiFlowNodeDTO(); + activitiFlowNodeDTO.setId(flowNode.getId()); + activitiFlowNodeDTO.setName(flowNode.getName()); + activitiFlowNodeDTO.setSummary(flowNode.getDocumentation()); + if (flowNode instanceof StartEvent) { + StartEvent startEvent = (StartEvent) flowNode; + activitiFlowNodeDTO.setFormKey(startEvent.getFormKey()); + activitiFlowNodeDTO.setType(StartEvent.class.getSimpleName()); + } else if (flowNode instanceof EndEvent) { + activitiFlowNodeDTO.setType(EndEvent.class.getSimpleName()); + } else if (flowNode instanceof UserTask) { + UserTask userTask = (UserTask) flowNode; + activitiFlowNodeDTO.setFormKey(userTask.getFormKey()); + activitiFlowNodeDTO.setType(UserTask.class.getSimpleName()); + } else { + continue; + } + activitiFlowNodeDTOs.add(activitiFlowNodeDTO); + } + return activitiFlowNodeDTOs; + } + + @Override + public List listFlowNodeByDeploymentId(String deploymentId) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); + if (processDefinition == null) { + throw new SearchException("流程定义不存在,请检查流程部署情况"); + } + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); + List flowNodes = listFlowNode(bpmnModel); + return listActivitiFlowNodeByModel(flowNodes); + } + @Override public JSONObject getEditorJson(String modelId) throws UnsupportedEncodingException { Model model = repositoryService.getModel(modelId); @@ -166,6 +272,27 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct } } + @Override + public String getProcessXml(String processDefinitionId) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); + if (processDefinition == null) { + throw new SearchException("流程定义不存在"); + } + String result; + try (InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName()); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + ) { + StringBuilder xmlSB = new StringBuilder(); + for (String line; (line = bufferedReader.readLine()) != null; ) { + xmlSB.append(line); + } + result = XMLUtil.formatXmlString(xmlSB.toString()); + } catch (IOException e) { + throw new SystemException(e); + } + return result; + } + /** * 获取运行流程图输入流 * @@ -291,5 +418,48 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct return new ArrayList<>(flowSet); } + /** + * 排他条件判断通过 + * + * @param conditionExpression 条件表达式 + * @param reportFormMap 表单变量 + * @return + */ + private static boolean isExclusiveConditionPass(String conditionExpression, Map reportFormMap) { + if (StringUtils.isBlank(conditionExpression)) { + LOG.debug("排他网关条件表达式为空"); + return false; + } + if (reportFormMap.isEmpty()) { + LOG.debug("上报表单为空"); + return false; + } + //分割表达式 + String[] expressionArray = conditionExpression.split("[{}$&]"); + for (String expression : expressionArray) { + // 是否包含条件字段 + if (!expression.contains(IActivitiModelService.EXCLUSIVE_GATEWAY_CONDITION_KEY)) { + continue; + } + // 表单中是否包含条件字段 + if (!reportFormMap.containsKey(IActivitiModelService.EXCLUSIVE_GATEWAY_CONDITION_KEY)) { + continue; + } + if (expression.contains("==")) { + String[] primes = expression.split("=="); + String valExpr = primes[1].trim(); + if (valExpr.startsWith("'")) { + valExpr = valExpr.substring(1); + } + if (valExpr.endsWith("'")) { + valExpr = valExpr.substring(0, valExpr.length() - 1); + } + if (primes.length == 2 && valExpr.equals(reportFormMap.get(IActivitiModelService.EXCLUSIVE_GATEWAY_CONDITION_KEY))) { + return true; + } + } + } + return false; + } } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiProcdefServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiProcdefServiceImpl.java index d8d13c1e..25b1026a 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiProcdefServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiProcdefServiceImpl.java @@ -1,14 +1,10 @@ package ink.wgink.module.activiti.service.activiti.impl; import ink.wgink.common.base.DefaultBaseService; -import ink.wgink.exceptions.SearchException; -import ink.wgink.exceptions.base.SystemException; -import ink.wgink.module.activiti.pojo.dtos.ActivitiFlowNodeDTO; import ink.wgink.module.activiti.pojo.dtos.ActivitiProcdefDTO; +import ink.wgink.module.activiti.service.activiti.IActivitiModelService; import ink.wgink.module.activiti.service.activiti.IActivitiProcdefService; import ink.wgink.pojo.result.SuccessResultList; -import org.activiti.bpmn.model.Process; -import org.activiti.bpmn.model.*; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.repository.ProcessDefinition; @@ -34,6 +30,8 @@ public class ActivitiProcdefServiceImpl extends DefaultBaseService implements IA private RepositoryService repositoryService; @Autowired private RuntimeService runtimeService; + @Autowired + private IActivitiModelService activitiModelService; @Override public void delete(String deploymentId) { @@ -55,46 +53,4 @@ public class ActivitiProcdefServiceImpl extends DefaultBaseService implements IA return new SuccessResultList<>(activitiProcdefDTOs, page, processDefinitionQuery.count()); } - @Override - public List listFlowNodeByDeploymentId(String deploymentId) { - ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); - if (processDefinition == null) { - throw new SearchException("流程定义不存在,请检查流程部署情况"); - } - BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); - return listFlowNodeByModel(bpmnModel); - } - - @Override - public List listFlowNodeByModel(BpmnModel bpmnModel) { - List processes = bpmnModel.getProcesses(); - if (processes.size() > 1) { - throw new SystemException("流程不能有多条"); - } - List flowNodes = processes.get(0).findFlowElementsOfType(FlowNode.class); - List activitiFlowNodeDTOs = new ArrayList<>(); - for (FlowNode flowNode : flowNodes) { - ActivitiFlowNodeDTO activitiFlowNodeDTO = new ActivitiFlowNodeDTO(); - activitiFlowNodeDTO.setId(flowNode.getId()); - activitiFlowNodeDTO.setName(flowNode.getName()); - activitiFlowNodeDTO.setSummary(flowNode.getDocumentation()); - if (flowNode instanceof StartEvent) { - StartEvent startEvent = (StartEvent) flowNode; - activitiFlowNodeDTO.setFormKey(startEvent.getFormKey()); - activitiFlowNodeDTO.setType(StartEvent.class.getSimpleName()); - } else if (flowNode instanceof EndEvent) { - activitiFlowNodeDTO.setType(EndEvent.class.getSimpleName()); - } else if (flowNode instanceof UserTask) { - UserTask userTask = (UserTask) flowNode; - activitiFlowNodeDTO.setFormKey(userTask.getFormKey()); - activitiFlowNodeDTO.setType(UserTask.class.getSimpleName()); - } else { - continue; - } - activitiFlowNodeDTOs.add(activitiFlowNodeDTO); - } - return activitiFlowNodeDTOs; - } - - } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiServiceImpl.java index da2df468..09f3b5a7 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiServiceImpl.java @@ -12,6 +12,7 @@ import ink.wgink.module.activiti.pojo.dtos.ActivitiFlowNodeDTO; import ink.wgink.module.activiti.pojo.vos.ActivitiVO; import ink.wgink.module.activiti.pojo.vos.oa.NodeFieldUpdateVO; import ink.wgink.module.activiti.pojo.vos.oa.NodeFieldVO; +import ink.wgink.module.activiti.service.activiti.IActivitiModelService; import ink.wgink.module.activiti.service.activiti.IActivitiProcdefService; import ink.wgink.module.activiti.service.activiti.IActivitiService; import ink.wgink.module.activiti.service.oa.INodeFieldService; @@ -20,9 +21,7 @@ import ink.wgink.module.form.pojo.pos.design.FormPO; import ink.wgink.module.form.service.design.IFormFieldService; import ink.wgink.module.form.service.design.IFormService; import ink.wgink.pojo.result.SuccessResultList; -import org.activiti.bpmn.model.BpmnModel; -import org.activiti.bpmn.model.EndEvent; -import org.activiti.bpmn.model.StartEvent; +import org.activiti.bpmn.model.*; import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.editor.language.json.converter.BpmnJsonConverter; import org.activiti.engine.HistoryService; @@ -60,6 +59,8 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti @Autowired private RuntimeService runtimeService; @Autowired + private IActivitiModelService activitiModelService; + @Autowired private IActivitiProcdefService activitiProcdefService; @Autowired private INodeFieldService nodeFieldService; @@ -110,15 +111,46 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti LOG.debug("部署流程"); JsonNode modelNode = new ObjectMapper().readTree(modelEditorSource); BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(modelNode); + + + LOG.debug("获取流程节点列表"); + List flowNodes = activitiModelService.listFlowNode(bpmnModel); + LOG.debug("获得开始节点"); + StartEvent startEvent = activitiModelService.getStartEvent(flowNodes); + // 判断是否存在表单,如果存在表单,说明是OA流程,进行初始化再部署,如果不是OA流程则正常部署 + String formKey = startEvent.getFormKey(); + String deploymentId; + if (!StringUtils.isBlank(formKey)) { + LOG.debug("存在自定义表单,是OA流程,执行初始化操作"); + LOG.debug("1.初始化"); + LOG.debug("2.部署流程"); + deploymentId = deployProcess(model, bpmnModel); + LOG.debug("3.绑定节点设置"); + LOG.debug("4.绑定流程节点与表单关系"); + saveNodeField(deploymentId, flowNodes); + } else { + LOG.debug("不存在自定义表单,不是OA流程,直接部署"); + deploymentId = deployProcess(model, bpmnModel); + } + model.setDeploymentId(deploymentId); + LOG.debug("保存模型"); + repositoryService.saveModel(model); + } + + /** + * 部署流程 + * + * @param model + * @param bpmnModel + * @return + */ + private String deployProcess(Model model, BpmnModel bpmnModel) { Deployment deployment = repositoryService.createDeployment() .name(model.getName()) .key(model.getKey()) .addBpmnModel(model.getKey() + "." + model.getVersion() + ".bpmn20.xml", bpmnModel) .deploy(); - model.setDeploymentId(deployment.getId()); - repositoryService.saveModel(model); - LOG.debug("节点关联表单"); - saveNodeField(deployment.getId(), bpmnModel); + return deployment.getId(); } /** @@ -126,8 +158,8 @@ public class ActivitiServiceImpl extends DefaultBaseService implements IActiviti * * @param deploymentId */ - private void saveNodeField(String deploymentId, BpmnModel bpmnModel) { - List activitiFlowNodeDTOs = activitiProcdefService.listFlowNodeByModel(bpmnModel); + private void saveNodeField(String deploymentId, List flowNodes) { + List activitiFlowNodeDTOs = activitiModelService.listActivitiFlowNodeByModel(flowNodes); if (activitiFlowNodeDTOs.isEmpty()) { return; } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiUserTaskServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiUserTaskServiceImpl.java new file mode 100644 index 00000000..fe62303c --- /dev/null +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/activiti/impl/ActivitiUserTaskServiceImpl.java @@ -0,0 +1,115 @@ +package ink.wgink.module.activiti.service.activiti.impl; + +import ink.wgink.common.base.DefaultBaseService; +import ink.wgink.module.activiti.service.activiti.IActivitiUserTaskService; +import org.activiti.bpmn.model.*; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.RuntimeService; +import org.activiti.engine.TaskService; +import org.activiti.engine.task.Task; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @ClassName: ActivitiUserTaskServiceImpl + * @Description: 流程用户任务 + * @Author: wanggeng + * @Date: 2022/3/29 17:44 + * @Version: 1.0 + */ +@Service +public class ActivitiUserTaskServiceImpl extends DefaultBaseService implements IActivitiUserTaskService { + + @Autowired + private TaskService taskService; + @Autowired + private RuntimeService runtimeService; + @Autowired + private RepositoryService repositoryService; + + @Override + public void getNextUserTask(String userTaskId) { + Task task = taskService.createTaskQuery().taskId(userTaskId).singleResult(); + String taskDefinitionKey = task.getTaskDefinitionKey(); + String processInstanceId = task.getProcessInstanceId(); + String processDefinitionId = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult().getProcessDefinitionId(); + + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); + + FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(taskDefinitionKey); + + // 流入线 + List incomingFlows = flowNode.getIncomingFlows(); + + // 流出线 + List outgoingFlows = flowNode.getOutgoingFlows(); + HashMap vars = new HashMap<>(); + vars.put("message", ""); + for (SequenceFlow outgoingFlow : outgoingFlows) { + //获取输出节点元素 + FlowElement targetFlowElement = outgoingFlow.getTargetFlowElement(); + //排除非用户任务接点 + if (targetFlowElement instanceof UserTask) { + LOG.debug("UserTask"); + UserTask userTask = (UserTask) targetFlowElement; + System.out.println(userTask); + //判断输出节点的el表达式 +// if (isCondition(outgoingFlow.getConditionExpression(), vars)) { +// //true 获取输出节点名称 +// // nameList.add(outgoingFlow.getTargetFlowElement().getName()); +// } + } else if (targetFlowElement instanceof ExclusiveGateway) { + LOG.debug("排他网关"); + + } else if (targetFlowElement instanceof ParallelGateway) { + LOG.debug("并行网关"); + + } + } + + System.out.println(flowNode); + } + + /** + * el表达式判断 + * + * @param expression + * @param vars + * @return + */ + private static boolean isCondition(String expression, Map vars) { + if (expression == null || expression == "") { + return false; + } + + //分割表达式 + String[] exprArr = expression.split("[{}$&]"); + for (String expr : exprArr) { + //是否包含键message + if (expr.contains("message")) { + if (!vars.containsKey("message")) { + continue; + } + if (expr.contains("==")) { + String[] primes = expr.split("=="); + String valExpr = primes[1].trim(); + if (valExpr.startsWith("'")) { + valExpr = valExpr.substring(1); + } + if (valExpr.endsWith("'")) { + valExpr = valExpr.substring(0, valExpr.length() - 1); + } + if (primes.length == 2 && valExpr.equals(vars.get("message"))) { + return true; + } + } + } + } + return false; + } + +} diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/IOaFormReportService.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/IOaFormReportService.java index b8ee407d..47a49560 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/IOaFormReportService.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/IOaFormReportService.java @@ -27,6 +27,7 @@ public interface IOaFormReportService { /** * 更新表单 + * * @param taskId * @param formCode * @param formVersion @@ -35,4 +36,13 @@ public interface IOaFormReportService { */ void update(String taskId, String formCode, Integer formVersion, String uid, Map params); + /** + * 表单详情 + * + * @param formCode + * @param formVersion + * @param uid + */ + Map get(String formCode, Integer formVersion, String uid); + } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportServiceImpl.java index 4417fc60..f0f5765f 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaFormReportServiceImpl.java @@ -47,4 +47,9 @@ public class OaFormReportServiceImpl extends DefaultBaseService implements IOaFo taskService.complete(taskId, params); } + @Override + public Map get(String formCode, Integer formVersion, String uid) { + return formReportService.get(formCode, formVersion, uid); + } + } diff --git a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaServiceImpl.java b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaServiceImpl.java index c1fe63b6..487ec1f7 100644 --- a/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaServiceImpl.java +++ b/module-activiti/src/main/java/ink/wgink/module/activiti/service/oa/impl/OaServiceImpl.java @@ -134,6 +134,8 @@ public class OaServiceImpl extends DefaultBaseService implements IOaService { oaTaskDTO.setTaskName(task.getName()); oaTaskDTO.setTaskDescription(task.getDescription()); oaTaskDTO.setOwner(task.getOwner()); + oaTaskDTO.setTaskDefinitionKey(task.getTaskDefinitionKey()); + oaTaskDTO.setProcessDefinitionId(task.getProcessDefinitionId()); Map variables = runtimeService.getVariables(task.getProcessInstanceId()); if (variables.isEmpty()) { diff --git a/module-activiti/src/main/resources/static/editor-app/configuration/properties-task-listeners-controller.js b/module-activiti/src/main/resources/static/editor-app/configuration/properties-task-listeners-controller.js index 33f2dfb3..af1003c3 100644 --- a/module-activiti/src/main/resources/static/editor-app/configuration/properties-task-listeners-controller.js +++ b/module-activiti/src/main/resources/static/editor-app/configuration/properties-task-listeners-controller.js @@ -33,7 +33,7 @@ var KisBpmTaskListenersCtrl = [ '$scope', '$modal', '$timeout', '$translate', fu $modal(opts); }]; -var KisBpmTaskListenersPopupCtrl = [ '$scope', '$q', '$translate', function($scope, $q, $translate) { +var KisBpmTaskListenersPopupCtrl = [ '$scope', '$timeout', '$q', '$translate', function($scope, $timeout, $q, $translate) { // Put json representing form properties on scope if ($scope.property.value !== undefined && $scope.property.value !== null @@ -158,15 +158,89 @@ var KisBpmTaskListenersPopupCtrl = [ '$scope', '$q', '$translate', function($sco } }; + function addListener(event, className, expression, delegateExpression) { + var implementation = ''; + if(className) { + implementation = className; + } else if(expression) { + implementation = expression; + } else if(delegateExpression) { + implementation = delegateExpression; + } + $scope.taskListeners.push({ + event : event, + implementation : implementation, + className : className ? className : '', + expression: expression ? expression : '', + delegateExpression: delegateExpression ? delegateExpression : '' + }); + } + // Click handler for add button $scope.addNewListener = function() { - $scope.taskListeners.push({ event : 'create', - implementation : '', - className : '', - expression: '', - delegateExpression: ''}); + addListener('create'); }; + /** + * 判断监听器是否存在 + * @param event + * @param className + */ + function isListenerExist(event, className) { + for(var i = 0, item; item = $scope.taskListeners[i++]; ) { + if(item.event == event && item.className == className) { + return true; + } + } + return false; + } + + // quick add listener + $scope.addOaUserTaskCreateListener = function() { + var event = 'create', + className = '', + expression = '', + delegateExpression = '${oaUserTaskCreateListener}'; + if(isListenerExist(event, className)) { + top.dialog.msg('监听器已经存在'); + return; + } + addListener(event, className, expression, delegateExpression); + } + $scope.addOaUserTaskCompleteListener = function() { + var event = 'complete', + className = '', + expression = '', + delegateExpression = '${oaUserTaskCompleteListener}'; + if(isListenerExist(event, className)) { + top.dialog.msg('监听器已经存在'); + return; + } + addListener(event, className, expression, delegateExpression); + } + $scope.addOaUserTaskAssignmentListener = function() { + var event = 'assignment', + className = '', + expression = '', + delegateExpression = '${oaUserTaskAssignmentListener}'; + if(isListenerExist(event, className)) { + top.dialog.msg('监听器已经存在'); + return; + } + addListener(event, className, expression, delegateExpression); + } + $scope.addOaUserTaskDeleteListener = function() { + var event = 'delete', + className = '', + expression = '', + delegateExpression = '${oaUserTaskDeleteListener}'; + if(isListenerExist(event, className)) { + top.dialog.msg('监听器已经存在'); + return; + } + addListener(event, className, expression, delegateExpression); + } + // Click handler for remove button $scope.removeListener = function() { if ($scope.selectedListeners.length > 0) { @@ -189,12 +263,12 @@ var KisBpmTaskListenersPopupCtrl = [ '$scope', '$q', '$translate', function($sco var index = $scope.taskListeners.indexOf($scope.selectedListeners[0]); if (index != 0) { // If it's the first, no moving up of course // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272 + var prevIndex = index - 1; var temp = $scope.taskListeners[index]; $scope.taskListeners.splice(index, 1); - $timeout(function(){ - $scope.taskListeners.splice(index + -1, 0, temp); + $timeout(function() { + $scope.taskListeners.splice(prevIndex, 0, temp); }, 100); - } } }; @@ -205,10 +279,11 @@ var KisBpmTaskListenersPopupCtrl = [ '$scope', '$q', '$translate', function($sco var index = $scope.taskListeners.indexOf($scope.selectedListeners[0]); if (index != $scope.taskListeners.length - 1) { // If it's the last element, no moving down of course // Reason for funny way of swapping, see https://github.com/angular-ui/ng-grid/issues/272 + var nextIndex = index + 1; var temp = $scope.taskListeners[index]; $scope.taskListeners.splice(index, 1); $timeout(function(){ - $scope.taskListeners.splice(index + 1, 0, temp); + $scope.taskListeners.splice(nextIndex, 0, temp); }, 100); } diff --git a/module-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup-bak.html b/module-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup-bak.html new file mode 100644 index 00000000..7d83e576 --- /dev/null +++ b/module-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup-bak.html @@ -0,0 +1,102 @@ + + diff --git a/module-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup.html b/module-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup.html index 7d83e576..15b82ef7 100644 --- a/module-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup.html +++ b/module-activiti/src/main/resources/static/editor-app/configuration/properties/task-listeners-popup.html @@ -11,18 +11,26 @@
-
-
- - -
-
- - -
-
+
+ 快速设置 +
+ + + + +
+
+
+
+ + +
+
+ + +
+
-
@@ -57,12 +65,12 @@
- - + +
- - + +
diff --git a/module-activiti/src/main/resources/templates/activiti/list.html b/module-activiti/src/main/resources/templates/activiti/list.html index 1b607c11..8acd321e 100644 --- a/module-activiti/src/main/resources/templates/activiti/list.html +++ b/module-activiti/src/main/resources/templates/activiti/list.html @@ -116,7 +116,7 @@ if(!row.deploymentId) { return '-'; } - var flowChatImg = '' + var flowChatImg = '' setTimeout(function() { new Viewer(document.getElementById('flowChat'+ row.id)); }, 50); diff --git a/module-activiti/src/main/resources/templates/activiti/model/get-process-xml.html b/module-activiti/src/main/resources/templates/activiti/model/get-process-xml.html new file mode 100644 index 00000000..ffe00d5c --- /dev/null +++ b/module-activiti/src/main/resources/templates/activiti/model/get-process-xml.html @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + +
+
+
+
+ +
+
+ +
+
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/module-activiti/src/main/resources/templates/activiti/procdef/list.html b/module-activiti/src/main/resources/templates/activiti/procdef/list.html index b94e9120..d0290d24 100644 --- a/module-activiti/src/main/resources/templates/activiti/procdef/list.html +++ b/module-activiti/src/main/resources/templates/activiti/procdef/list.html @@ -57,7 +57,7 @@ cols: [ [ {field:'rowNum', width:80, title: '序号', fixed: 'left', align:'center', templet: '{{d.LAY_INDEX}}'}, - {field:'id', width:150, title: '主键', align:'center', + {field:'id', width:220, title: '流程定义ID', align:'center', templet: function(row) { var rowData = row[this.field]; if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') { @@ -66,7 +66,7 @@ return rowData; } }, - {field:'key', width:150, title: '流程定义ID', align:'center', + {field:'key', width:150, title: '流程key', align:'center', templet: function(row) { var rowData = row[this.field]; if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') { @@ -84,7 +84,7 @@ return rowData; } }, - {field:'name', width:150, title: '名称', align:'center', + {field:'name', width:200, title: '名称', align:'center', templet: function(row) { var rowData = row[this.field]; if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') { @@ -93,7 +93,7 @@ return rowData; } }, - {field:'description', width:150, title: '描述', align:'center', + {field:'description', width:200, title: '描述', align:'center', templet: function(row) { var rowData = row[this.field]; if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') { @@ -111,13 +111,13 @@ return rowData; } }, - {field:'resourceName', width:200, title: '流程资源名称', align:'center', + {field:'resourceName', width:300, title: '流程资源名称', align:'center', templet: function(row) { var rowData = row[this.field]; if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') { return '-'; } - return rowData; + return ''+ rowData +''; } }, {field: 'diagramResourceName', width: 80, title: '流程图', align:'center', @@ -125,7 +125,7 @@ if(!row.deploymentId) { return '-'; } - var flowChatImg = '' + var flowChatImg = '' setTimeout(function() { new Viewer(document.getElementById('flowChat'+ row.id)); }, 50); @@ -181,7 +181,15 @@ table.on('tool(dataTable)', function(obj) { var data = obj.data; var layEvent = obj.event; - if(layEvent === 'nodeEvent') { + if(layEvent === 'showXml') { + top.dialog.open({ + url: top.restAjax.path('route/activiti/model/get-process-xml?processDefinitionId={processDefinitionId}', [data.id]), + title: '流程XML', + width: '80%', + height: '95%', + onClose: function() {} + }); + } else if(layEvent === 'nodeEvent') { top.dialog.open({ url: top.restAjax.path('route/oa/node-field/list-node?deploymentId={deploymentId}', [data.deploymentId]), title: '节点字段管理', diff --git a/module-activiti/src/main/resources/templates/oa/list-procdef.html b/module-activiti/src/main/resources/templates/oa/list-procdef.html index b5b2c014..f7ca707e 100644 --- a/module-activiti/src/main/resources/templates/oa/list-procdef.html +++ b/module-activiti/src/main/resources/templates/oa/list-procdef.html @@ -57,7 +57,7 @@ cols: [ [ {field:'rowNum', width:80, title: '序号', fixed: 'left', align:'center', templet: '{{d.LAY_INDEX}}'}, - {field:'id', width:150, title: '主键', align:'center', + {field:'id', width:300, title: '流程定义ID', align:'center', templet: function(row) { var rowData = row[this.field]; if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') { @@ -75,7 +75,7 @@ return rowData; } }, - {field:'name', width:150, title: '名称', align:'center', + {field:'name', width:200, title: '名称', align:'center', templet: function(row) { var rowData = row[this.field]; if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') { @@ -84,7 +84,7 @@ return rowData; } }, - {field:'description', width:150, title: '描述', align:'center', + {field:'description', width:200, title: '描述', align:'center', templet: function(row) { var rowData = row[this.field]; if(typeof(rowData) === 'undefined' || rowData == null || rowData == '') { @@ -98,7 +98,7 @@ if(!row.deploymentId) { return '-'; } - var flowChatImg = '' + var flowChatImg = '' setTimeout(function() { new Viewer(document.getElementById('flowChat'+ row.id)); }, 50);