Przeglądaj źródła

支持历史流程签出逻辑

hubin 1 rok temu
rodzic
commit
7780cd9dee

+ 22 - 2
src/main/java/com/aizuda/boot/modules/flw/controller/ProcessController.java

@@ -2,14 +2,17 @@ package com.aizuda.boot.modules.flw.controller;
 
 import com.aizuda.boot.modules.flw.entity.dto.FlwCategorySortDTO;
 import com.aizuda.boot.modules.flw.entity.dto.FlwProcessDTO;
+import com.aizuda.boot.modules.flw.entity.dto.FlwProcessHistoryDTO;
 import com.aizuda.boot.modules.flw.entity.dto.ProcessStartDTO;
 import com.aizuda.boot.modules.flw.entity.vo.FlwProcessCategoryVO;
 import com.aizuda.boot.modules.flw.flow.FlowHelper;
 import com.aizuda.boot.modules.flw.service.IFlwProcessService;
 import com.aizuda.bpm.engine.entity.FlwProcess;
 import com.aizuda.core.api.ApiController;
+import com.aizuda.core.api.PageParam;
 import com.aizuda.core.validation.Create;
 import com.baomidou.kisso.annotation.Permission;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Parameters;
@@ -33,6 +36,13 @@ import java.util.List;
 public class ProcessController extends ApiController {
     private IFlwProcessService flwProcessService;
 
+    @Operation(summary = "历史分页列表")
+    @Permission("sys:process:page")
+    @PostMapping("/page-history")
+    public Page<FlwProcess> getPageHistory(@RequestBody PageParam<FlwProcessHistoryDTO> dto) {
+        return flwProcessService.pageHistory(dto.page(), dto.getData());
+    }
+
     @Operation(summary = "获取所有分类流程定义列表")
     @Permission("flw:process:listCategory")
     @Parameters({
@@ -111,7 +121,7 @@ public class ProcessController extends ApiController {
     @Parameters({
             @Parameter(name = "id", description = "流程ID")
     })
-    @Permission("flw:process:create")
+    @Permission("flw:process:release")
     @PostMapping("/release")
     public boolean release(@RequestParam Long id) {
         return flwProcessService.releaseById(id);
@@ -135,14 +145,24 @@ public class ProcessController extends ApiController {
     }
 
     @Operation(summary = "根据流程定义ID更新流程状态")
-    @Permission("flw:process:updateSate")
     @Parameters({
             @Parameter(name = "id", description = "主键ID"),
             @Parameter(name = "state", description = "流程状态 0,不可用 1,可用")
     })
+    @Permission("flw:process:updateSate")
     @PostMapping("/update-state-{id}")
     public boolean updateSate(@PathVariable("id") Long id, @RequestParam Integer state) {
         return flwProcessService.updateSateById(id, state);
     }
 
+    @Operation(summary = "根据指定ID签出历史流程")
+    @Parameters({
+            @Parameter(name = "id", description = "流程ID")
+    })
+    @Permission("flw:process:checkout")
+    @PostMapping("/checkout")
+    public boolean checkout(@RequestParam Long id) {
+        return flwProcessService.checkoutById(id);
+    }
+
 }

+ 21 - 0
src/main/java/com/aizuda/boot/modules/flw/entity/dto/FlwProcessHistoryDTO.java

@@ -0,0 +1,21 @@
+package com.aizuda.boot.modules.flw.entity.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.PositiveOrZero;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class FlwProcessHistoryDTO {
+
+    @Schema(description = "流程定义ID")
+    @NotNull
+    @PositiveOrZero
+    private Long processId;
+
+    @Schema(description = "流程定义名称")
+    private String processName;
+
+}

+ 17 - 0
src/main/java/com/aizuda/boot/modules/flw/service/IFlwProcessService.java

@@ -2,11 +2,13 @@ package com.aizuda.boot.modules.flw.service;
 
 import com.aizuda.boot.modules.flw.entity.dto.FlwCategorySortDTO;
 import com.aizuda.boot.modules.flw.entity.dto.FlwProcessDTO;
+import com.aizuda.boot.modules.flw.entity.dto.FlwProcessHistoryDTO;
 import com.aizuda.boot.modules.flw.entity.dto.ProcessStartDTO;
 import com.aizuda.boot.modules.flw.entity.vo.FlwProcessCategoryVO;
 import com.aizuda.bpm.engine.core.FlowCreator;
 import com.aizuda.bpm.engine.entity.FlwProcess;
 import com.aizuda.service.service.IBaseService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 
 import java.util.List;
 
@@ -18,6 +20,11 @@ import java.util.List;
  */
 public interface IFlwProcessService extends IBaseService<FlwProcess> {
 
+    /**
+     * 流程定义历史分页列表
+     */
+    Page<FlwProcess> pageHistory(Page<FlwProcess> page, FlwProcessHistoryDTO dto);
+
     /**
      * 流程定义分类查询所有流程定义列表
      *
@@ -104,4 +111,14 @@ public interface IFlwProcessService extends IBaseService<FlwProcess> {
      * @param id 流程定义ID
      */
     boolean releaseById(Long id);
+
+    /**
+     * 根据指定ID签出历史流程
+     * <p>
+     * 当前版本和历史版本交换
+     * </p>
+     *
+     * @param id 流程定义ID
+     */
+    boolean checkoutById(Long id);
 }

+ 0 - 2
src/main/java/com/aizuda/boot/modules/flw/service/impl/FlwProcessConfigureServiceImpl.java

@@ -24,8 +24,6 @@ public class FlwProcessConfigureServiceImpl extends BaseServiceImpl<FlwProcessCo
 
     @Override
     public boolean saveByDto(Long processId, FlwProcessDTO dto) {
-        // 删除流程定义ID历史数据
-        this.removeByProcessId(processId);
         // 保存最新配置
         FlwProcessConfigure fpc = new FlwProcessConfigure();
         fpc.setProcessId(processId);

+ 0 - 2
src/main/java/com/aizuda/boot/modules/flw/service/impl/FlwProcessPermissionServiceImpl.java

@@ -22,8 +22,6 @@ public class FlwProcessPermissionServiceImpl extends BaseServiceImpl<FlwProcessP
 
     @Override
     public boolean saveProcessPermissions(Long processId, List<FlwProcessPermissionDTO> dtoList) {
-        // 先删除流程定义ID历史数据
-        this.removeByProcessId(processId);
         // 保存流程定义权限列表
         return super.saveBatch(dtoList.stream().map(t -> t.toFlwProcessPermission(processId)).toList());
     }

+ 81 - 35
src/main/java/com/aizuda/boot/modules/flw/service/impl/FlwProcessServiceImpl.java

@@ -4,10 +4,7 @@ import com.aizuda.boot.modules.flw.entity.FlwProcessActor;
 import com.aizuda.boot.modules.flw.entity.FlwProcessCategory;
 import com.aizuda.boot.modules.flw.entity.FlwProcessConfigure;
 import com.aizuda.boot.modules.flw.entity.FlwProcessPermission;
-import com.aizuda.boot.modules.flw.entity.dto.FlwCategorySortDTO;
-import com.aizuda.boot.modules.flw.entity.dto.FlwProcessDTO;
-import com.aizuda.boot.modules.flw.entity.dto.FlwProcessPermissionDTO;
-import com.aizuda.boot.modules.flw.entity.dto.ProcessStartDTO;
+import com.aizuda.boot.modules.flw.entity.dto.*;
 import com.aizuda.boot.modules.flw.entity.vo.FlwProcessCategoryVO;
 import com.aizuda.boot.modules.flw.entity.vo.FlwProcessVO;
 import com.aizuda.boot.modules.flw.flow.FlowForm;
@@ -15,8 +12,10 @@ import com.aizuda.boot.modules.flw.mapper.FlowlongMapper;
 import com.aizuda.boot.modules.flw.service.*;
 import com.aizuda.bpm.engine.FlowDataTransfer;
 import com.aizuda.bpm.engine.FlowLongEngine;
+import com.aizuda.bpm.engine.ProcessService;
 import com.aizuda.bpm.engine.core.FlowCreator;
 import com.aizuda.bpm.engine.core.FlowLongContext;
+import com.aizuda.bpm.engine.core.enums.FlowState;
 import com.aizuda.bpm.engine.entity.FlwInstance;
 import com.aizuda.bpm.engine.entity.FlwProcess;
 import com.aizuda.bpm.engine.model.*;
@@ -24,6 +23,9 @@ import com.aizuda.bpm.mybatisplus.mapper.FlwProcessMapper;
 import com.aizuda.common.toolkit.DateUtils;
 import com.aizuda.core.api.ApiAssert;
 import com.aizuda.service.web.UserSession;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.AllArgsConstructor;
 import org.apache.commons.collections.CollectionUtils;
@@ -43,6 +45,7 @@ import java.util.*;
 @Service
 @AllArgsConstructor
 public class FlwProcessServiceImpl extends ServiceImpl<FlwProcessMapper, FlwProcess> implements IFlwProcessService {
+    private final ProcessService processService;
     private IFlwProcessCategoryService flwProcessCategoryService;
     private IFlwProcessPermissionService flwProcessPermissionService;
     private IFlwProcessConfigureService flwProcessConfigureService;
@@ -51,6 +54,17 @@ public class FlwProcessServiceImpl extends ServiceImpl<FlwProcessMapper, FlwProc
     private FlowlongMapper flowlongMapper;
     private FlowLongEngine flowLongEngine;
 
+    @Override
+    public Page<FlwProcess> pageHistory(Page<FlwProcess> page, FlwProcessHistoryDTO dto) {
+        FlwProcess flwProcess = this.checkById(dto.getProcessId());
+        LambdaQueryWrapper<FlwProcess> lqw = Wrappers.lambdaQuery();
+        lqw.select(FlwProcess::getId, FlwProcess::getProcessName, FlwProcess::getProcessIcon,
+                FlwProcess::getProcessVersion, FlwProcess::getRemark, FlwProcess::getCreateTime);
+        lqw.eq(FlwProcess::getProcessState, 2);
+        lqw.eq(FlwProcess::getProcessKey, flwProcess.getProcessKey());
+        return super.page(page, lqw);
+    }
+
     @Override
     public List<FlwProcessCategoryVO> listCategoryAll(String keyword) {
         return this.listCategoryVO(keyword, false);
@@ -199,41 +213,38 @@ public class FlwProcessServiceImpl extends ServiceImpl<FlwProcessMapper, FlwProc
         int checkConditionNode = ModelHelper.checkConditionNode(rootNode);
         if (checkConditionNode > 0) {
             ApiAssert.fail(Objects.equals(1, checkConditionNode), "存在多个条件表达式为空");
-            ApiAssert.fail(Objects.equals(2, checkConditionNode), "存在多个子节点为空");
+            ApiAssert.fail(Objects.equals(2, checkConditionNode), "存在多个条件子节点为空");
+            ApiAssert.fail(Objects.equals(3, checkConditionNode), "存在条件节点KEY重复");
         }
         ApiAssert.fail(!ModelHelper.checkExistApprovalNode(rootNode), "必须存在审批节点");
+        this.checkProcessKey(dto.getProcessId(), dto.getProcessKey());
+
+        // 设置创建者信息
+        UserSession userSession = UserSession.getLoginInfo();
+
+        // 部署流程定义,修改会产生历史流程
+        final Long processId = processService.deploy(dto.getProcessId(), dto.getModelContent(),
+                FlowCreator.of(userSession.getUserId(), userSession.getUsername()), true, flwProcess -> {
+                    // 流程图标
+                    flwProcess.setProcessIcon(dto.getProcessIcon());
+
+                    // 流程类型
+                    flwProcess.setProcessType(dto.getProcessType());
+
+                    // 创建 0 不可用状态,需要发布后才可以使用
+                    flwProcess.setFlowState(FlowState.inactive);
+
+                    // 备注说明
+                    flwProcess.setRemark(dto.getRemark());
+                });
 
-        // 流程定义ID
-        Long processId = dto.getProcessId();
-        FlwProcess flwProcess = new FlwProcess();
-        flwProcess.setProcessKey(dto.getProcessKey());
-        flwProcess.setProcessName(dto.getProcessName());
-        flwProcess.setProcessIcon(dto.getProcessIcon());
-        flwProcess.setProcessType(dto.getProcessType());
-        flwProcess.setUseScope(dto.getUseScope());
-        flwProcess.setModelContent(dto.getModelContent());
-        flwProcess.setProcessState(0); // 创建 0 不可用状态,需要发布后才可以使用
-        flwProcess.setSort(1);
-        flwProcess.setRemark(dto.getRemark());
-        if (null == processId) {
-            // 设置创建者信息
-            UserSession userSession = UserSession.getLoginInfo();
-            flwProcess.setCreateId(String.valueOf(userSession.getId()));
-            flwProcess.setCreateBy(userSession.getUsername());
-            flwProcess.setCreateTime(new Date());
-            flwProcess.setProcessVersion(1); // 流程版本,默认 1
-            ApiAssert.fail(!super.save(flwProcess), "流程定义保存失败");
-            processId = flwProcess.getId();
-        } else {
-            flwProcess.setId(processId);
-            ApiAssert.fail(!super.updateById(flwProcess), "流程定义保存失败");
-        }
         // 流程定义权限
         List<FlwProcessPermissionDTO> processPermissionList = dto.getProcessPermissionList();
         if (CollectionUtils.isNotEmpty(processPermissionList)) {
             ApiAssert.fail(!flwProcessPermissionService.saveProcessPermissions(processId, processPermissionList),
                     "流程定义管理权限保存失败");
         }
+
         // 保存流程定义配置
         if (null != dto.getCategoryId()) {
             ApiAssert.fail(!flwProcessConfigureService.saveByDto(processId, dto), "流程定义配置保存失败");
@@ -241,6 +252,16 @@ public class FlwProcessServiceImpl extends ServiceImpl<FlwProcessMapper, FlwProc
         return processId;
     }
 
+    /**
+     * 验证判断非历史版本流程流程唯一标识key
+     */
+    private void checkProcessKey(Long processId, String processKey) {
+        Long count = lambdaQuery().ne(null != processId, FlwProcess::getId, processId)
+                .ne(FlwProcess::getProcessState, 2)
+                .eq(FlwProcess::getProcessKey, processKey).count();
+        ApiAssert.fail(count > 0, "流程唯一标识key不允许重复");
+    }
+
     @Transactional(rollbackFor = Exception.class)
     @Override
     public boolean removeProcessInfo(Long id) {
@@ -258,14 +279,14 @@ public class FlwProcessServiceImpl extends ServiceImpl<FlwProcessMapper, FlwProc
     protected void checkOperateApproval(Long processId) {
         UserSession userSession = UserSession.getLoginInfo();
         if (null == userSession || !UserSession.isAdmin(userSession.getId())) {
-            FlwProcessPermission fpp = getFlwProcessPermissionByProcessId(processId);
+            FlwProcessPermission fpp = getFlwProcessPermissionByProcessId(userSession, processId);
             ApiAssert.fail(null == fpp || !fpp.allowOperateApproval(), "无权限编辑操作审批流程");
         }
     }
 
-    protected FlwProcessPermission getFlwProcessPermissionByProcessId(Long processId) {
-        UserSession userSession = UserSession.getLoginInfo();
-        return flwProcessPermissionService.getByUserIdAndProcessId(userSession.getId(), processId);
+    protected FlwProcessPermission getFlwProcessPermissionByProcessId(UserSession userSession, Long processId) {
+        Long userId = null == userSession ? null : userSession.getId();
+        return flwProcessPermissionService.getByUserIdAndProcessId(userId, processId);
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -280,7 +301,7 @@ public class FlwProcessServiceImpl extends ServiceImpl<FlwProcessMapper, FlwProc
                 if (CollectionUtils.isNotEmpty(processIds)) {
                     int j = 0;
                     fpcList.add(dto.toFlwProcessCategory(++i));
-                    for(Long processId : processIds) {
+                    for (Long processId : processIds) {
                         FlwProcess fp = new FlwProcess();
                         fp.setId(processId);
                         fp.setSort(++j);
@@ -359,4 +380,29 @@ public class FlwProcessServiceImpl extends ServiceImpl<FlwProcessMapper, FlwProc
         temp.setProcessState(1);
         return super.updateById(temp);
     }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean checkoutById(Long id) {
+        FlwProcess flwProcess = this.checkById(id);
+        final int hisVersion = flwProcess.getProcessVersion();
+        FlwProcess currentProcess = lambdaQuery().eq(FlwProcess::getProcessKey, flwProcess.getProcessKey())
+                .ne(FlwProcess::getProcessState, 2).one();
+        if (null != currentProcess) {
+            // 启用历史流程,设置为当前版本
+            FlwProcess temp = new FlwProcess();
+            temp.setId(flwProcess.getId());
+            temp.setProcessVersion(currentProcess.getProcessVersion());
+            temp.setProcessState(currentProcess.getProcessState());
+            if (super.updateById(temp)) {
+                // 当前流程归档为历史状态
+                FlwProcess his = new FlwProcess();
+                his.setId(currentProcess.getId());
+                his.setProcessVersion(hisVersion);
+                his.setFlowState(FlowState.history);
+                return super.updateById(his);
+            }
+        }
+        return false;
+    }
 }

+ 2 - 2
src/main/resources/mapper/FlowlongMapper.xml

@@ -1,11 +1,11 @@
 <?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">
-<!--suppress ALL -->
 <mapper namespace="com.aizuda.boot.modules.flw.mapper.FlowlongMapper">
 
     <select id="selectFlwProcessList" resultType="com.aizuda.boot.modules.flw.entity.vo.FlwProcessVO">
         SELECT t2.category_id,t2.process_id,t1.process_key,t1.process_name,t1.process_icon,t1.process_type,t1.process_version,t1.instance_url,t1.remark,t1.use_scope,
-               t1.process_state,t1.sort AS process_sort,t1.create_time FROM flw_process t1 JOIN  flw_process_configure t2 ON t1.id=t2.process_id
+               t1.process_state,t1.sort AS process_sort,t1.create_time FROM flw_process t1 JOIN flw_process_configure t2 ON t1.id=t2.process_id
+        WHERE t1.process_state IN (0, 1)
     </select>
 
     <select id="selectLaunchProcessList" resultType="com.aizuda.boot.modules.flw.entity.vo.FlwProcessVO">