mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 04:08:43 +08:00 
			
		
		
		
	【功能优化】工作流:BPMN 流程图高亮的计算,切换到后端为主
This commit is contained in:
		@@ -38,6 +38,10 @@ public enum BpmProcessInstanceStatusEnum implements IntArrayValuable {
 | 
			
		||||
        return ARRAYS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isRejectStatus(Integer status) {
 | 
			
		||||
        return REJECT.getStatus().equals(status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isProcessEndStatus(Integer status) {
 | 
			
		||||
        return ObjectUtils.equalsAny(status,
 | 
			
		||||
                APPROVE.getStatus(), REJECT.getStatus(), CANCEL.getStatus());
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,10 @@ public enum BpmTaskStatusEnum {
 | 
			
		||||
     */
 | 
			
		||||
    private final String name;
 | 
			
		||||
 | 
			
		||||
    public static boolean isRejectStatus(Integer status) {
 | 
			
		||||
        return REJECT.getStatus().equals(status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 判断该状态是否已经处于 End 最终状态
 | 
			
		||||
     * <p>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,40 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.module.bpm.controller.admin.task;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.convert.task.BpmActivityConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Parameter;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestParam;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
 | 
			
		||||
import jakarta.annotation.Resource;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 | 
			
		||||
 | 
			
		||||
@Tag(name = "管理后台 - 流程活动实例")
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/bpm/activity")
 | 
			
		||||
@Validated
 | 
			
		||||
public class BpmActivityController {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private BpmActivityService activityService;
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    @Operation(summary = "生成指定流程实例的高亮流程图",
 | 
			
		||||
            description = "只高亮进行中的任务。不过要注意,该接口暂时没用,通过前端的 ProcessViewer.vue 界面的 highlightDiagram 方法生成")
 | 
			
		||||
    @Parameter(name = "processInstanceId", description = "流程实例的编号", required = true)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('bpm:task:query')")
 | 
			
		||||
    public CommonResult<List<BpmActivityRespVO>> getActivityList(
 | 
			
		||||
            @RequestParam("processInstanceId") String processInstanceId) {
 | 
			
		||||
        return success(BpmActivityConvert.INSTANCE.convertList(activityService.getActivityListByProcessInstanceId(processInstanceId)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,5 @@
 | 
			
		||||
### 请求 /bpm/process-instance/get-bpmn 接口 => 成功
 | 
			
		||||
GET {{baseUrl}}/bpm/process-instance/get-bpmn-model-view?id=1d5fb5a6-85f8-11ef-b717-7e93075f94e3
 | 
			
		||||
Content-Type: application/json
 | 
			
		||||
tenant-id: 1
 | 
			
		||||
Authorization: Bearer {{token}}
 | 
			
		||||
@@ -173,4 +173,11 @@ public class BpmProcessInstanceController {
 | 
			
		||||
        return success(processInstanceService.getApprovalDetail(getLoginUserId(), reqVO));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/get-bpmn-model-view")
 | 
			
		||||
    @Operation(summary = "获取流程实例的 BPMN 模型视图", description = "在【流程详细】界面中,进行调用")
 | 
			
		||||
    @Parameter(name = "id", description = "流程实例的编号", required = true)
 | 
			
		||||
    public CommonResult<BpmProcessInstanceBpmnModelViewRespVO> getProcessInstanceBpmnModelView(@RequestParam(value = "id") String id) {
 | 
			
		||||
        return success(processInstanceService.getProcessInstanceBpmnModelView(id));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -121,7 +121,7 @@ public class BpmTaskController {
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('bpm:task:query')")
 | 
			
		||||
    public CommonResult<List<BpmTaskRespVO>> getTaskListByProcessInstanceId(
 | 
			
		||||
            @RequestParam("processInstanceId") String processInstanceId) {
 | 
			
		||||
        List<HistoricTaskInstance> taskList = taskService.getTaskListByProcessInstanceId(processInstanceId);
 | 
			
		||||
        List<HistoricTaskInstance> taskList = taskService.getTaskListByProcessInstanceId(processInstanceId, true);
 | 
			
		||||
        if (CollUtil.isEmpty(taskList)) {
 | 
			
		||||
            return success(Collections.emptyList());
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,39 @@
 | 
			
		||||
package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
@Schema(description = "管理后台 - 流程示例的 BPMN 视图 Response VO")
 | 
			
		||||
@Data
 | 
			
		||||
public class BpmProcessInstanceBpmnModelViewRespVO {
 | 
			
		||||
 | 
			
		||||
    // ========== 基本信息 ==========
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "流程实例信息", requiredMode = Schema.RequiredMode.REQUIRED)
 | 
			
		||||
    private BpmProcessInstanceRespVO processInstance;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "任务列表", requiredMode = Schema.RequiredMode.REQUIRED)
 | 
			
		||||
    private List<BpmTaskRespVO> tasks;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "BPMN XML", requiredMode = Schema.RequiredMode.REQUIRED)
 | 
			
		||||
    private String bpmnXml;
 | 
			
		||||
 | 
			
		||||
    // ========== 进度信息 ==========
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "进行中的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED)
 | 
			
		||||
    private Set<String> unfinishedTaskActivityIds; // 只包括 UserTask
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "已经完成的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED)
 | 
			
		||||
    private Set<String> finishedTaskActivityIds; // 包括 UserTask、Gateway 等,不包括 SequenceFlow
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "已经完成的连线节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED)
 | 
			
		||||
    private Set<String> finishedSequenceFlowActivityIds; // 只包括 SequenceFlow
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "已经拒绝的活动节点编号集合", requiredMode = Schema.RequiredMode.REQUIRED)
 | 
			
		||||
    private Set<String> rejectedTaskActivityIds; // 只包括 UserTask
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.module.bpm.convert.task;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.activity.BpmActivityRespVO;
 | 
			
		||||
import org.flowable.engine.history.HistoricActivityInstance;
 | 
			
		||||
import org.mapstruct.Mapper;
 | 
			
		||||
import org.mapstruct.Mapping;
 | 
			
		||||
import org.mapstruct.Mappings;
 | 
			
		||||
import org.mapstruct.factory.Mappers;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * BPM 活动 Convert
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Mapper(uses = DateUtils.class)
 | 
			
		||||
public interface BpmActivityConvert {
 | 
			
		||||
 | 
			
		||||
    BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class);
 | 
			
		||||
 | 
			
		||||
    List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list);
 | 
			
		||||
 | 
			
		||||
    @Mappings({
 | 
			
		||||
            @Mapping(source = "activityId", target = "key"),
 | 
			
		||||
            @Mapping(source = "activityType", target = "type")
 | 
			
		||||
    })
 | 
			
		||||
    BpmActivityRespVO convert(HistoricActivityInstance bean);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,23 +1,29 @@
 | 
			
		||||
package cn.iocoder.yudao.module.bpm.convert.task;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceBpmnModelViewRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEvent;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 | 
			
		||||
import org.flowable.bpmn.model.BpmnModel;
 | 
			
		||||
import org.flowable.engine.history.HistoricProcessInstance;
 | 
			
		||||
import org.flowable.engine.repository.ProcessDefinition;
 | 
			
		||||
import org.flowable.engine.runtime.ProcessInstance;
 | 
			
		||||
import org.flowable.task.api.Task;
 | 
			
		||||
import org.flowable.task.api.history.HistoricTaskInstance;
 | 
			
		||||
import org.mapstruct.Mapper;
 | 
			
		||||
import org.mapstruct.Mapping;
 | 
			
		||||
import org.mapstruct.MappingTarget;
 | 
			
		||||
@@ -25,6 +31,9 @@ import org.mapstruct.factory.Mappers;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 流程实例 Convert
 | 
			
		||||
@@ -109,4 +118,49 @@ public interface BpmProcessInstanceConvert {
 | 
			
		||||
            .setStartUserId(NumberUtils.parseLong(instance.getStartUserId()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default BpmProcessInstanceBpmnModelViewRespVO buildProcessInstanceBpmnModelView(HistoricProcessInstance processInstance,
 | 
			
		||||
                                                                                    List<HistoricTaskInstance> taskInstances,
 | 
			
		||||
                                                                                    BpmnModel bpmnModel,
 | 
			
		||||
                                                                                    Set<String> unfinishedTaskActivityIds,
 | 
			
		||||
                                                                                    Set<String> finishedTaskActivityIds,
 | 
			
		||||
                                                                                    Set<String> finishedSequenceFlowActivityIds,
 | 
			
		||||
                                                                                    Set<String> rejectTaskActivityIds,
 | 
			
		||||
                                                                                    Map<Long, AdminUserRespDTO> userMap,
 | 
			
		||||
                                                                                    Map<Long, DeptRespDTO> deptMap) {
 | 
			
		||||
        BpmProcessInstanceBpmnModelViewRespVO respVO = new BpmProcessInstanceBpmnModelViewRespVO();
 | 
			
		||||
        // 基本信息
 | 
			
		||||
        respVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmProcessInstanceRespVO.class, o -> o
 | 
			
		||||
                        .setStatus(FlowableUtils.getProcessInstanceStatus(processInstance)))
 | 
			
		||||
                        .setStartUser(buildUser(processInstance.getStartUserId(), userMap, deptMap)));
 | 
			
		||||
        respVO.setTasks(convertList(taskInstances, task -> BeanUtils.toBean(task, BpmTaskRespVO.class)
 | 
			
		||||
                .setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task))
 | 
			
		||||
                .setAssigneeUser(buildUser(task.getAssignee(), userMap, deptMap))
 | 
			
		||||
                .setOwnerUser(buildUser(task.getOwner(), userMap, deptMap))));
 | 
			
		||||
        respVO.setBpmnXml(BpmnModelUtils.getBpmnXml(bpmnModel));
 | 
			
		||||
        // 进度信息
 | 
			
		||||
        respVO.setUnfinishedTaskActivityIds(unfinishedTaskActivityIds)
 | 
			
		||||
                .setFinishedTaskActivityIds(finishedTaskActivityIds)
 | 
			
		||||
                .setFinishedSequenceFlowActivityIds(finishedSequenceFlowActivityIds)
 | 
			
		||||
                .setRejectedTaskActivityIds(rejectTaskActivityIds);
 | 
			
		||||
        return respVO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default BpmProcessInstanceRespVO.User buildUser(String userId,
 | 
			
		||||
                                                    Map<Long, AdminUserRespDTO> userMap,
 | 
			
		||||
                                                    Map<Long, DeptRespDTO> deptMap) {
 | 
			
		||||
        if (StrUtil.isBlank(userId)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        AdminUserRespDTO user = userMap.get(NumberUtils.parseLong(userId));
 | 
			
		||||
        if (user == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        BpmProcessInstanceRespVO.User userVO = BeanUtils.toBean(user, BpmProcessInstanceRespVO.User.class);
 | 
			
		||||
        DeptRespDTO dept = user.getDeptId() != null ? deptMap.get(user.getDeptId()) : null;
 | 
			
		||||
        if (dept != null) {
 | 
			
		||||
            userVO.setDeptName(dept.getName());
 | 
			
		||||
        }
 | 
			
		||||
        return userVO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// TODO 芋艿:准备废弃
 | 
			
		||||
/**
 | 
			
		||||
 * BPM 活动实例 Service 实现类
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -104,6 +104,14 @@ public interface BpmProcessInstanceService {
 | 
			
		||||
     */
 | 
			
		||||
    BpmApprovalDetailRespVO getApprovalDetail(Long loginUserId, @Valid BpmApprovalDetailReqVO reqVO);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取流程实例的 BPMN 模型视图
 | 
			
		||||
     *
 | 
			
		||||
     * @param id 流程实例的编号
 | 
			
		||||
     * @return BPMN 模型视图
 | 
			
		||||
     */
 | 
			
		||||
    BpmProcessInstanceBpmnModelViewRespVO getProcessInstanceBpmnModelView(String id);
 | 
			
		||||
 | 
			
		||||
    // ========== Update 写入相关方法 ==========
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -157,5 +165,4 @@ public interface BpmProcessInstanceService {
 | 
			
		||||
     */
 | 
			
		||||
    void processProcessInstanceCompleted(ProcessInstance instance);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -73,9 +73,10 @@ public interface BpmTaskService {
 | 
			
		||||
     * 获得指定流程实例的流程任务列表,包括所有状态的
 | 
			
		||||
     *
 | 
			
		||||
     * @param processInstanceId 流程实例的编号
 | 
			
		||||
     * @param asc 是否升序
 | 
			
		||||
     * @return 流程任务列表
 | 
			
		||||
     */
 | 
			
		||||
    List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId);
 | 
			
		||||
    List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取任务
 | 
			
		||||
 
 | 
			
		||||
@@ -170,16 +170,16 @@ public class BpmTaskServiceImpl implements BpmTaskService {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId) {
 | 
			
		||||
        List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
 | 
			
		||||
    public List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc) {
 | 
			
		||||
        HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery()
 | 
			
		||||
                .includeTaskLocalVariables()
 | 
			
		||||
                .processInstanceId(processInstanceId)
 | 
			
		||||
                .orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
 | 
			
		||||
                .list();
 | 
			
		||||
        if (CollUtil.isEmpty(tasks)) {
 | 
			
		||||
            return Collections.emptyList();
 | 
			
		||||
                .processInstanceId(processInstanceId);
 | 
			
		||||
        if (Boolean.TRUE.equals(asc)) {
 | 
			
		||||
            query.orderByHistoricTaskInstanceStartTime().asc();
 | 
			
		||||
        } else {
 | 
			
		||||
            query.orderByHistoricTaskInstanceStartTime().desc();
 | 
			
		||||
        }
 | 
			
		||||
        return tasks;
 | 
			
		||||
        return query.list();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user