yangys
2025-08-23 60eff99d978e557821ce9a73460db9d03deb5ed6
增加撤回功能
已添加3个文件
已修改3个文件
320 ■■■■■ 文件已修改
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/FlowMgrController.java 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowableBackWithAssigneeService.java 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/WIthdrawService.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/WithdrawProperties.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
blade-service/blade-mdm/src/main/java/org/springblade/mdm/test/MyTest2Controller.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
blade-service/blade-mdm/src/main/java/org/springblade/mdm/test/MyTestController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/FlowMgrController.java
@@ -5,10 +5,10 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.mail.MessagingException;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.history.HistoricTaskInstance;
@@ -18,9 +18,9 @@
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.mdm.flow.service.ApproveRecordService;
import org.springblade.mdm.flow.service.ApproveTableService;
import org.springblade.mdm.flow.service.FlowBusinessService;
import org.springblade.mdm.flow.service.WIthdrawService;
import org.springblade.mdm.flow.vo.FlowVO;
import org.springblade.mdm.flow.vo.OvertimeTaskExcelVO;
import org.springblade.mdm.flow.vo.TaskTraceVO;
@@ -31,6 +31,7 @@
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
@@ -51,13 +52,13 @@
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private ApproveTableService approveTableService;
    @Autowired
    private ApproveRecordService approveRecordService;
    @Autowired
    private IUserClient userClient;
    @Autowired
    private WIthdrawService withdrawService;
    @GetMapping("overtime-list")
    @ApiOperationSupport(order = 3)
    @Operation(summary = "超时查询", description = "查询所有超时任务")
