package com.agent.management.controller; import com.agent.management.common.Result; import com.agent.management.engine.WorkflowEngine; import com.agent.management.engine.WorkflowRunRequest; import com.agent.management.model.entity.Workflow; import com.agent.management.model.vo.PageResult; import com.agent.management.model.vo.WorkflowVO; import com.agent.management.repository.WfCategoryRepository; import com.agent.management.service.TagService; import com.agent.management.service.WfCategoryService; import com.agent.management.service.WorkflowService; import lombok.Data; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @RestController @RequestMapping("/api/workflows") @RequiredArgsConstructor public class WorkflowController { private final WorkflowService workflowService; private final WorkflowEngine workflowEngine; private final TagService tagService; private final WfCategoryRepository wfCategoryRepository; private final WfCategoryService wfCategoryService; @GetMapping public Result> list( @RequestParam(required = false) String search, @RequestParam(required = false) Long categoryId, @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "12") int size) { List all = workflowService.listWorkflows(); // 搜索过滤 if (search != null && !search.trim().isEmpty()) { String kw = search.trim().toLowerCase(); all = all.stream() .filter(wf -> (wf.getName() != null && wf.getName().toLowerCase().contains(kw)) || (wf.getDescription() != null && wf.getDescription().toLowerCase().contains(kw))) .collect(Collectors.toList()); } // 分类过滤(含子孙分类) if (categoryId != null) { List catIds = new ArrayList<>(); catIds.add(categoryId); catIds.addAll(wfCategoryService.getDescendantCategoryIds(categoryId)); all = all.stream() .filter(wf -> wf.getCategoryId() != null && catIds.contains(wf.getCategoryId())) .collect(Collectors.toList()); } int total = all.size(); int totalPages = Math.max(1, (int) Math.ceil((double) total / size)); if (page > totalPages) page = totalPages; int from = (page - 1) * size; int to = Math.min(from + size, total); List pageData = from < total ? all.subList(from, to) : List.of(); List voList = pageData.stream().map(this::toVO).collect(Collectors.toList()); return Result.success(PageResult.of(voList, total, page, size)); } @GetMapping("/{id}") public Result get(@PathVariable Long id) { Workflow wf = workflowService.getWorkflow(id); return Result.success(toVO(wf)); } @PostMapping public Result create(@RequestBody CreateWorkflowReq req) { Workflow wf = workflowService.createWorkflow(req.getName(), req.getDescription()); return Result.success(toVO(wf)); } @PostMapping("/{id}/save") public Result save(@PathVariable Long id, @RequestBody SaveWorkflowReq req) { Workflow wf = workflowService.updateWorkflow(id, req.getName(), req.getDescription(), req.getGraphData()); return Result.success(toVO(wf)); } @PostMapping("/{id}/delete") public Result delete(@PathVariable Long id) { workflowService.deleteWorkflow(id); return Result.success(null); } /** 设置工作流分类 */ @PutMapping("/{id}/category") public Result setCategory(@PathVariable Long id, @RequestBody SetCategoryReq req) { Workflow wf = workflowService.getWorkflow(id); wf.setCategoryId(req.getCategoryId()); workflowService.updateWorkflow(wf.getId(), wf.getName(), wf.getDescription(), wf.getGraphData()); return Result.success(null); } /** * 运行工作流(SSE 实时推送执行状态) */ @PostMapping(value = "/{id}/run", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter run(@PathVariable Long id, @RequestBody WorkflowRunRequest req) { SseEmitter emitter = new SseEmitter(600_000L); // 10 分钟超时 workflowEngine.executeAsync(id, req.getInputs(), emitter); return emitter; } private WorkflowVO toVO(Workflow wf) { WorkflowVO vo = WorkflowVO.from(wf); vo.setTags(tagService.getEntityTags("workflow", String.valueOf(wf.getId()))); // 填充分类名称 if (wf.getCategoryId() != null) { wfCategoryRepository.findById(wf.getCategoryId()) .ifPresent(cat -> vo.setCategoryName(cat.getName())); } return vo; } @Data public static class CreateWorkflowReq { private String name; private String description; } @Data public static class SaveWorkflowReq { private String name; private String description; private String graphData; } @Data public static class SetCategoryReq { private Long categoryId; } }