From 6fbfdf4c73f9673adb7e2777e83565195568f7a8 Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期四, 28 十一月 2024 06:04:16 +0800
Subject: [PATCH] 完善流程(表单回显接口)、项目流程表增加流程实例id字段、流程推进详情接口

---
 flowable/src/main/java/com/ycl/service/IFlowTaskService.java                  |   10 +
 business/src/main/java/com/ycl/domain/vo/ProjectProcessDetailVO.java          |   86 ++++++++++
 business/src/main/java/com/ycl/domain/entity/ProjectProcess.java              |    5 
 business/src/main/java/com/ycl/service/impl/ProcessConfigInfoServiceImpl.java |   20 +-
 flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java          |   28 +++
 business/src/main/java/com/ycl/controller/ProjectProcessController.java       |   21 +
 start/src/main/resources/application.yml                                      |   20 +-
 flowable/src/main/java/com/ycl/common/enums/FlowComment.java                  |    3 
 flowable/src/main/java/com/ycl/controller/FlowTaskController.java             |   14 +
 business/src/main/resources/mapper/ProjectProcessMapper.xml                   |    1 
 business/src/main/java/com/ycl/service/impl/ProjectProcessServiceImpl.java    |  253 ++++++++++++++++++++++++++++++-
 business/src/main/java/com/ycl/service/ProjectProcessService.java             |   16 +
 business/src/main/java/com/ycl/domain/vo/ProjectProcessVO.java                |    3 
 13 files changed, 437 insertions(+), 43 deletions(-)

diff --git a/business/src/main/java/com/ycl/controller/ProjectProcessController.java b/business/src/main/java/com/ycl/controller/ProjectProcessController.java
index 40e3749..9024cbf 100644
--- a/business/src/main/java/com/ycl/controller/ProjectProcessController.java
+++ b/business/src/main/java/com/ycl/controller/ProjectProcessController.java
@@ -34,7 +34,7 @@
 
     @PostMapping("/page")
     @ApiOperation(value = "鍒嗛〉", notes = "鍒嗛〉")
-    @PreAuthorize("@ss.hasPermi('projectProcess:page')")
+//    @PreAuthorize("@ss.hasPermi('projectProcess:page')")
     public Result page(ProjectProcessQuery query) {
         return projectProcessService.page(query);
     }
@@ -42,16 +42,23 @@
 
     @PostMapping("/set")
     @ApiOperation(value = "椤圭洰璁剧疆娴佺▼", notes = "椤圭洰璁剧疆娴佺▼")
-    @PreAuthorize("@ss.hasPermi('projectProcess:set')")
+//    @PreAuthorize("@ss.hasPermi('projectProcess:set')")
     public Result projectSetProcess(@RequestBody @Validated ProjectProcessForm form) {
         return projectProcessService.projectSetProcess(form);
     }
 
 
-    @GetMapping("/{id}")
-    @ApiOperation(value = "璇︽儏", notes = "璇︽儏")
-    @PreAuthorize("@ss.hasPermi('projectProcess:detail')")
-    public Result detail(@PathVariable("id") Integer id) {
-        return projectProcessService.detail(id);
+    @GetMapping("/detail/{projectId}/{processId}")
+    @ApiOperation(value = "鑾峰彇椤圭洰娴佺▼璇︽儏淇℃伅", notes = "鑾峰彇椤圭洰娴佺▼璇︽儏淇℃伅")
+//    @PreAuthorize("@ss.hasPermi('projectProcess:detail')")
+    public Result detail(@PathVariable("projectId") Long projectId, @PathVariable("processId") String processId) {
+        return projectProcessService.detail(projectId, processId);
+    }
+
+    @PostMapping("/start/{projectId}/{processId}")
+    @ApiOperation(value = "鍚姩娴佺▼", notes = "鍚姩娴佺▼")
+//    @PreAuthorize("@ss.hasPermi('projectProcess:start')")
+    public Result startProcess(@PathVariable("projectId") String projectId, @PathVariable("processId") String processId) {
+        return projectProcessService.startProcess(projectId, processId);
     }
 }
diff --git a/business/src/main/java/com/ycl/domain/entity/ProjectProcess.java b/business/src/main/java/com/ycl/domain/entity/ProjectProcess.java
index b3f79fd..e5609bf 100644
--- a/business/src/main/java/com/ycl/domain/entity/ProjectProcess.java
+++ b/business/src/main/java/com/ycl/domain/entity/ProjectProcess.java
@@ -24,8 +24,11 @@
     private Long projectId;
 
     @TableField("flowable_process_id")
-    /** 娴佺▼ID */
+    /** 娴佺▼瀹氫箟ID */
     private String flowableProcessId;
 
+    @TableField("process_instance_id")
+    /** 娴佺▼瀹炰緥id */
+    private String processInstanceId;
 
 }
diff --git a/business/src/main/java/com/ycl/domain/vo/ProjectProcessDetailVO.java b/business/src/main/java/com/ycl/domain/vo/ProjectProcessDetailVO.java
new file mode 100644
index 0000000..fc38137
--- /dev/null
+++ b/business/src/main/java/com/ycl/domain/vo/ProjectProcessDetailVO.java
@@ -0,0 +1,86 @@
+package com.ycl.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author锛歺p
+ * @date锛�2024/11/27 16:25
+ */
+@Data
+public class ProjectProcessDetailVO {
+
+    /**
+     * 椤圭洰id
+     */
+    private Long projectId;
+
+    /**
+     * 椤圭洰鍚嶇О
+     */
+    private String projectName;
+
+    /**
+     * 椤圭洰浠g爜
+     */
+    private String projectCode;
+
+    /**
+     * 椤圭洰鏍囩
+     */
+    private List<String> tagList;
+
+    /**
+     * 浠e姙鍒楄〃
+     */
+    private List<Object> taskList;
+
+    private TaskStatistics statistics;
+
+
+    @Data
+    public static class TaskStatistics {
+
+        /**
+         * 鎬诲叡浠诲姟鏁�
+         */
+        private Long totalTaskNum = 0L;
+
+        /**
+         * 寰呭姙浠诲姟鏁�
+         */
+        private Long todoTaskNum = 0L;
+
+        /**
+         * 褰撳墠浠诲姟
+         */
+        private Object currentTask;
+
+        /**
+         * 鍓╀綑浠诲姟鏁�
+         */
+        private Long remainingTaskNum = 0L;
+
+        /**
+         * 鎸夋椂瀹屾垚浠诲姟鏁�
+         */
+        private Long timelyFinishedTaskNum = 0L;
+
+        /**
+         * 瓒呮椂瀹屾垚浠诲姟鏁�
+         */
+        private Long overtimeFinishedTaskNum = 0L;
+
+        /**
+         * 涓存湡浠诲姟鏁�
+         */
+        private Long willOvertimeTaskNum = 0L;
+
+        /**
+         * 鐫e姙浠诲姟鏁�
+         */
+        private Long urgeTaskNum = 0L;
+
+    }
+}
diff --git a/business/src/main/java/com/ycl/domain/vo/ProjectProcessVO.java b/business/src/main/java/com/ycl/domain/vo/ProjectProcessVO.java
index a063406..1c0c7b1 100644
--- a/business/src/main/java/com/ycl/domain/vo/ProjectProcessVO.java
+++ b/business/src/main/java/com/ycl/domain/vo/ProjectProcessVO.java
@@ -27,4 +27,7 @@
 
     @ApiModelProperty("娴佺▼鍚嶇О")
     private String flowableProcessName;
+
+    @ApiModelProperty("娴佺▼瀹炰緥id")
+    private String processInstanceId;
 }
diff --git a/business/src/main/java/com/ycl/service/ProjectProcessService.java b/business/src/main/java/com/ycl/service/ProjectProcessService.java
index e200d09..2a67244 100644
--- a/business/src/main/java/com/ycl/service/ProjectProcessService.java
+++ b/business/src/main/java/com/ycl/service/ProjectProcessService.java
@@ -23,11 +23,12 @@
     Result page(ProjectProcessQuery query);
 
     /**
-     * 鏍规嵁id鏌ユ壘
-     * @param id
+     * 鏍规嵁椤圭洰id鏌ユ壘
+     * @param projectId
+     * @param processId
      * @return
      */
-    Result detail(Integer id);
+    Result detail(Long projectId, String processId);
 
     /**
      * 椤圭洰璁剧疆娴佺▼
@@ -36,4 +37,13 @@
      * @return
      */
     Result projectSetProcess(ProjectProcessForm form);
+
+    /**
+     * 鍚姩娴佺▼
+     *
+     * @param processId  娴佺▼瀹氫箟id
+     * @param projectId  椤圭洰id锛屼綔涓轰笟鍔d瀛樺叆activity琛�
+     * @return
+     */
+    Result startProcess(String projectId, String processId);
 }
