home 2 жил өмнө
parent
commit
e323accabe

+ 87 - 0
hx-common/service-flow/src/main/java/com/fjhx/feign/FlowClient.java

@@ -0,0 +1,87 @@
+package com.fjhx.feign;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fjhx.constants.FlowConstant;
+import com.fjhx.constants.FlowExplainConstant;
+import com.fjhx.constants.StatusConstant;
+import com.fjhx.entity.example.ExampleInfo;
+import com.fjhx.entity.process.ProcessInfo;
+import com.fjhx.entity.process.ProcessNodeButton;
+import com.fjhx.entity.process.ProcessTenant;
+import com.fjhx.service.example.ExampleInfoService;
+import com.fjhx.service.process.ProcessInfoService;
+import com.fjhx.service.process.ProcessNodeButtonService;
+import com.fjhx.service.process.ProcessTenantService;
+import com.fjhx.utils.Assert;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class FlowClient implements IFlowClient {
+
+    @Autowired
+    private ExampleInfoService exampleInfoService;
+
+    @Autowired
+    private ProcessInfoService processInfoService;
+
+    @Autowired
+    private ProcessTenantService processTenantService;
+
+    @Autowired
+    private ProcessNodeButtonService processNodeButtonService;
+
+
+    @PostMapping(GET_EXAMPLE_INFO_BY_BUSINESS_ID)
+    @Override
+    public R<ExampleInfo> getExampleInfoByBusinessId(Long businessId) {
+        ExampleInfo exampleInfo = exampleInfoService.getOne(Wrappers.<ExampleInfo>lambdaQuery()
+                .eq(ExampleInfo::getBusinessId, businessId).eq(ExampleInfo::getComplete, StatusConstant.No));
+        return R.success(exampleInfo);
+    }
+
+    @PostMapping(GET_PROCESS_TENANT_BY_CODE)
+    @Override
+    public R<ProcessTenant> getProcessTenantByCode(String code) {
+
+        // 查找通用流程
+        ProcessInfo processInfo = processInfoService.getOne(ProcessInfo::getCode, code);
+        Assert.notEmpty(processInfo, String.format(FlowExplainConstant.PROCESS_NOT_EXIST, code));
+        Long processInfoId = processInfo.getId();
+
+        // 获取租户流程
+        ProcessTenant processTenant = processTenantService.getOne(Wrappers.<ProcessTenant>lambdaQuery()
+                .eq(ProcessTenant::getProcessInfoId, processInfoId)
+                .eq(ProcessTenant::getBindingTenantId, AuthUtil.getTenantId())
+                .eq(ProcessTenant::getCurrentVersion, StatusConstant.YES)
+                .last("limit 1"));
+
+        if (processTenant == null) {
+            processTenant = new ProcessTenant();
+            processTenant.setProcessInfoId(processInfo.getId());
+        }
+
+        return R.success(processTenant);
+    }
+
+    @PostMapping(GET_PROCESS_NODE_START_BUTTON_BY_PROCESS_TENANT_ID)
+    @Override
+    public R<ProcessNodeButton> getProcessNodeStartButtonByProcessTenantId(Long processTenantId) {
+        ProcessNodeButton processNodeButton = processNodeButtonService.getOne(
+                Wrappers.<ProcessNodeButton>lambdaQuery()
+                        .eq(ProcessNodeButton::getProcessTenantId, processTenantId)
+                        .eq(ProcessNodeButton::getProcessNodeCode, FlowConstant.START_CODE));
+        return R.success(processNodeButton);
+    }
+
+    @PostMapping(EXAMPLE_INFO_SAVE)
+    @Override
+    public R<ExampleInfo> exampleInfoSave(ExampleInfo exampleInfo) {
+        exampleInfoService.save(exampleInfo);
+        return R.success(exampleInfo);
+    }
+
+}

+ 4 - 5
hx-common/service-flow/src/main/java/com/fjhx/service/example/ExampleInfoService.java

@@ -1,11 +1,8 @@
 package com.fjhx.service.example;
 
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.fjhx.entity.example.ExampleInfo;
-import com.fjhx.params.example.ExampleInfoVo;
 import com.fjhx.base.BaseService;
