Spring Boot 流程引擎服务:流程定义/实例/任务、审批人解析、 回调分发、oapi 接口及单元测试。 保留远程 .gitea/workflows/build.yml 与 docker/Dockerfile, 新增 .gitignore 排除 target/ 构建产物。
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
package com.yunhai.flowcenter.controller.api;
|
||||
|
||||
import com.yunhai.flowcenter.entity.FlwInstance;
|
||||
import com.yunhai.flowcenter.entity.FlwTask;
|
||||
import com.yunhai.flowcenter.model.FlowModels;
|
||||
import com.yunhai.flowcenter.service.FlowAccessGuard;
|
||||
import com.yunhai.flowcenter.service.FlowDiagramService;
|
||||
import com.yunhai.flowcenter.service.FlowInstanceService;
|
||||
import com.yunhai.flowcenter.service.FlowQueryService;
|
||||
import com.yunhai.flowcenter.service.FlowTaskService;
|
||||
import com.yunhai.platform.apistd.BizException;
|
||||
import com.yunhai.platform.utils.exception.ErrorCode;
|
||||
import com.yunhai.platform.utils.model.BasePageResult;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用户面(/api/flow/**,CAS 会话):我的办件/待办/已办/办件详情/办理/撤回/催办。
|
||||
* 一切审批入口的收敛点(概览 §8.5 不变式 2):业务系统内嵌页、消息跳转最终都调这套 API。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/flow")
|
||||
@RequiredArgsConstructor
|
||||
public class FlowUserController {
|
||||
|
||||
private final FlowQueryService queryService;
|
||||
private final FlowTaskService taskService;
|
||||
private final FlowInstanceService instanceService;
|
||||
private final FlowAccessGuard accessGuard;
|
||||
private final FlowDiagramService diagramService;
|
||||
|
||||
/** 我提交的办件 */
|
||||
@GetMapping("/my")
|
||||
public BasePageResult<FlowModels.InstanceItem> my(BoaUser user,
|
||||
@RequestParam(value = "status", required = false) Integer status,
|
||||
@RequestParam(value = "page", required = false) Integer page,
|
||||
@RequestParam(value = "size", required = false) Integer size) {
|
||||
return queryService.pageMy(requireSchId(user), user.getId(), status, page, size);
|
||||
}
|
||||
|
||||
/** 我的待办(主路径,走 assignee 索引) */
|
||||
@GetMapping("/todo")
|
||||
public BasePageResult<FlowModels.TaskItem> todo(BoaUser user,
|
||||
@RequestParam(value = "page", required = false) Integer page,
|
||||
@RequestParam(value = "size", required = false) Integer size) {
|
||||
return queryService.pageTodo(requireSchId(user), user.getId(), page, size);
|
||||
}
|
||||
|
||||
/** 我的已办 */
|
||||
@GetMapping("/done")
|
||||
public BasePageResult<FlowModels.TaskItem> done(BoaUser user,
|
||||
@RequestParam(value = "page", required = false) Integer page,
|
||||
@RequestParam(value = "size", required = false) Integer size) {
|
||||
return queryService.pageDone(requireSchId(user), user.getId(), page, size);
|
||||
}
|
||||
|
||||
/** 办件详情(提交人/办理人/本校管理员可见) */
|
||||
@GetMapping("/instance/{id}")
|
||||
public FlowModels.InstanceDetail detail(BoaUser user, @PathVariable("id") Long id) {
|
||||
FlwInstance instance = instanceService.requireInstance(requireSchId(user), id);
|
||||
accessGuard.requireInstanceVisible(instance, user);
|
||||
return queryService.detail(requireSchId(user), id, user.getId());
|
||||
}
|
||||
|
||||
/** 任务定位办件详情(办理页 /task/{taskId} 数据源;可见性走办件详情同一守卫) */
|
||||
@GetMapping("/task/{id}/detail")
|
||||
public FlowModels.InstanceDetail taskDetail(BoaUser user, @PathVariable("id") Long id) {
|
||||
Long schId = requireSchId(user);
|
||||
FlwTask task = taskService.requireTask(schId, id);
|
||||
FlwInstance instance = instanceService.requireInstance(schId, task.getInstanceId());
|
||||
accessGuard.requireInstanceVisible(instance, user);
|
||||
return queryService.detail(schId, instance.getId(), user.getId());
|
||||
}
|
||||
|
||||
/** 同意(opinion 可选)——一切审批入口的收敛点 */
|
||||
@PostMapping("/task/{id}/approve")
|
||||
public void approve(BoaUser user, @PathVariable("id") Long id,
|
||||
@RequestBody(required = false) Map<String, String> body) {
|
||||
String opinion = body == null ? null : body.get("opinion");
|
||||
taskService.handle(requireSchId(user), id, true, opinion, user.getId());
|
||||
}
|
||||
|
||||
/** 拒绝(opinion 必填) */
|
||||
@PostMapping("/task/{id}/reject")
|
||||
public void reject(BoaUser user, @PathVariable("id") Long id,
|
||||
@RequestBody(required = false) Map<String, String> body) {
|
||||
String opinion = body == null ? null : body.get("opinion");
|
||||
taskService.handle(requireSchId(user), id, false, opinion, user.getId());
|
||||
}
|
||||
|
||||
/** 撤回(提交人;仅尚无任务被办理时) */
|
||||
@PostMapping("/instance/{id}/withdraw")
|
||||
public void withdraw(BoaUser user, @PathVariable("id") Long id) {
|
||||
FlwInstance instance = instanceService.requireInstance(requireSchId(user), id);
|
||||
if (!instance.getSubmitterId().equals(user.getId())) {
|
||||
throw new BizException(ErrorCode.FORBIDDEN, "仅提交人本人可撤回");
|
||||
}
|
||||
instanceService.withdraw(requireSchId(user), id);
|
||||
}
|
||||
|
||||
/** 催办(提交人/管理员;对全部待办任务各催一次,msgNo 幂等) */
|
||||
@PostMapping("/instance/{id}/urge")
|
||||
public void urge(BoaUser user, @PathVariable("id") Long id) {
|
||||
instanceService.urgeInstance(requireSchId(user), id, user.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程示意图(方案 §3.1):flowGuid=最高已发布版(登录+本校);
|
||||
* instanceId=办件 def 快照版,可见性与办件详情同口径(requireInstanceVisible)。
|
||||
*/
|
||||
@GetMapping("/diagram")
|
||||
public FlowModels.DiagramVo diagram(BoaUser user,
|
||||
@RequestParam(value = "flowGuid", required = false) String flowGuid,
|
||||
@RequestParam(value = "instanceId", required = false) Long instanceId,
|
||||
@RequestParam(value = "mode", required = false) String mode) {
|
||||
Long schId = requireSchId(user);
|
||||
if (flowGuid != null && !flowGuid.trim().isEmpty()) {
|
||||
return diagramService.byGuid(schId, flowGuid.trim(), mode);
|
||||
}
|
||||
if (instanceId != null) {
|
||||
FlwInstance instance = instanceService.requireInstance(schId, instanceId);
|
||||
accessGuard.requireInstanceVisible(instance, user);
|
||||
return diagramService.byInstance(instance, mode);
|
||||
}
|
||||
throw new BizException(ErrorCode.PARAM_ERROR, "缺少必要参数:flowGuid 或 instanceId");
|
||||
}
|
||||
|
||||
private Long requireSchId(BoaUser user) {
|
||||
if (user == null) {
|
||||
throw new BizException(ErrorCode.FORBIDDEN, "未登录");
|
||||
}
|
||||
if (user.getCurrentRole() == null || user.getCurrentRole().getSchId() == null) {
|
||||
throw new BizException(ErrorCode.PARAM_ERROR, "当前身份无学校归属(区域账号无流程业务)");
|
||||
}
|
||||
return Long.valueOf(user.getCurrentRole().getSchId());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user