templateParams;
+
+ @Schema(description = "短信 API 模板编号")
+ private String apiTemplateId;
+
+ @Schema(description = "手机号", example = "13800138000")
+ private String mobile;
+
+ @Schema(description = "用户编号", example = "1024")
+ private Long userId;
+
+ @Schema(description = "用户类型")
+ private Integer userType;
+
+ @Schema(description = "发送状态")
+ private Integer sendStatus;
+
+ @Schema(description = "发送时间")
+ private LocalDateTime sendTime;
+
+ @Schema(description = "发送结果编码")
+ private String apiSendCode;
+
+ @Schema(description = "发送结果信息")
+ private String apiSendMsg;
+
+ @Schema(description = "发送请求ID")
+ private String apiRequestId;
+
+ @Schema(description = "发送序列号")
+ private String apiSerialNo;
+
+ @Schema(description = "接收状态")
+ private Integer receiveStatus;
+
+ @Schema(description = "接收时间")
+ private LocalDateTime receiveTime;
+
+ @Schema(description = "接收结果编码")
+ private String apiReceiveCode;
+
+ @Schema(description = "接收结果信息")
+ private String apiReceiveMsg;
+
+}
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/DictTypeConstants.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/DictTypeConstants.java
index e8b5038f..a913df2b 100644
--- a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/DictTypeConstants.java
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/DictTypeConstants.java
@@ -23,4 +23,6 @@ public interface DictTypeConstants {
String SMS_SEND_STATUS = "system_sms_send_status"; // 短信发送状态
String SMS_RECEIVE_STATUS = "system_sms_receive_status"; // 短信接收状态
+ String DEPT_EXTERNAL_SYSTEM = "system_dept_external_system"; // 部门外部系统标识
+
}
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/ErrorCodeConstants.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/ErrorCodeConstants.java
index aaef27c3..8178c53e 100644
--- a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/ErrorCodeConstants.java
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/ErrorCodeConstants.java
@@ -107,6 +107,7 @@ public interface ErrorCodeConstants {
ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1_002_011_000, "短信渠道不存在");
ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1_002_011_001, "短信渠道不处于开启状态,不允许选择");
ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1_002_011_002, "无法删除,该短信渠道还有短信模板");
+ ErrorCode SMS_CHANNEL_BALANCE_UNSUPPORTED = new ErrorCode(1_002_011_003, "该短信渠道不支持余额查询");
// ========== 短信模板 1-002-012-000 ==========
ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_012_000, "短信模板不存在");
@@ -120,6 +121,7 @@ public interface ErrorCodeConstants {
ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1_002_013_000, "手机号不存在");
ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_013_001, "模板参数({})缺失");
ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_013_002, "短信模板不存在");
+ ErrorCode SMS_CALLBACK_SIGN_INVALID = new ErrorCode(1_002_013_100, "短信回调签名校验失败");
// ========== 短信验证码 1-002-014-000 ==========
ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/dept/ExternalPlatformEnum.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/dept/ExternalPlatformEnum.java
new file mode 100644
index 00000000..cabd786b
--- /dev/null
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/dept/ExternalPlatformEnum.java
@@ -0,0 +1,32 @@
+package com.zt.plat.module.system.enums.dept;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 外部系统 / 平台枚举
+ *
+ * 与字典类型 {@code system_dept_external_system} 对应,用于声明常用的平台标识,便于代码与前端字典对齐。
+ */
+@AllArgsConstructor
+@Getter
+public enum ExternalPlatformEnum {
+
+ ERP("ERP", "企业资源计划"),
+ IWORK("IWORK", "iWork 同步");
+
+ private final String code;
+ private final String label;
+
+ public static boolean isValid(String code) {
+ if (code == null) {
+ return false;
+ }
+ for (ExternalPlatformEnum item : values()) {
+ if (item.code.equalsIgnoreCase(code.trim())) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/sms/SmsSendApiImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/sms/SmsSendApiImpl.java
index 52a4ba82..b9232c13 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/sms/SmsSendApiImpl.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/sms/SmsSendApiImpl.java
@@ -1,7 +1,10 @@
package com.zt.plat.module.system.api.sms;
import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.system.api.sms.dto.log.SmsLogRespDTO;
import com.zt.plat.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
+import com.zt.plat.module.system.service.sms.SmsLogService;
import com.zt.plat.module.system.service.sms.SmsSendService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
@@ -16,6 +19,8 @@ public class SmsSendApiImpl implements SmsSendApi {
@Resource
private SmsSendService smsSendService;
+ @Resource
+ private SmsLogService smsLogService;
@Override
public CommonResult sendSingleSmsToAdmin(SmsSendSingleToUserReqDTO reqDTO) {
@@ -29,4 +34,9 @@ public class SmsSendApiImpl implements SmsSendApi {
reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
}
+ @Override
+ public CommonResult getSmsLog(Long id) {
+ return success(BeanUtils.toBean(smsLogService.getSmsLog(id), SmsLogRespDTO.class));
+ }
+
}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java
index 94a755e8..a850f311 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java
@@ -23,6 +23,15 @@ public class DeptSaveReqVO {
@Size(max = 50, message = "部门编码长度不能超过 50 个字符")
private String code;
+ @Schema(description = "外部系统标识,用于建立编码映射", example = "ERP")
+ private String externalSystemCode;
+
+ @Schema(description = "外部系统组织编码,用于建立映射", example = "ERP-001")
+ private String externalDeptCode;
+
+ @Schema(description = "外部系统组织名称", example = "ERP总部")
+ private String externalDeptName;
+
@Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ZT")
@NotBlank(message = "部门名称不能为空")
@Size(max = 30, message = "部门名称长度不能超过 30 个字符")
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/IWorkIntegrationController.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/IWorkIntegrationController.java
index e69863fe..b5a63c35 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/IWorkIntegrationController.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/IWorkIntegrationController.java
@@ -12,6 +12,8 @@ import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -45,6 +47,20 @@ public class IWorkIntegrationController {
return success(integrationService.acquireToken(reqVO));
}
+ @PostMapping("/oa/token")
+ @Operation(summary = "透传获取 OA Token")
+ public ResponseEntity acquireOaToken(@Valid @RequestBody IWorkOaTokenReqVO reqVO) {
+ IWorkOaRawResponse resp = integrationService.getOaToken(reqVO);
+ return buildOaResponse(resp);
+ }
+
+ @PostMapping("/oa/check")
+ @Operation(summary = "透传校验 OA Token")
+ public ResponseEntity checkOaToken(@Valid @RequestBody IWorkOaCheckTokenReqVO reqVO) {
+ IWorkOaRawResponse resp = integrationService.checkOaToken(reqVO);
+ return buildOaResponse(resp);
+ }
+
@PostMapping("/user/resolve")
@Operation(summary = "根据外部标识获取 iWork 用户编号")
public CommonResult resolveUser(@Valid @RequestBody IWorkUserInfoReqVO reqVO) {
@@ -97,30 +113,6 @@ public class IWorkIntegrationController {
return success(orgRestService.listUsers(reqVO));
}
-// @PostMapping("/hr/subcompany/sync")
-// @Operation(summary = "同步分部信息至 iWork")
-// public CommonResult syncSubcompanies(@Valid @RequestBody IWorkOrgSyncReqVO reqVO) {
-// return success(orgRestService.syncSubcompanies(reqVO));
-// }
-//
-// @PostMapping("/hr/department/sync")
-// @Operation(summary = "同步部门信息至 iWork")
-// public CommonResult syncDepartments(@Valid @RequestBody IWorkOrgSyncReqVO reqVO) {
-// return success(orgRestService.syncDepartments(reqVO));
-// }
-//
-// @PostMapping("/hr/job-title/sync")
-// @Operation(summary = "同步岗位信息至 iWork")
-// public CommonResult syncJobTitles(@Valid @RequestBody IWorkOrgSyncReqVO reqVO) {
-// return success(orgRestService.syncJobTitles(reqVO));
-// }
-//
-// @PostMapping("/hr/user/sync")
-// @Operation(summary = "同步人员信息至 iWork")
-// public CommonResult syncUsers(@Valid @RequestBody IWorkOrgSyncReqVO reqVO) {
-// return success(orgRestService.syncUsers(reqVO));
-// }
-
// ----------------- 同步到本地 -----------------
@PostMapping("/hr/departments/full-sync")
@@ -146,4 +138,20 @@ public class IWorkIntegrationController {
public CommonResult fullSyncUsers(@Valid @RequestBody IWorkFullSyncReqVO reqVO) {
return success(syncService.fullSyncUsers(reqVO));
}
+
+ private ResponseEntity buildOaResponse(IWorkOaRawResponse resp) {
+ if (resp == null) {
+ return ResponseEntity.internalServerError().body("OA 响应为空");
+ }
+ HttpHeaders headers = new HttpHeaders();
+ if (resp.getHeaders() != null) {
+ resp.getHeaders().forEach(headers::add);
+ }
+ if (resp.getContentType() != null) {
+ headers.setContentType(resp.getContentType());
+ }
+ return ResponseEntity.status(resp.getStatusCode())
+ .headers(headers)
+ .body(resp.getBody());
+ }
}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkFileCallbackReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkFileCallbackReqVO.java
index 58519d84..12a5d2b5 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkFileCallbackReqVO.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkFileCallbackReqVO.java
@@ -18,4 +18,7 @@ public class IWorkFileCallbackReqVO {
@Schema(description = "文件名称,可选", example = "合同附件.pdf")
private String fileName;
+
+ @Schema(description = "OA 单点下载使用的 ssoToken,可选", example = "6102A7C13F09DD6B1AF06CDA0E479AC8...")
+ private String ssoToken;
}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkHrSyncRespVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkHrSyncRespVO.java
deleted file mode 100644
index c0e17393..00000000
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkHrSyncRespVO.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
-
-import com.fasterxml.jackson.annotation.JsonAnyGetter;
-import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * iWork 人力同步响应。
- */
-@Data
-@Schema(description = "iWork 人力同步响应")
-public class IWorkHrSyncRespVO {
-
- @Schema(description = "响应码")
- private String code;
-
- @Schema(description = "提示信息")
- private String message;
-
- @Schema(description = "是否成功")
- private boolean success;
-
- @Schema(description = "同步结果明细")
- private List result;
-
- @Data
- @Schema(description = "同步结果项")
- public static class SyncResult {
-
- @Schema(description = "操作动作 add/update/delete")
- @JsonProperty("@action")
- private String action;
-
- @Schema(description = "外部编码")
- @JsonProperty("code")
- private String code;
-
- @Schema(description = "执行结果 success/fail")
- @JsonProperty("result")
- private String result;
-
- @Schema(description = "是否成功")
- @JsonProperty("success")
- private Boolean success;
-
- @Schema(description = "失败描述")
- @JsonProperty("message")
- private String message;
-
- @JsonIgnore
- private Map attributes;
-
- @JsonAnySetter
- public void putAttribute(String key, Object value) {
- if (attributes == null) {
- attributes = new LinkedHashMap<>();
- }
- attributes.put(key, value);
- }
-
- @JsonAnyGetter
- public Map any() {
- return attributes == null ? Collections.emptyMap() : attributes;
- }
- }
-}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaCheckTokenReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaCheckTokenReqVO.java
new file mode 100644
index 00000000..be77880b
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaCheckTokenReqVO.java
@@ -0,0 +1,16 @@
+package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * 校验 OA Token 的请求参数。
+ */
+@Data
+public class IWorkOaCheckTokenReqVO {
+
+ @Schema(description = "需要校验的 OA token")
+ @NotBlank(message = "token 不能为空")
+ private String token;
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaRawResponse.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaRawResponse.java
new file mode 100644
index 00000000..45b5fc53
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaRawResponse.java
@@ -0,0 +1,27 @@
+package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.http.MediaType;
+
+import java.util.Map;
+
+/**
+ * 封装 OA 接口的原始返回,用于透传 HTTP 状态与 body。
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IWorkOaRawResponse {
+
+ private int statusCode;
+
+ private String body;
+
+ private MediaType contentType;
+
+ private Map headers;
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaTokenReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaTokenReqVO.java
new file mode 100644
index 00000000..bfbd488f
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOaTokenReqVO.java
@@ -0,0 +1,19 @@
+package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * 获取 OA Token 的请求参数。
+ */
+@Data
+public class IWorkOaTokenReqVO {
+
+ @Schema(description = "OA 登录账号 loginid", example = "zixun004")
+ @NotBlank(message = "loginId 不能为空")
+ private String loginId;
+
+ @Schema(description = "应用 appid,未填则使用配置默认值", example = "a17ca6ca-88b0-463e-bffa-7995086bf225")
+ private String appId;
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOrgSyncReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOrgSyncReqVO.java
deleted file mode 100644
index 52120368..00000000
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/integration/iwork/vo/IWorkOrgSyncReqVO.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
-import lombok.Data;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * 同步 iWork 人力组织信息的请求。
- */
-@Data
-public class IWorkOrgSyncReqVO {
-
- @Schema(description = "同步数据集合,将被序列化为 data 传给 iWork", requiredMode = Schema.RequiredMode.REQUIRED)
- @NotEmpty(message = "同步数据不能为空")
- private List