WorkflowResponseBodyAdvice.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. package com.xjrsoft.common.advice;
  2. import cn.dev33.satoken.stp.StpUtil;
  3. import cn.hutool.core.bean.BeanUtil;
  4. import cn.hutool.core.convert.Convert;
  5. import cn.hutool.core.util.*;
  6. import cn.hutool.db.Entity;
  7. import cn.hutool.extra.servlet.ServletUtil;
  8. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  9. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  10. import com.baomidou.mybatisplus.core.toolkit.StringPool;
  11. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  12. import com.xjrsoft.common.enums.WorkflowIsRecycleType;
  13. import com.xjrsoft.common.enums.YesOrNoEnum;
  14. import com.xjrsoft.common.exception.MyException;
  15. import com.xjrsoft.common.model.result.R;
  16. import com.xjrsoft.common.page.PageOutput;
  17. import com.xjrsoft.module.workflow.constant.WorkflowConstant;
  18. import com.xjrsoft.module.workflow.entity.WorkflowDraft;
  19. import com.xjrsoft.module.workflow.entity.WorkflowFormRelation;
  20. import com.xjrsoft.module.workflow.entity.WorkflowSchema;
  21. import com.xjrsoft.module.workflow.model.WorkflowListResult;
  22. import com.xjrsoft.module.workflow.service.IWorkflowDraftService;
  23. import com.xjrsoft.module.workflow.service.IWorkflowFormRelationService;
  24. import com.xjrsoft.module.workflow.service.IWorkflowSchemaService;
  25. import javassist.*;
  26. import lombok.AllArgsConstructor;
  27. import lombok.NonNull;
  28. import lombok.extern.slf4j.Slf4j;
  29. import org.camunda.bpm.engine.HistoryService;
  30. import org.camunda.bpm.engine.TaskService;
  31. import org.camunda.bpm.engine.history.HistoricProcessInstance;
  32. import org.camunda.bpm.engine.task.Task;
  33. import org.springframework.core.MethodParameter;
  34. import org.springframework.http.MediaType;
  35. import org.springframework.http.server.ServerHttpRequest;
  36. import org.springframework.http.server.ServerHttpResponse;
  37. import org.springframework.http.server.ServletServerHttpRequest;
  38. import org.springframework.web.bind.annotation.RestControllerAdvice;
  39. import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
  40. import java.lang.reflect.Constructor;
  41. import java.lang.reflect.InvocationTargetException;
  42. import java.util.*;
  43. import java.util.stream.Collectors;
  44. /**
  45. * 工作流 模板 绑定菜单 返回值新增工作流的相关属性
  46. *
  47. * @Author: tzx
  48. * @Date: 2023/3/27 14:24
  49. */
  50. @Slf4j
  51. @RestControllerAdvice
  52. @AllArgsConstructor
  53. public class WorkflowResponseBodyAdvice implements ResponseBodyAdvice<Object> {
  54. private IWorkflowFormRelationService formRelationService;
  55. private HistoryService historyService;
  56. private IWorkflowSchemaService workflowSchemaService;
  57. private final IWorkflowDraftService workflowDraftService;
  58. private TaskService taskService;
  59. private static final Map<String, Constructor<?>> cacheClass = new HashMap<>();
  60. private static final String FORM_ID_KEY = "FormId";
  61. private static final String KEY_VALUE_KEY = "PK";
  62. private static final String FIELD_STRING = "private Object workflowData;";
  63. private static final String GET_MOTHOD_STRING = "public Object getWorkflowData(){ return this.workflowData; }";
  64. private static final String RESULT_KEY = "workflowData";
  65. @Override
  66. public boolean supports(@NonNull MethodParameter returnType, @NonNull Class converterType) {
  67. return true;
  68. }
  69. @Override
  70. public Object beforeBodyWrite(Object body, @NonNull MethodParameter returnType, @NonNull MediaType selectedContentType, @NonNull Class selectedConverterType, @NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response) {
  71. if (!(body instanceof R)) {
  72. return body;
  73. }
  74. if (((R) body).getData() == null) {
  75. return body;
  76. }
  77. //先从header里面获取formId 如果能获取到 就证明是自定义表单
  78. String headerFormId = ServletUtil.getHeader(((ServletServerHttpRequest) request).getServletRequest(), FORM_ID_KEY, CharsetUtil.UTF_8);
  79. String headerKey = ServletUtil.getHeader(((ServletServerHttpRequest) request).getServletRequest(), KEY_VALUE_KEY, CharsetUtil.UTF_8);
  80. //如果是自定义表单 需要获取 工作流数据
  81. if(StrUtil.isNotBlank(headerFormId)){
  82. if (ClassUtil.equals(((R) body).getData().getClass(), PageOutput.class.getName(), true)){
  83. return formTemplateGetWorkflowDataHandler(body, headerFormId, headerKey);
  84. }
  85. }
  86. String formId = ((ServletServerHttpRequest) request).getServletRequest().getParameter(FORM_ID_KEY);
  87. if (StrUtil.isBlank(formId)) {
  88. return body;
  89. }
  90. String key = ((ServletServerHttpRequest) request).getServletRequest().getParameter(KEY_VALUE_KEY);
  91. if (StrUtil.isBlank(key)) {
  92. return body;
  93. }
  94. //如果是代码生成器表单 需要获取 工作流数据
  95. return codeGetWorkflowDataHandler(body, formId, key);
  96. }
  97. private Object formTemplateGetWorkflowDataHandler(Object body, String headerFormId, String headerKey) {
  98. List<Object> keyValueFormList = new ArrayList<>();
  99. List<?> listData = null;
  100. if (ClassUtil.equals(((R) body).getData().getClass(), PageOutput.class.getName(), true)){
  101. Object result = Convert.convert(R.class, body).getData();
  102. PageOutput<?> pageOutput = Convert.convert(PageOutput.class, result);
  103. listData = pageOutput.getList();
  104. if (listData == null || listData.size() == 0) {
  105. return body;
  106. }
  107. }
  108. else if (ClassUtil.equals(((R) body).getData().getClass(), ArrayList.class.getName(), true)){
  109. Object result = Convert.convert(R.class, body).getData();
  110. listData = Convert.convert(List.class, result);
  111. if (listData == null || listData.size() == 0) {
  112. return body;
  113. }
  114. }
  115. else {
  116. return body;
  117. }
  118. for (Object data : listData) {
  119. Entity rowValue = Convert.convert(Entity.class, data);
  120. Object keyValue = rowValue.get(headerKey);
  121. keyValueFormList.add(keyValue);
  122. }
  123. WorkflowSchema schema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getFormId, Long.parseLong(headerFormId)).select(WorkflowSchema::getId));
  124. //获取到所有关联的 流程id
  125. List<WorkflowFormRelation> relations = formRelationService.list(Wrappers.lambdaQuery(WorkflowFormRelation.class).eq(WorkflowFormRelation::getFormId, Long.parseLong(headerFormId)).in(WorkflowFormRelation::getFormKeyValue, keyValueFormList).select(WorkflowFormRelation::getProcessId, WorkflowFormRelation::getFormKeyValue));
  126. Set<String> processIds = relations.stream().map(WorkflowFormRelation::getProcessId).collect(Collectors.toSet());
  127. List<HistoricProcessInstance> processInstanceList;
  128. if (processIds.size() == 0) {
  129. processInstanceList = new ArrayList<>();
  130. } else {
  131. processInstanceList = historyService.createHistoricProcessInstanceQuery().processInstanceIds(processIds).list();
  132. }
  133. //找到当前所有流程的 所在执行的任务list
  134. String[] processIdArrays = relations.stream().map(WorkflowFormRelation::getProcessId).toArray(String[]::new);
  135. List<Task> taskList;
  136. if (processIdArrays.length > 0) {
  137. taskList = taskService.createTaskQuery()
  138. .active()
  139. .processInstanceIdIn(processIdArrays)
  140. .taskVariableValueEquals(WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode())
  141. .processVariableValueEquals(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode())
  142. .taskVariableValueLike(WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StringPool.PERCENT + StpUtil.getLoginIdAsString() + StringPool.PERCENT)
  143. .list();
  144. } else {
  145. taskList = new ArrayList<>();
  146. }
  147. for (Object data : listData) {
  148. Entity rowValue = Convert.convert(Entity.class, data);
  149. Object keyValue = rowValue.get(headerKey);
  150. Optional<WorkflowFormRelation> thisRelationOp = relations.stream().filter(x -> x.getFormKeyValue().equals(keyValue)).findFirst();
  151. WorkflowListResult workflowListResult = new WorkflowListResult();
  152. thisRelationOp.ifPresent(r -> {
  153. HistoricProcessInstance historicProcessInstance = processInstanceList.stream().filter(p -> p.getId().equals(r.getProcessId())).findFirst().orElse(null);
  154. if (ObjectUtil.isNotNull(historicProcessInstance)) {
  155. assert historicProcessInstance != null;
  156. workflowListResult.setStatus(historicProcessInstance.getState());
  157. workflowListResult.setProcessId(historicProcessInstance.getId());
  158. }
  159. //获取到当前数据 所关联的 的流程 正在执行的 任务
  160. List<Task> thisDataTask = taskList.stream().filter(x -> x.getProcessInstanceId().equals(r.getProcessId())).collect(Collectors.toList());
  161. if (thisDataTask.size() > 0) {
  162. workflowListResult.setTaskIds(thisDataTask.stream().map(Task::getId).collect(Collectors.toList()));
  163. }
  164. });
  165. if (ObjectUtil.isNotNull(schema)) {
  166. workflowListResult.setSchemaId(schema.getId());
  167. // 查询草稿信息
  168. LambdaQueryWrapper<WorkflowDraft> wrapper = Wrappers.<WorkflowDraft>query().lambda().select(WorkflowDraft::getId)
  169. .eq(WorkflowDraft::getCreateUserId, StpUtil.getLoginIdAsLong());
  170. List<String> taskIds = workflowListResult.getTaskIds();
  171. if (CollectionUtils.isNotEmpty(taskIds)) {
  172. wrapper.eq(WorkflowDraft::getTaskId, taskIds.get(0));
  173. } else {
  174. wrapper.eq(WorkflowDraft::getDataId, String.valueOf(keyValue))
  175. .eq(WorkflowDraft::getSchemaId, schema.getId());
  176. }
  177. WorkflowDraft draft = workflowDraftService.getOne(wrapper, false);
  178. if (draft != null) workflowListResult.setDraftId(draft.getId());
  179. } else {
  180. workflowListResult.setEnabled(Boolean.FALSE);
  181. }
  182. rowValue.set(RESULT_KEY, workflowListResult);
  183. }
  184. return body;
  185. }
  186. private Object codeGetWorkflowDataHandler(Object body,String formId, String key) {
  187. WorkflowSchema schema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getFormId, Long.parseLong(formId)).select(WorkflowSchema::getId));
  188. List<Object> keyValueList = new ArrayList<>();
  189. List<?> listData;
  190. //判断是否为分页返回值
  191. boolean isPage = ClassUtil.equals(((R) body).getData().getClass(), PageOutput.class.getName(), true);
  192. R r = Convert.convert(R.class, body);
  193. Object resultData = r.getData();
  194. if (isPage) {
  195. PageOutput<?> pageOutput = Convert.convert(PageOutput.class, resultData);
  196. listData = pageOutput.getList();
  197. if (listData == null || listData.size() == 0) {
  198. return body;
  199. }
  200. for (Object data : listData) {
  201. Object keyValue = ReflectUtil.getFieldValue(data, key);
  202. keyValueList.add(keyValue.toString());
  203. }
  204. }
  205. //判断是否为不分页列表返回值
  206. else if (ClassUtil.equals(((R) body).getData().getClass(), ArrayList.class.getName(), true)) {
  207. listData = Convert.convert(List.class, resultData);
  208. if (listData == null || listData.size() == 0) {
  209. return body;
  210. }
  211. for (Object data : listData) {
  212. Object keyValue = ReflectUtil.getFieldValue(data, key);
  213. keyValueList.add(keyValue.toString());
  214. }
  215. } else {
  216. return body;
  217. }
  218. //获取到所有关联的 流程id
  219. List<WorkflowFormRelation> relations = formRelationService.list(Wrappers.lambdaQuery(WorkflowFormRelation.class).eq(WorkflowFormRelation::getFormId, Long.parseLong(formId)).in(WorkflowFormRelation::getFormKeyValue, keyValueList).select(WorkflowFormRelation::getProcessId, WorkflowFormRelation::getFormKeyValue));
  220. // if (relations.size() == 0) {
  221. // return body;
  222. // }
  223. Set<String> processIds = relations.stream().map(WorkflowFormRelation::getProcessId).collect(Collectors.toSet());
  224. List<HistoricProcessInstance> processInstanceList;
  225. if (processIds.size() == 0) {
  226. processInstanceList = new ArrayList<>();
  227. } else {
  228. processInstanceList = historyService.createHistoricProcessInstanceQuery().processInstanceIds(processIds).list();
  229. }
  230. //找到当前所有流程的 所在执行的任务list
  231. String[] processIdArrays = relations.stream().map(WorkflowFormRelation::getProcessId).toArray(String[]::new);
  232. List<Task> taskList;
  233. if (processIdArrays.length > 0) {
  234. taskList = taskService.createTaskQuery()
  235. .active()
  236. .processInstanceIdIn(processIdArrays)
  237. .taskVariableValueEquals(WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode())
  238. .processVariableValueEquals(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode())
  239. .taskVariableValueLike(WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StringPool.PERCENT + StpUtil.getLoginIdAsString() + StringPool.PERCENT)
  240. .list();
  241. } else {
  242. taskList = new ArrayList<>();
  243. }
  244. ClassPool pool = new ClassPool(true);
  245. pool.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
  246. List<Object> result = new ArrayList<>();
  247. try {
  248. CtClass ctClass = pool.get(listData.get(0).getClass().getName());
  249. try {
  250. CtField workflowField = CtField.make(FIELD_STRING, ctClass);
  251. ctClass.addField(workflowField);
  252. CtMethod workflowMethod = CtMethod.make(GET_MOTHOD_STRING, ctClass);
  253. ctClass.addMethod(workflowMethod);
  254. } catch (CannotCompileException e) {
  255. e.printStackTrace();
  256. }
  257. Constructor<?> declaredConstructor;
  258. if (!cacheClass.containsKey(ctClass.getName())) {
  259. declaredConstructor = ctClass.toClass().getDeclaredConstructor();
  260. cacheClass.put(ctClass.getName(), declaredConstructor);
  261. } else {
  262. declaredConstructor = cacheClass.get(ctClass.getName());
  263. }
  264. for (Object data : listData) {
  265. Object keyValue = ReflectUtil.getFieldValue(data, key);
  266. //keyValue.toString是采购申请时使用的,因为采购表存的id是Long类型的
  267. Optional<WorkflowFormRelation> thisRelationOp = relations.stream().filter(x -> x.getFormKeyValue().equals(keyValue) || x.getFormKeyValue().equals(keyValue.toString())).findFirst();
  268. Object newObject = declaredConstructor.newInstance();
  269. result.add(newObject);
  270. BeanUtil.copyProperties(data, newObject);
  271. WorkflowListResult workflowListResult = new WorkflowListResult();
  272. thisRelationOp.ifPresent(relation -> {
  273. HistoricProcessInstance historicProcessInstance = processInstanceList.stream().filter(p -> p.getId().equals(relation.getProcessId())).findFirst().orElse(null);
  274. if (ObjectUtil.isNotNull(historicProcessInstance)) {
  275. assert historicProcessInstance != null;
  276. workflowListResult.setStatus(historicProcessInstance.getState());
  277. workflowListResult.setProcessId(historicProcessInstance.getId());
  278. }
  279. //获取到当前数据 所关联的 的流程 正在执行的 任务
  280. List<Task> thisDataTask = taskList.stream().filter(x -> x.getProcessInstanceId().equals(relation.getProcessId())).collect(Collectors.toList());
  281. if (thisDataTask.size() > 0) {
  282. workflowListResult.setTaskIds(thisDataTask.stream().map(Task::getId).collect(Collectors.toList()));
  283. }
  284. });
  285. if (ObjectUtil.isNotNull(schema)) {
  286. workflowListResult.setSchemaId(schema.getId());
  287. // 查询草稿信息
  288. LambdaQueryWrapper<WorkflowDraft> wrapper = Wrappers.<WorkflowDraft>query().lambda().select(WorkflowDraft::getId)
  289. .eq(WorkflowDraft::getCreateUserId, StpUtil.getLoginIdAsLong())
  290. .eq(WorkflowDraft::getDataId, String.valueOf(keyValue));
  291. List<String> taskIds = workflowListResult.getTaskIds();
  292. if (CollectionUtils.isNotEmpty(taskIds)) {
  293. wrapper.eq(WorkflowDraft::getTaskId, taskIds.get(0));
  294. } else {
  295. wrapper.eq(WorkflowDraft::getSchemaId, schema.getId());
  296. }
  297. WorkflowDraft draft = workflowDraftService.getOne(wrapper, false);
  298. if (draft != null) workflowListResult.setDraftId(draft.getId());
  299. } else {
  300. workflowListResult.setEnabled(Boolean.FALSE);
  301. }
  302. ReflectUtil.setFieldValue(newObject, RESULT_KEY, workflowListResult);
  303. }
  304. ctClass.detach();
  305. } catch (NotFoundException | CannotCompileException | NoSuchMethodException | InvocationTargetException |
  306. InstantiationException | IllegalAccessException e) {
  307. e.printStackTrace();
  308. throw new MyException("表单发起流程数据转换出错,请联系管理员!" );
  309. }
  310. if (isPage) {
  311. ((PageOutput) (r.getData())).setList(result);
  312. } else{
  313. r.put("data", result);
  314. }
  315. return body;
  316. }
  317. }