diff --git a/business/src/main/java/com/ycl/service/impl/ProcessConfigInfoServiceImpl.java b/business/src/main/java/com/ycl/service/impl/ProcessConfigInfoServiceImpl.java
index 5d39aaf..bea6ce4 100644
--- a/business/src/main/java/com/ycl/service/impl/ProcessConfigInfoServiceImpl.java
+++ b/business/src/main/java/com/ycl/service/impl/ProcessConfigInfoServiceImpl.java
@@ -91,23 +91,23 @@
     public Result list(ProcessConfigInfoQuery query) {
         List<FlowProcDefWithConfigDto> dataList = flowDeployMapper.selectDeployListWithConfig(query);
 
-        // 鏍规嵁 processDefId 鍒嗙粍锛屽苟鍙栨瘡缁勪腑 鐗堟湰鍙� 鏈�澶х殑閭d竴涓�
-        Map<String, FlowProcDefWithConfigDto> groupedByProcessDefId = dataList.stream()
-                .collect(Collectors.toMap(
-                        FlowProcDefWithConfigDto::getProcessDefId, // keyMapper: 鎻愬彇 processDefId 浣滀负閿�
-                        Function.identity(),                      // valueMapper: 鐩存帴浣跨敤瀵硅薄浣滀负鍊�
-                        BinaryOperator.maxBy(Comparator.comparingInt(FlowProcDefWithConfigDto::getProcessDefVersion)) // mergeFunction: 姣旇緝 processDefVersion锛屽彇鏈�澶х殑
-                ));
-        List<FlowProcDefWithConfigDto> resultList = new ArrayList<>(groupedByProcessDefId.values());
+//        // 鏍规嵁 processDefId 鍒嗙粍锛屽苟鍙栨瘡缁勪腑 鐗堟湰鍙� 鏈�澶х殑閭d竴涓�
+//        Map<String, FlowProcDefWithConfigDto> groupedByProcessDefId = dataList.stream()
+//                .collect(Collectors.toMap(
+//                        FlowProcDefWithConfigDto::getProcessDefId, // keyMapper: 鎻愬彇 processDefId 浣滀负閿�
+//                        Function.identity(),                      // valueMapper: 鐩存帴浣跨敤瀵硅薄浣滀负鍊�
+//                        BinaryOperator.maxBy(Comparator.comparingInt(FlowProcDefWithConfigDto::getProcessDefVersion)) // mergeFunction: 姣旇緝 processDefVersion锛屽彇鏈�澶х殑
+//                ));
+//        List<FlowProcDefWithConfigDto> resultList = new ArrayList<>(groupedByProcessDefId.values());
 
         // 鍔犺浇鎸傝〃鍗�
-        for (FlowProcDefWithConfigDto procDef : resultList) {
+        for (FlowProcDefWithConfigDto procDef : dataList) {
             SysForm sysForm = sysDeployFormService.selectSysDeployFormByDeployId(procDef.getDeploymentId());
             if (Objects.nonNull(sysForm)) {
                 procDef.setFormName(sysForm.getFormName());
                 procDef.setFormId(sysForm.getFormId());
             }
         }
-        return Result.ok().data(resultList);
+        return Result.ok().data(dataList);
     }
 }
diff --git a/business/src/main/java/com/ycl/service/impl/ProjectProcessServiceImpl.java b/business/src/main/java/com/ycl/service/impl/ProjectProcessServiceImpl.java
index 31d6031..4856ea1 100644
--- a/business/src/main/java/com/ycl/service/impl/ProjectProcessServiceImpl.java
+++ b/business/src/main/java/com/ycl/service/impl/ProjectProcessServiceImpl.java
@@ -1,9 +1,21 @@
 package com.ycl.service.impl;
 
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
 import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
+import com.ycl.common.constant.ProcessConstants;
+import com.ycl.common.core.domain.AjaxResult;
+import com.ycl.common.core.domain.entity.SysRole;
+import com.ycl.common.core.domain.entity.SysUser;
+import com.ycl.common.enums.FlowComment;
+import com.ycl.common.utils.SecurityUtils;
+import com.ycl.domain.dto.FlowTaskDto;
+import com.ycl.domain.entity.ProjectInfo;
 import com.ycl.domain.entity.ProjectProcess;
+import com.ycl.domain.vo.ProjectProcessDetailVO;
+import com.ycl.mapper.ProjectInfoMapper;
 import com.ycl.mapper.ProjectProcessMapper;
 import com.ycl.service.ProjectProcessService;
 import com.ycl.common.base.Result;
@@ -11,14 +23,30 @@
 import com.ycl.domain.form.ProjectProcessForm;
 import com.ycl.domain.vo.ProjectProcessVO;
 import com.ycl.domain.query.ProjectProcessQuery;
