1. 清理 iwork 同步的旧逻辑

This commit is contained in:
chenbowen
2025-12-02 15:08:47 +08:00
parent ee9bc438b5
commit b7ad25e91c
9 changed files with 45 additions and 232 deletions

View File

@@ -1,23 +0,0 @@
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
/**
* 传递给 iWork 的单条明细记录。
*/
@Data
public class IWorkDetailRecordVO {
@Schema(description = "记录序号,从 0 开始", example = "0")
private Integer recordOrder;
@Schema(description = "明细字段列表")
@NotEmpty(message = "明细字段不能为空")
@Valid
private List<IWorkFormFieldVO> fields;
}

View File

@@ -1,25 +0,0 @@
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
/**
* iWork 流程请求中的明细表定义。
*/
@Data
public class IWorkDetailTableVO {
@Schema(description = "表名", example = "formtable_main_26_dt1")
@NotBlank(message = "明细表名不能为空")
private String tableDBName;
@Schema(description = "明细记录集合")
@NotEmpty(message = "明细记录不能为空")
@Valid
private List<IWorkDetailRecordVO> records;
}

View File

@@ -1,20 +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.NotBlank;
import lombok.Data;
/**
* 提交给 iWork 的单个表单字段。
*/
@Data
public class IWorkFormFieldVO {
@Schema(description = "字段名", example = "sqr")
@NotBlank(message = "字段名不能为空")
private String fieldName;
@Schema(description = "字段值", example = "张三")
@NotBlank(message = "字段值不能为空")
private String fieldValue;
}

View File

@@ -1,5 +1,6 @@
package com.zt.plat.module.system.controller.admin.integration.iwork.vo; package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -11,12 +12,49 @@ import java.util.Map;
@Data @Data
public class IWorkOperationRespVO { public class IWorkOperationRespVO {
@Schema(description = "iWork 返回的原始数据") @Schema(description = "iWork 返回的原始数据结构")
private Map<String, Object> payload; private Payload payload;
@Schema(description = "是否判断为成功") @Schema(description = "是否判断为成功")
private boolean success; private boolean success;
@Schema(description = "返回提示信息") @Schema(description = "返回提示信息")
private String message; private String message;
@Data
public static class Payload {
@Schema(description = "iWork 返回的业务状态码,例如 SUCCESS")
private String code;
@Schema(description = "iWork 返回的数据体")
private PayloadData data;
@Schema(description = "错误信息对象,通常为空对象")
private Map<String, Object> errMsg;
@Schema(description = "返回失败时的详细信息")
private ReqFailMsg reqFailMsg;
}
@Data
public static class PayloadData {
@Schema(description = "iWork 生成的请求编号 requestid")
@JsonProperty("requestid")
private Long requestId;
}
@Data
public static class ReqFailMsg {
@Schema(description = "失败时的关键参数集合")
private Map<String, Object> keyParameters;
@Schema(description = "失败消息对象")
private Map<String, Object> msgInfo;
@Schema(description = "其他附加参数,例如 doAutoApprove")
private Map<String, Object> otherParams;
}
} }

View File

@@ -1,73 +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.Map;
/**
* 查询 iWork 人力组织信息所需的参数。
*/
@Data
public class IWorkOrgQueryReqVO {
@Schema(description = "当前页码", example = "1")
private Integer curpage;
@Schema(description = "每页条数", example = "10")
private Integer pagesize;
// ================= 分部查询 =================
@Schema(description = "分部编码")
private String subcompanyCode;
@Schema(description = "分部名称")
private String subcompanyName;
// ================= 部门查询 =================
@Schema(description = "部门编码")
private String departmentCode;
@Schema(description = "部门名称")
private String departmentName;
@Schema(description = "所属分部ID")
private String subcompanyId;
// ================= 岗位查询 =================
@Schema(description = "岗位编码")
private String jobTitleCode;
@Schema(description = "岗位名称")
private String jobTitleName;
// ================= 人员查询 =================
@Schema(description = "人员工号")
private String workCode;
@Schema(description = "人员姓名")
private String lastName;
@Schema(description = "所属部门ID")
private String departmentId;
@Schema(description = "所属岗位ID")
private String jobTitleId;
@Schema(description = "人员状态 (0:试用, 1:正式, 2:临时, 3:试用延期, 4:解聘, 5:离职, 6:退休, 7:无效)")
private String status;
@Schema(description = "手机号")
private String mobile;
@Schema(description = "邮箱")
private String email;
@Schema(description = "查询参数(扩展用),将被序列化为 params 传给 iWork")
private Map<String, Object> params;
}

