diff --git a/anomaly/pom.xml b/anomaly/pom.xml
index 1e828357..a3350a89 100644
--- a/anomaly/pom.xml
+++ b/anomaly/pom.xml
@@ -89,5 +89,14 @@
spring-boot-starter-quartz
2.0.5.RELEASE
+
+ org.projectlombok
+ lombok
+
+
+ org.apache.httpcomponents
+ httpmime
+ 4.5
+
\ No newline at end of file
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/NcCodesVO.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/NcCodesVO.java
new file mode 100644
index 00000000..268f4136
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/NcCodesVO.java
@@ -0,0 +1,16 @@
+package com.foreverwin.mesnac.anomaly.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-17 15:18
+ */
+@Data
+public class NcCodesVO {
+ private List ncGroupAndNcCodes;
+ private List dutyCauseType;
+ private List dutyType;
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/QualitySystemDto.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/QualitySystemDto.java
new file mode 100644
index 00000000..2f8e256d
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/QualitySystemDto.java
@@ -0,0 +1,219 @@
+package com.foreverwin.mesnac.anomaly.dto;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.foreverwin.mesnac.anomaly.model.AbnormalBill;
+import com.foreverwin.mesnac.anomaly.model.AbnormalBillDispose;
+import com.foreverwin.mesnac.anomaly.model.Photos;
+import lombok.Builder;
+import lombok.Data;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 质量系统传参
+ * @Author YinQ
+ * @create 2022-08-02 13:43
+ */
+@Data
+@Builder
+@JsonInclude(value= JsonInclude.Include.NON_NULL)
+public class QualitySystemDto {
+
+ /**
+ * 异常单号
+ */
+ private String abnormalbill_no;
+ /**
+ * 异常车间
+ */
+ private String abnormalbill_workshop;//异常车间
+ /**
+ * 物料编码
+ */
+ private String material_code;//物料编码
+ /**
+ * 物料描述
+ */
+ private String material_description;//物料编码
+ /**
+ * 工单
+ */
+ private String shop_order;//工单
+ /**
+ * 图号
+ */
+ private String number;//工单
+ /**
+ * 产品条码
+ */
+ private String product_barcode;//产品条码
+ /**
+ * 工作令
+ */
+ private String work_order;//工作令
+ /**
+ * 项目编号
+ */
+ private String item_number;//项目编号
+ /**
+ * 产品类别
+ */
+ private String product_category;//产品类别
+ /**
+ * 提报用户组
+ */
+ private String submission_users;//提报用户组
+ /**
+ * 工序编码
+ */
+ private String working_procedure_code;//工序编码
+ /**
+ * 发起时间
+ */
+ private Date submit_date;
+
+ /**
+ * 问题提报人
+ */
+ private String pbUser;
+
+ /**
+ * 表单标题
+ */
+ private String name;
+
+ /**
+ * 检验人员员工号
+ */
+ private String test_user_employeeNo;
+
+ /**
+ * 提报人员工号
+ */
+ private String submission_man_employeeNo;
+
+
+ /**
+ * 问题描述
+ */
+ private String problem_description;//问题描述
+ /**
+ * 不良代码组
+ */
+ private String bad_code_group;//不良代码组
+ /**
+ * 不良代码
+ */
+ private String bad_code;//不良代码
+ /**
+ * 不良品数量
+ */
+ private String rejects_number;//不良品数量
+ /**
+ * 问题等级
+ */
+ private String problem_level;//问题等级
+ /**
+ * 检验人员
+ */
+ private String test_user;//检验人员
+ /**
+ * 问题数量
+ */
+ private String problem_number;//问题数量
+ /**
+ * 发现环节
+ */
+ private String discover_link;//发现环节
+ /**
+ * 实物位置
+ */
+ private String entity_location;//实物位置
+ /**
+ * 上报来源
+ */
+ private String report_from;//上报来源
+ /**
+ * 问题照片
+ */
+ private List problem_photos;//问题照片
+
+
+ /**
+ * 原因分析
+ */
+ private String cause_analysis;//原因分析
+ /**
+ * 原因分类
+ */
+ private String reason_type;//原因分类
+ /**
+ * 责任分类
+ */
+ private String responsibility_type;//责任分类
+ /**
+ * 责任部门
+ */
+ private String responsibility_dept;//责任部门
+ /**
+ * 责任人
+ */
+ private String problem_owner;//责任人
+ /**
+ * 发送用户组
+ */
+ private String send_user_group;//发送用户组
+
+
+ /**
+ * 异常方案
+ */
+ private String abnormalbill_programme;//异常方案
+ /**
+ * 返修工艺路线
+ */
+ private String repair_process_route;//返修工艺路线
+ /**
+ * 返修工艺版本
+ */
+ private String repair_process_version;//返修工艺版本
+ /**
+ * 返修工单
+ */
+ private String repair_workorder;//返修工单
+ //解决方案发送用户组
+ /**
+ * 返修工艺内容
+ */
+ private String repair_process_content;//返修工艺内容
+ /**
+ * 方案备注
+ */
+ private String programme_remark;//方案备注
+
+
+ /**
+ * 异常原因
+ */
+ private String abnormalbill_reason;//异常原因
+ /**
+ * 预防措施
+ */
+ private String preventive_measure;//预防措施
+ /**
+ * 整改记录照片(问题照片)
+ */
+ private List rectification_record_photos;//整改记录照片
+
+
+ /**
+ * 效果验证结果
+ */
+ private String effect_verification_results;//效果验证结果
+
+ /**
+ * 方案会签人
+ */
+ private String programme_sign_man;//方案会签人
+
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/RouterBpmVO.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/RouterBpmVO.java
new file mode 100644
index 00000000..c8938e05
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/dto/RouterBpmVO.java
@@ -0,0 +1,23 @@
+package com.foreverwin.mesnac.anomaly.dto;
+
+import com.foreverwin.mesnac.meapi.dto.RouterStepDto;
+import com.foreverwin.mesnac.meapi.model.RouterStep;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class RouterBpmVO {
+ private String abnormalNo;
+ private String pbDescription;
+ private String item;
+ private String itemRevision;
+ private String itemDescription;
+ private String shopOrder;
+ private String router;
+ private String routerRevision;
+ private String routerType;
+ private String routerBo;
+ private String site;
+ private List routerStep;
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/model/Photos.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/model/Photos.java
new file mode 100644
index 00000000..fc41531c
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/model/Photos.java
@@ -0,0 +1,135 @@
+package com.foreverwin.mesnac.anomaly.model;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-02 13:50
+ */
+public class Photos {
+
+ private String id;
+ private String remarks;
+ private String createdTime;
+ private String modifiedTime;
+ private boolean deleted;
+ private String createdBy;
+ private String modifiedBy;
+ private String refId;
+ private String schemaCode;
+ private String name;
+ private String fileExtension;
+ private Long fileSize;
+ private String mimeType;
+ private String base64ImageStr;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getRemarks() {
+ return remarks;
+ }
+
+ public void setRemarks(String remarks) {
+ this.remarks = remarks;
+ }
+
+ public String getCreatedTime() {
+ return createdTime;
+ }
+
+ public void setCreatedTime(String createdTime) {
+ this.createdTime = createdTime;
+ }
+
+ public String getModifiedTime() {
+ return modifiedTime;
+ }
+
+ public void setModifiedTime(String modifiedTime) {
+ this.modifiedTime = modifiedTime;
+ }
+
+ public boolean isDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(boolean deleted) {
+ this.deleted = deleted;
+ }
+
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ public void setCreatedBy(String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ public String getModifiedBy() {
+ return modifiedBy;
+ }
+
+ public void setModifiedBy(String modifiedBy) {
+ this.modifiedBy = modifiedBy;
+ }
+
+ public String getRefId() {
+ return refId;
+ }
+
+ public void setRefId(String refId) {
+ this.refId = refId;
+ }
+
+ public String getSchemaCode() {
+ return schemaCode;
+ }
+
+ public void setSchemaCode(String schemaCode) {
+ this.schemaCode = schemaCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getFileExtension() {
+ return fileExtension;
+ }
+
+ public void setFileExtension(String fileExtension) {
+ this.fileExtension = fileExtension;
+ }
+
+ public Long getFileSize() {
+ return fileSize;
+ }
+
+ public void setFileSize(Long fileSize) {
+ this.fileSize = fileSize;
+ }
+
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ public void setMimeType(String mimeType) {
+ this.mimeType = mimeType;
+ }
+
+ public String getBase64ImageStr() {
+ return base64ImageStr;
+ }
+
+ public void setBase64ImageStr(String base64ImageStr) {
+ this.base64ImageStr = base64ImageStr;
+ }
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/service/YunBpmService.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/service/YunBpmService.java
new file mode 100644
index 00000000..c90a5c5a
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/service/YunBpmService.java
@@ -0,0 +1,74 @@
+package com.foreverwin.mesnac.anomaly.service;
+
+import com.foreverwin.mesnac.anomaly.model.AbnormalBill;
+import com.foreverwin.mesnac.anomaly.model.AbnormalBillDispose;
+import com.foreverwin.mesnac.anomaly.utils.OAuthTokenInfo;
+import com.foreverwin.mesnac.anomaly.utils.YunBpmApiRes;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-04 14:16
+ */
+public interface YunBpmService {
+
+
+ /**
+ * 新建bpm表单
+ *
+ * @param formData
+ * @param owner
+ * @param ownerDeptId
+ * @param sheetCode
+ * @param workflowCode
+ * @param replayToken
+ * @param accessToken
+ * @return
+ */
+ YunBpmApiRes saveForm(Object formData, String owner, String ownerDeptId, String sheetCode, String workflowCode, String replayToken, String accessToken);
+
+ /**
+ * 更新bpm表单
+ *
+ * @param formData
+ * @param sheetCode
+ * @param workflowCode
+ * @param workflowFormId
+ * @param workflowInstanceId
+ * @param workItemId
+ * @param replayToken
+ * @param accessToken
+ * @return
+ */
+ YunBpmApiRes updateForm(Object formData, String sheetCode, String workflowCode, String workflowFormId, String workflowInstanceId, String workItemId, String replayToken, String accessToken);
+
+
+ /**
+ * 用户鉴权
+ *
+ * @param userName
+ * @param password
+ * @return
+ */
+ OAuthTokenInfo getTokenByUserNameAndPassword(String userName, String password);
+
+ /**
+ * 上传附件
+ * @param urlStr http://yunbpmcs.mesnac.com:8080/api/api/aliyun/upload
+ * @param file 文件类
+ * @param token accessToken
+ **/
+ String postFile(String urlStr, MultipartFile file, String token) throws IOException, InterruptedException;
+
+ /**
+ * 质量异常提报给质量bpm系统
+ * @param abnormalBill
+ * @param ncGroup
+ * @param ncCode
+ * @return
+ */
+ YunBpmApiRes saveQualitySystem(AbnormalBill abnormalBill, AbnormalBillDispose abnormalBillDispose, String ncGroup, String ncCode);
+
+}
\ No newline at end of file
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/service/impl/YunBpmServiceImpl.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/service/impl/YunBpmServiceImpl.java
new file mode 100644
index 00000000..b879a153
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/service/impl/YunBpmServiceImpl.java
@@ -0,0 +1,255 @@
+package com.foreverwin.mesnac.anomaly.service.impl;
+
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.foreverwin.mesnac.anomaly.dto.QualitySystemDto;
+import com.foreverwin.mesnac.anomaly.model.AbnormalBill;
+import com.foreverwin.mesnac.anomaly.model.AbnormalBillDispose;
+import com.foreverwin.mesnac.anomaly.service.YunBpmService;
+import com.foreverwin.mesnac.anomaly.utils.*;
+import com.foreverwin.mesnac.common.util.DateUtil;
+import com.foreverwin.mesnac.meapi.util.StringUtils;
+import org.apache.http.Consts;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.mime.HttpMultipartMode;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.text.DecimalFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-04 14:16
+ */
+@Service
+public class YunBpmServiceImpl implements YunBpmService {
+
+ @Override
+ public YunBpmApiRes saveForm(Object formData, String owner, String ownerDeptId, String sheetCode, String workflowCode, String replayToken, String accessToken) {
+ return saveOrUpdateForm(formData, owner, ownerDeptId, sheetCode, workflowCode, null, null, null, replayToken, accessToken);
+ }
+
+ @Override
+ public YunBpmApiRes updateForm(Object formData, String sheetCode, String workflowCode, String workflowFormId, String workflowInstanceId, String workItemId, String replayToken, String accessToken) {
+ return saveOrUpdateForm(formData, null, null, sheetCode, workflowCode, workflowFormId, workflowInstanceId, workItemId, replayToken, accessToken);
+ }
+
+ /**
+ * 质量异常提报给质量bpm系统
+ *
+ * @param abnormalBill
+ * @param ncGroup
+ * @param ncCode
+ * @return
+ */
+ public YunBpmApiRes saveQualitySystem(AbnormalBill abnormalBill, AbnormalBillDispose abnormalBillDispose, String ncGroup, String ncCode) {
+
+ QualitySystemDto qualitySystemDto = QualitySystemDto.builder()
+ //异常主数据
+ .abnormalbill_no(abnormalBill.getAbnormalNo()).abnormalbill_workshop(abnormalBill.getWorkCenter())
+ .material_code(abnormalBill.getItemBo().split(",")[1]).number(abnormalBill.getMapNo())
+ .material_description(abnormalBill.getItemDescription()).shop_order(abnormalBill.getShopOrder())
+ .product_barcode(abnormalBill.getSfc()).work_order(abnormalBill.getWorkOrder()).submit_date(DateUtil.getCurrentDate())
+ .item_number(abnormalBill.getItemNumber()).product_category(abnormalBill.getProductCategory())
+ .submission_users(abnormalBill.getReportSendUserGroup()).working_procedure_code(abnormalBill.getOperation())
+ //不良明细
+ .problem_description(abnormalBill.getPbDescription()).problem_number(abnormalBill.getPbQty())
+ .discover_link(abnormalBill.getDiscover()).entity_location(abnormalBill.getEntityLocation())
+ .report_from(abnormalBill.getReportFrom()).rejects_number(abnormalBill.getNcQty())
+ .bad_code_group(ncGroup).bad_code(ncCode).problem_level(abnormalBill.getPbGrade())
+ // .problem_photos(null)
+ // .test_user_employeeNo(abnormalBill.getInspector()).submission_man_employeeNo(pbUserList)
+ //责任划分
+ .cause_analysis(abnormalBillDispose.getDutyCauseDescription()).reason_type(abnormalBillDispose.getDutyCauseType())
+ .responsibility_type(abnormalBillDispose.getDutyType()).responsibility_dept(abnormalBillDispose.getDutyDepart())
+ .problem_owner(abnormalBillDispose.getPrincipalUser())
+ //.send_user_group()
+ /*//解决方案
+ .abnormalbill_programme().repair_process_route().repair_process_version()
+ .repair_workorder().repair_process_content().programme_remark()
+ //纠正预防
+ .abnormalbill_reason().preventive_measure().rectification_record_photos(null)*/
+ .build();
+
+ System.out.println(qualitySystemDto);
+ String jsonString = JSONObject.toJSONString(qualitySystemDto);
+ JSONObject qualitySystem = JSONObject.parseObject(jsonString);
+ OAuthTokenInfo auth = getTokenByUserNameAndPassword(yunBpmConfig.userName, yunBpmConfig.passWord);
+ YunBpmApiRes tokenRes = getReplayToken(auth.getAccess_token());
+ if (auth.getSuccess()) {
+ /**
+ * 新建bpm表单
+ */
+ YunBpmApiRes result = saveForm(qualitySystem, auth.getUser_id(), yunBpmConfig.deptId,
+ yunBpmConfig.workCode, yunBpmConfig.workCode, (String)tokenRes.getData(), auth.getAccess_token());
+ /*YunBpmApiRes result = updateForm(qualitySystem, yunBpmConfig.workCode, yunBpmConfig.workCode,
+ "d9e5aa7ec13849aabf2a879aa94ebc15", "1165ec5df80f4df8ae615539de6fa7ff", "50f1f3cf78124e7ab91a0432f3aeb3f0",
+ (String) tokenRes.getData(), auth.getAccess_token());*/
+ System.out.println(result.toString());
+ return result;
+ }
+ return null;
+ }
+
+ /**
+ * 保存或更新表单信息
+ *
+ * @param formData 表单信息 业务数据对象(建议在原本的实体类属性上挂@Alias()注解,直接转JSONObject传输)
+ * @param owner 流程所有者 用户id
+ * @param ownerDeptId 所有者部门 部门id
+ * @param sheetCode 表单Code 固定值manufacture_cores
+ * @param workflowCode 工作流Code 固定值manufacture_cores
+ * @param replayToken ReplayToken 调用接口时实时获取
+ * @param accessToken AccessToken 调用接口时实时获取
+ * @return com.foreverwin.mesnac.anomaly.utils.YunBpmApis
+ **/
+ private YunBpmApiRes saveOrUpdateForm(Object formData, String owner, String ownerDeptId, String sheetCode,
+ String workflowCode, String workflowFormId,
+ String workflowInstanceId, String workItemId,
+ String replayToken, String accessToken) {
+ BizObjectModel bizObjectModel = BizObjectModel.builder()
+ .data(formData)
+ .owner(owner)
+ .ownerDeptId(ownerDeptId)
+ .sheetCode(sheetCode)
+ .schemaCode(sheetCode)
+ .workflowInstanceId(workflowInstanceId)
+ .id(workflowFormId)
+ .build();
+
+ SaveFormModel saveFormModel = SaveFormModel.builder()
+ .replayToken(replayToken)
+ .workflowCode(workflowCode)
+ .bizObject(bizObjectModel)
+ .saveBizObject(true)
+ .workItemId(workItemId)
+ .workflowInstanceId(workflowInstanceId)
+ .build();
+ String requestUrl = yunBpmConfig.getApiBaseUrl() +
+ String.format(YunBpmApis.SAVE_OR_UPDATE_FORM, accessToken);
+ String jsons = JSONUtil.toJsonStr(saveFormModel);
+ String respBody = HttpUtil.post(requestUrl, JSONUtil.toJsonStr(saveFormModel));
+ return JSONUtil.toBean(respBody, YunBpmApiRes.class);
+ }
+
+
+ /**
+ * 用户鉴权
+ * @param userName
+ * @param password
+ * @return
+ */
+ public OAuthTokenInfo getTokenByUserNameAndPassword(String userName, String password) {
+ YunBpmApiRes yunBpmApiRes = this.getOauthCode(userName, password, null);//获取授权码
+ if (yunBpmConfig.SUCCESS_CODE.equals(yunBpmApiRes.getErrCode())) {
+ return getTokenByOauthCode(yunBpmApiRes.getCode());//根据授权码获取token
+ }
+ return null;
+ }
+
+ public YunBpmApiRes getOauthCode(String userName, String password, String url) {
+ String requestUrl = yunBpmConfig.getApiBaseUrl() + "/api/login/Authentication/get_code";
+ if (StringUtils.isEmpty(url)) {
+ url = this.getDefaultOauthCodeUrl();
+ }
+
+ Map params = new HashMap<>();
+ params.put("username", userName);
+ params.put("password", password);
+ params.put("url", url);
+
+ String respBody = HttpUtil.post(requestUrl, JSONUtil.toJsonStr(params));
+ return JSONUtil.toBean(respBody, YunBpmApiRes.class);
+ }
+
+ private String getDefaultOauthCodeUrl() {
+ return yunBpmConfig.getApiBaseUrl() + "/api/login?redirect_uri="
+ + yunBpmConfig.getApiBaseUrl() +
+ "/api/oauth/authorize?client_id=api&response_type=code&scope=read&redirect_uri="
+ + yunBpmConfig.getApiBaseUrl() + "/oauth";
+ }
+
+ public OAuthTokenInfo getTokenByOauthCode(String oAuthCode) {
+ String url = yunBpmConfig.getApiBaseUrl() + "/api";
+ String redirectUri = yunBpmConfig.getApiBaseUrl() + "/oauth";
+ String requestUrl = yunBpmConfig.getApiBaseUrl() + "/api/login/Authentication/get_token?code="
+ + oAuthCode + "&client_secret=" + yunBpmConfig.getClientSecret() +
+ "&client_id=" + yunBpmConfig.getClientId() + "&url=" + url + "&redirect_uri=" + redirectUri;
+ String respBody = HttpUtil.get(requestUrl);
+ return JSONUtil.toBean(respBody, OAuthTokenInfo.class);
+ }
+
+
+ /**
+ * 上传附件
+ *
+ * @param urlStr http://yunbpmcs.mesnac.com:8080/api/api/aliyun/upload
+ * @param file 文件类
+ * @param token accessToken 上传文件不同于其他接口,需要在请求头中使用authorization:Bearer 的方式挂载,注意Bearer和token中间有空格
+ * @date 2021/8/14 22:34
+ **/
+ public String postFile(String urlStr, MultipartFile file, String token) throws IOException, InterruptedException {
+
+ String prefix = file.getOriginalFilename();
+ assert prefix != null;
+ int lastIndex = prefix.lastIndexOf('.');
+ String suffix = prefix.substring(lastIndex);
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ HttpPost uploadFile = new HttpPost(urlStr);
+
+ uploadFile.setHeader("authorization", "Bearer " + token);
+ DecimalFormat df = new DecimalFormat("#.##");
+ MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
+
+ builder.addTextBody("name", file.getOriginalFilename(), ContentType.create("text/plain", Consts.UTF_8));
+ builder.addTextBody("size", df.format((double) file.getSize() / 1024), ContentType.TEXT_PLAIN);
+ builder.addTextBody("suffix", suffix, ContentType.TEXT_PLAIN);
+
+ builder.addBinaryBody(
+ "file",
+ file.getInputStream(),
+ // new FileInputStream(f),
+ ContentType.DEFAULT_BINARY,
+ file.getOriginalFilename()
+ );
+
+ HttpEntity multipart = builder.build();
+ uploadFile.setEntity(multipart);
+ CloseableHttpResponse response = httpClient.execute(uploadFile);
+ HttpEntity responseEntity = response.getEntity();
+ String sResponse = EntityUtils.toString(responseEntity, "UTF-8");
+ JSONObject jsonObject = JSONObject.parseObject(sResponse);
+
+ return JSON.toJSONString(jsonObject);
+ }
+
+ /**
+ * 获取replayToken接口
+ *
+ * @param accessToken
+ * @return
+ */
+ private YunBpmApiRes getReplayToken(String accessToken) {
+ String requestUrl = yunBpmConfig.getApiBaseUrl()
+ + "/api/api/runtime/form/getReplayToken?access_token="
+ + accessToken;
+ HashMap map = new HashMap<>();
+ map.put("access_token", accessToken);
+ String respBody = HttpUtil.get(requestUrl, map);
+ return JSONUtil.toBean(respBody, YunBpmApiRes.class);
+ }
+
+
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/BizObjectModel.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/BizObjectModel.java
new file mode 100644
index 00000000..34154759
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/BizObjectModel.java
@@ -0,0 +1,86 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-02 15:17
+ */
+@Data
+@Builder
+@JsonInclude(value= JsonInclude.Include.NON_NULL)
+public class BizObjectModel {
+ /**
+ * 创建人部门
+ */
+ private String createdDeptId;
+ /**
+ * 创建时间
+ */
+ private Date createdTime;
+ /**
+ * 创建人
+ */
+ private String creater;
+ /**
+ * 业务数据对象,数据格式与对应的业务模型一致
+ */
+ private Object data;
+ /**
+ * 业务对象ID
+ */
+ private String id;
+ /**
+ * 是否是从数据库加载的对象
+ */
+ private String loadedFromDb;
+ /**
+ * 修改时间
+ */
+ private Date modifiedTime;
+ /**
+ * 创建人部门
+ */
+ private String modifier;
+ /**
+ * 名称
+ */
+ private String name;
+ /**
+ * 所有人
+ */
+ private String owner;
+ /**
+ * 所有人部门
+ */
+ private String ownerDeptId;
+ /**
+ * 部门查询编码
+ */
+ private String ownerDeptQueryCode;
+ /**
+ * 部门查询编码
+ */
+ private String schemaCode;
+ /**
+ * 单据号
+ */
+ private String sequenceNo;
+
+ private String sequenceStatus;
+
+ private String sheetCode;
+ /**
+ * 业务数据对象状态
+ */
+ private String status;
+ /**
+ * 流程实例ID
+ */
+ private String workflowInstanceId;
+
+}
\ No newline at end of file
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/OAuthTokenInfo.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/OAuthTokenInfo.java
new file mode 100644
index 00000000..875f6de5
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/OAuthTokenInfo.java
@@ -0,0 +1,164 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+import java.util.List;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-02 10:44
+ */
+public class OAuthTokenInfo {
+
+ private String corpId;
+ private String user_name;
+ private boolean mobile;
+ private boolean isAdmin;
+ private String token_type;
+ private List authorities;
+ private String client_id;
+ private String access_token;
+ private String refresh_token;
+ private List aud;
+ private String user_id;
+ private boolean success;
+ private List scope;
+ private String exp;
+ private String expires_in;
+ private boolean isAppAdmin;
+ private String jti;
+
+ public String getCorpId() {
+ return corpId;
+ }
+
+ public void setCorpId(String corpId) {
+ this.corpId = corpId;
+ }
+
+ public String getUser_name() {
+ return user_name;
+ }
+
+ public void setUser_name(String user_name) {
+ this.user_name = user_name;
+ }
+
+ public boolean isMobile() {
+ return mobile;
+ }
+
+ public void setMobile(boolean mobile) {
+ this.mobile = mobile;
+ }
+
+ public boolean isAdmin() {
+ return isAdmin;
+ }
+
+ public void setAdmin(boolean admin) {
+ isAdmin = admin;
+ }
+
+ public String getToken_type() {
+ return token_type;
+ }
+
+ public void setToken_type(String token_type) {
+ this.token_type = token_type;
+ }
+
+ public List getAuthorities() {
+ return authorities;
+ }
+
+ public void setAuthorities(List authorities) {
+ this.authorities = authorities;
+ }
+
+ public String getClient_id() {
+ return client_id;
+ }
+
+ public void setClient_id(String client_id) {
+ this.client_id = client_id;
+ }
+
+ public String getAccess_token() {
+ return access_token;
+ }
+
+ public void setAccess_token(String access_token) {
+ this.access_token = access_token;
+ }
+
+ public String getRefresh_token() {
+ return refresh_token;
+ }
+
+ public void setRefresh_token(String refresh_token) {
+ this.refresh_token = refresh_token;
+ }
+
+ public List getAud() {
+ return aud;
+ }
+
+ public void setAud(List aud) {
+ this.aud = aud;
+ }
+
+ public String getUser_id() {
+ return user_id;
+ }
+
+ public void setUser_id(String user_id) {
+ this.user_id = user_id;
+ }
+
+ public boolean getSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public List getScope() {
+ return scope;
+ }
+
+ public void setScope(List scope) {
+ this.scope = scope;
+ }
+
+ public String getExp() {
+ return exp;
+ }
+
+ public void setExp(String exp) {
+ this.exp = exp;
+ }
+
+ public String getExpires_in() {
+ return expires_in;
+ }
+
+ public void setExpires_in(String expires_in) {
+ this.expires_in = expires_in;
+ }
+
+ public boolean getIsAppAdmin() {
+ return isAppAdmin;
+ }
+
+ public void setIsAppAdmin(boolean isAppAdmin) {
+ this.isAppAdmin = isAppAdmin;
+ }
+
+ public String getJti() {
+ return jti;
+ }
+
+ public void setJti(String jti) {
+ this.jti = jti;
+ }
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/ResultCode.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/ResultCode.java
new file mode 100644
index 00000000..7756fb5e
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/ResultCode.java
@@ -0,0 +1,23 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+import lombok.Getter;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-05 11:46
+ */
+@Getter
+public enum ResultCode implements StatusCode{
+ SUCCESS(0, "请求成功"),
+ FAILED(403, "请求失败"),
+ VALIDATE_ERROR(1002, "参数校验失败"),
+ RESPONSE_PACK_ERROR(1003, "response返回包装失败");
+
+ private int code;
+ private String msg;
+
+ ResultCode(int code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/ResultVo.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/ResultVo.java
new file mode 100644
index 00000000..67a87b80
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/ResultVo.java
@@ -0,0 +1,52 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+import lombok.Data;
+import lombok.Getter;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-05 11:44
+ */
+@Data
+public class ResultVo {
+ // 状态码
+ private int code;
+
+ // 状态信息
+ private String msg;
+
+ // 返回对象
+ private Object data;
+
+ // 手动设置返回vo
+ public ResultVo(int code, String msg, Object data) {
+ this.code = code;
+ this.msg = msg;
+ this.data = data;
+ }
+
+ // 默认返回成功状态码,数据对象
+ public ResultVo(Object data) {
+ this.code = ResultCode.SUCCESS.getCode();
+ this.msg = ResultCode.SUCCESS.getMsg();
+ this.data = data;
+ }
+
+ // 返回指定状态码,数据对象
+ public ResultVo(StatusCode statusCode, Object data) {
+ this.code = statusCode.getCode();
+ this.msg = statusCode.getMsg();
+ this.data = data;
+ }
+
+ // 只返回状态码
+ public ResultVo(StatusCode statusCode) {
+ this.code = statusCode.getCode();
+ this.msg = statusCode.getMsg();
+ this.data = null;
+ }
+}
+
+
+
+
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/SaveFormModel.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/SaveFormModel.java
new file mode 100644
index 00000000..c3283f39
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/SaveFormModel.java
@@ -0,0 +1,33 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-02 15:16
+ */
+@Data
+@Builder
+@JsonInclude(value= JsonInclude.Include.NON_NULL)
+public class SaveFormModel {
+ /** 审批意见 */
+ //private BizCommentModel approval;
+
+ /** 业务数据对象 */
+ private BizObjectModel bizObject;
+
+ /** 重放验证码 */
+ private String replayToken;
+
+ /** 是否saveBizObject*/
+ private Boolean saveBizObject;
+
+ /** 任务id */
+ private String workItemId;
+ /** 流程编码 */
+ private String workflowCode;
+ /** 流程实例id */
+ private String workflowInstanceId;
+}
\ No newline at end of file
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/StatusCode.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/StatusCode.java
new file mode 100644
index 00000000..e4b43314
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/StatusCode.java
@@ -0,0 +1,13 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+/**
+ * @Author Yinq
+ * @create 2022-08-05 11:46
+ */
+public interface StatusCode {
+
+ public int getCode();
+
+ public String getMsg();
+
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/YunBpmApiRes.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/YunBpmApiRes.java
new file mode 100644
index 00000000..66f19b42
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/YunBpmApiRes.java
@@ -0,0 +1,72 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import org.apache.ibatis.type.Alias;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-02 10:46
+ */
+public class YunBpmApiRes {
+ /** 错误码,成功返回0 */
+ private Integer errcode;
+ /** 提示消息 */
+ private String errmsg;
+ private String traceId;
+ /** 授权code */
+ private String code;
+ /** 返回结果 */
+ private Object data;
+
+ public Integer getErrCode() {
+ return errcode;
+ }
+
+ public void setErrCode(Integer errCode) {
+ this.errcode = errCode;
+ }
+
+ public String getErrMsg() {
+ return errmsg;
+ }
+
+ public void setErrMsg(String errMsg) {
+ this.errmsg = errMsg;
+ }
+
+ public String getTraceId() {
+ return traceId;
+ }
+
+ public void setTraceId(String traceId) {
+ this.traceId = traceId;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ @Override
+ public String toString() {
+ return "YunBpmApiRes{" +
+ "errcode=" + errcode +
+ ", errmsg='" + errmsg + '\'' +
+ ", traceId='" + traceId + '\'' +
+ ", code='" + code + '\'' +
+ ", data=" + data +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/YunBpmApis.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/YunBpmApis.java
new file mode 100644
index 00000000..e224b7a8
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/YunBpmApis.java
@@ -0,0 +1,41 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-02 15:14
+ */
+public class YunBpmApis {
+ /** 获取OAuth Code */
+ public static final String GET_CODE = "/api/login/Authentication/get_code";
+ /** 获取Token */
+ public static final String GET_TOKEN = "/api/login/Authentication/get_token?code=%s&client_secret=%s&client_id=%s&url=%s&redirect_uri=%s";
+ /** 获取重放Token */
+ public static final String GET_REPLAY_TOKEN = "/api/api/runtime/form/getReplayToken?access_token=%s";
+
+ /** 保存或修改表单 */
+ public static final String SAVE_OR_UPDATE_FORM = "/api/api/runtime/form/save?access_token=%s";
+ /** 提交待办任务 */
+ public static final String FORM_SUBMIT = "/api/api/runtime/form/submit?access_token=%s";
+ /** 作废流程实例 */
+ public static final String ABORT_INSTANCE = "/api/api/runtime/workflow/abort_instance?access_token=%s&workflowInstanceId=%s";
+ /** 驳回任务 */
+ public static final String REJECT_WORK_ITEM = "/api/api/runtime/workflow/reject_workItem?access_token=%s";
+ /** 下载文件 */
+ public static final String FILE_DOWNLOAD = "/api/api/aliyun/download?access_token=%s&refId=%s";
+ /** 上传文件 */
+ public static final String FILE_UPLOAD = "/api/api/aliyun/upload";
+ /** 转发任务 */
+ public static final String FORWARD_WORKITEM = "/api/api/runtime/workflow/forward_workItem?access_token=%s";
+ /** 根据流程实例id获取审批记录列表 */
+ public static final String LIST_WORKITEM_APPROVALS = "/api/api/runtime/workflow/list_workitem_approvals?access_token=%s&workflowInstanceId=%s";
+ /** 通知任务设置已阅 */
+ public static final String UPDATE_CIRCULATE_READED = "/api/api/runtime/workflow/update_circulate_readed?access_token=%s";
+ /** 查询物料信息 */
+ public static final String SELECT_MATERIAL_DESP = "/api/public/api/xmzlwt/selectMaterialDesp?materialCode=%s";
+ /** 我的待办 */
+ public static final String SEARCH_WORKITEMS = "/api/api/runtime/workflow/search_workitems?workflowCode=%s&access_token=%s&size=100000";
+ /** 我的已办 */
+ public static final String FINISHED_WORKITEMS = "/api/api/runtime/workflow/list_finished_workitems?workflowCode=%s&access_token=%s&size=100000";
+ /** 我的提交 */
+ public static final String MY_INSTANCES = "/api/api/runtime/workflow/list_my_instances?workflowCode=%s&access_token=%s&size=100000&state=PROCESSING";
+}
diff --git a/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/yunBpmConfig.java b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/yunBpmConfig.java
new file mode 100644
index 00000000..6341a5a1
--- /dev/null
+++ b/anomaly/src/main/java/com/foreverwin/mesnac/anomaly/utils/yunBpmConfig.java
@@ -0,0 +1,50 @@
+package com.foreverwin.mesnac.anomaly.utils;
+
+/**
+ * @Author YinQ
+ * @create 2022-08-02 10:36
+ */
+public class yunBpmConfig {
+
+ public static final String userName = "zhangzy";
+ public static final String passWord = "123456";
+
+ public static final String apiBaseUrl = "http://yunbpmcs.mesnac.com:8080";
+ /**
+ * 上传附件url
+ */
+ public static final String urlStr = "http://yunbpmcs.mesnac.com:8080/api/api/aliyun/upload";
+ public static final String clientSecret = "c31b32364ce19ca8fcd150a417ecce58";
+ public static final String clientId = "api";
+ /**
+ * 部门Id
+ */
+ public static final String deptId = "ff808081785ec88301788183073b0b2b";
+ /**
+ * 表单Code、工作流Code
+ */
+ public static final String workCode = "manufacture_cores";
+ /**
+ * 成功代码
+ */
+ public static final Integer SUCCESS_CODE = 200;
+ /**
+ * bpm向mes通信秘钥
+ */
+ public static final String secretKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb3JwSWQiOm51bGwsInVzZXJfbmFtZSI6InpoYW5nenkiLCJtb2JpbGUiOmZhbHNlLCJpc0FkbWluIjpmYWxzZSwiYXV0aG9yaXRpZXMiOlsiVVNFUiIsIkFVVEhfU1lTVEVNX01BTkFHRSJdLCJjbGllbnRfaWQiOiJhcGkiLCJhdWQiOlsiYXBpIl0sInVzZXJfaWQiOiJiZDMzZWQ3MmI1NWU0YTMyODBlZjI3OTgxNjNkYjA2OSIsInNjb3BlIjpbInJlYWQiXSwiYXRpIjoiYTE2YWI0NzMtZTA5MC00Y2M1LWJjNzktYTNjNDc4YWFlNWQ2IiwiZXhwIjoxNjU5NTE2NDkxLCJpc0FwcEFkbWluIjpmYWxzZSwianRpIjoiMDhlNTU3OGYtNTdjOS00YTRkLTkzZWEtNzUyOGMxODNjZDdjIn0.LwTWHq1DS6NK0zbrbaQMS11I6sNmSBS3JN-QsjNH-lJCWg0voXwZ3MWEvr4S-DDOjdjeQRmhbtW5uxDZp4o3rwYRSg4sizoqStGmulqjEvjAdwbF-EzDChGdL8bWUYiWL9wWn0JP9-vBBkUei74H-By8vvSzB6CuJxr6CF1G4bAyBUTFFKzQovnRuiy9cqhXARe2rUi0lPQrOy7aFXX0V8NrwgUAJJxRdMR4COF9htjifD0aQwRtRvuuOtRuIuWPY0rZPtA161zQEwlp6owvccpNnRbgVj2SSHl8Jx89f5vgidWRjHLxxiY_j4toCj40-mHg7lI3YQWhDszI7Qnb0Q";
+
+
+
+
+ public static String getApiBaseUrl() {
+ return apiBaseUrl;
+ }
+
+ public static String getClientSecret() {
+ return clientSecret;
+ }
+
+ public static String getClientId() {
+ return clientId;
+ }
+}