package com.xjrsoft.common.advice; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.*; import cn.hutool.db.Entity; import cn.hutool.extra.servlet.ServletUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.xjrsoft.common.enums.WorkflowIsRecycleType; import com.xjrsoft.common.enums.YesOrNoEnum; import com.xjrsoft.common.exception.MyException; import com.xjrsoft.common.model.result.R; import com.xjrsoft.common.page.PageOutput; import com.xjrsoft.module.workflow.constant.WorkflowConstant; import com.xjrsoft.module.workflow.entity.WorkflowDraft; import com.xjrsoft.module.workflow.entity.WorkflowFormRelation; import com.xjrsoft.module.workflow.entity.WorkflowSchema; import com.xjrsoft.module.workflow.model.WorkflowListResult; import com.xjrsoft.module.workflow.service.IWorkflowDraftService; import com.xjrsoft.module.workflow.service.IWorkflowFormRelationService; import com.xjrsoft.module.workflow.service.IWorkflowSchemaService; import javassist.*; import lombok.AllArgsConstructor; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.camunda.bpm.engine.HistoryService; import org.camunda.bpm.engine.TaskService; import org.camunda.bpm.engine.history.HistoricProcessInstance; import org.camunda.bpm.engine.task.Task; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.stream.Collectors; /** * 工作流 模板 绑定菜单 返回值新增工作流的相关属性 * * @Author: tzx * @Date: 2023/3/27 14:24 */ @Slf4j @RestControllerAdvice @AllArgsConstructor public class WorkflowResponseBodyAdvice implements ResponseBodyAdvice { private IWorkflowFormRelationService formRelationService; private HistoryService historyService; private IWorkflowSchemaService workflowSchemaService; private final IWorkflowDraftService workflowDraftService; private TaskService taskService; private static final Map> cacheClass = new HashMap<>(); private static final String FORM_ID_KEY = "FormId"; private static final String KEY_VALUE_KEY = "PK"; private static final String FIELD_STRING = "private Object workflowData;"; private static final String GET_MOTHOD_STRING = "public Object getWorkflowData(){ return this.workflowData; }"; private static final String RESULT_KEY = "workflowData"; @Override public boolean supports(@NonNull MethodParameter returnType, @NonNull Class converterType) { return true; } @Override public Object beforeBodyWrite(Object body, @NonNull MethodParameter returnType, @NonNull MediaType selectedContentType, @NonNull Class selectedConverterType, @NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response) { if (!(body instanceof R)) { return body; } if (((R) body).getData() == null) { return body; } //先从header里面获取formId 如果能获取到 就证明是自定义表单 String headerFormId = ServletUtil.getHeader(((ServletServerHttpRequest) request).getServletRequest(), FORM_ID_KEY, CharsetUtil.UTF_8); String headerKey = ServletUtil.getHeader(((ServletServerHttpRequest) request).getServletRequest(), KEY_VALUE_KEY, CharsetUtil.UTF_8); //如果是自定义表单 需要获取 工作流数据 if(StrUtil.isNotBlank(headerFormId)){ if (ClassUtil.equals(((R) body).getData().getClass(), PageOutput.class.getName(), true)){ return formTemplateGetWorkflowDataHandler(body, headerFormId, headerKey); } } String formId = ((ServletServerHttpRequest) request).getServletRequest().getParameter(FORM_ID_KEY); if (StrUtil.isBlank(formId)) { return body; } String key = ((ServletServerHttpRequest) request).getServletRequest().getParameter(KEY_VALUE_KEY); if (StrUtil.isBlank(key)) { return body; } //如果是代码生成器表单 需要获取 工作流数据 return codeGetWorkflowDataHandler(body, formId, key); } private Object formTemplateGetWorkflowDataHandler(Object body, String headerFormId, String headerKey) { List keyValueFormList = new ArrayList<>(); List listData = null; if (ClassUtil.equals(((R) body).getData().getClass(), PageOutput.class.getName(), true)){ Object result = Convert.convert(R.class, body).getData(); PageOutput pageOutput = Convert.convert(PageOutput.class, result); listData = pageOutput.getList(); if (listData == null || listData.size() == 0) { return body; } } else if (ClassUtil.equals(((R) body).getData().getClass(), ArrayList.class.getName(), true)){ Object result = Convert.convert(R.class, body).getData(); listData = Convert.convert(List.class, result); if (listData == null || listData.size() == 0) { return body; } } else { return body; } for (Object data : listData) { Entity rowValue = Convert.convert(Entity.class, data); Object keyValue = rowValue.get(headerKey); keyValueFormList.add(keyValue); } WorkflowSchema schema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getFormId, Long.parseLong(headerFormId)).select(WorkflowSchema::getId)); //获取到所有关联的 流程id List relations = formRelationService.list(Wrappers.lambdaQuery(WorkflowFormRelation.class).eq(WorkflowFormRelation::getFormId, Long.parseLong(headerFormId)).in(WorkflowFormRelation::getFormKeyValue, keyValueFormList).select(WorkflowFormRelation::getProcessId, WorkflowFormRelation::getFormKeyValue)); Set processIds = relations.stream().map(WorkflowFormRelation::getProcessId).collect(Collectors.toSet()); List processInstanceList; if (processIds.size() == 0) { processInstanceList = new ArrayList<>(); } else { processInstanceList = historyService.createHistoricProcessInstanceQuery().processInstanceIds(processIds).list(); } //找到当前所有流程的 所在执行的任务list String[] processIdArrays = relations.stream().map(WorkflowFormRelation::getProcessId).toArray(String[]::new); List taskList; if (processIdArrays.length > 0) { taskList = taskService.createTaskQuery() .active() .processInstanceIdIn(processIdArrays) .taskVariableValueEquals(WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode()) .processVariableValueEquals(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode()) .taskVariableValueLike(WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StringPool.PERCENT + StpUtil.getLoginIdAsString() + StringPool.PERCENT) .list(); } else { taskList = new ArrayList<>(); } for (Object data : listData) { Entity rowValue = Convert.convert(Entity.class, data); Object keyValue = rowValue.get(headerKey); Optional thisRelationOp = relations.stream().filter(x -> x.getFormKeyValue().equals(keyValue)).findFirst(); WorkflowListResult workflowListResult = new WorkflowListResult(); thisRelationOp.ifPresent(r -> { HistoricProcessInstance historicProcessInstance = processInstanceList.stream().filter(p -> p.getId().equals(r.getProcessId())).findFirst().orElse(null); if (ObjectUtil.isNotNull(historicProcessInstance)) { assert historicProcessInstance != null; workflowListResult.setStatus(historicProcessInstance.getState()); workflowListResult.setProcessId(historicProcessInstance.getId()); } //获取到当前数据 所关联的 的流程 正在执行的 任务 List thisDataTask = taskList.stream().filter(x -> x.getProcessInstanceId().equals(r.getProcessId())).collect(Collectors.toList()); if (thisDataTask.size() > 0) { workflowListResult.setTaskIds(thisDataTask.stream().map(Task::getId).collect(Collectors.toList())); } }); if (ObjectUtil.isNotNull(schema)) { workflowListResult.setSchemaId(schema.getId()); // 查询草稿信息 LambdaQueryWrapper wrapper = Wrappers.query().lambda().select(WorkflowDraft::getId) .eq(WorkflowDraft::getCreateUserId, StpUtil.getLoginIdAsLong()); List taskIds = workflowListResult.getTaskIds(); if (CollectionUtils.isNotEmpty(taskIds)) { wrapper.eq(WorkflowDraft::getTaskId, taskIds.get(0)); } else { wrapper.eq(WorkflowDraft::getDataId, String.valueOf(keyValue)) .eq(WorkflowDraft::getSchemaId, schema.getId()); } WorkflowDraft draft = workflowDraftService.getOne(wrapper, false); if (draft != null) workflowListResult.setDraftId(draft.getId()); } else { workflowListResult.setEnabled(Boolean.FALSE); } rowValue.set(RESULT_KEY, workflowListResult); } return body; } private Object codeGetWorkflowDataHandler(Object body,String formId, String key) { WorkflowSchema schema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getFormId, Long.parseLong(formId)).select(WorkflowSchema::getId)); List keyValueList = new ArrayList<>(); List listData; //判断是否为分页返回值 boolean isPage = ClassUtil.equals(((R) body).getData().getClass(), PageOutput.class.getName(), true); R r = Convert.convert(R.class, body); Object resultData = r.getData(); if (isPage) { PageOutput pageOutput = Convert.convert(PageOutput.class, resultData); listData = pageOutput.getList(); if (listData == null || listData.size() == 0) { return body; } for (Object data : listData) { Object keyValue = ReflectUtil.getFieldValue(data, key); keyValueList.add(keyValue.toString()); } } //判断是否为不分页列表返回值 else if (ClassUtil.equals(((R) body).getData().getClass(), ArrayList.class.getName(), true)) { listData = Convert.convert(List.class, resultData); if (listData == null || listData.size() == 0) { return body; } for (Object data : listData) { Object keyValue = ReflectUtil.getFieldValue(data, key); keyValueList.add(keyValue.toString()); } } else { return body; } //获取到所有关联的 流程id List relations = formRelationService.list(Wrappers.lambdaQuery(WorkflowFormRelation.class).eq(WorkflowFormRelation::getFormId, Long.parseLong(formId)).in(WorkflowFormRelation::getFormKeyValue, keyValueList).select(WorkflowFormRelation::getProcessId, WorkflowFormRelation::getFormKeyValue)); // if (relations.size() == 0) { // return body; // } Set processIds = relations.stream().map(WorkflowFormRelation::getProcessId).collect(Collectors.toSet()); List processInstanceList; if (processIds.size() == 0) { processInstanceList = new ArrayList<>(); } else { processInstanceList = historyService.createHistoricProcessInstanceQuery().processInstanceIds(processIds).list(); } //找到当前所有流程的 所在执行的任务list String[] processIdArrays = relations.stream().map(WorkflowFormRelation::getProcessId).toArray(String[]::new); List taskList; if (processIdArrays.length > 0) { taskList = taskService.createTaskQuery() .active() .processInstanceIdIn(processIdArrays) .taskVariableValueEquals(WorkflowConstant.TASK_IS_APPOINT_APPROVE, YesOrNoEnum.NO.getCode()) .processVariableValueEquals(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode()) .taskVariableValueLike(WorkflowConstant.TASK_ASSIGNEE_VAR_KEY, StringPool.PERCENT + StpUtil.getLoginIdAsString() + StringPool.PERCENT) .list(); } else { taskList = new ArrayList<>(); } ClassPool pool = new ClassPool(true); pool.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader())); List result = new ArrayList<>(); try { CtClass ctClass = pool.get(listData.get(0).getClass().getName()); try { CtField workflowField = CtField.make(FIELD_STRING, ctClass); ctClass.addField(workflowField); CtMethod workflowMethod = CtMethod.make(GET_MOTHOD_STRING, ctClass); ctClass.addMethod(workflowMethod); } catch (CannotCompileException e) { e.printStackTrace(); } Constructor declaredConstructor; if (!cacheClass.containsKey(ctClass.getName())) { declaredConstructor = ctClass.toClass().getDeclaredConstructor(); cacheClass.put(ctClass.getName(), declaredConstructor); } else { declaredConstructor = cacheClass.get(ctClass.getName()); } for (Object data : listData) { Object keyValue = ReflectUtil.getFieldValue(data, key); //keyValue.toString是采购申请时使用的,因为采购表存的id是Long类型的 Optional thisRelationOp = relations.stream().filter(x -> x.getFormKeyValue().equals(keyValue) || x.getFormKeyValue().equals(keyValue.toString())).findFirst(); Object newObject = declaredConstructor.newInstance(); result.add(newObject); BeanUtil.copyProperties(data, newObject); WorkflowListResult workflowListResult = new WorkflowListResult(); thisRelationOp.ifPresent(relation -> { HistoricProcessInstance historicProcessInstance = processInstanceList.stream().filter(p -> p.getId().equals(relation.getProcessId())).findFirst().orElse(null); if (ObjectUtil.isNotNull(historicProcessInstance)) { assert historicProcessInstance != null; workflowListResult.setStatus(historicProcessInstance.getState()); workflowListResult.setProcessId(historicProcessInstance.getId()); } //获取到当前数据 所关联的 的流程 正在执行的 任务 List thisDataTask = taskList.stream().filter(x -> x.getProcessInstanceId().equals(relation.getProcessId())).collect(Collectors.toList()); if (thisDataTask.size() > 0) { workflowListResult.setTaskIds(thisDataTask.stream().map(Task::getId).collect(Collectors.toList())); } }); if (ObjectUtil.isNotNull(schema)) { workflowListResult.setSchemaId(schema.getId()); // 查询草稿信息 LambdaQueryWrapper wrapper = Wrappers.query().lambda().select(WorkflowDraft::getId) .eq(WorkflowDraft::getCreateUserId, StpUtil.getLoginIdAsLong()) .eq(WorkflowDraft::getDataId, String.valueOf(keyValue)); List taskIds = workflowListResult.getTaskIds(); if (CollectionUtils.isNotEmpty(taskIds)) { wrapper.eq(WorkflowDraft::getTaskId, taskIds.get(0)); } else { wrapper.eq(WorkflowDraft::getSchemaId, schema.getId()); } WorkflowDraft draft = workflowDraftService.getOne(wrapper, false); if (draft != null) workflowListResult.setDraftId(draft.getId()); } else { workflowListResult.setEnabled(Boolean.FALSE); } ReflectUtil.setFieldValue(newObject, RESULT_KEY, workflowListResult); } ctClass.detach(); } catch (NotFoundException | CannotCompileException | NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); throw new MyException("表单发起流程数据转换出错,请联系管理员!" ); } if (isPage) { ((PageOutput) (r.getData())).setList(result); } else{ r.put("data", result); } return body; } }