diff --git a/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/client/IoaClient.java b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/client/IoaClient.java
new file mode 100644
index 0000000..3809220
--- /dev/null
+++ b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/client/IoaClient.java
@@ -0,0 +1,149 @@
+package com.chinaunicom.mall.ebtp.extend.ioa.client;
+
+import com.chinaunicom.mall.ebtp.extend.ioa.entity.Flow;
+import com.chinaunicom.mall.ebtp.extend.ioa.entity.IoaBaseResponseDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * IOA待办待阅服务
+ * 创建待办、修改状态、删除待办
+ */
+@FeignClient(name = "ioa-service", url = "${spring.ioa.url}")
+@RequestMapping("/api/task")
+public interface IoaClient {
+
+ /**
+ * 创建待办待阅(批量最多支持100个)
+ * POST 测试环境-创建待办待阅
+ * header:
+ * app_id: ${spring.ioa.app_id}
+ * app_secret: ${spring.ioa.app_secret}
+ 参数body:
+ {
+ "flowId": "1639178577644933121",
+ "flowName": "请假流程",
+ "bizInstanceId": "489482",
+ "createDate": 1749621480,
+ "creatorName": "张三",
+ // "creatorId": "zyhybj-zougaoming",
+ "creatorId": "1",
+ "tasks": [
+ {
+ "bizTaskId": "ABC100003",
+ "workNum": "ABC100003",
+ "taskType": 0,
+ "businessMode": "QJ",
+ // "handler": "30028727",
+ "handler": "1",
+ "formUrl": "https://feikong.coscoshipping.com/hec_prod/weixin#####7A182",
+ "title": "张三请假申请--领导审批...",
+ "priority": 1,
+ "ext": {
+ "axx": "1cd2",
+ "bxx": "2aa"
+ }
+ }
+ ]
+ }
+ 返回: 成功没有code, 失败有对应的code, 成功status为true,失败status为false
+ 成功:
+ {
+ "msg_ids": [
+ "1935498644363452416"
+ ],
+ "status": true
+ }
+ 失败:
+ {
+ "code": "T_12",
+ "msg_ids": [
+ "1935498644363452416"
+ ],
+ "status": false
+ }
+ *
+ * @param flow 请求体参数,结构见文档
+ * @param appId app_id请求头
+ * @param appSecret app_secret请求头
+ * @return 结果Map或自定义响应对象
+ */
+ @PostMapping("/create")
+ IoaBaseResponseDTO createTask(
+ @RequestHeader("app_id") String appId,
+ @RequestHeader("app_secret") String appSecret,
+ @RequestBody Flow flow);
+
+ /**
+ * 修改待办待阅状态(批量最多支持100个)
+ * POST 测试环境-修改待办待阅
+ * header:
+ * app_id: ${spring.ioa.app_id}
+ * app_secret: ${spring.ioa.app_secret}
+ 参数body:
+ ["ABC100002"]
+ 返回: 成功没有code, 失败有对应的code, 成功status为true,失败status为false
+ 成功:
+ {
+ "msg_ids": [
+ "1935498644363452416"
+ ],
+ "status": true
+ }
+ 失败:
+ {
+ "code": "T_12",
+ "msg_ids": [
+ "1935498644363452416"
+ ],
+ "status": false
+ }
+ *
+ * @param bizTaskId 请求体参数,包含bizTaskId列表
+ * @return 结果Map或自定义响应对象
+ */
+ @PostMapping("/update")
+ IoaBaseResponseDTO updateTask(
+ @RequestHeader("app_id") String appId,
+ @RequestHeader("app_secret") String appSecret,
+ @RequestBody List bizTaskId);
+
+ /**
+ * 批量删除待办/待阅/已办/已阅(最多支持100个)
+ * POST 测试环境-撤回待办待阅
+ * header:
+ * app_id: ${spring.ioa.app_id}
+ * app_secret: ${spring.ioa.app_secret}
+ 参数body:
+ ["ABC100002"]
+ 返回: 成功没有code, 失败有对应的code, 成功status为true,失败status为false
+ 成功:
+ {
+ "msg_ids": [
+ "1935498644363452416"
+ ],
+ "status": true
+ }
+ 失败:
+ {
+ "code": "T_12",
+ "msg_ids": [
+ "1935498644363452416"
+ ],
+ "status": false
+ }
+ * @param bizTaskId 请求体参数,包含bizTaskId列表
+ * @return 结果Map或自定义响应对象
+ */
+ @PostMapping("/delete")
+ IoaBaseResponseDTO deleteTask(
+ @RequestHeader("app_id") String appId,
+ @RequestHeader("app_secret") String appSecret,
+ @RequestBody List bizTaskId);
+}
\ No newline at end of file
diff --git a/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/constant/IoaErrorEnum.java b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/constant/IoaErrorEnum.java
new file mode 100644
index 0000000..88bf565
--- /dev/null
+++ b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/constant/IoaErrorEnum.java
@@ -0,0 +1,91 @@
+package com.chinaunicom.mall.ebtp.extend.ioa.constant;
+
+/**
+ * IOA错误枚举类
+ * 定义了IOA系统中可能出现的各种错误类型及其描述信息。
+ * 每个错误类型都有一个唯一的代码和对应的描述。
+ */
+public enum IoaErrorEnum {
+ E_10("E_10", "系统异常"),
+ A_10("A_10", "没有权限记录"),
+ A_11("A_11", "权限被禁用"),
+ A_12("A_12", "权限已过期"),
+ A_13("A_13", "key secret错误"),
+ A_14("A_14", "校验权限异常"),
+ A_15("A_15", "不允许该ip访问"),
+ A_16("A_16", "限流处理异常"),
+ A_17("A_17", "报文重复"),
+ A_18("A_18", "请求被限流"),
+ H_10("H_10", "头为空"),
+ H_11("H_11", "头的必输项键值为空"),
+ H_12("H_12", "不是有效的contentType"),
+ H_13("H_13", "不是post请求"),
+ B_10("B_10", "体为空"),
+ B_11("B_11", "体太大"),
+ B_13("B_13", "批量消息过大"),
+ M_10("M_10", "构建Message对象异常"),
+ M_11("M_11", "请求报文转换成接收数据实体对象失败"),
+ M_12("M_12", "请求报文中不包含主题"),
+ M_13("M_13", "请求报文中不包含内容"),
+ M_14("M_14", "请求报文中扩展字段过多"),
+ M_141("M_141", "扩展字段键非法"),
+ M_142("M_142", "扩展字段值非法"),
+ M_15("M_15", "请求报文中目标渠道为空"),
+ M_16("M_16", "请求报文中目标渠道中的编码为空"),
+ M_17("M_17", "请求报文中目标渠道中的接收人列表为空"),
+ M_18("M_18", "请求报文中目标渠道中的接收数据校验格式失败"),
+ M_19("M_19", "请求报文中中转换后的消息对象大小为空"),
+ M_20("M_20", "请求报文中不包含消息ID"),
+ M_201("M_201", "撤销的MSG_ID没有在库中找到"),
+ M_21("M_21", "校验Message解析前置决断json异常"),
+ M_22("M_22", "Message执行前置决断失败"),
+ M_31("M_31", "校验Message解析后置决断json异常"),
+ M_32("M_32", "Message执行后置决断失败"),
+ M_33("M_33", "前置决断类型配置错误"),
+ M_34("M_34", "后置决断类型配置错误"),
+ M_41("M_41", "校验Message指定渠道失败. 请求报文不存在任何渠道编码配置"),
+ M_42("M_42", "校验Message指定渠道失败. 当前appid没有配置任何渠道数据"),
+ M_43("M_43", "校验Message指定渠道失败. 当前appid里面配置的渠道列表数据不包含请求报文配置的渠道"),
+ M_44("M_44", "校验Message指定渠道失败. 当前报文中传递的渠道编码在渠道表中对应的动态表单json转换成对象失败"),
+ M_51("M_51", "校验Message解析回执json异常"),
+ M_61("M_61", "Message执行渠道失败"),
+ P_10("P_10", "数据生产异常"),
+ C_10("C_10", "数据消费异常"),
+ M_A1("M_A1", "Message执行回执失败"),
+ M_E1("M_E1", "数据处理未知异常"),
+ T_10("T_10", "iTask不能识别的类型"),
+ T_11("T_11", "task接收对象实体校验失败"),
+ T_12("T_12", "task单据在库中已存在"),
+ T_13("T_13", "task单据在库中不存在"),
+ T_14("T_14", "task单据重复"),
+ T_15("T_15", "task单据数据校验异常"),
+ T_16("T_16", "数据值不合理"),
+ T_17("T_17", "不允许操作. 该单据不允许修改状态,因为状态不允许"),
+ S_10("S_10", "查询参数异常");
+
+ private final String code;
+ private final String desc;
+
+ IoaErrorEnum(String code, String desc) {
+ this.code = code;
+ this.desc = desc;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public static String getDescByCode(String code) {
+ for (IoaErrorEnum e : IoaErrorEnum.values()) {
+ if (e.getCode().equals(code)) {
+ return e.getDesc();
+ }
+ }
+ return "未知错误";
+ }
+}
+
diff --git a/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/controller/IoaController.java b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/controller/IoaController.java
new file mode 100644
index 0000000..098576d
--- /dev/null
+++ b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/controller/IoaController.java
@@ -0,0 +1,81 @@
+package com.chinaunicom.mall.ebtp.extend.ioa.controller;
+
+import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
+import com.chinaunicom.mall.ebtp.common.util.PropertyUtils;
+import com.chinaunicom.mall.ebtp.extend.ioa.constant.IoaErrorEnum;
+import com.chinaunicom.mall.ebtp.extend.ioa.entity.Flow;
+import com.chinaunicom.mall.ebtp.extend.ioa.entity.IoaBaseResponseDTO;
+import com.chinaunicom.mall.ebtp.extend.ioa.service.IoaService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Slf4j
+@RestController
+@RequestMapping("/ioa/task")
+public class IoaController {
+
+ @Autowired
+ private IoaService ioaService;
+
+ private static final String IOA_ERRER_DESC = "iOA错误代码/描述: ";
+
+ /**
+ * 创建待办
+ */
+ @PostMapping("/create")
+ public BaseResponse createTask(@RequestBody Flow flow) {
+ // 判断并设置默认值
+ if (StringUtils.isBlank(flow.getFlowId())) {
+ flow.setFlowId(PropertyUtils.getSnowflakeId());
+ }
+ if (StringUtils.isBlank(flow.getFlowName())) {
+ flow.setFlowName(PropertyUtils.getSnowflakeId());
+ }
+ if (StringUtils.isBlank(flow.getBizInstanceId())) {
+ flow.setBizInstanceId(PropertyUtils.getSnowflakeId());
+ }
+ if (flow.getCreateDate() == null || flow.getCreateDate() == 0L) {
+ flow.setCreateDate(System.currentTimeMillis());
+ }
+ IoaBaseResponseDTO ioaBaseResponseDTO = ioaService.createTask(flow);
+ if (!ioaBaseResponseDTO.isStatus()) {
+ String code = ioaBaseResponseDTO.getCode();
+ String message = IoaErrorEnum.getDescByCode(code);
+ // message: "iOA错误代码/描述: T_12task单据在库中已存在"
+ return BaseResponse.fail(IOA_ERRER_DESC + code + message, ioaBaseResponseDTO.getMsg_ids());
+ }
+ return BaseResponse.success(ioaBaseResponseDTO.getMsg_ids());
+ }
+
+ /**
+ * 修改待办
+ */
+ @PostMapping("/update")
+ public BaseResponse updateTask(@RequestBody List bizTaskIds) {
+ IoaBaseResponseDTO ioaBaseResponseDTO = ioaService.updateTask(bizTaskIds);
+ if (!ioaBaseResponseDTO.isStatus()) {
+ String code = ioaBaseResponseDTO.getCode();
+ String message = IoaErrorEnum.getDescByCode(code);
+ return BaseResponse.fail(IOA_ERRER_DESC + code + message, ioaBaseResponseDTO.getMsg_ids());
+ }
+ return BaseResponse.success(ioaBaseResponseDTO.getMsg_ids());
+ }
+
+ /**
+ * 撤回待办
+ */
+ @PostMapping("/delete")
+ public BaseResponse deleteTask(@RequestBody List bizTaskIds) {
+ IoaBaseResponseDTO ioaBaseResponseDTO = ioaService.deleteTask(bizTaskIds);
+ if (!ioaBaseResponseDTO.isStatus()) {
+ String code = ioaBaseResponseDTO.getCode();
+ String message = IoaErrorEnum.getDescByCode(code);
+ return BaseResponse.fail(IOA_ERRER_DESC + code + message, ioaBaseResponseDTO.getMsg_ids());
+ }
+ return BaseResponse.success(ioaBaseResponseDTO.getMsg_ids());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/Flow.java b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/Flow.java
new file mode 100644
index 0000000..814cbc5
--- /dev/null
+++ b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/Flow.java
@@ -0,0 +1,38 @@
+package com.chinaunicom.mall.ebtp.extend.ioa.entity;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Flow {
+ /**
+ * 流程ID (不传就是雪花ID)
+ */
+ private String flowId;
+ /**
+ * 流程名称 (不传就是雪花ID)
+ */
+ private String flowName;
+ /**
+ * 业务流程实例 id,流程实例在业务系统的唯一标识号 (不传就是雪花ID)
+ */
+ private String bizInstanceId;
+ /**
+ * 创建时间,时间戳 (不传就是当前系统时间)
+ */
+ private Long createDate;
+ /**
+ * 创建人姓名
+ */
+ private String creatorName;
+ /**
+ * 创建人id
+ */
+ private String creatorId;
+ /**
+ * 待办待阅数据集合,最多100
+ */
+ private List tasks;
+
+}
diff --git a/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/IoaBaseResponseDTO.java b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/IoaBaseResponseDTO.java
new file mode 100644
index 0000000..9dec434
--- /dev/null
+++ b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/IoaBaseResponseDTO.java
@@ -0,0 +1,20 @@
+package com.chinaunicom.mall.ebtp.extend.ioa.entity;
+
+import lombok.Data;
+
+/**
+ *
+ {
+ "code": "T_12",
+ "msg_ids": [
+ "1935498644363452416"
+ ],
+ "status": false
+ }
+ */
+@Data
+public class IoaBaseResponseDTO {
+ private String code;
+ private String[] msg_ids;
+ private boolean status;
+}
diff --git a/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/Task.java b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/Task.java
new file mode 100644
index 0000000..50f7786
--- /dev/null
+++ b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/entity/Task.java
@@ -0,0 +1,46 @@
+package com.chinaunicom.mall.ebtp.extend.ioa.entity;
+
+import lombok.Data;
+
+import java.util.Map;
+
+@Data
+public class Task {
+ /**
+ * 业务待办id,待办待阅在业务系统的唯一标识 id
+ */
+ private String bizTaskId;
+ /**
+ * 工单号,工单在业务系统的唯一标识
+ */
+ private String workNum;
+ /**
+ * 单据类型,0:待办,1:待阅
+ */
+ private Integer taskType;
+ /**
+ * 业务类型
+ */
+ private String businessMode;
+ /**
+ * 当前处理人的用户ID
+ */
+ private String handler;
+ /**
+ * 业务系统提供工单处理页面的Url
+ */
+ private String formUrl;
+ /**
+ * 工单标题
+ */
+ private String title;
+ /**
+ * 优先级别,0:低,1:中,2:高
+ */
+ private Integer priority;
+ /**
+ * 扩展信息JSON,最多50个元素,键[a-z]{1,30},值<100字符
+ */
+ private Map ext;
+
+}
diff --git a/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/service/IoaService.java b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/service/IoaService.java
new file mode 100644
index 0000000..e3a39a8
--- /dev/null
+++ b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/service/IoaService.java
@@ -0,0 +1,30 @@
+package com.chinaunicom.mall.ebtp.extend.ioa.service;
+
+import com.chinaunicom.mall.ebtp.extend.ioa.entity.Flow;
+import com.chinaunicom.mall.ebtp.extend.ioa.entity.IoaBaseResponseDTO;
+
+import java.util.List;
+import java.util.Map;
+
+public interface IoaService {
+ /**
+ * 创建待办待阅(批量)
+ * @param flow 流程对象
+ * @return 结果Map
+ */
+ IoaBaseResponseDTO createTask(Flow flow);
+
+ /**
+ * 修改待办待阅状态(批量)
+ * @param bizTaskIds 待办id列表
+ * @return 结果Map
+ */
+ IoaBaseResponseDTO updateTask(List bizTaskIds);
+
+ /**
+ * 撤回/删除待办(批量)
+ * @param bizTaskIds 待办id列表
+ * @return 结果Map
+ */
+ IoaBaseResponseDTO deleteTask(List bizTaskIds);
+}
diff --git a/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/service/impl/IoaServiceImpl.java b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/service/impl/IoaServiceImpl.java
new file mode 100644
index 0000000..22bd4c5
--- /dev/null
+++ b/src/main/java/com/chinaunicom/mall/ebtp/extend/ioa/service/impl/IoaServiceImpl.java
@@ -0,0 +1,39 @@
+package com.chinaunicom.mall.ebtp.extend.ioa.service.impl;
+
+import com.chinaunicom.mall.ebtp.extend.ioa.client.IoaClient;
+import com.chinaunicom.mall.ebtp.extend.ioa.entity.Flow;
+import com.chinaunicom.mall.ebtp.extend.ioa.entity.IoaBaseResponseDTO;
+import com.chinaunicom.mall.ebtp.extend.ioa.service.IoaService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class IoaServiceImpl implements IoaService {
+
+ @Autowired
+ private IoaClient ioaClient;
+
+ @Value("${spring.ioa.app_id}")
+ private String appId;
+
+ @Value("${spring.ioa.app_secret}")
+ private String appSecret;
+
+ @Override
+ public IoaBaseResponseDTO createTask(Flow flow) {
+ return ioaClient.createTask(appId, appSecret, flow);
+ }
+
+ @Override
+ public IoaBaseResponseDTO updateTask(List bizTaskIds) {
+ return ioaClient.updateTask(appId, appSecret, bizTaskIds);
+ }
+
+ @Override
+ public IoaBaseResponseDTO deleteTask(List bizTaskIds) {
+ return ioaClient.deleteTask(appId, appSecret, bizTaskIds);
+ }
+}