View File

@@ -1,12 +0,0 @@
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 获取 iWork 会话令牌的请求载荷。
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class IWorkTokenApplyReqVO extends IWorkBaseReqVO {
}

View File

@@ -97,11 +97,6 @@ public class IWorkProperties {
*/ */
@Min(value = 1, message = "iWork Token 有效期必须大于 0") @Min(value = 1, message = "iWork Token 有效期必须大于 0")
private long ttlSeconds; private long ttlSeconds;
/**
* Token 过期前提前刷新的秒数。
*/
@Min(value = 0, message = "iWork Token 提前刷新秒数不能为负数")
private long refreshAheadSeconds;
} }
@Data @Data

View File

@@ -20,7 +20,6 @@ import com.zt.plat.module.system.framework.integration.iwork.config.IWorkPropert
import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService; import com.zt.plat.module.system.service.integration.iwork.IWorkIntegrationService;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.*; import okhttp3.*;
import okio.Buffer; import okio.Buffer;
@@ -59,10 +58,6 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
private final FileApi fileApi; private final FileApi fileApi;
private final BusinessFileApi businessFileApi; private final BusinessFileApi businessFileApi;
private final Cache<SessionKey, IWorkSession> sessionCache = Caffeine.newBuilder()
.maximumSize(256)
.build();
private final Cache<String, RegistrationState> registrationCache = Caffeine.newBuilder() private final Cache<String, RegistrationState> registrationCache = Caffeine.newBuilder()
.maximumSize(32) .maximumSize(32)
.build(); .build();
@@ -104,7 +99,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
boolean force = forceRegistration || forceToken; boolean force = forceRegistration || forceToken;
ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, forceRegistration); ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, forceRegistration);
IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, force); IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, force);
IWorkAuthTokenRespVO respVO = new IWorkAuthTokenRespVO(); IWorkAuthTokenRespVO respVO = new IWorkAuthTokenRespVO();
respVO.setAppId(appId); respVO.setAppId(appId);
@@ -124,7 +119,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId()); String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId());
ensureIdentifier(reqVO.getIdentifierKey(), reqVO.getIdentifierValue()); ensureIdentifier(reqVO.getIdentifierKey(), reqVO.getIdentifierValue());
IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken())); IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
Map<String, Object> payload = buildUserPayload(reqVO); Map<String, Object> payload = buildUserPayload(reqVO);
String responseBody = executeJsonRequest(properties.getPaths().getUserInfo(), reqVO.getQueryParams(), appId, session, payload); String responseBody = executeJsonRequest(properties.getPaths().getUserInfo(), reqVO.getQueryParams(), appId, session, payload);
@@ -137,7 +132,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
String appId = resolveAppId(); String appId = resolveAppId();
ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, Boolean.TRUE.equals(reqVO.getForceRefreshToken())); ClientKeyPair clientKeyPair = resolveClientKeyPair(appId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId()); String operatorUserId = resolveOperatorUserId(reqVO.getOperatorUserId());
IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken())); IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
Map<String, Object> payload = buildCreatePayload(reqVO); Map<String, Object> payload = buildCreatePayload(reqVO);
String responseBody = executeFormRequest(properties.getPaths().getCreateWorkflow(), null, appId, session, payload); String responseBody = executeFormRequest(properties.getPaths().getCreateWorkflow(), null, appId, session, payload);
@@ -153,7 +148,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
if (!StringUtils.hasText(reqVO.getRequestId())) { if (!StringUtils.hasText(reqVO.getRequestId())) {
throw ServiceExceptionUtil.exception(IWORK_USER_IDENTIFIER_MISSING); throw ServiceExceptionUtil.exception(IWORK_USER_IDENTIFIER_MISSING);
} }
IWorkSession session = ensureSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken())); IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, Boolean.TRUE.equals(reqVO.getForceRefreshToken()));
Map<String, Object> payload = buildVoidPayload(reqVO); Map<String, Object> payload = buildVoidPayload(reqVO);
String responseBody = executeJsonRequest(properties.getPaths().getVoidWorkflow(), null, appId, session, payload); String responseBody = executeJsonRequest(properties.getPaths().getVoidWorkflow(), null, appId, session, payload);
@@ -308,26 +303,6 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
} }
} }
private IWorkSession ensureSession(String appId, ClientKeyPair clientKeyPair, String operatorUserId, boolean forceRefresh) {
SessionKey key = new SessionKey(appId, operatorUserId);
Instant now = Instant.now();
if (!forceRefresh) {
IWorkSession cached = sessionCache.getIfPresent(key);
if (cached != null && cached.isValid(now, properties.getToken().getRefreshAheadSeconds())) {
return cached;
}
}
synchronized (key.intern()) {
IWorkSession cached = sessionCache.getIfPresent(key);
if (!forceRefresh && cached != null && cached.isValid(now, properties.getToken().getRefreshAheadSeconds())) {
return cached;
}
IWorkSession session = createSession(appId, clientKeyPair, operatorUserId, forceRefresh);
sessionCache.put(key, session);
return session;
}
}
private IWorkSession createSession(String appId, ClientKeyPair clientKeyPair, String operatorUserId, boolean forceRefreshRegistration) { private IWorkSession createSession(String appId, ClientKeyPair clientKeyPair, String operatorUserId, boolean forceRefreshRegistration) {
RegistrationState registration = obtainRegistration(appId, clientKeyPair, forceRefreshRegistration); RegistrationState registration = obtainRegistration(appId, clientKeyPair, forceRefreshRegistration);
String encryptedSecret = encryptWithPublicKey(registration.secret(), registration.spk()); String encryptedSecret = encryptWithPublicKey(registration.secret(), registration.spk());
@@ -651,7 +626,7 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
return respVO; return respVO;
} }
JsonNode node = parseJson(responseBody, IWORK_REMOTE_REQUEST_FAILED); JsonNode node = parseJson(responseBody, IWORK_REMOTE_REQUEST_FAILED);
respVO.setPayload(objectMapper.convertValue(node, MAP_TYPE)); respVO.setPayload(objectMapper.convertValue(node, IWorkOperationRespVO.Payload.class));
respVO.setSuccess(isSuccess(node)); respVO.setSuccess(isSuccess(node));
respVO.setMessage(resolveMessage(node)); respVO.setMessage(resolveMessage(node));
return respVO; return respVO;
@@ -992,46 +967,5 @@ public class IWorkIntegrationServiceImpl implements IWorkIntegrationService {
this.expiresAt = expiresAt; this.expiresAt = expiresAt;
this.spk = spk; this.spk = spk;
} }
private boolean isValid(Instant now, long refreshAheadSeconds) {
Instant refreshThreshold = expiresAt.minusSeconds(Math.max(0L, refreshAheadSeconds));
return refreshThreshold.isAfter(now) && StringUtils.hasText(token) && StringUtils.hasText(encryptedUserId);
}
}
@ToString
private static final class SessionKey {
private final String appId;
private final String operatorUserId;
private SessionKey(String appId, String operatorUserId) {
this.appId = appId;
this.operatorUserId = operatorUserId;
}
private String cacheKey() {
return appId + "::" + operatorUserId;
}
private String intern() {
return cacheKey().intern();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof SessionKey that)) {
return false;
}
return Objects.equals(appId, that.appId)
&& Objects.equals(operatorUserId, that.operatorUserId);
}
@Override
public int hashCode() {
return Objects.hash(appId, operatorUserId);
}
} }
} }

View File

@@ -118,7 +118,6 @@ iwork:
void-workflow: /api/workflow/paService/doCancelRequest void-workflow: /api/workflow/paService/doCancelRequest
token: token:
ttl-seconds: 3600 ttl-seconds: 3600
refresh-ahead-seconds: 60
client: client:
connect-timeout: 60s connect-timeout: 60s
response-timeout: 60s response-timeout: 60s