feat: 提交流程中心后端代码
build / build-push (push) Successful in 28s

Spring Boot 流程引擎服务:流程定义/实例/任务、审批人解析、
回调分发、oapi 接口及单元测试。
保留远程 .gitea/workflows/build.yml 与 docker/Dockerfile,
新增 .gitignore 排除 target/ 构建产物。
This commit is contained in:
chenxing
2026-09-15 10:42:56 +08:00
parent 0296b2b5dd
commit c1103aeb29
65 changed files with 7119 additions and 0 deletions
@@ -0,0 +1,201 @@
package com.yunhai.flowcenter.controller.api;
import com.yunhai.flowcenter.entity.FlwAssigneeMap;
import com.yunhai.flowcenter.entity.FlwCallbackLog;
import com.yunhai.flowcenter.entity.FlwCallbackReg;
import com.yunhai.flowcenter.entity.FlwDef;
import com.yunhai.flowcenter.entity.FlwInstance;
import com.yunhai.flowcenter.model.FlowModels;
import com.yunhai.flowcenter.repository.FlwInstanceRepository;
import com.yunhai.flowcenter.service.FlowAdminGuard;
import com.yunhai.flowcenter.service.FlowCallbackAdminService;
import com.yunhai.flowcenter.service.FlowDefAdminService;
import com.yunhai.flowcenter.service.FlowDiagramService;
import com.yunhai.flowcenter.service.FlowMapAdminService;
import com.yunhai.platform.utils.model.BasePageResult;
import com.yunhai.platform.utils.model.BoaUser;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
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.List;
import java.util.Map;
/**
* 管理端(/api/flow/admin/**,CAS + 管理员角色,FlowAdminGuard 校验):
* 定义 JSON 编辑/发布/停用、办理人映射 CRUD(成员检索调 UserBase)、
* 回调注册管理/推送日志/死信重推、办件查询。
*/
@RestController
@RequestMapping("/api/flow/admin")
@RequiredArgsConstructor
public class FlowAdminController {
private final FlowAdminGuard adminGuard;
private final FlowDefAdminService defAdminService;
private final FlowMapAdminService mapAdminService;
private final FlowCallbackAdminService callbackAdminService;
private final FlwInstanceRepository instanceRepository;
private final FlowDiagramService diagramService;
// ==================== 流程定义 ====================
@GetMapping("/def/list")
public List<FlwDef> defList(BoaUser user,
@RequestParam(value = "status", required = false) Integer status) {
return defAdminService.list(adminGuard.requireAdmin(user, null), status);
}
@GetMapping("/def/get")
public FlwDef defGet(BoaUser user, @RequestParam("id") Long id) {
return defAdminService.get(adminGuard.requireAdmin(user, null), id);
}
/** 保存(新建草稿/编辑;已发布定义保存=升版本,flowGuid 不变;baseGuid=在指定流程线上开新版本草稿) */
@PostMapping("/def/save")
public FlwDef defSave(BoaUser user, @RequestBody Map<String, Object> body) {
Long schId = adminGuard.requireAdmin(user, null);
Long id = body.get("id") == null ? null : Long.valueOf(String.valueOf(body.get("id")));
return defAdminService.save(schId, id,
(String) body.get("code"), (String) body.get("name"),
(String) body.get("contentJson"), (String) body.get("baseGuid"));
}
@PostMapping("/def/publish/{id}")
public FlwDef defPublish(BoaUser user, @PathVariable("id") Long id) {
return defAdminService.publish(adminGuard.requireAdmin(user, null), id);
}
@PostMapping("/def/offline/{id}")
public void defOffline(BoaUser user, @PathVariable("id") Long id) {
defAdminService.offline(adminGuard.requireAdmin(user, null), id);
}
@GetMapping("/def/versions")
public List<FlwDef> defVersions(BoaUser user, @RequestParam("flowGuid") String flowGuid) {
return defAdminService.versions(adminGuard.requireAdmin(user, null), flowGuid);
}
/** 流程定义示意图(方案 §3.1):requireAdmin 后按 defId 任意版本出图(草稿可预览) */
@GetMapping("/def/diagram")
public FlowModels.DiagramVo defDiagram(BoaUser user, @RequestParam("id") Long id,
@RequestParam(value = "mode", required = false) String mode) {
Long schId = adminGuard.requireAdmin(user, null);
FlwDef def = defAdminService.get(schId, id);
return diagramService.build(def, null, mode);
}
// ==================== 办理人映射 ====================
@GetMapping("/map/list")
public List<FlwAssigneeMap> mapList(BoaUser user,
@RequestParam(value = "deptKey", required = false) String deptKey) {
return mapAdminService.listByDept(adminGuard.requireAdmin(user, null), deptKey);
}
@PostMapping("/map/save")
public FlwAssigneeMap mapSave(BoaUser user, @RequestBody Map<String, Object> body) {
Long schId = adminGuard.requireAdmin(user, null);
return mapAdminService.save(schId,
(String) body.get("deptKey"), (String) body.get("deptName"),
body.get("userId") == null ? null : Integer.valueOf(String.valueOf(body.get("userId"))),
(String) body.get("userName"));
}
@PostMapping("/map/disable/{id}")
public void mapDisable(BoaUser user, @PathVariable("id") Long id) {
mapAdminService.disable(adminGuard.requireAdmin(user, null), id);
}
/** 成员检索(UserBase /oapi/user/byId) */
@GetMapping("/map/lookupUser")
public com.yunhai.platform.utils.model.BoaUser lookupUser(BoaUser user,
@RequestParam("userId") Integer userId) {
adminGuard.requireAdmin(user, null);
return mapAdminService.lookupUser(userId);
}
// ==================== 回调注册/推送日志/死信 ====================
@GetMapping("/callback/regList")
public List<FlwCallbackReg> regList(BoaUser user) {
return callbackAdminService.listRegs(adminGuard.requireAdmin(user, null));
}
@PostMapping("/callback/regStatus/{id}")
public void regStatus(BoaUser user, @PathVariable("id") Long id,
@RequestParam("enabled") boolean enabled) {
callbackAdminService.setRegStatus(adminGuard.requireAdmin(user, null), id, enabled);
}
/** secret 重置(新 secret 返回给前端展示一次) */
@PostMapping("/callback/resetSecret/{id}")
public Map<String, String> resetSecret(BoaUser user, @PathVariable("id") Long id) {
String secret = callbackAdminService.resetSecret(adminGuard.requireAdmin(user, null), id);
return java.util.Collections.singletonMap("secret", secret);
}
@GetMapping("/callback/logs")
public BasePageResult<FlwCallbackLog> logs(BoaUser user,
@RequestParam(value = "status", required = false) Integer status,
@RequestParam(value = "event", required = false) String event,
@RequestParam(value = "instanceId", required = false) Long instanceId,
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "size", required = false) Integer size) {
return callbackAdminService.pageLogs(adminGuard.requireAdmin(user, null), status, event, instanceId, page, size);
}
/** 挂起列表(待推且重试达阈值;持续重试中疑似消费方停机的可视入口) */
@GetMapping("/callback/hung")
public BasePageResult<FlwCallbackLog> hung(BoaUser user,
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "size", required = false) Integer size) {
return callbackAdminService.pageHung(adminGuard.requireAdmin(user, null), page, size);
}
/** 管理端手工标记死信(死信唯一人工入口;标记后可 rePush 复活) */
@PostMapping("/callback/markDead/{id}")
public void markDead(BoaUser user, @PathVariable("id") Long id) {
callbackAdminService.markDead(adminGuard.requireAdmin(user, null), id);
}
@GetMapping("/callback/dead")
public BasePageResult<FlwCallbackLog> dead(BoaUser user,
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "size", required = false) Integer size) {
return callbackAdminService.pageDead(adminGuard.requireAdmin(user, null), page, size);
}
@PostMapping("/callback/repush")
public void repush(BoaUser user, @RequestBody List<Long> logIds) {
callbackAdminService.rePush(adminGuard.requireAdmin(user, null), logIds);
}
// ==================== 办件查询 ====================
@GetMapping("/instance/page")
public BasePageResult<FlwInstance> instancePage(
BoaUser user,
@RequestParam(value = "status", required = false) Integer status,
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "size", required = false) Integer size) {
Long schId = adminGuard.requireAdmin(user, null);
Page<FlwInstance> p = instanceRepository.pageAdmin(schId, status, keyword,
PageRequest.of(page == null || page < 1 ? 0 : page - 1,
size == null || size < 1 || size > 100 ? 10 : size,
Sort.by(Sort.Order.desc("id"))));
int pi = page == null || page < 1 ? 1 : page;
int ps = size == null || size < 1 || size > 100 ? 10 : size;
return new BasePageResult<>(p.getContent(), (int) p.getTotalElements(), pi, ps,
p.getTotalPages(), p.hasNext());
}
}