pom.xml
@@ -50,7 +50,7 @@ <!-- 面向运行时的D-ORM依赖 --> <anyline.version>8.7.2-20241022</anyline.version> <!--工作流配置--> <warm-flow.version>1.3.7</warm-flow.version> <warm-flow.version>1.6.0-m4</warm-flow.version> <!-- 插件版本 --> <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version> ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java
@@ -1,12 +1,6 @@ package org.dromara.workflow.config; import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import org.dromara.warm.flow.core.config.WarmFlow; import org.dromara.warm.flow.core.utils.IdUtils; import org.dromara.warm.plugin.modes.sb.config.BeanConfig; import org.dromara.workflow.common.ConditionalOnEnable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; /** @@ -16,16 +10,7 @@ */ @ConditionalOnEnable @Configuration public class WarmFlowConfig extends BeanConfig { @Autowired private IdentifierGenerator identifierGenerator; @Override public void after(WarmFlow flowConfig) { // 设置Mybatis-Plus默认主键生成器 IdUtils.setInstanceNative(() -> identifierGenerator.nextId(null).longValue()); } public class WarmFlowConfig { } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java
@@ -104,7 +104,6 @@ @Log(title = "流程定义", businessType = BusinessType.INSERT) @PutMapping("/publish/{id}") @RepeatSubmit() @Transactional(rollbackFor = Exception.class) public R<Boolean> publish(@PathVariable Long id) { return R.ok(flwDefinitionService.publish(id)); } @@ -127,7 +126,6 @@ */ @Log(title = "流程定义", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") @Transactional(rollbackFor = Exception.class) public R<Void> remove(@PathVariable List<Long> ids) { return toAjax(flwDefinitionService.removeDef(ids)); } @@ -153,9 +151,8 @@ */ @Log(title = "流程定义", businessType = BusinessType.IMPORT) @PostMapping("/importDef") @Transactional(rollbackFor = Exception.class) public R<Boolean> importDef(MultipartFile file, String category) { return R.ok(flwDefinitionService.importXml(file, category)); return R.ok(flwDefinitionService.importJson(file, category)); } /** @@ -172,13 +169,13 @@ } /** * 获取流程定义xml字符串 * 获取流程定义JSON字符串 * * @param id 流程定义id */ @GetMapping("/xmlString/{id}") public R<String> xmlString(@PathVariable Long id) { return R.ok("操作成功", defService.xmlString(id)); return R.ok("操作成功", defService.exportJson(id)); } /** @@ -189,6 +186,7 @@ */ @RepeatSubmit() @PutMapping("/active/{id}") @Transactional(rollbackFor = Exception.class) public R<Boolean> active(@PathVariable Long id, @RequestParam boolean active) { return R.ok(active ? defService.active(id) : defService.unActive(id)); } ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java
@@ -60,7 +60,7 @@ * @param category 分类 * @return 结果 */ boolean importXml(MultipartFile file, String category); boolean importJson(MultipartFile file, String category); /** * 删除流程定义 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java
@@ -3,22 +3,21 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.io.IoUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dom4j.Document; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.warm.flow.core.dto.FlowCombine; import org.dromara.warm.flow.core.entity.Definition; import org.dromara.warm.flow.core.dto.DefJson; import org.dromara.warm.flow.core.enums.NodeType; import org.dromara.warm.flow.core.enums.PublishStatus; import org.dromara.warm.flow.core.service.DefService; @@ -42,6 +41,8 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -120,6 +121,7 @@ * @param id 流程定义id */ @Override @Transactional(rollbackFor = Exception.class) public boolean publish(Long id) { List<FlowNode> flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper<FlowNode>().eq(FlowNode::getDefinitionId, id)); List<String> errorMsg = new ArrayList<>(); @@ -143,16 +145,20 @@ * @param file 文件 */ @Override public boolean importXml(MultipartFile file, String category) { try { FlowCombine combine = defService.readXml(file.getInputStream()); // 流程定义 Definition definition = combine.getDefinition(); definition.setCategory(category); defService.importFlow(combine); @Transactional(rollbackFor = Exception.class) public boolean importJson(MultipartFile file, String category) { try (InputStream inputStream = file.getInputStream()) { byte[] fileBytes = inputStream.readAllBytes(); String fileContent = new String(fileBytes, StandardCharsets.UTF_8); DefJson defJson = JsonUtils.parseObject(fileContent, DefJson.class); defJson.setCategory(category); defService.importDef(defJson); } catch (IOException e) { log.error("读取文件流错误: {}", e.getMessage(), e); throw new IllegalStateException("文件读取失败,请检查文件内容", e); } catch (Exception e) { log.error("导入流程定义错误: {}", e.getMessage(), e); throw new RuntimeException(e); throw new IllegalStateException("导入流程定义失败", e); } return true; } @@ -166,24 +172,15 @@ */ @Override public void exportDef(Long id, HttpServletResponse response) throws IOException { Document document = defService.exportXml(id); // 设置生成xml的格式 OutputFormat of = OutputFormat.createPrettyPrint(); // 设置编码格式 of.setEncoding("UTF-8"); of.setIndent(true); of.setIndent(" "); of.setNewlines(true); // 创建一个xml文档编辑器 XMLWriter writer = new XMLWriter(response.getOutputStream(), of); writer.setEscapeText(false); byte[] data = defService.exportJson(id).getBytes(StandardCharsets.UTF_8); String filename = "workflow_export_" + DateUtils.dateTimeNow() + ".json"; // 设置响应头和内容类型 response.reset(); response.setCharacterEncoding("UTF-8"); response.setContentType("application/x-msdownload"); response.setHeader("Content-Disposition", "attachment;"); writer.write(document); writer.close(); response.setCharacterEncoding(StandardCharsets.UTF_8.name()); response.setContentType("application/json"); response.setHeader("Content-Disposition", "attachment; filename=" + filename); response.addHeader("Content-Length", "" + data.length); IoUtil.write(response.getOutputStream(), false, data); } /** ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java
@@ -19,13 +19,14 @@ import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.warm.flow.core.FlowFactory; import org.dromara.warm.flow.core.FlowEngine; import org.dromara.warm.flow.core.constant.ExceptionCons; import org.dromara.warm.flow.core.dto.FlowParams; import org.dromara.warm.flow.core.entity.Definition; import org.dromara.warm.flow.core.entity.Instance; import org.dromara.warm.flow.core.entity.Task; import org.dromara.warm.flow.core.enums.NodeType; import org.dromara.warm.flow.core.service.ChartService; import org.dromara.warm.flow.core.service.DefService; import org.dromara.warm.flow.core.service.InsService; import org.dromara.warm.flow.core.service.TaskService; @@ -51,7 +52,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; @@ -68,6 +68,7 @@ private final InsService insService; private final DefService defService; private final ChartService chartService; private final TaskService taskService; private final FlowHisTaskMapper flowHisTaskMapper; private final FlowInstanceMapper flowInstanceMapper; @@ -248,7 +249,7 @@ //撤销 WorkflowUtils.backTask(message, instance.getId(), applyNodeCode, BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus()); //判断或签节点是否有多个,只保留一个 List<Task> currentTaskList = taskService.list(FlowFactory.newTask().setInstanceId(instance.getId())); List<Task> currentTaskList = taskService.list(FlowEngine.newTask().setInstanceId(instance.getId())); if (CollUtil.isNotEmpty(currentTaskList)) { if (currentTaskList.size() > 1) { currentTaskList.remove(0); @@ -284,14 +285,14 @@ */ @Override public Map<String, Object> flowImage(String businessId) { Map<String, Object> map = new HashMap<>(16); FlowInstance flowInstance = this.selectInstByBusinessId(businessId); if (flowInstance == null) { if (ObjectUtil.isNull(flowInstance)) { throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); } Long instanceId = flowInstance.getId(); //运行中的任务 List<FlowHisTaskVo> list = new ArrayList<>(); List<FlowTask> flowTaskList = flwTaskService.selectByInstId(flowInstance.getId()); List<FlowTask> flowTaskList = flwTaskService.selectByInstId(instanceId); if (CollUtil.isNotEmpty(flowTaskList)) { List<FlowHisTaskVo> flowHisTaskVos = BeanUtil.copyToList(flowTaskList, FlowHisTaskVo.class); for (FlowHisTaskVo flowHisTaskVo : flowHisTaskVos) { @@ -312,22 +313,15 @@ } //历史任务 LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery(); wrapper.eq(FlowHisTask::getInstanceId, flowInstance.getId()); wrapper.eq(FlowHisTask::getInstanceId, instanceId); wrapper.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()); wrapper.orderByDesc(FlowHisTask::getCreateTime).orderByDesc(FlowHisTask::getUpdateTime); List<FlowHisTask> flowHisTasks = flowHisTaskMapper.selectList(wrapper); if (CollUtil.isNotEmpty(flowHisTasks)) { list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class)); } map.put("list", list); try { String flowChart = defService.flowChart(flowInstance.getId()); map.put("image", flowChart); } catch (IOException e) { throw new RuntimeException(e); } return map; String flowChart = chartService.chartIns(instanceId); return Map.of("list", list, "image", flowChart); } /**