+import com.ycl.system.service.ISysRoleService;
+import com.ycl.system.service.ISysUserService;
+import org.apache.commons.lang3.StringUtils;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.bpmn.model.FlowElement;
+import org.flowable.bpmn.model.Process;
+import org.flowable.bpmn.model.StartEvent;
+import org.flowable.engine.*;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.repository.ProcessDefinition;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.identitylink.api.IdentityLink;
+import org.flowable.task.api.Task;
+import org.flowable.task.api.TaskQuery;
+import org.flowable.task.api.history.HistoricTaskInstance;
+import org.flowable.task.api.history.HistoricTaskInstanceQuery;
 import org.springframework.stereotype.Service;
 import lombok.RequiredArgsConstructor;
 import com.ycl.framework.utils.PageUtil;
 import org.springframework.beans.BeanUtils;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.Assert;
 
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -32,6 +60,14 @@
 public class ProjectProcessServiceImpl extends ServiceImpl<ProjectProcessMapper, ProjectProcess> implements ProjectProcessService {
 
     private final ProjectProcessMapper projectProcessMapper;
+    private final RuntimeService runtimeService;
+    private final TaskService taskService;
+    private final IdentityService identityService;
+    private final RepositoryService repositoryService;
+    private final ProjectInfoMapper projectInfoMapper;
+    private final HistoryService historyService;
+    private final ISysUserService sysUserService;
+    private final ISysRoleService sysRoleService;
 
     /**
      * 鍒嗛〉鏌ヨ
@@ -46,15 +82,48 @@
     }
 
     /**
-     * 鏍规嵁id鏌ユ壘
-     * @param id
+     * 鑾峰彇娴佺▼璇︽儏
+     * @param projectId
      * @return
      */
     @Override
-    public Result detail(Integer id) {
-        ProjectProcessVO vo = baseMapper.getById(id);
-        Assert.notNull(vo, "璁板綍涓嶅瓨鍦�");
-        return Result.ok().data(vo);
+    public Result detail(Long projectId, String processId) {
+        // 椤圭洰淇℃伅
+        ProjectInfo projectInfo = new LambdaQueryChainWrapper<>(projectInfoMapper)
+                .select(ProjectInfo::getId, ProjectInfo::getProjectName, ProjectInfo::getProjectCode)
+                .eq(ProjectInfo::getId, projectId)
+                .one();
+
+        if (Objects.isNull(projectInfo)) {
+            return Result.error("璇ラ」鐩笉瀛樺湪");
+        }
+
+        ProjectProcess projectProcess = new LambdaQueryChainWrapper<>(baseMapper)
+                .eq(ProjectProcess::getProjectId, projectId)
+                .eq(ProjectProcess::getFlowableProcessId, processId)
+                .one();
+        if (Objects.isNull(projectProcess)) {
+            return Result.error("璇ラ」鐩湭璁剧疆娴佺▼");
+        }
+
+        ProjectProcessDetailVO detail = new ProjectProcessDetailVO();
+        detail.setProjectId(projectId);
+        detail.setProjectName(projectInfo.getProjectName());
+        detail.setProjectCode(projectInfo.getProjectCode());
+
+        ProjectProcessDetailVO.TaskStatistics taskStatistics = new ProjectProcessDetailVO.TaskStatistics();
+        // 鐘舵�佺粺璁�
+        taskStatistics.setTotalTaskNum(this.getTotalTaskNum(processId));
+        taskStatistics.setTodoTaskNum(this.getTodoTaskNum(projectProcess.getProcessInstanceId()));
+//        taskStatistics.setCurrentTask(this.getCurrentNodeTaskList(projectProcess.getProcessInstanceId()));
+        taskStatistics.setRemainingTaskNum(this.getNotFinishedTaskNum(projectProcess.getProcessInstanceId()));
+        detail.setStatistics(taskStatistics);
+
+        Result result = Result.ok();
+
+        // 浠e姙浠诲姟
+        this.getTodoTaskList(projectProcess.getProcessInstanceId(),"", 1, 5, result);
+        return result.data(detail);
     }
 
 
@@ -76,4 +145,172 @@
         }
         return Result.ok("娴佺▼鍙樻洿鎴愬姛");
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result startProcess(String projectId, String processId) {
+        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processId)
+                .latestVersion().singleResult();
+        if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
+            return Result.error("璇ユ祦绋嬪凡琚寕璧�,璇峰厛婵�娲绘祦绋�");
+        }
+        Map<String, Object> variables = new HashMap<>(2);
+        // 璁剧疆娴佺▼鍙戣捣浜篒d鍒版祦绋嬩腑
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
+        variables.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUserId());
+        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processId, projectId, variables);
+//        // 娴佺▼鍙戣捣鏃� 璺宠繃鍙戣捣浜鸿妭鐐�
+//        // 缁欑涓�姝ョ敵璇蜂汉鑺傜偣璁剧疆浠诲姟鎵ц浜哄拰鎰忚
+//        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
+//        if (Objects.nonNull(task)) {
+//            taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), sysUser.getNickName() + "鍙戣捣娴佺▼鐢宠");
+//            taskService.complete(task.getId(), variables);
+//        }
+        // 椤圭洰娴佺▼鍏宠仈娴佺▼瀹炰緥id
+        new LambdaUpdateChainWrapper<>(baseMapper)
+                .eq(ProjectProcess::getProjectId, projectId)
+                .eq(ProjectProcess::getFlowableProcessId, processId)
+                .set(ProjectProcess::getProcessInstanceId, processInstance.getProcessInstanceId())
+                .update();
+        return Result.ok("娴佺▼鍚姩鎴愬姛");
+    }
+
+
+    private void getTodoTaskList(String processInstanceId, String name, Integer pageNum, Integer pageSize, Result result) {
+        TaskQuery taskQuery = taskService.createTaskQuery()
+                .active()
+                .processInstanceId(processInstanceId)
+                .includeProcessVariables()
+                .orderByTaskCreateTime().desc();
+
+//        TODO 浼犲叆鍚嶇О鏌ヨ涓嶅埌鏁版嵁?
+        if (StringUtils.isNotBlank(name)) {
+            taskQuery.processDefinitionNameLike(name);
+        }
+        result.total(taskQuery.count());
+        List<Task> taskList = taskQuery.listPage(pageSize * (pageNum - 1), pageSize);
+        List<FlowTaskDto> flowList = new ArrayList<>();
+        for (Task task : taskList) {
+            FlowTaskDto flowTask = new FlowTaskDto();
+            // 褰撳墠娴佺▼淇℃伅
+            flowTask.setTaskId(task.getId());
+            flowTask.setTaskDefKey(task.getTaskDefinitionKey());
+            flowTask.setCreateTime(task.getCreateTime());
+            flowTask.setProcDefId(task.getProcessDefinitionId());
+            flowTask.setExecutionId(task.getExecutionId());
+            flowTask.setTaskName(task.getName());
+            // 娴佺▼瀹氫箟淇℃伅
+            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
+                    .processDefinitionId(task.getProcessDefinitionId())
+                    .singleResult();
+            flowTask.setDeployId(pd.getDeploymentId());
+            flowTask.setProcDefName(pd.getName());
+            flowTask.setProcDefVersion(pd.getVersion());
+            flowTask.setProcInsId(task.getProcessInstanceId());
+
+            // 娴佺▼鍙戣捣浜轰俊鎭�
+            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
+                    .processInstanceId(task.getProcessInstanceId())
+                    .singleResult();
+            SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
+            flowTask.setStartUserId(startUser.getUserId().toString());
+            flowTask.setStartUserName(startUser.getNickName());
+            flowTask.setStartDeptName(Objects.nonNull(startUser.getDept()) ? startUser.getDept().getDeptName() : "");
+            // 娴佺▼澶勭悊浜轰俊鎭�
+            List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(task.getId());
+            for (IdentityLink identityLink : identityLinksForTask) {
+                // 缁戝畾鐨勬槸鐢ㄦ埛锛屾煡鍑虹敤鎴峰鍚嶃�侀儴闂�
+                if (StringUtils.isNotBlank(identityLink.getUserId())) {
+                    SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
+                    if (Objects.nonNull(sysUser)) {
+                        flowTask.setAssigneeId(sysUser.getUserId());
+                        if (Objects.nonNull(sysUser.getDept())) {
+                            flowTask.setAssigneeDeptName(sysUser.getDept().getDeptName());
+                        }
+                        flowTask.setAssigneeName(sysUser.getNickName());
+                    }
+                // 缁戝畾鐨勬槸瑙掕壊锛屾煡鍑鸿鑹插悕绉�
+                } else if (StringUtils.isNotBlank(identityLink.getGroupId())) {
+                    SysRole role = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
+                    if (Objects.nonNull(role)) {
+                        flowTask.setAssigneeId(Long.parseLong(identityLink.getGroupId()));
+                        flowTask.setAssigneeDeptName("鐢辨嫢鏈夎鑹诧細銆�" + role.getRoleName() + "銆戠殑浜哄鐞�");
+                        flowTask.setAssigneeName("鏆傛湭澶勭悊");
+                    }
+                }
+            }
+            flowList.add(flowTask);
+        }
+        result.put("taskList", flowList);
+    }
+
+    /**
+     * 鑾峰彇娴佺▼鑺傜偣鏁帮紙鎬讳换鍔℃暟锛屼笉鍖呭惈寮�濮嬨�佺粨鏉熺瓑鐗规畩鐨勶紝鍙粺璁serTask绫诲瀷鐨勶級
+     *
+     * @param processDefinitionId  娴佺▼瀹氫箟id
+     * @return
+     */
+    private Long getTotalTaskNum(String processDefinitionId) {
+        // 鑾峰彇娴佺▼瀹氫箟
+        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
+                .processDefinitionId(processDefinitionId)
+                .singleResult();
+
+        if (processDefinition == null) {
+            throw new IllegalArgumentException("娴佺▼瀹氫箟ID鏃犳晥: " + processDefinitionId);
+        }
+
+        // 鑾峰彇BPMN妯″瀷
+        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
+        if (bpmnModel == null) {
+            throw new IllegalStateException("鏃犳硶鑾峰彇BPMN妯″瀷: " + processDefinitionId);
+        }
+
+        // 鑾峰彇娴佺▼瀵硅薄
+        Process process = bpmnModel.getProcessById(processDefinition.getKey());
+        if (process == null) {
+            throw new IllegalStateException("鏃犳硶鑾峰彇娴佺▼瀵硅薄: " + processDefinition.getKey());
+        }
+
+        // 璁$畻浠诲姟鑺傜偣鏁伴噺
+        Long taskNodeCount = 0L;
+        List<FlowElement> flowElements = process.getFlowElements().stream().toList();
+        for (FlowElement flowElement : flowElements) {
+            if (flowElement instanceof org.flowable.bpmn.model.UserTask) {
+                taskNodeCount++;
+            }
+        }
+        return taskNodeCount;
+    }
+
+    /**
+     * 鑾峰彇娴佺▼鍓╀綑鏈畬鎴愮殑浠诲姟鏁�
+     *
+     * @param processInstanceId
+     * @return
+     */
+    private Long getNotFinishedTaskNum(String processInstanceId) {
+        return historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).processUnfinished().count();
+    }
+
+    /**
+     * 鑾峰彇寰呭姙浠诲姟鏁�
+     *
+     * @param processInstanceId
+     * @return
+     */
+    private Long getTodoTaskNum(String processInstanceId) {
+        return taskService.createTaskQuery().active().processInstanceId(processInstanceId).count();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐜妭鐨勬墍鏈変换鍔℃暟
+     *
+     * @param processInstanceId
+     * @return
+     */
+    private List<Task> getCurrentNodeTaskList(String processInstanceId) {
+       return taskService.createTaskQuery().processDefinitionId(processInstanceId).list();
+    }
 }
