From a0e8d1bbff7a02f538be76e852aa233324bd8810 Mon Sep 17 00:00:00 2001 From: fuliqi <fuliqi@qq.com> Date: 星期五, 03 一月 2025 13:31:51 +0800 Subject: [PATCH] 赋码 --- flowable/src/main/java/com/ycl/service/impl/ProcessCodingServiceImpl.java | 119 ++++++++ business/src/main/java/com/ycl/listener/flowable/FlowableOverTimeListener.java | 96 ++++++ flowable/src/main/java/com/ycl/common/constant/ProcessOverTimeConstants.java | 18 + flowable/src/main/java/com/ycl/service/ProcessCodingService.java | 66 ++++ flowable/src/main/java/com/ycl/mapper/ProcessCodingMapper.java | 39 ++ flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java | 104 +++--- flowable/src/main/java/com/ycl/domain/vo/ProcessCodingVO.java | 59 ++++ flowable/src/main/resources/mapper/ProcessCodingMapper.xml | 73 +++++ flowable/src/main/java/com/ycl/domain/dto/FlowTaskDto.java | 2 flowable/src/main/java/com/ycl/domain/dto/FlowViewerDto.java | 4 flowable/src/main/java/com/ycl/domain/query/ProcessCodingQuery.java | 22 + flowable/src/main/java/com/ycl/domain/form/ProcessCodingForm.java | 62 ++++ business/src/main/java/com/ycl/task/FlowableTask.java | 94 +++++- flowable/src/main/java/com/ycl/domain/entity/ProcessCoding.java | 49 +++ 14 files changed, 734 insertions(+), 73 deletions(-) diff --git a/business/src/main/java/com/ycl/listener/flowable/FlowableOverTimeListener.java b/business/src/main/java/com/ycl/listener/flowable/FlowableOverTimeListener.java new file mode 100644 index 0000000..6fde445 --- /dev/null +++ b/business/src/main/java/com/ycl/listener/flowable/FlowableOverTimeListener.java @@ -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锛堝垹闄わ級锛氬湪浠诲姟鍗冲皢琚垹闄ゅ墠瑙﹀彂銆傝娉ㄦ剰浠诲姟鐢眂ompleteTask姝e父瀹屾垚鏃朵篃浼氳Е鍙� + * + * @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鐨刡ean鑷繁绠$悊鐨勯渶瑕佹墜鍔ㄨ幏鍙� + 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鍜岃妭鐐瑰畾涔塱d鎵惧埌瀵瑰簲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("娣诲姞鑺傜偣鍒板畾鏃跺櫒"); + } + } +} diff --git a/business/src/main/java/com/ycl/task/FlowableTask.java b/business/src/main/java/com/ycl/task/FlowableTask.java index 7336100..5842b3b 100644 --- a/business/src/main/java/com/ycl/task/FlowableTask.java +++ b/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("寮�濮嬭祴鐮�"); + //褰撳墠姝e湪杩愯鐨勬墍鏈変换鍔¤妭鐐� 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涓簍askId value涓烘湰浣撳璞� + Map<String, ProcessCoding> taskMap = processCodingList.stream().collect(Collectors.toMap(ProcessCoding::getTaskId, Function.identity())); + //鎷垮埌寮�濮嬭鏃剁殑鑺傜偣闆嗗悎 key:taskId value:寮�濮嬫椂闂� + Map<String, Date> startTaskMap = getStartTaskList(processCodingList); + //鎻愬墠鍑嗗鎺ユ敹鏁版嵁鐨刴ap 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()); + //鏌ュ嚭璧峰璁℃椂鑺傜偣鏁版嵁 娉ㄦ剰姝e湪杩涜鐨勪换鍔′笉浼氳繘鍏is琛� 缁撴潫浜嗘墠浼氳繘鍏� 鎵�浠ラ渶瑕佹煡涓ゅ紶琛� + 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; + } + /** * 璧嬬爜 * diff --git a/flowable/src/main/java/com/ycl/common/constant/ProcessOverTimeConstants.java b/flowable/src/main/java/com/ycl/common/constant/ProcessOverTimeConstants.java new file mode 100644 index 0000000..10d736b --- /dev/null +++ b/flowable/src/main/java/com/ycl/common/constant/ProcessOverTimeConstants.java @@ -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"; +} diff --git a/flowable/src/main/java/com/ycl/domain/dto/FlowTaskDto.java b/flowable/src/main/java/com/ycl/domain/dto/FlowTaskDto.java index 1e639a4..d4af86e 100644 --- a/flowable/src/main/java/com/ycl/domain/dto/FlowTaskDto.java +++ b/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; } diff --git a/flowable/src/main/java/com/ycl/domain/dto/FlowViewerDto.java b/flowable/src/main/java/com/ycl/domain/dto/FlowViewerDto.java index 63f252f..73ba121 100644 --- a/flowable/src/main/java/com/ycl/domain/dto/FlowViewerDto.java +++ b/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; } diff --git a/flowable/src/main/java/com/ycl/domain/entity/ProcessCoding.java b/flowable/src/main/java/com/ycl/domain/entity/ProcessCoding.java new file mode 100644 index 0000000..4820b53 --- /dev/null +++ b/flowable/src/main/java/com/ycl/domain/entity/ProcessCoding.java @@ -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") + /** 璁℃椂鐨勮捣濮嬭妭鐐筰d */ + 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; + + +} diff --git a/flowable/src/main/java/com/ycl/domain/form/ProcessCodingForm.java b/flowable/src/main/java/com/ycl/domain/form/ProcessCodingForm.java new file mode 100644 index 0000000..933a331 --- /dev/null +++ b/flowable/src/main/java/com/ycl/domain/form/ProcessCodingForm.java @@ -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 = "璁℃椂鐨勮捣濮嬭妭鐐筰d涓嶈兘涓虹┖", groups = {Add.class, Update.class}) + @ApiModelProperty("璁℃椂鐨勮捣濮嬭妭鐐筰d") + 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("浠诲姟鐘舵�乬reen/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; + } + +} diff --git a/flowable/src/main/java/com/ycl/domain/query/ProcessCodingQuery.java b/flowable/src/main/java/com/ycl/domain/query/ProcessCodingQuery.java new file mode 100644 index 0000000..67bd159 --- /dev/null +++ b/flowable/src/main/java/com/ycl/domain/query/ProcessCodingQuery.java @@ -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 { +} + diff --git a/flowable/src/main/java/com/ycl/domain/vo/ProcessCodingVO.java b/flowable/src/main/java/com/ycl/domain/vo/ProcessCodingVO.java new file mode 100644 index 0000000..7282c21 --- /dev/null +++ b/flowable/src/main/java/com/ycl/domain/vo/ProcessCodingVO.java @@ -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; + + /** 璁℃椂鐨勮捣濮嬭妭鐐筰d */ + @ApiModelProperty("璁℃椂鐨勮捣濮嬭妭鐐筰d") + private String startTaskId; + + /** 娴佺▼瀹炰緥id */ + @ApiModelProperty("娴佺▼瀹炰緥id") + private String processInsId; + + /** 鍙橀粍鐮佺殑澶╂暟 */ + @ApiModelProperty("鍙橀粍鐮佺殑澶╂暟") + private Integer yellowTime; + + /** 鍙樼孩鐮佺殑澶╂暟 */ + @ApiModelProperty("鍙樼孩鐮佺殑澶╂暟") + private Integer redTime; + + /** 浠诲姟鐘舵��0杩涜涓�1缁撴潫 */ + @ApiModelProperty("浠诲姟鐘舵�乬reen/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; + } + +} diff --git a/flowable/src/main/java/com/ycl/mapper/ProcessCodingMapper.java b/flowable/src/main/java/com/ycl/mapper/ProcessCodingMapper.java new file mode 100644 index 0000000..829157c --- /dev/null +++ b/flowable/src/main/java/com/ycl/mapper/ProcessCodingMapper.java @@ -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); +} diff --git a/flowable/src/main/java/com/ycl/service/ProcessCodingService.java b/flowable/src/main/java/com/ycl/service/ProcessCodingService.java new file mode 100644 index 0000000..a270408 --- /dev/null +++ b/flowable/src/main/java/com/ycl/service/ProcessCodingService.java @@ -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(); +} diff --git a/flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java b/flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java index 09202bf..26a400d 100644 --- a/flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java +++ b/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; /** * 瀹屾垚瀹℃牳浠诲姟 @@ -114,8 +121,8 @@ /** * 瀹屾垚琛ㄥ崟鎻愪氦浠诲姟/鏅�氫换鍔� * - * @param taskId 浠诲姟id - * @param variables 琛ㄥ崟鏁版嵁 + * @param taskId 浠诲姟id + * @param variables 琛ㄥ崟鏁版嵁 * @return */ @Override @@ -126,7 +133,7 @@ return AjaxResult.error("浠诲姟涓嶅瓨鍦�"); } Map<String, Object> newV = new HashMap<>(2); - if (! org.springframework.util.CollectionUtils.isEmpty(variables)) { + if (!org.springframework.util.CollectionUtils.isEmpty(variables)) { for (String key : variables.keySet()) { newV.put(task.getTaskDefinitionKey() + "&" + key, variables.get(key)); // if (ProcessConstants.TASK_FORM_KEY.equals(key)) { @@ -310,7 +317,6 @@ if (!isSequential) { throw new CustomException("褰撳墠鑺傜偣鐩稿浜庣洰鏍囪妭鐐癸紝涓嶅睘浜庝覆琛屽叧绯伙紝鏃犳硶鍥為��"); } - // 鑾峰彇鎵�鏈夋甯歌繘琛岀殑浠诲姟鑺傜偣 Key锛岃繖浜涗换鍔′笉鑳界洿鎺ヤ娇鐢紝闇�瑕佹壘鍑哄叾涓渶瑕佹挙鍥炵殑浠诲姟 List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); @@ -792,11 +798,11 @@ .processInstanceId(procInsId) .orderByHistoricActivityInstanceStartTime() .desc().list(); - Date now =new Date(); - //鎵╁睍 - List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery() - .processInstanceId(procInsId) - .list(); + Date now = new Date(); + //鎵╁睍 鑾峰彇杩欎釜娴佺▼瀹炰緥鐨勭洃鎺т俊鎭� 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) ) { - //濡傛灉浠诲姟杩樻病瀹屾垚 - if(flowTask.getDuration()==null) { - //鍒ゆ柇褰撳墠鏃堕棿鏄惁瓒呰繃鍒版湡鏃堕棿 - if (now.after(dueDate)) flowTask.setOvertime(Boolean.TRUE); - }else { - //濡傛灉浠诲姟鑺傜偣宸茬粡瀹屾垚浜嗭紝鐢ㄥ畬鎴愭椂闂村垽鏂� - if(histIns.getEndTime().after(dueDate)) flowTask.setOvertime(Boolean.TRUE); + ProcessCoding processCoding = processCodingMap.get(histIns.getTaskId()); + if(processCoding!=null){ + //濡傛灉浠诲姟鏄唬鍔炶妭鐐� + if (flowTask.getDuration() == null) { + 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); - //鎵╁睍鍐呭 浠e姙鐨勯�氳繃褰撳墠鏃堕棿鍘诲垽鏂� - for (Task task : taskList) { - if(s.getTaskId()!=null && s.getTaskId().equals(task.getId())){ - if(task.getDueDate()!=null && now.after(task.getDueDate())){ - flowViewerDto.setOvertime(true); - } - } + // 鎵╁睍鍐呭 浠e姙鐨勯�氳繃褰撳墠鏃堕棿浣滀负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("楂樹寒鍘嗗彶浠诲姟澶辫触"); } } @@ -1234,15 +1229,15 @@ /** * 鑾峰彇褰撳墠鑺傜偣鍜屼笂涓�鑺傜偣鐨勮〃鍗曞唴瀹� * - * @param parameters 鏍规嵁浠诲姟鏌ユ壘鍑烘潵鐨勫弬鏁� - * @param formKey task鑷韩鍏宠仈鐨勮〃鍗昳d - * @param taskName task鑷韩鐨勪换鍔″悕 - * @param processDefId 娴佺▼瀹氫箟id + * @param parameters 鏍规嵁浠诲姟鏌ユ壘鍑烘潵鐨勫弬鏁� + * @param formKey task鑷韩鍏宠仈鐨勮〃鍗昳d + * @param taskName task鑷韩鐨勪换鍔″悕 + * @param processDefId 娴佺▼瀹氫箟id * @param processDefKey 娴佺▼瀹炰緥id * @return */ private List<FormDetailVO> getBeforeNodeForm(Map<String, Object> parameters, String formKey, String taskName, String processDefId, String processDefKey, Boolean currentNeedData) { - if (! parameters.keySet().stream().anyMatch(key -> key.contains(ProcessConstants.TASK_FORM_KEY))) { + if (!parameters.keySet().stream().anyMatch(key -> key.contains(ProcessConstants.TASK_FORM_KEY))) { // 濡傛灉鏄┖鐨勶紝浣跨敤formId鍘绘煡 if (StringUtils.isNotBlank(formKey)) { SysForm sysForm = sysFormService.selectSysFormById(Long.parseLong(formKey)); @@ -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)); } } diff --git a/flowable/src/main/java/com/ycl/service/impl/ProcessCodingServiceImpl.java b/flowable/src/main/java/com/ycl/service/impl/ProcessCodingServiceImpl.java new file mode 100644 index 0000000..a40d634 --- /dev/null +++ b/flowable/src/main/java/com/ycl/service/impl/ProcessCodingServiceImpl.java @@ -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()); + + // 涓虹┖鎶汭llegalArgumentException锛屽仛鍏ㄥ眬寮傚父澶勭悊 + 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); + } +} diff --git a/flowable/src/main/resources/mapper/ProcessCodingMapper.xml b/flowable/src/main/resources/mapper/ProcessCodingMapper.xml new file mode 100644 index 0000000..c87910b --- /dev/null +++ b/flowable/src/main/resources/mapper/ProcessCodingMapper.xml @@ -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> + + <!-- 鑷畾涔夋壒閲忔洿鏂�,浣跨敤鍓嶅垽鏂璴ist鏄惁涓虹┖ 杞崲涓簊ql + 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,"><!-- 鏋勯�燾ase璇硶 鏈熬鍔犱笂end锛屽鏋滈渶瑕佹洿鏂板涓瓧娈靛鍒惰繖涓猼rim --> + <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> -- Gitblit v1.8.0