@@ -182,4 +183,16 @@
        }
    }
    @GetMapping("/withdraw")
    @Operation(summary = "撤回任务", description = "从其他任务节点直接撤回编程员节点")
    public R<Void> withdraw(String processInstanceId)  {
        try {
            withdrawService.withdraw(processInstanceId);
            return R.success();
        }catch(Exception e) {
            log.error("<UNK>", e);
            return R.fail(e.getMessage());
        }
    }
}
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowableBackWithAssigneeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,161 @@
package org.springblade.mdm.flow.service;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
@Service
public class FlowableBackWithAssigneeService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    /**
     * å°†æµç¨‹é€€å›žåˆ°æŒ‡å®šä»»åŠ¡èŠ‚ç‚¹å¹¶æŒ‡å®šæ–°çš„å¤„ç†äºº
     * @param currentTaskId å½“前任务ID
     * @param targetActivityId ç›®æ ‡æ´»åŠ¨èŠ‚ç‚¹ID
     * @param newAssignee æ–°çš„处理人
     * @param comment é€€å›žæ„è§
     * @param variables æµç¨‹å˜é‡
     */
    @Transactional
    public void backToTaskWithNewAssignee(String currentTaskId,
                                          String targetActivityId,
                                          String newAssignee,
                                          String comment,
                                          Map<String, Object> variables) {
        // èŽ·å–å½“å‰ä»»åŠ¡
        Task currentTask = taskService.createTaskQuery()
            .taskId(currentTaskId)
            .singleResult();
        if (currentTask == null) {
            throw new RuntimeException("当前任务不存在");
        }
        String processInstanceId = currentTask.getProcessInstanceId();
        // æ·»åŠ è¯„è®º
        if (comment != null && !comment.trim().isEmpty()) {
            taskService.addComment(currentTaskId, processInstanceId, comment);
        }
        // éªŒè¯ç›®æ ‡èŠ‚ç‚¹æ˜¯å¦å­˜åœ¨
        validateTargetActivity(processInstanceId, targetActivityId);
        // ä½¿ç”¨è¿è¡Œæ—¶æœåŠ¡è·³è½¬åˆ°ç›®æ ‡èŠ‚ç‚¹
        runtimeService.createChangeActivityStateBuilder()
            .processInstanceId(processInstanceId)
            .moveActivityIdTo(currentTask.getTaskDefinitionKey(), targetActivityId)
            .changeState();
        // èŽ·å–æ–°åˆ›å»ºçš„ä»»åŠ¡ï¼ˆé€€å›žåŽäº§ç”Ÿçš„ä»»åŠ¡ï¼‰
        Task newTask = taskService.createTaskQuery()
            .processInstanceId(processInstanceId)
            .taskDefinitionKey(targetActivityId)
            .singleResult();
        if (newTask != null) {
            // è®¾ç½®æ–°çš„处理人
            if (newAssignee != null && !newAssignee.trim().isEmpty()) {
                taskService.setAssignee(newTask.getId(), newAssignee);
            }
            // è®¾ç½®æµç¨‹å˜é‡
            if (variables != null && !variables.isEmpty()) {
                taskService.setVariables(newTask.getId(), variables);
            }
        }
        // åˆ é™¤å½“前任务
        taskService.deleteTask(currentTaskId, "退回流程并指定新处理人: " + newAssignee);
    }
    /**
     * é€€å›žå¹¶ä¿ç•™åŽŸå¤„ç†äººä¿¡æ¯ï¼ˆè®°å½•åŽ†å²ï¼‰
     */
    @Transactional
    public void backToTaskWithOriginalAssignee(String currentTaskId,
                                               String targetActivityId,
                                               String comment) {
        Task currentTask = taskService.createTaskQuery()
            .taskId(currentTaskId)
            .singleResult();
        if (currentTask == null) {
            throw new RuntimeException("当前任务不存在");
        }
        String processInstanceId = currentTask.getProcessInstanceId();
        // èŽ·å–ç›®æ ‡èŠ‚ç‚¹çš„åŽ†å²ä»»åŠ¡ä¿¡æ¯
        HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery()
            .processInstanceId(processInstanceId)
            .taskDefinitionKey(targetActivityId)
            .orderByHistoricTaskInstanceEndTime().desc()
            .list()
            .stream()
            .findFirst()
            .orElse(null);
        String originalAssignee = historicTask != null ? historicTask.getAssignee() : null;
        // æ‰§è¡Œé€€å›žæ“ä½œ
        backToTaskWithNewAssignee(currentTaskId, targetActivityId, originalAssignee, comment, null);
    }
    /**
     * éªŒè¯ç›®æ ‡æ´»åŠ¨èŠ‚ç‚¹æ˜¯å¦å­˜åœ¨
     */
    private void validateTargetActivity(String processInstanceId, String targetActivityId) {
        List<HistoricActivityInstance> targetActivities = historyService
            .createHistoricActivityInstanceQuery()
            .processInstanceId(processInstanceId)
            .activityId(targetActivityId)
            .list();
        if (targetActivities.isEmpty()) {
            throw new RuntimeException("目标节点不存在于流程实例中");
        }
    }
    /**
     * èŽ·å–å¯é€€å›žçš„èŠ‚ç‚¹åˆ—è¡¨ï¼ˆç”¨æˆ·ä»»åŠ¡èŠ‚ç‚¹ï¼‰
     */
    public List<HistoricActivityInstance> getBackableUserTasks(String processInstanceId) {
        return historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(processInstanceId)
            .activityType("userTask")
            .orderByHistoricActivityInstanceStartTime().desc()
            .list();
    }
    /**
     * èŽ·å–æŒ‡å®šèŠ‚ç‚¹çš„åŽ†å²å¤„ç†äºº
     */
    public String getHistoricAssignee(String processInstanceId, String activityId) {
        HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery()
            .processInstanceId(processInstanceId)
            .taskDefinitionKey(activityId)
            .orderByHistoricTaskInstanceEndTime().desc()
            .list()
            .stream()
            .findFirst()
            .orElse(null);
        return historicTask != null ? historicTask.getAssignee() : null;
    }
}
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/WIthdrawService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
package org.springblade.mdm.flow.service;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.flowable.engine.RepositoryService;
import java.util.HashMap;
import java.util.Optional;
/**
 * æµç¨‹æ’¤å›žæœåŠ¡
 */