diff --git a/business/src/main/resources/mapper/ProjectProcessMapper.xml b/business/src/main/resources/mapper/ProjectProcessMapper.xml
index 2e19f42..3d69fe9 100644
--- a/business/src/main/resources/mapper/ProjectProcessMapper.xml
+++ b/business/src/main/resources/mapper/ProjectProcessMapper.xml
@@ -18,7 +18,6 @@
         <result column="area_code" property="areaCode" />
 <!--        <result column="management_centralization" property="managementCentralization" />-->
         <result column="project_approval_type" property="projectApprovalType" />
-        <result column="investment_catalogue" property="investmentCatalogue" />
         <result column="importance_type" property="importanceType" />
         <result column="year" property="year" />
         <result column="year_invest_amount" property="yearInvestAmount" />
diff --git a/flowable/src/main/java/com/ycl/common/enums/FlowComment.java b/flowable/src/main/java/com/ycl/common/enums/FlowComment.java
index e066c76..f845a7b 100644
--- a/flowable/src/main/java/com/ycl/common/enums/FlowComment.java
+++ b/flowable/src/main/java/com/ycl/common/enums/FlowComment.java
@@ -11,7 +11,8 @@
     /**
      * 璇存槑
      */
-    NORMAL("1", "姝e父鎰忚"),
+    SUBMIT("submit", "/鎻愪氦琛ㄥ崟/鎻愪氦瀹℃牳锛屾�讳箣浠h〃涓婃姤鐨勬搷浣�"),
+    NORMAL("1", "姝e父鎰忚锛屽鏍搁�氳繃鐨勬剰鎬�"),
     REBACK("2", "閫�鍥炴剰瑙�"),
     REJECT("3", "椹冲洖鎰忚"),
     DELEGATE("4", "濮旀淳鎰忚"),
