package com.yunhai.flowcenter.controller.oapi; import com.yunhai.flowcenter.model.OapiModels; import com.yunhai.flowcenter.service.FlowRouterAdminService; import com.yunhai.flowcenter.service.OapiFlowService; import com.yunhai.platform.utils.model.BasePageResult; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * 托管接入件(/oapi/flow/**,appKey 签名强制,V2.0 Part D #5 前置 M1)。 * 出入参逐字对齐 svc-hall FlowCenterClient(《流程中心M1开工说明.md》§5 契约锚点): * - GET /oapi/flow/list?schId= → data=[{flowGuid,name,version,nodeSummary}] * - GET /oapi/flow/{flowGuid}?schId= → data={flowGuid,name,version,nodeSummary} * - POST /oapi/flow/apply → data={instanceId,duplicated} * - GET /oapi/flow/instance?bizType=&bizId=&schId= → data={status,version,instanceId,nodeSummary,traceJson,…} * - POST /oapi/flow/instance/{instanceId}/withdraw?schId=&submitterId= → data=null(提交人复核后撤回) * - GET /oapi/flow/progress?instanceId=|bizType=&bizId=&schId= → data={status,steps:[…]} * - GET /oapi/flow/diagram/url?instanceId=|flowGuid=&mode=&schId= → data={imgUrl,expiresIn} * - GET /oapi/flow/embed/url?instanceId=|bizType=&bizId=&mode=&schId= → data={pageUrl,expiresIn} * - POST /oapi/flow/callback/reg?schId= → data={secret} * - POST /oapi/flow/router/reg → data=null(判断服务自注册,归属=appKey) * 应用内审批(2026-09 第三步,原"刻意不提供审批动作"立场由该方案修订:登录身份由调用方 * 应用按其 CAS 会话保证并以 operatorId 传入,本端按任务办理人逐字复核,审计链不断): * - GET /oapi/flow/tasks/todo?schId=&assigneeId=&bizType=&page=&size= → data=分页待办 * - GET /oapi/flow/tasks/by-biz?schId=&bizType=&bizId=&operatorId= → data=当前人在该单据的待办(0/1/N) * - GET /oapi/flow/instances?schId=&bizType=&status=&page=&size= → data=分页办件 * - POST /oapi/flow/task/{taskId}/approve?schId=&operatorId=&operatorName=(body: opinion/edgeName) * - POST /oapi/flow/task/{taskId}/reject?schId=&operatorId=&operatorName=(body: opinion 必填) */ @RestController @RequestMapping("/oapi/flow") @RequiredArgsConstructor public class OapiFlowController { private final OapiFlowService flowService; private final FlowRouterAdminService routerAdminService; @GetMapping("/list") public List list(@RequestParam("schId") Long schId) { return flowService.listFlows(schId); } @GetMapping("/{flowGuid}") public OapiModels.FlowSummaryVo getFlow(@PathVariable("flowGuid") String flowGuid, @RequestParam("schId") Long schId) { return flowService.getFlow(schId, flowGuid); } @PostMapping("/apply") public OapiModels.ApplyResultVo apply(@RequestParam("schId") Long schId, @RequestAttribute(value = "yh.app.auth", required = false) String appKey, @RequestBody OapiModels.ApplyBody body) { return flowService.apply(schId, appKey, body); } /** 发起预览:返回开启发起时指派的节点与候选人(已剔除发起人本人),供子应用提交页选人 */ @GetMapping("/apply/preview") public OapiModels.ApplyPreviewVo applyPreview(@RequestParam("schId") Long schId, @RequestParam("flowGuid") String flowGuid, @RequestParam("submitterId") Integer submitterId) { return flowService.applyPreview(schId, flowGuid, submitterId); } @GetMapping("/instance") public OapiModels.InstanceVo instance(@RequestParam("bizType") String bizType, @RequestParam("bizId") String bizId, @RequestParam("schId") Long schId) { return flowService.instanceByBiz(schId, bizType, bizId); } /** * 办件进度(结构化轨迹,SDK FlowProgress 契约):instanceId 或 bizType/bizId 定位。 * 消费方渲染时间线(发起申请→各节点办理人行),SDK com.yunhai.platform.openapi.flow.model 同构。 */ @GetMapping("/progress") public OapiModels.ProgressVo progress(@RequestParam(value = "instanceId", required = false) Long instanceId, @RequestParam(value = "bizType", required = false) String bizType, @RequestParam(value = "bizId", required = false) String bizId, @RequestParam("schId") Long schId) { return flowService.progress(schId, instanceId, bizType, bizId); } /** * 流程图换图(token 模式,"CAS 验证码式嵌入"):img 标签带不了签名,本端点在 app-sign 保护下 * 签发短时 token,返回可直接放 {@code } 的免签路径 {@code /open/flow/diagram/img?token=}。 * 口径:instanceId=办件运行时状态图;flowGuid=最高已发布版定义图。 */ @GetMapping("/diagram/url") public OapiModels.DiagramUrlVo diagramUrl(@RequestParam(value = "instanceId", required = false) Long instanceId, @RequestParam(value = "flowGuid", required = false) String flowGuid, @RequestParam(value = "mode", required = false) String mode, @RequestParam("schId") Long schId) { return flowService.diagramUrl(schId, instanceId, flowGuid, mode); } /** * 办件进度嵌入页换址(iframe 场景,token 模式与换图同构):pageUrl 为 flow-center 前端 * 绝对地址,子应用直接放 {@code