@Service
public class WIthdrawService {
    @Autowired
    private WithdrawProperties withdrawProps;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private FlowableBackWithAssigneeService backWithAssigneeService;
    @Autowired
    private RepositoryService repositoryService;
    /*
     * æ’¤å›žåˆ°ç¼–程员
     */
    @Transactional
    public void withdraw(String processInstanceId) {
        //System.out.println(withdrawProps);
        String targetAssignee = ""+AuthUtil.getUserId();
        String processDefKey = getProcessDefinitionKeyByProcessInstanceId(processInstanceId);
        String targetActivityId = this.withdrawProps.getMapping().get(processDefKey);
        String taskId = getCurrentTaskIdByProcessInstanceId(processInstanceId);
        backWithAssigneeService.backToTaskWithNewAssignee(taskId,targetActivityId,targetAssignee,"流程撤回",new HashMap<>());
    }
/*
    String getprocessDefinitionKey(String processInstanceId){
        Task task = taskService.createTaskQuery()
            .taskId(taskId)
            .singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionId(task.getProcessDefinitionId())
            .singleResult();
        String taskId = getCurrentTaskIdByProcessInstanceId(processInstanceId);
        if (processDefinition == null) {
            throw new RuntimeException("流程定义不存在,processDefinitionId: " + task.getProcessDefinitionId());
        }
        return processDefinition.getKey();
    }*/
    public String getCurrentTaskIdByProcessInstanceId(String processInstanceId) {
        Optional<String> optTaskId = taskService.createTaskQuery()
            .processInstanceId(processInstanceId)
            .active()
            .list()
            .stream()
            .map(Task::getId).findFirst();
        return optTaskId.orElse(null);
    }
    public String getProcessDefinitionKeyByProcessInstanceId(String processInstanceId) {
        // èŽ·å–æµç¨‹å®žä¾‹
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
            .processInstanceId(processInstanceId)
            .singleResult();
        if (processInstance == null) {
            throw new RuntimeException("流程实例不存在: " + processInstanceId);
        }
        // èŽ·å–æµç¨‹å®šä¹‰
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionId(processInstance.getProcessDefinitionId())
            .singleResult();
        if (processDefinition == null) {
            throw new RuntimeException("流程定义不存在: " + processInstance.getProcessDefinitionId());
        }
        return processDefinition.getKey();
    }
}
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/WithdrawProperties.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package org.springblade.mdm.flow.service;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
@ConfigurationProperties(prefix = "withdraw")
@Getter
@Setter
public class WithdrawProperties {
    private Map<String, String> mapping = new HashMap<>();
}
blade-service/blade-mdm/src/main/java/org/springblade/mdm/test/MyTest2Controller.java
@@ -42,4 +42,6 @@
        return this.bizDictClient.getList(code);
    }
}
blade-service/blade-mdm/src/main/java/org/springblade/mdm/test/MyTestController.java
@@ -8,6 +8,7 @@
import org.springblade.core.tool.api.R;
import org.springblade.mdm.basesetting.machine.entity.Machine;
import org.springblade.mdm.commons.service.EmailService;
import org.springblade.mdm.flow.service.WIthdrawService;
import org.springblade.mdm.gkw.programnode.entity.MachineFile;
import org.springblade.mdm.program.entity.NcNode;
import org.springblade.mdm.program.service.NcNodeService;
@@ -22,7 +23,6 @@
import org.springframework.web.bind.annotation.RestController;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@@ -44,6 +44,9 @@
    private IDictBizClient bizDictClient;
    @Autowired
    private EmailService mailService;
    @Autowired
    private WIthdrawService withdrawService;
    /**
     * æ–°å¢ž
     */
@@ -113,4 +116,12 @@
        return R.success();
    }
    @GetMapping("/withdraw")
    public R<Void> withdraw(String id) throws IOException, MessagingException {
        withdrawService.withdraw(id);
        return R.success();
    }
}