diff --git a/flowable/src/main/java/com/ycl/controller/FlowTaskController.java b/flowable/src/main/java/com/ycl/controller/FlowTaskController.java
index ef3110d..70a98a4 100644
--- a/flowable/src/main/java/com/ycl/controller/FlowTaskController.java
+++ b/flowable/src/main/java/com/ycl/controller/FlowTaskController.java
@@ -22,6 +22,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Map;
 
 /**
  * <p>宸ヤ綔娴佷换鍔$鐞�<p>
@@ -84,7 +85,7 @@
     }
 
 
-    @ApiOperation(value = "娴佺▼鍒濆鍖栬〃鍗�", response = FlowTaskDto.class)
+    @ApiOperation(value = "鑾峰彇娴佺▼鍏宠仈鐨勮〃鍗�", response = FlowTaskDto.class)
     @GetMapping(value = "/flowFormData")
     public AjaxResult flowFormData(String deployId) {
         return flowTaskService.flowFormData(deployId);
@@ -96,7 +97,16 @@
         return flowTaskService.processVariables(taskId);
     }
 
-    @ApiOperation(value = "瀹℃壒浠诲姟")
+
+    @ApiOperation(value = "瀹屾垚鎻愪氦琛ㄥ崟浠诲姟/鏅�氭彁浜�")
+    @Log(title = "瀹屾垚鎻愪氦琛ㄥ崟浠诲姟/鏅�氭彁浜�", businessType = BusinessType.INSERT)
+    @PostMapping("/complete/form/{taskId}")
+    public AjaxResult completeSubmitForm(@ApiParam(value = "娴佺▼瀹氫箟id") @PathVariable(value = "taskId") String taskId,
+                            @ApiParam(value = "鍙橀噺闆嗗悎,json瀵硅薄") @RequestBody Map<String, Object> variables) {
+        return flowTaskService.completeSubmitForm(taskId, variables);
+    }
+
+    @ApiOperation(value = "瀹屾垚瀹℃壒浠诲姟")
     @Log(title = "瀹℃壒浠诲姟", businessType = BusinessType.UPDATE)
     @PostMapping(value = "/complete")
     public AjaxResult complete(@RequestBody FlowTaskVo flowTaskVo) {
diff --git a/flowable/src/main/java/com/ycl/service/IFlowTaskService.java b/flowable/src/main/java/com/ycl/service/IFlowTaskService.java
index 2c088c2..93cd0cc 100644
--- a/flowable/src/main/java/com/ycl/service/IFlowTaskService.java
+++ b/flowable/src/main/java/com/ycl/service/IFlowTaskService.java
@@ -5,6 +5,7 @@
 import com.ycl.domain.vo.FlowTaskVo;
 
 import java.io.InputStream;
+import java.util.Map;
 
 /**
  * @author Tony
@@ -213,4 +214,13 @@
      * @return
      */
     AjaxResult flowTaskInfo(String procInsId, String elementId);
