24282 2 жил өмнө
parent
commit
66435d1744

+ 60 - 2
hx-flow/src/main/java/com/fjhx/flow/controller/flow/FlowExampleController.java

@@ -1,6 +1,21 @@
 package com.fjhx.flow.controller.flow;
 
-import org.springframework.web.bind.annotation.*;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.flow.entity.flow.dto.FlowExampleSelectDto;
+import com.fjhx.flow.entity.flow.po.FlowInfo;
+import com.fjhx.flow.entity.flow.vo.ApprovalRecordVo;
+import com.fjhx.flow.entity.flow.vo.FlowExampleVo;
+import com.fjhx.flow.service.flow.FlowExampleService;
+import com.ruoyi.common.constant.BaseSourceConstant;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
 
 
 /**
@@ -8,12 +23,55 @@ import org.springframework.web.bind.annotation.*;
  * 流程实例 前端控制器
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-03-16
  */
+@DS(BaseSourceConstant.BASE)
 @RestController
 @RequestMapping("/flowExample")
 public class FlowExampleController {
 
+    @Autowired
+    private FlowExampleService flowExampleService;
+
+    /**
+     * 获取流程类型
+     */
+    @PostMapping("/getFlowType")
+    public List<FlowInfo> getFlowType() {
+        return flowExampleService.getFlowType();
+    }
+
+    /**
+     * 获取待处理流程实例
+     */
+    @PostMapping("getToBeProcessedPage")
+    public Page<FlowExampleVo> getToBeProcessedPage(@RequestBody FlowExampleSelectDto dto) {
+        return flowExampleService.getToBeProcessedPage(dto);
+    }
+
+    /**
+     * 获取已发起流程实例
+     */
+    @PostMapping("/getHaveInitiatedPage")
+    public Page<FlowExampleVo> getHaveInitiatedPage(@RequestBody FlowExampleSelectDto dto) {
+        return flowExampleService.getHaveInitiatedPage(dto);
+    }
+
+    /**
+     * 获取已处理流程实例
+     */
+    @PostMapping("/getProcessedPage")
+    public Page<FlowExampleVo> getProcessedPage(@RequestBody FlowExampleSelectDto dto) {
+        return flowExampleService.getProcessedPage(dto);
+    }
+
+    /**
+     * 获取审批记录
+     */
+    @PostMapping("/getApprovalRecord")
+    public ApprovalRecordVo getApprovalRecord(@RequestBody BaseSelectDto dto) {
+        return flowExampleService.getApprovalRecord(dto.getId());
+    }
 
 }

+ 23 - 0
hx-flow/src/main/java/com/fjhx/flow/entity/flow/dto/FlowExampleSelectDto.java

@@ -0,0 +1,23 @@
+package com.fjhx.flow.entity.flow.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 流程实例列表查询入参实体
+ *
+ * @author
+ * @since 2023-04-10
+ */
+@Getter
+@Setter
+public class FlowExampleSelectDto extends BaseSelectDto {
+
+    /**
+     * 流程id
+     */
+    private Long flowInfoId;
+
+
+}

+ 95 - 0
hx-flow/src/main/java/com/fjhx/flow/entity/flow/vo/ApprovalRecordVo.java

@@ -0,0 +1,95 @@
+package com.fjhx.flow.entity.flow.vo;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+import java.util.List;
+
+@Getter
+@Setter
+public class ApprovalRecordVo {
+
+    /**
+     * 流程实例id
+     */
+    private Long id;
+
+    /**
+     * 实例版本
+     */
+    private Integer version;
+
+    /**
+     * 处理当前节点按钮列表
+     */
+    private List<ButtonInfo> buttonInfoList;
+
+    /**
+     * 审批记录
+     */
+    private List<Record> recordList;
+
+    @Getter
+    @Setter
+    public static class ButtonInfo {
+
+        /**
+         * 按钮处理类型
+         */
+        private Integer type;
+
+        /**
+         * 按钮名称
+         */
+        private String name;
+
+    }
+
+    @Getter
+    @Setter
+    public static class Record {
+
+        /**
+         * 状态 1已处理 2进行中 3未开始
+         */
+        private Integer status;
+
+        /**
+         * 节点id
+         */
+        private Long nodeId;
+
+        /**
+         * 节点类型 1开始 2办理 3分支 99结束
+         */
+        private Integer nodeType;
+
+        /**
+         * 节点名称
+         */
+        private String nodeName;
+
+        /**
+         * 处理时间
+         */
+        private Date processedDate;
+
+        /**
+         * 处理人
+         */
+        private String processedUser;
+
+        /**
+         * 处理人id
+         */
+        private Long processedUserId;
+
+        /**
+         * 处理意见
+         */
+        private String remark;
+
+    }
+
+}