-
-import java.util.Map;
+import com.fjhx.entity.example.ExampleInfo;
+import com.fjhx.utils.ExampleAbstract;
 
 /**
  * <p>
@@ -17,4 +14,6 @@ import java.util.Map;
  */
 public interface ExampleInfoService extends BaseService<ExampleInfo> {
 
+    ExampleInfo create(Long businessId, ExampleAbstract exampleAbstract);
+
 }

+ 87 - 7
hx-common/service-flow/src/main/java/com/fjhx/service/example/impl/ExampleInfoServiceImpl.java

@@ -1,18 +1,26 @@
 package com.fjhx.service.example.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.fjhx.utils.WrapperUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.constants.FlowConstant;
+import com.fjhx.constants.FlowExplainConstant;
+import com.fjhx.constants.StatusConstant;
 import com.fjhx.entity.example.ExampleInfo;
-import com.fjhx.params.example.ExampleInfoVo;
+import com.fjhx.entity.process.ProcessInfo;
+import com.fjhx.entity.process.ProcessNodeButton;
+import com.fjhx.entity.process.ProcessTenant;
 import com.fjhx.mapper.example.ExampleInfoMapper;
 import com.fjhx.service.example.ExampleInfoService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.service.process.ProcessInfoService;
+import com.fjhx.service.process.ProcessNodeButtonService;
+import com.fjhx.service.process.ProcessTenantService;
+import com.fjhx.utils.Assert;
+import com.fjhx.utils.ExampleAbstract;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.Map;
-
 /**
  * <p>
  * 流程实例 服务实现类
@@ -24,5 +32,77 @@ import java.util.Map;
 @Service
 public class ExampleInfoServiceImpl extends ServiceImpl<ExampleInfoMapper, ExampleInfo> implements ExampleInfoService {
 
+    @Autowired
+    private ProcessTenantService processTenantService;
+
+    @Autowired
+    private ProcessInfoService processInfoService;
+
+    @Autowired
+    private ProcessNodeButtonService processNodeButtonService;
+
+
+    @Override
+    public ExampleInfo create(Long businessId, ExampleAbstract exampleAbstract) {
+
+        // 查看流程是否已发起
+        Assert.notEmpty(
+                getOne(Wrappers.<ExampleInfo>lambdaQuery()
+                        .eq(ExampleInfo::getBusinessId, businessId).eq(ExampleInfo::getComplete, StatusConstant.No)),
+                FlowExplainConstant.EXPLAIN_NOT_EXIST);
+
+        // 获取流程编码
+        String code = exampleAbstract.getCode();
+
+        // 查找通用流程
+        ProcessInfo processInfo = processInfoService.getOne(ProcessInfo::getCode, code);
+        Assert.notEmpty(processInfo, String.format(FlowExplainConstant.PROCESS_NOT_EXIST, code));
+        Long processInfoId = processInfo.getId();
+
+        // 获取租户流程
+        ProcessTenant processTenant = processTenantService.getOne(Wrappers.<ProcessTenant>lambdaQuery()
+                .eq(ProcessTenant::getProcessInfoId, processInfoId)
+                .eq(ProcessTenant::getBindingTenantId, AuthUtil.getTenantId())
+                .eq(ProcessTenant::getCurrentVersion, StatusConstant.YES)
+                .last("limit 1"));
+
+        ExampleInfo exampleInfo = new ExampleInfo();
+        exampleInfo.setProcessInfoId(processInfoId);
+        exampleInfo.setBusinessId(businessId);
+        exampleInfo.setCacheData(exampleAbstract.getCacheData());
+
+        // 如果租户流程为空,直接结束流程
+        if (ObjectUtil.isEmpty(processTenant)) {
+            exampleInfo.setProcessNodeId(FlowConstant.OVER_PROCESS_FLAG);
+            exampleInfo.setComplete(StatusConstant.YES);
+
+            // 执行流程结束方法
+            exampleAbstract.end();
+        } else {
+            Long processTenantId = processTenant.getId();
+            exampleInfo.setProcessTenantId(processTenantId);
+
+            ProcessNodeButton processNodeButton = processNodeButtonService.getOne(
+                    Wrappers.<ProcessNodeButton>lambdaQuery()
+                            .eq(ProcessNodeButton::getProcessTenantId, processTenantId)
+                            .eq(ProcessNodeButton::getProcessNodeCode, FlowConstant.START_CODE));
+
+            Long jumpNodeId = processNodeButton.getJumpNodeId();
+
+            // 如果跳转id为空,则走到分支
+            if (jumpNodeId == null) {
+                String circulation = exampleAbstract.circulation(processNodeButton.getProcessNodeCode());
+                Assert.notEmpty(circulation, FlowExplainConstant.SPECIFY_BRANCH_EMPTY);
+
+
+
+
+            }
+
+        }
+
+        save(exampleInfo);
 
+        return exampleInfo;
+    }
 }

+ 9 - 0
hx-service-api/service-flow-api/src/main/java/com/fjhx/constants/FlowExplainConstant.java

@@ -44,4 +44,13 @@ public interface FlowExplainConstant {
 
     String PREVIOUS_ERROR = "节点名称为 %s 的上级节点配置异常";
 
+    /*
+     实例
+     */
+    String PROCESS_NOT_EXIST = "编码为 %s 的流程不存在";
+
+    String EXPLAIN_NOT_EXIST = "流程已发起";
+
+    String SPECIFY_BRANCH_EMPTY = "没有找到指定流转的分支";
+
 }