+
+    /**
+     * 瀹屾垚鎻愪氦琛ㄥ崟浠诲姟
+     *
+     * @param taskId  浠诲姟id
+     * @param variables  琛ㄥ崟鏁版嵁
+     * @return
+     */
+    AjaxResult completeSubmitForm(String taskId, Map<String, Object> variables);
 }
diff --git a/flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java b/flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java
index 4bcfac6..bae5779 100644
--- a/flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java
+++ b/flowable/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java
@@ -82,7 +82,7 @@
     private final ISysFormService sysFormService;
 
     /**
-     * 瀹屾垚浠诲姟
+     * 瀹屾垚瀹℃牳浠诲姟
      *
      * @param taskVo 璇锋眰瀹炰綋鍙傛暟
      */
@@ -103,6 +103,25 @@
             taskService.complete(taskVo.getTaskId(), taskVo.getVariables());
         }
         return AjaxResult.success();
+    }
+
+    /**
+     * 瀹屾垚琛ㄥ崟鎻愪氦浠诲姟/鏅�氫换鍔�
+     *
+     * @param taskId  浠诲姟id
+     * @param variables  琛ㄥ崟鏁版嵁
+     * @return
+     */
+    @Override
+    public AjaxResult completeSubmitForm(String taskId, Map<String, Object> variables) {
+        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
+        if (Objects.isNull(task)) {
+            return AjaxResult.error("浠诲姟涓嶅瓨鍦�");
+        }
+//        variables.put(taskId + "formJson", variables.get("formJson"));
+        taskService.addComment(taskId, task.getProcessInstanceId(), FlowComment.SUBMIT.getType(), "瀹屾垚鎻愪氦");
+        taskService.complete(taskId, variables);
+        return AjaxResult.success("鎻愪氦鎴愬姛");
     }
 
     /**
@@ -1114,7 +1133,13 @@
         } else {
             parameters = taskService.getVariables(taskId);
         }
+
         JSONObject oldVariables = JSONObject.parseObject(JSON.toJSONString(parameters.get("formJson")));
+        if (Objects.isNull(oldVariables)) {
+            // 濡傛灉鏄┖鐨勶紝鐩存帴浣跨敤涓昏〃鍗�
+            String deploymentId = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getDeploymentId();
+            return this.flowFormData(deploymentId);
+        }
         List<JSONObject> oldFields = JSON.parseObject(JSON.toJSONString(oldVariables.get("widgetList")), new TypeReference<List<JSONObject>>() {
         });
         // 璁剧疆宸插~鍐欑殑琛ㄥ崟涓虹鐢ㄧ姸鎬�
@@ -1215,6 +1240,7 @@
         return AjaxResult.success(flowTask);
     }
 
+
     /**
      * 灏哋bject绫诲瀷鐨勬暟鎹浆鍖栨垚Map<String,Object>
      *
diff --git a/start/src/main/resources/application.yml b/start/src/main/resources/application.yml
index f70d518..161c6cd 100644
--- a/start/src/main/resources/application.yml
+++ b/start/src/main/resources/application.yml
@@ -41,6 +41,8 @@
   level:
     com.ruoyi: debug
     org.springframework: warn
+    org.flowable.engine.impl.persistence.entity.*: debug
+    org.flowable.task.service.impl.persistence.entity.*: debug
 
 # 鐢ㄦ埛閰嶇疆
 user:
@@ -78,7 +80,7 @@
   # 浠ょ墝瀵嗛挜
   secret: gfabcdefghijklmnopqrstuvwxyz12
   # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
-  expireTime: 1200
+  expireTime: 10000
 
 # PageHelper鍒嗛〉鎻掍欢
 pagehelper:
@@ -107,13 +109,13 @@
 # 宸ヤ綔娴� Flowable 閰嶇疆锛宖lowable瀹屾暣鐨勯厤缃紝鍙傝锛欯see https://www.flowable.com/open-source/docs/bpmn/ch05a-Spring-Boot/#flowable-application-properties
 flowable:
   database-schema-update: true  # 鑷姩鏇存柊flowable琛ㄧ粨鏋勶紝绗竴娆¤繛鎺ユ暟鎹簱鏃跺彲浠ヨ缃负true
-  # 鍏抽棴鍚勪釜妯″潡鐢熸垚琛紝鐩墠鍙娇鐢ㄥ伐浣滄祦鍩虹琛�
+#  # 鍏抽棴鍚勪釜妯″潡鐢熸垚琛紝鐩墠鍙娇鐢ㄥ伐浣滄祦鍩虹琛�
   idm:  # idm鏄痜lowable鐨勮韩浠界鐞嗘ā鍧楋細鍗崇敤鎴枫�佽璇併�佹潈闄愮瓑
     enabled: false
-  cmmn: # cmmn鏄痜lowable鐨勬渚嬬鐞嗘ā鍧楋紝浣撶幇鍦╢lowable-ui涓殑锛氭祦绋嬪缓妯″櫒銆乁I锛孈see https://www.flowable.com/open-source/docs/cmmn/ch06-cmmn
-    enabled: true
-  dmn: # dmn鏄痜lowable鐨勫喅绛栨ā鍨嬶紝浣撶幇鍦╢lowable-ui涓殑鍐崇瓥琛�  @see https://www.flowable.com/open-source/docs/dmn/ch06-DMN-Introduction
-    enabled: false
-  app: # app鐨勫姛鑳芥槸涓篺lowable鍦╯pring涓珮鏁堣繍琛岃�屾彁渚涗簡寰堝bean锛屼笌flowable鏈韩鐨勫唴瀹规棤鍏�
-    enabled: true
-  check-process-definitions: true
+#  cmmn: # cmmn鏄痜lowable鐨勬渚嬬鐞嗘ā鍧楋紝浣撶幇鍦╢lowable-ui涓殑锛氭祦绋嬪缓妯″櫒銆乁I锛孈see https://www.flowable.com/open-source/docs/cmmn/ch06-cmmn
+#    enabled: true
+#  dmn: # dmn鏄痜lowable鐨勫喅绛栨ā鍨嬶紝浣撶幇鍦╢lowable-ui涓殑鍐崇瓥琛�  @see https://www.flowable.com/open-source/docs/dmn/ch06-DMN-Introduction
+#    enabled: false
+#  app: # app鐨勫姛鑳芥槸涓篺lowable鍦╯pring涓珮鏁堣繍琛岃�屾彁渚涗簡寰堝bean锛屼笌flowable鏈韩鐨勫唴瀹规棤鍏�
+#    enabled: true
+#  check-process-definitions: true

--
Gitblit v1.8.0