当前位置: 首页 > article >正文

Spring Boot3.x集成Flowable7.x(一)Spring Boot集成与设计、部署、发起、完成简单流程

一、Flowable简介

Flowable 是一个轻量级、开源的业务流程管理(BPM)和工作流引擎,旨在帮助开发者和企业实现业务流程的自动化。它支持 BPMN 2.0 标准,适用于各种规模的企业和项目。Flowable 的核心功能包括流程定义、流程执行、任务管理、历史记录查询等,广泛应用于企业级应用中。

官网:https://www.flowable.com/open-source/docs/

二、Spring Boot3整合

环境:JDK21、Spring Boot3.4.1、Flowable7.1.0

1.引入依赖

        <!-- Flowable启动引擎 --><dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter</artifactId><version>7.1.0</version></dependency>

2.yml配置

注意本文数据源、数据库是MySQL和Druid,各位码友请根据实际情况调整

spring:#配置数据源datasource:#MySQLdriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/foleable?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: 123456type: com.alibaba.druid.pool.DruidDataSourceflowable:# 开启定时任务JOBasync-executor-activate: true# 在引擎启动时,会自动更新数据库架构database-schema-update: true

3.线程池配置

1.提供一个全局的默认线程池

2.提供一个folwable依赖的线程池,注意Bean的名称一定要是applicationTaskExecutor

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;/*** 统一线程池管理** @author xie**/
@Configuration
public class ThreadPoolTaskConfig {@Bean("applicationTaskExecutor")public ThreadPoolTaskExecutor applicationTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//此方法返回可用处理器的虚拟机的最大数量; 不小于1int core = Runtime.getRuntime().availableProcessors();executor.setCorePoolSize(core);//设置核心线程数executor.setMaxPoolSize(core * 2 + 1);//设置最大线程数executor.setKeepAliveSeconds(120);//除核心线程外的线程存活时间executor.setQueueCapacity(120);//如果传入值大于0,底层队列使用的是LinkedBlockingQueue,否则默认使用SynchronousQueueexecutor.setThreadNamePrefix("thread-default-execute");//线程名称前缀executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//设置拒绝策略,抛出 RejectedExecutionException来拒绝新任务的处理。
//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//设置拒绝策略,使用主线程
//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());//设置拒绝策略,直接丢弃掉
//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());//设置拒绝策略,丢弃最早的未处理的任务请求。return executor;}
}

不配置线程池可能出现以下错误

三、流程定义

官方流程设计器

docker run -p 9096:8080 -d --name flow flowable/flowable-ui:6.8.0

访问IP加启动容器的端口

默认账户/密码:admin/test

进入设计器

创建流程并设计

创建测试流程
这里先简单画个流程 后期写个详细流程图的绘画

确定后进入设计界面

添加用活动后设置名称

点击用户任务设置用户任务的执行人

这里先简单设置一个固定的人,分配用户ID为:user1

再重复添加一个用户任务,添加一下结束事件

最后就依次连线就行了,选中开始节点然后连接到用户一

最后的效果图


点击保存

选择查看刚刚创建的流程

导出XML

四、部署流程

1.把导出的xml放入我们工程的resources目录

