diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java index 817a7a307..a18d8cf9c 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java @@ -35,7 +35,7 @@ public class WfDefinitionConfig extends BaseEntity { /** * 流程定义ID */ - private String definitionId; + private Long definitionId; /** * 流程KEY diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java index 543638239..4b1fc7cba 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java @@ -35,8 +35,8 @@ public class WfDefinitionConfigBo extends BaseEntity { /** * 流程定义ID */ - @NotBlank(message = "流程定义ID不能为空", groups = {AddGroup.class}) - private String definitionId; + @NotNull(message = "流程定义ID不能为空", groups = {AddGroup.class}) + private Long definitionId; /** * 流程KEY diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java index 1d7b51d8f..9b9d09a76 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java @@ -3,7 +3,6 @@ package org.dromara.workflow.domain.vo; import lombok.Data; import org.dromara.common.translation.annotation.Translation; import org.dromara.common.translation.constant.TransConstant; -import org.dromara.warm.flow.core.enums.FlowStatus; import java.io.Serial; import java.io.Serializable; @@ -170,14 +169,13 @@ public class FlowHisTaskVo implements Serializable { */ private String flowCode; + /** + * 流程版本号 + */ + private String version; + /** * 运行时长 */ private String runDuration; - - public void setFlowStatus(String flowStatus) { - this.flowStatus = flowStatus; - // TODO 建议前端使用字典 - this.flowStatusName = FlowStatus.getValueByKey(flowStatus); - } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java index 4b56e90db..806d8c271 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java @@ -124,6 +124,11 @@ public class FlowTaskVo implements Serializable { @Translation(type = TransConstant.TASK_ID_TO_ASSIGNEE, mapper = "id") private String transactorNames; + /** + * 抄送人id + */ + private String processedBy; + /** * 办理人类型 */ diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java index d3cee928a..89ed36df9 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java @@ -40,7 +40,7 @@ public class WfDefinitionConfigVo implements Serializable { * 流程定义ID */ @ExcelProperty(value = "流程定义ID") - private String definitionId; + private Long definitionId; /** * 流程KEY diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java index fe5cf7ad3..0ca50355c 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java @@ -79,5 +79,5 @@ public interface IWfDefinitionConfigService { * @param ids 流程定义id * @return 结果 */ - Boolean deleteByDefIds(Collection ids); + Boolean deleteByDefIds(Collection ids); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java index 64bbf6df2..d40059aae 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java @@ -24,7 +24,9 @@ import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; import org.dromara.workflow.domain.vo.FlowDefinitionVo; import org.dromara.workflow.mapper.FlwDefMapper; import org.dromara.workflow.service.IFlwDefinitionService; +import org.dromara.workflow.service.IWfDefinitionConfigService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @@ -43,6 +45,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { private final FlowDefinitionMapper flowDefinitionMapper; private final FlwDefMapper flwDefMapper; private final FlowHisTaskMapper flowHisTaskMapper; + private final IWfDefinitionConfigService wfDefinitionConfigService; /** * 分页查询 @@ -125,6 +128,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { * @param ids 流程定义id */ @Override + @Transactional(rollbackFor = Exception.class) public boolean removeDef(List ids) { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.in(FlowHisTask::getDefinitionId, ids); @@ -139,6 +143,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { } try { defService.removeDef(ids); + wfDefinitionConfigService.deleteByDefIds(ids); } catch (Exception e) { log.error("Error removing flow definitions: {}", e.getMessage(), e); throw new RuntimeException("Failed to remove flow definitions", e); diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java index 59ee1f654..84c820155 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java @@ -158,7 +158,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { wrapper.in(FlowInstance::getDefinitionId, defIdList); } } - wrapper.eq(FlowInstance::getCreateBy, LoginHelper.getUserId()); + wrapper.eq(FlowInstance::getCreateBy, LoginHelper.getUserIdStr()); Page page = flowInstanceMapper.selectPage(pageQuery.build(), wrapper); TableDataInfo build = TableDataInfo.build(); List flowInstanceVos = BeanUtil.copyToList(page.getRecords(), FlowInstanceVo.class); diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java index c6123c998..c102a7dc6 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java @@ -3,6 +3,7 @@ package org.dromara.workflow.service.impl; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; @@ -20,14 +21,9 @@ import org.dromara.warm.flow.core.dto.FlowParams; import org.dromara.warm.flow.core.entity.*; import org.dromara.warm.flow.core.enums.NodeType; import org.dromara.warm.flow.core.enums.SkipType; -import org.dromara.warm.flow.core.service.DefService; -import org.dromara.warm.flow.core.service.InsService; -import org.dromara.warm.flow.core.service.TaskService; -import org.dromara.warm.flow.core.service.UserService; -import org.dromara.warm.flow.orm.entity.FlowHisTask; -import org.dromara.warm.flow.orm.entity.FlowInstance; -import org.dromara.warm.flow.orm.entity.FlowSkip; -import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.warm.flow.core.enums.UserType; +import org.dromara.warm.flow.core.service.*; +import org.dromara.warm.flow.orm.entity.*; import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; import org.dromara.warm.flow.orm.mapper.FlowSkipMapper; import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; @@ -35,6 +31,7 @@ import org.dromara.workflow.common.enums.TaskStatusEnum; import org.dromara.workflow.domain.bo.*; import org.dromara.workflow.domain.vo.FlowHisTaskVo; import org.dromara.workflow.domain.vo.FlowTaskVo; +import org.dromara.workflow.domain.vo.WfCopy; import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; import org.dromara.workflow.handler.FlowProcessEventHandler; import org.dromara.workflow.mapper.FlwTaskMapper; @@ -45,12 +42,10 @@ import org.dromara.workflow.utils.WorkflowUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; +import static org.dromara.common.core.enums.TaskAssigneeEnum.USER; import static org.dromara.workflow.common.constant.FlowConstant.*; /** @@ -74,6 +69,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { private final FlowSkipMapper flowSkipMapper; private final FlowProcessEventHandler flowProcessEventHandler; private final DefService defService; + private final HisTaskService hisTaskService; + private final IdentifierGenerator identifierGenerator; /** * 启动任务 @@ -95,10 +92,15 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { // 业务id variables.put(BUSINESS_KEY, businessKey); WfDefinitionConfigVo wfDefinitionConfigVo = wfDefinitionConfigService.getByTableNameLastVersion(startProcessBo.getTableName()); - if (wfDefinitionConfigVo == null) { + if (wfDefinitionConfigVo == null || wfDefinitionConfigVo.getDefinitionId() == null) { throw new ServiceException("请到流程定义绑定业务表名与流程KEY!"); } - + Long definitionId = wfDefinitionConfigVo.getDefinitionId(); + Definition definition = defService.getById(definitionId); + if (definition == null) { + log.error("流程定义ID【{}】不存在!", definitionId); + throw new ServiceException("请到流程定义ID【" + definitionId + "】不存在!"); + } FlowInstance flowInstance = iFlwInstanceService.instanceByBusinessId(businessKey); if (flowInstance != null) { List taskList = taskService.list(new FlowTask().setInstanceId(flowInstance.getId())); @@ -137,6 +139,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { // 获取任务ID并查询对应的流程任务和实例信息 Long taskId = completeTaskBo.getTaskId(); + // 获取抄送人 + List wfCopyList = completeTaskBo.getWfCopyList(); FlowTask flowTask = flowTaskMapper.selectById(taskId); Instance ins = insService.getById(flowTask.getInstanceId()); @@ -159,9 +163,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { flowParams.handler(userId); flowParams.permissionFlag(WorkflowUtils.permissionList()); flowParams.flowStatus(BusinessStatusEnum.WAITING.getStatus()).hisStatus(TaskStatusEnum.PASS.getStatus()); - // 执行任务跳转,并根据返回的处理人设置下一步处理人 - setHandler(taskService.skip(taskId, flowParams)); + setHandler(taskService.skip(taskId, flowParams), flowTask, wfCopyList); // 更新实例状态为待审核状态 iFlwInstanceService.updateStatus(ins.getId(), BusinessStatusEnum.WAITING.getStatus()); @@ -175,17 +178,20 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { /** * 设置办理人 * - * @param instance 实例 + * @param instance 实例 + * @param task (当前任务)未办理的任务 + * @param wfCopyList 抄送人 */ - private void setHandler(Instance instance) { + private void setHandler(Instance instance, FlowTask task, List wfCopyList) { if (instance == null) { return; } + //添加抄送人 + setCopy(task, wfCopyList); // 根据流程实例ID查询所有关联的任务 List flowTasks = flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) .eq(FlowTask::getInstanceId, instance.getId())); List userList = new ArrayList<>(); - // 遍历任务列表,处理每个任务的办理人 for (FlowTask flowTask : flowTasks) { // 获取与当前任务关联的用户列表 @@ -194,16 +200,53 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { userList.addAll(WorkflowUtils.getUser(associatedUsers, flowTask.getId())); } } - // 批量删除现有任务的办理人记录 userService.deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId)); - // 确保要保存的 userList 不为空 if (CollUtil.isNotEmpty(userList)) { userService.saveBatch(userList); } } + /** + * 添加抄送人 + * + * @param task 任务信息 + * @param wfCopyList 抄送人 + */ + private void setCopy(FlowTask task, List wfCopyList) { + // 添加抄送人记录 + if (CollUtil.isNotEmpty(wfCopyList)) { + FlowHisTask flowHisTask = flowHisTaskMapper.selectOne(new LambdaQueryWrapper<>(FlowHisTask.class).eq(FlowHisTask::getTaskId, task.getId())); + FlowNode flowNode = new FlowNode(); + flowNode.setNodeCode(flowHisTask.getTargetNodeCode()); + flowNode.setNodeName(flowHisTask.getTargetNodeName()); + //生成新的任务id + long taskId = identifierGenerator.nextId(null).longValue(); + task.setId(taskId); + task.setNodeName("【抄送】" + task.getNodeName()); + FlowParams flowParams = FlowParams.build(); + flowParams.skipType(SkipType.NONE.getKey()); + flowParams.hisStatus(TaskStatusEnum.PASS.getStatus()); + flowParams.handler(LoginHelper.getUserIdStr()); + flowParams.message("【抄送给】" + StreamUtils.join(wfCopyList, WfCopy::getUserName)); + HisTask hisTask = hisTaskService.setSkipHisTask(task, flowNode, flowParams); + hisTaskService.save(hisTask); + //保存抄送人员 + List userList = new ArrayList<>(); + for (WfCopy wfCopy : wfCopyList) { + FlowUser flowUser = new FlowUser(); + flowUser.setType(String.valueOf(4)); + flowUser.setProcessedBy(USER.getCode() + wfCopy.getUserId()); + flowUser.setAssociated(taskId); + userList.add(flowUser); + } + if (CollUtil.isNotEmpty(userList)) { + userService.saveBatch(userList); + } + } + } + /** * 查询当前用户的待办任务 * @@ -230,7 +273,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { public TableDataInfo getPageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); - queryWrapper.in("t.approver", LoginHelper.getUserId()); + queryWrapper.in("t.approver", LoginHelper.getUserIdStr()); Page page = flwTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper); return TableDataInfo.build(page); } @@ -271,6 +314,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { @Override public TableDataInfo getPageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery) { QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.in("t.processed_by", LoginHelper.getUserIdStr()); Page page = flwTaskMapper.getTaskCopyByPage(pageQuery.build(), queryWrapper); return TableDataInfo.build(page); } @@ -320,7 +364,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { flowParams.nodeCode(bo.getNodeCode()); flowParams.permissionFlag(WorkflowUtils.permissionList()); Instance instance = taskService.skip(taskId, flowParams); - setHandler(instance); + setHandler(instance, flowTasks.get(0), null); flowProcessEventHandler.processHandler(definition.getFlowCode(), instance.getBusinessId(), BusinessStatusEnum.BACK.getStatus(), false); return true; @@ -389,7 +433,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { if (StringUtils.isBlank(taskIds)) { return null; } - List userList = userService.getByAssociateds(List.of(Long.valueOf(taskIds))); + List userList = userService.getByAssociateds(List.of(Long.valueOf(taskIds)) + , UserType.APPROVAL.getKey(), UserType.TRANSFER.getKey(), UserType.DEPUTE.getKey()); // 获取处理用户的昵称并将其合并为一个字符串 return WorkflowUtils.getHandlerUser(userList).stream() .map(UserDTO::getNickName) @@ -407,7 +452,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService, AssigneeService { if (CollUtil.isEmpty(taskIdList)) { return Collections.emptyList(); } - List userList = userService.getByAssociateds(taskIdList); + List userList = userService.getByAssociateds(taskIdList + , UserType.APPROVAL.getKey(), UserType.TRANSFER.getKey(), UserType.DEPUTE.getKey()); return WorkflowUtils.getHandlerUser(userList); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java index b2ffb9ef9..ccf7127d7 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java @@ -111,7 +111,7 @@ public class WfDefinitionConfigServiceImpl implements IWfDefinitionConfigService } @Override - public Boolean deleteByDefIds(Collection ids) { + public Boolean deleteByDefIds(Collection ids) { return baseMapper.delete(new LambdaQueryWrapper().in(WfDefinitionConfig::getDefinitionId, ids)) > 0; } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml index 791ea873c..b280fb89e 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml +++ b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml @@ -65,12 +65,17 @@ d.flow_code, d.form_custom, d.form_path, + d.version, uu.processed_by, uu.type from flow_task as t left join flow_user uu on uu.associated = t.id left join flow_definition d on t.definition_id = d.id - left join flow_instance i on t.instance_id = i.id where t.node_type = 1 and t.del_flag = '0' and uu.del_flag = '0') t + left join flow_instance i on t.instance_id = i.id where + t.node_type = 1 and + t.del_flag = '0' and + uu.del_flag = '0' and + uu.type in ('1','2','3')) t ${ew.getCustomSqlSegment} @@ -97,7 +102,8 @@ b.business_id, c.form_path, c.flow_name, - c.flow_code + c.flow_code, + c.version from flow_his_task a left join flow_instance b on a.instance_id = b.id left join flow_definition c on a.definition_id = c.id where @@ -109,19 +115,22 @@ select * from ( select b.id , - b.flow_status, - b.business_id, + a.processed_by, + c.flow_status, + c.business_id, a.create_time, b.node_name, b.node_code, d.flow_name, - d.flow_code + d.flow_code, + d.version from flow_user a - left join flow_instance b on a.associated = b.id - left join flow_definition d on b.definition_id=d.id + left join flow_his_task b on a.associated = b.task_id + left join flow_instance c on b.instance_id = c.id + left join flow_definition d on c.definition_id=d.id where - a.type = 4 and a.del_flag = '0' and b.del_flag = '0' + a.type = '4' and a.del_flag = '0' and b.del_flag = '0' and d.del_flag = '0' ) t ${ew.getCustomSqlSegment}