business/src/main/java/com/ycl/domain/entity/ProjectCodingStatus.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 ProjectCodingStatus 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/ProjectCodingStatusForm.java
New file @@ -0,0 +1,50 @@ package com.ycl.domain.form; import com.ycl.common.group.Update; import com.ycl.common.group.Add; import com.ycl.system.domain.base.AbsForm; import com.ycl.domain.entity.ProjectCodingStatus; import org.springframework.beans.BeanUtils; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import org.springframework.lang.NonNull; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; /** * 表单 * * @author zxl * @since 2025-04-01 */ @Data @ApiModel(value = "ProjectCodingStatus表单", description = "表单") public class ProjectCodingStatusForm 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 ProjectCodingStatus getEntityByForm(@NonNull ProjectCodingStatusForm form, ProjectCodingStatus entity) { if(entity == null) { entity = new ProjectCodingStatus(); } BeanUtils.copyProperties(form, entity); return entity; } } business/src/main/java/com/ycl/domain/query/ProjectCodingStatusQuery.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 = "ProjectCodingStatus查询参数", description = "查询参数") public class ProjectCodingStatusQuery extends AbsQuery { } business/src/main/java/com/ycl/domain/vo/ProjectCodingStatusVO.java
New file @@ -0,0 +1,48 @@ package com.ycl.domain.vo; import com.ycl.system.domain.base.AbsVo; import com.ycl.domain.entity.ProjectCodingStatus; import java.util.List; import org.springframework.lang.NonNull; import org.springframework.beans.BeanUtils; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; /** * 展示 * * @author zxl * @since 2025-04-01 */ @Data @ApiModel(value = "响应数据", description = "响应数据") public class ProjectCodingStatusVO extends AbsVo { /** 任务超时数*/ @ApiModelProperty("任务超时数") private Integer taskOvertimeNum; /** 流程实例id*/ @ApiModelProperty("流程实例id") private String processInsId; /** 项目id*/ @ApiModelProperty("项目id") private String projectId; /** 项目类型*/ @ApiModelProperty("项目类型") private String projectType; public static ProjectCodingStatusVO getVoByEntity(@NonNull ProjectCodingStatus entity, ProjectCodingStatusVO vo) { if(vo == null) { vo = new ProjectCodingStatusVO(); } BeanUtils.copyProperties(entity, vo); return vo; } } business/src/main/java/com/ycl/mapper/ProjectCodingStatusMapper.java
New file @@ -0,0 +1,37 @@ package com.ycl.mapper; import com.ycl.domain.entity.ProjectCodingStatus; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ycl.domain.vo.ProjectCodingStatusVO; import com.ycl.domain.form.ProjectCodingStatusForm; import com.ycl.domain.query.ProjectCodingStatusQuery; import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * Mapper 接口 * * @author zxl * @since 2025-04-01 */ @Mapper public interface ProjectCodingStatusMapper extends BaseMapper<ProjectCodingStatus> { /** * id查找 * @param id * @return */ ProjectCodingStatusVO getById(Integer id); /** * 分页 */ IPage getPage(IPage page, @Param("query") ProjectCodingStatusQuery query); void delAll(); } business/src/main/java/com/ycl/service/ProjectCodingStatusService.java
New file @@ -0,0 +1,65 @@ package com.ycl.service; import com.ycl.domain.entity.ProjectCodingStatus; import com.baomidou.mybatisplus.extension.service.IService; import com.ycl.common.base.Result; import com.ycl.domain.form.ProjectCodingStatusForm; import com.ycl.domain.query.ProjectCodingStatusQuery; import java.util.List; /** * 服务类 * * @author zxl * @since 2025-04-01 */ public interface ProjectCodingStatusService extends IService<ProjectCodingStatus> { /** * 添加 * @param form * @return */ Result add(ProjectCodingStatusForm form); /** * 修改 * @param form * @return */ Result update(ProjectCodingStatusForm form); /** * 批量删除 * @param ids * @return */ Result remove(List<String> ids); /** * id删除 * @param id * @return */ Result removeById(String id); /** * 分页查询 * @param query * @return */ Result page(ProjectCodingStatusQuery query); /** * 根据id查找 * @param id * @return */ Result detail(Integer id); /** * 列表 * @return */ Result all(); } business/src/main/java/com/ycl/service/impl/ProjectCodingStatusServiceImpl.java
New file @@ -0,0 +1,120 @@ package com.ycl.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ycl.domain.entity.ProjectCodingStatus; import com.ycl.mapper.ProjectCodingStatusMapper; import com.ycl.service.ProjectCodingStatusService; import com.ycl.common.base.Result; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.domain.form.ProjectCodingStatusForm; import com.ycl.domain.vo.ProjectCodingStatusVO; import com.ycl.domain.query.ProjectCodingStatusQuery; 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<ProjectCodingStatusMapper, ProjectCodingStatus> implements ProjectCodingStatusService { private final ProjectCodingStatusMapper projectCodingStatusMapper; /** * 添加 * @param form * @return */ @Override public Result add(ProjectCodingStatusForm form) { ProjectCodingStatus entity = ProjectCodingStatusForm.getEntityByForm(form, null); baseMapper.insert(entity); return Result.ok("添加成功"); } /** * 修改 * @param form * @return */ @Override public Result update(ProjectCodingStatusForm form) { ProjectCodingStatus 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(ProjectCodingStatusQuery query) { IPage<ProjectCodingStatusVO> page = PageUtil.getPage(query, ProjectCodingStatusVO.class); baseMapper.getPage(page, query); return Result.ok().data(page.getRecords()).total(page.getTotal()); } /** * 根据id查找 * @param id * @return */ @Override public Result detail(Integer id) { ProjectCodingStatusVO vo = baseMapper.getById(id); Assert.notNull(vo, "记录不存在"); return Result.ok().data(vo); } /** * 列表 * @return */ @Override public Result all() { List<ProjectCodingStatus> entities = baseMapper.selectList(null); List<ProjectCodingStatusVO> vos = entities.stream() .map(entity -> ProjectCodingStatusVO.getVoByEntity(entity, null)) .collect(Collectors.toList()); return Result.ok().data(vos); } } business/src/main/java/com/ycl/task/CodingTask.java
New file @@ -0,0 +1,226 @@ package com.ycl.task; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.ycl.common.enums.business.CodingRulerCodeTypeEnum; import com.ycl.common.enums.business.CodingRulerIntervalTypeEnum; import com.ycl.common.enums.business.CodingRulerSymbolTypeEnum; 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.ProjectCodingStatusVO; import com.ycl.domain.vo.ProjectProcessVO; import com.ycl.factory.FlowServiceFactory; import com.ycl.mapper.*; import com.ycl.service.ProjectCodingStatusService; import liquibase.pro.packaged.A; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; 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 @Component("codingTask") public class CodingTask extends FlowServiceFactory { @Autowired private ProjectCodingStatusMapper projectCodingStatusMapper; @Autowired private ProjectCodingStatusService projectCodingStatusService; @Autowired private ProjectProcessMapper projectProcessMapper; @Autowired private ProjectInfoMapper projectInfoMapper; @Autowired private CodingRulerMapper codingRulerMapper; @Autowired private ProcessCodingMapper processCodingMapper; public void codingTask(){ log.info("开始计算项目并且赋码"); //获得启用的赋码规则 List<CodingRulerVO> codingRulerVOS = codingRulerMapper.getStartRuler(); //没启用直接结束 if (CollectionUtils.isEmpty(codingRulerVOS)){ log.info("未启用赋码规则"); return; } 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; } } //获得所有 超时任务数与流程实例id List<ProcessCodingVO> processCodingVOS = processCodingMapper.countProjectOverTimeNum(); if (!CollectionUtils.isEmpty(processCodingVOS)){ //将流程实例id转换为list List<String> processIds = processCodingVOS.stream().map(ProcessCodingVO::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<ProjectCodingStatus> addList = new ArrayList<>(); for (ProcessCodingVO processCoding : processCodingVOS) { //判断 项目类型为 ProjectProcessTypeEnum.PROJECT 并且超时任务数大于0 if (processCoding.getTaskOvertimeNum() != 0 && projectMap.containsKey(processCoding.getProcessInsId())) { ProjectCodingStatus projectCodingStatus = new ProjectCodingStatus(); projectCodingStatus.setProjectType(ProjectProcessTypeEnum.PROJECT.getValue()); projectCodingStatus.setProjectId(projectMap.get(processCoding.getProcessInsId()).getProjectId()); projectCodingStatus.setProcessInsId(processCoding.getProcessInsId()); projectCodingStatus.setTaskOvertimeNum(processCoding.getTaskOvertimeNum()); //添加到新增集合内 addList.add(projectCodingStatus); //检验赋码规则 checkCodingType(projectCodingStatus.getTaskOvertimeNum(), projectCodingStatus.getProjectId(), yellowProjectCodingIds,redProjectCodingIds, yellowRuler,redRuler); } } if(!CollectionUtils.isEmpty(addList)){ projectCodingStatusMapper.delAll(); projectCodingStatusService.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/resources/mapper/ProjectCodingStatusMapper.xml
New file @@ -0,0 +1,46 @@ <?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.ProjectCodingStatusMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.ycl.domain.vo.ProjectCodingStatusVO"> <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/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)); } }