概述背景
oa的入参理念就是map类型的,这样能统一兼容,但是调用的时候挨个set 有规律的值,代码就有点冗余了,下面以创建流程为例子写个工具类(本次修改支持上传多图片/文件)
获取token代码(也简单)不是我写的我也就不列了
基础类:
OA创建参数类: Create
OA明细实体: DetailData
OA明细记录实体(一个实体代表一条明细): WorkflowRequestTableRecord
OA其他参数: OtherParams
OA明细信息实体: DetailInfo
OA属性实体: Field
OA文件属性实体: File
OA出参实体 : OaRes
工具类代码:
入参的主表对象(InspectPushConcessionOaBo)、子表对象(InspectPushOaConcessionItemBo)都实现这个接口
package org.dromara.mes.common.domain.flow;
import cn.hutool.core.bean.BeanUtil;
import org.apache.commons.lang3.ObjectUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.domain.flow
* @className: ObjToField
* @author: zhangxuewei
* @description:
* @date: 2024/12/25 14:43
* @version: 1.0
*/
public interface ObjToField {
default List<Field> toMap(Object obj) {
Map<String, Object> map = BeanUtil.beanToMap(obj);
List<Field> fields = new ArrayList<>();
map.forEach((k, v) -> {
if (ObjectUtils.isNotEmpty(v)) {
Field field = new Field(k, v);
fields.add(field);
}
});
return fields;
}
}
package org.dromara.mes.common.utils.oa;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.dromara.common.core.enums.sys.ExtApiEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.mes.common.config.OaConfig;
import org.dromara.mes.common.domain.flow.*;
import org.dromara.mes.utils.ApiCallUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.utils.oa
* @className: OaFlowUtils
* @author: zhangxuewei
* @description: 泛微OA流程工具类
* @date: 2024/8/9 17:06
* @version: 1.0
*/
@Slf4j
public class OaFlowUtils<A extends ObjToField> {
/**
* @param userId: OA用户主键
* @param workflowId: 流程主键
* @param mainData: 主表的数据
* @param details: k-明细表名称 v-数据集合
* @return String
* @author zhangxuewei
* @description 新建OA流程
* @date 2024/8/10 10:02
*/
public OaRes doCreateRequest(String userId, Integer workflowId, String title, A mainData, DetailInfo<? extends ObjToField>... details) {
log.info("已进入新建OA流程,workflowId={}...", workflowId);
String path = OaConfig.getHost() + "/api/workflow/paService/doCreateRequest";
Map<String, String> headers = new HashMap<>();
headers.put("token", OaTokenUtils.getToken());
headers.put("appid", OaConfig.getAppId());
if (StringUtils.isNotEmpty(userId)) {
RSA rsa = new RSA(null, OaConfig.getSpk());
String u = rsa.encryptBase64(userId, CharsetUtil.CHARSET_UTF_8, KeyType.PublicKey);
headers.put("userid", u);
}
Create oc = new Create();
oc.setWorkflowId(workflowId);
oc.setMainData(objToOaMainData(oc, mainData).toString());
oc.setDetailData(objToOaDetailData(oc, details).toString());
oc.setRequestName(title);
Map<String, Object> body = BeanUtil.beanToMap(oc);
HttpRequest request = HttpRequest.post(path).addHeaders(headers).form(body);
log.info("header:{}", JSONUtil.parseObj(request.headers()));
log.info("form:{}", JSONUtil.parseObj(request.form()));
String response = request.execute().body();
log.info("调用创建流程接口完毕,OA出参:{}", response);
OaRes oaRes = JSONUtil.toBean(response, OaRes.class);
return oaRes;
}
/**
* @return JSONArray
* @author zhangxuewei
* @description 对象转OA的明细表对象数据
* @date 2024/8/10 9:18
*/
private JSONArray objToOaDetailData(Create oc, DetailInfo<? extends ObjToField>... details) {
if (details.length == 0)
return new JSONArray();
List<DetailData> detailDataList = new ArrayList<>();
for (DetailInfo<? extends ObjToField> detail : details) {
DetailData detailData = new DetailData();
List<WorkflowRequestTableRecord> requestTableRecords = new ArrayList<>();
// 明细表名称
detailData.setTableDBName(detail.getDetailTableName());
if (ObjectUtils.isEmpty(detail.getDetailDatas()))
throw new ServiceException("明细列表数据不能为空!");
detail.getDetailDatas().forEach(item -> {
WorkflowRequestTableRecord record = new WorkflowRequestTableRecord();
List<Field> workflowRequestTableFields = item.toMap(item);
record.setWorkflowRequestTableFields(workflowRequestTableFields);
requestTableRecords.add(record);
});
detailData.setWorkflowRequestTableRecords(requestTableRecords);
detailDataList.add(detailData);
}
return JSONUtil.parseArray(detailDataList);
}
/**
* @param obj:
* @return JSONObject
* @author zhangxuewei
* @description 对象转OA的主表数据
* @date 2024/8/10 9:18
*/
private JSONArray objToOaMainData(Create oc, A obj) {
List<Field> fields = obj.toMap(obj);
return JSONUtil.parseArray(fields);
}
}
调用样例:
public ...... {
.....
// 主表数据
InspectPushConcessionOaBo mainData = ...;
// 明细信息
List<InspectPushOaConcessionItemBo> inspectPushOaItemBos = ....;
OaFlowUtils<InspectPushConcessionOaBo, InspectPushOaConcessionItemBo> oaFlowUtils = new OaFlowUtils();
// 明细数据
DetailInfo<InspectPushOaConcessionItemBo> detailInfo = new DetailInfo<>();
detailInfo.setDetailDatas(inspectPushOaItemBos);
// 明细表名称
detailInfo.setDetailTableName(OaDetailTableNameAndFlowId.MaterialConcessionD1.getDetailTableName());
// 标题
String title = "材料让步接收-" + LoginHelper.getLoginUser().getNickname() + "-" + timeStr[0];
// 开始调用
OaRes oaRes = oaFlowUtils.doCreateRequest(hrmreSource.getId(), OaDetailTableNameAndFlowId.MaterialConcessionD1.getFlowId(), title, mainData, detailInfo);
}
调用结果

