Quellcode durchsuchen

1. 修复已办任务的 API 接口的 NPE
2. 实现已办任务的 UI 界面

YunaiV vor 3 Jahren
Ursprung
Commit
a5b8b9b67e

+ 4 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmTaskConvert.java

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task.TaskStep
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import org.activiti.engine.history.HistoricActivityInstance;
+import org.activiti.engine.history.HistoricProcessInstance;
 import org.activiti.engine.history.HistoricTaskInstance;
 import org.activiti.engine.impl.persistence.entity.SuspensionState;
 import org.activiti.engine.runtime.ProcessInstance;
@@ -64,10 +65,10 @@ public interface BpmTaskConvert {
     }
 
     default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks,
-                                                         Map<String, ProcessInstance> processInstanceMap,
+                                                         Map<String, HistoricProcessInstance> historicProcessInstanceMap,
                                                          Map<Long, SysUserDO> userMap) {
         return CollectionUtils.convertList(tasks, task -> {
-            ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
+            HistoricProcessInstance processInstance = historicProcessInstanceMap.get(task.getProcessInstanceId());
             return convert(task, processInstance, userMap.get(Long.valueOf(processInstance.getStartUserId())));
         });
     }
@@ -85,6 +86,6 @@ public interface BpmTaskConvert {
             @Mapping(source = "processInstance.processDefinitionId", target = "processInstance.processDefinitionId"),
             @Mapping(source = "user.nickname", target = "processInstance.startUserNickname")
     })
-    BpmTaskDonePageItemRespVO convert(HistoricTaskInstance task, ProcessInstance processInstance, SysUserDO user);
+    BpmTaskDonePageItemRespVO convert(HistoricTaskInstance task, HistoricProcessInstance processInstance, SysUserDO user);
 
 }

+ 27 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmProcessInstanceService.java

@@ -8,6 +8,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceDel
 import cn.iocoder.yudao.adminserver.modules.bpm.enums.task.BpmProcessInstanceResultEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import org.activiti.engine.history.HistoricProcessInstance;
 import org.activiti.engine.runtime.ProcessInstance;
 
 import javax.validation.Valid;
@@ -91,4 +92,30 @@ public interface BpmProcessInstanceService {
         return CollectionUtils.convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
     }
 
+    /**
+     * 获得历史的流程实例
+     *
+     * @param id 流程实例的编号
+     * @return 历史的流程实例
+     */
+    HistoricProcessInstance getHistoricProcessInstance(String id);
+
+    /**
+     * 获得历史的流程实例列表
+     *
+     * @param ids 流程实例的编号集合
+     * @return 历史的流程实例列表
+     */
+    List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids);
+
+    /**
+     * 获得历史的流程实例 Map
+     *
+     * @param ids 流程实例的编号集合
+     * @return 历史的流程实例列表 Map
+     */
+    default Map<String, HistoricProcessInstance> getHistoricProcessInstanceMap(Set<String> ids) {
+        return CollectionUtils.convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);
+    }
+
 }

+ 7 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmProcessInstanceServiceImpl.java

@@ -186,8 +186,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
      * @param id 流程实例的编号
      * @return 历史的流程实例
      */
-    private HistoricProcessInstance getHistoricProcessInstance(String id) {
+    @Override
+    public HistoricProcessInstance getHistoricProcessInstance(String id) {
         return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
     }
 
+    @Override
+    public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) {
+        return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list();
+    }
+
 }

+ 3 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java

@@ -144,13 +144,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
         }
 
         // 获得 ProcessInstance Map
