| 2025-04-02 | zxl | ![]() |
| 2025-04-02 | zxl | ![]() |
| 2025-04-01 | zxl | ![]() |
| 2025-04-01 | zxl | ![]() |
| 2025-03-31 | xiangpei | ![]() |
| 2025-03-31 | xiangpei | ![]() |
| 2025-03-26 | xiangpei | ![]() |
| 2025-03-26 | xiangpei | ![]() |
| 2025-03-26 | xiangpei | ![]() |
| 2025-03-26 | xiangpei | ![]() |
| 2025-03-25 | xiangpei | ![]() |
| 2025-03-25 | xiangpei | ![]() |
| 2025-03-25 | xiangpei | ![]() |
| 2025-03-24 | xiangpei | ![]() |
| 2025-03-24 | xiangpei | ![]() |
business/src/main/java/com/ycl/constant/TaskTypeConstant.java
@@ -11,6 +11,7 @@ public final static String ALL = "all"; // 全部任务 public final static String TODO = "todo"; // 待办任务 public final static String WAIT = "wait"; // 容缺 public final static String JUMP = "jump"; // 容缺 public final static String REMAINING = "remaining"; // 剩余任务 public final static String TIMELY = "timely"; // 及时完成的任务 public final static String OVERTIME = "overtime"; // 超时完成的任务 business/src/main/java/com/ycl/controller/CodingRulerController.java
@@ -25,7 +25,7 @@ */ @Validated @RequiredArgsConstructor @Api(value = "项目编码类型管理", tags = "管理") @Api(value = "赋码规则类型管理", tags = "管理") @RestController @RequestMapping("/coding-ruler") public class CodingRulerController { business/src/main/java/com/ycl/domain/entity/ProjectOvertimeTimes.java
New file @@ -0,0 +1,39 @@ package com.ycl.domain.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import com.ycl.system.domain.base.AbsEntity; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * * * @author zxl * @since 2025-04-01 */ @Data @TableName("t_project_overtime_times") public class ProjectOvertimeTimes extends AbsEntity { private static final long serialVersionUID = 1L; @TableField("task_overtime_num") /** 超时任务数*/ private Long taskOvertimeNum; @TableField("process_ins_id") /** 流程实例id*/ private String processInsId; @TableField("project_id") /** 项目id*/ private String projectId; /** 项目类型*/ @TableField("project_type") private String projectType; } business/src/main/java/com/ycl/domain/form/ProjectOvertimeTimesForm.java
New file @@ -0,0 +1,49 @@ package com.ycl.domain.form; import com.ycl.common.group.Update; import com.ycl.common.group.Add; import com.ycl.domain.entity.ProjectOvertimeTimes; import com.ycl.system.domain.base.AbsForm; import org.springframework.beans.BeanUtils; import javax.validation.constraints.NotNull; import org.springframework.lang.NonNull; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * 表单 * * @author zxl * @since 2025-04-01 */ @Data @ApiModel(value = "ProjectCodingStatus表单", description = "表单") public class ProjectOvertimeTimesForm extends AbsForm { @NotNull(message = "不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("超时任务数") private Integer taskOvertimeNum; @NotNull(message = "不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("流程实例id") private String processInsId; @NotNull(message = "不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("项目id") private String projectId; @NotNull(message = "不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("项目类型") private String projectType; public static ProjectOvertimeTimes getEntityByForm(@NonNull ProjectOvertimeTimesForm form, ProjectOvertimeTimes entity) { if(entity == null) { entity = new ProjectOvertimeTimes(); } BeanUtils.copyProperties(form, entity); return entity; } } business/src/main/java/com/ycl/domain/query/ProjectInfoQuery.java
@@ -46,19 +46,29 @@ private String investType; //行政区划 private String area; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date projectStartTime; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date projectEndTime; //从有没有流程判断是存储还是早期 private String reserveOrPrevious; private Integer role;// 业主:0,审核:1 //查询条件业主单位 private Long projectOwnerUnit; private Integer usedStatus; //查询条件主管部门 private Long competentDepartment; @ApiModelProperty("项目码") private String coding; @ApiModelProperty("是否是异常项目查询:0 不是 1是") private Integer exe; business/src/main/java/com/ycl/domain/query/ProjectOvertimeTimesQuery.java
New file @@ -0,0 +1,22 @@ package com.ycl.domain.query; import com.ycl.system.domain.base.AbsQuery; import java.util.List; import org.springframework.lang.NonNull; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * 查询 * * @author zxl * @since 2025-04-01 */ @Data @ApiModel(value = "ProjectOvertimeTimesQuery查询参数", description = "查询参数") public class ProjectOvertimeTimesQuery extends AbsQuery { } business/src/main/java/com/ycl/domain/vo/ProjectOvertimeTimesVO.java
New file @@ -0,0 +1,46 @@ package com.ycl.domain.vo; import com.ycl.domain.entity.ProjectOvertimeTimes; import com.ycl.system.domain.base.AbsVo; import org.springframework.lang.NonNull; import org.springframework.beans.BeanUtils; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * 展示 * * @author zxl * @since 2025-04-01 */ @Data @ApiModel(value = "响应数据", description = "响应数据") public class ProjectOvertimeTimesVO extends AbsVo { /** 任务超时数*/ @ApiModelProperty("任务超时数") private Integer taskOvertimeNum; /** 流程实例id*/ @ApiModelProperty("流程实例id") private String processInsId; /** 项目id*/ @ApiModelProperty("项目id") private String projectId; /** 项目类型*/ @ApiModelProperty("项目类型") private String projectType; public static ProjectOvertimeTimesVO getVoByEntity(@NonNull ProjectOvertimeTimes entity, ProjectOvertimeTimesVO vo) { if(vo == null) { vo = new ProjectOvertimeTimesVO(); } BeanUtils.copyProperties(entity, vo); return vo; } } business/src/main/java/com/ycl/domain/vo/ProjectProcessDetailVO.java
@@ -90,6 +90,11 @@ /** * 容缺任务数 */ private Long toleranceNum = 0L; private Long waitTaskNum = 0L; /** * 跳过任务数 */ private Long jumpTaskNum = 0L; } } business/src/main/java/com/ycl/mapper/CodingRulerMapper.java
@@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ycl.domain.vo.CodingRulerVO; import com.ycl.domain.form.CodingRulerForm; import com.ycl.domain.query.CodingRulerQuery; import java.util.List; import org.apache.ibatis.annotations.Mapper; @@ -31,4 +30,6 @@ */ IPage getPage(IPage page, @Param("query") CodingRulerQuery query); List<CodingRulerVO> getStartRuler(); } business/src/main/java/com/ycl/mapper/ProjectOvertimeTimesMapper.java
New file @@ -0,0 +1,36 @@ package com.ycl.mapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ycl.domain.entity.ProjectOvertimeTimes; import com.ycl.domain.query.ProjectOvertimeTimesQuery; import com.ycl.domain.vo.ProjectOvertimeTimesVO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * Mapper 接口 * * @author zxl * @since 2025-04-01 */ @Mapper public interface ProjectOvertimeTimesMapper extends BaseMapper<ProjectOvertimeTimes> { /** * id查找 * @param id * @return */ ProjectOvertimeTimesVO getById(Integer id); /** * 分页 */ IPage getPage(IPage page, @Param("query") ProjectOvertimeTimesQuery query); void delAll(); } business/src/main/java/com/ycl/service/CodingRulerService.java
@@ -8,7 +8,7 @@ import java.util.List; /** * 服务类 * 赋码规则服务类 * * @author zxl * @since 2025-03-18 @@ -68,4 +68,10 @@ * @return */ Result changeCodingRulerStatus(Integer id); /** * 获得启动的赋码规则 * @return 存放的字段 yellowRuler启用的黄码规则,redRuler启用的红码规则 */ Result getStartRuler(); } business/src/main/java/com/ycl/service/ProjectOvertimeTimesService.java
New file @@ -0,0 +1,66 @@ package com.ycl.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ycl.common.base.Result; import com.ycl.domain.entity.ProjectOvertimeTimes; import com.ycl.domain.form.ProjectOvertimeTimesForm; import com.ycl.domain.query.ProjectOvertimeTimesQuery; import java.util.List; /** * 服务类 * * @author zxl * @since 2025-04-01 */ public interface ProjectOvertimeTimesService extends IService<ProjectOvertimeTimes> { /** * 添加 * @param form * @return */ Result add(ProjectOvertimeTimesForm form); /** * 修改 * @param form * @return */ Result update(ProjectOvertimeTimesForm form); /** * 批量删除 * @param ids * @return */ Result remove(List<String> ids); /** * id删除 * @param id * @return */ Result removeById(String id); /** * 分页查询 * @param query * @return */ Result page(ProjectOvertimeTimesQuery query); /** * 根据id查找 * @param id * @return */ Result detail(Integer id); /** * 列表 * @return */ Result all(); } business/src/main/java/com/ycl/service/impl/CodingRulerServiceImpl.java
@@ -17,6 +17,7 @@ import com.ycl.framework.utils.PageUtil; import org.springframework.beans.BeanUtils; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.stream.Collectors; @@ -150,4 +151,30 @@ baseMapper.updateById(codingRuler); return Result.ok(msg); } /** * 获得启动的赋码规则 * @return 存放的字段 yellowRuler启用的黄码规则,redRuler启用的红码规则 */ @Override public Result getStartRuler() { Result result = new Result(); //获得启用的赋码规则 List<CodingRulerVO> codingRulerVOS = codingRulerMapper.getStartRuler(); if (CollectionUtils.isEmpty(codingRulerVOS)){ log.error("未启用赋码规则"); return result; } CodingRulerVO yellowRuler = null; CodingRulerVO redRuler = null; for (CodingRulerVO codingRulerVO : codingRulerVOS){ if (CodingRulerCodeTypeEnum.YELLOW.getValue().equals(codingRulerVO.getProjectCodeType())){ yellowRuler = codingRulerVO; }else if (CodingRulerCodeTypeEnum.RED.getValue().equals(codingRulerVO.getProjectCodeType())){ redRuler = codingRulerVO; } } result.put("yellowRuler",yellowRuler); result.put("redRuler",redRuler); return result; } } business/src/main/java/com/ycl/service/impl/ProjectCodingStatusServiceImpl.java
New file @@ -0,0 +1,121 @@ package com.ycl.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ycl.domain.entity.ProjectOvertimeTimes; import com.ycl.domain.query.ProjectOvertimeTimesQuery; import com.ycl.common.base.Result; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.domain.form.ProjectOvertimeTimesForm; import com.ycl.domain.vo.ProjectOvertimeTimesVO; import com.ycl.mapper.ProjectOvertimeTimesMapper; import com.ycl.service.ProjectOvertimeTimesService; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import com.ycl.framework.utils.PageUtil; import org.springframework.beans.BeanUtils; import org.springframework.util.Assert; import java.util.List; import java.util.stream.Collectors; /** * 服务实现类 * * @author zxl * @since 2025-04-01 */ @Service @RequiredArgsConstructor public class ProjectCodingStatusServiceImpl extends ServiceImpl<ProjectOvertimeTimesMapper, ProjectOvertimeTimes> implements ProjectOvertimeTimesService { private final ProjectOvertimeTimesMapper projectCodingStatusMapper; /** * 添加 * @param form * @return */ @Override public Result add(ProjectOvertimeTimesForm form) { ProjectOvertimeTimes entity = ProjectOvertimeTimesForm.getEntityByForm(form, null); baseMapper.insert(entity); return Result.ok("添加成功"); } /** * 修改 * @param form * @return */ @Override public Result update(ProjectOvertimeTimesForm form) { ProjectOvertimeTimes entity = baseMapper.selectById(form.getId()); // 为空抛IllegalArgumentException,做全局异常处理 Assert.notNull(entity, "记录不存在"); BeanUtils.copyProperties(form, entity); baseMapper.updateById(entity); return Result.ok("修改成功"); } /** * 批量删除 * @param ids * @return */ @Override public Result remove(List<String> ids) { baseMapper.deleteBatchIds(ids); return Result.ok("删除成功"); } /** * id删除 * @param id * @return */ @Override public Result removeById(String id) { baseMapper.deleteById(id); return Result.ok("删除成功"); } /** * 分页查询 * @param query * @return */ @Override public Result page(ProjectOvertimeTimesQuery query) { IPage<ProjectOvertimeTimesVO> page = PageUtil.getPage(query, ProjectOvertimeTimesVO.class); baseMapper.getPage(page, query); return Result.ok().data(page.getRecords()).total(page.getTotal()); } /** * 根据id查找 * @param id * @return */ @Override public Result detail(Integer id) { ProjectOvertimeTimesVO vo = baseMapper.getById(id); Assert.notNull(vo, "记录不存在"); return Result.ok().data(vo); } /** * 列表 * @return */ @Override public Result all() { List<ProjectOvertimeTimes> entities = baseMapper.selectList(null); List<ProjectOvertimeTimesVO> vos = entities.stream() .map(entity -> ProjectOvertimeTimesVO.getVoByEntity(entity, null)) .collect(Collectors.toList()); return Result.ok().data(vos); } } business/src/main/java/com/ycl/service/impl/ProjectInfoServiceImpl.java
@@ -20,10 +20,7 @@ import com.ycl.common.core.domain.BaseEntity; import com.ycl.common.core.domain.entity.SysDictData; import com.ycl.common.enums.YesOrNo; import com.ycl.common.enums.business.FileTypeEnum; import com.ycl.common.enums.business.ImportanceTypeEnum; import com.ycl.common.enums.business.ProjectCategoryEnum; import com.ycl.common.enums.business.ProjectStatusEnum; import com.ycl.common.enums.business.*; import com.ycl.common.exception.base.BaseException; import com.ycl.common.utils.CopyUtils; import com.ycl.common.utils.DateUtils; @@ -100,6 +97,7 @@ private final ProjectUnitRegistrationInfoServiceImpl projectUnitRegistrationInfoServiceImpl; private final SysDeptMapper sysDeptMapper; private final ISysDictDataService dictDataService; private final ProcessLogService processLogService; /** @@ -547,6 +545,12 @@ public Map<String, Integer> countExceptionProject(IndexDTO indexDTO) { Map<String, Integer> map = new HashMap<>(); map.put("processExceptionProject", 0); // 查询发生过容缺的项目数 List<String> projectIds = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .select(ProcessLog::getProjectId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.WAIT) .list().stream().map(ProcessLog::getProjectId).distinct().collect(Collectors.toList()); map.put("hasWaitProjectNum", projectIds.size()); return map; } business/src/main/java/com/ycl/service/impl/ProjectProcessServiceImpl.java
@@ -13,6 +13,7 @@ import com.ycl.common.core.domain.entity.SysRole; import com.ycl.common.core.domain.entity.SysUser; import com.ycl.common.enums.business.*; import com.ycl.common.utils.DateUtils; import com.ycl.common.utils.SecurityUtils; import com.ycl.constant.TaskTypeConstant; import com.ycl.domain.entity.*; @@ -305,8 +306,8 @@ taskStatistics.setTimelyFinishedTaskNum(this.getTimelyTaskNum(projectProcess.getProcessInsId())); taskStatistics.setOvertimeTaskNum(this.getOvertimeTaskNum(projectProcess.getProcessInsId())); taskStatistics.setWillOvertimeTaskNum(this.getWillOvertimeTaskNum(projectProcess.getProcessInsId())); taskStatistics.setToleranceNum(this.getToleranceTask(projectProcess.getProcessInsId())); // taskStatistics.setCurrentTask(this.getCurrentNodeTaskList(projectProcess.getProcessInstanceId())); taskStatistics.setWaitTaskNum(this.getWaitTaskNum(projectProcess.getProcessInsId())); taskStatistics.setJumpTaskNum(this.getJumpTaskNum(projectProcess.getProcessInsId())); detail.setStatistics(taskStatistics); Result result = Result.ok(); @@ -321,7 +322,7 @@ * @param processInsId * @return */ private Long getToleranceTask(String processInsId){ private Long getWaitTaskNum(String processInsId){ // 查出容缺过的任务 List<ProcessLog> allWaitTaskList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) @@ -331,7 +332,7 @@ // 排除容缺后又完成的任务 List<ProcessLog> finishedTaskList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.FINISHED) .in(ProcessLog::getEventType, ProcessLogEventTypeEnum.FINISHED, ProcessLogEventTypeEnum.REJECT) .list(); List<String> finishedTaskIds = finishedTaskList.stream().map(ProcessLog::getTaskId).distinct().collect(Collectors.toList()); // 得到未完成的容缺任务 @@ -339,7 +340,19 @@ if (CollectionUtils.isEmpty(waitTaskIds)) { return 0L; } return Long.valueOf(waitTaskIds.size()); // 容缺的任务都属于历史任务,只是需要补表单数据 List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInsId) .taskIds(waitTaskIds) .includeIdentityLinks() .orderByHistoricTaskInstanceStartTime() .desc() .list(); hisTaskList = this.distinctHisTask(hisTaskList); // 排除运行时任务 List<String> runTaskKeys = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); hisTaskList = hisTaskList.stream().filter(his -> !runTaskKeys.contains(his.getTaskDefinitionKey())).collect(Collectors.toList()); return Long.valueOf(hisTaskList.size()); } @Override @@ -363,6 +376,9 @@ break; case TaskTypeConstant.WAIT: this.getWaitTask(query.getProjectId(), query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; case TaskTypeConstant.JUMP: this.getJumpTask(query.getProjectId(), query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; case TaskTypeConstant.REMAINING: this.getRemainingTask(query.getProjectId(), query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); @@ -420,7 +436,7 @@ Long overtime = getTime(processCoding.getRedTime()); long durationTime = 0l; if (Objects.nonNull(processCoding.getStartTaskTime())) { durationTime = ((new Date()).getTime() - processCoding.getStartTaskTime().getTime()) / 1000; durationTime = DateUtils.getWorkingSed(processCoding.getStartTaskTime(), new Date()); } if (overtime > durationTime) { order.setNum((overtime - durationTime) / 3600); @@ -1400,16 +1416,30 @@ */ private Long getTimelyTaskNum(String processInsId) { // 查出已完成的任务key List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInsId) .finished() .list(); hisTaskList = this.distinctHisTask(hisTaskList); .includeIdentityLinks() .orderByTaskCreateTime() .desc(); List<HistoricTaskInstance> hisTaskList = query.list(); if (CollectionUtils.isEmpty(hisTaskList)) { return 0L; } hisTaskList = this.distinctHisTask(hisTaskList); // 排除跳过、容缺的任务,因为这两个操作都会完成任务而产生历史任务 List<String> jumpAndWaitTaskKeys = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) .in(ProcessLog::getEventType, ProcessLogEventTypeEnum.JUMP, ProcessLogEventTypeEnum.WAIT) // TODO 如果运行时任务正好是被驳回的,需要想办法排除调被驳回的任务,不能直接在这加 ProcessLogEventTypeEnum.REJECT .list().stream().map(ProcessLog::getTaskDefKey).collect(Collectors.toList()); List<String> runtimeTaskKey = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); jumpAndWaitTaskKeys.addAll(runtimeTaskKey); hisTaskList = hisTaskList.stream().filter(hisTask -> jumpAndWaitTaskKeys.indexOf(hisTask.getTaskDefinitionKey()) == -1).collect(Collectors.toList()); List<String> hisTaskKeys = hisTaskList.stream().map(HistoricTaskInstance::getTaskDefinitionKey).distinct().collect(Collectors.toList()); if (CollectionUtils.isEmpty(hisTaskKeys)) { return 0L; } Map<String, HistoricTaskInstance> hisTaskMap = hisTaskList.stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, his -> his)); // 查出时间正常的任务key List<ProcessCoding> codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) @@ -1451,21 +1481,37 @@ int endNum = startNum + pageSize; // 查出已完成的任务key List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInsId) .finished() .taskNameLike(taskName) .includeIdentityLinks() .orderByTaskCreateTime() .desc() .list(); .desc(); if (StringUtils.isNotBlank(taskName)) { query.taskNameLike(taskName); } List<HistoricTaskInstance> hisTaskList = query.list(); if (CollectionUtils.isEmpty(hisTaskList)) { result.total(0); return new ArrayList<>(); } hisTaskList = this.distinctHisTask(hisTaskList); // 排除跳过、容缺的任务,因为这两个操作都会完成任务而产生历史任务 List<String> jumpAndWaitTaskKeys = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getProjectId, projectId) .in(ProcessLog::getEventType, ProcessLogEventTypeEnum.JUMP, ProcessLogEventTypeEnum.WAIT) .list().stream().map(ProcessLog::getTaskDefKey).collect(Collectors.toList()); List<String> runtimeTaskKey = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); jumpAndWaitTaskKeys.addAll(runtimeTaskKey); hisTaskList = hisTaskList.stream().filter(hisTask -> jumpAndWaitTaskKeys.indexOf(hisTask.getTaskDefinitionKey()) == -1).collect(Collectors.toList()); List<String> hisTaskKeys = hisTaskList.stream().map(HistoricTaskInstance::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map<String, HistoricTaskInstance> hisTaskMap = this.distinctHisTask(hisTaskList).stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, his -> his)); if (CollectionUtils.isEmpty(hisTaskKeys)) { result.total(0); return new ArrayList<>(); } Map<String, HistoricTaskInstance> hisTaskMap = hisTaskList.stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, his -> his)); // 查出时间正常的任务key List<ProcessCoding> codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) @@ -1571,6 +1617,81 @@ } /** * 设置历史任务信息 * * @param hisTask * @param vo * @param projectId * @param processInsId */ private void setHisTaskInfo(HistoricTaskInstance hisTask, CustomerTaskVO vo, String projectId, String processInsId) { // 查出流程 ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(processInsId).singleResult(); String deployId = ""; String processName = ""; String processDefinitionId = ""; if (Objects.nonNull(process)) { deployId = process.getDeploymentId(); processName = process.getProcessDefinitionName(); processDefinitionId = process.getProcessDefinitionId(); } else { HistoricProcessInstance hisProcess = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInsId).singleResult(); deployId = hisProcess.getDeploymentId(); processName = hisProcess.getProcessDefinitionName(); processDefinitionId = hisProcess.getProcessDefinitionId(); } vo.setProcessInsId(processInsId); vo.setProcessDefId(processDefinitionId); vo.setDeployId(deployId); vo.setTaskName(hisTask.getName()); vo.setProcessName(processName); // 一个任务可能有多个候选人/组,所以需要使用list List<Long> handlerIds = new ArrayList<>(2); List<String> handlerNames = new ArrayList<>(2); List<Long> handlerUnitIds = new ArrayList<>(2); List<String> handlerUnitNames = new ArrayList<>(2); List<String> promoterNames = new ArrayList<>(2); List<String> promoterUnitNames = new ArrayList<>(2); vo.setHandlerId(handlerIds); vo.setHandlerName(handlerNames); vo.setHandlerUnitId(handlerUnitIds); vo.setHandlerUnitName(handlerUnitNames); vo.setPromoterName(promoterNames); vo.setPromoterUnitName(promoterUnitNames); List<UserTask> targetUserTasks = this.getAllUserTaskElement(processDefinitionId).stream().filter(userTask -> hisTask.getTaskDefinitionKey().equals(userTask.getId())).collect(Collectors.toList()); UserTask userTask = null; if (! CollectionUtils.isEmpty(targetUserTasks)) { userTask = targetUserTasks.get(0); } this.setCandidateInfo(userTask, vo, projectId, processInsId); vo.setTaskStatus(TaskStatusEnum.FINISHED); // 如果是已完成的,信息需要单独赋值 vo.setTaskId(hisTask.getId()); vo.setExecutionId(hisTask.getExecutionId()); vo.setCreateTime(hisTask.getStartTime()); // 查询实际处理人 if (StringUtils.isNotBlank(hisTask.getAssignee())) { long handlerUserId = Long.parseLong(hisTask.getAssignee()); SysUser handlerUser = sysUserService.selectUserById(handlerUserId); if (Objects.nonNull(handlerUser)) { vo.getHandlerId().add(handlerUserId); vo.getHandlerName().add(this.getUserShowName(handlerUser)); if (Objects.nonNull(handlerUser.getDept())) { vo.getHandlerUnitId().add(handlerUser.getDept().getDeptId()); vo.getHandlerUnitName().add(handlerUser.getDept().getDeptName()); } } } vo.setTaskDefinitionKey(hisTask.getTaskDefinitionKey()); this.distinctVo(vo); } /** * 用户名称后面跟电话号码 * * @param user @@ -1619,36 +1740,16 @@ * @return */ private Long getOvertimeTaskNum(String processInsId) { // 查出运行在的任务key List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInsId).list(); if (CollectionUtils.isEmpty(taskList)) { // 查出已超时的任务id List<ProcessCoding> overtimeRecords = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .eq(ProcessCoding::getOvertimeStatus, ProcessOverTimeConstants.OVERTIME) .orderByDesc(ProcessCoding::getGmtCreate) .list(); if (CollectionUtils.isEmpty(overtimeRecords)) { return 0L; } List<String> taskKeys = taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map<String, Task> taskMap = taskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // 查出数据库的任务key List<ProcessCoding> codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .in(ProcessCoding::getTaskDefKey, taskKeys) .list(); List<Task> tList = new ArrayList<>(); // 判断 for (String key : taskMap.keySet()) { List<ProcessCoding> targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 if (CollectionUtils.isEmpty(targetProcessCodings)) { tList.add(taskMap.get(key)); } else { // 按照时间降序排列 targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); ProcessCoding latestProjectProcess = targetProcessCodings.get(0); if (Objects.nonNull(latestProjectProcess) && ProcessOverTimeConstants.OVERTIME.equals(latestProjectProcess.getOvertimeStatus())) { tList.add(taskMap.get(key)); } } } return Long.valueOf(taskList.size()); return Long.valueOf(overtimeRecords.size()); } /** @@ -1667,63 +1768,108 @@ int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; // 查出运行在的任务key List<Task> taskList = new ArrayList<>(12); if (StringUtils.isNotBlank(taskName)) { taskList = taskService.createTaskQuery().processInstanceId(processInsId).taskNameLike(taskName).orderByTaskCreateTime().desc().list(); } else { taskList = taskService.createTaskQuery().processInstanceId(processInsId).orderByTaskCreateTime().desc().list(); } if (CollectionUtils.isEmpty(taskList)) { // 查出已超时的任务id List<ProcessCoding> overtimeRecords = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .eq(ProcessCoding::getOvertimeStatus, ProcessOverTimeConstants.OVERTIME) .orderByDesc(ProcessCoding::getGmtCreate) .list(); if (CollectionUtils.isEmpty(overtimeRecords)) { result.total(0); return new ArrayList<>(); } List<String> taskKeys = taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map<String, Task> taskMap = taskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // 查出数据库的任务key List<ProcessCoding> codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .in(ProcessCoding::getTaskDefKey, taskKeys) .list(); List<Task> tList = new ArrayList<>(); // 判断 for (String key : taskMap.keySet()) { List<ProcessCoding> targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 if (CollectionUtils.isEmpty(targetProcessCodings)) { tList.add(taskMap.get(key)); } else { // 按照时间降序排列 targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); ProcessCoding latestProjectProcess = targetProcessCodings.get(0); if (Objects.nonNull(latestProjectProcess) && ProcessOverTimeConstants.OVERTIME.equals(latestProjectProcess.getOvertimeStatus())) { tList.add(taskMap.get(key)); } } } if (startNum >= tList.size()) { if (startNum >= overtimeRecords.size()) { // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } result.total(tList.size()); int end = Math.min(endNum, tList.size()); List<Task> pageTaskList = tList.subList(startNum, end); List<String> taskDefs = pageTaskList.stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); Map<String, Task> keyMap = pageTaskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); result.total(overtimeRecords.size()); int end = Math.min(endNum, overtimeRecords.size()); List<ProcessCoding> pageOvertimeRecords = overtimeRecords.subList(startNum, end); // 得到目标任务对应的定义 List<UserTask> finishedUserTaskElement = this.getAllUserTaskElement(processDefinitionId).stream().filter(el -> taskDefs.contains(el.getId())).collect(Collectors.toList()); // 查询任务相关信息 List<CustomerTaskVO> vos = finishedUserTaskElement.stream().map(userTask -> { Task task = keyMap.get(userTask.getId()); List<CustomerTaskVO> vos = pageOvertimeRecords.stream().map(record -> { CustomerTaskVO vo = new CustomerTaskVO(); this.setRuntimeTaskInfo(task, vo, projectId); return vo; }).collect(Collectors.toList()); Task task = taskService.createTaskQuery().processInstanceId(processInsId).taskId(record.getTaskId()).singleResult(); if (Objects.nonNull(task)) { this.setRuntimeTaskInfo(task, vo, projectId); vo.setTaskStatus(TaskStatusEnum.OVER_TIME); return vo; } else { List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery() .finished() .processInstanceId(processInsId) .taskId(record.getTaskId()) .orderByHistoricTaskInstanceStartTime() .desc() .list(); if (CollectionUtils.isEmpty(list)) { return null; } List<HistoricTaskInstance> hisTask = this.distinctHisTask(list); this.setHisTaskInfo(hisTask.get(0), vo, projectId, processInsId); vo.setTaskStatus(TaskStatusEnum.OVER_TIME_FINISHED); return vo; } }).filter(Objects::nonNull).collect(Collectors.toList()); result.data(vos); return vos; // // 查出运行在的任务key // List<Task> taskList = new ArrayList<>(12); // if (StringUtils.isNotBlank(taskName)) { // taskList = taskService.createTaskQuery().processInstanceId(processInsId).taskNameLike(taskName).orderByTaskCreateTime().desc().list(); // } else { // taskList = taskService.createTaskQuery().processInstanceId(processInsId).orderByTaskCreateTime().desc().list(); // } // if (CollectionUtils.isEmpty(taskList)) { // result.total(0); // return new ArrayList<>(); // } // List<String> taskKeys = taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()); // Map<String, Task> taskMap = taskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // // 查出数据库的任务key // List<ProcessCoding> codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) // .eq(ProcessCoding::getProcessInsId, processInsId) // .in(ProcessCoding::getTaskDefKey, taskKeys) // .list(); // List<Task> tList = new ArrayList<>(); // // 判断 // for (String key : taskMap.keySet()) { // List<ProcessCoding> targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 // if (CollectionUtils.isEmpty(targetProcessCodings)) { // tList.add(taskMap.get(key)); // } else { // // 按照时间降序排列 // targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); // ProcessCoding latestProjectProcess = targetProcessCodings.get(0); // if (Objects.nonNull(latestProjectProcess) && ProcessOverTimeConstants.OVERTIME.equals(latestProjectProcess.getOvertimeStatus())) { // tList.add(taskMap.get(key)); // } // } // } // // if (startNum >= tList.size()) { // // 如果起始索引超出了列表的大小,返回一个空列表 // return new ArrayList<>(); // } // result.total(tList.size()); // int end = Math.min(endNum, tList.size()); // List<Task> pageTaskList = tList.subList(startNum, end); // List<String> taskDefs = pageTaskList.stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); // Map<String, Task> keyMap = pageTaskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // // // 得到目标任务对应的定义 // List<UserTask> finishedUserTaskElement = this.getAllUserTaskElement(processDefinitionId).stream().filter(el -> taskDefs.contains(el.getId())).collect(Collectors.toList()); // // // 查询任务相关信息 // List<CustomerTaskVO> vos = finishedUserTaskElement.stream().map(userTask -> { // Task task = keyMap.get(userTask.getId()); // CustomerTaskVO vo = new CustomerTaskVO(); // this.setRuntimeTaskInfo(task, vo, projectId); // return vo; // }).collect(Collectors.toList()); // result.data(vos); // return vos; } /** @@ -1991,6 +2137,190 @@ } /** * 获取跳过任务 * * @param processInsId * @return */ private Long getJumpTaskNum(String processInsId) { // 查出跳过的任务 List<ProcessLog> allJumpTaskList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.JUMP) .orderByDesc(ProcessLog::getGmtCreate) .list(); // 排除驳回的 List<String> rejectTaskIds = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .select(ProcessLog::getTaskId) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.REJECT) .orderByDesc(ProcessLog::getGmtCreate) .list().stream().map(ProcessLog::getTaskId).collect(Collectors.toList()); List<String> jumpTaskIds = allJumpTaskList.stream().map(ProcessLog::getTaskId).collect(Collectors.toList()); jumpTaskIds.removeAll(rejectTaskIds); if(CollectionUtils.isEmpty(jumpTaskIds)) { return 0L; } List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInsId) .finished() .taskIds(jumpTaskIds) .includeIdentityLinks() .orderByHistoricTaskInstanceStartTime() .desc() .list(); hisTaskList = this.distinctHisTask(hisTaskList); // 排除运行时任务 List<String> runTaskKeys = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); hisTaskList = hisTaskList.stream().filter(his -> !runTaskKeys.contains(his.getTaskDefinitionKey())).collect(Collectors.toList()); return Long.valueOf(hisTaskList.size()); } /** * 获取跳过任务 * * @param projectId * @param processDefinitionId * @param processInsId * @param taskName * @param pageNum * @param pageSize * @param result * @return */ private List<CustomerTaskVO> getJumpTask(String projectId, String processDefinitionId, String processInsId, String taskName, Integer pageNum, Integer pageSize, Result result) { // 查出跳过的任务 List<ProcessLog> allJumpTaskList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.JUMP) .like(StringUtils.isNotBlank(taskName), ProcessLog::getTaskName, taskName) .orderByDesc(ProcessLog::getGmtCreate) .list(); // 排除驳回的 List<String> rejectTaskIds = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .select(ProcessLog::getTaskId) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.REJECT) .like(StringUtils.isNotBlank(taskName), ProcessLog::getTaskName, taskName) .orderByDesc(ProcessLog::getGmtCreate) .list().stream().map(ProcessLog::getTaskId).collect(Collectors.toList()); List<String> jumpTaskIds = allJumpTaskList.stream().map(ProcessLog::getTaskId).collect(Collectors.toList()); jumpTaskIds.removeAll(rejectTaskIds); if(CollectionUtils.isEmpty(jumpTaskIds)) { result.total(0l); return new ArrayList<>(); } List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInsId) .finished() .taskIds(jumpTaskIds) .includeIdentityLinks() .orderByHistoricTaskInstanceStartTime() .desc() .list(); hisTaskList = this.distinctHisTask(hisTaskList); // 排除运行时任务 List<String> runTaskKeys = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); hisTaskList = hisTaskList.stream().filter(his -> !runTaskKeys.contains(his.getTaskDefinitionKey())).collect(Collectors.toList()); if (CollectionUtils.isEmpty(hisTaskList)) { result.total(0l); return new ArrayList<>(); } int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; if (startNum >= hisTaskList.size()) { result.total(0l); // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } result.total(hisTaskList.size()); int end = Math.min(endNum, hisTaskList.size()); List<HistoricTaskInstance> targetTaskList = hisTaskList.subList(startNum, end); // 转换成VO // 得到目标任务对应的定义 List<String> taskDefs = targetTaskList.stream().map(HistoricTaskInstance::getTaskDefinitionKey).collect(Collectors.toList()); Map<String, HistoricTaskInstance> keyMap = targetTaskList.stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, his -> his)); List<UserTask> finishedUserTaskElement = this.getAllUserTaskElement(processDefinitionId).stream().filter(el -> taskDefs.contains(el.getId())).collect(Collectors.toList()); // 查出流程 ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(processInsId).singleResult(); String deployId = ""; String processName = ""; if (Objects.nonNull(process)) { deployId = process.getDeploymentId(); processName = process.getProcessDefinitionName(); } else { HistoricProcessInstance hisProcess = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInsId).singleResult(); deployId = hisProcess.getDeploymentId(); processName = hisProcess.getProcessDefinitionName(); } String finalDeployId = deployId; String finalProcessName = processName; List<CustomerTaskVO> vos = finishedUserTaskElement.stream().map(userTask -> { CustomerTaskVO vo = new CustomerTaskVO(); vo.setProcessInsId(processInsId); vo.setProcessDefId(processDefinitionId); vo.setDeployId(finalDeployId); vo.setTaskName(userTask.getName()); vo.setProcessName(finalProcessName); // 一个任务可能有多个候选人/组,所以需要使用list List<Long> handlerIds = new ArrayList<>(2); List<String> handlerNames = new ArrayList<>(2); List<Long> handlerUnitIds = new ArrayList<>(2); List<String> handlerUnitNames = new ArrayList<>(2); List<String> promoterNames = new ArrayList<>(2); List<String> promoterUnitNames = new ArrayList<>(2); vo.setHandlerId(handlerIds); vo.setHandlerName(handlerNames); vo.setHandlerUnitId(handlerUnitIds); vo.setHandlerUnitName(handlerUnitNames); vo.setPromoterName(promoterNames); vo.setPromoterUnitName(promoterUnitNames); this.setCandidateInfo(userTask, vo, projectId, processInsId); HistoricTaskInstance hisTask = keyMap.get(userTask.getId()); if (Objects.nonNull(hisTask)) { vo.setTaskStatus(TaskStatusEnum.JUMP); // 如果是已完成的,信息需要单独赋值 vo.setTaskId(hisTask.getId()); vo.setExecutionId(hisTask.getExecutionId()); vo.setCreateTime(hisTask.getStartTime()); // 查询实际处理人 if (StringUtils.isNotBlank(hisTask.getAssignee())) { long handlerUserId = Long.parseLong(hisTask.getAssignee()); SysUser handlerUser = sysUserService.selectUserById(handlerUserId); if (Objects.nonNull(handlerUser)) { vo.getHandlerId().add(handlerUserId); vo.getHandlerName().add(this.getUserShowName(handlerUser)); if (Objects.nonNull(handlerUser.getDept())) { vo.getHandlerUnitId().add(handlerUser.getDept().getDeptId()); vo.getHandlerUnitName().add(handlerUser.getDept().getDeptName()); } } } this.setHandler(vo, hisTask.getIdentityLinks()); vo.setTaskDefinitionKey(hisTask.getTaskDefinitionKey()); } this.distinctVo(vo); return vo; }).collect(Collectors.toList()); result.data(vos); return vos; } /** * 容缺任务分页 * * @param projectId @@ -2020,7 +2350,7 @@ // 排除容缺后又完成的任务 List<ProcessLog> finishedTaskList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.FINISHED) .in(ProcessLog::getEventType, ProcessLogEventTypeEnum.FINISHED, ProcessLogEventTypeEnum.REJECT) .list(); List<String> finishedTaskIds = finishedTaskList.stream().map(ProcessLog::getTaskId).distinct().collect(Collectors.toList()); // 得到未完成的容缺任务 @@ -2038,7 +2368,9 @@ .desc() .list(); hisTaskList = this.distinctHisTask(hisTaskList); // 排除运行时任务 List<String> runTaskKeys = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); hisTaskList = hisTaskList.stream().filter(his -> !runTaskKeys.contains(his.getTaskDefinitionKey())).collect(Collectors.toList()); if (CollectionUtils.isEmpty(hisTaskList)) { result.total(0l); return new ArrayList<>(); @@ -2160,8 +2492,14 @@ // 排除进行中的任务和已完成的任务 List<String> runTaskKeyList = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); List<String> finishedTaskKeyList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInsId).finished().list().stream().map(HistoricTaskInstance::getTaskDefinitionKey).distinct().collect(Collectors.toList()); allUserTaskElement = allUserTaskElement.stream().filter(el -> !runTaskKeyList.contains(el.getId()) && !finishedTaskKeyList.contains(el.getId())).collect(Collectors.toList()); List<String> finishedTaskKeyList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .select(ProcessLog::getTaskDefKey) .eq(ProcessLog::getProcessInsId, processInsId) .in(ProcessLog::getEventType, ProcessLogEventTypeEnum.FINISHED, ProcessLogEventTypeEnum.JUMP, ProcessLogEventTypeEnum.WAIT) .list().stream().map(ProcessLog::getTaskDefKey).collect(Collectors.toList()); finishedTaskKeyList.addAll(runTaskKeyList); // List<String> finishedTaskKeyList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInsId).finished().list().stream().map(HistoricTaskInstance::getTaskDefinitionKey).distinct().collect(Collectors.toList()); allUserTaskElement = allUserTaskElement.stream().filter(el -> finishedTaskKeyList.indexOf(el.getId()) == -1).collect(Collectors.toList()); // 模拟模糊查询 if (StringUtils.isNotBlank(taskName)) { allUserTaskElement = allUserTaskElement.stream().filter(taskEl -> taskEl.getName().contains(taskName)).collect(Collectors.toList()); @@ -2318,14 +2656,18 @@ // 运行时未找到流程,说明流程已经结束了 return 0L; } // 查出已完成的任务,用总任务数-已完成的就得到剩余事项 List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery() .processInstanceId(process.getProcessInstanceId()) .finished() .list(); long num = list.stream().map(HistoricTaskInstance::getTaskDefinitionKey).distinct().count(); List<UserTask> allUserTaskElement = this.getAllUserTaskElement(processDefinitionId); return totalNum - num; // 排除进行中的任务和已完成的任务 List<String> runTaskKeyList = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); List<String> finishedTaskKeyList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .select(ProcessLog::getTaskDefKey) .eq(ProcessLog::getProcessInsId, processInsId) .in(ProcessLog::getEventType, ProcessLogEventTypeEnum.FINISHED, ProcessLogEventTypeEnum.JUMP, ProcessLogEventTypeEnum.WAIT) .list().stream().map(ProcessLog::getTaskDefKey).collect(Collectors.toList()); finishedTaskKeyList.addAll(runTaskKeyList); allUserTaskElement = allUserTaskElement.stream().filter(el -> finishedTaskKeyList.indexOf(el.getId()) == -1).collect(Collectors.toList()); return Long.valueOf(allUserTaskElement.size()); } /** business/src/main/java/com/ycl/task/CodingTask.java
New file @@ -0,0 +1,216 @@ package com.ycl.task; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.ycl.common.base.Result; import com.ycl.common.enums.business.CodingRulerIntervalTypeEnum; import com.ycl.common.enums.business.ProjectProcessTypeEnum; import com.ycl.domain.entity.*; import com.ycl.domain.vo.CodingRulerVO; import com.ycl.domain.vo.ProcessCodingVO; import com.ycl.domain.vo.ProcessOvertimeTimesVO; import com.ycl.factory.FlowServiceFactory; import com.ycl.mapper.*; import com.ycl.service.CodingRulerService; import com.ycl.service.ProjectOvertimeTimesService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; @Slf4j @RequiredArgsConstructor @Component("codingTask") public class CodingTask extends FlowServiceFactory { private final ProjectOvertimeTimesMapper projectOvertimeTimesMapper; private final ProjectOvertimeTimesService projectOvertimeTimesService; private final ProjectProcessMapper projectProcessMapper; private final ProjectInfoMapper projectInfoMapper; private final CodingRulerService codingRulerService; private final ProcessCodingMapper processCodingMapper; //计数项目超时任务数并更具赋码规则进行赋码 public void codingTask(){ log.info("开始计算项目并且赋码"); //获得启用的赋码规则 Result result = codingRulerService.getStartRuler(); CodingRulerVO yellowRuler = (CodingRulerVO) result.get("yellowRuler"); CodingRulerVO redRuler = (CodingRulerVO) result.get("redRuler"); //没启用直接结束 if (Objects.isNull(yellowRuler) && Objects.isNull(redRuler)) { log.error("未启用赋码规则"); return; } //获得所有 超时任务数与流程实例id List<ProcessOvertimeTimesVO> processOvertimeTimesVOS = processCodingMapper.countProjectOvertimeTimes(); if (!CollectionUtils.isEmpty(processOvertimeTimesVOS)){ //将流程实例id转换为list List<String> processIds = processOvertimeTimesVOS.stream().map(ProcessOvertimeTimesVO::getProcessInsId).toList(); //获得所有 更具流程定义id,流程相关项目id, key为流程id Map<String, ProjectProcess> projectMap = new LambdaQueryChainWrapper<>(projectProcessMapper) .in(ProjectProcess::getProcessInsId, processIds) .eq(ProjectProcess::getProjectType, ProjectProcessTypeEnum.PROJECT) .list() .stream() .collect(Collectors.toMap(ProjectProcess::getProcessInsId, Function.identity())); //修改为黄码的项目 id List<String> yellowProjectCodingIds = new ArrayList<>(); //修改为红码的项目 id List<String> redProjectCodingIds = new ArrayList<>(); //新增的记录集合 List<ProjectOvertimeTimes> addList = new ArrayList<>(); for (ProcessOvertimeTimesVO processOvertimeTimesVO : processOvertimeTimesVOS) { //判断 项目类型为 ProjectProcessTypeEnum.PROJECT 并且超时任务数大于0 if (processOvertimeTimesVO.getTaskOvertimeNum() != 0 && projectMap.containsKey(processOvertimeTimesVO.getProcessInsId())) { ProjectOvertimeTimes projectOvertimeTimes = new ProjectOvertimeTimes(); projectOvertimeTimes.setProjectType(ProjectProcessTypeEnum.PROJECT.getValue()); projectOvertimeTimes.setProjectId(projectMap.get(processOvertimeTimesVO.getProcessInsId()).getProjectId()); projectOvertimeTimes.setProcessInsId(processOvertimeTimesVO.getProcessInsId()); projectOvertimeTimes.setTaskOvertimeNum(processOvertimeTimesVO.getTaskOvertimeNum()); //添加到新增集合内 addList.add(projectOvertimeTimes); //检验赋码规则 checkCodingType(projectOvertimeTimes.getTaskOvertimeNum(), projectOvertimeTimes.getProjectId(), yellowProjectCodingIds,redProjectCodingIds, yellowRuler,redRuler); } } if(!CollectionUtils.isEmpty(addList)){ projectOvertimeTimesMapper.delAll(); projectOvertimeTimesService.saveBatch(addList); } //修改项目赋码 updateProjectCoding(redProjectCodingIds,"red"); log.info("打印赋值为红码的项目id"); for (String s : redProjectCodingIds){ System.out.println(s); } log.info("打印赋值为红码的项目id完毕"); updateProjectCoding(yellowProjectCodingIds,"yellow"); log.info("打印赋值为黄码的项目id"); for (String s : yellowProjectCodingIds){ System.out.println(s); } log.info("打印赋值为黄码的项目id完毕"); } log.info("结束计算项目并且赋码"); } /** * 赋码 * * @param projectIds 流程实例ID列表 * @param coding 赋码值 */ private void updateProjectCoding(List<String> projectIds, String coding) { if (!CollectionUtils.isEmpty(projectIds)) { //将id 类型转换为Long List<Long> longList = projectIds.stream() .map(Long::parseLong) .collect(Collectors.toList()); new LambdaUpdateChainWrapper<>(projectInfoMapper) .in(ProjectInfo::getId, longList) .set(ProjectInfo::getCoding, coding) .update(); } } /** * * @param overTimeNum 超时任务数 * @param projectId 项目id * @param yellowProjectCodingIds 修改项目赋码为黄码的id集合 * @param redProjectCodingIds 修改项目赋码为红码的id集合 * @param yellowRuler 黄码规则 * @param redRuler 红码规则 */ private void checkCodingType(Long overTimeNum,String projectId, List<String> yellowProjectCodingIds, List<String> redProjectCodingIds, CodingRulerVO yellowRuler,CodingRulerVO redRuler){ //先判断红码,规则如果满足,则不执行黄码规则 if (judgeState(overTimeNum, projectId, redProjectCodingIds, redRuler)) return; //判断是否满足黄码规则 judgeState(overTimeNum, projectId, yellowProjectCodingIds, yellowRuler); } private boolean judgeState(Long overTimeNum, String projectId, List<String> projectCodingIds, CodingRulerVO ruler) { if (ruler != null){ if (CodingRulerIntervalTypeEnum.Interval.getValue().equals(ruler.getIntervalType())){ //区间情况 boolean result = false; //判断满足左区间 if (ruler.getLeftSymbol().equals("0")){ result = (overTimeNum > ruler.getLeftValue()); }else if (ruler.getLeftSymbol().equals("1")){ result = (overTimeNum >= ruler.getLeftValue()); }else if (ruler.getLeftSymbol().equals("2")){ result = (Objects.equals(overTimeNum, ruler.getLeftValue())); } //满足则判断满足右区间 if (result){ if (ruler.getRightSymbol().equals("2")){ result = (Objects.equals(overTimeNum, ruler.getRightValue())); }else if (ruler.getRightSymbol().equals("3")){ result = (overTimeNum < ruler.getRightValue()); }else if (ruler.getRightSymbol().equals("4")){ result = (overTimeNum <= ruler.getRightValue()); } } if (result){ //符合该赋码条件 projectCodingIds.add(projectId); return true; } } else{ //单区间情况 boolean result = false; if (ruler.getLeftSymbol().equals("0")){ result = (overTimeNum > ruler.getLeftValue()); }else if (ruler.getLeftSymbol().equals("1")){ result = (overTimeNum >= ruler.getLeftValue()); }else if (ruler.getLeftSymbol().equals("2")){ result = (Objects.equals(overTimeNum, ruler.getLeftValue())); }else if (ruler.getLeftSymbol().equals("3")){ result = (overTimeNum < ruler.getLeftValue()); }else if (ruler.getLeftSymbol().equals("4")){ result = (overTimeNum <= ruler.getLeftValue()); } if (result){ //符合该赋码条件 projectCodingIds.add(projectId); return true; } } } return false; } } business/src/main/java/com/ycl/task/FlowableTask.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.ycl.common.enums.business.ProcessLogEventTypeEnum; import com.ycl.common.enums.business.ProjectProcessTypeEnum; import com.ycl.common.utils.DateUtils; import com.ycl.domain.entity.ProcessCoding; import com.ycl.domain.entity.ProcessLog; import com.ycl.domain.entity.ProjectInfo; @@ -111,8 +112,10 @@ // Long yellowTime = getTime(processCoding.getYellowTime()); // Long overtime = getTime(processCoding.getOvertime()); if (startTime == null) continue; //节点处理时间 long durationTime = (now.getTime() - startTime.getTime()) / 1000; //节点处理时间,需排除节假日 long durationTime = DateUtils.getWorkingSed(startTime, now); //TODO:减去流程挂起时长 //减去节点挂起时长 business/src/main/resources/mapper/CodingRulerMapper.xml
@@ -13,11 +13,21 @@ <result column="status" property="status"/> </resultMap> <select id="getStartRuler" resultMap="BaseResultMap"> select TCR.project_code_type, TCR.interval_type, TCR.left_symbol, TCR.left_value, TCR.right_symbol, TCR.right_value, TCR.id, TCR.status FROM t_coding_ruler TCR WHERE TCR.status = 1 AND TCR.deleted = 0; </select> <select id="getById" resultMap="BaseResultMap"> SELECT business/src/main/resources/mapper/ProjectInfoMapper.xml
@@ -116,6 +116,9 @@ LEFT JOIN sys_dept d ON d.dept_id = TPI.project_owner_unit <where> TPI.deleted = 0 <if test="query.coding !=null and query.coding!=''"> and TPI.coding = #{query.coding} </if> <if test="query.projectName !=null and query.projectName!=''"> and TPI.project_name like concat('%',#{query.projectName},'%') </if> business/src/main/resources/mapper/ProjectOvertimeTimesMapper.xml
New file @@ -0,0 +1,43 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ycl.mapper.ProjectOvertimeTimesMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.ycl.domain.vo.ProjectOvertimeTimesVO"> <result column="task_overtime_num" property="taskOvertimeNum" /> <result column="process_ins_id" property="processInsId" /> <result column="project_id" property="projectId" /> <result column="project_type" property="projectType" /> </resultMap> <delete id="delAll"> DELETE FROM t_project_overtime_times </delete> <select id="getById" resultMap="BaseResultMap"> SELECT TPOT.task_overtime_num, TPOT.process_ins_id, TPOT.project_id, TPOT.id FROM t_project_overtime_times TPOT WHERE TPOT.id = #{id} AND TPOT.deleted = 0 </select> <select id="getPage" resultMap="BaseResultMap"> SELECT TPOT.task_overtime_num, TPOT.process_ins_id, TPOT.project_id, TPOT.id FROM t_project_overtime_times TPOT WHERE TPOT.deleted = 0 </select> </mapper> common/src/main/java/com/ycl/common/enums/business/CodingRulerCodeTypeEnum.java
@@ -11,7 +11,7 @@ @Getter public enum CodingRulerCodeTypeEnum { RED("red", "红码"), GREEN("green","绿码"); YELLOW("yellow","黄码"); @EnumValue @JsonValue common/src/main/java/com/ycl/common/enums/business/CodingRulerSymbolTypeEnum.java
New file @@ -0,0 +1,36 @@ package com.ycl.common.enums.business; import com.baomidou.mybatisplus.annotation.EnumValue; import com.fasterxml.jackson.annotation.JsonValue; import lombok.Getter; import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; @Getter public enum CodingRulerSymbolTypeEnum { GT("0","大于"), GE("1","大于等于"), EQ("2","等于"), LT("3","小于"), LE("4","小于等于"); @EnumValue @JsonValue private final String value; private final String desc; CodingRulerSymbolTypeEnum(String value, String desc) { this.value = value; this.desc = desc; } // 将枚举转换为 Map public static Map<String, String> getMap() { return Arrays.stream(CodingRulerSymbolTypeEnum.values()) .collect(Collectors.toMap(CodingRulerSymbolTypeEnum::getValue, CodingRulerSymbolTypeEnum::getDesc)); } } common/src/main/java/com/ycl/common/enums/business/TaskStatusEnum.java
@@ -17,6 +17,9 @@ FINISHED("finished", "已完成"), WAIT("wait", "容缺"), HANGUP("HANGUP", "挂起"), JUMP("JUMP", "跳过"), OVER_TIME("OVER_TIME", "超时未完成"), OVER_TIME_FINISHED("OVER_TIME_FINISHED", "超时已完成"), ; private final String value; common/src/main/java/com/ycl/common/utils/DateUtils.java
@@ -4,11 +4,7 @@ import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.*; import java.util.Date; import java.util.HashSet; import java.util.Objects; @@ -80,6 +76,52 @@ return workingHours; } /** * 获取两个时间内,除去周末周日以及法定节假日的 秒总数。 * @param startDate * @param endDate * @return */ public static long getWorkingSed(Date startDate,Date endDate){ long workingHours = 0; long workingMill = 0; //转换日期格式 LocalDateTime startTime = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); LocalDateTime endTime = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); if(startTime.isAfter(endTime)){ throw new RuntimeException("开始时间不能晚于结束时间"); } LocalDateTime varTime = startTime; //节假日日期(2025为列) Set<LocalDate> holidays = new HashSet<>(); String[] holiday = isHoliday.split(","); for (String str : holiday) { String[] md = str.split("-"); int month = Integer.parseInt(md[0]); int day = Integer.parseInt(md[1]); holidays.add(LocalDate.of(2025,month,day)); } while (varTime.isBefore(endTime)){ boolean isWorkDay = varTime.getDayOfWeek().getValue() < 6 && !holidays.contains(varTime.toLocalDate()); long diffMill = endTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - varTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); // 判断是否是工作日(非周末 + 非节假日) if (isWorkDay){ if (diffMill < 3600000) { // 如果两个时间不到一小时差距 workingMill += diffMill; break; } workingHours++; workingMill += 3600000; } varTime = varTime.plusHours(1); } return workingMill / 1000; } /** * 获取当前Date型日期 flowable/src/main/java/com/ycl/domain/vo/ProcessOvertimeTimesVO.java
New file @@ -0,0 +1,18 @@ package com.ycl.domain.vo; import com.ycl.system.domain.base.AbsVo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel(value = "响应数据", description = "响应数据") public class ProcessOvertimeTimesVO extends AbsVo { /** 流程实例id */ @ApiModelProperty("流程实例id") private String processInsId; /** 超时任务数 */ @ApiModelProperty("超时任务数") private Long taskOvertimeNum; } flowable/src/main/java/com/ycl/mapper/ProcessCodingMapper.java
@@ -5,6 +5,7 @@ import com.ycl.domain.entity.ProcessCoding; import com.ycl.domain.query.ProcessCodingQuery; import com.ycl.domain.vo.ProcessCodingVO; import com.ycl.domain.vo.ProcessOvertimeTimesVO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -38,4 +39,10 @@ void updateBatch(@Param("list") List<ProcessCoding> list); List<ProcessCoding> findByTaskId(@Param("taskId") String taskId); /** * 查询出每个流程实例id中超时的任务数,流程实例id * @return */ List<ProcessOvertimeTimesVO> countProjectOvertimeTimes(); } flowable/src/main/resources/mapper/ProcessCodingMapper.xml
@@ -14,6 +14,21 @@ <result column="status" property="status" /> <result column="overtime_status" property="overtimeStatus" /> </resultMap> <resultMap id="processOvertimeTimesVO" type="com.ycl.domain.vo.ProcessOvertimeTimesVO"> <id column="id" property="id"/> <result column="task_overtime_num" property="taskOvertimeNum"/> <result column="process_ins_id" property="processInsId"/> </resultMap> <select id="countProjectOvertimeTimes" resultMap="processOvertimeTimesVO"> select TPC.id, TPC.process_ins_id, COUNT(TPC.overtime_status) as task_overtime_num FROM t_process_coding TPC where TPC.overtime_status = 'overtime' GROUP BY TPC.process_ins_id </select> <select id="getById" resultMap="BaseResultMap">