package jnpf.flowable.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.dynamic.datasource.annotation.DSTransactional; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import jnpf.base.UserInfo; import jnpf.base.entity.DictionaryDataEntity; import jnpf.base.entity.SystemEntity; import jnpf.base.entity.VisualdevEntity; import jnpf.base.model.module.ModuleModel; import jnpf.base.service.SuperServiceImpl; import jnpf.constant.JnpfConst; import jnpf.constant.MsgCode; import jnpf.exception.WorkFlowException; import jnpf.flowable.entity.*; import jnpf.flowable.enums.*; import jnpf.flowable.mapper.*; import jnpf.flowable.model.candidates.*; import jnpf.flowable.model.flowable.FlowAbleUrl; import jnpf.flowable.model.message.FlowMsgModel; import jnpf.flowable.model.monitor.MonitorVo; import jnpf.flowable.model.operator.OperatorVo; import jnpf.flowable.model.record.NodeRecordModel; import jnpf.flowable.model.task.*; import jnpf.flowable.model.template.BeforeInfoVo; import jnpf.flowable.model.templatejson.TemplateJsonInfoVO; import jnpf.flowable.model.templatenode.ButtonModel; import jnpf.flowable.model.templatenode.TaskNodeModel; import jnpf.flowable.model.templatenode.nodejson.NodeModel; import jnpf.flowable.model.util.FlowNature; import jnpf.flowable.service.RejectDataService; import jnpf.flowable.service.TaskService; import jnpf.flowable.util.*; import jnpf.permission.entity.UserEntity; import jnpf.permission.model.authorize.AuthorizeVO; import jnpf.util.*; import jnpf.util.context.RequestContext; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; /** * 类的描述 * * @author JNPF@YinMai Info. Co., Ltd * @version 5.0.x * @since 2024/4/17 15:09 */ @Service @RequiredArgsConstructor public class TaskServiceImpl extends SuperServiceImpl implements TaskService { private final FlowAbleUrl flowAbleUrl; private final ServiceUtil serviceUtil; private final OperatorUtil operatorUtil; private final NodeUtil nodeUtil; private final MsgUtil msgUtil; private final ButtonUtil buttonUtil; private final RecordUtil recordUtil; private final FlowUtil flowUtil; private final TaskUtil taskUtil; private final TemplateMapper templateMapper; private final TemplateJsonMapper templateJsonMapper; private final TemplateNodeMapper templateNodeMapper; private final LaunchUserMapper launchUserMapper; private final CandidatesMapper candidatesMapper; private final OperatorMapper operatorMapper; private final RecordMapper recordMapper; private final CirculateMapper circulateMapper; private final RejectDataService rejectDataService; private final NodeRecordMapper nodeRecordMapper; private final TaskLineMapper taskLineMapper; private final RevokeMapper revokeMapper; private final EventLogMapper eventLogMapper; private final TemplateUseNumMapper templateUseNumMapper; private final TriggerLaunchflowMapper triggerLaunchflowMapper; @Override public TaskEntity getInfoSubmit(String id, SFunction... columns) { return this.baseMapper.getInfoSubmit(id, columns); } @Override public List getInfosSubmit(String[] ids, SFunction... columns) { return this.baseMapper.getInfosSubmit(ids, columns); } @Override public List getList(TaskPagination pagination) { String userId = UserProvider.getUser().getUserId(); List templateStatusList = ImmutableList.of(TemplateStatueEnum.UP.getCode(), TemplateStatueEnum.DOWN_CONTINUE.getCode()); List taskStatusList = ImmutableList.of(TaskStatusEnum.TO_BE_SUBMIT.getCode(), TaskStatusEnum.RUNNING.getCode(), TaskStatusEnum.PAUSED.getCode(), TaskStatusEnum.BACKED.getCode(), TaskStatusEnum.RECALL.getCode()); MPJLambdaWrapper queryWrapper = JoinWrappers.lambda(TaskEntity.class) .select(TaskEntity::getId, TaskEntity::getFullName, TaskEntity::getStartTime, TaskEntity::getCurrentNodeName, TaskEntity::getFlowName, TaskEntity::getFlowType, TaskEntity::getFlowVersion, TaskEntity::getParentId, TaskEntity::getStatus, TaskEntity::getFlowCategory, TaskEntity::getFlowCode, TaskEntity::getFlowId, TaskEntity::getInstanceId, TaskEntity::getTemplateId ) .selectAs(TaskEntity::getDelegateUserId, TaskVo::getDelegateUser) .selectAs(TaskEntity::getUrgent, TaskVo::getFlowUrgent) .selectAs(TemplateEntity::getSystemId, TaskVo::getSystemName) .selectAs(TaskEntity::getCreatorUserId, TaskVo::getCreatorUser) .leftJoin(TemplateEntity.class, TemplateEntity::getId, TaskEntity::getTemplateId) .and(e -> e.in(TemplateEntity::getStatus, templateStatusList) .or(t -> t.eq(TemplateEntity::getStatus, TemplateStatueEnum.DOWN_HIDDEN.getCode()).notIn(TaskEntity::getStatus, taskStatusList)) ) .ne(TaskEntity::getStatus, TaskStatusEnum.WAITING.getCode()); List delegateList = flowUtil.getByToUserId(userId, 0); queryWrapper.and(t -> { t.eq(TaskEntity::getCreatorUserId, userId); for (DelegateEntity delegate : delegateList) { if (StringUtil.isNotEmpty(delegate.getFlowId())) { String[] flowIds = delegate.getFlowId().split(","); t.or(tw -> tw.in(TaskEntity::getTemplateId, flowIds) .eq(TaskEntity::getCreatorUserId, delegate.getUserId()).eq(TaskEntity::getDelegateUserId, userId) .between(TaskEntity::getStartTime, delegate.getStartTime(), delegate.getEndTime()) ); } else { t.or().eq(TaskEntity::getCreatorUserId, delegate.getUserId()).eq(TaskEntity::getDelegateUserId, userId) .between(TaskEntity::getStartTime, delegate.getStartTime(), delegate.getEndTime()); } } }); //关键字(流程名称、流程编码) String keyWord = pagination.getKeyword(); if (ObjectUtil.isNotEmpty(keyWord)) { queryWrapper.and(t -> t.like(TaskEntity::getEnCode, keyWord).or().like(TaskEntity::getFullName, keyWord)); } //日期范围(近7天、近1月、近3月、自定义) if (ObjectUtil.isNotEmpty(pagination.getStartTime()) && ObjectUtil.isNotEmpty(pagination.getEndTime())) { queryWrapper.between(TaskEntity::getStartTime, new Date(pagination.getStartTime()), new Date(pagination.getEndTime())); } //所属流程 String templateId = pagination.getTemplateId(); if (ObjectUtil.isNotEmpty(templateId)) { queryWrapper.eq(TaskEntity::getTemplateId, templateId); } //流程状态 Integer status = pagination.getStatus(); if (ObjectUtil.isNotEmpty(status)) { if (status.equals(0)) {// 待提交 List list = ImmutableList.of(TaskStatusEnum.TO_BE_SUBMIT.getCode(), TaskStatusEnum.BACKED.getCode() , TaskStatusEnum.RECALL.getCode()); queryWrapper.in(TaskEntity::getStatus, list); } else if (status.equals(1)) { // 进行中 List list = ImmutableList.of(TaskStatusEnum.RUNNING.getCode(), TaskStatusEnum.PAUSED.getCode()); queryWrapper.in(TaskEntity::getStatus, list); } else { // 已完成 List list = ImmutableList.of(TaskStatusEnum.PASSED.getCode(), TaskStatusEnum.REJECTED.getCode(), TaskStatusEnum.CANCEL.getCode(), TaskStatusEnum.REVOKED.getCode()); queryWrapper.in(TaskEntity::getStatus, list); } } //紧急程度 Integer flowUrgent = pagination.getFlowUrgent(); if (ObjectUtil.isNotEmpty(flowUrgent)) { queryWrapper.eq(TaskEntity::getUrgent, flowUrgent); } //所属分类 String flowCategory = pagination.getFlowCategory(); if (ObjectUtil.isNotEmpty(flowCategory)) { queryWrapper.eq(TaskEntity::getFlowCategory, flowCategory); } //应用主键 String systemId = pagination.getSystemId(); if (ObjectUtil.isNotEmpty(systemId)) { queryWrapper.eq(TemplateEntity::getSystemId, systemId); } //排序 queryWrapper.orderByAsc(TaskEntity::getStatus).orderByDesc(TaskEntity::getStartTime); Page page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize()); IPage taskEntityPage = this.selectJoinListPage(page, TaskVo.class, queryWrapper); return pagination.setData(taskEntityPage.getRecords(), page.getTotal()); } @Override public List getMonitorList(TaskPagination pagination) { return this.baseMapper.getMonitorList(pagination); } @Override public TaskEntity getInfo(String id) throws WorkFlowException { return this.baseMapper.getInfo(id); } // 发起、审批详情 @Override public BeforeInfoVo getInfo(String id, FlowModel fo) throws WorkFlowException { BeforeInfoVo vo = new BeforeInfoVo(); TemplateJsonInfoVO jsonInfoVO = null; TemplateEntity template = null; if (!StringUtils.equals(FlowNature.PARENT_ID, id)) { TaskEntity taskEntity = this.getById(id); if (null != taskEntity) { jsonInfoVO = flowUtil.getInfoVo(taskEntity.getFlowId()); template = templateMapper.getInfo(taskEntity.getTemplateId()); } vo.setLineKeyList(taskLineMapper.getLineKeyList(id)); } if (null == jsonInfoVO) { template = null == template ? templateMapper.getInfo(fo.getFlowId()) : template; jsonInfoVO = flowUtil.getInfoVo(template.getFlowId()); } fo.setTemplateEntity(template); vo.setFlowInfo(jsonInfoVO); fo.setDeploymentId(jsonInfoVO.getFlowableId()); // 节点 List nodeEntities = templateNodeMapper.getList(jsonInfoVO.getFlowId()); TemplateNodeEntity nodeEntity = null; OperatorEntity operatorEntity = new OperatorEntity(); RecordEntity recordEntity = new RecordEntity(); Map map = new HashMap<>(); Map draft = new HashMap<>(); String operatorId = ObjectUtil.isNotEmpty(fo.getOperatorId()) ? fo.getOperatorId() : ""; OpTypeEnum type = OpTypeEnum.getType(fo.getOpType()); switch (type) { case LAUNCH_CREATE: case SIGN:// 待签 case TODO:// 待办 case DOING:// 在办 OperatorEntity operator = operatorMapper.getInfo(operatorId); if (null != operator) { nodeEntity = nodeEntities.stream() .filter(e -> StringUtils.equals(operator.getNodeCode(), e.getNodeCode())).findFirst().orElse(null); operatorEntity = operator; } break; case DONE:// 已办 RecordEntity recordMapperInfo = recordMapper.getInfo(operatorId); if (null != recordMapperInfo) { nodeEntity = nodeEntities.stream() .filter(e -> StringUtils.equals(recordMapperInfo.getNodeCode(), e.getNodeCode()) && !Objects.equals(NodeEnum.OUTSIDE.getType(), e.getNodeType())).findFirst().orElse(null); if (StringUtils.isNotBlank(recordMapperInfo.getOperatorId())) { OperatorEntity op = operatorMapper.selectById(recordMapperInfo.getOperatorId()); if (null != op) { operatorEntity = op; } } recordEntity = recordMapperInfo; } break; case CIRCULATE:// 抄送 CirculateEntity circulateEntity = circulateMapper.selectById(operatorId); if (null != circulateEntity) { nodeEntity = nodeEntities.stream() .filter(e -> StringUtils.equals(circulateEntity.getNodeCode(), e.getNodeCode())).findFirst().orElse(null); circulateEntity.setCirculateRead(1); circulateMapper.updateById(circulateEntity); if (StringUtils.isNotBlank(circulateEntity.getOperatorId())) { OperatorEntity ope = operatorMapper.selectById(circulateEntity.getOperatorId()); if (null != ope) { operatorEntity = ope; } } } break; default: break; } //发起流程添加使用次数 if (Objects.equals(fo.getIsFlow(), 1)) { templateUseNumMapper.insertOrUpdateUseNum(fo.getFlowId()); } if (null == nodeEntity) { // 默认获取开始节点 nodeEntity = nodeEntities.stream() .filter(e -> StringUtils.equals(NodeEnum.START.getType(), e.getNodeType())).findFirst().orElse(null); } if (null == nodeEntity) { throw new WorkFlowException(MsgCode.WF076.get()); } if (OpTypeEnum.DOING.equals(type) && null != operatorEntity.getDraftData()) { Map draftData = JsonUtil.stringToMap(operatorEntity.getDraftData()); draftData.forEach((k, v) -> { if (ObjectUtil.isNotEmpty(v) && !Objects.equals(TableFeildsEnum.VERSION.getField(), k)) { map.put(k, v); } }); draft.putAll(draftData); } String formId = nodeEntity.getFormId(); NodeModel currentNode = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class); vo.setFormOperates(currentNode.getFormOperates()); // 表单数据 if (!StringUtils.equals(FlowNature.PARENT_ID, id)) { Map formData = serviceUtil.infoData(formId, id); vo.setFormData(formData); fo.setFormData(formData); formData.putAll(map); draft.putAll(formData); String flowTaskID = Objects.nonNull(formData.get(FlowFormConstant.FLOWTASKID)) ? formData.get(FlowFormConstant.FLOWTASKID).toString() : ""; id = StringUtils.isNotBlank(flowTaskID) ? flowTaskID : id; TaskEntity taskEntity = this.getById(id); if (null != taskEntity) { TaskVo taskVo = JsonUtil.getJsonToBean(taskEntity, TaskVo.class); taskVo.setFlowUrgent(taskEntity.getUrgent()); UserEntity user = serviceUtil.getUserInfo(taskEntity.getCreatorUserId()); taskVo.setCreatorUser(user.getRealName()); taskVo.setHeadIcon(UploaderUtil.uploaderImg(user.getHeadIcon())); String flowCategory = taskEntity.getFlowCategory(); // 分类名称 List categoryIds = ImmutableList.of(flowCategory); List dictionName = serviceUtil.getDictionName(categoryIds); taskVo.setFlowCategory(dictionName.stream().map(DictionaryDataEntity::getFullName).collect(Collectors.joining(","))); vo.setTaskInfo(taskVo); fo.setTaskEntity(taskEntity); // 流转记录 List records = recordMapper.getList(taskEntity.getId()); vo.setRecordList(recordUtil.getRecordList(records, nodeEntities)); FlowModel flowModel = new FlowModel(); flowModel.setFormData(formData); flowModel.setDeploymentId(fo.getDeploymentId()); flowModel.setTaskEntity(taskEntity); flowModel.setNodeEntityList(nodeEntities); flowModel.setNodeEntity(nodeEntity); flowModel.setOpType(fo.getOpType()); flowModel.setRecordEntity(recordEntity); // 节点 List nodeList = nodeUtil.getNodeList(flowModel); vo.setNodeList(nodeList); fo.setNodeList(nodeList); vo.setFlowInfo(jsonInfoVO); Map nodeProperties = jsonInfoVO.getFlowNodes().get(nodeEntity.getNodeCode()); nodeUtil.setFlowFile(currentNode, taskEntity, nodeProperties); vo.setNodeProperties(nodeProperties); vo.setProgressList(!Objects.equals(type, OpTypeEnum.MONITOR) ? recordUtil.getProgressList(flowModel) : new ArrayList<>()); } } // 判断按钮 fo.setOperatorEntity(operatorEntity); fo.setNodeEntity(nodeEntity); fo.setRecordEntity(recordEntity); fo.setNodeEntityList(nodeEntities); fo.setFlowId(jsonInfoVO.getFlowId()); ButtonModel model = buttonUtil.handleButton(fo); vo.setBtnInfo(model); RevokeEntity revokeEntity = revokeMapper.getRevokeTask(id); if (null != revokeEntity) { Map revokeMap = JsonUtil.stringToMap(revokeEntity.getFormData()); vo.setFormData(revokeMap); VisualdevEntity formInfo = new VisualdevEntity(); formInfo.setEnCode(FlowNature.REVOKE_FORM_CODE); formInfo.setType(2); vo.setFormInfo(formInfo); TaskVo taskInfo = vo.getTaskInfo(); if (null != taskInfo) { taskInfo.setIsRevokeTask(true); } } else { vo.setFormData(draft); // 获取表单 if (null != formId) { VisualdevEntity formInfo = serviceUtil.getFormInfo(formId); vo.setFormInfo(formInfo); } } return vo; } @Override public CandidateCheckVo checkCandidates(String id, CandidateCheckFo fo) throws WorkFlowException { return operatorUtil.checkCandidates(id, fo); } @Override public List getCandidateUser(String id, CandidateCheckFo fo) throws WorkFlowException { TemplateJsonEntity jsonEntity = templateJsonMapper.selectById(fo.getFlowId()); if (null == jsonEntity) { TemplateEntity template = templateMapper.getInfo(fo.getFlowId()); jsonEntity = templateJsonMapper.getInfo(template.getFlowId()); } List nodeEntities = templateNodeMapper.getList(jsonEntity.getId()); Map nodes = new HashMap<>(); for (TemplateNodeEntity nodeEntity : nodeEntities) { nodes.put(nodeEntity.getNodeCode(), JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class)); } NodeModel nodeModel = nodes.get(fo.getNodeCode()); if (null == nodeModel) { throw new WorkFlowException(MsgCode.WF076.get()); } // 获取候选人 CandidateCheckVo candidateCheckVo = checkCandidates(id, fo); List list = candidateCheckVo.getList(); Map> nodeMap = list.stream().collect(Collectors.groupingBy(CandidateListModel::getNodeCode)); List candidateList = nodeMap.get(fo.getNodeCode()) != null ? nodeMap.get(fo.getNodeCode()) : new ArrayList<>(); List userIds = new ArrayList<>(); for (CandidateListModel model : candidateList) { userIds.addAll(model.getSelectIdList()); } // 候选人范围过滤 UserInfo userInfo = UserProvider.getUser(); UserEntity userEntity = serviceUtil.getUserInfo(userInfo.getUserId()); OperatorEntity operator = operatorMapper.selectById(id); if (null != operator) { userEntity = serviceUtil.getUserInfo(operator.getHandleId()); } else { if (StringUtils.isNotBlank(fo.getDelegateUser())) { userEntity = serviceUtil.getUserInfo(fo.getDelegateUser()); } } LaunchUserEntity flowUser = new LaunchUserEntity(); flowUtil.launchUser(flowUser, userEntity); flowUtil.rule(userIds, flowUser, nodeModel.getExtraRule()); return operatorUtil.getUserModelByUserIds(userIds, fo); } @DSTransactional @Override public void batchSaveOrSubmit(FlowModel flowModel) throws WorkFlowException { operatorUtil.batchSaveOrSubmit(flowModel); } // 提交或暂存 @Override public void saveOrSubmit(FlowModel flowModel) throws WorkFlowException { operatorUtil.saveOrSubmit(flowModel); } // 发起撤回 @DSTransactional @Override public void recall(String id, FlowModel flowModel) throws WorkFlowException { flowUtil.setFlowModel(id, flowModel); TaskEntity taskEntity = flowModel.getTaskEntity(); operatorUtil.checkTemplateHide(taskEntity.getTemplateId()); List nodeEntityList = flowModel.getNodeEntityList(); if (CollUtil.isEmpty(nodeEntityList)) { throw new WorkFlowException(MsgCode.WF076.get()); } operatorUtil.addTask(ImmutableList.of(taskEntity.getId())); // 开始节点 TemplateNodeEntity nodeEntity = nodeEntityList.stream() .filter(e -> StringUtils.equals(NodeEnum.START.getType(), e.getNodeType())).findFirst().orElse(null); if (null == nodeEntity) { throw new WorkFlowException(MsgCode.WF076.get()); } NodeModel start = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class); flowModel.setNodeEntity(nodeEntity); flowModel.setIsException(true); if (!buttonUtil.checkRecall(flowModel)) { throw new WorkFlowException(MsgCode.WF077.get()); } // 删除子流程(判断方法中,存在异步 或 同步子流程已提交 则不允许撤回) operatorUtil.deleteSubflow(taskEntity.getId(), null); // 删除外部节点 eventLogMapper.delete(taskEntity.getId(), null); // 记录 FlowMethod flowMethod = new FlowMethod(); flowMethod.setType(RecordEnum.RECALL.getCode()); flowMethod.setFlowModel(flowModel); OperatorEntity operatorEntity = new OperatorEntity(); operatorEntity.setNodeCode(nodeEntity.getNodeCode()); operatorEntity.setNodeName(start.getNodeName()); operatorEntity.setTaskId(taskEntity.getId()); operatorEntity.setHandleId(taskEntity.getCreatorUserId()); operatorEntity.setHandleTime(new Date()); flowMethod.setOperatorEntity(operatorEntity); recordMapper.createRecord(flowMethod); // 节点记录 NodeRecordModel nodeRecordModel = new NodeRecordModel(); nodeRecordModel.setTaskId(taskEntity.getId()); nodeRecordModel.setNodeCode(nodeEntity.getNodeCode()); nodeRecordModel.setNodeStatus(NodeStateEnum.RECALL.getCode()); nodeRecordMapper.update(nodeRecordModel); // 删除经办 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.lambda().eq(OperatorEntity::getTaskId, taskEntity.getId()); operatorMapper.delete(wrapper); // 删除候选人 candidatesMapper.deleteByCodes(taskEntity.getId(), null); // 删除发起人 launchUserMapper.delete(taskEntity.getId()); //删除同步流程 List triggerLaunchList = operatorUtil.getLaunchFlowList(taskEntity.getId()); triggerLaunchflowMapper.deleteByIds(triggerLaunchList); // 删除引擎实例 flowAbleUrl.deleteInstance(taskEntity.getInstanceId(), "retract"); // 变更任务状态 UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.lambda().eq(TaskEntity::getId, taskEntity.getId()) .set(TaskEntity::getInstanceId, null) .set(TaskEntity::getRejectDataId, null) .set(TaskEntity::getCurrentNodeName, FlowNature.START_NAME) .set(TaskEntity::getCurrentNodeCode, FlowNature.START_CODE) .set(TaskEntity::getStatus, TaskStatusEnum.RECALL.getCode()); this.update(updateWrapper); if (taskEntity.getRejectDataId() != null) { rejectDataService.removeById(taskEntity.getRejectDataId()); } } // 催办 @Override public boolean press(String id) throws WorkFlowException { FlowModel flowModel = new FlowModel(); flowUtil.setFlowModel(id, flowModel); TaskEntity taskEntity = flowModel.getTaskEntity(); List nodeEntityList = flowModel.getNodeEntityList(); // 消息 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(OperatorEntity::getTaskId, id).eq(OperatorEntity::getCompletion, FlowNature.NORMAL) .ne(OperatorEntity::getStatus, OperatorStateEnum.FUTILITY.getCode()) .isNull(OperatorEntity::getHandleStatus).isNotNull(OperatorEntity::getDuedate); List operatorList = operatorMapper.selectList(queryWrapper); if (operatorList.isEmpty()) { return false; } FlowMsgModel flowMsgModel = new FlowMsgModel(); flowMsgModel.setNodeList(nodeEntityList); flowMsgModel.setUserInfo(flowModel.getUserInfo()); flowMsgModel.setTaskEntity(taskEntity); flowMsgModel.setOperatorList(operatorList); flowMsgModel.setPress(true); msgUtil.message(flowMsgModel); return true; } @DSTransactional @Override public void revoke(String id, FlowModel flowModel) throws WorkFlowException { flowUtil.setFlowModel(id, flowModel); TaskEntity taskEntity = flowModel.getTaskEntity(); if (!TaskStatusEnum.PASSED.getCode().equals(taskEntity.getStatus())) { throw new WorkFlowException(MsgCode.WF078.get()); } // 处理撤销表单的数据 operatorUtil.submitOfRevoke(flowModel); } @DSTransactional @Override public List delete(String id) throws WorkFlowException { List taskList = taskUtil.delete(ImmutableList.of(id), false); operatorUtil.deleteFormData(taskList); return taskList; } @DSTransactional @Override public void deleteBatch(List ids) throws WorkFlowException { List taskList = taskUtil.delete(ids, true); operatorUtil.deleteFormData(taskList); List instanceIds = taskList.stream() .filter(t -> TaskStatusEnum.RUNNING.getCode().equals(t.getStatus()) || TaskStatusEnum.CANCEL.getCode().equals(t.getStatus())) .map(TaskEntity::getInstanceId).distinct().collect(Collectors.toList()); if (CollUtil.isNotEmpty(instanceIds)) { for (String instanceId : instanceIds) { flowAbleUrl.deleteInstance(instanceId, "monitor"); } } } @Override public void deleTaskAll(List idList, List idAll) { this.baseMapper.deleTaskAll(idList, idAll); } // 终止与挂起的区别,就是能否在列表中查询到,撤销中不允许终止等操作 @DSTransactional @Override public void cancel(String id, FlowModel flowModel, boolean isCancel) throws WorkFlowException { operatorUtil.cancel(id, flowModel, isCancel); } @Override public boolean checkAsync(String id) { return this.baseMapper.checkAsync(id); } // isSuspend: true 挂起、false 恢复 @DSTransactional @Override public void pause(String id, FlowModel flowModel, Boolean isSuspend) throws WorkFlowException { List idList = new ArrayList<>(); idList.add(id); boolean pause = false; // 暂停的选项,0.全部 1:仅主流程,同时暂停同步子流程 if (Boolean.TRUE.equals(isSuspend)) { pause = flowModel.getPause() == 1; } else { TaskEntity taskEntity = this.getInfo(id); if (ObjectUtil.equals(taskEntity.getIsRestore(), FlowNature.NOT_RESTORE)) { throw new WorkFlowException("无法恢复"); } List childList = this.baseMapper.getChildList(id, TaskEntity::getId, TaskEntity::getIsRestore); // 存在 0(能恢复的),就只恢复 1(不能恢复的,即同步的) pause = childList.stream().anyMatch(e -> ObjectUtil.equals(e.getIsRestore(), FlowNature.RESTORE)); } String userId = UserProvider.getLoginUserId(); this.baseMapper.getChildList(id, pause, idList); List orderStaList = this.baseMapper.getOrderStaList(idList); this.pause(orderStaList, isSuspend, id); for (TaskEntity entity : orderStaList) { // 记录 FlowMethod flowMethod = new FlowMethod(); flowMethod.setFlowModel(flowModel); flowMethod.setType(Boolean.TRUE.equals(isSuspend) ? RecordEnum.PAUSE.getCode() : RecordEnum.REBOOT.getCode()); OperatorEntity operatorEntity = new OperatorEntity(); operatorEntity.setNodeCode(StringUtils.isNotBlank(entity.getCurrentNodeCode()) ? entity.getCurrentNodeCode() : FlowNature.START_CODE); operatorEntity.setNodeName(StringUtils.isNotBlank(entity.getCurrentNodeName()) ? entity.getCurrentNodeName() : FlowNature.START_NAME); operatorEntity.setTaskId(entity.getId()); operatorEntity.setHandleId(userId); flowMethod.setOperatorEntity(operatorEntity); recordMapper.createRecord(flowMethod); operatorUtil.addTask(ImmutableList.of(entity.getId())); } } public List pause(List orderStaList, boolean isSuspend, String id) { List operatorList = new ArrayList<>(); for (TaskEntity taskEntity : orderStaList) { if (isSuspend) { // 暂停 if (!ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) { taskEntity.setHisStatus(taskEntity.getStatus()); taskEntity.setStatus(TaskStatusEnum.PAUSED.getCode()); } taskEntity.setIsRestore(ObjectUtil.equals(taskEntity.getId(), id) ? FlowNature.RESTORE : FlowNature.NOT_RESTORE); this.updateById(taskEntity); } else { // 恢复 taskEntity.setStatus(taskEntity.getHisStatus()); taskEntity.setHisStatus(TaskStatusEnum.PAUSED.getCode()); taskEntity.setIsRestore(FlowNature.RESTORE); this.updateById(taskEntity); } // 过滤作废的经办 List list = operatorMapper.getList(taskEntity.getId()).stream() .filter(e -> !e.getStatus().equals(OperatorStateEnum.FUTILITY.getCode())).collect(Collectors.toList()); operatorList.addAll(list); } return operatorList; } @DSTransactional @Override public void assign(String id, FlowModel flowModel) throws WorkFlowException { flowUtil.setFlowModel(id, flowModel); TaskEntity entity = flowModel.getTaskEntity(); flowUtil.isSuspend(entity); flowUtil.isCancel(entity); String handleId = flowModel.getUserInfo() == null ? UserProvider.getLoginUserId() : flowModel.getUserInfo().getUserId(); List nodeEntityList = flowModel.getNodeEntityList(); // 作废原先的经办、生成指派的经办 OperatorEntity operator = operatorUtil.handleAssign(flowModel); List list = new ArrayList<>(); list.add(operator); String nodeCode = flowModel.getNodeCode(); NodeModel nodeModel = flowModel.getNodes().get(nodeCode); Boolean autoTransfer = flowModel.getAutoTransferFlag(); boolean isProcessing = ObjectUtil.equals(nodeModel.getType(), NodeEnum.PROCESSING.getType()); if (Boolean.TRUE.equals(autoTransfer)) { flowModel.setHandleOpinion(isProcessing ? "系统转办" : "系统转审"); } //指派逐级审批失效 if (StringUtil.isNotEmpty(nodeCode)) { launchUserMapper.delete(operator.getTaskId(), ImmutableList.of(nodeCode)); } // 记录 FlowMethod flowMethod = new FlowMethod(); flowMethod.setFlowModel(flowModel); Integer transferType = isProcessing ? RecordEnum.TRANSFER_PROCESSING.getCode() : RecordEnum.TRANSFER.getCode(); flowMethod.setType(Boolean.TRUE.equals(autoTransfer) ? transferType : RecordEnum.ASSIGN.getCode()); OperatorEntity operatorEntity = new OperatorEntity(); operatorEntity.setId(operator.getId()); operatorEntity.setNodeCode(nodeCode); operatorEntity.setNodeId(operator.getNodeId()); operatorEntity.setNodeName(nodeModel.getNodeName()); operatorEntity.setTaskId(entity.getId()); operatorEntity.setHandleId(Boolean.TRUE.equals(autoTransfer) ? FlowNature.SYSTEM_CODE : handleId); flowMethod.setOperatorEntity(operatorEntity); List userIds = ImmutableList.of(flowModel.getHandleIds()); flowMethod.setUserId(String.join(",", userIds)); recordMapper.createRecord(flowMethod); // 消息 FlowMsgModel flowMsgModel = new FlowMsgModel(); flowMsgModel.setNodeList(nodeEntityList); flowMsgModel.setUserInfo(flowModel.getUserInfo()); flowMsgModel.setTaskEntity(entity); flowMsgModel.setOperatorList(list); if (Boolean.TRUE.equals(flowModel.getAutoTransferFlag())) { flowMsgModel.setTransfer(true); } else { flowMsgModel.setAssign(true); } msgUtil.message(flowMsgModel); operatorUtil.addOperatorList(list, flowModel); } @Override public TaskUserListModel getTaskUserList(String taskId) { return flowUtil.getTaskUserList(taskId); } @Override public List subFlowInfo(FlowModel flowModel) throws WorkFlowException { List list = new ArrayList<>(); List entityList = this.baseMapper.subFlowInfo(flowModel); if (CollUtil.isNotEmpty(entityList)) { for (TaskEntity entity : entityList) { FlowModel model = new FlowModel(); model.setFlowId(entity.getFlowId()); BeforeInfoVo info = this.getInfo(entity.getId(), model); list.add(info); } } return list; } // 消息跳转流程时,校验以及返回opType @Override public String checkInfo(String id) throws WorkFlowException { CirculateEntity circulate = circulateMapper.selectById(id); if (null != circulate) { return OpTypeEnum.CIRCULATE.getType(); } OperatorEntity operator = operatorMapper.getInfo(id); if (null == operator) { throw new WorkFlowException(MsgCode.FA001.get()); } if (operator.getStatus().equals(OperatorStateEnum.FUTILITY.getCode())) { throw new WorkFlowException("该流程无权限查看"); } TaskEntity taskEntity = this.getById(operator.getTaskId()); if (null == taskEntity) { throw new WorkFlowException(MsgCode.FA001.get()); } if (TaskStatusEnum.CANCEL.getCode().equals(taskEntity.getStatus())) { throw new WorkFlowException(MsgCode.WF041.get()); } if (TaskStatusEnum.RECALL.getCode().equals(taskEntity.getStatus())) { throw new WorkFlowException(MsgCode.WF042.get()); } operatorUtil.checkTemplateHide(taskEntity.getTemplateId()); String handleId = operator.getHandleId(); String userId = UserProvider.getLoginUserId(); List delegateList = flowUtil.getToUser(handleId, taskEntity.getFlowId()); delegateList.add(handleId); if (!delegateList.contains(userId)) { throw new WorkFlowException(MsgCode.FA021.get()); } String opType = OpTypeEnum.LAUNCH_DETAIL.getType(); if (null == operator.getSignTime() && null == operator.getStartHandleTime() && null == operator.getHandleStatus()) { opType = OpTypeEnum.SIGN.getType(); } if (null != operator.getSignTime() && null == operator.getStartHandleTime() && null == operator.getHandleStatus()) { opType = OpTypeEnum.TODO.getType(); } if (null != operator.getSignTime() && null != operator.getStartHandleTime() && null == operator.getHandleStatus()) { opType = OpTypeEnum.DOING.getType(); } if (null != operator.getHandleStatus() || operator.getCompletion().equals(FlowNature.ACTION)) { opType = OpTypeEnum.CIRCULATE.getType(); } return opType; } @Override public void updateIsFile(String taskId) throws WorkFlowException { TaskEntity taskEntity = this.getInfo(taskId); if (null != taskEntity) { taskEntity.setIsFile(1); this.updateById(taskEntity); } } // 获取发起表单 @Override public ViewFormModel getStartForm(String taskId) throws WorkFlowException { ViewFormModel model = new ViewFormModel(); TaskEntity taskEntity = this.getInfo(taskId); List nodeEntityList = templateNodeMapper.getList(taskEntity.getFlowId()); TemplateNodeEntity nodeEntity = nodeEntityList.stream() .filter(e -> ObjectUtil.equals(e.getNodeType(), NodeEnum.START.getType())).findFirst().orElse(null); if (null != nodeEntity) { String formId = nodeEntity.getFormId(); VisualdevEntity formInfo = serviceUtil.getFormInfo(formId); model.setFormInfo(formInfo); Map map = serviceUtil.infoData(formId, taskId); model.setFormData(map); } return model; } @Override public TaskTo getFlowTodoCount(TaskTo taskTo) { TaskPagination pagination = new TaskPagination(); pagination.setDelegateType(true); pagination.setPageSize(1L); pagination.setCurrentPage(1L); String appCode = RequestContext.getAppCode(); boolean isMainSystem = Objects.equals(JnpfConst.MAIN_SYSTEM_CODE, appCode); SystemEntity systemEntity = serviceUtil.getInfoByEnCode(!isMainSystem ? appCode : JnpfConst.WORK_FLOW_CODE); if (!isMainSystem) { pagination.setSystemId(systemEntity.getId()); } TaskTo vo = new TaskTo(); boolean isPc = RequestContext.isOrignPc(); String webType = isPc ? JnpfConst.WEB : JnpfConst.APP; List moduleListAll = taskTo.getModuleList() != null ? taskTo.getModuleList() : new ArrayList<>(); List moduleList = moduleListAll.stream(). filter(e -> Objects.equals(e.getSystemId(), systemEntity.getId()) && Objects.equals(webType, e.getCategory())) .collect(Collectors.toList()); Map> encodeMap = moduleList.stream().collect(Collectors.groupingBy(ModuleModel::getEnCode)); vo.setIsLaunch(ObjectUtil.isNotEmpty(encodeMap.get(JnpfConst.WORK_FLOWLAUNCH))); if (Boolean.TRUE.equals(vo.getIsLaunch())) { getList(pagination); vo.setFlowLaunch(pagination.getTotal()); } vo.setIsToSign(ObjectUtil.isNotEmpty(encodeMap.get(JnpfConst.WORK_FLOWSIGN))); if (Boolean.TRUE.equals(vo.getIsToSign())) { if (ObjectUtil.isNotEmpty(taskTo.getFlowToSignType())) { pagination.setFlowCategory(String.join(",", taskTo.getFlowToSignType())); } pagination.setCategory(CategoryEnum.SIGN.getType()); flowUtil.getOperatorList(pagination); vo.setFlowToSign(pagination.getTotal()); } vo.setIsTodo(ObjectUtil.isNotEmpty(encodeMap.get(JnpfConst.WORK_FLOWTODO))); if (Boolean.TRUE.equals(vo.getIsTodo())) { if (ObjectUtil.isNotEmpty(taskTo.getFlowTodoType())) { pagination.setFlowCategory(String.join(",", taskTo.getFlowTodoType())); } pagination.setCategory(CategoryEnum.TODO.getType()); flowUtil.getOperatorList(pagination); vo.setFlowTodo(pagination.getTotal()); } vo.setIsDoing(ObjectUtil.isNotEmpty(encodeMap.get(JnpfConst.WORK_FLOWDOING))); if (Boolean.TRUE.equals(vo.getIsDoing())) { if (ObjectUtil.isNotEmpty(taskTo.getFlowDoingType())) { pagination.setFlowCategory(String.join(",", taskTo.getFlowDoingType())); } pagination.setCategory(CategoryEnum.DOING.getType()); flowUtil.getOperatorList(pagination); vo.setFlowDoing(pagination.getTotal()); } vo.setIsDone(ObjectUtil.isNotEmpty(encodeMap.get(JnpfConst.WORK_FLOWDONE))); if (Boolean.TRUE.equals(vo.getIsDone())) { if (ObjectUtil.isNotEmpty(taskTo.getFlowDoneType())) { pagination.setFlowCategory(String.join(",", taskTo.getFlowDoneType())); } flowUtil.getRecordList(pagination); vo.setFlowDone(pagination.getTotal()); } vo.setIsCirculate(ObjectUtil.isNotEmpty(encodeMap.get(JnpfConst.WORK_FLOWCIRCULATE))); if (Boolean.TRUE.equals(vo.getIsCirculate())) { if (ObjectUtil.isNotEmpty(taskTo.getFlowCirculateType())) { pagination.setFlowCategory(String.join(",", taskTo.getFlowCirculateType())); } circulateMapper.getList(pagination); vo.setFlowCirculate(pagination.getTotal()); } return vo; } @Override public FlowTodoVO getFlowTodo(TaskPagination pagination) { FlowTodoVO flowTodoVO = new FlowTodoVO(); String appCode = RequestContext.getAppCode(); String category = pagination.getCategory(); pagination.setSystemId(serviceUtil.getSystemCodeById(appCode)); if (Objects.equals(JnpfConst.MAIN_SYSTEM_CODE, appCode)) { appCode = JnpfConst.WORK_FLOW_CODE; } boolean isPc = RequestContext.isOrignPc(); String webType = isPc ? JnpfConst.WEB : JnpfConst.APP; SystemEntity systemEntity = serviceUtil.getInfoByEnCode(appCode); AuthorizeVO authorize = serviceUtil.getAuthorizeByUser(); List moduleList = authorize.getModuleList().stream(). filter(e -> Objects.equals(e.getSystemId(), systemEntity.getId()) && Objects.equals(webType, e.getCategory())) .collect(Collectors.toList()); Map> encodeMap = moduleList.stream().collect(Collectors.groupingBy(ModuleModel::getEnCode)); Map flowType = ImmutableMap.of( CategoryEnum.SIGN.getType(), JnpfConst.WORK_FLOWSIGN, CategoryEnum.TODO.getType(), JnpfConst.WORK_FLOWTODO, CategoryEnum.DOING.getType(), JnpfConst.WORK_FLOWDOING ); String module = flowType.get(category); flowTodoVO.setIsAuthorize(ObjectUtil.isNotEmpty(encodeMap.get(module))); if (Boolean.TRUE.equals(flowTodoVO.getIsAuthorize())) { List waitList = flowUtil.getOperatorList(pagination); List list = new ArrayList<>(); for (OperatorVo operatorVo : waitList) { TaskFlowTodoVO vo = JsonUtil.getJsonToBean(operatorVo, TaskFlowTodoVO.class); vo.setTaskNodeId(operatorVo.getNodeCode()); vo.setTaskOperatorId(operatorVo.getId()); vo.setType(2); list.add(vo); } flowTodoVO.setList(list); } return flowTodoVO; } }