-        Map<String, ProcessInstance> processInstanceMap = processInstanceService.getProcessInstanceMap(
+        Map<String, HistoricProcessInstance> historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap(
                 convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
         // 获得 User Map
         Map<Long, SysUserDO> userMap = userService.getUserMap(
-                convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
+                convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
         // 拼接结果
-        return new PageResult<>(BpmTaskConvert.INSTANCE.convertList2(tasks, processInstanceMap, userMap),
+        return new PageResult<>(BpmTaskConvert.INSTANCE.convertList2(tasks, historicProcessInstanceMap, userMap),
                 taskQuery.count());
     }
 

+ 8 - 0
yudao-admin-ui/src/api/bpm/task.js

@@ -8,6 +8,14 @@ export function getTodoTaskPage(query) {
   })
 }
 
+export function getDoneTaskPage(query) {
+  return request({
+    url: '/bpm/task/done-page',
+    method: 'get',
+    params: query
+  })
+}
+
 export function completeTask(data) {
   return request({
     url: '/bpm/task/complete',

+ 105 - 0
yudao-admin-ui/src/views/bpm/task/done.vue

@@ -0,0 +1,105 @@
+<template>
+  <div class="app-container">
+
+    <!-- 搜索工作栏 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="流程名" prop="name">
+        <el-input v-model="queryParams.name" placeholder="请输入流程名" clearable size="small" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item label="创建时间">
+        <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+                        type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 列表 -->
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="任务编号" align="center" prop="id" width="300" />
+      <el-table-column label="任务名称" align="center" prop="name" />
+      <el-table-column label="所属流程" align="center" prop="processInstance.name" />
+      <el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="审批时间" align="center" prop="endTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.endTime) }}</span>
+        </template>
+      </el-table-column>
+      <!-- TODO 耗时 -->
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <!-- TODO 权限、颜色 -->
+          <el-button size="mini" type="text" icon="el-icon-edit">详情</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页组件 -->
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
+
+  </div>
+</template>
+
+<script>
+import {getDoneTaskPage} from '@/api/bpm/task'
+
+export default {
+  name: "Done",
+  components: {
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 待办任务列表
+      list: [],
+      // 查询参数
+      dateRangeCreateTime: [],
+      queryParams: {
+        pageNo: 1,
+        pageSize: 10,
+        name: null,
+      },
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询列表 */
+    getList() {
+      this.loading = true;
+      // 处理查询参数
+      let params = {...this.queryParams};
+      this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
+      getDoneTaskPage(params).then(response => {
+        this.list = response.data.list;
+        this.total = response.data.total;
+        this.loading = false;
+      });
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNo = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.dateRangeCreateTime = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+  }
+};
+</script>

+ 1 - 23
yudao-admin-ui/src/views/bpm/task/todo.vue

@@ -52,7 +52,7 @@
 </template>
 
 <script>
-import {approveTask, completeTask, getTodoTaskPage, rejectTask} from '@/api/bpm/task'
+import {approveTask, getTodoTaskPage, rejectTask} from '@/api/bpm/task'
 
 export default {
   name: "Todo",
@@ -93,27 +93,6 @@ export default {
         this.loading = false;
       });
     },
-    /** 取消按钮 */
-    cancel() {
-      this.open = false;
-      this.reset();
-    },
-    /** 表单重置 */
-    reset() {
-      this.form = {
-        id: undefined,
-        processInstanceId: undefined,
-        status: undefined,
-        userId: undefined,
-        startTime: undefined,
-        endTime: undefined,
-        leaveType: undefined,
-        reason: undefined,
-        applyTime: undefined,
-      };
-      this.resetForm("form");
-    },
-
     /** 搜索按钮操作 */
     handleQuery() {
       this.queryParams.pageNo = 1;
@@ -122,7 +101,6 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.dateRangeCreateTime = [];
-      this.dateRangeApplyTime = [];
       this.resetForm("queryForm");
       this.handleQuery();
     },

+ 5 - 0
yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java

@@ -2,7 +2,10 @@ package cn.iocoder.yudao.framework.activiti.core.util;
 
 import cn.hutool.core.util.ReflectUtil;
 import com.alibaba.ttl.TransmittableThreadLocal;
+import org.activiti.engine.history.HistoricProcessInstance;
 import org.activiti.engine.impl.identity.Authentication;
+import org.activiti.engine.impl.persistence.entity.HistoricProcessInstanceEntityImpl;
+import org.activiti.engine.impl.persistence.entity.HistoricScopeInstanceEntityImpl;
 
 /**
  * Activiti 工具类
@@ -15,6 +18,8 @@ public class ActivitiUtils {
         setAuthenticationThreadLocal();
     }
 
+    // ========== Authentication 相关 ==========
+
     /**
      * 反射修改 Authentication 的 authenticatedUserIdThreadLocal 静态变量,使用 TTL 线程变量
      * 目的:保证 @Async 等异步执行时,变量丢失的问题