+ 47 - 0
hx-service-api/service-flow-api/src/main/java/com/fjhx/feign/IFlowClient.java

@@ -0,0 +1,47 @@
+package com.fjhx.feign;
+
+import com.fjhx.constants.ClientConstant;
+import com.fjhx.entity.example.ExampleInfo;
+import com.fjhx.entity.process.ProcessNodeButton;
+import com.fjhx.entity.process.ProcessTenant;
+import org.springblade.core.tool.api.R;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * File Feign接口类
+ */
+@FeignClient(value = "service-flow")
+public interface IFlowClient {
+
+    String GET_EXAMPLE_INFO_BY_BUSINESS_ID = ClientConstant.API_PREFIX + "/getExampleInfoByBusinessId";
+    String GET_PROCESS_TENANT_BY_CODE = ClientConstant.API_PREFIX + "/getProcessTenantByCode";
+    String EXAMPLE_INFO_SAVE = ClientConstant.API_PREFIX + "/exampleInfoSave";
+    String GET_PROCESS_NODE_START_BUTTON_BY_PROCESS_TENANT_ID = ClientConstant.API_PREFIX + "/getProcessNodeStartButtonByProcessTenantId";
+
+    /**
+     * 通过业务id获取正在进行中的流程实例
+     */
+    @PostMapping(GET_EXAMPLE_INFO_BY_BUSINESS_ID)
+    R<ExampleInfo> getExampleInfoByBusinessId(@RequestParam("businessId") Long businessId);
+
+    /**
+     * 通过流程编码获取租户流程
+     */
+    @PostMapping(GET_PROCESS_TENANT_BY_CODE)
+    R<ProcessTenant> getProcessTenantByCode(String code);
+
+    /**
+     * 通过租户业务流程id获取开始节点按钮信息
+     */
+    @PostMapping(GET_PROCESS_NODE_START_BUTTON_BY_PROCESS_TENANT_ID)
+    R<ProcessNodeButton> getProcessNodeStartButtonByProcessTenantId(Long processTenantId);
+
+    /**
+     * 保存流程实例
+     */
+    @PostMapping(EXAMPLE_INFO_SAVE)
+    R<ExampleInfo> exampleInfoSave(ExampleInfo exampleInfo);
+
+}

+ 60 - 0
hx-service-api/service-flow-api/src/main/java/com/fjhx/utils/ExampleAbstract.java

@@ -0,0 +1,60 @@
+package com.fjhx.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Getter;
+import lombok.Setter;
+
+public abstract class ExampleAbstract {
+
+    /**
+     * 流程编码
+     */
+    @Getter
+    private String code;
+
+    /**
+     * 流程缓存值
+     */
+    @Setter
+    private Object cacheData;
+
+    /**
+     * 获取缓存值
+     */
+    public <T> T getCacheData() {
+        return (T) JSONObject.parseObject(cacheData.toString());
+    }
+
+    /**
+     * 设置流程编码
+     */
+    public abstract void setCode();
+
+    /**
+     * 实例结束方法
+     */
+    public abstract void end();
+
+    /**
+     * 审批不通过方法
+     * 需要时重写即可
+     *
+     * @param code 节点编码
+     */
+    public void fail(String code) {
+
+    }
+
+    /**
+     * 控制流程流转
+     * 存在分支时需要重写此方法,流转向指定分支
+     *
+     * @param code 节点编码
+     * @return 指定流转分支编码
+     */
+    public String circulation(String code) {
+        return null;
+    }
+
+
+}

