From a103d661fc6746836aae412888f1eacc6d8ec288 Mon Sep 17 00:00:00 2001 From: chenxing Date: Sat, 3 Oct 2026 16:59:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(notice):=20=E6=8E=A5=E5=85=A5=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=BF=9B=E5=BA=A6=E5=B5=8C=E5=85=A5=E9=A1=B5=EF=BC=88?= =?UTF-8?q?=E5=AE=88=E5=8D=AB=E7=AB=AF=E7=82=B9=20+=20Drawer=20iframe?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/api/NoticeFlowController.java | 11 ++++ .../service/flow/NoticeFlowEmbedService.java | 52 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/main/java/com/yunhai/notice/service/flow/NoticeFlowEmbedService.java diff --git a/src/main/java/com/yunhai/notice/controller/api/NoticeFlowController.java b/src/main/java/com/yunhai/notice/controller/api/NoticeFlowController.java index f4205b9..5d60b2e 100644 --- a/src/main/java/com/yunhai/notice/controller/api/NoticeFlowController.java +++ b/src/main/java/com/yunhai/notice/controller/api/NoticeFlowController.java @@ -22,6 +22,7 @@ import java.util.Map; *
  • POST Flow/Binding/Save:保存/解除应用级绑定(仅本校管理员);
  • *
  • POST Flow/TrySubmit:提交/重提审核(幂等,bizId=notice.id;apply 失败保持待提交可重推);
  • *
  • GET Flow/Trace:审批进度(后端 getInstanceByBiz 组装,前端不直调 oapi——放行判定必须收在后端)。
  • + *
  • GET Flow/Embed:办件进度嵌入页地址(Drawer iframe 直嵌,可见性与 Trace 同口径)。
  • * */ @RestController @@ -30,6 +31,7 @@ import java.util.Map; public class NoticeFlowController { private final NoticeFlowService noticeFlowService; + private final com.yunhai.notice.service.flow.NoticeFlowEmbedService noticeFlowEmbedService; /** 审核流程下拉选项(流程中心未启用时返回空列表,前端隐藏选择器) */ @GetMapping("Options") @@ -81,6 +83,15 @@ public class NoticeFlowController { return noticeFlowService.diagramImage(serid, user); } + /** + * 办件进度嵌入页地址(详情页 Drawer 内 iframe 直嵌 flow-center 统一进度页)。 + * 可见性与 Trace/Diagram 同口径;pageUrl 含短时 token,现取现发不落前端缓存。 + */ + @GetMapping("Embed") + public Map embed(@RequestParam("serid") Integer serid, BoaUser user) { + return noticeFlowEmbedService.embedUrl(serid, user); + } + private Integer currentSchId(BoaUser user) { if (user == null || user.getCurrentRole() == null) { return null; diff --git a/src/main/java/com/yunhai/notice/service/flow/NoticeFlowEmbedService.java b/src/main/java/com/yunhai/notice/service/flow/NoticeFlowEmbedService.java new file mode 100644 index 0000000..c3ba7e9 --- /dev/null +++ b/src/main/java/com/yunhai/notice/service/flow/NoticeFlowEmbedService.java @@ -0,0 +1,52 @@ +package com.yunhai.notice.service.flow; + +import com.yunhai.notice.entity.Notice; +import com.yunhai.notice.repository.NoticeRepository; +import com.yunhai.platform.apistd.BizException; +import com.yunhai.platform.openapi.flow.YschFlowOpenApi; +import com.yunhai.platform.openapi.flow.model.FlowEmbedUrl; +import com.yunhai.platform.utils.exception.ErrorCode; +import com.yunhai.platform.utils.model.BoaUser; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.util.Collections; +import java.util.Map; + +/** + * 办件进度嵌入页换址(2026-10-03 嵌入页方案):子应用 Drawer 内 iframe 直嵌 flow-center + * 统一进度页,零样式复制。与 Diagram 同口径的用户级守卫(未发布仅提交人/管理员/办理人 + * /被抄送人可见);oapi 层只认 schId——"谁能看"必须落在本端点,应用签名不替代身份。 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class NoticeFlowEmbedService { + + private final NoticeRepository noticeRepository; + private final NoticeFlowGuard noticeFlowGuard; + + /** + * 取嵌入页地址(pageUrl 含 10 分钟短时 token):现取现发、不缓存、不落库、 + * 不打进应用日志(token 泄露窗口即有效期,纪律见方案 §6.1/§7)。 + */ + public Map embedUrl(Integer noticeId, BoaUser user) { + Notice notice = noticeRepository.findById(noticeId) + .orElseThrow(() -> new BizException(ErrorCode.FORBIDDEN, "通知不存在: " + noticeId)); + if (notice.getStatus() == null || notice.getStatus() != 1) { + noticeFlowGuard.requireUnpublishedVisible(notice, user); + } + if (notice.getFlowInstanceId() == null || notice.getSchId() == null) { + throw new BizException(ErrorCode.PARAM_ERROR, "该通知尚未进入流程"); + } + FlowEmbedUrl embed = YschFlowOpenApi.embedUrl( + null, FlowCenterClient.BIZ_TYPE, String.valueOf(notice.getId()), + notice.getSchId(), FlowEmbedUrl.class); + if (embed == null || !StringUtils.hasText(embed.getPageUrl())) { + throw new BizException(ErrorCode.INTERNAL_SERVER_ERROR, "嵌入页地址获取失败,请稍后重试"); + } + return Collections.singletonMap("pageUrl", embed.getPageUrl()); + } +}