2.部署流程(这里先把我们后面用到的查询服务都注入)

    @Resourceprivate RepositoryService repositoryService;@Resourceprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@Resourceprivate HistoryService historyService;@ResourceIdentityService identityService;/*** 初始化流程** @method: initFlow* @return:* @author: xie* @date: 2024/12/24 上午9:26**/@GetMapping("initFlow")@Transactional(rollbackFor = Exception.class)public void initFlow() {// 获取bpmn文件夹的所有.bpmn20.xml文件ClassPathResource bpmnFolder = new ClassPathResource("bpmn/");var files = bpmnFolder.getFile().listFiles((dir, name) -> name.endsWith(".bpmn20.xml"));if (files != null && files.length > 0) {// 创建部署对象var deploymentBuilder = repositoryService.createDeployment();for (var file : files) {// 添加BPMN文件到部署deploymentBuilder.addInputStream(file.getName(), file.toURI().toURL().openStream());}// 执行部署Deployment deployment = deploymentBuilder.deploy();}}

五、查询部署的全部流程

当然这里也可以进行分页查询已经写在下面注释了 这里为了测试 我就简单写了

    /**** 查询所有的流程实例* @method: queryAllDeployedProcesses* @return:* @author: xie* @date: 2024/12/20 下午1:12**/@GetMapping("/queryAllDeployedProcesses")public List<JSONObject> queryAllDeployedProcesses() {List<JSONObject> jsonObjects = new ArrayList<>();// 查询所有流程定义List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionKey().asc() // 按流程定义的 Key 排序.latestVersion() // 只查询每个流程定义的最新版本.list();// 打印所有已部署的流程的 key 和 namefor (ProcessDefinition processDefinition : processDefinitions) {System.out.println("Process ID: " + processDefinition.getId());System.out.println("Process Key: " + processDefinition.getKey());System.out.println("Process Name: " + processDefinition.getName());System.out.println("Process Version: " + processDefinition.getVersion());JSONObject object = new JSONObject();object.put("id", processDefinition.getId());object.put("key", processDefinition.getKey());object.put("name", processDefinition.getName());object.put("version", processDefinition.getVersion());jsonObjects.add(object);}//分页查询// 创建查询对象
//        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery()
//                .latestVersion() // 只查询最新版本的流程定义
//                .orderByProcessDefinitionKey().asc(); // 按流程定义的 Key 升序排序
//
//        // 获取总条数
//        long totalCount = query.count();
//
//        // 分页查询流程定义
//        List<ProcessDefinition> processDefinitions = query.listPage((pageNum - 1) * pageSize, pageSize);return jsonObjects;}

看看界面的效果吧,这个简单的前端页面展示方便查询

六、发起审批

    /*** 是否被拒绝标记*/public static final String REFUSEFLAG = "refuseFlag";/*** 发起流程** @param key : 流程信息* @method: startFlow* @return:* @author: xie* @date: 2024/12/20 下午1:43**/@GetMapping("/startFlow")@Transactional(rollbackFor = Exception.class)public String startFlow(@RequestParam("key") String key) {Map<String, Object> map = Map.of("businessType", "业务类型(业务审批、请假、出差等)","day", 1,REFUSEFLAG, false);//发起人用户IDString userId = SysConstan.USER_ID;//订单号String businessKey = "PO00001";//参数一 流程key//参数二 页面单据类型(比如请假流水号、订单号等)//参数三 运行时变量信息比如请假天数//设置发起人identityService.setAuthenticatedUserId(userId);//启动流程变量ProcessInstance processInstanceByKey = runtimeService.startProcessInstanceByKey(key, businessKey, map);log.info("流程实例id-{}", processInstanceByKey.getId());// 清除当前用户identityService.setAuthenticatedUserId(null);return processInstanceByKey.getId();}

注意:

参数key:指的是我们上一步部署流程后得到的key也就是页面查询的key

map对象是设置的变量集,比如我们请假的时候可能要根据不同的天数走不同的分支,这里的变量集后期可以自己封装一个对象指定一些必须传入的变量信息

拒绝标记:由于Flowable并不会记录流程是否是被拒绝而结束的流程实例

userId:Flowable默认是无状态的可以通过identityService临时设置发起人

businessKey:业务订单号,可以把它看做是审批的单据号后面审批通过了需要通知业务系统的时候需要用到

七、查询所有发起的流程及展示状态

这里包含了:我的发起、我参与审批的流程、根据业务单号查询审批流程等查询功能

    /*** 查询所有流程实例** @method: queryAllprocess* @return:* @author: xie* @date: 2024/12/20 下午3:35**/@GetMapping("queryAllprocess")public List<JSONObject> queryAllprocess() {// 获取所有活跃的流程实例(包括已结束的)List<HistoricProcessInstance> allProcessInstances = historyService.createHistoricProcessInstanceQuery()//查询用户参与过的流程实例//.involvedUser("1")//查询发起人用户//.startedBy(SysConstan.USER_ID)//根据变量查询(自己设的变量)//.variableValueEquals("businessType", "查询的业务类型")//根据订单号模糊查询//.processInstanceBusinessKeyLikeIgnoreCase("orderCode").orderByProcessInstanceStartTime().asc()  // 可以按ID排序,便于调试.list(); // 查询所有的流程实例,包括历史的和活跃的List<JSONObject> jsonObjects = new ArrayList<>();for (HistoricProcessInstance processInstance : allProcessInstances) {String processInstanceId = processInstance.getId();JSONObject json = new JSONObject();if (processInstance.getEndTime() == null) {json.put("status", "审批中");} else {json.put("status", "审批完成");}json.put("id", processInstance.getProcessDefinitionId());json.put("processInstanceId", processInstanceId);json.put("startUser", processInstance.getStartUserId());json.put("key", processInstance.getProcessDefinitionKey());json.put("businessKey", processInstance.getBusinessKey());json.put("name", processInstance.getProcessDefinitionName());json.put("deleteReason", processInstance.getDeleteReason());json.put("startTime", DateUtil.format(processInstance.getStartTime(), "yyyy-MM-dd HH:mm:ss"));json.put("endTime", processInstance.getEndTime() != null ? DateUtil.format(processInstance.getEndTime(), "yyyy-MM-dd HH:mm:ss") : "");// 获取与任务相关的所有变量// 获取该流程实例的变量List<HistoricVariableInstance> variables = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();if(CollUtil.isNotEmpty(variables)){for (HistoricVariableInstance variable : variables) {json.put(variable.getVariableName(), variable.getValue());if (REFUSEFLAG.equals(variable.getVariableName()) && variable.getValue() != null && variable.getValue().toString().equalsIgnoreCase("true")) {json.put("status", "审批驳回");}}}jsonObjects.add(json);}return jsonObjects;}

这里就用到了发起流程时是否驳回这个变量,判断当前业务单据是否被驳回

查询流程时可以有多种条件查询比如查询我发起的审批流程上面代码已经列出查询条件

对应的页面简单展示,发起后进入到用户一审批

八、我的代办任务

这里注释了用户ID条件查询,实际业务系统应该是要设置当前用户的ID查询

    /*** 获取代办列表 (这里暂时查看所有的)** @method: getTasks* @return:* @author: xie* @date: 2024/12/20 下午1:44**/@GetMapping("/allTasks")public List<JSONObject> getTasks() {List<Task> taskList = taskService.createTaskQuery()//查询业务类型为指定的任务//.processInstanceBusinessKey("LEAVE")//查询所有zhangsan用户代办的任务//.taskAssignee(SysConstan.USER_ID).list();List<JSONObject> jsonObjects = new ArrayList<>();for (Task task : taskList) {JSONObject json = new JSONObject();json.put("id", task.getId());json.put("name", task.getName());json.put("user", task.getAssignee());json.put("processDefinitionId", task.getProcessDefinitionId());json.put("processInstanceId", task.getProcessInstanceId());// 获取与任务相关的所有变量Map<String, Object> taskVariables = taskService.getVariables(task.getId());// 打印出任务的变量json.putAll(taskVariables);jsonObjects.add(json);}return jsonObjects;}

九、完成任务

这里的任务ID为上面我的代办任务接口查询出来Task的ID

     /*** 完成任务** @method: testComplete* @return:* @author: xie* @date: 2024/12/20 下午1:44**/@GetMapping("/testComplete")@Transactional(rollbackFor = Exception.class)public boolean testComplete(@RequestParam("id") String taskId) {     // 获取任务对应的流程实例IDTask task = taskService.createTaskQuery().taskId(taskId).singleResult();// 检查任务是否为空if (task == null) {System.out.println("任务不存在");return false;}String processInstanceId = task.getProcessInstanceId();String orderCode = (String) runtimeService.getVariable(processInstanceId, "orderCode");log.info("业务单据:{}", orderCode);// 1. 设置新执行者//taskService.setAssignee(taskId, newAssigneeId); // 任务的执行者被替换为新的用户taskService.addComment(taskId, processInstanceId, "备注信息test");// 完成任务taskService.complete(taskId);// 查询当前流程实例的所有活动任务boolean isFinish =  processInstanceFinished(processInstanceId);log.debug("流程是否完成L:{}", isFinish);return isFinish;}/*** 校验当前流程是否结束了* @method: isProcessInstanceFinished* @param processInstanceId :* @return:* @author: xie* @date: 2024/12/23 下午1:57**/public boolean processInstanceFinished(String processInstanceId) {// 获取当前流程实例ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();// 如果 processInstance 为空,表示该流程实例已结束return processInstance == null;}

十、驳回任务

processInstanceId指的是发起流程的实例ID

    /*** 驳回流程* @method: stopFlow * @param processInstanceId : * @return: * @author: xie* @date: 2024/12/24 下午4:38 **/@GetMapping("stopFlow")@Transactional(rollbackFor = Exception.class)public void stopFlow(@RequestParam("id") String processInstanceId) {// 在删除前设置拒绝变量runtimeService.setVariable(processInstanceId, "refuseFlag", true);//拒绝 后一个参数是拒绝的原因runtimeService.deleteProcessInstance(processInstanceId, "驳回任务备注原因");}

十一、 完成效果展示

1.BPMN-JS插件渲染的连接线不起效果

2.Flowable引擎自带构建的图片没有经过的节点


相关文章:

Spring Boot3.x集成Flowable7.x(一)Spring Boot集成与设计、部署、发起、完成简单流程

一、Flowable简介 Flowable 是一个轻量级、开源的业务流程管理&#xff08;BPM&#xff09;和工作流引擎&#xff0c;旨在帮助开发者和企业实现业务流程的自动化。它支持 BPMN 2.0 标准&#xff0c;适用于各种规模的企业和项目。Flowable 的核心功能包括流程定义、流程执行、任…...

Dify 工作流分类器技巧

在使用 Dify 工作流中的分类器&#xff08;如问题分类器&#xff0c;Question Classifier&#xff09;时&#xff0c;想要实现高效且准确的分类&#xff0c;可以遵循以下技巧和最佳实践。这些建议基于 Dify 的工作流功能&#xff0c;帮助你更好地设计和优化分类过程&#xff1a…...

网络安全-openssl工具

OpenSSl是一个开源项目&#xff0c;包括密码库和SSL/TLS工具集。它已是在安全领域的事实标准&#xff0c;并且拥有比较长的历史&#xff0c;现在几乎所有的服务器软件和很多客户端都在使用openssl&#xff0c;其中基于命令行的工具是进行加密、证书管理以及测试最常用到的软件。…...

【Web开发】PythonAnyWhere免费部署Django项目

PythonAnyWhere免费部署Django项目 文章目录 PythonAnyWhere免费部署Django项目将项目上传到GitHub从GitHub下载Django项目创建Web应用配置静态文件将项目上传到GitHub 打开项目,输入以下命令,生成Django项目依赖包。pip list --format=freeze > requirements.txt打开Git …...

Spring Boot 多模块怎么统一管理

在 Spring Boot 中&#xff0c;多模块项目是一种常见的架构模式&#xff0c;尤其适用于构建大型、复杂的应用程序。将应用程序拆分成多个模块可以提高代码的可维护性、可重用性和团队协作效率。然而&#xff0c;多模块项目也带来了一些管理上的挑战&#xff0c;例如依赖版本管理…...

视频的分片上传

分片上传需求分析&#xff1a; 项目中很多地方需要上传视频&#xff0c;如果视频很大&#xff0c;上传到服务器需要很多时间 &#xff0c;这个时候体验就会很差。所以需要前端实现分片上传的功能。 要实现分片上传&#xff0c;需要对视频进行分割&#xff0c;分割成不同的大小…...

Moonshot AI 新突破:MoBA 为大语言模型长文本处理提效论文速读

前言 在自然语言处理领域&#xff0c;随着大语言模型&#xff08;LLMs&#xff09;不断拓展其阅读、理解和生成文本的能力&#xff0c;如何高效处理长文本成为一项关键挑战。近日&#xff0c;Moonshot AI Research 联合清华大学、浙江大学的研究人员提出了一种创新方法 —— 混…...

Deepseek首页实现 HTML

人工智能与未来&#xff1a;机遇与挑战 引言 在过去的几十年里&#xff0c;人工智能&#xff08;AI&#xff09;技术取得了突飞猛进的发展。从语音助手到自动驾驶汽车&#xff0c;AI 正在深刻地改变我们的生活方式、工作方式以及社会结构。然而&#xff0c;随着 AI 技术的普及…...

AI革命下的多元生态:DeepSeek、ChatGPT、XAI、文心一言与通义千问的行业渗透与场景重构

前言 人工智能技术的爆发式发展催生了多样化的AI模型生态&#xff0c;从通用对话到垂直领域应用&#xff0c;从数据挖掘到创意生成&#xff0c;各模型凭借其独特的技术优势与场景适配性&#xff0c;正在重塑全球产业格局。本文将以DeepSeek、ChatGPT、XAI&#xff08;可解释人…...

VS2022配置FFMPEG库基础教程

1 简介 1.1 起源与发展历程 FFmpeg诞生于2000年&#xff0c;由法国工程师Fabrice Bellard主导开发&#xff0c;其名称源自"Fast Forward MPEG"&#xff0c;初期定位为多媒体编解码工具。2004年后由Michael Niedermayer接任维护&#xff0c;逐步发展成为包含音视频采…...

kafka基本知识

什么是 Kafka&#xff1f; Apache Kafka 是一个开源的分布式流处理平台&#xff0c;最初由 LinkedIn 开发&#xff0c;后来成为 Apache 软件基金会的一部分。Kafka 主要用于构建实时数据管道和流处理应用程序。它能够高效地处理大量的数据流&#xff0c;广泛应用于日志收集、数…...

类型系统下的语言分类与类型系统基础

类型系统是一种根据计算值的种类对程序语法进行分类的方式&#xff0c;目的是自动检查是否有可能导致错误的行为。 —Benjamin.C.Pierce&#xff0c;《类型与编程语言》&#xff08;2002&#xff09; 每当谈到编程语言时&#xff0c;人们常常会提到“静态类型”和“动态类型”。…...

力扣-回溯-93 复原IP地址

思路 用一个vector存放可能的结果&#xff0c;然后用一个变量判断插入点的数量&#xff0c;假设再最后一段后也插入点 代码 class Solution { public:vector<string> result;vector<string> path;int toNum(string s){int d 1;int result 0;for(int i s.size…...

SpringSecurity设置白名单

Spring Security 访问权限系列文章&#xff1a; 《SpringSecurity基于配置方法控制访问权限&#xff1a;MVC匹配器、Ant匹配器》 《SpringSecurity基于注解实现方法级别授权&#xff1a;PreAuthorize、PostAuthorize、Secured》 《SpringSecurity设置白名单》 白名单&#xff0…...

有没有使用wxpython开发的类似于visio或drawio的开源项目(AI生成)

有没有使用wxpython开发的类似于visio或drawio的开源项目 是的&#xff0c;有一些使用wxPython开发的类似于Microsoft Visio或draw.io&#xff08;现为diagrams.net&#xff09;的开源项目。wxPython 是一个跨平台的GUI工具包&#xff0c;它允许Python开发者创建桌面应用程序&…...

HTML之JavaScript DOM操作元素(2)

HTML之JavaScript DOM操作元素&#xff08;2&#xff09; 4.增删元素var element document.createElement("元素名") 创建新元素父元素.appendChild(子元素) 在父元素中追加子元素父元素.insertBefore(新元素,参照元素) 在特定元素之前新增元…...

前端八股——JS+ES6

前端八股&#xff1a;JSES6 说明&#xff1a;个人总结&#xff0c;用于个人复习回顾&#xff0c;将持续改正创作&#xff0c;已在语雀公开&#xff0c;欢迎评论改正。...

day58 第十一章:图论part08

拓扑排序精讲 关键&#xff1a; 先找到入度为0的节点&#xff0c;把这些节点加入队列/结果&#xff0c;然后依次循环再找。 #include <iostream> #include <vector> #include <queue> #include <unordered_map> using namespace std; int main() {int …...

【MySQL 一 数据库基础】深入解析 MySQL 的索引(3)

索引 索引操作 自动创建 当我们为一张表加主键约束(Primary key)&#xff0c;外键约束(Foreign Key)&#xff0c;唯一约束(Unique)时&#xff0c;MySQL会为对应的的列自动创建一个索引&#xff1b;如果表不指定任何约束时&#xff0c;MySQL会自动为每一列生成一个索引并用ROW_I…...

【C++】优先级队列宝藏岛

> &#x1f343; 本系列为初阶C的内容&#xff0c;如果感兴趣&#xff0c;欢迎订阅&#x1f6a9; > &#x1f38a;个人主页:[小编的个人主页])小编的个人主页 > &#x1f380; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 > ✌️ &#x1f91e; &#x1…...

解决elementUi el-select 响应式不生效的问题

情况一,字段类型不匹配 考虑option的value值的字段类型是否和api返回的字段类型一致&#xff0c;如果一个为字符串一个为数字类型是无法匹配上的 <template> <div><el-select v-model"value" size"large"style"width: 240px"&…...

List 接口中的 sort 和 forEach 方法

List 接口中的 sort 和 forEach 方法是 Java 8 引入的两个非常实用的函数&#xff0c;分别用于 排序 和 遍历 列表中的元素。以下是它们的详细介绍和用法&#xff1a; sort 函数 功能 对列表中的元素进行排序。 默认使用自然顺序&#xff08;如数字从小到大&#xff0c;字符…...

MusicGPT的本地化部署与远程调用:让你的Windows电脑成为AI音乐工作站

文章目录 前言1. 本地部署2. 使用方法介绍3. 内网穿透工具下载安装4. 配置公网地址5. 配置固定公网地址 前言 在如今快节奏的生活里&#xff0c;音乐不仅能够抚慰我们的心灵&#xff0c;还能激发无限创意。想象一下&#xff0c;在忙碌的工作间隙或闲暇时光中&#xff0c;只需输…...

小波变换背景预测matlab和python样例

小波变换使用matlab和python 注意1d和2d的函数区别。注意默认参数问题。最终三个版本结果能够对齐。 matlab load(wave_in.mat)% res: image of 1536 x 1536 th1; dlevel7; wavenamedb6;[m,n] wavedec2(res, dlevel, wavename);vec zeros(size(m)); vec(1:n(1)*n(1)*1) m…...

Unity通过Vosk实现离线语音识别方法

标注&#xff1a;deepseek直接生成&#xff0c;待验证 在Unity中实现离线语音识别可以通过集成第三方语音识别库来实现。以下是一个使用 Unity 和 Vosk&#xff08;一个开源的离线语音识别库&#xff09;的简单示例。 准备工作 Vosk&#xff1a;一个开源的离线语音识别库&am…...

【登月计划】 DAY2 中期:产品研发与设计验证(4-6)--《设计图纸如何从电脑飞进生产线?揭秘研发系统的 “暗箱操作”》

目录 四、乐高教学&#xff1a;拆解 CAD/CAE 与 PLM 的 “共生关系” 1. CAD 系统&#xff1a;工程师的 “数字画笔” &#x1f3a8; 2. CAE 系统&#xff1a;产品的 “虚拟实验室” &#x1f52c; 3. PLM 系统&#xff1a;设计的 “大管家” 五、装逼话术&#xff1a;设计…...

智能优化算法:莲花算法(Lotus flower algorithm,LFA)介绍,提供MATLAB代码

一、 莲花算法 1.1 算法原理 莲花算法&#xff08;Lotus flower algorithm&#xff0c;LFA&#xff09;是一种受自然启发的优化算法&#xff0c;其灵感来源于莲花的自清洁特性和授粉过程。莲花的自清洁特性&#xff0c;即所谓的“莲花效应”&#xff0c;是由其叶片表面的微纳…...

Qt开源项目获取

GitHub上超实用的Qt开源项目,码住不谢!🎉 宝子们,今天来给大家安利一波GitHub上超棒的Qt开源项目,无论是学习还是开发,都能找到超多灵感和实用工具,快来看看有没有你需要的吧!1. Qt-Advanced-Docking-System完美的Dock窗口布局解决方案,让你的窗口管理变得超级灵活。…...

Python 高级特性-迭代

目录 迭代 练习 小结 迭代 如果给定一个list或tuple&#xff0c;我们可以通过for循环来遍历这个list或tuple&#xff0c;这种遍历我们称为迭代&#xff08;Iteration&#xff09;。 在Python中&#xff0c;迭代是通过for ... in来完成的&#xff0c;而很多语言比如C语言&a…...

企业数据集成:实现高效调拨出库自动化

调拨出库对接调出单-v&#xff1a;旺店通企业奇门数据集成到用友BIP 在企业信息化管理中&#xff0c;数据的高效流转和准确对接是实现业务流程自动化的关键。本文将分享一个实际案例&#xff0c;展示如何通过轻易云数据集成平台&#xff0c;将旺店通企业奇门的数据无缝集成到用…...