+ 109 - 0
hx-service-api/service-flow-api/src/main/java/com/fjhx/utils/FlowConstructor.java

@@ -0,0 +1,109 @@
+package com.fjhx.utils;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import com.fjhx.constants.FlowConstant;
+import com.fjhx.constants.FlowExplainConstant;
+import com.fjhx.constants.StatusConstant;
+import com.fjhx.entity.example.ExampleInfo;
+import com.fjhx.entity.process.ProcessNodeButton;
+import com.fjhx.entity.process.ProcessTenant;
+import com.fjhx.feign.IFlowClient;
+import org.springblade.core.tool.api.R;
+
+public class FlowConstructor {
+
+    private static final IFlowClient flowClient = SpringUtil.getBean(IFlowClient.class);
+
+    private ExampleAbstract exampleAbstract;
+
+    private FlowConstructor() {
+
+    }
+
+    /**
+     * 初始化
+     */
+    public static FlowConstructor init(ExampleAbstract exampleAbstract) {
+        FlowConstructor flowConstructor = new FlowConstructor();
+        flowConstructor.exampleAbstract = exampleAbstract;
+        return flowConstructor;
+    }
+
+    /**
+     * 创建流程
+     *
+     * @param businessId 给予流程关联业务id
+     * @return 流程实例对象
+     */
+    public ExampleInfo create(Long businessId) {
+
+        // 获取流程编码
+        String code = exampleAbstract.getCode();
+        Assert.notEmpty(code, FlowExplainConstant.CODE_EMPTY);
+
+        // 查看流程是否已发起
+        ExampleInfo data = flowClient.getExampleInfoByBusinessId(businessId).getData();
+        Assert.notEmpty(data, FlowExplainConstant.EXPLAIN_NOT_EXIST);
+
+
+        R<ProcessTenant> r = flowClient.getProcessTenantByCode(code);
+        Assert.eqTrue(r.isSuccess(), r.getMsg());
+
+        ProcessTenant processTenant = r.getData();
+
+        Long processInfoId = processTenant.getProcessInfoId();
+
+        ExampleInfo exampleInfo = new ExampleInfo();
+        exampleInfo.setProcessInfoId(processInfoId);
+        exampleInfo.setBusinessId(businessId);
+        exampleInfo.setCacheData(exampleAbstract.getCacheData());
+
+        // 如果租户流程为空,直接结束流程
+        if (ObjectUtil.isEmpty(processTenant.getId())) {
+            exampleInfo.setProcessNodeId(FlowConstant.OVER_PROCESS_FLAG);
+            exampleInfo.setComplete(StatusConstant.YES);
+
+            // 执行流程结束方法
+            exampleAbstract.end();
+        }
+        // 租户流程不为空,走租户流程
+        else {
+            Long processTenantId = processTenant.getId();
+            exampleInfo.setProcessTenantId(processTenantId);
+
+            // 获取开始节点按钮
+            ProcessNodeButton processNodeButton = flowClient.getProcessNodeStartButtonByProcessTenantId(processTenantId).getData();
+            Long jumpNodeId = processNodeButton.getJumpNodeId();
+
+            // 调用方法查看是否有指定跳转节点
+            String circulation = exampleAbstract.circulation(processNodeButton.getProcessNodeCode());
+            if (circulation != null) {
+                // 如果跳转id为空,则走到分支
+                if (jumpNodeId == null) {
+//                    String circulation = exampleAbstract.circulation(processNodeButton.getProcessNodeCode());
+                    Assert.notEmpty(circulation, FlowExplainConstant.SPECIFY_BRANCH_EMPTY);
+                    // TODO
+                }
+            }
+            // 没有则正常流转
+            else {
+                exampleInfo.setProcessNodeId(jumpNodeId);
+                // 流程结束
+                if (jumpNodeId.equals(FlowConstant.OVER_PROCESS_FLAG)) {
+                    exampleInfo.setComplete(StatusConstant.YES);
+                    // 执行流程结束方法
+                    exampleAbstract.end();
+                }
+                // 否则正常流转
+                else {
+                    exampleInfo.setComplete(StatusConstant.No);
+                }
+            }
+        }
+
+        return flowClient.exampleInfoSave(exampleInfo).getData();
+    }
+
+
+}