diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java index 5c644448f..81c96db24 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmProcessInstanceController.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.validation.Valid; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Api(tags = "流程实例") // 流程实例,通过流程定义创建的一次“申请” @@ -28,8 +29,8 @@ public class BpmProcessInstanceController { @PostMapping("/create") @ApiOperation("新建流程实例") public CommonResult createProcessInstance(@Valid @RequestBody BpmProcessInstanceCreateReqVO createReqVO) { -// return success(processInstanceService.createProcessInstance(getLoginUserId(), createReqVO)); - processInstanceService.getMyProcessInstancePage(getLoginUserId()); + return success(processInstanceService.createProcessInstance(getLoginUserId(), createReqVO)); +// processInstanceService.getMyProcessInstancePage(getLoginUserId()); return null; } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionDO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionDO.java index fda5c4b1a..ed4b4a9bd 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionDO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/definition/BpmProcessDefinitionDO.java @@ -9,7 +9,7 @@ import org.activiti.engine.repository.ProcessDefinition; /** * Bpm 流程定义的拓展表 - * 主要解决 主要进行 Activiti {@link ProcessDefinition} 不支持拓展字段,所以新建拓展表 + * 主要解决 Activiti {@link ProcessDefinition} 不支持拓展字段,所以新建拓展表 * * @author 芋道源码 */ diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java new file mode 100644 index 000000000..256f28f8d --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/BpmProcessInstanceExtDO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task; + +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.ProcessInstanceResultEnum; +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.ProcessInstanceStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; +import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.runtime.ProcessInstance; + +/** + * Bpm 流程实例的拓展表 + * 主要解决 Activiti {@link ProcessInstance} 和 {@link HistoricProcessInstance} 不支持拓展字段,所以新建拓展表 + * + * @author 芋道源码 + */ +@TableName(value = "bpm_process_instance_ext", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BpmProcessInstanceExtDO extends BaseDO { + + /** + * 发起流程的用户编号 + * + * 冗余 {@link HistoricProcessInstance#getStartUserId()} + */ + private Long userId; + /** + * 流程实例的名字 + * + * 冗余 {@link ProcessInstance#getName()} 为了筛选 + */ + private String name; + /** + * 流程实例的编号 + * + * 关联 {@link ProcessInstance#getId()} + */ + private String processInstanceId; + /** + * 流程实例的状态 + * + * 枚举 {@link ProcessInstanceStatusEnum} + */ + private Integer status; + /** + * 结果 + * + * 枚举 {@link ProcessInstanceResultEnum} + */ + private Integer result; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/package-info.java deleted file mode 100644 index 0cb016039..000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/dal/dataobject/task/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * TODO 芋艿:工作流创建后的定义 - */ -package cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.task; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/FlowStatusEnum.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/FlowStatusEnum.java deleted file mode 100644 index 68f10fe2d..000000000 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/FlowStatusEnum.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.adminserver.modules.bpm.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 流程状态 - */ -@Getter -@AllArgsConstructor -public enum FlowStatusEnum { - - HANDLE(1, "处理中"), - - PASS(2, "审批通过"), - - REJECTED(3, "审批不通过"); - - /** - * 状态 - */ - private final Integer status; - - - /** - * 描述 - */ - private final String desc; -} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/ProcessInstanceResultEnum.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/ProcessInstanceResultEnum.java new file mode 100644 index 000000000..d59c9d958 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/ProcessInstanceResultEnum.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.adminserver.modules.bpm.enums.task; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 流程实例的结果 + * + * @author jason + */ +@Getter +@AllArgsConstructor +public enum ProcessInstanceResultEnum { + + PROCESS(1, "处理中"), + PASS(2, "通过"), + REJECT(3, "不通过"), + CANCEL(4, "撤销"); + + /** + * 结果 + */ + private final Integer result; + /** + * 描述 + */ + private final String desc; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/ProcessInstanceStatusEnum.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/ProcessInstanceStatusEnum.java new file mode 100644 index 000000000..9413f539c --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/task/ProcessInstanceStatusEnum.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.adminserver.modules.bpm.enums.task; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 流程实例的结果 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum ProcessInstanceStatusEnum { + + RUNNING(1, "进行中"), + FINISH(2, "已完成"); + + /** + * 状态 + */ + private final Integer result; + /** + * 描述 + */ + private final String desc; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/LeaveApplyEndProcessor.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/LeaveApplyEndProcessor.java index 605c2fb83..cef077924 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/LeaveApplyEndProcessor.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/LeaveApplyEndProcessor.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.service.oa; import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.OALeaveDO; import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa.OALeaveMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.FlowStatusEnum; +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.ProcessInstanceResultEnum; import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.ExecutionListener; import org.springframework.stereotype.Component; @@ -29,9 +29,9 @@ public class LeaveApplyEndProcessor implements ExecutionListener { OALeaveDO updateDo = new OALeaveDO(); updateDo.setId(Long.valueOf(businessKey)); if (Objects.equals(approved, true)) { - updateDo.setStatus(FlowStatusEnum.PASS.getStatus()); + updateDo.setStatus(ProcessInstanceResultEnum.PASS.getResult()); } else { - updateDo.setStatus(FlowStatusEnum.REJECTED.getStatus()); + updateDo.setStatus(ProcessInstanceResultEnum.REJECT.getResult()); } leaveMapper.updateById(updateDo); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/OALeaveServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/OALeaveServiceImpl.java index dabc38c62..cf6f1199a 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/OALeaveServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/OALeaveServiceImpl.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.oa.vo.*; import cn.iocoder.yudao.adminserver.modules.bpm.convert.oa.OALeaveConvert; import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.leave.OALeaveDO; import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.oa.OALeaveMapper; -import cn.iocoder.yudao.adminserver.modules.bpm.enums.FlowStatusEnum; +import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.ProcessInstanceResultEnum; import cn.iocoder.yudao.adminserver.modules.bpm.service.oa.OALeaveService; import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.dept.SysPostMapper; @@ -62,7 +62,7 @@ public class OALeaveServiceImpl implements OALeaveService { public Long createLeave(OALeaveCreateReqVO createReqVO) { // 插入 OA 请假单 OALeaveDO leave = OALeaveConvert.INSTANCE.convert(createReqVO); - leave.setStatus(FlowStatusEnum.HANDLE.getStatus()); + leave.setStatus(ProcessInstanceResultEnum.PROCESS.getResult()); // TODO @jason:应该是存储 userId?? leave.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername()); leaveMapper.insert(leave); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java index c136523f4..c7b13e885 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java @@ -13,7 +13,6 @@ import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricProcessInstanceQuery; -import org.activiti.engine.impl.identity.Authentication; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; @@ -70,12 +69,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } - // 设置流程发起人 - Authentication.setAuthenticatedUserId(String.valueOf(userId)); - // 创建流程实例 Map variables = createReqVO.getVariables(); - variables.put("INITIATOR", userId); // TODO 芋艿:初始化人员 ProcessInstance instance = runtimeService.startProcessInstanceById(createReqVO.getProcessDefinitionId(), variables); // 添加初始的评论 TODO 芋艿:在思考下 @@ -97,6 +92,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // id title 所属流程 当前审批环节 状态 结果 创建时间 提交申请时间 【标题、状态】「ActBusiness」 // id title 流程类别 流程版本 提交时间 流程状态 耗时 当前节点 办理 【标题、提交时间】「HistoricProcessInstanceQuery」 + // id title 所属流程 流程类别 创建时间 状态 当前审批环节 【标题、状态】 + runtimeService.createProcessInstanceQuery().list(); HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery() .startedBy(String.valueOf(userId)) // 发起人是自己 diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java index 2c4dfc4c6..6cfbba177 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java @@ -25,7 +25,9 @@ public interface WebFilterOrderEnum { // Spring Security Filter 默认为 -100,可见 org.springframework.boot.autoconfigure.security.SecurityProperties 配置属性类 - int TENANT_SECURITY_FILTER = -99; // 需要保证在 Spring Security 过滤器后 + int TENANT_SECURITY_FILTER = -99; // 需要保证在 Spring Security 过滤器后面 + + int ACTIVITI_FILTER = -98; // 需要保证在 Spring Security 过滤后面 int DEMO_FILTER = Integer.MAX_VALUE; diff --git a/yudao-framework/yudao-spring-boot-starter-activiti/pom.xml b/yudao-framework/yudao-spring-boot-starter-activiti/pom.xml index c2b403f62..75a4d87ce 100644 --- a/yudao-framework/yudao-spring-boot-starter-activiti/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-activiti/pom.xml @@ -37,6 +37,14 @@ yudao-common + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + org.mybatis mybatis @@ -72,6 +80,7 @@ activiti-image-generator ${activiti.version} + diff --git a/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/config/YudaoActivitiConfiguration.java b/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/config/YudaoActivitiConfiguration.java index e3b802c15..f65c2a23c 100644 --- a/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/config/YudaoActivitiConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/config/YudaoActivitiConfiguration.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.framework.activiti.config; +import cn.iocoder.yudao.framework.activiti.core.web.ActivitiWebFilter; +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import org.activiti.image.ProcessDiagramGenerator; import org.activiti.image.impl.DefaultProcessDiagramGenerator; import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer; import org.apache.ibatis.session.SqlSessionFactory; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -26,4 +29,12 @@ public class YudaoActivitiConfiguration { return springProcessEngineConfiguration -> springProcessEngineConfiguration.setSqlSessionFactory(sqlSessionFactory); } + @Bean + public FilterRegistrationBean activitiWebFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new ActivitiWebFilter()); + registrationBean.setOrder(WebFilterOrderEnum.ACTIVITI_FILTER); + return registrationBean; + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java b/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java new file mode 100644 index 000000000..2a6c97b46 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.framework.activiti.core.util; + +import org.activiti.engine.impl.identity.Authentication; + +/** + * Activiti 工具类 + * + * @author 芋道源码 + */ +public class ActivitiUtils { + + public static void setAuthenticatedUserId(Long userId) { + Authentication.setAuthenticatedUserId(String.valueOf(userId)); + } + + public static void clearAuthenticatedUserId() { + Authentication.setAuthenticatedUserId(null); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/web/ActivitiWebFilter.java b/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/web/ActivitiWebFilter.java new file mode 100644 index 000000000..cb190f1fa --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/web/ActivitiWebFilter.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.activiti.core.web; + +import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * Activiti Web 过滤器,将 userId 设置到 {@link org.activiti.engine.impl.identity.Authentication} 中 + * + * @author 芋道源码 + */ +public class ActivitiWebFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException { + try { + // 设置工作流的用户 + Long userId = SecurityFrameworkUtils.getLoginUserId(); + if (userId != null) { + ActivitiUtils.setAuthenticatedUserId(userId); + } + // 过滤 + chain.doFilter(request, response); + } finally { + // 清理 + ActivitiUtils.clearAuthenticatedUserId(); + } + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java index f008acf81..93f163086 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java @@ -98,15 +98,6 @@ public class SecurityFrameworkUtils { // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息 WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); -// // TODO @jason:使用 userId 会不会更合适哈? -// // TODO @芋艿:activiti 需要使用 ttl 上下文 -// // TODO @jason:清理问题 -// if (Objects.equals(UserTypeEnum.ADMIN.getValue(), loginUser.getUserType())) { -// org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername()); -// } -// // TODO @芋道源码 该值被赋值给 user task 中assignee , username 显示更直白一点 -// // TODO @jason:有办法设置 userId,然后 activiti 有地方读取到 username 么?毕竟 username 只是 User 的登陆账号,并不能绝对像 userId 代表一个用户 -// org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(loginUser.getUsername()); } }