24282 2 years ago
parent
commit
e3e3fa0c89

+ 5 - 5
hx-flow/src/main/java/com/fjhx/flow/core/FlowBean.java

@@ -15,17 +15,17 @@ public class FlowBean {
     /**
      * 添加流程bean
      *
-     * @param flowKey 流程标识
-     * @param cls     流程实现类
+     * @param flowKey   流程标识
+     * @param beanClass 流程实现类
      */
-    public static void addBean(String flowKey, Class<? extends FlowDelegate> cls) {
-        map.put(flowKey, cls);
+    public static void addBean(String flowKey, Class<? extends FlowDelegate> beanClass) {
+        map.put(flowKey, beanClass);
     }
 
     public static Class<? extends FlowDelegate> getBean(String flowKey) {
         Class<? extends FlowDelegate> bean = map.get(flowKey);
         if (bean == null) {
-            throw new ServiceException("未添加流程bean");
+            throw new ServiceException("没有找到流程bean");
         }
         return bean;
     }

+ 3 - 7
hx-flow/src/main/java/com/fjhx/flow/core/FlowDelegate.java

@@ -7,14 +7,10 @@ import java.util.Map;
 
 public abstract class FlowDelegate {
 
-    private final Map<String, String> templateMap = new HashMap<>();
+    public Map<String, Object> initTemplateMap() {
+        HashMap<String, Object> map = new HashMap<>();
 
-    public void initTemplateMap() {
-
-    }
-
-    public Map<String, String> getTemplateMap() {
-        return templateMap;
+        return map;
     }
 
     /**

+ 38 - 0
hx-flow/src/main/java/com/fjhx/flow/core/FlowThreadLocalData.java

@@ -0,0 +1,38 @@
+package com.fjhx.flow.core;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Map;
+
+@Getter
+@Setter
+public class FlowThreadLocalData {
+
+    /**
+     * 流程id
+     */
+    private Long flowId;
+
+    /**
+     * 业务id
+     */
+    private Long businessId;
+
+    /**
+     * 当前节点提交参数
+     */
+    private JSONObject currentData;
+
+    /**
+     * 发起流程提交参数
+     */
+    private JSONObject startData;
+
+    /**
+     * 模板配置参数
+     */
+    private Map<String, Object> templateData;
+
+}

+ 61 - 0
hx-flow/src/main/java/com/fjhx/flow/core/FlowThreadLocalUtil.java

@@ -0,0 +1,61 @@
+package com.fjhx.flow.core;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.core.NamedThreadLocal;
+
+import java.util.Map;
+
+public class FlowThreadLocalUtil {
+
+    private static final ThreadLocal<FlowThreadLocalData> FLOW_HOLDER = new NamedThreadLocal<>("saas-flow");
+
+    public static Long getFlowId() {
+        return getData().getFlowId();
+    }
+
+    public static void setFlowId(Long flowId) {
+        getData().setFlowId(flowId);
+    }
+
+    public static Long getBusinessId() {
+        return getData().getBusinessId();
+    }
+
+    public static void setBusinessId(Long businessId) {
+        getData().setBusinessId(businessId);
+    }
+
+    public static JSONObject getCurrentData() {
+        return getData().getCurrentData();
+    }
+
+    public static void setCurrentData(JSONObject currentData) {
+        getData().setCurrentData(currentData);
+    }
+
+    public static JSONObject getStartData() {
+        return getData().getStartData();
+    }
+
+    public static void setStartData(JSONObject startData) {
+        getData().setStartData(startData);
+    }
+
+    public static Map<String, Object> getTemplateData() {
+        return getData().getTemplateData();
+    }
+
+    public static void setTemplateData(Map<String, Object> templateData) {
+        getData().setTemplateData(templateData);
+    }
+
+    private static FlowThreadLocalData getData() {
+        FlowThreadLocalData flowThreadLocalData = FLOW_HOLDER.get();
+        if (flowThreadLocalData == null) {
+            flowThreadLocalData = new FlowThreadLocalData();
+            FLOW_HOLDER.set(flowThreadLocalData);
+        }
+        return flowThreadLocalData;
+    }
+
+}

+ 5 - 0
hx-flow/src/main/java/com/fjhx/flow/entity/flow/po/FlowExample.java

@@ -44,4 +44,9 @@ public class FlowExample extends BasePo {
      */
     private Integer status;
 
+    /**
+     * 开始流程提交参数
+     */
+    private String startData;
+
 }

+ 52 - 35
hx-flow/src/main/java/com/fjhx/flow/service/flow/impl/FlowProcessServiceImpl.java

@@ -1,11 +1,12 @@
 package com.fjhx.flow.service.flow.impl;
 
-import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
 import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.fjhx.flow.core.FlowBean;
 import com.fjhx.flow.core.FlowDelegate;
+import com.fjhx.flow.core.FlowThreadLocalUtil;
 import com.fjhx.flow.entity.flow.dto.InitiateDto;
 import com.fjhx.flow.entity.flow.po.FlowDefinition;
 import com.fjhx.flow.entity.flow.po.FlowDefinitionNode;
@@ -26,7 +27,11 @@ import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
 
-import java.util.*;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 @Service
@@ -58,13 +63,10 @@ public class FlowProcessServiceImpl implements FlowProcessService {
 
         // 实例化bean
         FlowDelegate flowDelegate;
-        try {
-            flowDelegate = flowDelegateCls.newInstance();
-            flowDelegate.initTemplateMap();
-        } catch (InstantiationException e) {
-            throw new ServiceException("实例化异常");
-        } catch (IllegalAccessException e) {
-            throw new ServiceException("非法访问异常");
+
+        flowDelegate = SpringUtil.getBean(flowDelegateCls);
+        if (flowDelegate == null) {
+            throw new ServiceException("没有把流程bean注册到spring中");
         }
 
         // 查找流程定义
@@ -76,6 +78,12 @@ public class FlowProcessServiceImpl implements FlowProcessService {
             throw new ServiceException("没有找到可用流程");
         }
 
+        // 初始化模板参数
+        Map<String, Object> templateMap = flowDelegate.initTemplateMap();
+        FlowThreadLocalUtil.setTemplateData(templateMap);
+        FlowThreadLocalUtil.setStartData(dto.getData());
+        FlowThreadLocalUtil.setCurrentData(dto.getData());
+
         // 流程节点列表
         List<FlowDefinitionNode> flowDefinitionNodeList = flowDefinitionNodeService
                 .list(q -> q.eq(FlowDefinitionNode::getFlowDefinitionId, flowDefinition.getId()));
@@ -102,6 +110,7 @@ public class FlowProcessServiceImpl implements FlowProcessService {
         try {
             // 生成流程id
             long flowId = IdWorker.getId();
+            FlowThreadLocalUtil.setFlowId(flowId);
 
             // 切换到主库执行流程开始节点逻辑
             DynamicDataSourceContextHolder.push(DatasourceConstant.MASTER_NAME);
@@ -111,6 +120,7 @@ public class FlowProcessServiceImpl implements FlowProcessService {
 
             // 执行开始流程方法
             Long businessId = flowDelegate.start(flowId, dto.getData());
+            FlowThreadLocalUtil.setBusinessId(businessId);
 
             FlowExampleDetail startExampleDetail = new FlowExampleDetail();
             startExampleDetail.setFlowExampleId(flowId);
@@ -121,10 +131,15 @@ public class FlowProcessServiceImpl implements FlowProcessService {
 
             // 如果下个节点是结束节点
             if (NodeTypeEnum.END.equals(NodeTypeEnum.getEnum(nextUserNode.getNodeType()))) {
-                // todo 走非默认方法
-
-                // 执行流程结束方法
-                flowDelegate.end();
+                // 走非默认方法
+                String handlingMethod = nextUserNode.getHandlingMethod();
+                if (StrUtil.isNotBlank(handlingMethod)) {
+                    Method method = flowDelegateCls.getMethod(handlingMethod);
+                    method.invoke(flowDelegate);
+                } else {
+                    // 执行流程结束方法
+                    flowDelegate.end();
+                }
 
                 // 流程已通过
                 flowExample.setStatus(FlowStatus.HAVE_PASSED.getKey());
@@ -144,10 +159,11 @@ public class FlowProcessServiceImpl implements FlowProcessService {
             // 切换到从库执行流程信息保存
             DynamicDataSourceContextHolder.push(DatasourceConstant.SLAVE_NAME);
 
-            flowExample.setTitle(getTitle(flowDelegate.getTemplateMap()));
+            flowExample.setTitle(StrUtil.format(flowDefinition.getTitleTemplate(), templateMap, false));
             flowExample.setDefinitionId(flowDefinition.getId());
             flowExample.setDefintionNodeId(nextUserNode.getId());
             flowExample.setBusinessId(businessId);
+            flowExample.setStartData(dto.getData().toJSONString());
             flowExampleService.save(flowExample);
             flowExampleDetailService.saveBatch(flowExampleDetailList);
 
@@ -182,44 +198,45 @@ public class FlowProcessServiceImpl implements FlowProcessService {
             return nextNodeList.get(0);
         }
 
+        // 找到分支跳转节点
+        FlowDefinitionNode defaultDefinitionNode = null;
+        Map<String, Object> templateData = FlowThreadLocalUtil.getTemplateData();
         for (FlowDefinitionNode flowDefinitionNode : nextNodeList) {
-            String handlingMethod = flowDefinitionNode.getHandlingMethod();
-            if (StrUtil.isBlank(handlingMethod)) {
-                throw new ServiceException("未配置分支流转表达式");
+            String jumpCondition = flowDefinitionNode.getJumpCondition();
+            if (StrUtil.isBlank(jumpCondition)) {
+                defaultDefinitionNode = flowDefinitionNode;
+            }
+            if (expressionResult(templateData, jumpCondition)) {
+                return flowDefinitionNode;
             }
-
         }
 
-        // todo 如果为分支,判断分支走向
-        return nextNodeList.get(0);
-    }
+        if (defaultDefinitionNode == null) {
+            throw new ServiceException("未识别到分支跳转节点");
+        }
 
-    private String getTitle(Map<String, String> map) {
-        return "";
+        return defaultDefinitionNode;
     }
 
     /**
      * 校验el表达式
-     *
-     * @param map
-     * @param expression
-     * @return
      */
     public static boolean expressionResult(Map<String, Object> map, String expression) {
         Expression exp = AviatorEvaluator.compile(expression);
-        final Object execute = exp.execute(map);
+        Object execute = exp.execute(map);
         return Boolean.parseBoolean(String.valueOf(execute));
     }
 
-
     public static void main(String[] args) {
-        HashMap<Object, Object> map1 = new HashMap<>();
-        map1.put("test2", "2");
+        // HashMap<Object, Object> map1 = new HashMap<>();
+        // map1.put("test2", "2");
+        //
+        HashMap<String, Object> map2 = new HashMap<>();
+
+        map2.put("admin3", "dsaasdsad");
+        map2.put("admin1", 2);
 
-        HashMap<String, Object> map = new HashMap<>();
-        map.put("admin", new Date());
-        map.put("admin2", DateUtil.offsetDay(new Date(), 1));
-        System.out.println(expressionResult(map, "admin < admin2"));
+        System.out.println(expressionResult(map2, "admin1 > 2"));
     }
 
 }

+ 14 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java

@@ -1,7 +1,11 @@
 package com.ruoyi.system.service;
 
+import com.baomidou.dynamic.datasource.annotation.DS;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.constant.DatasourceConstant;
 import com.ruoyi.common.core.domain.entity.SysUser;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 
@@ -204,4 +208,14 @@ public interface ISysUserService extends IService<SysUser> {
      * @return 结果
      */
     public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
+
+    /**
+     * 通过userId列表获取uis对象list
+     * @param userIdList 用户id list
+     * @return 用户list
+     */
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    @DS(DatasourceConstant.SLAVE_NAME)
+    List<SysUser> getListByUserId(List<Long> userIdList);
+
 }

+ 5 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

@@ -480,4 +480,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         }
         return successMsg.toString();
     }
+
+    @Override
+    public List<SysUser> getListByUserId(List<Long> userIdList) {
+        return listByIds(userIdList);
+    }
 }

+ 39 - 0
ruoyi-system/src/main/java/com/ruoyi/system/utils/UserUtil.java

@@ -0,0 +1,39 @@
+package com.ruoyi.system.utils;
+
+import cn.hutool.extra.spring.SpringUtil;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.system.service.ISysUserService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class UserUtil {
+
+    private static final ISysUserService sysUserService = SpringUtil.getBean(ISysUserService.class);
+
+    public static List<SysUser> getListByIds(List<Long> idList) {
+        if (idList.size() == 0) {
+            return new ArrayList<>();
+        }
+        return sysUserService.getListByUserId(idList);
+    }
+
+    public static Map<Long, SysUser> getMapByIds(List<Long> idList) {
+        return getListByIds(idList).stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity()));
+    }
+
+    public static Map<Long, String> getNickNameMapByIds(List<Long> idList) {
+        return getListByIds(idList).stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));
+    }
+
+    public static <T> void assignmentNickName(List<T> list, Function<T, Long> idMapper, Consumer<String> setNickNameMap) {
+        List<Long> idList = list.stream().map(idMapper).collect(Collectors.toList());
+        Map<Long, String> nickNameMapByIds = getNickNameMapByIds(idList);
+        list.forEach(item -> setNickNameMap.accept(nickNameMapByIds.get(idMapper.apply(item))));
+    }
+
+}