mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 18:49:06 +08:00 
			
		
		
		
	1. 修复已办任务的 API 接口的 NPE
2. 实现已办任务的 UI 界面
This commit is contained in:
		| @ -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); | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -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(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -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,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
									
								
								yudao-admin-ui/src/views/bpm/task/done.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								yudao-admin-ui/src/views/bpm/task/done.vue
									
									
									
									
									
										Normal file
									
								
							| @ -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> | ||||
| @ -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(); | ||||
|     }, | ||||
|  | ||||
| @ -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 等异步执行时,变量丢失的问题 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV