From 23855599412c4d61b38d78f0f3abd3430a48b5b1 Mon Sep 17 00:00:00 2001 From: zhangherong <571457620@qq.com> Date: 星期三, 25 六月 2025 11:51:38 +0800 Subject: [PATCH] Merge branch 'mdc_hyjs_master' --- lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowDefinitionServiceImpl.java | 480 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 480 insertions(+), 0 deletions(-) diff --git a/lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowDefinitionServiceImpl.java b/lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowDefinitionServiceImpl.java new file mode 100644 index 0000000..379cfdd --- /dev/null +++ b/lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowDefinitionServiceImpl.java @@ -0,0 +1,480 @@ +package org.jeecg.modules.flowable.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.commons.io.IOUtils; +import org.flowable.bpmn.model.BpmnModel; +import org.flowable.bpmn.model.UserTask; +import org.flowable.engine.ProcessEngineConfiguration; +import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.repository.Deployment; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.engine.repository.ProcessDefinitionQuery; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.image.ProcessDiagramGenerator; +import org.flowable.image.impl.DefaultProcessDiagramGenerator; +import org.flowable.task.api.Task; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.util.SpringContextUtils; +import org.jeecg.modules.flowable.apithird.business.entity.FlowMyBusiness; +import org.jeecg.modules.flowable.apithird.business.service.impl.FlowMyBusinessServiceImpl; +import org.jeecg.modules.flowable.apithird.common.constant.ProcessConstants; +import org.jeecg.modules.flowable.apithird.common.enums.FlowComment; +import org.jeecg.modules.flowable.apithird.entity.SysUser; +import org.jeecg.modules.flowable.apithird.service.FlowCallBackServiceI; +import org.jeecg.modules.flowable.apithird.service.IFlowThirdService; +import org.jeecg.modules.flowable.domain.dto.FlowNextDto; +import org.jeecg.modules.flowable.domain.dto.FlowProcDefDto; +import org.jeecg.modules.flowable.factory.FlowServiceFactory; +import org.jeecg.modules.flowable.service.IFlowDefinitionService; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 娴佺▼瀹氫箟 + */ +@Service +public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFlowDefinitionService { + @Autowired + IFlowThirdService iFlowThirdService; + @Autowired + FlowMyBusinessServiceImpl flowMyBusinessService; + @Autowired + FlowTaskServiceImpl flowTaskService; + + private static final String BPMN_FILE_SUFFIX = ".bpmn"; + + @Override + public boolean exist(String processDefinitionKey) { + ProcessDefinitionQuery processDefinitionQuery + = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey); + long count = processDefinitionQuery.count(); + return count > 0; + } + + + /** + * 娴佺▼瀹氫箟鍒楄〃 + * + * @param pageNum 褰撳墠椤电爜 + * @param pageSize 姣忛〉鏉℃暟 + * @param flowProcDefDto + * @return 娴佺▼瀹氫箟鍒嗛〉鍒楄〃鏁版嵁 + */ + @Override + public Page<FlowProcDefDto> list(Integer pageNum, Integer pageSize, FlowProcDefDto flowProcDefDto) { + Page<FlowProcDefDto> page = new Page<>(); + // 娴佺▼瀹氫箟鍒楄〃鏁版嵁鏌ヨ + ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); + processDefinitionQuery + //.processDefinitionId("cs:5:15e953ed-4d09-11ec-85b8-e884a5deddfc") + .orderByProcessDefinitionKey().asc().orderByProcessDefinitionVersion().desc(); + /*=====鍙傛暟=====*/ + if (StrUtil.isNotBlank(flowProcDefDto.getName())) { + processDefinitionQuery.processDefinitionNameLike("%" + flowProcDefDto.getName() + "%"); + } + if (StrUtil.isNotBlank(flowProcDefDto.getCategory())) { + processDefinitionQuery.processDefinitionCategory(flowProcDefDto.getCategory()); + } + if (flowProcDefDto.getSuspensionState() == 1) { + processDefinitionQuery.active(); + } + if (StrUtil.isNotBlank(flowProcDefDto.getKey())) { + processDefinitionQuery.processDefinitionKey(flowProcDefDto.getKey()); + } + if (flowProcDefDto.getIsLastVersion() == 1) { + processDefinitionQuery.latestVersion(); + } + /*============*/ + page.setTotal(processDefinitionQuery.count()); + List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage((pageNum - 1) * pageSize, pageSize); + + List<FlowProcDefDto> dataList = new ArrayList<>(); + for (ProcessDefinition processDefinition : processDefinitionList) { + String deploymentId = processDefinition.getDeploymentId(); + Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); + FlowProcDefDto reProcDef = new FlowProcDefDto(); + BeanUtils.copyProperties(processDefinition, reProcDef); + // 娴佺▼瀹氫箟鏃堕棿 + reProcDef.setDeploymentTime(deployment.getDeploymentTime()); + dataList.add(reProcDef); + } + page.setRecords(dataList); + return page; + } + + + /** + * 瀵煎叆娴佺▼鏂囦欢 + * + * @param name + * @param category + * @param in + */ + @Override + public void importFile(String name, String category, InputStream in) { + Deployment deploy = repositoryService.createDeployment().addInputStream(name + BPMN_FILE_SUFFIX, in).name(name).category(category).deploy(); + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult(); + repositoryService.setProcessDefinitionCategory(definition.getId(), category); + + } + + /** + * 璇诲彇xml + * + * @param deployId + * @return + */ + @Override + public Result readXml(String deployId) throws IOException { + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName()); + String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + return Result.OK("", result); + } + + @Override + public Result readXmlByDataId(String dataId) throws IOException { + LambdaQueryWrapper<FlowMyBusiness> flowMyBusinessLambdaQueryWrapper = new LambdaQueryWrapper<>(); + flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId, dataId) + ; + //濡傛灉淇濆瓨鏁版嵁鍓嶆湭璋冪敤蹇呰皟鐨凢lowCommonService.initActBusiness鏂规硶锛屽氨浼氭湁闂 + FlowMyBusiness business = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper); + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().processDefinitionId(business.getProcessDefinitionId()).singleResult(); + InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName()); + String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + return Result.OK("", result); + } + + /** + * 璇诲彇xml 鏍规嵁涓氬姟Id + * + * @param dataId + * @return + */ + @Override + public InputStream readImageByDataId(String dataId) { + FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId); + + String processId = business.getProcessInstanceId(); + ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult(); + //娴佺▼璧板畬鐨� 鏄剧ず鍏ㄥ浘 + if (pi == null) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(business.getProcessDefinitionId()).singleResult(); + return this.readImage(processDefinition.getDeploymentId()); + } + + List<HistoricActivityInstance> historyProcess = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processId).list(); + List<String> activityIds = new ArrayList<>(); + List<String> flows = new ArrayList<>(); + //鑾峰彇娴佺▼鍥� + BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId()); + for (HistoricActivityInstance hi : historyProcess) { + String activityType = hi.getActivityType(); + if (activityType.equals("sequenceFlow") || activityType.equals("exclusiveGateway")) { + flows.add(hi.getActivityId()); + } else if (activityType.equals("userTask") || activityType.equals("startEvent")) { + activityIds.add(hi.getActivityId()); + } + } + List<Task> tasks = taskService.createTaskQuery().processInstanceId(processId).list(); + for (Task task : tasks) { + activityIds.add(task.getTaskDefinitionKey()); + } + ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration(); + //瀹氫箟娴佺▼鐢诲竷鐢熸垚鍣� + ProcessDiagramGenerator processDiagramGenerator = engConf.getProcessDiagramGenerator(); + InputStream in = processDiagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engConf.getActivityFontName(), engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true); + return in; + } + + /** + * 璇诲彇xml + * + * @param deployId + * @return + */ + @Override + public InputStream readImage(String deployId) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + //鑾峰緱鍥剧墖娴� + DefaultProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); + //杈撳嚭涓哄浘鐗� + return diagramGenerator.generateDiagram( + bpmnModel, + "png", + Collections.emptyList(), + Collections.emptyList(), + "瀹嬩綋", + "瀹嬩綋", + "瀹嬩綋", + null, + 1.0, + false); + + } + + /** + * 鏍规嵁娴佺▼瀹氫箟ID鍚姩娴佺▼瀹炰緥 + * + * @param procDefKey 娴佺▼瀹氫箟Id + * @param variables 娴佺▼鍙橀噺 + * @return + */ + @Override + @Transactional(rollbackFor = {Exception.class}) + public Result<?> startProcessInstanceByKey(String procDefKey, Map<String, Object> variables) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() + .processDefinitionKey(procDefKey) + .latestVersion().singleResult(); + Result result = startProcessInstanceById(processDefinition.getId(), variables); + return result; + } + + /** + * 鏍规嵁娴佺▼瀹氫箟ID鍚姩娴佺▼瀹炰緥 + * + * @param procDefId 娴佺▼瀹氫箟Id + * @param variables 娴佺▼鍙橀噺 + * @return + */ + @Override + @Transactional + public Result<?> startProcessInstanceById(String procDefId, Map<String, Object> variables) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(procDefId) + .singleResult(); + if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) { + return Result.error("娴佺▼宸茶鎸傝捣,璇峰厛婵�娲绘祦绋�"); + } +// variables.put("skip", true); +// variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true); + // 璁剧疆娴佺▼鍙戣捣浜篒d鍒版祦绋嬩腑 + SysUser sysUser = iFlowThirdService.getLoginUser(); + identityService.setAuthenticatedUserId(sysUser.getUsername()); + variables.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUsername()); + ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables); + // 缁欑涓�姝ョ敵璇蜂汉鑺傜偣璁剧疆浠诲姟鎵ц浜哄拰鎰忚 + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().singleResult(); + if (Objects.nonNull(task)) { + taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), variables.get("organization").toString()); + taskService.setAssignee(task.getId(), sysUser.getUsername()); + task.setDescription(variables.get("organization").toString()); + //taskService.complete(task.getId(), variables); + } + //璁剧疆鎵�鏈夌敵璇蜂汉 + + /*======================todo 鍚姩涔嬪悗 鍥炶皟浠ュ強鍏抽敭鏁版嵁淇濆瓨======================*/ + //涓氬姟鏁版嵁id + String dataId = variables.get("dataId").toString(); + //濡傛灉淇濆瓨鏁版嵁鍓嶆湭璋冪敤蹇呰皟鐨凢lowCommonService.initActBusiness鏂规硶锛屽氨浼氭湁闂 + FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId); + //璁剧疆鏁版嵁 + List<FlowNextDto> nextFlowNodeList = flowTaskService.getNextFlowNode(task.getId(), variables); + taskService.complete(task.getId(), variables); + //涓嬩竴涓疄渚嬭妭鐐� 澶氬疄渚嬩細鏄竴涓猯ist,闅忔剰鍙栦竴涓嵆鍙� 鏁扮粍涓畾涔塊ey鏄竴鑷寸殑 + //Task task2 = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().singleResult(); + List<Task> task2List = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().list(); + String doneUsers = business.getDoneUsers(); + // 澶勭悊杩囨祦绋嬬殑浜� + JSONArray doneUserList = new JSONArray(); + if (StrUtil.isNotBlank(doneUsers)) { + doneUserList = JSON.parseArray(doneUsers); + } + if (!doneUserList.contains(sysUser.getUsername())) { + doneUserList.add(sysUser.getUsername()); + } + + if (CollectionUtil.isEmpty(nextFlowNodeList)) { + // **娌℃湁涓嬩竴涓妭鐐癸紝娴佺▼宸茬粡缁撴潫浜� + business.setProcessDefinitionId(procDefId) + .setProcessInstanceId(processInstance.getProcessInstanceId()) +// .setActStatus(ActStatus.pass) + .setProposer(sysUser.getUsername()) + .setDoneUsers(doneUserList.toJSONString()) + ; + flowMyBusinessService.updateById(business); + } else if (nextFlowNodeList.size() == 1) { + //涓嬩釜鑺傜偣鍙湁涓�涓� + FlowNextDto nextFlowNode = nextFlowNodeList.get(0); + UserTask nextTask = nextFlowNode.getUserTask(); + Task task2 = null; + Optional<Task> first = task2List.stream().filter(t -> t.getTaskDefinitionKey().equals(nextTask.getId())).findFirst(); + if (first.isPresent()) { + task2 = first.get(); + } + if (task2 != null) { + //鑳藉澶勭悊涓嬩釜鑺傜偣鐨勫�欓�変汉 + List<SysUser> nextFlowNodeUserList = nextFlowNode.getUserList(); + + List<String> collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList()); + //spring瀹瑰櫒绫诲悕 + String serviceImplName = business.getServiceImplName(); + FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName); + List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionId(), variables); + business.setProcessDefinitionId(procDefId) + .setProcessInstanceId(processInstance.getProcessInstanceId()) +//// .setActStatus(ActStatus.start) + .setProposer(sysUser.getUsername()) + .setTaskId(task2.getId()) + .setTaskName(nextTask.getName()) + .setTaskNameId(nextTask.getId()) + .setPriority(nextTask.getPriority()) + .setDoneUsers(doneUserList.toJSONString()); + if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) { + // 鍒犻櫎鍚庨噸鍐� + for (String oldUser : collect_username) { + taskService.deleteCandidateUser(task2.getId(), oldUser); + } + // 涓氬姟灞傛湁鎸囧畾鍊欓�変汉锛岃鐩� + for (String newUser : beforeParamsCandidateUsernames) { + taskService.addCandidateUser(task2.getId(), newUser); + } + business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames)); + } else { + // 涓氬姟灞傛病鏈夋寚瀹氬�欓�変汉锛岀洿鎺ヨ鐩� + business.setTodoUsers(JSON.toJSONString(collect_username)); + } + flowMyBusinessService.updateById(business); + } + } else { + for (FlowNextDto nextFlowNode : nextFlowNodeList) { + //**鏈変笅涓�涓妭鐐� + UserTask nextTask = nextFlowNode.getUserTask(); + Task task2 = null; + Optional<Task> first = task2List.stream().filter(t -> t.getTaskDefinitionKey().equals(nextTask.getId())).findFirst(); + if (first.isPresent()) { + task2 = first.get(); + } + if (task2 != null) { + //鏂扮殑涓氬姟娴佺▼鑺傜偣 + FlowMyBusiness newBusiness = BeanUtil.copyProperties(business, FlowMyBusiness.class, "id"); + //鑳藉澶勭悊涓嬩釜鑺傜偣鐨勫�欓�変汉 + List<SysUser> nextFlowNodeUserList = nextFlowNode.getUserList(); + + List<String> collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList()); + //spring瀹瑰櫒绫诲悕 + String serviceImplName = newBusiness.getServiceImplName(); + FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName); + List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionId(), variables); + newBusiness.setProcessDefinitionId(procDefId) + .setProcessInstanceId(processInstance.getProcessInstanceId()) +//// .setActStatus(ActStatus.start) + .setProposer(sysUser.getUsername()) + .setTaskId(task2.getId()) + .setTaskName(nextTask.getName()) + .setTaskNameId(nextTask.getId()) + .setPriority(nextTask.getPriority()) + .setDoneUsers(doneUserList.toJSONString()); + if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) { + // 鍒犻櫎鍚庨噸鍐� + for (Task task2One : task2List) { + for (String oldUser : beforeParamsCandidateUsernames) { + taskService.deleteCandidateUser(task2One.getId(), oldUser); + } + } + // 涓氬姟灞傛湁鎸囧畾鍊欓�変汉锛岃鐩� + for (Task task2One : task2List) { + for (String newUser : beforeParamsCandidateUsernames) { + taskService.addCandidateUser(task2One.getId(), newUser); + } + } + newBusiness.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames)); + } else { + // 涓氬姟灞傛病鏈夋寚瀹氬�欓�変汉锛岀洿鎺ヨ鐩� + newBusiness.setTodoUsers(JSON.toJSONString(collect_username)); + // 鍒犻櫎鍚庨噸鍐� + for (Task task2One : task2List) { + for (String oldUser : collect_username) { + taskService.deleteCandidateUser(task2One.getId(), oldUser); + } + } + // 涓氬姟灞傛湁鎸囧畾鍊欓�変汉锛岃鐩� + for (Task task2One : task2List) { + for (String newUser : collect_username) { + taskService.addCandidateUser(task2One.getId(), newUser); + } + } + } + flowMyBusinessService.save(newBusiness); + } + } + //鍒犻櫎鍘熸湁鐨勪笟鍔℃暟鎹� + flowMyBusinessService.removeById(business.getId()); + } + //spring瀹瑰櫒绫诲悕 + String serviceImplName = business.getServiceImplName(); + FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName); + // 娴佺▼澶勭悊瀹屽悗锛岃繘琛屽洖璋冧笟鍔″眰 + business.setValues(variables); + if (flowCallBackService != null) { + flowCallBackService.afterFlowHandle(business); + } + return Result.OK("娴佺▼鍚姩鎴愬姛"); + } + + @Override + public Result startProcessInstanceByDataId(String dataId, Map<String, Object> variables) { + LambdaQueryWrapper<FlowMyBusiness> flowMyBusinessLambdaQueryWrapper = new LambdaQueryWrapper<>(); + flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId, dataId) + ; + FlowMyBusiness business = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper); + if (business == null) { + return Result.error("鏈壘鍒癲ataId锛�" + dataId); + } + if (StrUtil.isNotBlank(business.getProcessDefinitionId())) { + return this.startProcessInstanceById(business.getProcessDefinitionId(), variables); + } + return this.startProcessInstanceByKey(business.getProcessDefinitionKey(), variables); + } + + + /** + * 婵�娲绘垨鎸傝捣娴佺▼瀹氫箟 + * + * @param state 鐘舵�� 婵�娲�1 鎸傝捣2 + * @param deployId 娴佺▼閮ㄧ讲ID + */ + @Override + public void updateState(Integer state, String deployId) { + ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult(); + // 婵�娲� + if (state == 1) { + repositoryService.activateProcessDefinitionById(procDef.getId(), true, null); + } + // 鎸傝捣 + if (state == 2) { + repositoryService.suspendProcessDefinitionById(procDef.getId(), true, null); + } + } + + + /** + * 鍒犻櫎娴佺▼瀹氫箟 + * + * @param deployId 娴佺▼閮ㄧ讲ID act_ge_bytearray 琛ㄤ腑 deployment_id鍊� + */ + @Override + public void delete(String deployId) { + // true 鍏佽绾ц仈鍒犻櫎 ,涓嶈缃細瀵艰嚧鏁版嵁搴撳閿叧鑱斿紓甯� + repositoryService.deleteDeployment(deployId, true); + } + + +} -- Gitblit v1.9.3