基础类结构
package org.dromara.mes.common.domain.flow;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.List;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.domain
* @className: Create
* @author: zhangxuewei
* @description: OA创建vo
* @date: 2024/8/9 17:11
* @version: 1.0
*/
@Data
public class Create {
/**
* 必填 主表数据 org.dromara.mes.common.domain.flow.MainData
*/
private String mainData;
/**
* 必填 流程标题
*/
private String requestName;
/**
* 必填 流程Id
*/
private Integer workflowId;
/**
* 非必填 明细表数据 org.dromara.mes.common.domain.flow.DetailData
*/
private String detailData;
/**
* 非必填 其他参数 org.dromara.mes.common.domain.flow.OtherParams
*/
private String otherParams;
/**
* 非必填 签字意见,默认值流程默认意见若未设置则为空
*/
// private String remark;
/**
* 非必填 紧急程度
*/
// private String requestLevel;
}
package org.dromara.mes.common.domain.flow;
import lombok.Data;
import java.util.List;
/**
* @projectName: ruoyi
* @package: com.ruoyi.bmp.oa.domain.dto
* @className: DetailData
* @author: zhangxuewei
* @description: OA明细实体
* @date: 2024/8/9 17:40
* @version: 1.0
*/
@Data
public class DetailData {
/**
* 表名名称
*/
private String tableDBName;
/**
* "deleteAll":"1"(删除该流程原有明细)
*/
private String deleteAll;
/**
* "deleteKeys":"12,13"(删除该流程明细id=12,13d的明细行)
*/
private String deleteKeys;
/**
* 明细列表
*/
private List<WorkflowRequestTableRecord> workflowRequestTableRecords;
}
package org.dromara.mes.common.domain.flow;
import lombok.Data;
import java.util.List;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.domain.flow
* @className: DetailInfo
* @author: zhangxuewei
* @description: OA明细信息实体
* @date: 2024/8/10 10:08
* @version: 1.0
*/
@Data
public class DetailInfo<B extends ObjToField> {
// 明细表名称
String detailTableName;
// 明细数据
List<B> detailDatas;
}
package org.dromara.mes.common.domain.flow;
import lombok.Data;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.domain
* @className: Field
* @author: zhangxuewei
* @description: oa属性实体
* @date: 2024/8/9 16:55
* @version: 1.0
*/
@Data
public class Field<T> {
private String fieldName;
private T fieldValue;
public Field() {
}
public Field(String fieldName, T fieldValue) {
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}
}
package org.dromara.mes.common.domain.flow;
import lombok.Data;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.domain.flow
* @className: OaRes
* @author: zhangxuewei
* @description: OA出参实体
* @date: 2024/8/10 16:31
* @version: 1.0
*/
@Data
public class OaRes {
/**
* 返回数据状态 SUCCESS:成功,PARAM_ERROR:参数错误,NO_PERMISSION:无权限,SYSTEM_INNER_ERROR:程序异常,USER_EXCEPTION:用户异常
*/
private String code;
/**
* 接口状态为SUCCESS,则data中包含生成的requestid
*/
private Data data;
/**
* 接口异常信息:例如状态为PARAM_ERROR 则返回错误参数信息
*/
private String errMsg;
@lombok.Data
public static class Data {
private Integer requestid;
}
}
package org.dromara.mes.common.domain.flow;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import org.dromara.common.json.utils.JsonUtils;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.domain.flow
* @className: OtherParams
* @author: zhangxuewei
* @description: 其他参数
* @date: 2024/8/9 17:17
* @version: 1.0
*/
@Data
public class OtherParams {
/**
* (api未描述)
*/
private String messageType;
/**
* 新建流程是否默认提交到第二节点,可选值为[0 :不流转 1:流转 (默认)]
*/
private String isnextflow;
/**
* "流程密级, 开启密级后生效, 默认公开"
*/
private String requestSecLevel;
/**
* ”保密期限,流程密级为秘密或机密时,通过改参数上传保密期限,不上传时取分级保护出的保密期限“
*/
private String requestSecValidity;
/**
* 新建流程失败是否默认删除流程,可选值为[0 :不删除 1:删除 (默认)]
*/
private String delReqFlowFaild;
/**
* "是否验证用户创建流程权限,可选值为[0 :不验证 1:验证 (默认)]"
*/
private String isVerifyPer;
}
package org.dromara.mes.common.domain.flow;
import lombok.Data;
import java.util.List;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.domain
* @className: WorkflowRequestTableRecord
* @author: zhangxuewei
* @description: OA明细实体(一个实体代表一条明细)
* @date: 2024/8/9 16:57
* @version: 1.0
*/
@Data
public class WorkflowRequestTableRecord {
/**
* 明细表recordOrder参数说明 0:代表新增,创建流程全部传0即可 传入其他行id,代表修改该id的明细(该id为数据库明细表的id值)
*/
private Integer recordOrder = 0;
/**
* 一条明细上的所有属性
*/
private List<Field> workflowRequestTableFields;
}
文件上传支持
支持上传文件需要加上这个类
package org.dromara.mes.common.domain.flow;
import lombok.Data;
/**
* @projectName: wmes
* @package: org.dromara.mes.common.domain.flow
* @className: File
* @author: zhangxuewei
* @description:
* @date: 2025/2/25 12:52
* @version: 1.0
*/
@Data
public class File {
/**
* 文件名称
*/
private String fileName;
/**
* 文件地址
*/
private String filePath;
}
组装数据:
需要在传参的类(主表/明细对应的类)中增加Oa对应的的字段属性如fj,定义如下
...
/**
* 附件
*/
private List<File> fj;
...
然后将附件集合组装完毕后赋值给对应的属性(主表/明细对应的类属性)即可。