153 lines
7.4 KiB
Java
153 lines
7.4 KiB
Java
package com.yunhai.notice.service.flow;
|
||
|
||
import com.yunhai.platform.openapi.core.PlatformService;
|
||
import com.yunhai.platform.openapi.core.YschOpenCall;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.beans.factory.ObjectProvider;
|
||
import org.springframework.stereotype.Service;
|
||
|
||
import java.util.LinkedHashMap;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* 应用内审批出站客户端(第三步 T-C4):待办/办件查询 + 通过/驳回,经网关打 flow-center
|
||
* {@code /oapi/flow/tasks|task/**}(2026-09-23 已上线)。
|
||
* <p>
|
||
* <b>刻意用 {@link YschOpenCall} 泛化调用而非 YschFlowOpenApi 新门面方法</b>——四方法
|
||
* (todoTasks/instances/approveTask/rejectTask)在 SDK main 已编码但**未发版**,notice 运行时
|
||
* 依赖的是 nexus 已发布快照;泛化调用与 FlowCenterClient legacy 分支同一条
|
||
* resolveTarget 解析链(targets > services > 枚举 base-host 兜底=网关),零发版依赖。
|
||
* SDK 发版后可平替为门面方法(行为等价,测试锁 URL 不变)。
|
||
* <p>
|
||
* 身份口径:operatorId/operatorName 由调用方(controller)从 CAS 登录态取,本类不猜身份;
|
||
* 对端按任务办理人逐字复核(非办理人→业务码拒绝),notice 不重复校验。
|
||
*/
|
||
@Slf4j
|
||
@Service
|
||
public class NoticeApprovalClient {
|
||
|
||
private static final String TARGET = PlatformService.FLOW_CENTER.key();
|
||
private static final String NOT_CONNECTED = "流程中心未接入,审批功能不可用";
|
||
|
||
private final NoticeFlowProperties properties;
|
||
private final YschOpenCall openCall;
|
||
|
||
public NoticeApprovalClient(NoticeFlowProperties properties,
|
||
ObjectProvider<YschOpenCall> openCallProvider) {
|
||
this.properties = properties;
|
||
this.openCall = openCallProvider.getIfAvailable();
|
||
}
|
||
|
||
/** 我的待办(bizType 固定 notice):Map 形态即 flow-center BasePageResult JSON(total/content/…) */
|
||
public Map<String, Object> todoTasks(Integer schId, Integer assigneeId, Integer page, Integer size) {
|
||
requireEnabled();
|
||
Map<String, String> query = new LinkedHashMap<>();
|
||
query.put("schId", String.valueOf(schId));
|
||
query.put("assigneeId", String.valueOf(assigneeId));
|
||
query.put("bizType", FlowCenterClient.BIZ_TYPE);
|
||
if (page != null) {
|
||
query.put("page", String.valueOf(page));
|
||
}
|
||
if (size != null) {
|
||
query.put("size", String.valueOf(size));
|
||
}
|
||
return openCall.get(TARGET, "/oapi/flow/tasks/todo", query, Map.class);
|
||
}
|
||
|
||
/** 办件分页(bizType 固定 notice;status 可空) */
|
||
public Map<String, Object> instances(Integer schId, Integer status, Integer page, Integer size) {
|
||
requireEnabled();
|
||
Map<String, String> query = new LinkedHashMap<>();
|
||
query.put("schId", String.valueOf(schId));
|
||
query.put("bizType", FlowCenterClient.BIZ_TYPE);
|
||
if (status != null) {
|
||
query.put("status", String.valueOf(status));
|
||
}
|
||
if (page != null) {
|
||
query.put("page", String.valueOf(page));
|
||
}
|
||
if (size != null) {
|
||
query.put("size", String.valueOf(size));
|
||
}
|
||
return openCall.get(TARGET, "/oapi/flow/instances", query, Map.class);
|
||
}
|
||
|
||
/**
|
||
* 当前人在本通知上的待办(v2.1 业务详情卡片数据源,{@code /oapi/flow/tasks/by-biz})。
|
||
* <p>返回 Map 即对端 {@code ByBizTasksVo} JSON:{@code tasks[]} 0/1/N 三种计数都走 HTTP 200,
|
||
* <b>调用方不得据 tasks 反推"这个通知上有没有别人的待办"</b>——办件不存在、错学校、错 bizType、
|
||
* 非办理人四种情形出参完全同形(都是空 tasks),这是对端的防探测设计,本端不要试图区分。
|
||
* <p>{@code currentNodes} 是节点 <b>id</b> 逗号串(办件原文口径),人读名称取 {@code tasks[].nodeName}。
|
||
*/
|
||
@SuppressWarnings("unchecked")
|
||
public Map<String, Object> byBiz(Integer schId, Integer operatorId, Integer noticeId) {
|
||
requireEnabled();
|
||
Map<String, String> query = new LinkedHashMap<>();
|
||
query.put("schId", String.valueOf(schId));
|
||
query.put("bizType", FlowCenterClient.BIZ_TYPE);
|
||
query.put("bizId", String.valueOf(noticeId));
|
||
query.put("operatorId", String.valueOf(operatorId));
|
||
return openCall.get(TARGET, "/oapi/flow/tasks/by-biz", query, Map.class);
|
||
}
|
||
|
||
/**
|
||
* 完整办理任务页地址({@code /oapi/flow/embed/url?mode=task}):返回 CAS 会话页
|
||
* {@code {front}/#/task/{taskId}},<b>无 token</b>(写面,办理权由该页加载时的用户面接口按
|
||
* assigneeId 复核)。仍走 {@link YschOpenCall} 泛化调用——nexus 已发布快照的
|
||
* {@code YschFlowOpenApi} 只有 embedUrl/todoTasks/instances,没有 taskPageUrl 门面方法,
|
||
* 而本批纪律是不动 BasePlatform。SDK 补齐后可平替(URL 不变,测试锁死)。
|
||
*/
|
||
@SuppressWarnings("unchecked")
|
||
public Map<String, Object> taskPageUrl(Integer schId, Long taskId) {
|
||
requireEnabled();
|
||
Map<String, String> query = new LinkedHashMap<>();
|
||
query.put("schId", String.valueOf(schId));
|
||
query.put("mode", "task");
|
||
query.put("taskId", String.valueOf(taskId));
|
||
return openCall.get(TARGET, "/oapi/flow/embed/url", query, Map.class);
|
||
}
|
||
|
||
/** 同意(opinion 可空;多出口 edgeName 透传) */
|
||
public void approve(Long taskId, Integer schId, Integer operatorId, String operatorName,
|
||
String opinion, String edgeName) {
|
||
requireEnabled();
|
||
Map<String, Object> body = new LinkedHashMap<>();
|
||
if (opinion != null && !opinion.trim().isEmpty()) {
|
||
body.put("opinion", opinion.trim());
|
||
}
|
||
if (edgeName != null && !edgeName.trim().isEmpty()) {
|
||
body.put("edgeName", edgeName.trim());
|
||
}
|
||
openCall.post(TARGET, "/oapi/flow/task/" + taskId + "/approve",
|
||
operatorQuery(schId, operatorId, operatorName), body, Void.class);
|
||
}
|
||
|
||
/** 拒绝(opinion 必填由对端强制;此处前置校验给前端更快的反馈) */
|
||
public void reject(Long taskId, Integer schId, Integer operatorId, String operatorName, String opinion) {
|
||
requireEnabled();
|
||
if (opinion == null || opinion.trim().isEmpty()) {
|
||
throw new com.yunhai.platform.apistd.BizException(
|
||
com.yunhai.platform.utils.exception.ErrorCode.PARAM_ERROR, "驳回必须填写意见");
|
||
}
|
||
Map<String, Object> body = new LinkedHashMap<>();
|
||
body.put("opinion", opinion.trim());
|
||
openCall.post(TARGET, "/oapi/flow/task/" + taskId + "/reject",
|
||
operatorQuery(schId, operatorId, operatorName), body, Void.class);
|
||
}
|
||
|
||
private static Map<String, String> operatorQuery(Integer schId, Integer operatorId, String operatorName) {
|
||
Map<String, String> query = new LinkedHashMap<>();
|
||
query.put("schId", String.valueOf(schId));
|
||
query.put("operatorId", String.valueOf(operatorId));
|
||
query.put("operatorName", operatorName);
|
||
return query;
|
||
}
|
||
|
||
private void requireEnabled() {
|
||
if (!properties.isEnabled() || openCall == null) {
|
||
throw new com.yunhai.platform.apistd.BizException(
|
||
com.yunhai.platform.utils.exception.ErrorCode.FORBIDDEN, NOT_CONNECTED);
|
||
}
|
||
}
|
||
}
|