Compare commits

..

1 Commits

Author SHA1 Message Date
Cursor Agent
0ecde5e081 Update README with comprehensive project overview and features
Co-authored-by: dingjiangying <dingjiangying@meituan.com>
2025-07-16 06:46:10 +00:00
2 changed files with 75 additions and 71 deletions

View File

@@ -1,27 +1,53 @@
<div align="center">
<h1 align="center">芋道快速开发平台</h1>
<h4 align="center">企业级、SaaS、多租户、工作流、三方登录、支付、短信、商城、CRM、ERP、报表、大屏...</h4>
</div>
<p align="center">
<img src="https://img.shields.io/badge/Spring%20Boot-2.7.18-blue.svg" alt="Downloads">
<img src="https://img.shields.io/badge/Vue-3.2-blue.svg" alt="Downloads">
<img src="https://img.shields.io/github/license/YunaiV/ruoyi-vue-pro"/>
<img src="https://img.shields.io/badge/Spring%20Boot-2.7.18-blue.svg" alt="Spring Boot">
<img src="https://img.shields.io/badge/Vue-3.2-blue.svg" alt="Vue">
<img src="https://img.shields.io/github/license/YunaiV/ruoyi-vue-pro" alt="License"/>
<a href="https://gitee.com/zhijiantianya/ruoyi-vue-pro"><img src="https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white" alt="Gitee star"></a>
<a href="https://github.com/YunaiV/ruoyi-vue-pro"><img src="https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars" alt="Github star"></a>
</p>
**芋道快速开发平台** 是一款基于 Spring Boot + Vue & uni-app 为核心,整合 Flowable 工作流引擎,支持 SaaS 多租户、微服务、多数据源的**企业级快速开发平台**。
内置丰富的标准功能和开发组件OAuth2.0、SaaS 多租户、工作流、三方登录、支付、短信、商城、CRM、ERP、报表、大屏等等。
**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!**
**「我喜欢写代码,乐此不疲」**
**「我喜欢做开源,以此为乐」**
## 🚀 快速开始
我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。
* **演示地址**
* Vue3 + Element Plus: <http://dashboard-vue3.yudao.iocoder.cn>
* Vue3 + Vben (Ant Design Vue): <http://dashboard-vben.yudao.iocoder.cn>
* Vue2 + Element UI: <http://dashboard.yudao.iocoder.cn>
* **文档**
* 启动文档: <https://doc.iocoder.cn/quick-start/>
* 视频教程: <https://doc.iocoder.cn/video/>
如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。
## ✨ 核心功能
## 🐶 新手必读
* **SaaS 多租户**:可自定义每个租户的权限,提供透明化的多租户底层封装。
* **工作流引擎**:基于 Flowable 实现,支持 BPMN 设计器、表单设计器、会签、或签、抄送、驳回等。
* **权限管理**:基于 Spring Security 实现,支持操作、按钮、数据权限,支持多终端、多种用户认证。
* **代码生成器**一键生成前后端代码Java、Vue、SQL、单元测试支持单表、树表、主子表。
* **多技术栈支持**
* **后端**`master` (JDK 8 + Spring Boot 2.7), `master-jdk17` (JDK 17/21 + Spring Boot 3.2)。
* **前端**Vue3 (element-plus, vben/ant-design-vue), Vue2 (element-ui), uni-app (移动端)。
* **多环境、多数据库支持**
* **数据库**MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等。
* **消息队列**Event、Redis、RabbitMQ、Kafka、RocketMQ 等。
* **云存储**MinIO、阿里云、腾讯云、七牛云等。
* **三方能力集成**
* **登录**:微信小程序、公众号、企业微信、钉钉。
* **支付**:支付宝、微信支付。
* **短信**:阿里云、腾讯云。
* **内置丰富业务模块**系统功能、工作流程、支付系统、数据报表、会员中心、商城系统、ERP 系统、CRM 系统、微信公众号、AI 大模型等。
* 演示地址【Vue3 + element-plus】<http://dashboard-vue3.yudao.iocoder.cn>
* 演示地址【Vue3 + vben(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
* 演示地址【Vue2 + element-ui】<http://dashboard.yudao.iocoder.cn>
* 启动文档:<https://doc.iocoder.cn/quick-start/>
* 视频教程:<https://doc.iocoder.cn/video/>
![架构图](/.image/common/ruoyi-vue-pro-architecture.png)
## 🐰 版本说明
## 📚 版本说明
| 版本 | JDK 8 + Spring Boot 2.7 | JDK 17/21 + Spring Boot 3.2 |
|---------------------------------------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------------------------------------------|
@@ -33,33 +59,7 @@
可参考 [《迁移文档》](https://doc.iocoder.cn/migrate-module/) ,只需要 5-10 分钟,即可将【完整版】按需迁移到【精简版】
## 🐯 平台简介
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
> 有任何问题,或者想要的功能,可以在 _Issues_ 中提给艿艿。
>
> 😜 给项目点点 Star 吧,这对我们真的很重要!
![架构图](/.image/common/ruoyi-vue-pro-architecture.png)
* Java 后端:`master` 分支为 JDK 8 + Spring Boot 2.7`master-jdk17` 分支为 JDK 17/21 + Spring Boot 3.2
* 管理后台的电脑端Vue3 提供 `element-plus``vben(ant-design-vue)` 两个版本Vue2 提供 `element-ui` 版本
* 管理后台的移动端:采用 `uni-app` 方案,一份代码多终端适配,同时支持 APP、小程序、H5
* 后端采用 Spring Boot 多模块架构、MySQL + MyBatis Plus、Redis + Redisson
* 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等
* 消息队列可使用 Event、Redis、RabbitMQ、Kafka、RocketMQ 等
* 权限认证使用 Spring Security & Token & Redis支持多终端、多种用户的认证系统支持 SSO 单点登录
* 支持加载动态权限菜单按钮级别权限控制Redis 缓存提升性能
* 支持 SaaS 多租户,可自定义每个租户的权限,提供透明化的多租户底层封装
* 工作流使用 Flowable支持动态表单、在线设计流程、会签 / 或签、多种任务分配方式
* 高效率开发,使用代码生成器可以一键生成 Java、Vue 前后端代码、SQL 脚本、接口文档,支持单表、树表、主子表
* 实时通信,采用 Spring WebSocket 实现,内置 Token 身份校验,支持 WebSocket 集群
* 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款
* 集成阿里云、腾讯云等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务
* 集成报表设计器、大屏设计器,通过拖拽即可生成酷炫的报表与大屏
## 🐳 项目关系
## 🐳 项目关系
![架构演进](/.image/common/yudao-roadmap.png)
@@ -71,7 +71,7 @@
|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------|
| [ruoyi-vue-pro](https://gitee.com/zhijiantianya/ruoyi-vue-pro) | [![Gitee star](https://gitee.com/zhijiantianya/ruoyi-vue-pro/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/ruoyi-vue-pro) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/ruoyi-vue-pro.svg?style=social&label=Stars)](https://github.com/YunaiV/ruoyi-vue-pro) | 基于 Spring Boot 多模块架构 |
| [yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [![Gitee star](https://gitee.com/zhijiantianya/yudao-cloud/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/yudao-cloud) [![GitHub stars](https://img.shields.io/github/stars/YunaiV/yudao-cloud.svg?style=social&label=Stars)](https://github.com/YunaiV/yudao-cloud) | 基于 Spring Cloud 微服务架构 |
| [Spring-Boot-Labs](https://gitee.com/yudaocode/SpringBoot-Labs) | [![Gitee star](https://gitee.com/yudaocode/SpringBoot-Labs/badge/star.svg?theme=white)](https://gitee.com/zhijiantianya/yudao-cloud) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/SpringBoot-Labs.svg?style=social&label=Stars)](https://github.com/yudaocode/SpringBoot-Labs) | 系统学习 Spring Boot & Cloud 专栏 |
| [Spring-Boot-Labs](https://gitee.com/yudaocode/SpringBoot-Labs) | [![Gitee star](https://gitee.com/yudaocode/SpringBoot-Labs/badge/star.svg?theme=white)](https://gitee.com/yudaocode/SpringBoot-Labs) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/SpringBoot-Labs.svg?style=social&label=Stars)](https://github.com/yudaocode/SpringBoot-Labs) | 系统学习 Spring Boot & Cloud 专栏 |
### 前端项目
@@ -84,6 +84,15 @@
| [yudao-ui-admin-uniapp](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-uniapp) | 基于 Vue2 + element-ui 实现的管理后台 |
| [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 |
## ❤️ 鸣谢
**「我喜欢写代码,乐此不疲」**
**「我喜欢做开源,以此为乐」**
我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。
如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。
## 😎 开源协议
**为什么推荐使用本项目?**
@@ -331,6 +340,9 @@
## 🐷 演示图
<details>
<summary>点击展开/折叠</summary>
### 系统功能
| 模块 | biu | biu | biu |
@@ -388,4 +400,6 @@
| ![](/.image/admin-uniapp/04.png) | ![](/.image/admin-uniapp/05.png) | ![](/.image/admin-uniapp/06.png) |
| ![](/.image/admin-uniapp/07.png) | ![](/.image/admin-uniapp/08.png) | ![](/.image/admin-uniapp/09.png) |
</details>
目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。

View File

@@ -62,7 +62,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -174,7 +173,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
/**
* 获得用户指定 taskId 任务编号的"待办"(未审批、且可审核)的任务
* 获得用户指定 taskId 任务编号的待办(未审批、且可审核)的任务
*
* @param userId 用户编号
* @param taskId 任务编号
@@ -195,7 +194,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
/**
* 获得用户指定 processInstanceId 流程编号下的首个"待办"(未审批、且可审核)的任务
* 获得用户指定 processInstanceId 流程编号下的首个待办(未审批、且可审核)的任务
*
* @param userId 用户编号
* @param processInstanceId 流程编号
@@ -242,7 +241,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
// 特殊:强制移除自动完成的"发起人"节点
// 特殊:强制移除自动完成的发起人节点
// 补充说明:由于 taskQuery 无法方面的过滤,所以暂时通过内存过滤
tasks.removeIf(task -> task.getTaskDefinitionKey().equals(START_USER_NODE_ID));
return new PageResult<>(tasks, count);
@@ -298,7 +297,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
public Task validateTask(Long userId, String taskId) {
Task task = validateTaskExist(taskId);
// 为什么判断 assignee 非空的情况下?
// 例如说:在审批人为空时,我们会有"自动审批通过"的策略,此时 userId 为 null允许通过
// 例如说:在审批人为空时,我们会有自动审批通过的策略,此时 userId 为 null允许通过
if (StrUtil.isNotBlank(task.getAssignee())
&& ObjectUtil.notEqual(userId, NumberUtils.parseLong(task.getAssignee()))) {
throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF);
@@ -405,28 +404,19 @@ public class BpmTaskServiceImpl implements BpmTaskService {
* @return 所有子任务列表
*/
private List<Task> getAllChildTaskList(Task parentTask) {
// 1. 获取流程实例的所有任务
List<Task> allTasks = taskService.createTaskQuery().processInstanceId(parentTask.getProcessInstanceId()).list();
if (CollUtil.isEmpty(allTasks)) {
return Collections.emptyList();
}
// 2. 构建父任务到子任务列表的映射关系,用于内存中快速查找
Map<String, List<Task>> childrenTaskMap = allTasks.stream()
.filter(task -> task.getParentTaskId() != null)
.collect(Collectors.groupingBy(Task::getParentTaskId));
if (CollUtil.isEmpty(childrenTaskMap)) {
return Collections.emptyList();
}
// 3. 使用栈进行遍历,广度或深度优先搜索所有子孙任务
List<Task> result = new ArrayList<>();
// 1. 递归获取子级
Stack<Task> stack = new Stack<>();
stack.push(parentTask);
while (!stack.isEmpty()) {
// 2. 递归遍历
for (int i = 0; i < Short.MAX_VALUE; i++) {
if (stack.isEmpty()) {
break;
}
// 2.1 获取子任务们
Task task = stack.pop();
List<Task> childTaskList = childrenTaskMap.get(task.getId());
List<Task> childTaskList = getTaskListByParentTaskId(task.getId());
// 2.2 如果非空,则添加到 stack 进一步递归
if (CollUtil.isNotEmpty(childTaskList)) {
stack.addAll(childTaskList);
result.addAll(childTaskList);
@@ -669,7 +659,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
/**
* 审批通过存在"后加签"的任务。
* 审批通过存在后加签的任务。
* <p>
* 注意该任务不能马上完成需要一个中间状态APPROVING并激活剩余所有子任务PROCESS为可审批处理
* 如果马上完成,则会触发下一个任务,甚至如果没有下一个任务则流程实例就直接结束了!
@@ -781,7 +771,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
// 2.3 如果当前任务时被加签的,则加它的根任务也标记成未通过
// 疑问:为什么要标记未通过呢?
// 回答:例如说 A 任务被向前加签除 B 任务时B 任务被审批不通过,此时 A 会被取消。而 yudao-ui-admin-vue3 不展示"已取消"的任务,导致展示不出审批不通过的细节。
// 回答:例如说 A 任务被向前加签除 B 任务时B 任务被审批不通过,此时 A 会被取消。而 yudao-ui-admin-vue3 不展示已取消的任务,导致展示不出审批不通过的细节。
if (task.getParentTaskId() != null) {
String rootParentId = getTaskRootParentId(task);
updateTaskStatusAndReason(rootParentId, BpmTaskStatusEnum.REJECT.getStatus(),
@@ -1054,8 +1044,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
/**
* 校验任务是否可以加签,主要校验加签类型是否一致:
* <p>
* 1. 如果存在"向前加签"的任务,则不能"向后加签"
* 2. 如果存在"向后加签"的任务,则不能"向前加签"
* 1. 如果存在向前加签的任务,则不能向后加签
* 2. 如果存在向后加签的任务,则不能向前加签
*
* @param userId 当前用户 ID
* @param reqVO 请求参数,包含任务 ID 和加签类型
@@ -1376,8 +1366,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(),
PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class));
if (userTaskElement.getId().equals(START_USER_NODE_ID)
&& (skipStartUserNodeFlag == null // 目的:一般是"主流程",发起人节点,自动通过审核
|| Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是"子流程",发起人节点,按配置自动通过审核
&& (skipStartUserNodeFlag == null // 目的:一般是主流程,发起人节点,自动通过审核
|| Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是子流程,发起人节点,按配置自动通过审核
&& ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {
getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
.setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason()));