Commit 1bc4bdac0c27bf7894838ae4a122ff1b85c00b42
1 parent
baab642d
工作流的 code review
Showing
7 changed files
with
32 additions
and
20 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/LeaveApplyEndProcessor.java
| ... | ... | @@ -28,6 +28,7 @@ public class LeaveApplyEndProcessor implements ExecutionListener { |
| 28 | 28 | final Object approved = delegateExecution.getVariable("approved"); |
| 29 | 29 | OALeaveDO updateDo = new OALeaveDO(); |
| 30 | 30 | updateDo.setId(Long.valueOf(businessKey)); |
| 31 | + // TODO @jason:代码的格式哈。} else { 。另外,这里可以简化成,二元表达式 | |
| 31 | 32 | if (Objects.equals(approved, true)) { |
| 32 | 33 | updateDo.setStatus(FlowStatusEnum.PASS.getStatus()); |
| 33 | 34 | }else{ | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/oa/impl/OALeaveServiceImpl.java
| ... | ... | @@ -26,11 +26,9 @@ import org.springframework.transaction.annotation.Transactional; |
| 26 | 26 | import org.springframework.validation.annotation.Validated; |
| 27 | 27 | |
| 28 | 28 | import javax.annotation.Resource; |
| 29 | -import javax.validation.constraints.NotNull; | |
| 30 | 29 | import java.util.*; |
| 31 | 30 | |
| 32 | 31 | import static cn.iocoder.yudao.adminserver.modules.bpm.enums.oa.OAErrorCodeConstants.*; |
| 33 | -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.POST_CODE_DUPLICATE; | |
| 34 | 32 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 35 | 33 | |
| 36 | 34 | /** |
| ... | ... | @@ -116,6 +114,7 @@ public class OALeaveServiceImpl implements OALeaveService { |
| 116 | 114 | } |
| 117 | 115 | } |
| 118 | 116 | |
| 117 | + // TODO @jason:要不,请假不支持删除,只支持取消? | |
| 119 | 118 | @Override |
| 120 | 119 | public void deleteLeave(Long id) { |
| 121 | 120 | // 校验存在 | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/TaskService.java
| ... | ... | @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | import javax.servlet.http.HttpServletResponse; |
| 7 | 7 | import java.util.List; |
| 8 | 8 | |
| 9 | - | |
| 9 | +// TODO @jason:前缀 | |
| 10 | 10 | /** |
| 11 | 11 | * 用户任务服务接口 |
| 12 | 12 | */ |
| ... | ... | @@ -25,14 +25,13 @@ public interface TaskService { |
| 25 | 25 | */ |
| 26 | 26 | void claimTask(String taskId); |
| 27 | 27 | |
| 28 | - | |
| 28 | + // TODO @jason:可以把实现方法的注释,统一写到接口里 | |
| 29 | 29 | /** |
| 30 | 30 | * 办理完成用户任务 |
| 31 | 31 | * @param taskReq 任务参数, 包含任务的参数,和 评论 |
| 32 | 32 | */ |
| 33 | 33 | void completeTask(TaskReqVO taskReq); |
| 34 | 34 | |
| 35 | - | |
| 36 | 35 | /** |
| 37 | 36 | * 根据任务id, 查询已经完成的用户任务,未完成的用户任务 |
| 38 | 37 | * @param taskQuery 查询参数 一般 taskId |
| ... | ... | @@ -45,7 +44,6 @@ public interface TaskService { |
| 45 | 44 | */ |
| 46 | 45 | List<TaskStepVO> getHistorySteps(String processInstanceId); |
| 47 | 46 | |
| 48 | - | |
| 49 | 47 | /** |
| 50 | 48 | * 获取用户任务的 formKey, 对应外置表单, 需要根据formKey 对应业务表单 |
| 51 | 49 | * @param taskQuery 查询参数 ,一般taskId | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/workflow/impl/TaskServiceImpl.java
| ... | ... | @@ -174,21 +174,24 @@ public class TaskServiceImpl implements TaskService { |
| 174 | 174 | public void getHighlightImg(String processInstanceId, HttpServletResponse response) { |
| 175 | 175 | // 查询历史 |
| 176 | 176 | //TODO 云扬四海 貌似流程结束后,点击审批进度会报错 |
| 177 | - HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); | |
| 178 | - // 如果有结束时间 | |
| 177 | + // TODO @Li:一些 historyService 的查询,貌似比较通用,是不是抽一些小方法出来 | |
| 178 | + HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); | |
| 179 | + // 如果有结束时间 TODO @Li:如果查询不到,是不是抛出一个业务异常比较好哈? | |
| 179 | 180 | if (hpi == null) { |
| 180 | 181 | return; |
| 181 | 182 | } |
| 182 | 183 | // 没有结束时间。说明流程在执行过程中 |
| 184 | + // TODO @Li:一些 runtimeService 的查询,貌似比较通用,是不是抽一些小方法出来 | |
| 183 | 185 | ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); |
| 184 | - BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId()); | |
| 186 | + BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId()); // TODO @Li:这块和下面的逻辑比较相关,可以在后面一点查询。 | |
| 185 | 187 | List<String> highLightedActivities = new ArrayList<>(); |
| 186 | 188 | |
| 187 | 189 | List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId) |
| 188 | - .orderByHistoricActivityInstanceId().asc().list(); | |
| 190 | + .orderByHistoricActivityInstanceId().asc().list(); // TODO @Li:这块和下面的逻辑比较相关,可以在后面一点查询。 | |
| 189 | 191 | // 获取所有活动节点 |
| 190 | 192 | List<HistoricActivityInstance> finishedInstances = historyService.createHistoricActivityInstanceQuery() |
| 191 | 193 | .processInstanceId(processInstanceId).finished().list(); |
| 194 | + // TODO @Li:highLightedActivities 结果,可以使用 CollUtils.buildList() 方法。即使不用,也应该用 stream。简洁很重要。 | |
| 192 | 195 | for (HistoricActivityInstance hai : finishedInstances) { |
| 193 | 196 | highLightedActivities.add(hai.getActivityId()); |
| 194 | 197 | } |
| ... | ... | @@ -199,6 +202,7 @@ public class TaskServiceImpl implements TaskService { |
| 199 | 202 | List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, historicActivityInstances); |
| 200 | 203 | |
| 201 | 204 | //设置"宋体" |
| 205 | + // TODO @Li:Service 返回 bytes,最终 Controller 去写 | |
| 202 | 206 | try (InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, highLightedActivities, highLightedFlowIds, |
| 203 | 207 | "宋体", "宋体", "宋体")){ |
| 204 | 208 | String picName = hpi.getProcessDefinitionName()+".svg"; |
| ... | ... | @@ -207,9 +211,9 @@ public class TaskServiceImpl implements TaskService { |
| 207 | 211 | } catch (IOException e) { |
| 208 | 212 | log.error(ExceptionUtils.getStackTrace(e)); |
| 209 | 213 | } |
| 210 | - | |
| 211 | 214 | } |
| 212 | 215 | |
| 216 | + // TODO @Li:参考 ServletUtils 方法。如果没有满足的,可以在写一个。 | |
| 213 | 217 | private void responseImage(HttpServletResponse response, InputStream inputStream, String picName) throws IOException { |
| 214 | 218 | response.setContentType("application/octet-stream;charset=UTF-8"); |
| 215 | 219 | response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(picName, "UTF-8")); |
| ... | ... | @@ -220,6 +224,8 @@ public class TaskServiceImpl implements TaskService { |
| 220 | 224 | } |
| 221 | 225 | response.flushBuffer(); |
| 222 | 226 | } |
| 227 | + | |
| 228 | + // TODO @Li:这个方法的可读性还有一定的优化空间,可以思考下哈。 | |
| 223 | 229 | /** |
| 224 | 230 | * 获取已经流转的线 https://blog.csdn.net/qiuxinfa123/article/details/119579863 |
| 225 | 231 | * @see |
| ... | ... | @@ -244,6 +250,7 @@ public class TaskServiceImpl implements TaskService { |
| 244 | 250 | } |
| 245 | 251 | } |
| 246 | 252 | |
| 253 | + // TODO @Li:这两个变量,直接放到循环里。这种优化一般不需要做的,对性能影响超级小。 | |
| 247 | 254 | FlowNode currentFlowNode; |
| 248 | 255 | FlowNode targetFlowNode; |
| 249 | 256 | // 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的 |
| ... | ... | @@ -252,11 +259,10 @@ public class TaskServiceImpl implements TaskService { |
| 252 | 259 | currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true); |
| 253 | 260 | List<SequenceFlow> sequenceFlows = currentFlowNode.getOutgoingFlows(); |
| 254 | 261 | |
| 255 | - /** | |
| 256 | - * 遍历outgoingFlows并找到已流转的 满足如下条件认为已已流转: | |
| 257 | - * 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转 | |
| 258 | - * 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转 | |
| 259 | - */ | |
| 262 | + // 遍历outgoingFlows并找到已流转的 满足如下条件认为已已流转: | |
| 263 | + // 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转 | |
| 264 | + // 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转 | |
| 265 | + // TODO @Li:“parallelGateway” 和 "inclusiveGateway",有对应的枚举么?如果木有,可以自己枚举哈 | |
| 260 | 266 | if ("parallelGateway".equals(currentActivityInstance.getActivityType()) || "inclusiveGateway".equals(currentActivityInstance.getActivityType())) { |
| 261 | 267 | // 遍历历史活动节点,找到匹配流程目标节点的 |
| 262 | 268 | for (SequenceFlow sequenceFlow : sequenceFlows) { |
| ... | ... | @@ -266,6 +272,7 @@ public class TaskServiceImpl implements TaskService { |
| 266 | 272 | } |
| 267 | 273 | } |
| 268 | 274 | } else { |
| 275 | + // TODO @Li:如果是为了获取到时间更早的一个,是不是遍历的过程中,就可以解决 | |
| 269 | 276 | List<Map<String, Object>> tempMapList = new ArrayList<>(); |
| 270 | 277 | for (SequenceFlow sequenceFlow : sequenceFlows) { |
| 271 | 278 | for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { |
| ... | ... | @@ -283,6 +290,7 @@ public class TaskServiceImpl implements TaskService { |
| 283 | 290 | long earliestStamp = 0L; |
| 284 | 291 | String highLightedFlowId = null; |
| 285 | 292 | for (Map<String, Object> map : tempMapList) { |
| 293 | + // TODO @Li:可以使用 MapUtil 去 get 值 | |
| 286 | 294 | long highLightedFlowStartTime = Long.valueOf(map.get("highLightedFlowStartTime").toString()); |
| 287 | 295 | if (earliestStamp == 0 || earliestStamp >= highLightedFlowStartTime) { |
| 288 | 296 | highLightedFlowId = map.get("highLightedFlowId").toString(); | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/user/SysUserMapper.java
| ... | ... | @@ -56,6 +56,7 @@ public interface SysUserMapper extends BaseMapperX<SysUserDO> { |
| 56 | 56 | return selectList(new QueryWrapperX<SysUserDO>().like("username", username)); |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | + // TODO jason:变量平铺比较好 | |
| 59 | 60 | default List<SysUserDO> selectListByBaseVO(SysUserBaseVO reqVO) { |
| 60 | 61 | return selectList(new QueryWrapperX<SysUserDO>().likeIfPresent("username", reqVO.getUsername()) |
| 61 | 62 | .likeIfPresent("nickname", reqVO.getNickname()) | ... | ... |
yudao-framework/yudao-spring-boot-starter-activiti/pom.xml
yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/config/YudaoActivitiConfiguration.java
| 1 | 1 | package cn.iocoder.yudao.framework.activiti.config; |
| 2 | 2 | |
| 3 | +import lombok.AllArgsConstructor; | |
| 3 | 4 | import org.activiti.api.runtime.shared.identity.UserGroupManager; |
| 4 | 5 | import org.activiti.image.ProcessDiagramGenerator; |
| 5 | 6 | import org.activiti.image.impl.DefaultProcessDiagramGenerator; |
| ... | ... | @@ -14,24 +15,27 @@ import org.springframework.stereotype.Component; |
| 14 | 15 | public class YudaoActivitiConfiguration { |
| 15 | 16 | |
| 16 | 17 | |
| 17 | - | |
| 18 | + // TODO @Li:可以说明下 ProcessDiagramGenerator 作用 | |
| 18 | 19 | @Bean |
| 19 | 20 | public ProcessDiagramGenerator processDiagramGenerator (){ |
| 20 | 21 | return new DefaultProcessDiagramGenerator(); |
| 21 | 22 | } |
| 23 | + | |
| 24 | + /** | |
| 25 | + * ProcessEngineConfigurationConfigurer 实现类,设置使用 MyBatis SqlSessionFactory | |
| 26 | + */ | |
| 22 | 27 | @Component |
| 28 | + @AllArgsConstructor | |
| 23 | 29 | public static class SqlSessionFactoryProcessEngineConfigurationConfigurer |
| 24 | 30 | implements ProcessEngineConfigurationConfigurer { |
| 25 | 31 | |
| 26 | 32 | private final SqlSessionFactory sqlSessionFactory; |
| 27 | - public SqlSessionFactoryProcessEngineConfigurationConfigurer(SqlSessionFactory sessionFactory) { | |
| 28 | - this.sqlSessionFactory = sessionFactory; | |
| 29 | - } | |
| 30 | 33 | |
| 31 | 34 | @Override |
| 32 | 35 | public void configure(SpringProcessEngineConfiguration springProcessEngineConfiguration) { |
| 33 | 36 | springProcessEngineConfiguration.setSqlSessionFactory(sqlSessionFactory); |
| 34 | 37 | } |
| 38 | + | |
| 35 | 39 | } |
| 36 | 40 | |
| 37 | 41 | ... | ... |