diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java index fc3e526a..ba3628c0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task; -import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; -import cn.iocoder.yudao.module.bpm.controller.admin.oa.BpmOALeaveController; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.attachment.BpmOAAttachmentReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmProcessInstancePrintDataReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmProcessInstancePrintDataRespVO; @@ -12,16 +10,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO; -import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALeaveDO; -import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAPetitionDO; -import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementDO; -import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASealDO; -import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALeaveMapper; -import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAPetitionMapper; -import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAReimbursementMapper; -import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOASealMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; -import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.service.financialpayment.FinancialPaymentService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.bpm.service.oa.BpmOAAttachmentService; @@ -36,26 +25,21 @@ import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.validation.Valid; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Tag(name = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请” +@Tag(name = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次"申请" @RestController @RequestMapping("/bpm/process-instance") @Validated @@ -78,6 +62,9 @@ public class BpmProcessInstanceController { @Resource private FinancialPaymentService financialPaymentService; + @Resource + private BpmOAAttachmentService bpmOAAttachmentService; + @GetMapping("/my-page") @Operation(summary = "获得我的实例分页列表", description = "在【我的流程】菜单中,进行调用") @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')") @@ -210,69 +197,14 @@ public class BpmProcessInstanceController { return success(processInstanceService.getOAReportPrintData(reqVO)); } - private final Map entityTypeMap = new ConcurrentHashMap<>(); - - @PostConstruct - public void init() { - // 注册支持的实体类型 - entityTypeMap.put("oa_reimbursement", new ArrayList>(Arrays.asList(BpmOAReimbursementDO.class, BpmOAReimbursementMapper.class))); - entityTypeMap.put("oa_seal", new ArrayList>(Arrays.asList(BpmOASealDO.class, BpmOASealMapper.class))); - entityTypeMap.put("oa_contract", new ArrayList>(Arrays.asList(BpmOASealDO.class, BpmOASealMapper.class))); - entityTypeMap.put("oa_leave", new ArrayList>(Arrays.asList(BpmOALeaveDO.class, BpmOALeaveMapper.class))); - entityTypeMap.put("oa_cash", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_overtime", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_regular", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_shiftjobs", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - - entityTypeMap.put("oa_second", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_evection", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_procure", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_procure_pay", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_imprest", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_incentive", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("work_task", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_entry", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_overtime", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - - entityTypeMap.put("oa_regular", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_incentive", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_salary", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_go_out", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_salary_adjustment", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_petition", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_business_card", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_hire", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_business_card", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_business_hospitality", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_finance", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_invoice", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_replacementCard", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_project", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_payment", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_expenses", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_loan", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_receipt", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - entityTypeMap.put("oa_refund", new ArrayList>(Arrays.asList(BpmOAPetitionDO.class, BpmOAPetitionMapper.class))); - } - - @Resource - private BpmOAAttachmentService bpmOAAttachmentService; @PostMapping("/uploadAttachment") + @Operation(summary = "更新流程附件") + @DataPermission(enable = false) public CommonResult uploadAttachment(@Valid @RequestBody BpmOAAttachmentReqVO reqVO) { - // 解析实体类型 - List> entityClazzs = resolveEntityType(reqVO.getProcessType()); - // 调用通用服务 + // 通过服务层解析实体类型 + List> entityClazzs = bpmOAAttachmentService.resolveEntityType(reqVO.getProcessType()); + // 调用服务层更新附件 bpmOAAttachmentService.updateAttachment(entityClazzs, reqVO.getProcessBusinessId(), reqVO.getFileItems()); return success("附件更新成功"); } - - private List> resolveEntityType(String typeName) { - List> entityClazzs = entityTypeMap.get(typeName); - if (entityClazzs == null) { - // 添加日志记录以便更好地调试 - log.error("不支持的流程类型: {}", typeName); - throw new ServiceException(500, "不支持的流程类型: " + typeName); - } - return entityClazzs; - } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAAttachmentService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAAttachmentService.java index eef030cc..b57a2c53 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAAttachmentService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAAttachmentService.java @@ -4,15 +4,23 @@ import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; import java.util.List; +/** + * BPM OA 附件服务接口 + */ public interface BpmOAAttachmentService { /** * 更新业务实体的附件信息 - * @param entityClazzs 业务实体 + * @param entityClazzs 业务实体类列表 * @param entityId 业务ID * @param fileItems 附件数据 */ void updateAttachment(List> entityClazzs, Long entityId, List fileItems); - + /** + * 通过流程代码解析实体类型 + * @param processCode 流程标识码 + * @return 实体类和Mapper类的列表 + */ + List> resolveEntityType(String processCode); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAAttachmentServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAAttachmentServiceImpl.java index 429c8169..8d9688cd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAAttachmentServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAAttachmentServiceImpl.java @@ -1,47 +1,98 @@ package cn.iocoder.yudao.module.bpm.service.oa; +import cn.hutool.core.util.ClassUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; +import cn.iocoder.yudao.module.bpm.dal.dataobject.processmapping.BpmProcessMappingConfigDO; +import cn.iocoder.yudao.module.bpm.framework.core.util.ReflectionInvoker; +import cn.iocoder.yudao.module.bpm.service.processmapping.ProcessMappingConfigService; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import liquibase.pro.packaged.T; import lombok.extern.slf4j.Slf4j; -import org.flowable.common.engine.impl.persistence.entity.EntityManager; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.List; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_MAPPING_CONFIG_NOT_EXISTS; + @Service @Validated @Slf4j public class BpmOAAttachmentServiceImpl implements BpmOAAttachmentService { + @Resource + private ProcessMappingConfigService processMappingConfigService; + /** * 更新业务实体的附件信息 - * @param entityClazzs 业务实体 + * @param entityClazzs 业务实体类列表 * @param entityId 业务ID * @param fileItems 附件数据 */ + @Override public void updateAttachment(List> entityClazzs, Long entityId, List fileItems) { try { - // 1. 获取实体, 赋值实体类 - Class doClass = entityClazzs.get(0) ; + // 1. 获取实体类并创建实例 + Class doClass = entityClazzs.get(0); Object entity = doClass.getDeclaredConstructor().newInstance(); - Method setIdMethod = doClass.getMethod("setId", Long.class) ; + + // 2. 使用反射设置实体属性 + Method setIdMethod = doClass.getMethod("setId", Long.class); setIdMethod.invoke(entity, entityId); - Method setFileItems = doClass.getMethod("setFileItems", List.class) ; + Method setFileItems = doClass.getMethod("setFileItems", List.class); setFileItems.invoke(entity, fileItems); - //获取MyBatist的操作类实体 - Class mapperClass = entityClazzs.get(1) ; - BaseMapper mapper = (BaseMapper) SpringUtil.getBean(mapperClass); - mapper.updateById(entity); + + // 3. 获取Mapper实例并调用updateById方法 + Class mapperClass = entityClazzs.get(1); + Object mapperBean = SpringUtil.getBean(mapperClass); + + // 4. 使用ReflectionInvoker调用updateById方法 + ReflectionInvoker.invokeMapperMethod(mapperBean, "updateById", Object.class, entity); + + log.debug("[updateAttachment][附件更新成功] entityClass={}, entityId={}, fileCount={}", + doClass.getSimpleName(), entityId, fileItems != null ? fileItems.size() : 0); + } catch (Exception e) { - log.error(e.getMessage()); - throw new ServiceException(500, "系统异常,请联系管理员"); + log.error("[updateAttachment][附件更新失败] entityId={}, error={}", entityId, e.getMessage(), e); + throw new ServiceException(500, "附件更新失败,请联系管理员"); + } + } + + /** + * 通过流程代码动态解析实体类型 + * @param processCode 流程标识码 + * @return 实体类和Mapper类的列表 + */ + @Override + public List> resolveEntityType(String processCode) { + try { + // 1. 获取流程映射配置 + BpmProcessMappingConfigDO config = processMappingConfigService.getProcessMappingConfigByCode(processCode); + if (config == null) { + log.error("[resolveEntityType][流程映射配置不存在] processCode={}", processCode); + throw exception(PROCESS_MAPPING_CONFIG_NOT_EXISTS); + } + + // 2. 动态加载实体类和Mapper类 + Class entityClass = ClassUtil.loadClass(config.getEntityClass()); + Class mapperClass = ClassUtil.loadClass(config.getMapperClass()); + + // 3. 验证Mapper类是否可获取Bean实例 + SpringUtil.getBean(mapperClass); + + log.debug("[resolveEntityType][成功解析流程类型] processCode={}, entityClass={}, mapperClass={}", + processCode, config.getEntityClass(), config.getMapperClass()); + + return Arrays.asList(entityClass, mapperClass); + + } catch (Exception e) { + log.error("[resolveEntityType][解析流程类型失败] processCode={}", processCode, e); + throw new ServiceException(500, String.format("不支持的流程类型: %s, 错误信息: %s", processCode, e.getMessage())); } } }