+ 5 - 0
hx-flow/src/main/java/com/fjhx/flow/entity/flow/vo/FlowDefinitionPageVo.java

@@ -19,6 +19,11 @@ public class FlowDefinitionPageVo {
     private Long id;
 
     /**
+     * 流程id
+     */
+    private Long flowInfoId;
+
+    /**
      * 分类名称
      */
     private String classifyName;

+ 32 - 0
hx-flow/src/main/java/com/fjhx/flow/entity/flow/vo/FlowExampleVo.java

@@ -0,0 +1,32 @@
+package com.fjhx.flow.entity.flow.vo;
+
+import com.fjhx.flow.entity.flow.po.FlowExample;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 流程实例列表查询返回值实体
+ *
+ * @author
+ * @since 2023-04-10
+ */
+@Getter
+@Setter
+public class FlowExampleVo extends FlowExample {
+
+    /**
+     * 发起人名称
+     */
+    private String createUserName;
+
+    /**
+     * 流程key
+     */
+    private String flowKey;
+
+    /**
+     * 流程名称
+     */
+    private String flowName;
+
+}

+ 8 - 2
hx-flow/src/main/java/com/fjhx/flow/mapper/flow/FlowExampleMapper.java

@@ -1,7 +1,11 @@
 package com.fjhx.flow.mapper.flow;
 
-import com.fjhx.flow.entity.flow.po.FlowExample;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.flow.entity.flow.po.FlowExample;
+import com.fjhx.flow.entity.flow.vo.FlowExampleVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
 
 
 /**
@@ -9,9 +13,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  * 流程实例 Mapper 接口
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-03-16
  */
 public interface FlowExampleMapper extends BaseMapper<FlowExample> {
 
+    Page<FlowExampleVo> selectExample(@Param("page") Page<Object> page, @Param("ew") IWrapper<FlowExample> wrapper);
+
 }

+ 33 - 1
hx-flow/src/main/java/com/fjhx/flow/service/flow/FlowExampleService.java

@@ -1,17 +1,49 @@
 package com.fjhx.flow.service.flow;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.flow.entity.flow.dto.FlowExampleSelectDto;
 import com.fjhx.flow.entity.flow.po.FlowExample;
+import com.fjhx.flow.entity.flow.po.FlowInfo;
+import com.fjhx.flow.entity.flow.vo.ApprovalRecordVo;
+import com.fjhx.flow.entity.flow.vo.FlowExampleVo;
 import com.ruoyi.common.core.service.BaseService;
 
+import java.util.List;
+
 
 /**
  * <p>
  * 流程实例 服务类
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-03-16
  */
 public interface FlowExampleService extends BaseService<FlowExample> {
 
+    /**
+     * 获取流程类型
+     */
+    List<FlowInfo> getFlowType();
+
+    /**
+     * 获取待处理流程实例
+     */
+    Page<FlowExampleVo> getToBeProcessedPage(FlowExampleSelectDto dto);
+
+    /**
+     * 获取已发起流程实例
+     */
+    Page<FlowExampleVo> getHaveInitiatedPage(FlowExampleSelectDto dto);
+
+    /**
+     * 获取已处理流程实例
+     */
+    Page<FlowExampleVo> getProcessedPage(FlowExampleSelectDto dto);
+
+    /**
+     * 获取审批记录
+     */
+    ApprovalRecordVo getApprovalRecord(Long id);
+
 }

+ 266 - 4
hx-flow/src/main/java/com/fjhx/flow/service/flow/impl/FlowExampleServiceImpl.java

@@ -1,21 +1,283 @@
 package com.fjhx.flow.service.flow.impl;
 
-import com.fjhx.flow.entity.flow.po.FlowExample;
-import com.fjhx.flow.mapper.flow.FlowExampleMapper;
-import com.fjhx.flow.service.flow.FlowExampleService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.flow.entity.flow.dto.FlowExampleSelectDto;
+import com.fjhx.flow.entity.flow.po.*;
+import com.fjhx.flow.entity.flow.vo.ApprovalRecordVo;
+import com.fjhx.flow.entity.flow.vo.FlowExampleVo;
+import com.fjhx.flow.enums.FlowStatusEnum;
+import com.fjhx.flow.enums.HandleTypeEnum;
+import com.fjhx.flow.enums.NodeTypeEnum;
+import com.fjhx.flow.mapper.flow.FlowExampleMapper;
+import com.fjhx.flow.service.flow.*;
+import com.ruoyi.common.core.domain.BasePo;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import com.ruoyi.common.utils.wrapper.SqlField;
+import com.ruoyi.system.utils.UserUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * <p>
  * 流程实例 服务实现类
  * </p>
  *
- * @author 
+ * @author
  * @since 2023-03-16
  */
 @Service
 public class FlowExampleServiceImpl extends ServiceImpl<FlowExampleMapper, FlowExample> implements FlowExampleService {
 
+    @Autowired
+    private FlowExampleDetailService flowExampleDetailService;
+
+    @Autowired
+    private FlowDefinitionService flowDefinitionService;
+
+    @Autowired
+    private FlowInfoService flowInfoService;
+
+    @Autowired
+    private FlowDefinitionNodeService flowDefinitionNodeService;
+
+    @Override
+    public List<FlowInfo> getFlowType() {
+        List<Long> flowInofIdList = flowDefinitionService.getDistinctList(FlowDefinition::getFlowInfoId);
+        return flowInfoService.listByIds(flowInofIdList);
+    }
+
+    @Override
+    public Page<FlowExampleVo> getToBeProcessedPage(FlowExampleSelectDto dto) {
+
+        IWrapper<FlowExample> wrapper = getWrapper()
+                .lt("fe", FlowExample::getStatus, 2)
+                .eq("fe", FlowExample::getHandleUserId, SecurityUtils.getUserId());
+
+        return doSelectExample(dto, wrapper);
+    }
+
+    @Override
+    public Page<FlowExampleVo> getHaveInitiatedPage(FlowExampleSelectDto dto) {
+        IWrapper<FlowExample> wrapper = getWrapper().eq("fe", FlowExample::getCreateUser, SecurityUtils.getUserId());
+        return doSelectExample(dto, wrapper);
+    }
+
+    @Override
+    public Page<FlowExampleVo> getProcessedPage(FlowExampleSelectDto dto) {
+
+        List<Long> flowExampleId = flowExampleDetailService.listObject(FlowExampleDetail::getFlowExampleId,
+                q -> q.eq(BasePo::getCreateUser, SecurityUtils.getUserId()));
+
+        if (flowExampleId.size() == 0) {
+            return new Page<>();
+        }
+
+        IWrapper<FlowExample> wrapper = getWrapper().in("fe", FlowExample::getId, flowExampleId);
+
+        return doSelectExample(dto, wrapper);
+    }
+
+    @Override
+    public ApprovalRecordVo getApprovalRecord(Long id) {
+
+        if (id == null) {
+            throw new ServiceException("id不能为空");
+        }
+
+        ApprovalRecordVo result = new ApprovalRecordVo();
+
+        // 流程实例
+        FlowExample flowExample = getById(id);
+
+        if (flowExample == null) {
+            throw new ServiceException("没有找到流程");
+        }
+
+        // 获取已完成节点
+        List<FlowExampleDetail> flowExampleDetailList = flowExampleDetailService.list(
+                q -> q.eq(FlowExampleDetail::getFlowExampleId, id));
+
+        // 获取流程全部节点
+        List<FlowDefinitionNode> flowDefinitionNodeList = flowDefinitionNodeService.list(
+                q -> q.eq(FlowDefinitionNode::getFlowDefinitionId, flowExample.getDefinitionId()));
+
+        // 审批记录list
+        List<ApprovalRecordVo.Record> recordList = new ArrayList<>();
+
+        // 添加已处理记录
+        addProcessed(recordList, flowExampleDetailList);
+
+        // 添加进行中记录
+        addInProgress(recordList, flowExample);
+
+        // 赋值节点信息以及处理人名称
+        setNodeInfoAndHandleUserName(recordList, flowDefinitionNodeList);
+
+        // 添加未开始记录
+        addNotStarted(recordList, flowExample, flowDefinitionNodeList);
+
+        // 获取button列表
+        List<ApprovalRecordVo.ButtonInfo> buttonInfoList = getButtonInfoList(flowExample, flowDefinitionNodeList);
+
+        result.setId(id);
+        result.setVersion(result.getVersion());
+        result.setRecordList(recordList);
+        result.setButtonInfoList(buttonInfoList);
+
+        return result;
+    }
+
+    private List<ApprovalRecordVo.ButtonInfo> getButtonInfoList(FlowExample flowExample,
+                                                                List<FlowDefinitionNode> flowDefinitionNodeList) {
+
+        List<ApprovalRecordVo.ButtonInfo> buttonInfoList = new ArrayList<>();
+
+        Integer status = flowExample.getStatus();
+
+        if (FlowStatusEnum.PASS.getKey().equals(status)
+                || FlowStatusEnum.REJECT.getKey().equals(status)
+                || !Objects.equals(flowExample.getHandleUserId(), SecurityUtils.getUserId())) {
+            return buttonInfoList;
+        }
+
+        FlowDefinitionNode flowDefinitionNode = flowDefinitionNodeList.stream()
+                .filter(item -> Objects.equals(item.getId(), flowExample.getDefinitionNodeId()))
+                .findFirst().orElse(null);
+
+        if (flowDefinitionNode == null) {
+            return buttonInfoList;
+        }
+
+        String nodeButtonSet = flowDefinitionNode.getNodeButtonSet();
+        for (String buttonTypeStr : nodeButtonSet.split(",")) {
+            ApprovalRecordVo.ButtonInfo buttonInfo = new ApprovalRecordVo.ButtonInfo();
+            Integer buttonType = Convert.toInt(buttonTypeStr);
+            buttonInfo.setType(buttonType);
+            buttonInfo.setName(HandleTypeEnum.getEnum(buttonType).getValue());
+            buttonInfoList.add(buttonInfo);
+        }
+
+        return buttonInfoList;
+    }
+
+    /**
+     * 添加未开始记录
+     */
+    private void addNotStarted(List<ApprovalRecordVo.Record> recordList, FlowExample flowExample,
+                               List<FlowDefinitionNode> flowDefinitionNodeList) {
+
+        Integer status = flowExample.getStatus();
+
+        if (FlowStatusEnum.PASS.getKey().equals(status) || FlowStatusEnum.REJECT.getKey().equals(status)) {
+            return;
+        }
+
+        // 父节点id map
+        Map<Long, FlowDefinitionNode> flowDefinitionNodeMap = flowDefinitionNodeList.stream()
+                .collect(Collectors.toMap(FlowDefinitionNode::getParentId, Function.identity()));
+
+        FlowDefinitionNode nextNode = flowDefinitionNodeMap.get(flowExample.getDefinitionNodeId());
+
+        while (nextNode != null) {
+
+            Integer nodeType = nextNode.getNodeType();
+
+            ApprovalRecordVo.Record record = new ApprovalRecordVo.Record();
+            record.setStatus(3);
+            record.setNodeId(nextNode.getId());
+            record.setNodeType(nodeType);
+            record.setNodeName(nextNode.getNodeName());
+            recordList.add(record);
+
+            if (NodeTypeEnum.BRANCH.getKey().equals(nodeType) || NodeTypeEnum.END.getKey().equals(nodeType)) {
+                nextNode = null;
+            } else {
+                nextNode = flowDefinitionNodeMap.get(nextNode.getId());
+            }
+
+        }
+    }
+
+    /**
+     * 赋值节点信息以及处理人名称
+     */
+    private void setNodeInfoAndHandleUserName(List<ApprovalRecordVo.Record> recordList,
+                                              List<FlowDefinitionNode> flowDefinitionNodeList) {
+
+        Map<Long, FlowDefinitionNode> flowDefinitionNodeMap = flowDefinitionNodeList.stream()
+                .collect(Collectors.toMap(FlowDefinitionNode::getId, Function.identity()));
+
+        for (ApprovalRecordVo.Record record : recordList) {
+            FlowDefinitionNode flowDefinitionNode = flowDefinitionNodeMap.get(record.getNodeId());
+            record.setNodeName(flowDefinitionNode.getNodeName());
+            record.setNodeType(flowDefinitionNode.getNodeType());
+        }
+
+        UserUtil.assignmentNickName(
+                recordList,
+                ApprovalRecordVo.Record::getProcessedUserId,
+                ApprovalRecordVo.Record::setProcessedUser);
+    }
+
+    /**
+     * 添加进行中记录
+     */
+    private void addInProgress(List<ApprovalRecordVo.Record> recordList, FlowExample flowExample) {
+        Integer status = flowExample.getStatus();
+
+        if (FlowStatusEnum.PASS.getKey().equals(status) || FlowStatusEnum.REJECT.getKey().equals(status)) {
+            return;
+        }
+
+        ApprovalRecordVo.Record record = new ApprovalRecordVo.Record();
+        record.setStatus(2);
+        record.setNodeId(flowExample.getDefinitionNodeId());
+        record.setProcessedUserId(flowExample.getHandleUserId());
+        recordList.add(record);
+    }
+
+    /**
+     * 添加已处理记录
+     */
+    private void addProcessed(List<ApprovalRecordVo.Record> recordList, List<FlowExampleDetail> flowExampleDetailList) {
+        for (FlowExampleDetail flowExampleDetail : flowExampleDetailList) {
+            ApprovalRecordVo.Record record = new ApprovalRecordVo.Record();
+            record.setStatus(1);
+            record.setNodeId(flowExampleDetail.getFlowDefinitionNodeId());
+            record.setProcessedDate(flowExampleDetail.getCreateTime());
+            record.setProcessedUserId(flowExampleDetail.getCreateUser());
+            record.setRemark(flowExampleDetail.getHandleRemark());
+            recordList.add(record);
+        }
+    }
+
+    /**
+     * 执行查询流程实例
+     */
+    private Page<FlowExampleVo> doSelectExample(FlowExampleSelectDto dto, IWrapper<FlowExample> wrapper) {
+
+        wrapper.eq("fd", FlowDefinition::getFlowInfoId, dto.getFlowInfoId())
+                .keyword(dto, new SqlField("fe", FlowExample::getTitle))
+                .orderByDesc("fe", FlowExample::getId);
+
+        Page<FlowExampleVo> page = baseMapper.selectExample(dto.getPage(), wrapper);
+        List<FlowExampleVo> records = page.getRecords();
+
+        // 赋值流程发起人名称
+        UserUtil.assignmentNickName(records, BasePo::getCreateUser, FlowExampleVo::setCreateUserName);
+
+        return page;
+    }
+
 }

+ 1 - 0
hx-flow/src/main/resources/mapper/flow/FlowDefinitionMapper.xml

@@ -4,6 +4,7 @@
 
     <select id="getPage" resultType="com.fjhx.flow.entity.flow.vo.FlowDefinitionPageVo">
         select fd.id,
+               fd.flow_info_id,
                fi.classify_name,
                fi.flow_name,
                fi.flow_key,

+ 16 - 0
hx-flow/src/main/resources/mapper/flow/FlowExampleMapper.xml

@@ -1,4 +1,20 @@
 <?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">
 <mapper namespace="com.fjhx.flow.mapper.flow.FlowExampleMapper">
+
+    <select id="selectExample" resultType="com.fjhx.flow.entity.flow.vo.FlowExampleVo">
+        select fe.id,
+               fi.flow_key,
+               fi.flow_name,
+               fe.title,
+               fe.status,
+               fe.create_user,
+               fe.create_time,
+               fe.business_id
+        from flow_info fi
+                 inner join flow_definition fd on fd.flow_info_id = fi.id
+                 inner join flow_example fe on fe.definition_id = fd.id
+            ${ew.customSqlSegment}
+    </select>
+
 </mapper>

+ 2 - 1
ruoyi-common/src/main/java/com/ruoyi/common/core/service/BaseService.java

@@ -61,7 +61,8 @@ public interface BaseService<T extends BaseIdPo> extends IService<T> {
     }
 
     default <K> List<K> listObject(SFunction<T, K> mapper, Consumer<LambdaQueryWrapper<T>> consumer) {
-        return listObjs(Wrappers.<T>lambdaQuery().select(mapper).func(ObjectUtil.isNotEmpty(consumer), consumer), t -> (K) t);
+        List<T> list = list(Wrappers.<T>lambdaQuery().select(mapper).func(ObjectUtil.isNotEmpty(consumer), consumer));
+        return list.stream().map(mapper).filter(Objects::nonNull).distinct().collect(Collectors.toList());
     }
 
     default <K, V> Map<K, V> mapKV(SFunction<T, K> kFun, SFunction<T, V> vFun, Consumer<LambdaQueryWrapper<T>> consumer) {

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

@@ -5,6 +5,7 @@ import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.system.service.ISysUserService;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.BiConsumer;
@@ -27,10 +28,16 @@ public class UserUtil {
     }
 
     public static Map<Long, String> getNickNameMapByIds(List<Long> idList) {
+        if (idList.size() == 0) {
+            new HashMap<>();
+        }
         return getListByIds(idList).stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));
     }
 
     public static <T> void assignmentNickName(List<T> list, Function<T, Long> idMapper, BiConsumer<T, String> setNickNameMap) {
+        if (list == null || list.size() == 0) {
+            return;
+        }
         List<Long> idList = list.stream().map(idMapper).collect(Collectors.toList());
         Map<Long, String> nickNameMapByIds = getNickNameMapByIds(idList);
         list.forEach(item -> setNickNameMap.accept(item, nickNameMapByIds.get(idMapper.apply(item))));