business/src/main/java/com/ycl/listener/flowable/FlowableOverTimeListener.java
New file @@ -0,0 +1,96 @@ package com.ycl.listener.flowable; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.ycl.common.utils.spring.SpringUtils; import com.ycl.domain.entity.ProcessCoding; import com.ycl.factory.FlowServiceFactory; import com.ycl.mapper.ProcessCodingMapper; import lombok.extern.slf4j.Slf4j; import org.flowable.common.engine.impl.el.FixedValue; import org.flowable.engine.delegate.TaskListener; import org.flowable.task.api.history.HistoricTaskInstance; import org.flowable.task.service.delegate.DelegateTask; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; import static com.ycl.common.constant.ProcessOverTimeConstants.GREEN; /** * 任务监听器 * * create(创建):在任务被创建且所有的任务属性设置完成后才触发 * assignment(指派):在任务被分配给某个办理人之后触发 * complete(完成):在配置了监听器的上一个任务完成时触发 * delete(删除):在任务即将被删除前触发。请注意任务由completeTask正常完成时也会触发 * * @author Tony * @date 2021/4/20 */ @Slf4j @Component public class FlowableOverTimeListener extends FlowServiceFactory implements TaskListener { /** * 黄码时间 */ private FixedValue yellowTime; /** * 红码时间 */ private FixedValue redTime; /** * 计时起始节点定义Id */ private FixedValue startTaskId; @Override public void notify(DelegateTask delegateTask) { log.info("触发超时监听器:{}", delegateTask); //Flowable的bean自己管理的需要手动获取 ProcessCodingMapper processCodingMapper = SpringUtils.getBean(ProcessCodingMapper.class); //任务id String taskId = delegateTask.getId(); //流程实例id String processInstanceId = delegateTask.getProcessInstanceId(); ProcessCoding processCoding = new ProcessCoding(); processCoding.setTaskId(taskId); processCoding.setProcessInsId(processInstanceId); processCoding.setTaskDefKey(delegateTask.getTaskDefinitionKey()); //涉及到驳回,需要查一下这个节点是否已经添加过了,如果添加过就不进行后续操作 List<ProcessCoding> processCodings = processCodingMapper.selectList(new QueryWrapper<ProcessCoding>() .eq("process_ins_id", processInstanceId) .eq("task_def_key", delegateTask.getTaskDefinitionKey())); if (CollectionUtils.isEmpty(processCodings)) { processCoding.setStatus(GREEN); if (yellowTime != null && yellowTime.getValue(delegateTask) != null) { processCoding.setYellowTime(Integer.parseInt(yellowTime.getValue(delegateTask).toString())); } if (redTime != null && redTime.getValue(delegateTask) != null) { processCoding.setRedTime(Integer.parseInt(redTime.getValue(delegateTask).toString())); } if (startTaskId != null && startTaskId.getValue(delegateTask) != null) { String taskDefKey = startTaskId.getValue(delegateTask).toString(); //通过流程实例id和节点定义id找到对应taskId if (delegateTask.getTaskDefinitionKey().equals(taskDefKey)) { //当前节点为开始计时节点 processCoding.setStartTaskId(delegateTask.getId()); } else { //开始节点从历史节点查询 取多条中最早的一条 List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInstanceId) .taskDefinitionKey(delegateTask.getTaskDefinitionKey()) .orderByHistoricTaskInstanceStartTime() .asc() .list(); if (!CollectionUtils.isEmpty(list)) { HistoricTaskInstance hisTask = list.get(0); processCoding.setStartTaskId(hisTask.getId()); } } } processCodingMapper.insert(processCoding); log.info("添加节点到定时器"); } } } business/src/main/java/com/ycl/task/FlowableTask.java
@@ -2,23 +2,27 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.ycl.domain.entity.ProcessCoding; import com.ycl.domain.entity.ProjectInfo; import com.ycl.domain.entity.ProjectProcess; import com.ycl.factory.FlowServiceFactory; import com.ycl.mapper.ProcessCodingMapper; import com.ycl.mapper.ProjectInfoMapper; import com.ycl.mapper.ProjectProcessMapper; import com.ycl.service.ProjectProcessService; import com.ycl.service.ProcessCodingService; import lombok.extern.slf4j.Slf4j; import org.flowable.task.api.Task; import org.flowable.task.api.TaskInfo; import org.flowable.task.api.history.HistoricTaskInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.Date; import java.util.List; import java.util.Map; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import static com.ycl.common.constant.ProcessOverTimeConstants.*; @Slf4j @Component("flowableTask") @@ -27,28 +31,88 @@ private ProjectProcessMapper projectProcessMapper; @Autowired private ProjectInfoMapper projectInfoMapper; @Autowired private ProcessCodingMapper processCodingMapper; /** * 赋码任务 * 两个逻辑 改项目码、改节点颜色 */ public void expireTask() { log.info("开始赋码"); //当前正在运行的所有任务节点 List<Task> taskList = taskService.createTaskQuery().list(); if (!CollectionUtils.isEmpty(taskList)) { if(CollectionUtils.isEmpty(taskList)) return; List<String> taskIds = taskList.stream().map(TaskInfo::getId).collect(Collectors.toList()); //需要监控的赋码任务 List<ProcessCoding> processCodingList = processCodingMapper.selectList(new QueryWrapper<ProcessCoding>().in("task_id",taskIds)); if (!CollectionUtils.isEmpty(processCodingList)) { //key为taskId value为本体对象 Map<String, ProcessCoding> taskMap = processCodingList.stream().collect(Collectors.toMap(ProcessCoding::getTaskId, Function.identity())); //拿到开始计时的节点集合 key:taskId value:开始时间 Map<String, Date> startTaskMap = getStartTaskList(processCodingList); //提前准备接收数据的map key:流程实例id value:需要改变的颜色 Map<String, List<String>> map = new HashMap<>(); List<ProcessCoding> list = new ArrayList<>(); map.put(GREEN, new ArrayList<>()); map.put(RED, new ArrayList<>()); map.put(YELLOW, new ArrayList<>()); Date now = new Date(); // 按超时状态分组任务 Map<Boolean, List<String>> processInstanceMap = taskList.stream() .collect(Collectors.groupingBy( task -> task.getDueDate() != null && now.after(task.getDueDate()), Collectors.mapping(TaskInfo::getProcessInstanceId, Collectors.toList()) )); // 处理超时和未超时的项目 updateProjectCoding(processInstanceMap.get(true), "red"); // 超时项目 updateProjectCoding(processInstanceMap.get(false), "green"); // 未超时项目 //遍历所有代办的节点 for (Task task : taskList) { String taskId = task.getId(); ProcessCoding processCoding = taskMap.get(taskId); if (processCoding == null) { //不需要监控的任务节点直接改为绿色 List<String> processInsIds = map.get(GREEN); processInsIds.add(task.getProcessInstanceId()); continue; } //判断是否超时 Date startTime = startTaskMap.get(processCoding.getStartTaskId()); Integer yellowTime = processCoding.getYellowTime(); Integer redTime = processCoding.getRedTime(); if (startTime == null) continue; // long durationDay = (now.getTime() - startTime.getTime()) / (1000 * 60 * 60 * 24); long durationDay = (now.getTime() - startTime.getTime()) / (1000 * 60); String status = GREEN; // 默认状态为绿色 if (redTime != null && durationDay >= redTime) { status = RED; // 如果超过红色时间阈值,则状态为红色 } else if (yellowTime != null && durationDay >= yellowTime) { status = YELLOW; // 否则,如果超过黄色时间阈值,则状态为黄色 } List<String> processInsIds = map.get(status); processInsIds.add(task.getProcessInstanceId()); processCoding.setStatus(status); list.add(processCoding); } //更新项目码 map.forEach((key,value)-> updateProjectCoding(value, key)); //更新节点状态 自定义的mybatis方法 if(!CollectionUtils.isEmpty(list)) processCodingMapper.updateBatch(list); } log.info("结束赋码"); } private Map<String, Date> getStartTaskList(List<ProcessCoding> processCodingList) { //查出任务计时起始节点集合 List<String> startTaskIds = processCodingList.stream().map(ProcessCoding::getStartTaskId).collect(Collectors.toList()); //查出起始计时节点数据 注意正在进行的任务不会进入his表 结束了才会进入 所以需要查两张表 Map<String, Date> startDateMap = new HashMap<>(); List<Task> startTasks = taskService.createTaskQuery().taskIds(startTaskIds).list(); List<HistoricTaskInstance> hisStartTasks = historyService.createHistoricTaskInstanceQuery().taskIds(startTaskIds).list(); if (!CollectionUtils.isEmpty(startTasks)) { startTasks.forEach(task -> { startDateMap.put(task.getId(), task.getCreateTime()); }); } if (!CollectionUtils.isEmpty(hisStartTasks)) { hisStartTasks.forEach(hisTask -> { startDateMap.put(hisTask.getId(), hisTask.getStartTime()); }); } return startDateMap; } /** * 赋码 * flowable/src/main/java/com/ycl/common/constant/ProcessOverTimeConstants.java
New file @@ -0,0 +1,18 @@ package com.ycl.common.constant; public class ProcessOverTimeConstants { /** * 绿码 */ public static final String GREEN = "green"; /** * 红码 */ public static final String RED = "red"; /** * 黄码 */ public static final String YELLOW = "yellow"; } flowable/src/main/java/com/ycl/domain/dto/FlowTaskDto.java
@@ -99,6 +99,6 @@ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date finishTime; private Boolean overtime; private String overtime; } flowable/src/main/java/com/ycl/domain/dto/FlowViewerDto.java
@@ -22,7 +22,7 @@ private boolean completed; /** * 是否已经超时 * 项目超时颜色码 green/yellow/red */ private boolean overtime; private String overtime; } flowable/src/main/java/com/ycl/domain/entity/ProcessCoding.java
New file @@ -0,0 +1,49 @@ package com.ycl.domain.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.ycl.system.domain.base.AbsEntity; import lombok.Data; /** * * * @author flq * @since 2025-01-02 */ @Data @TableName("t_process_coding") public class ProcessCoding extends AbsEntity { private static final long serialVersionUID = 1L; @TableField("task_id") /** 节点id */ private String taskId; @TableField("task_def_key") /** 节点定义key */ private String taskDefKey; @TableField("start_task_id") /** 计时的起始节点id */ private String startTaskId; @TableField("process_ins_id") /** 流程实例id */ private String processInsId; @TableField("yellow_time") /** 变黄码的天数 */ private Integer yellowTime; @TableField("red_time") /** 变红码的天数 */ private Integer redTime; @TableField("status") /** 任务状态 */ private String status; } flowable/src/main/java/com/ycl/domain/form/ProcessCodingForm.java
New file @@ -0,0 +1,62 @@ 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.ProcessCoding; 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 flq * @since 2025-01-02 */ @Data @ApiModel(value = "ProcessCoding表单", description = "表单") public class ProcessCodingForm extends AbsForm { @NotBlank(message = "节点id不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("节点id") private String taskId; @NotBlank(message = "节点定义key不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("节点定义key") private String taskDefKey; @NotBlank(message = "计时的起始节点id不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("计时的起始节点id") private String startTaskId; @NotBlank(message = "流程实例id不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("流程实例id") private String processInsId; @NotNull(message = "变黄码的天数不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("变黄码的天数") private Integer yellowTime; @NotNull(message = "变红码的天数不能为空", groups = {Add.class, Update.class}) @ApiModelProperty("变红码的天数") private Integer redTime; @NotNull(message = "任务状态", groups = {Add.class, Update.class}) @ApiModelProperty("任务状态green/yellow/red") private String status; public static ProcessCoding getEntityByForm(@NonNull ProcessCodingForm form, ProcessCoding entity) { if(entity == null) { entity = new ProcessCoding(); } BeanUtils.copyProperties(form, entity); return entity; } } flowable/src/main/java/com/ycl/domain/query/ProcessCodingQuery.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 flq * @since 2025-01-02 */ @Data @ApiModel(value = "ProcessCoding查询参数", description = "查询参数") public class ProcessCodingQuery extends AbsQuery { } flowable/src/main/java/com/ycl/domain/vo/ProcessCodingVO.java
New file @@ -0,0 +1,59 @@ package com.ycl.domain.vo; import com.ycl.system.domain.base.AbsVo; import com.ycl.domain.entity.ProcessCoding; 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 flq * @since 2025-01-02 */ @Data @ApiModel(value = "响应数据", description = "响应数据") public class ProcessCodingVO extends AbsVo { /** 节点id */ @ApiModelProperty("节点id") private String taskId; /** 节点定义key */ @ApiModelProperty("节点定义key") private String taskDefKey; /** 计时的起始节点id */ @ApiModelProperty("计时的起始节点id") private String startTaskId; /** 流程实例id */ @ApiModelProperty("流程实例id") private String processInsId; /** 变黄码的天数 */ @ApiModelProperty("变黄码的天数") private Integer yellowTime; /** 变红码的天数 */ @ApiModelProperty("变红码的天数") private Integer redTime; /** 任务状态0进行中1结束 */ @ApiModelProperty("任务状态green/red/yellow") private String status; public static ProcessCodingVO getVoByEntity(@NonNull ProcessCoding entity, ProcessCodingVO vo) { if(vo == null) { vo = new ProcessCodingVO(); } BeanUtils.copyProperties(entity, vo); return vo; } } flowable/src/main/java/com/ycl/mapper/ProcessCodingMapper.java
New file @@ -0,0 +1,39 @@ package com.ycl.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ycl.domain.entity.ProcessCoding; import com.ycl.domain.query.ProcessCodingQuery; import com.ycl.domain.vo.ProcessCodingVO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; /** * Mapper 接口 * * @author flq * @since 2025-01-02 */ @Mapper public interface ProcessCodingMapper extends BaseMapper<ProcessCoding> { /** * id查找 * @param id * @return */ ProcessCodingVO getById(Integer id); /** * 分页 */ IPage getPage(IPage page, @Param("query") ProcessCodingQuery query); /** * 自定义批量更新 * @param list */ void updateBatch(@Param("list") List<ProcessCoding> list); } flowable/src/main/java/com/ycl/service/ProcessCodingService.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.ProcessCoding; import com.ycl.domain.form.ProcessCodingForm; import com.ycl.domain.query.ProcessCodingQuery; import java.util.List; /** * 服务类 * * @author flq * @since 2025-01-02 */ public interface ProcessCodingService extends IService<ProcessCoding> { /** * 添加 * @param form * @return */ Result add(ProcessCodingForm form); /** * 修改 * @param form * @return */ Result update(ProcessCodingForm form); /** * 批量删除 * @param ids * @return */ Result remove(List<String> ids); /** * id删除 * @param id * @return */ Result removeById(String id); /** * 分页查询 * @param query * @return */ Result page(ProcessCodingQuery query); /** * 根据id查找 * @param id * @return */ Result detail(Integer id); /** * 列表 * @return */ Result all(); } flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java
@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.TypeReference; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ycl.common.constant.ProcessConstants; import com.ycl.common.core.domain.AjaxResult; @@ -17,6 +18,7 @@ import com.ycl.domain.dto.FlowNextDto; import com.ycl.domain.dto.FlowTaskDto; import com.ycl.domain.dto.FlowViewerDto; import com.ycl.domain.entity.ProcessCoding; import com.ycl.domain.entity.SysForm; import com.ycl.domain.vo.FlowQueryVo; import com.ycl.domain.vo.FlowTaskVo; @@ -25,6 +27,7 @@ import com.ycl.flow.CustomProcessDiagramGenerator; import com.ycl.flow.FindNextNodeUtil; import com.ycl.flow.FlowableUtils; import com.ycl.mapper.ProcessCodingMapper; import com.ycl.service.IFlowTaskService; import com.ycl.service.ISysDeployFormService; import com.ycl.service.ISysFormService; @@ -71,6 +74,9 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import static com.ycl.common.constant.ProcessOverTimeConstants.RED; import static com.ycl.common.constant.ProcessOverTimeConstants.YELLOW; /** * @author Tony * @date 2021-04-03 @@ -86,6 +92,7 @@ private final ISysDeployFormService sysInstanceFormService; private final ISysFormService sysFormService; private final TaskCommonService taskCommonService; private final ProcessCodingMapper processCodingMapper; /** * 完成审核任务 @@ -310,7 +317,6 @@ if (!isSequential) { throw new CustomException("当前节点相对于目标节点,不属于串行关系,无法回退"); } // 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务 List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); @@ -793,10 +799,10 @@ .orderByHistoricActivityInstanceStartTime() .desc().list(); Date now =new Date(); //扩展 List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(procInsId) .list(); //扩展 获取这个流程实例的监控信息 key:TaskId value:实体类 Map<String, ProcessCoding> processCodingMap = processCodingMapper.selectList(new QueryWrapper<ProcessCoding>().eq("process_ins_id", procInsId)) .stream() .collect(Collectors.toMap(ProcessCoding::getTaskId, Function.identity())); List<FlowTaskDto> hisFlowList = new ArrayList<>(); for (HistoricActivityInstance histIns : list) { // 展示开始节点 @@ -855,21 +861,19 @@ } flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis())); String taskId = histIns.getTaskId(); //扩展 判断是否超时 for (HistoricTaskInstance taskInstance : taskList) { Date dueDate = taskInstance.getDueDate(); //找到对应任务节点 if(dueDate!=null && taskInstance.getId().equals(taskId) ) { //如果任务还没完成 ProcessCoding processCoding = processCodingMap.get(histIns.getTaskId()); if(processCoding!=null){ //如果任务是代办节点 if(flowTask.getDuration()==null) { //判断当前时间是否超过到期时间 if (now.after(dueDate)) flowTask.setOvertime(Boolean.TRUE); }else { //如果任务节点已经完成了,用完成时间判断 if(histIns.getEndTime().after(dueDate)) flowTask.setOvertime(Boolean.TRUE); if(RED.equals(processCoding.getStatus()) || YELLOW.equals(processCoding.getStatus())){ flowTask.setOvertime(processCoding.getStatus()); } }else { //如果任务节点属于历史节点 if(RED.equals(processCoding.getStatus())){ flowTask.setOvertime(processCoding.getStatus()); }; } } // 获取意见评论内容 @@ -1117,35 +1121,28 @@ @Override public AjaxResult flowXmlAndNode(String procInsId, String deployId) { try { Date now = new Date(); List<FlowViewerDto> flowViewerList = new ArrayList<>(); // 获取已经完成的节点 List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery() .processInstanceId(procInsId) .finished() .list(); //获取所有历史任务节点信息(扩展) List<HistoricTaskInstance> taskHistoryList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(procInsId) .finished() .list(); //获取所有当前任务节点信息(扩展) List<Task> taskList = taskService.createTaskQuery() .processInstanceId(procInsId) .list(); //获取这个流程实例的监控信息 key:TaskId value:实体类 Map<String, ProcessCoding> processCodingMap = processCodingMapper.selectList(new QueryWrapper<ProcessCoding>().eq("process_ins_id", procInsId)) .stream() .collect(Collectors.toMap(ProcessCoding::getTaskId, Function.identity())); // 保存已经完成的流程节点编号 listFinished.forEach(s -> { FlowViewerDto flowViewerDto = new FlowViewerDto(); flowViewerDto.setKey(s.getActivityId()); flowViewerDto.setCompleted(true); //扩展内容 已完成的用完成时间判断 Date endTime = s.getEndTime(); for (HistoricTaskInstance task : taskHistoryList) { if(s.getTaskId()!=null && s.getTaskId().equals(task.getId())){ if(task.getDueDate()!=null && endTime.after(task.getDueDate())){ flowViewerDto.setOvertime(true); } } //扩展内容 不反overtime前端默认是绿色 ProcessCoding processCoding = processCodingMap.get(s.getTaskId()); //如果有监控数据, 历史节点只判断红码 if (processCoding != null && RED.equals(processCoding.getStatus())) { flowViewerDto.setOvertime(processCoding.getStatus()); } // 退回节点不进行展示 if (StringUtils.isBlank(s.getDeleteReason())) { @@ -1158,7 +1155,6 @@ .processInstanceId(procInsId) .unfinished() .list(); // 保存需要代办的节点编号 listUnFinished.forEach(s -> { // 删除已退回节点 @@ -1166,13 +1162,11 @@ FlowViewerDto flowViewerDto = new FlowViewerDto(); flowViewerDto.setKey(s.getActivityId()); flowViewerDto.setCompleted(false); //扩展内容 代办的通过当前时间去判断 for (Task task : taskList) { if(s.getTaskId()!=null && s.getTaskId().equals(task.getId())){ if(task.getDueDate()!=null && now.after(task.getDueDate())){ flowViewerDto.setOvertime(true); } } // 扩展内容 代办的通过当前时间作为endTime ProcessCoding processCoding = processCodingMap.get(s.getTaskId()); //如果有监控数据 不反的话前端默认是进行中(蓝色) if (processCoding != null && (RED.equals(processCoding.getStatus()) || YELLOW.equals(processCoding.getStatus()))) { flowViewerDto.setOvertime(processCoding.getStatus()); } flowViewerList.add(flowViewerDto); }); @@ -1185,6 +1179,7 @@ result.put("xmlData", xmlData); return AjaxResult.success(result); } catch (Exception e) { e.printStackTrace(); return AjaxResult.error("高亮历史任务失败"); } } @@ -1277,8 +1272,7 @@ if (key.startsWith(formDetailVO.getBeforeNodeDefId())) { if (key.contains(ProcessConstants.TASK_FORM_KEY)) { newP.put(key, parameters.get(key)); } else { } else { newP.put(key.split("&")[1], parameters.get(key)); } } flowable/src/main/java/com/ycl/service/impl/ProcessCodingServiceImpl.java
New file @@ -0,0 +1,119 @@ package com.ycl.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.common.base.Result; import com.ycl.domain.entity.ProcessCoding; import com.ycl.domain.form.ProcessCodingForm; import com.ycl.domain.query.ProcessCodingQuery; import com.ycl.domain.vo.ProcessCodingVO; import com.ycl.framework.utils.PageUtil; import com.ycl.mapper.ProcessCodingMapper; import com.ycl.service.ProcessCodingService; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import java.util.List; import java.util.stream.Collectors; /** * 服务实现类 * * @author flq * @since 2025-01-02 */ @Service @RequiredArgsConstructor public class ProcessCodingServiceImpl extends ServiceImpl<ProcessCodingMapper, ProcessCoding> implements ProcessCodingService { private final ProcessCodingMapper processCodingMapper; /** * 添加 * @param form * @return */ @Override public Result add(ProcessCodingForm form) { ProcessCoding entity = ProcessCodingForm.getEntityByForm(form, null); baseMapper.insert(entity); return Result.ok("添加成功"); } /** * 修改 * @param form * @return */ @Override public Result update(ProcessCodingForm form) { ProcessCoding 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(ProcessCodingQuery query) { IPage<ProcessCodingVO> page = PageUtil.getPage(query, ProcessCodingVO.class); baseMapper.getPage(page, query); return Result.ok().data(page.getRecords()).total(page.getTotal()); } /** * 根据id查找 * @param id * @return */ @Override public Result detail(Integer id) { ProcessCodingVO vo = baseMapper.getById(id); Assert.notNull(vo, "记录不存在"); return Result.ok().data(vo); } /** * 列表 * @return */ @Override public Result all() { List<ProcessCoding> entities = baseMapper.selectList(null); List<ProcessCodingVO> vos = entities.stream() .map(entity -> ProcessCodingVO.getVoByEntity(entity, null)) .collect(Collectors.toList()); return Result.ok().data(vos); } } flowable/src/main/resources/mapper/ProcessCodingMapper.xml
New file @@ -0,0 +1,73 @@ <?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.ProcessCodingMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.ycl.domain.vo.ProcessCodingVO"> <result column="task_id" property="taskId" /> <result column="task_def_key" property="taskDefKey" /> <result column="start_task_id" property="startTaskId" /> <result column="process_ins_id" property="processInsId" /> <result column="yellow_time" property="yellowTime" /> <result column="red_time" property="redTime" /> <result column="status" property="status" /> </resultMap> <select id="getById" resultMap="BaseResultMap"> SELECT TPC.task_id, TPC.task_def_key, TPC.start_task_id, TPC.process_ins_id, TPC.yellow_time, TPC.red_time, TPC.status, TPC.id FROM t_process_coding TPC WHERE TPC.id = #{id} AND TPC.deleted = 0 </select> <select id="getPage" resultMap="BaseResultMap"> SELECT TPC.task_id, TPC.task_def_key, TPC.start_task_id, TPC.process_ins_id, TPC.yellow_time, TPC.red_time, TPC.status, TPC.id FROM t_process_coding TPC WHERE TPC.deleted = 0 </select> <!-- 自定义批量更新,使用前判断list是否为空 转换为sql update t_process_coding set status = case when id = #{item.id} then #{item.status} ... end where id in (...);--> <update id="updateBatch" parameterType="java.util.List"> update t_process_coding <trim prefix="set" suffixOverrides=","><!-- 表示在生成的 SQL 语句前面添加 set 关键字,并移除末尾逗号 --> <trim prefix="status =case" suffix="end,"><!-- 构造case语法 末尾加上end,如果需要更新多个字段复制这个trim --> <foreach collection="list" item="item"> when id=#{item.id} then #{item.status} </foreach> </trim> </trim> where id in <foreach collection="list" index="index" item="item" separator="," open="(" close=")"> #{item.id,jdbcType=BIGINT} </foreach> </update> </mapper>