!635 合并 warmflow 功能分支
* update 优化 工作流设计器支持token传输 只需要放行token头获取即可
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 优化 无需多余set变量
* update 优化 避免重复处理
* update 优化 实体类隔离
* add 增加流程启动,办理接口
* update 调整流程驳回
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update warmflow 1.3.7
* update 增加 warmflow oracle pg sqlserver sql脚本文件
* update 增加 warmflow oracle pg sqlserver sql脚本文件
* add 新增workflow不同的sql语句
* add 新增添加租户同步默认流程定义
* update 优化 流程列表查询 删除无用mapper
* update 导入流程 支持并发多文件上传
* update 调整流程定义查询
* update 优化 统一书写格式
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 优化发布事件增加租户ID
* update 调整驳回记录
* Revert "update 获取用户简略信息,祖级部门列表,部门负责人等"
* update 获取用户简略信息,祖级部门列表,部门负责人等
* update 更新warm-flow版本到v1.3.6-m1
* update 更新注释信息
* fix 临时修复 warm参数读取问题
* update warm-flow 1.3.4 => 1.3.5 优化流程图导入
* update 更新warm-flow版本到v1.3.5 2024-12-20
* update 增加抄送人名称
* update 我的抄送增加申请人以及更新时间
* update 优化监听事件注释
* update 优化流程分类名称翻译回显
* fix 修改根据流程分类id查询
* update 新增流程分类id查询
* fix 修复抄送错误
* fix 修复错误判空
* fix 修复错误判空
* update 新增删除流程事件
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 调整sql书写顺序
* fix 修复 抄送缺数据问题 与 已完成任务数据取错问题
* update 新增根据业务id查询流程实例详细信息
* update 调整变量参数
* update 调整分类接口
* update 统一业务id参数
* update 调整返回参数
* update 增加业务id通用查询条件
* update 优化代码 修复bug
* update 优化新增流程分类判断
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 调整驳回
* update 优化错误注释
* update 优化流程分类sql语句
* update 调整驳回
* update 删除流程分类状态
* update 增加流程定义防重
* [fix]
* update 优化代码 修复bug
* update 优化流程定义增加类别树查询
* update 新增翻译根据流程分类ID查询流程分类名称
* update 根据分页对象构建表格分页数据对象
* update 优化流程定义列表名称
* update 优化流程分类校验
* update 导入流程 支持自定义类别
* update 流程案例 增加表单路径
* update 流程定义查询返回表单路径
* update 优化任务业务层
* fix 修复 请假天数不准确问题
* update 优化驳回 撤销
* update 删除类别查询权限 通用查询不需要加权限
* fix 修复 变量名修改错误
* Merge branch 'warm-flow-future' of https://gitee.com/dromara/RuoYi-Vue…
* update 调整驳回
* update 表名类名统一命名
* Merge branch 'warm-flow-future' of https://gitee.com/dromara/RuoYi-Vue…
* update 挑战者驳回 撤销
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* fix 修复会签 票签撤销问题
* update 调整并行环节撤销错误 增加办理校验
* Merge branch 'warm-flow-future' of https://gitee.com/dromara/RuoYi-Vue…
* update 优化获取办理人
* update 优化 workflow模块增加doc依赖输出接口文档
* Revert "update 优化 删除无用方法"
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* Merge branch 'warm-flow-future' of https://gitee.com/dromara/RuoYi-Vue…
* update 调整代办人查询错误 增加示例
* update 优化 重构代码
* update 优化 重构代码
* update 优化 将工作流消息推送改为sse
* add 添加模型
* update 调整审批记录
* update 调整请假案例
* fix 修复流程定义查询错误
* update 调整流程实例查询错误
* update 调整获取当前登录任务实例
* add 添加消息发送
* update 调整办理监听
* [add]
* [fix]
* update 重构 将工作流查询逻辑封装为单独的service类
* [update]
* [add]
* 办理附件提交
* 申请人查询修改
* update 回退优化 删除无用方法
* update 优化任务办理人翻译实现
* update 优化任务分配人枚举
* update 优化 删除无用方法
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* [add]
* update 优化全局任务办理监听
* update 删除无用引入
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 优化激活/挂起取反逻辑
* !614 style workflow xml 格式
* style workflow xml 格式
* !612 fix FlwInstanceMapper xml错误
* fix FlwInstanceMapper xml错误
* update 优化 后端代码
* update 优化接口请求路径
* update 调整已办排序
* add 添加任务作废
* update 调整任务办理操作
* update 调整加签,减签校验
* update 调整加签
* add 添加获取当前任务的办理人接口
* add 添加任务查询会签,票签比例
* update 调整任务,实例查询
* update 调整任务委托,转办,优化部分代码等
* update 调整流程定义视图
* add 添加任务,流程实例常用查询接口
* Merge branch 'dev' into warm-flow-future
* update 优化工作流常量使用
* update 优化流程记录运行时长获取
* update 优化任务管理控制层
* update 回复业务状态枚举
* update 优化业务状态枚举
* update 调整昵称翻译
* update 调整修改办理人接口
* update 调整流程全局监听,调整任务办理人批量修改,优化代码
* update 优化查询可驳回节点
* update 优化添加抄送人
* update 优化增加人员类型枚举,删除无用常量
* update 优化请假天数工具类,删除缓存,加锁处理,可以采用外部传参的形式处理redis部分
* update 优化请假天数计算
* update 优化任务完成时间处理
* update 优化任务办理人获取
* update 优化任务操作,委派、转办、加签、减签、修改办理人等
* add 新增warm-flow-all.sql
* del 删除多余SQL
* del 删除无用vo
* del 删除表单管理信息
* del 删除节点配置信息
* update 优化节点类型常量获取
* update 优化权限办理人获取
* update 优化权限办理人获取判断
* update 提交等待新版本待优化的开始监听信息
* update 新增获取部门负责人
* add 新增分派办理人监听器
* update 优化或者字符串用户ID
* update 用户前缀去掉
* update 调整流程实例状态查询
* add 添加流程撤销
* add 添加流程抄送
* add 新增办理人权限处理器
* update 升级warm-flow1.3.4
* Merge branch 'dev' into warm-flow-future
* update 调整流程定义复制
* update 调整流程启动设置启动人变量
* update 调整流程定义删除
* update 调整流程定义导入
* update 调整工作流任务,流程定义等查询
* update 调整工作流人员翻译查询
* update 调整转办,加签等参数
* update 调整流程办理设置办理人
* update 调整流程设计保存
* update 调整流程状态,移除过时方法,调整查询办理人
* update 补充工作流请求增加鉴权
* update 工作流请求增加鉴权
* update 新增流程完成监听器
* update 新增流程启动监听器
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 更新warm-flow版本
* update 优化workflow表sql格式
* update 优化,增加岗位权限判空处理
* update 当前用户所有权限岗位ID改为从token获取
* update 当前用户所有权限增加岗位ID权限
* update 更新通过岗位ID查询用户
* update 优化激活/挂起流程定义判断
* Revert "add 新增异常处理器和工作流封装包"
* add 新增异常处理器和工作流封装包
* update 优化待办任务查询以及任务流转
* update 优化工作流工具,避免多次获取请求
* fix 修改无效标识
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 查询部门并返回任务指派的列表根据部门树搜索
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 优化任务办理人分组
* update 优化任务办理人查询
* update 优化任务办理人查询
* update 优化任务办理人
* update 完善任务办理人
* add 新增角色办理人
* !596 优化工作流代码逻辑
* update 优化工作流工具冗余代码
* update 优化工作流代码逻辑
* update 调整办理 驳回 终止等状态
* update 调整流程定义查询
* 解决冲突提交 warmflow代码
* update 升级warm-flow到1.3.0 调整流程办理 ,驳回,终止等 添加自定义监听
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 调整流程xml查询
* update 调整驳回
* update 升级warm-flow
* update 调整任务办理设置办理人
* 调整转办,委托参数
* update warm-flow 1.2.4 => 1.2.7
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 调整抄送错误
* 添加已办,未办
* Merge branch 'warm-flow-future' of https://gitee.com/dromara/RuoYi-Vue…
* add 添加我发起的单据接口
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 调整流程实例,待办查询
* remove 删除无用校验
* add 添加待办人查询
* Merge branch 'dev' into warm-flow-future
* update 调整字段错误,流程导入
* add 添加流程激活/挂起接口 升级warm-flow到1.2.4
* add 添加历史流程定义查询 调整流程发布
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* Merge remote-tracking branch 'origin/dev' into warm-flow-future
* update 优化 TenantSpringCacheManager 处理逻辑
* fix 修复 一级缓存key未区分租户问题
* update 优化 角色权限判断
* update 更新 readme
* update 优化 增加删除标志位常量优化查询代码
* fix 修复 登出无法正确删除对应的租户数据问题
* update 优化 sse 拦截网络中断io异常
* fix 修复 登录错误锁定不区分租户问题
* update 优化 sse 关闭连接各种异常问题
* update 优化 监控使用独立web依赖
* fix 修复 代码生成 错误匹配表名问题
* update 优化 适配 anyline 新改动
* update anyline 8.7.2-20240728
* update 脱敏策略优化增加密码
* add 新增 更多脱敏策略
* update 优化oss查询代码
* update 优化 sse发送消息 增加token有效期判断
* fix 修复 登出后重新登录 sse推送报错问题
* fix 修复 代码生成 数据源切换问题
* update anyline 8.7.2-20240726
* fix 修复 代码生成 表结构缓存问题
* update snailjob 1.1.0 => 1.1.1
* fix 修复 代码生成 表结构缓存问题
* update 优化 sse 自动装配
* 初始化添加warm-flow
已添加51个文件
已复制1个文件
已重命名3个文件
已删除96个文件
已修改30个文件
19848 ■■■■■ 文件已修改
pom.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application.yml 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java 76 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/pom.xml 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java 113 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeType.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfCategory.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowVariableVo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java 1120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java 431 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java 444 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java 691 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java 861 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java 275 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java 455 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java 669 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java 132 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java 289 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java 363 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/bpmn/leave1.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/bpmn/leave2.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/bpmn/leave3.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/bpmn/leave4.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/bpmn/leave5.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/bpmn/模型.zip 补丁 | 查看 | 原始文档 | blame | 历史
script/sql/oracle/oracle_ry_workflow.sql 603 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/sql/postgres/postgres_ry_workflow.sql 658 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/sql/ry_workflow.sql 403 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/sql/sqlserver/sqlserver_ry_vue_5.X.sql 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
script/sql/sqlserver/sqlserver_ry_workflow.sql 1764 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -50,7 +50,7 @@
        <!-- é¢å‘运行时的D-ORM依赖 -->
        <anyline.version>8.7.2-20241022</anyline.version>
        <!--工作流配置-->
        <flowable.version>7.0.1</flowable.version>
        <warm-flow.version>1.3.7</warm-flow.version>
        <!-- æ’件版本 -->
        <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
@@ -118,12 +118,16 @@
                <scope>import</scope>
            </dependency>
            <!-- Warm-Flow国产工作流引擎, åœ¨çº¿æ–‡æ¡£ï¼šhttp://warm-flow.cn/ -->
            <dependency>
                <groupId>org.flowable</groupId>
                <artifactId>flowable-bom</artifactId>
                <version>${flowable.version}</version>
                <type>pom</type>
                <scope>import</scope>
                <groupId>org.dromara.warm</groupId>
                <artifactId>warm-flow-mybatis-plus-sb3-starter</artifactId>
                <version>${warm-flow.version}</version>
            </dependency>
            <dependency>
                <groupId>org.dromara.warm</groupId>
                <artifactId>warm-flow-plugin-ui-sb-web</artifactId>
                <version>${warm-flow.version}</version>
            </dependency>
            <!-- JustAuth çš„依赖配置-->
ruoyi-admin/src/main/resources/application.yml
@@ -119,6 +119,7 @@
    - /error
    - /*/api-docs
    - /*/api-docs/**
    - /warm-flow-ui/token-name
# å¤šç§Ÿæˆ·é…ç½®
tenant:
@@ -227,8 +228,7 @@
  # æŽ’除链接(多个用逗号分隔)
  excludeUrls:
    - /system/notice
    - /workflow/model/save
    - /workflow/model/editModelXml
    - /warm-flow/save-xml
# å…¨å±€çº¿ç¨‹æ± ç›¸å…³é…ç½®
# å¦‚使用JDK21请直接使用虚拟线程 ä¸è¦å¼€å¯æ­¤é…ç½®
@@ -273,24 +273,11 @@
  # è®¾ç½®è®¿é—®æºåœ°å€
  allowedOrigins: '*'
--- #flowable配置
flowable:
  # å¼€å…³ ç”¨äºŽå¯åЍ/停用工作流
--- # warm-flow工作流配置
warm-flow:
  # æ˜¯å¦å¼€å¯å·¥ä½œæµï¼Œé»˜è®¤true
  enabled: true
  process.enabled: ${flowable.enabled}
  eventregistry.enabled: ${flowable.enabled}
  async-executor-activate: false #关闭定时任务JOB
  #  å°†databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。
  database-schema-update: true
  activity-font-name: å®‹ä½“
  label-font-name: å®‹ä½“
  annotation-font-name: å®‹ä½“
  # å…³é—­å„个模块生成表,目前只使用工作流基础表
  idm:
    enabled: false
  cmmn:
    enabled: false
  dmn:
    enabled: false
  app:
    enabled: false
  # æ˜¯å¦å¼€å¯è®¾è®¡å™¨ui
  ui: true
  # é»˜è®¤Authorization,如果有多个token,用逗号分隔
  token-name: ${sa-token.token-name},clientid
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
package org.dromara.common.core.domain.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
 * åŠžç†ä»»åŠ¡è¯·æ±‚å¯¹è±¡
 *
 * @author may
 */
@Data
public class CompleteTaskDTO implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * ä»»åŠ¡id
     */
    private Long taskId;
    /**
     * é™„ä»¶id
     */
    private String fileId;
    /**
     * æŠ„送人员
     */
    private List<FlowCopyDTO> flowCopyList;
    /**
     * æ¶ˆæ¯ç±»åž‹
     */
    private List<String> messageType;
    /**
     * åŠžç†æ„è§
     */
    private String message;
    /**
     * æ¶ˆæ¯é€šçŸ¥
     */
    private String notice;
    /**
     * æµç¨‹å˜é‡
     */
    private Map<String, Object> variables;
    /**
     * æ‰©å±•变量(此处为逗号分隔的ossId)
     */
    private String ext;
    public Map<String, Object> getVariables() {
        if (variables == null) {
            return new HashMap<>(16);
        }
        variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
        return variables;
    }
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java
copy from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java copy to ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java
Îļþ´Ó ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java ¸´ÖÆ
@@ -1,9 +1,10 @@
package org.dromara.workflow.domain.vo;
package org.dromara.common.core.domain.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
 * æŠ„送
@@ -11,7 +12,7 @@
 * @author may
 */
@Data
public class WfCopy implements Serializable {
public class FlowCopyDTO implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package org.dromara.common.core.domain.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
 * å¯åŠ¨æµç¨‹å¯¹è±¡
 *
 * @author may
 */
@Data
public class StartProcessDTO implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * ä¸šåС唝䏀值id
     */
    private String businessId;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * æµç¨‹å˜é‡ï¼Œå‰ç«¯ä¼šæäº¤ä¸€ä¸ªå…ƒç´ {'entity': {业务详情数据对象}}
     */
    private Map<String, Object> variables;
    public Map<String, Object> getVariables() {
        if (variables == null) {
            return new HashMap<>(16);
        }
        variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
        return variables;
    }
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
package org.dromara.common.core.domain.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * ä»»åŠ¡å—è®©äºº
 *
 * @author AprilWind
 */
@Data
@NoArgsConstructor
public class TaskAssigneeDTO implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * æ€»å¤§å°
     */
    private Long total = 0L;
    /**
     *
     */
    private List<TaskHandler> list;
    public TaskAssigneeDTO(Long total, List<TaskHandler> list) {
        this.total = total;
        this.list = list;
    }
    /**
     * å°†æºåˆ—表转换为 TaskHandler åˆ—表
     *
     * @param <T>              é€šç”¨ç±»åž‹
     * @param sourceList       å¾…转换的源列表
     * @param storageId        æå– storageId çš„函数
     * @param handlerCode      æå– handlerCode çš„函数
     * @param handlerName      æå– handlerName çš„函数
     * @param groupName        æå– groupName çš„函数
     * @param createTimeMapper æå– createTime çš„函数
     * @return è½¬æ¢åŽçš„ TaskHandler åˆ—表
     */
    public static <T> List<TaskHandler> convertToHandlerList(
        List<T> sourceList,
        Function<T, Long> storageId,
        Function<T, String> handlerCode,
        Function<T, String> handlerName,
        Function<T, Long> groupName,
        Function<T, Date> createTimeMapper) {
        return sourceList.stream()
            .map(item -> new TaskHandler(
                String.valueOf(storageId.apply(item)),
                handlerCode.apply(item),
                handlerName.apply(item),
                groupName != null ? String.valueOf(groupName.apply(item)) : null,
                createTimeMapper.apply(item)
            )).collect(Collectors.toList());
    }
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class TaskHandler {
        /**
         * ä¸»é”®
         */
        private String storageId;
        /**
         * æƒé™ç¼–码
         */
        private String handlerCode;
        /**
         * æƒé™åç§°
         */
        private String handlerName;
        /**
         * æƒé™åˆ†ç»„
         */
        private String groupName;
        /**
         * åˆ›å»ºæ—¶é—´
         */
        private Date createTime;
    }
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
package org.dromara.common.core.domain.event;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
 * åˆ é™¤æµç¨‹ç›‘听
 *
 * @author AprilWind
 */
@Data
public class ProcessDeleteEvent implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * ç§Ÿæˆ·ID
     */
    private String tenantId;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * ä¸šåŠ¡id
     */
    private String businessId;
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java
@@ -10,7 +10,6 @@
 *
 * @author may
 */
@Data
public class ProcessEvent implements Serializable {
@@ -18,14 +17,19 @@
    private static final long serialVersionUID = 1L;
    /**
     * æµç¨‹å®šä¹‰key
     * ç§Ÿæˆ·ID
     */
    private String key;
    private String tenantId;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * ä¸šåŠ¡id
     */
    private String businessKey;
    private String businessId;
    /**
     * çŠ¶æ€
@@ -36,6 +40,5 @@
     * å½“为true时为申请人节点办理
     */
    private boolean submit;
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java
@@ -10,7 +10,6 @@
 *
 * @author may
 */
@Data
public class ProcessTaskEvent implements Serializable {
@@ -18,23 +17,28 @@
    private static final long serialVersionUID = 1L;
    /**
     * æµç¨‹å®šä¹‰key
     * ç§Ÿæˆ·ID
     */
    private String key;
    private String tenantId;
    /**
     * å®¡æ‰¹èŠ‚ç‚¹key
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String taskDefinitionKey;
    private String flowCode;
    /**
     * å®¡æ‰¹èŠ‚ç‚¹ç¼–ç 
     */
    private String nodeCode;
    /**
     * ä»»åŠ¡id
     */
    private String taskId;
    private Long taskId;
    /**
     * ä¸šåŠ¡id
     */
    private String businessKey;
    private String businessId;
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package org.dromara.common.core.domain.model;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
 * ä»»åŠ¡å—è®©äºº
 *
 * @author AprilWind
 */
@Data
@NoArgsConstructor
public class TaskAssigneeBody implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * æƒé™ç¼–码
     */
    private String handlerCode;
    /**
     * æƒé™åç§°
     */
    private String handlerName;
    /**
     * æƒé™åˆ†ç»„
     */
    private String groupId;
    /**
     * å¼€å§‹æ—¶é—´
     */
    private String beginTime;
    /**
     * ç»“束时间
     */
    private String endTime;
    /**
     * å½“前页
     */
    private Integer pageNum = 1;
    /**
     * æ¯é¡µæ˜¾ç¤ºæ¡æ•°
     */
    private Integer pageSize = 10;
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java
@@ -7,6 +7,10 @@
import org.dromara.common.core.utils.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * ä¸šåŠ¡çŠ¶æ€æžšä¸¾
@@ -16,30 +20,37 @@
@Getter
@AllArgsConstructor
public enum BusinessStatusEnum {
    /**
     * å·²æ’¤é”€
     */
    CANCEL("cancel", "已撤销"),
    /**
     * è‰ç¨¿
     */
    DRAFT("draft", "草稿"),
    /**
     * å¾…审核
     */
    WAITING("waiting", "待审核"),
    /**
     * å·²å®Œæˆ
     */
    FINISH("finish", "已完成"),
    /**
     * å·²ä½œåºŸ
     */
    INVALID("invalid", "已作废"),
    /**
     * å·²é€€å›ž
     */
    BACK("back", "已退回"),
    /**
     * å·²ç»ˆæ­¢
     */
@@ -55,20 +66,72 @@
     */
    private final String desc;
    private static final Map<String, BusinessStatusEnum> STATUS_MAP = Arrays.stream(BusinessStatusEnum.values())
        .collect(Collectors.toConcurrentMap(BusinessStatusEnum::getStatus, Function.identity()));
    /**
     * èŽ·å–ä¸šåŠ¡çŠ¶æ€
     * æ ¹æ®çŠ¶æ€èŽ·å–å¯¹åº”çš„ BusinessStatusEnum æžšä¸¾
     *
     * @param status çŠ¶æ€
     * @param status ä¸šåŠ¡çŠ¶æ€ç 
     * @return å¯¹åº”çš„ BusinessStatusEnum æžšä¸¾ï¼Œå¦‚果找不到则返回 null
     */
    public static BusinessStatusEnum getByStatus(String status) {
        // ä½¿ç”¨ STATUS_MAP èŽ·å–å¯¹åº”çš„æžšä¸¾ï¼Œè‹¥æ‰¾ä¸åˆ°åˆ™è¿”å›ž null
        return STATUS_MAP.get(status);
    }
    /**
     * æ ¹æ®çŠ¶æ€èŽ·å–å¯¹åº”çš„ä¸šåŠ¡çŠ¶æ€æè¿°ä¿¡æ¯
     *
     * @param status ä¸šåŠ¡çŠ¶æ€ç 
     * @return è¿”回业务状态描述,若状态码为空或未找到对应的枚举,返回空字符串
     */
    public static String findByStatus(String status) {
        if (StringUtils.isBlank(status)) {
            return StrUtil.EMPTY;
        }
        return Arrays.stream(BusinessStatusEnum.values())
            .filter(statusEnum -> statusEnum.getStatus().equals(status))
            .findFirst()
            .map(BusinessStatusEnum::getDesc)
            .orElse(StrUtil.EMPTY);
        BusinessStatusEnum statusEnum = STATUS_MAP.get(status);
        return (statusEnum != null) ? statusEnum.getDesc() : StrUtil.EMPTY;
    }
    /**
     * åˆ¤æ–­æ˜¯å¦ä¸ºæŒ‡å®šçš„状态之一:草稿、已撤销或已退回
     *
     * @param status è¦æ£€æŸ¥çš„状态
     * @return å¦‚果状态为草稿、已撤销或已退回之一,则返回 true;否则返回 false
     */
    public static boolean isDraftOrCancelOrBack(String status) {
        return DRAFT.status.equals(status) || CANCEL.status.equals(status) || BACK.status.equals(status);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦ä¸ºæ’¤é”€ï¼Œé€€å›žï¼Œä½œåºŸï¼Œç»ˆæ­¢
     *
     * @param status status
     * @return ç»“æžœ
     */
    public static boolean initialState(String status) {
        return CANCEL.status.equals(status) || BACK.status.equals(status) || INVALID.status.equals(status) || TERMINATION.status.equals(status);
    }
    /**
     * èŽ·å–è¿è¡Œä¸­çš„å®žä¾‹çŠ¶æ€åˆ—è¡¨
     *
     * @return åŒ…含运行中实例状态的不可变列表
     * ï¼ˆåŒ…含 DRAFT、WAITING、BACK å’Œ CANCEL çŠ¶æ€ï¼‰
     */
    public static List<String> runningStatus() {
        return Arrays.asList(DRAFT.status, WAITING.status, BACK.status, CANCEL.status);
    }
    /**
     * èŽ·å–ç»“æŸå®žä¾‹çš„çŠ¶æ€åˆ—è¡¨
     *
     * @return åŒ…含结束实例状态的不可变列表
     * ï¼ˆåŒ…含 FINISH、INVALID å’Œ TERMINATION çŠ¶æ€ï¼‰
     */
    public static List<String> finishStatus() {
        return Arrays.asList(FINISH.status, INVALID.status, TERMINATION.status);
    }
    /**
@@ -148,5 +211,5 @@
            throw new ServiceException("流程状态为空!");
        }
    }
}
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package org.dromara.common.core.service;
import org.dromara.common.core.domain.dto.TaskAssigneeDTO;
import org.dromara.common.core.domain.model.TaskAssigneeBody;
/**
 * å·¥ä½œæµè®¾è®¡å™¨èŽ·å–ä»»åŠ¡æ‰§è¡Œäºº
 *
 * @author Lion Li
 */
public interface TaskAssigneeService {
    /**
     * æŸ¥è¯¢è§’色并返回任务指派的列表,支持分页
     *
     * @param taskQuery æŸ¥è¯¢æ¡ä»¶
     * @return åŠžç†äºº
     */
    TaskAssigneeDTO selectRolesByTaskAssigneeList(TaskAssigneeBody taskQuery);
    /**
     * æŸ¥è¯¢å²—位并返回任务指派的列表,支持分页
     *
     * @param taskQuery æŸ¥è¯¢æ¡ä»¶
     * @return åŠžç†äºº
     */
    TaskAssigneeDTO selectPostsByTaskAssigneeList(TaskAssigneeBody taskQuery);
    /**
     * æŸ¥è¯¢éƒ¨é—¨å¹¶è¿”回任务指派的列表,支持分页
     *
     * @param taskQuery æŸ¥è¯¢æ¡ä»¶
     * @return åŠžç†äºº
     */
    TaskAssigneeDTO selectDeptsByTaskAssigneeList(TaskAssigneeBody taskQuery);
    /**
     * æŸ¥è¯¢ç”¨æˆ·å¹¶è¿”回任务指派的列表,支持分页
     *
     * @param taskQuery æŸ¥è¯¢æ¡ä»¶
     * @return åŠžç†äºº
     */
    TaskAssigneeDTO selectUsersByTaskAssigneeList(TaskAssigneeBody taskQuery);
}
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java
@@ -1,5 +1,8 @@
package org.dromara.common.core.service;
import org.dromara.common.core.domain.dto.CompleteTaskDTO;
import org.dromara.common.core.domain.dto.StartProcessDTO;
import java.util.List;
import java.util.Map;
@@ -13,64 +16,63 @@
    /**
     * è¿è¡Œä¸­çš„实例 åˆ é™¤ç¨‹å®žä¾‹ï¼Œåˆ é™¤åŽ†å²è®°å½•ï¼Œåˆ é™¤ä¸šåŠ¡ä¸Žæµç¨‹å…³è”ä¿¡æ¯
     *
     * @param businessKeys ä¸šåŠ¡id
     * @param businessIds ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    boolean deleteRunAndHisInstance(List<String> businessKeys);
    boolean deleteInstance(List<Long> businessIds);
    /**
     * èŽ·å–å½“å‰æµç¨‹çŠ¶æ€
     *
     * @param taskId ä»»åŠ¡id
     * @return çŠ¶æ€
     */
    String getBusinessStatusByTaskId(String taskId);
    String getBusinessStatusByTaskId(Long taskId);
    /**
     * èŽ·å–å½“å‰æµç¨‹çŠ¶æ€
     *
     * @param businessKey ä¸šåŠ¡id
     * @param businessId ä¸šåŠ¡id
     * @return çŠ¶æ€
     */
    String getBusinessStatus(String businessKey);
    String getBusinessStatus(String businessId);
    /**
     * è®¾ç½®æµç¨‹å˜é‡(全局变量)
     * è®¾ç½®æµç¨‹å˜é‡
     *
     * @param taskId       ä»»åŠ¡id
     * @param variableName å˜é‡åç§°
     * @param value        å˜é‡å€¼
     * @param instanceId æµç¨‹å®žä¾‹id
     * @param variable   æµç¨‹å˜é‡
     */
    void setVariable(String taskId, String variableName, Object value);
    /**
     * è®¾ç½®æµç¨‹å˜é‡(全局变量)
     *
     * @param taskId    ä»»åŠ¡id
     * @param variables æµç¨‹å˜é‡
     */
    void setVariables(String taskId, Map<String, Object> variables);
    /**
     * è®¾ç½®æµç¨‹å˜é‡(本地变量,非全局变量)
     *
     * @param taskId       ä»»åŠ¡id
     * @param variableName å˜é‡åç§°
     * @param value        å˜é‡å€¼
     */
    void setVariableLocal(String taskId, String variableName, Object value);
    /**
     * è®¾ç½®æµç¨‹å˜é‡(本地变量,非全局变量)
     *
     * @param taskId    ä»»åŠ¡id
     * @param variables æµç¨‹å˜é‡
     */
    void setVariablesLocal(String taskId, Map<String, Object> variables);
    void setVariable(Long instanceId, Map<String, Object> variable);
    /**
     * æŒ‰ç…§ä¸šåŠ¡id查询流程实例id
     *
     * @param businessKey ä¸šåŠ¡id
     * @param businessId ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    String getInstanceIdByBusinessKey(String businessKey);
    Long getInstanceIdByBusinessId(String businessId);
    /**
     * æ–°å¢žç§Ÿæˆ·æµç¨‹å®šä¹‰
     *
     * @param tenantId ç§Ÿæˆ·id
     */
    void syncDef(String tenantId);
    /**
     * å¯åŠ¨æµç¨‹
     *
     * @param startProcess å‚æ•°
     * @return ç»“æžœ
     */
    Map<String, Object> startWorkFlow(StartProcessDTO startProcess);
    /**
     * åŠžç†ä»»åŠ¡
     *
     * @param completeTask å‚æ•°
     * @return ç»“æžœ
     */
    boolean completeTask(CompleteTaskDTO completeTask);
}
ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java
@@ -15,6 +15,7 @@
import java.util.Set;
/**
 * ç™»å½•鉴权助手
 * <p>
ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java
@@ -63,7 +63,7 @@
    private final GenTableColumnMapper genTableColumnMapper;
    private final IdentifierGenerator identifierGenerator;
    private static final String[] TABLE_IGNORE = new String[]{"sj_", "act_", "flw_", "gen_"};
    private static final String[] TABLE_IGNORE = new String[]{"sj_", "flow_", "gen_"};
    /**
     * æŸ¥è¯¢ä¸šåŠ¡å­—æ®µåˆ—è¡¨
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.annotation.DataPermission;
@@ -32,6 +33,17 @@
    List<SysDeptVo> selectDeptList(@Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
    /**
     * åˆ†é¡µæŸ¥è¯¢éƒ¨é—¨ç®¡ç†æ•°æ®
     *
     * @param queryWrapper æŸ¥è¯¢æ¡ä»¶
     * @return éƒ¨é—¨ä¿¡æ¯é›†åˆ
     */
    @DataPermission({
        @DataColumn(key = "deptName", value = "dept_id"),
    })
    Page<SysDeptVo> selectPageDeptList(@Param("page") Page<SysDeptVo> page, @Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
    /**
     * ç»Ÿè®¡æŒ‡å®šéƒ¨é—¨ID的部门数量
     *
     * @param deptId éƒ¨é—¨ID
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java
@@ -245,4 +245,5 @@
        SysPost post = MapstructUtils.convert(bo, SysPost.class);
        return baseMapper.updateById(post);
    }
}
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java
@@ -548,4 +548,5 @@
            }
        });
    }
}
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,168 @@
package org.dromara.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.domain.dto.TaskAssigneeDTO;
import org.dromara.common.core.domain.model.TaskAssigneeBody;
import org.dromara.common.core.service.TaskAssigneeService;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.system.domain.SysDept;
import org.dromara.system.domain.SysPost;
import org.dromara.system.domain.SysRole;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.domain.vo.SysPostVo;
import org.dromara.system.domain.vo.SysRoleVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SysDeptMapper;
import org.dromara.system.mapper.SysPostMapper;
import org.dromara.system.mapper.SysRoleMapper;
import org.dromara.system.mapper.SysUserMapper;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * å·¥ä½œæµè®¾è®¡å™¨èŽ·å–ä»»åŠ¡æ‰§è¡Œäºº
 *
 * @author Lion Li
 */
@RequiredArgsConstructor
@Service
public class SysTaskAssigneeServiceImpl implements TaskAssigneeService {
    private final SysPostMapper postMapper;
    private final SysDeptMapper deptMapper;
    private final SysUserMapper userMapper;
    private final SysRoleMapper roleMapper;
    /**
     * æŸ¥è¯¢è§’色并返回任务指派的列表,支持分页
     *
     * @param taskQuery æŸ¥è¯¢æ¡ä»¶
     * @return åŠžç†äºº
     */
    @Override
    public TaskAssigneeDTO selectRolesByTaskAssigneeList(TaskAssigneeBody taskQuery) {
        PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum());
        QueryWrapper<SysRole> wrapper = Wrappers.query();
        wrapper.eq("r.del_flag", SystemConstants.NORMAL)
            .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), "r.role_name", taskQuery.getHandlerCode())
            .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), "r.role_key", taskQuery.getHandlerName())
            .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()),
                "r.create_time", taskQuery.getBeginTime(), taskQuery.getEndTime())
            .orderByAsc("r.role_sort").orderByAsc("r.create_time");
        Page<SysRoleVo> page = roleMapper.selectPageRoleList(pageQuery.build(), wrapper);
        // ä½¿ç”¨å°è£…的字段映射方法进行转换
        List<TaskAssigneeDTO.TaskHandler> handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(),
            SysRoleVo::getRoleId, SysRoleVo::getRoleKey, SysRoleVo::getRoleName, null, SysRoleVo::getCreateTime);
        return new TaskAssigneeDTO(page.getTotal(), handlers);
    }
    /**
     * æŸ¥è¯¢å²—位并返回任务指派的列表,支持分页
     *
     * @param taskQuery æŸ¥è¯¢æ¡ä»¶
     * @return åŠžç†äºº
     */
    @Override
    public TaskAssigneeDTO selectPostsByTaskAssigneeList(TaskAssigneeBody taskQuery) {
        PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum());
        LambdaQueryWrapper<SysPost> wrapper = Wrappers.<SysPost>lambdaQuery()
            .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), SysPost::getPostCategory, taskQuery.getHandlerCode())
            .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), SysPost::getPostName, taskQuery.getHandlerName())
            .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()),
                SysPost::getCreateTime, taskQuery.getBeginTime(), taskQuery.getEndTime());
        if (StringUtils.isNotBlank(taskQuery.getGroupId())) {
            Long belongDeptId = Long.valueOf(taskQuery.getGroupId());
            wrapper.and(x -> {
                List<SysDept> deptList = deptMapper.selectListByParentId(belongDeptId);
                List<Long> deptIds = StreamUtils.toList(deptList, SysDept::getDeptId);
                deptIds.add(belongDeptId);
                x.in(SysPost::getDeptId, deptIds);
            });
        }
        Page<SysPostVo> page = postMapper.selectPagePostList(pageQuery.build(), wrapper);
        // ä½¿ç”¨å°è£…的字段映射方法进行转换
        List<TaskAssigneeDTO.TaskHandler> handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(),
            SysPostVo::getPostId, SysPostVo::getPostCategory, SysPostVo::getPostName, SysPostVo::getDeptId, SysPostVo::getCreateTime);
        return new TaskAssigneeDTO(page.getTotal(), handlers);
    }
    /**
     * æŸ¥è¯¢éƒ¨é—¨å¹¶è¿”回任务指派的列表,支持分页
     *
     * @param taskQuery æŸ¥è¯¢æ¡ä»¶
     * @return åŠžç†äºº
     */
    @Override
    public TaskAssigneeDTO selectDeptsByTaskAssigneeList(TaskAssigneeBody taskQuery) {
        PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum());
        LambdaQueryWrapper<SysDept> wrapper = Wrappers.<SysDept>lambdaQuery()
            .eq(SysDept::getDelFlag, SystemConstants.NORMAL)
            .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), SysDept::getDeptCategory, taskQuery.getHandlerCode())
            .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), SysDept::getDeptName, taskQuery.getHandlerName())
            .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()),
                SysDept::getCreateTime, taskQuery.getBeginTime(), taskQuery.getEndTime())
            .orderByAsc(SysDept::getAncestors)
            .orderByAsc(SysDept::getParentId)
            .orderByAsc(SysDept::getOrderNum)
            .orderByAsc(SysDept::getDeptId);
        if (StringUtils.isNotBlank(taskQuery.getGroupId())) {
            //部门树搜索
            wrapper.and(x -> {
                Long parentId = Long.valueOf(taskQuery.getGroupId());
                List<SysDept> deptList = deptMapper.selectListByParentId(parentId);
                List<Long> deptIds = StreamUtils.toList(deptList, SysDept::getDeptId);
                deptIds.add(parentId);
                x.in(SysDept::getDeptId, deptIds);
            });
        }
        Page<SysDeptVo> page = deptMapper.selectPageDeptList(pageQuery.build(), wrapper);
        // ä½¿ç”¨å°è£…的字段映射方法进行转换
        List<TaskAssigneeDTO.TaskHandler> handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(),
            SysDeptVo::getDeptId, SysDeptVo::getDeptCategory, SysDeptVo::getDeptName, SysDeptVo::getParentId, SysDeptVo::getCreateTime);
        return new TaskAssigneeDTO(page.getTotal(), handlers);
    }
    /**
     * æŸ¥è¯¢ç”¨æˆ·å¹¶è¿”回任务指派的列表,支持分页
     *
     * @param taskQuery æŸ¥è¯¢æ¡ä»¶
     * @return åŠžç†äºº
     */
    @Override
    public TaskAssigneeDTO selectUsersByTaskAssigneeList(TaskAssigneeBody taskQuery) {
        PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum());
        QueryWrapper<SysUser> wrapper = Wrappers.query();
        wrapper.eq("u.del_flag", SystemConstants.NORMAL)
            .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), "u.user_name", taskQuery.getHandlerCode())
            .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), "u.nick_name", taskQuery.getHandlerName())
            .between(taskQuery.getBeginTime() != null && taskQuery.getEndTime() != null,
                "u.create_time", taskQuery.getBeginTime(), taskQuery.getEndTime())
            .orderByAsc("u.user_id");
        if (StringUtils.isNotBlank(taskQuery.getGroupId())) {
            //部门树搜索
            wrapper.and(x -> {
                Long parentId = Long.valueOf(taskQuery.getGroupId());
                List<SysDept> deptList = deptMapper.selectListByParentId(parentId);
                List<Long> deptIds = StreamUtils.toList(deptList, SysDept::getDeptId);
                deptIds.add(parentId);
                x.in("u.dept_id", deptIds);
            });
        }
        Page<SysUserVo> page = userMapper.selectPageUserList(pageQuery.build(), wrapper);
        // ä½¿ç”¨å°è£…的字段映射方法进行转换
        List<TaskAssigneeDTO.TaskHandler> handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(),
            SysUserVo::getUserId, SysUserVo::getUserName, SysUserVo::getNickName, SysUserVo::getDeptId, SysUserVo::getCreateTime);
        return new TaskAssigneeDTO(page.getTotal(), handlers);
    }
}
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java
@@ -15,6 +15,7 @@
import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.constant.TenantConstants;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.WorkflowService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
@@ -56,6 +57,7 @@
    private final SysDictTypeMapper dictTypeMapper;
    private final SysDictDataMapper dictDataMapper;
    private final SysConfigMapper configMapper;
    private final WorkflowService workflowService;
    /**
     * æŸ¥è¯¢ç§Ÿæˆ·
@@ -121,7 +123,9 @@
        // èŽ·å–æ‰€æœ‰ç§Ÿæˆ·ç¼–å·
        List<String> tenantIds = baseMapper.selectObjs(
            new LambdaQueryWrapper<SysTenant>().select(SysTenant::getTenantId), x -> {return Convert.toStr(x);});
            new LambdaQueryWrapper<SysTenant>().select(SysTenant::getTenantId), x -> {
                return Convert.toStr(x);
            });
        String tenantId = generateTenantId(tenantIds);
        add.setTenantId(tenantId);
        boolean flag = baseMapper.insert(add) > 0;
@@ -191,6 +195,8 @@
            config.setTenantId(tenantId);
        }
        configMapper.insertBatch(sysConfigList);
        //新增租户流程定义
        workflowService.syncDef(tenantId);
        return true;
    }
@@ -399,7 +405,9 @@
        // èŽ·å–æ‰€æœ‰ç§Ÿæˆ·ç¼–å·
        List<String> tenantIds = baseMapper.selectObjs(
            new LambdaQueryWrapper<SysTenant>().select(SysTenant::getTenantId)
                .eq(SysTenant::getStatus, SystemConstants.NORMAL), x -> {return Convert.toStr(x);});
                .eq(SysTenant::getStatus, SystemConstants.NORMAL), x -> {
                return Convert.toStr(x);
            });
        List<SysDictType> saveTypeList = new ArrayList<>();
        List<SysDictData> saveDataList = new ArrayList<>();
        Set<String> set = new HashSet<>();
ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -18,6 +18,17 @@
        from sys_dept ${ew.getCustomSqlSegment}
    </select>
    <select id="selectPageDeptList" resultMap="SysDeptResult">
        select
        <if test="ew.getSqlSelect != null">
            ${ew.getSqlSelect}
        </if>
        <if test="ew.getSqlSelect == null">
            *
        </if>
        from sys_dept ${ew.getCustomSqlSegment}
    </select>
    <select id="countDeptById" resultType="Long">
        select count(*) from sys_dept where del_flag = '0' and dept_id = #{deptId}
    </select>
ruoyi-modules/ruoyi-workflow/pom.xml
@@ -18,57 +18,14 @@
    <dependencies>
        <!--引入flowable依赖-->
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-autoconfigure</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.flowable</groupId>
                    <artifactId>flowable-spring-security</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-configurator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- ç»˜åˆ¶flowable流程图 -->
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-image-generator</artifactId>
        </dependency>
        <!-- flowable json è½¬æ¢ -->
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-json-converter</artifactId>
            <version>6.8.0</version>
        </dependency>
        <!-- svg转png图片工具-->
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-all</artifactId>
            <version>1.17</version>
            <exclusions>
                <exclusion>
                    <groupId>xalan</groupId>
                    <artifactId>xalan</artifactId>
                </exclusion>
            </exclusions>
            <groupId>org.dromara</groupId>
            <artifactId>ruoyi-common-sse</artifactId>
        </dependency>
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>ruoyi-common-websocket</artifactId>
            <artifactId>ruoyi-common-doc</artifactId>
        </dependency>
        <dependency>
@@ -113,6 +70,14 @@
            <groupId>org.dromara</groupId>
            <artifactId>ruoyi-common-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.dromara.warm</groupId>
            <artifactId>warm-flow-mybatis-plus-sb3-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.dromara.warm</groupId>
            <artifactId>warm-flow-plugin-ui-sb-web</artifactId>
        </dependency>
    </dependencies>
</project>
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java
@@ -8,83 +8,6 @@
 */
public interface FlowConstant {
    String MESSAGE_CURRENT_TASK_IS_NULL = "当前任务不存在或你不是任务办理人!";
    String MESSAGE_SUSPENDED = "当前任务已挂起不可审批!";
    /**
     * è¿žçº¿
     */
    String SEQUENCE_FLOW = "sequenceFlow";
    /**
     * å¹¶è¡Œç½‘å…³
     */
    String PARALLEL_GATEWAY = "parallelGateway";
    /**
     * æŽ’它网关
     */
    String EXCLUSIVE_GATEWAY = "exclusiveGateway";
    /**
     * åŒ…含网关
     */
    String INCLUSIVE_GATEWAY = "inclusiveGateway";
    /**
     * ç»“束节点
     */
    String END_EVENT = "endEvent";
    /**
     * æµç¨‹å§”派标识
     */
    String PENDING = "PENDING";
    /**
     * å€™é€‰äººæ ‡è¯†
     */
    String CANDIDATE = "candidate";
    /**
     * ä¼šç­¾ä»»åŠ¡æ€»æ•°
     */
    String NUMBER_OF_INSTANCES = "nrOfInstances";
    /**
     * æ­£åœ¨æ‰§è¡Œçš„会签总数
     */
    String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
    /**
     * å·²å®Œæˆçš„会签任务总数
     */
    String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
    /**
     * å¾ªçŽ¯çš„ç´¢å¼•å€¼ï¼Œå¯ä»¥ä½¿ç”¨elementIndexVariable属性修改loopCounter的变量名
     */
    String LOOP_COUNTER = "loopCounter";
    String ZIP = "ZIP";
    /**
     * ä¸šåŠ¡ä¸Žæµç¨‹å®žä¾‹å…³è”å¯¹è±¡
     */
    String BUSINESS_INSTANCE_DTO = "businessInstanceDTO";
    /**
     * æµç¨‹å®šä¹‰é…ç½®
     */
    String WF_DEFINITION_CONFIG_VO = "wfDefinitionConfigVo";
    /**
     * èŠ‚ç‚¹é…ç½®
     */
    String WF_NODE_CONFIG_VO = "wfNodeConfigVo";
    /**
     * æµç¨‹å‘起人
     */
@@ -98,40 +21,46 @@
    /**
     * ä¸šåŠ¡id
     */
    String BUSINESS_KEY = "businessKey";
    String BUSINESS_ID = "businessId";
    /**
     * æµç¨‹å®šä¹‰id
     * ä»»åŠ¡id
     */
    String PROCESS_DEFINITION_ID = "processDefinitionId";
    String TASK_ID = "taskId";
    /**
     * å¼€å¯è·³è¿‡è¡¨è¾¾å¼å˜é‡
     * å§”托
     */
    String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED";
    String DELEGATE_TASK = "delegateTask";
    /**
     * æ¨¡åž‹æ ‡è¯†key命名规范正则表达式
     * è½¬åŠž
     */
    String MODEL_KEY_PATTERN = "^[a-zA-Z][a-zA-Z0-9_]{0,254}$";
    String TRANSFER_TASK = "transferTask";
    /**
     * ç”¨æˆ·ä»»åŠ¡
     * åŠ ç­¾
     */
    String USER_TASK = "userTask";
    String ADD_SIGNATURE = "addSignature";
    /**
     * ä¼šç­¾
     * å‡ç­¾
     */
    String MULTI_INSTANCE = "multiInstance";
    String REDUCTION_SIGNATURE = "reductionSignature";
    /**
     * æ˜¯
     * æµç¨‹åˆ†ç±»Id转名称
     */
    String TRUE = "0";
    String CATEGORY_ID_TO_NAME = "category_id_to_name";
    /**
     * å¦
     * æµç¨‹åˆ†ç±»åç§°
     */
    String FALSE = "1";
    String FLOW_CATEGORY_NAME = "flow_category_name#30d";
    /**
     * é»˜è®¤ç§Ÿæˆ·OA申请分类id
     */
    Long FLOW_CATEGORY_ID = 100L;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java
@@ -3,8 +3,10 @@
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * æ¶ˆæ¯ç±»åž‹æžšä¸¾
@@ -14,14 +16,17 @@
@Getter
@AllArgsConstructor
public enum MessageTypeEnum {
    /**
     * ç«™å†…ä¿¡
     */
    SYSTEM_MESSAGE("1", "站内信"),
    /**
     * é‚®ç®±
     */
    EMAIL_MESSAGE("2", "邮箱"),
    /**
     * çŸ­ä¿¡
     */
@@ -31,21 +36,18 @@
    private final String desc;
    private final static Map<String, MessageTypeEnum> MESSAGE_TYPE_ENUM_MAP = new ConcurrentHashMap<>(MessageTypeEnum.values().length);
    static {
        for (MessageTypeEnum messageType : MessageTypeEnum.values()) {
            MESSAGE_TYPE_ENUM_MAP.put(messageType.code, messageType);
        }
    }
    private static final Map<String, MessageTypeEnum> MESSAGE_TYPE_ENUM_MAP = Arrays.stream(values())
        .collect(Collectors.toConcurrentMap(MessageTypeEnum::getCode, Function.identity()));
    /**
     * æ ¹æ®æ¶ˆæ¯ç±»åž‹ code èŽ·å– MessageTypeEnum
     *
     * @param code æ¶ˆæ¯ç±»åž‹code
     * @return MessageTypeEnum
     */
    public static MessageTypeEnum getByCode(String code) {
        return MESSAGE_TYPE_ENUM_MAP.get(code);
        return MESSAGE_TYPE_ENUM_MAP.getOrDefault(code, null);
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
package org.dromara.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.dromara.common.core.exception.ServiceException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
 * ä»»åŠ¡åˆ†é…äººæžšä¸¾
 *
 * @author AprilWind
 */
@Getter
@AllArgsConstructor
public enum TaskAssigneeEnum {
    /**
     * ç”¨æˆ·
     */
    USER("用户", ""),
    /**
     * è§’色
     */
    ROLE("角色", "role:"),
    /**
     * éƒ¨é—¨
     */
    DEPT("部门", "dept:"),
    /**
     * å²—位
     */
    POST("岗位", "post:");
    private final String desc;
    private final String code;
    /**
     * æ ¹æ®æè¿°èŽ·å–å¯¹åº”çš„æžšä¸¾ç±»åž‹
     * <p>
     * é€šè¿‡ä¼ å…¥æè¿°ï¼ŒæŸ¥æ‰¾å¹¶è¿”回匹配的枚举项。如果未找到匹配项,会抛出 {@link ServiceException}。
     * </p>
     *
     * @param desc æè¿°ï¼Œç”¨äºŽåŒ¹é…å¯¹åº”的枚举项
     * @return TaskAssigneeEnum è¿”回对应的枚举类型
     * @throws ServiceException å¦‚果未找到匹配的枚举项
     */
    public static TaskAssigneeEnum fromDesc(String desc) {
        for (TaskAssigneeEnum type : values()) {
            if (type.getDesc().equals(desc)) {
                return type;
            }
        }
        throw new ServiceException("未知的办理人类型: " + desc);
    }
    /**
     * æ ¹æ®ä»£ç èŽ·å–å¯¹åº”çš„æžšä¸¾ç±»åž‹
     * <p>
     * é€šè¿‡ä¼ å…¥ä»£ç ï¼ŒæŸ¥æ‰¾å¹¶è¿”回匹配的枚举项。如果未找到匹配项,会抛出 {@link ServiceException}。
     * </p>
     *
     * @param code ä»£ç ï¼Œç”¨äºŽåŒ¹é…å¯¹åº”的枚举项
     * @return TaskAssigneeEnum è¿”回对应的枚举类型
     * @throws IllegalArgumentException å¦‚果未找到匹配的枚举项
     */
    public static TaskAssigneeEnum fromCode(String code) {
        for (TaskAssigneeEnum type : values()) {
            if (type.getCode().equals(code)) {
                return type;
            }
        }
        throw new ServiceException("未知的办理人类型代码: " + code);
    }
    /**
     * èŽ·å–æ‰€æœ‰åŠžç†äººç±»åž‹çš„æè¿°åˆ—è¡¨
     * <p>
     * èŽ·å–å½“å‰æžšä¸¾ç±»æ‰€æœ‰é¡¹çš„æè¿°å­—æ®µåˆ—è¡¨ï¼Œé€šå¸¸ç”¨äºŽå±•ç¤ºé€‰æ‹©é¡¹ã€‚
     * </p>
     *
     * @return List<String> è¿”回所有办理人类型的描述列表
     */
    public static List<String> getAssigneeTypeList() {
        return Arrays.stream(values())
            .map(TaskAssigneeEnum::getDesc)
            .collect(Collectors.toList());
    }
    /**
     * èŽ·å–æ‰€æœ‰åŠžç†äººç±»åž‹çš„ä»£ç åˆ—è¡¨
     * <p>
     * èŽ·å–å½“å‰æžšä¸¾ç±»æ‰€æœ‰é¡¹çš„ä»£ç å­—æ®µåˆ—è¡¨ï¼Œé€šå¸¸ç”¨äºŽç¨‹åºå†…éƒ¨é€»è¾‘çš„åˆ¤æ–­ã€‚
     * </p>
     *
     * @return List<String> è¿”回所有办理人类型的代码列表
     */
    public static List<String> getAssigneeCodeList() {
        return Arrays.stream(values())
            .map(TaskAssigneeEnum::getCode)
            .collect(Collectors.toList());
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
package org.dromara.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * äººå‘˜ç±»åž‹
 *
 * @author AprilWind
 */
@Getter
@AllArgsConstructor
public enum TaskAssigneeType {
    /**
     * å¾…办任务的审批人权限
     * <p>该权限表示用户是待办任务的审批人,负责审核任务的执行情况。</p>
     */
    APPROVER("1", "待办任务的审批人权限"),
    /**
     * å¾…办任务的转办人权限
     * <p>该权限表示用户是待办任务的转办人,负责将任务分配给其他人员。</p>
     */
    TRANSFER("2", "待办任务的转办人权限"),
    /**
     * å¾…办任务的委托人权限
     * <p>该权限表示用户是待办任务的委托人,能够委托其他人代为处理任务。</p>
     */
    DELEGATE("3", "待办任务的委托人权限"),
    /**
     * å¾…办任务的抄送人权限
     * <p>该权限表示用户是待办任务的抄送人,仅接收任务信息的通知,不参与任务的审批或处理。</p>
     */
    COPY("4", "待办任务的抄送人权限");
    /**
     * ç±»åž‹
     */
    private final String code;
    /**
     * æè¿°
     */
    private final String description;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java
@@ -3,9 +3,10 @@
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * ä»»åŠ¡çŠ¶æ€æžšä¸¾
@@ -15,50 +16,62 @@
@Getter
@AllArgsConstructor
public enum TaskStatusEnum {
    /**
     * æ’¤é”€
     */
    CANCEL("cancel", "撤销"),
    /**
     * é€šè¿‡
     */
    PASS("pass", "通过"),
    /**
     * å¾…审核
     */
    WAITING("waiting", "待审核"),
    /**
     * ä½œåºŸ
     */
    INVALID("invalid", "作废"),
    /**
     * é€€å›ž
     */
    BACK("back", "退回"),
    /**
     * ç»ˆæ­¢
     */
    TERMINATION("termination", "终止"),
    /**
     * è½¬åŠž
     */
    TRANSFER("transfer", "转办"),
    /**
     * å§”托
     */
    PENDING("pending", "委托"),
    DEPUTE("depute", "委托"),
    /**
     * æŠ„送
     */
    COPY("copy", "抄送"),
    /**
     * åŠ ç­¾
     */
    SIGN("sign", "加签"),
    /**
     * å‡ç­¾
     */
    SIGN_OFF("sign_off", "减签"),
    /**
     * è¶…æ—¶
     */
@@ -74,21 +87,18 @@
     */
    private final String desc;
    private static final Map<String, String> STATUS_DESC_MAP = Arrays.stream(values())
        .collect(Collectors.toConcurrentMap(TaskStatusEnum::getStatus, TaskStatusEnum::getDesc));
    /**
     * ä»»åŠ¡ä¸šåŠ¡çŠ¶æ€
     *
     * @param status çŠ¶æ€
     */
    public static String findByStatus(String status) {
        if (StringUtils.isBlank(status)) {
            return StrUtil.EMPTY;
        }
        return Arrays.stream(TaskStatusEnum.values())
            .filter(statusEnum -> statusEnum.getStatus().equals(status))
            .findFirst()
            .map(TaskStatusEnum::getDesc)
            .orElse(StrUtil.EMPTY);
        // ä»Žç¼“存中直接获取描述
        return STATUS_DESC_MAP.getOrDefault(status, StrUtil.EMPTY);
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package org.dromara.workflow.config;
import org.springframework.context.annotation.Configuration;
/**
 * warmFlow配置
 *
 * @author may
 */
@Configuration
public class WarmFlowConfig {
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,130 @@
package org.dromara.workflow.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.tree.Tree;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.workflow.domain.bo.FlowCategoryBo;
import org.dromara.workflow.domain.vo.FlowCategoryVo;
import org.dromara.workflow.service.IFlwCategoryService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * æµç¨‹åˆ†ç±»
 *
 * @author may
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/category")
public class FlwCategoryController extends BaseController {
    private final IFlwCategoryService flwCategoryService;
    /**
     * æŸ¥è¯¢æµç¨‹åˆ†ç±»åˆ—表
     */
    @SaCheckPermission("workflow:category:list")
    @GetMapping("/list")
    public R<List<FlowCategoryVo>> list(FlowCategoryBo bo) {
        List<FlowCategoryVo> list = flwCategoryService.queryList(bo);
        return R.ok(list);
    }
    /**
     * å¯¼å‡ºæµç¨‹åˆ†ç±»åˆ—表
     */
    @SaCheckPermission("workflow:category:export")
    @Log(title = "流程分类", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(FlowCategoryBo bo, HttpServletResponse response) {
        List<FlowCategoryVo> list = flwCategoryService.queryList(bo);
        ExcelUtil.exportExcel(list, "流程分类", FlowCategoryVo.class, response);
    }
    /**
     * èŽ·å–æµç¨‹åˆ†ç±»è¯¦ç»†ä¿¡æ¯
     *
     * @param categoryId ä¸»é”®
     */
    @SaCheckPermission("workflow:category:query")
    @GetMapping("/{categoryId}")
    public R<FlowCategoryVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long categoryId) {
        flwCategoryService.checkCategoryDataScope(categoryId);
        return R.ok(flwCategoryService.queryById(categoryId));
    }
    /**
     * æ–°å¢žæµç¨‹åˆ†ç±»
     */
    @SaCheckPermission("workflow:category:add")
    @Log(title = "流程分类", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody FlowCategoryBo category) {
        if (!flwCategoryService.checkCategoryNameUnique(category)) {
            return R.fail("新增流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在");
        }
        return toAjax(flwCategoryService.insertByBo(category));
    }
    /**
     * ä¿®æ”¹æµç¨‹åˆ†ç±»
     */
    @SaCheckPermission("workflow:category:edit")
    @Log(title = "流程分类", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody FlowCategoryBo category) {
        Long categoryId = category.getCategoryId();
        flwCategoryService.checkCategoryDataScope(categoryId);
        if (!flwCategoryService.checkCategoryNameUnique(category)) {
            return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在");
        } else if (category.getParentId().equals(categoryId)) {
            return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,上级流程分类不能是自己");
        }
        return toAjax(flwCategoryService.updateByBo(category));
    }
    /**
     * åˆ é™¤æµç¨‹åˆ†ç±»
     *
     * @param categoryId ä¸»é”®
     */
    @SaCheckPermission("workflow:category:remove")
    @Log(title = "流程分类", businessType = BusinessType.DELETE)
    @DeleteMapping("/{categoryId}")
    public R<Void> remove(@PathVariable Long categoryId) {
        if (flwCategoryService.hasChildByCategoryId(categoryId)) {
            return R.warn("存在下级流程分类,不允许删除");
        }
        if (flwCategoryService.checkCategoryExistDefinition(categoryId)) {
            return R.warn("流程分类存在流程定义,不允许删除");
        }
        return toAjax(flwCategoryService.deleteWithValidById(categoryId));
    }
    /**
     * èŽ·å–æµç¨‹åˆ†ç±»æ ‘åˆ—è¡¨
     *
     * @param categoryBo æµç¨‹åˆ†ç±»
     */
    @GetMapping("/categoryTree")
    public R<List<Tree<Long>>> categoryTree(FlowCategoryBo categoryBo) {
        return R.ok(flwCategoryService.selectCategoryTreeList(categoryBo));
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,194 @@
package org.dromara.workflow.controller;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.warm.flow.core.entity.Definition;
import org.dromara.warm.flow.core.service.DefService;
import org.dromara.warm.flow.orm.entity.FlowDefinition;
import org.dromara.workflow.domain.vo.FlowDefinitionVo;
import org.dromara.workflow.service.IFlwDefinitionService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
/**
 * æµç¨‹å®šä¹‰ç®¡ç† æŽ§åˆ¶å±‚
 *
 * @author may
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/definition")
public class FlwDefinitionController extends BaseController {
    private final IFlwDefinitionService flwDefinitionService;
    private final DefService defService;
    /**
     * æŸ¥è¯¢æµç¨‹å®šä¹‰åˆ—表
     *
     * @param flowDefinition å‚æ•°
     * @param pageQuery      åˆ†é¡µ
     */
    @GetMapping("/list")
    public TableDataInfo<FlowDefinitionVo> list(FlowDefinition flowDefinition, PageQuery pageQuery) {
        return flwDefinitionService.queryList(flowDefinition, pageQuery);
    }
    /**
     * æŸ¥è¯¢æœªå‘布的流程定义列表
     *
     * @param flowDefinition å‚æ•°
     * @param pageQuery      åˆ†é¡µ
     */
    @GetMapping("/unPublishList")
    public TableDataInfo<FlowDefinitionVo> unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery) {
        return flwDefinitionService.unPublishList(flowDefinition, pageQuery);
    }
    /**
     * èŽ·å–æµç¨‹å®šä¹‰è¯¦ç»†ä¿¡æ¯
     *
     * @param id æµç¨‹å®šä¹‰id
     */
    @GetMapping(value = "/{id}")
    public R<Definition> getInfo(@PathVariable Long id) {
        return R.ok(defService.getById(id));
    }
    /**
     * æ–°å¢žæµç¨‹å®šä¹‰
     *
     * @param flowDefinition å‚æ•°
     */
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PostMapping
    @RepeatSubmit()
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> add(@RequestBody FlowDefinition flowDefinition) {
        return R.ok(defService.checkAndSave(flowDefinition));
    }
    /**
     * ä¿®æ”¹æµç¨‹å®šä¹‰
     *
     * @param flowDefinition å‚æ•°
     */
    @Log(title = "流程定义", businessType = BusinessType.UPDATE)
    @PutMapping
    @RepeatSubmit()
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> edit(@RequestBody FlowDefinition flowDefinition) {
        return R.ok(defService.updateById(flowDefinition));
    }
    /**
     * å‘布流程定义
     *
     * @param id æµç¨‹å®šä¹‰id
     */
    @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));
    }
    /**
     * å–消发布流程定义
     *
     * @param id æµç¨‹å®šä¹‰id
     */
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PutMapping("/unPublish/{id}")
    @RepeatSubmit()
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> unPublish(@PathVariable Long id) {
        return R.ok(defService.unPublish(id));
    }
    /**
     * åˆ é™¤æµç¨‹å®šä¹‰
     */
    @Log(title = "流程定义", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @Transactional(rollbackFor = Exception.class)
    public R<Void> remove(@PathVariable List<Long> ids) {
        return toAjax(flwDefinitionService.removeDef(ids));
    }
    /**
     * å¤åˆ¶æµç¨‹å®šä¹‰
     *
     * @param id æµç¨‹å®šä¹‰id
     */
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PostMapping("/copy/{id}")
    @RepeatSubmit()
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> copy(@PathVariable Long id) {
        return R.ok(defService.copyDef(id));
    }
    /**
     * å¯¼å…¥æµç¨‹å®šä¹‰
     *
     * @param file     æ–‡ä»¶
     * @param category åˆ†ç±»
     */
    @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));
    }
    /**
     * å¯¼å‡ºæµç¨‹å®šä¹‰
     *
     * @param id       æµç¨‹å®šä¹‰id
     * @param response å“åº”
     * @throws IOException å¼‚常
     */
    @Log(title = "流程定义", businessType = BusinessType.EXPORT)
    @PostMapping("/exportDef/{id}")
    public void exportDef(@PathVariable Long id, HttpServletResponse response) throws IOException {
        flwDefinitionService.exportDef(id, response);
    }
    /**
     * èŽ·å–æµç¨‹å®šä¹‰xml字符串
     *
     * @param id æµç¨‹å®šä¹‰id
     */
    @GetMapping("/xmlString/{id}")
    public R<String> xmlString(@PathVariable Long id) {
        return R.ok("操作成功", defService.xmlString(id));
    }
    /**
     * æ¿€æ´»/挂起流程定义
     *
     * @param id     æµç¨‹å®šä¹‰id
     * @param active æ¿€æ´»/挂起
     */
    @RepeatSubmit()
    @PutMapping("/active/{id}")
    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/controller/FlwInstanceController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,155 @@
package org.dromara.workflow.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.warm.flow.core.service.InsService;
import org.dromara.workflow.domain.bo.FlowCancelBo;
import org.dromara.workflow.domain.bo.FlowInstanceBo;
import org.dromara.workflow.domain.bo.FlowInvalidBo;
import org.dromara.workflow.domain.vo.FlowInstanceVo;
import org.dromara.workflow.service.IFlwInstanceService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
 * æµç¨‹å®žä¾‹ç®¡ç† æŽ§åˆ¶å±‚
 *
 * @author may
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/instance")
public class FlwInstanceController extends BaseController {
    private final IFlwInstanceService flwInstanceService;
    private final InsService insService;
    /**
     * æŸ¥è¯¢æ­£åœ¨è¿è¡Œçš„æµç¨‹å®žä¾‹åˆ—表
     *
     * @param flowInstanceBo æµç¨‹å®žä¾‹
     * @param pageQuery      åˆ†é¡µ
     */
    @GetMapping("/pageByRunning")
    public TableDataInfo<FlowInstanceVo> selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) {
        return flwInstanceService.selectRunningInstanceList(flowInstanceBo, pageQuery);
    }
    /**
     * æŸ¥è¯¢å·²ç»“束的流程实例列表
     *
     * @param flowInstanceBo æµç¨‹å®žä¾‹
     * @param pageQuery      åˆ†é¡µ
     */
    @GetMapping("/pageByFinish")
    public TableDataInfo<FlowInstanceVo> selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) {
        return flwInstanceService.selectFinishInstanceList(flowInstanceBo, pageQuery);
    }
    /**
     * æ ¹æ®ä¸šåŠ¡id查询流程实例详细信息
     *
     * @param businessId ä¸šåŠ¡id
     */
    @GetMapping("/getInfo/{businessId}")
    public R<FlowInstanceVo> getInfo(@PathVariable Long businessId) {
        return R.ok(flwInstanceService.queryByBusinessId(businessId));
    }
    /**
     * æŒ‰ç…§ä¸šåŠ¡id删除流程实例
     *
     * @param businessIds ä¸šåŠ¡id
     */
    @DeleteMapping("/deleteByBusinessIds/{businessIds}")
    public R<Void> deleteByBusinessIds(@PathVariable List<Long> businessIds) {
        return toAjax(flwInstanceService.deleteByBusinessIds(businessIds));
    }
    /**
     * æŒ‰ç…§å®žä¾‹id删除流程实例
     *
     * @param instanceIds å®žä¾‹id
     */
    @DeleteMapping("/deleteByInstanceIds/{instanceIds}")
    public R<Void> deleteByInstanceIds(@PathVariable List<Long> instanceIds) {
        return toAjax(flwInstanceService.deleteByInstanceIds(instanceIds));
    }
    /**
     * æ’¤é”€æµç¨‹
     *
     * @param bo å‚æ•°
     */
    @RepeatSubmit()
    @PutMapping("/cancelProcessApply")
    public R<Void> cancelProcessApply(@RequestBody FlowCancelBo bo) {
        return toAjax(flwInstanceService.cancelProcessApply(bo));
    }
    /**
     * æ¿€æ´»/挂起流程实例
     *
     * @param id     æµç¨‹å®žä¾‹id
     * @param active æ¿€æ´»/挂起
     */
    @RepeatSubmit()
    @PutMapping("/active/{id}")
    public R<Boolean> active(@PathVariable Long id, @RequestParam boolean active) {
        return R.ok(active ? insService.active(id) : insService.unActive(id));
    }
    /**
     * èŽ·å–å½“å‰ç™»é™†äººå‘èµ·çš„æµç¨‹å®žä¾‹
     *
     * @param flowInstanceBo å‚æ•°
     * @param pageQuery      åˆ†é¡µ
     */
    @GetMapping("/pageByCurrent")
    public TableDataInfo<FlowInstanceVo> selectCurrentInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) {
        return flwInstanceService.selectCurrentInstanceList(flowInstanceBo, pageQuery);
    }
    /**
     * èŽ·å–æµç¨‹å›¾ï¼Œæµç¨‹è®°å½•
     *
     * @param businessId ä¸šåŠ¡id
     */
    @GetMapping("/flowImage/{businessId}")
    public R<Map<String, Object>> flowImage(@PathVariable String businessId) {
        return R.ok(flwInstanceService.flowImage(businessId));
    }
    /**
     * èŽ·å–æµç¨‹å˜é‡
     *
     * @param instanceId æµç¨‹å®žä¾‹id
     */
    @GetMapping("/instanceVariable/{instanceId}")
    public R<Map<String, Object>> instanceVariable(@PathVariable String instanceId) {
        return R.ok(flwInstanceService.instanceVariable(instanceId));
    }
    /**
     * ä½œåºŸæµç¨‹
     *
     * @param bo å‚æ•°
     */
    @Log(title = "流程实例管理", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/invalid")
    public R<Boolean> invalid(@Validated @RequestBody FlowInvalidBo bo) {
        return R.ok(flwInstanceService.processInvalid(bo));
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,199 @@
package org.dromara.workflow.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.warm.flow.core.entity.Node;
import org.dromara.workflow.domain.bo.*;
import org.dromara.workflow.domain.vo.FlowHisTaskVo;
import org.dromara.workflow.domain.vo.FlowTaskVo;
import org.dromara.workflow.service.IFlwTaskService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
 * ä»»åŠ¡ç®¡ç† æŽ§åˆ¶å±‚
 *
 * @author may
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/task")
public class FlwTaskController extends BaseController {
    private final IFlwTaskService flwTaskService;
    /**
     * å¯åŠ¨ä»»åŠ¡
     *
     * @param startProcessBo å¯åŠ¨æµç¨‹å‚æ•°
     */
    @Log(title = "任务管理", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/startWorkFlow")
    public R<Map<String, Object>> startWorkFlow(@Validated(AddGroup.class) @RequestBody StartProcessBo startProcessBo) {
        Map<String, Object> map = flwTaskService.startWorkFlow(startProcessBo);
        return R.ok("提交成功", map);
    }
    /**
     * åŠžç†ä»»åŠ¡
     *
     * @param completeTaskBo åŠžç†ä»»åŠ¡å‚æ•°
     */
    @Log(title = "任务管理", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/completeTask")
    public R<Void> completeTask(@Validated(AddGroup.class) @RequestBody CompleteTaskBo completeTaskBo) {
        return toAjax(flwTaskService.completeTask(completeTaskBo));
    }
    /**
     * æŸ¥è¯¢å½“前用户的待办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @GetMapping("/pageByTaskWait")
    public TableDataInfo<FlowTaskVo> pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        return flwTaskService.pageByTaskWait(flowTaskBo, pageQuery);
    }
    /**
     * æŸ¥è¯¢å½“前用户的已办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @GetMapping("/pageByTaskFinish")
    public TableDataInfo<FlowHisTaskVo> pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        return flwTaskService.pageByTaskFinish(flowTaskBo, pageQuery);
    }
    /**
     * æŸ¥è¯¢å¾…办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @GetMapping("/pageByAllTaskWait")
    public TableDataInfo<FlowTaskVo> pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        return flwTaskService.pageByAllTaskWait(flowTaskBo, pageQuery);
    }
    /**
     * æŸ¥è¯¢å·²åŠžä»»åŠ¡
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @GetMapping("/pageByAllTaskFinish")
    public TableDataInfo<FlowHisTaskVo> pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        return flwTaskService.pageByAllTaskFinish(flowTaskBo, pageQuery);
    }
    /**
     * æŸ¥è¯¢å½“前用户的抄送
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @GetMapping("/pageByTaskCopy")
    public TableDataInfo<FlowTaskVo> pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        return flwTaskService.pageByTaskCopy(flowTaskBo, pageQuery);
    }
    /**
     * æ ¹æ®taskId查询代表任务
     *
     * @param taskId ä»»åŠ¡id
     */
    @GetMapping("/getTask/{taskId}")
    public R<FlowTaskVo> getTask(@PathVariable Long taskId) {
        return R.ok(flwTaskService.selectById(taskId));
    }
    /**
     * ç»ˆæ­¢ä»»åŠ¡
     *
     * @param bo å‚æ•°
     */
    @Log(title = "任务管理", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/terminationTask")
    public R<Boolean> terminationTask(@RequestBody FlowTerminationBo bo) {
        return R.ok(flwTaskService.terminationTask(bo));
    }
    /**
     * ä»»åŠ¡æ“ä½œ
     *
     * @param bo            å‚æ•°
     * @param taskOperation æ“ä½œç±»åž‹ï¼Œå§”æ´¾ delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature
     */
    @Log(title = "任务管理", businessType = BusinessType.UPDATE)
    @RepeatSubmit
    @PostMapping("/taskOperation/{taskOperation}")
    public R<Void> taskOperation(@Validated @RequestBody TaskOperationBo bo, @PathVariable String taskOperation) {
        return toAjax(flwTaskService.taskOperation(bo, taskOperation));
    }
    /**
     * ä¿®æ”¹ä»»åŠ¡åŠžç†äºº
     *
     * @param taskIdList ä»»åŠ¡id
     * @param userId     åŠžç†äººid
     */
    @Log(title = "任务管理", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping("/updateAssignee/{userId}")
    public R<Void> updateAssignee(@RequestBody List<Long> taskIdList, @PathVariable String userId) {
        return toAjax(flwTaskService.updateAssignee(taskIdList, userId));
    }
    /**
     * é©³å›žå®¡æ‰¹
     *
     * @param bo å‚æ•°
     */
    @Log(title = "任务管理", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/backProcess")
    public R<Void> backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo bo) {
        return toAjax(flwTaskService.backProcess(bo));
    }
    /**
     * èŽ·å–å¯é©³å›žçš„å‰ç½®èŠ‚ç‚¹
     *
     * @param definitionId æµç¨‹å®šä¹‰id
     * @param nowNodeCode  å½“前节点
     */
    @GetMapping("/getBackTaskNode/{definitionId}/{nowNodeCode}")
    public R<List<Node>> getBackTaskNode(@PathVariable Long definitionId, @PathVariable String nowNodeCode) {
        return R.ok(flwTaskService.getBackTaskNode(definitionId, nowNodeCode));
    }
    /**
     * èŽ·å–å½“å‰ä»»åŠ¡çš„æ‰€æœ‰åŠžç†äºº
     *
     * @param taskId ä»»åŠ¡id
     */
    @GetMapping("/currentTaskAllUser/{taskId}")
    public R<List<UserDTO>> currentTaskAllUser(@PathVariable Long taskId) {
        return R.ok(flwTaskService.currentTaskAllUser(taskId));
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package org.dromara.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
 * æµç¨‹åˆ†ç±»å¯¹è±¡ wf_category
 *
 * @author may
 * @date 2023-06-27
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("flow_category")
public class FlowCategory extends TenantEntity {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * æµç¨‹åˆ†ç±»ID
     */
    @TableId(value = "category_id")
    private Long categoryId;
    /**
     * çˆ¶æµç¨‹åˆ†ç±»id
     */
    private Long parentId;
    /**
     * ç¥–级列表
     */
    private String ancestors;
    /**
     * æµç¨‹åˆ†ç±»åç§°
     */
    private String categoryName;
    /**
     * æ˜¾ç¤ºé¡ºåº
     */
    private Long orderNum;
    /**
     * åˆ é™¤æ ‡å¿—(0代表存在 2代表删除)
     */
    @TableLogic
    private String delFlag;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfCategory.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java
@@ -1,12 +1,16 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
@@ -23,8 +27,8 @@
    /**
     * ä»»åŠ¡ID
     */
    @NotBlank(message = "任务ID不能为空", groups = AddGroup.class)
    private String taskId;
    @NotNull(message = "任务ID不能为空", groups = AddGroup.class)
    private Long taskId;
    /**
     * æ¶ˆæ¯ç±»åž‹
@@ -35,10 +39,28 @@
     * é©³å›žçš„节点id(目前未使用,直接驳回到申请人)
     */
    @NotBlank(message = "驳回的节点不能为空", groups = AddGroup.class)
    private String targetActivityId;
    private String nodeCode;
    /**
     * åŠžç†æ„è§
     */
    private String message;
    /**
     * é€šçŸ¥
     */
    private String notice;
    /**
     * æµç¨‹å˜é‡
     */
    private Map<String, Object> variables;
    public Map<String, Object> getVariables() {
        if (variables == null) {
            return new HashMap<>(16);
        }
        variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
        return variables;
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java
@@ -1,9 +1,8 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.workflow.domain.vo.WfCopy;
import java.io.Serial;
import java.io.Serializable;
@@ -26,8 +25,8 @@
    /**
     * ä»»åŠ¡id
     */
    @NotBlank(message = "任务id不能为空", groups = {AddGroup.class})
    private String taskId;
    @NotNull(message = "任务id不能为空", groups = {AddGroup.class})
    private Long taskId;
    /**
     * é™„ä»¶id
@@ -37,7 +36,7 @@
    /**
     * æŠ„送人员
     */
    private List<WfCopy> wfCopyList;
    private List<FlowCopyBo> flowCopyList;
    /**
     * æ¶ˆæ¯ç±»åž‹
@@ -50,10 +49,21 @@
    private String message;
    /**
     * æ¶ˆæ¯é€šçŸ¥
     */
    private String notice;
    /**
     * æµç¨‹å˜é‡
     */
    private Map<String, Object> variables;
    /**
     * æ‰©å±•变量(此处为逗号分隔的ossId)
     * @return
     */
    private String ext;
    public Map<String, Object> getVariables() {
        if (variables == null) {
            return new HashMap<>(16);
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
 * æ’¤é”€ä»»åŠ¡è¯·æ±‚å¯¹è±¡
 *
 * @author may
 */
@Data
public class FlowCancelBo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * ä»»åŠ¡ID
     */
    @NotBlank(message = "业务ID不能为空", groups = AddGroup.class)
    private String businessId;
    /**
     * åŠžç†æ„è§
     */
    private String message;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package org.dromara.workflow.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.workflow.domain.FlowCategory;
/**
 * æµç¨‹åˆ†ç±»ä¸šåŠ¡å¯¹è±¡ wf_category
 *
 * @author may
 * @date 2023-06-27
 */
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = FlowCategory.class, reverseConvertGenerate = false)
public class FlowCategoryBo extends BaseEntity {
    /**
     * æµç¨‹åˆ†ç±»ID
     */
    @NotNull(message = "流程分类ID不能为空", groups = { EditGroup.class })
    private Long categoryId;
    /**
     * çˆ¶æµç¨‹åˆ†ç±»id
     */
    @NotNull(message = "父流程分类id不能为空", groups = {AddGroup.class, EditGroup.class})
    private Long parentId;
    /**
     * æµç¨‹åˆ†ç±»åç§°
     */
    @NotBlank(message = "流程分类名称不能为空", groups = {AddGroup.class, EditGroup.class})
    private String categoryName;
    /**
     * æ˜¾ç¤ºé¡ºåº
     */
    private Long orderNum;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java
ÎļþÃû´Ó ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java ÐÞ¸Ä
@@ -1,9 +1,10 @@
package org.dromara.workflow.domain.vo;
package org.dromara.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
 * æŠ„送
@@ -11,7 +12,7 @@
 * @author may
 */
@Data
public class WfCopy implements Serializable {
public class FlowCopyBo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package org.dromara.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
 * æµç¨‹å®žä¾‹è¯·æ±‚对象
 *
 * @author may
 */
@Data
public class FlowInstanceBo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * æµç¨‹å®šä¹‰åç§°
     */
    private String flowName;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * ä»»åŠ¡å‘èµ·äºº
     */
    private String startUserId;
    /**
     * ä¸šåŠ¡id
     */
    private String businessId;
    /**
     * æµç¨‹åˆ†ç±»id
     */
    private String category;
    /**
     * ä»»åŠ¡åç§°
     */
    private String nodeName;
    /**
     * ç”³è¯·äººIds
     */
    private List<Long> createByIds;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
 * ä½œåºŸè¯·æ±‚对象
 *
 * @author may
 */
@Data
public class FlowInvalidBo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * æµç¨‹å®žä¾‹id
     */
    @NotNull(message = "流程实例id为空", groups = AddGroup.class)
    private Long id;
    /**
     * å®¡æ‰¹æ„è§
     */
    private String comment;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package org.dromara.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
 * ä»»åŠ¡è¯·æ±‚å¯¹è±¡
 *
 * @author may
 */
@Data
public class FlowTaskBo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * ä»»åŠ¡åç§°
     */
    private String nodeName;
    /**
     * æµç¨‹å®šä¹‰åç§°
     */
    private String flowName;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * æµç¨‹åˆ†ç±»id
     */
    private String category;
    /**
     * æµç¨‹å®žä¾‹id
     */
    private Long instanceId;
    /**
     * æƒé™åˆ—表
     */
    private List<String> permissionList;
    /**
     * ç”³è¯·äººIds
     */
    private List<Long> createByIds;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java
ÎļþÃû´Ó ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TerminationBo.java ÐÞ¸Ä
@@ -1,6 +1,6 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
@@ -13,7 +13,7 @@
 * @author may
 */
@Data
public class TerminationBo implements Serializable {
public class FlowTerminationBo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
@@ -21,8 +21,8 @@
    /**
     * ä»»åŠ¡id
     */
    @NotBlank(message = "任务id为空", groups = AddGroup.class)
    private String taskId;
    @NotNull(message = "任务id为空", groups = AddGroup.class)
    private Long taskId;
    /**
     * å®¡æ‰¹æ„è§
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java
@@ -26,13 +26,13 @@
     * ä¸šåС唝䏀值id
     */
    @NotBlank(message = "业务ID不能为空", groups = {AddGroup.class})
    private String businessKey;
    private String businessId;
    /**
     * è¡¨å
     * æµç¨‹å®šä¹‰ç¼–码
     */
    @NotBlank(message = "表名不能为空", groups = {AddGroup.class})
    private String tableName;
    @NotBlank(message = "流程定义编码不能为空", groups = {AddGroup.class})
    private String flowCode;
    /**
     * æµç¨‹å˜é‡ï¼Œå‰ç«¯ä¼šæäº¤ä¸€ä¸ªå…ƒç´ {'entity': {业务详情数据对象}}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
 * ä»»åŠ¡æ“ä½œä¸šåŠ¡å¯¹è±¡ï¼Œç”¨äºŽæè¿°ä»»åŠ¡å§”æ´¾ã€è½¬åŠžã€åŠ ç­¾ç­‰æ“ä½œçš„å¿…è¦å‚æ•°
 * åŒ…含了用户ID、任务ID、任务相关的消息、以及加签/减签的用户ID
 *
 * @author AprilWind
 */
@Data
public class TaskOperationBo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * å§”æ´¾/转办人的用户ID(必填,准对委派/转办人操作)
     */
    @NotNull(message = "委派/转办人id不能为空", groups = {AddGroup.class})
    private String userId;
    /**
     * åŠ ç­¾/减签人的用户ID列表(必填,针对加签/减签操作)
     */
    @NotNull(message = "加签/减签id不能为空", groups = {EditGroup.class})
    private List<String> userIds;
    /**
     * ä»»åŠ¡ID(必填)
     */
    @NotNull(message = "任务id不能为空")
    private Long taskId;
    /**
     * æ„è§æˆ–备注信息(可选)
     */
    private String message;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java
@@ -53,7 +53,6 @@
    /**
     * è¯·å‡å¤©æ•°
     */
    @NotNull(message = "请假天数不能为空", groups = {AddGroup.class, EditGroup.class})
    private Integer leaveDays;
    /**
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
package org.dromara.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.workflow.domain.FlowCategory;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
 * æµç¨‹åˆ†ç±»è§†å›¾å¯¹è±¡ wf_category
 *
 * @author may
 * @date 2023-06-27
 */
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = FlowCategory.class)
public class FlowCategoryVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * æµç¨‹åˆ†ç±»ID
     */
    @ExcelProperty(value = "流程分类ID")
    private Long categoryId;
    /**
     * çˆ¶çº§id
     */
    private Long parentId;
    /**
     * çˆ¶ç±»åˆ«åç§°
     */
    private String parentName;
    /**
     * ç¥–级列表
     */
    private String ancestors;
    /**
     * æµç¨‹åˆ†ç±»åç§°
     */
    @ExcelProperty(value = "流程分类名称")
    private String categoryName;
    /**
     * æ˜¾ç¤ºé¡ºåº
     */
    @ExcelProperty(value = "显示顺序")
    private Long orderNum;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    @ExcelProperty(value = "创建时间")
    private Date createTime;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,104 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.workflow.common.constant.FlowConstant;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
 * æµç¨‹å®šä¹‰è§†å›¾
 *
 * @author may
 */
@Data
public class FlowDefinitionVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    private Long id;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime;
    /**
     * æ›´æ–°æ—¶é—´
     */
    private Date updateTime;
    /**
     * ç§Ÿæˆ·ID
     */
    private String tenantId;
    /**
     * åˆ é™¤æ ‡è®°
     */
    private String delFlag;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * æµç¨‹å®šä¹‰åç§°
     */
    private String flowName;
    /**
     * æµç¨‹åˆ†ç±»id
     */
    private String category;
    /**
     * æµç¨‹åˆ†ç±»åç§°
     */
    @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category")
    private String categoryName;
    /**
     * æµç¨‹ç‰ˆæœ¬
     */
    private String version;
    /**
     * æ˜¯å¦å‘布(0未发布 1已发布 9失效)
     */
    private Integer isPublish;
    /**
     * å®¡æ‰¹è¡¨å•是否自定义(Y是 N否)
     */
    private String formCustom;
    /**
     * å®¡æ‰¹è¡¨å•路径
     */
    private String formPath;
    /**
     * æµç¨‹æ¿€æ´»çŠ¶æ€ï¼ˆ0挂起 1激活)
     */
    private Integer activityStatus;
    /**
     * ç›‘听器类型
     */
    private String listenerType;
    /**
     * ç›‘听器路径
     */
    private String listenerPath;
    /**
     * æ‰©å±•字段,预留给业务系统使用
     */
    private String ext;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,244 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.warm.flow.core.enums.CooperateType;
import org.dromara.workflow.common.constant.FlowConstant;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
 * åŽ†å²ä»»åŠ¡è§†å›¾
 *
 * @author may
 */
@Data
public class FlowHisTaskVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    private Long id;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime;
    /**
     * æ›´æ–°æ—¶é—´
     */
    private Date updateTime;
    /**
     * ç§Ÿæˆ·ID
     */
    private String tenantId;
    /**
     * åˆ é™¤æ ‡è®°
     */
    private String delFlag;
    /**
     * å¯¹åº”flow_definition表的id
     */
    private Long definitionId;
    /**
     * æµç¨‹å®šä¹‰åç§°
     */
    private String flowName;
    /**
     * æµç¨‹å®žä¾‹è¡¨id
     */
    private Long instanceId;
    /**
     * ä»»åŠ¡è¡¨id
     */
    private Long taskId;
    /**
     * åä½œæ–¹å¼(1审批 2转办 3委派 4会签 5票签 6加签 7减签)
     */
    private Integer cooperateType;
    /**
     * åä½œæ–¹å¼(1审批 2转办 3委派 4会签 5票签 6加签 7减签)
     */
    private String cooperateTypeName;
    /**
     * ä¸šåŠ¡id
     */
    private String businessId;
    /**
     * å¼€å§‹èŠ‚ç‚¹ç¼–ç 
     */
    private String nodeCode;
    /**
     * å¼€å§‹èŠ‚ç‚¹åç§°
     */
    private String nodeName;
    /**
     * å¼€å§‹èŠ‚ç‚¹ç±»åž‹ï¼ˆ0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
     */
    private Integer nodeType;
    /**
     * ç›®æ ‡èŠ‚ç‚¹ç¼–ç 
     */
    private String targetNodeCode;
    /**
     * ç»“束节点名称
     */
    private String targetNodeName;
    /**
     * å®¡æ‰¹è€…
     */
    private String approver;
    /**
     * å®¡æ‰¹è€…
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "approver")
    private String approveName;
    /**
     * åä½œäºº(只有转办、会签、票签、委派)
     */
    private String collaborator;
    /**
     * æƒé™æ ‡è¯† permissionFlag的list形式
     */
    private List<String> permissionList;
    /**
     * è·³è½¬ç±»åž‹ï¼ˆPASS通过 REJECT退回 NONE无动作)
     */
    private String skipType;
    /**
     * æµç¨‹çŠ¶æ€
     */
    private String flowStatus;
    /**
     * ä»»åŠ¡çŠ¶æ€
     */
    private String flowTaskStatus;
    /**
     * æµç¨‹çŠ¶æ€
     */
    private String flowStatusName;
    /**
     * å®¡æ‰¹æ„è§
     */
    private String message;
    /**
     * ä¸šåŠ¡è¯¦æƒ… å­˜ä¸šåŠ¡ç±»çš„json
     */
    private String ext;
    /**
     * åˆ›å»ºè€…
     */
    private String createBy;
    /**
     * ç”³è¯·äºº
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy")
    private String createByName;
    /**
     * æµç¨‹åˆ†ç±»id
     */
    private String category;
    /**
     * æµç¨‹åˆ†ç±»åç§°
     */
    @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category")
    private String categoryName;
    /**
     * å®¡æ‰¹è¡¨å•是否自定义(Y是 N否)
     */
    private String formCustom;
    /**
     * å®¡æ‰¹è¡¨å•路径
     */
    private String formPath;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * æµç¨‹ç‰ˆæœ¬å·
     */
    private String version;
    /**
     * è¿è¡Œæ—¶é•¿
     */
    private String runDuration;
    /**
     * è®¾ç½®åˆ›å»ºæ—¶é—´å¹¶è®¡ç®—任务运行时长
     *
     * @param createTime åˆ›å»ºæ—¶é—´
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
        updateRunDuration();
    }
    /**
     * è®¾ç½®æ›´æ–°æ—¶é—´å¹¶è®¡ç®—任务运行时长
     *
     * @param updateTime æ›´æ–°æ—¶é—´
     */
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
        updateRunDuration();
    }
    /**
     * æ›´æ–°è¿è¡Œæ—¶é•¿
     */
    private void updateRunDuration() {
        // å¦‚果创建时间和更新时间均不为空,计算它们之间的时长
        if (this.updateTime != null && this.createTime != null) {
            this.runDuration = DateUtils.getTimeDifference(this.updateTime, this.createTime);
        }
    }
    /**
     * è®¾ç½®åä½œæ–¹å¼ï¼Œå¹¶é€šè¿‡åä½œæ–¹å¼èŽ·å–åç§°
     */
    public void setCooperateType(Integer cooperateType) {
        this.cooperateType = cooperateType;
        this.cooperateTypeName = CooperateType.getValueByKey(cooperateType);
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.workflow.common.constant.FlowConstant;
import java.util.Date;
/**
 * æµç¨‹å®žä¾‹è§†å›¾
 *
 * @author may
 */
@Data
public class FlowInstanceVo {
    private Long id;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime;
    /**
     * æ›´æ–°æ—¶é—´
     */
    private Date updateTime;
    /**
     * ç§Ÿæˆ·ID
     */
    private String tenantId;
    /**
     * åˆ é™¤æ ‡è®°
     */
    private String delFlag;
    /**
     * å¯¹åº”flow_definition表的id
     */
    private Long definitionId;
    /**
     * æµç¨‹å®šä¹‰åç§°
     */
    private String flowName;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * ä¸šåŠ¡id
     */
    private String businessId;
    /**
     * èŠ‚ç‚¹ç±»åž‹ï¼ˆ0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
     */
    private Integer nodeType;
    /**
     * æµç¨‹èŠ‚ç‚¹ç¼–ç    æ¯ä¸ªæµç¨‹çš„nodeCode是唯一的,即definitionId+nodeCode唯一,在数据库层面做了控制
     */
    private String nodeCode;
    /**
     * æµç¨‹èŠ‚ç‚¹åç§°
     */
    private String nodeName;
    /**
     * æµç¨‹å˜é‡
     */
    private String variable;
    /**
     * æµç¨‹çŠ¶æ€ï¼ˆ0待提交 1审批中 2 å®¡æ‰¹é€šè¿‡ 3自动通过 8已完成 9已退回 10失效)
     */
    private String flowStatus;
    /**
     * æµç¨‹çŠ¶æ€
     */
    private String flowStatusName;
    /**
     * æµç¨‹æ¿€æ´»çŠ¶æ€ï¼ˆ0挂起 1激活)
     */
    private Integer activityStatus;
    /**
     * å®¡æ‰¹è¡¨å•是否自定义(Y是 N否)
     */
    private String formCustom;
    /**
     * å®¡æ‰¹è¡¨å•路径
     */
    private String formPath;
    /**
     * æ‰©å±•字段,预留给业务系统使用
     */
    private String ext;
    /**
     * æµç¨‹å®šä¹‰ç‰ˆæœ¬
     */
    private String version;
    /**
     * åˆ›å»ºè€…
     */
    private String createBy;
    /**
     * ç”³è¯·äºº
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy")
    private String createByName;
    /**
     * æµç¨‹åˆ†ç±»id
     */
    private String category;
    /**
     * æµç¨‹åˆ†ç±»åç§°
     */
    @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category")
    private String categoryName;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,176 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.warm.flow.core.entity.User;
import org.dromara.workflow.common.constant.FlowConstant;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
 * ä»»åŠ¡è§†å›¾
 *
 * @author may
 */
@Data
public class FlowTaskVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    private Long id;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime;
    /**
     * æ›´æ–°æ—¶é—´
     */
    private Date updateTime;
    /**
     * ç§Ÿæˆ·ID
     */
    private String tenantId;
    /**
     * åˆ é™¤æ ‡è®°
     */
    private String delFlag;
    /**
     * å¯¹åº”flow_definition表的id
     */
    private Long definitionId;
    /**
     * æµç¨‹å®žä¾‹è¡¨id
     */
    private Long instanceId;
    /**
     * æµç¨‹å®šä¹‰åç§°
     */
    private String flowName;
    /**
     * ä¸šåŠ¡id
     */
    private String businessId;
    /**
     * èŠ‚ç‚¹ç¼–ç 
     */
    private String nodeCode;
    /**
     * èŠ‚ç‚¹åç§°
     */
    private String nodeName;
    /**
     * èŠ‚ç‚¹ç±»åž‹ï¼ˆ0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
     */
    private Integer nodeType;
    /**
     * æƒé™æ ‡è¯† permissionFlag的list形式
     */
    private List<String> permissionList;
    /**
     * æµç¨‹ç”¨æˆ·åˆ—表
     */
    private List<User> userList;
    /**
     * å®¡æ‰¹è¡¨å•是否自定义(Y是 N否)
     */
    private String formCustom;
    /**
     * å®¡æ‰¹è¡¨å•
     */
    private String formPath;
    /**
     * æµç¨‹å®šä¹‰ç¼–码
     */
    private String flowCode;
    /**
     * æµç¨‹ç‰ˆæœ¬å·
     */
    private String version;
    /**
     * æµç¨‹çŠ¶æ€
     */
    private String flowStatus;
    /**
     * æµç¨‹åˆ†ç±»id
     */
    private String category;
    /**
     * æµç¨‹åˆ†ç±»åç§°
     */
    @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category")
    private String categoryName;
    /**
     * æµç¨‹çŠ¶æ€
     */
    @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "flowStatus", other = "wf_business_status")
    private String flowStatusName;
    /**
     * åŠžç†äººç±»åž‹
     */
    private String type;
    /**
     * åŠžç†äººids
     */
    private String assigneeIds;
    /**
     * åŠžç†äººåç§°
     */
    private String assigneeNames;
    /**
     * æŠ„送人id
     */
    private String processedBy;
    /**
     * æŠ„送人名称
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "processedBy")
    private String processedByName;
    /**
     * æµç¨‹ç­¾ç½²æ¯”例值 å¤§äºŽ0为票签,会签
     */
    private BigDecimal nodeRatio;
    /**
     * ç”³è¯·äººid
     */
    private String createBy;
    /**
     * ç”³è¯·äººåç§°
     */
    @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy")
    private String createByName;
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowVariableVo.java
ÎļþÃû´Ó ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/VariableVo.java ÐÞ¸Ä
@@ -11,7 +11,7 @@
 * @author may
 */
@Data
public class VariableVo implements Serializable {
public class FlowVariableVo implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
package org.dromara.workflow.handler;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.tenant.helper.TenantHelper;
import org.springframework.stereotype.Component;
/**
 * æµç¨‹ç›‘听服务
 *
 * @author may
 * @date 2024-06-02
 */
@Slf4j
@Component
public class FlowProcessEventHandler {
    /**
     * æ€»ä½“流程监听(例如: è‰ç¨¿ï¼Œæ’¤é”€ï¼Œé€€å›žï¼Œä½œåºŸï¼Œç»ˆæ­¢ï¼Œå·²å®Œæˆç­‰)
     *
     * @param flowCode   æµç¨‹å®šä¹‰ç¼–码
     * @param businessId ä¸šåŠ¡id
     * @param status     çŠ¶æ€
     * @param submit     å½“为true时为申请人节点办理
     */
    public void processHandler(String flowCode, String businessId, String status, boolean submit) {
        String tenantId = TenantHelper.getTenantId();
        log.info("发布流程事件,租户ID: {}, æµç¨‹çŠ¶æ€: {}, æµç¨‹ç¼–码: {}, ä¸šåŠ¡ID: {}, æ˜¯å¦ç”³è¯·äººèŠ‚ç‚¹åŠžç†: {}", tenantId, status, flowCode, businessId, submit);
        ProcessEvent processEvent = new ProcessEvent();
        processEvent.setTenantId(tenantId);
        processEvent.setFlowCode(flowCode);
        processEvent.setBusinessId(businessId);
        processEvent.setStatus(status);
        processEvent.setSubmit(submit);
        SpringUtils.context().publishEvent(processEvent);
    }
    /**
     * æ‰§è¡ŒåŠžç†ä»»åŠ¡ç›‘å¬
     *
     * @param flowCode   æµç¨‹å®šä¹‰ç¼–码
     * @param nodeCode   å®¡æ‰¹èŠ‚ç‚¹ç¼–ç 
     * @param taskId     ä»»åŠ¡id
     * @param businessId ä¸šåŠ¡id
     */
    public void processTaskHandler(String flowCode, String nodeCode, Long taskId, String businessId) {
        String tenantId = TenantHelper.getTenantId();
        log.info("发布流程任务事件, ç§Ÿæˆ·ID: {}, æµç¨‹ç¼–码: {}, èŠ‚ç‚¹ç¼–ç : {}, ä»»åŠ¡ID: {}, ä¸šåŠ¡ID: {}", tenantId, flowCode, nodeCode, taskId, businessId);
        ProcessTaskEvent processTaskEvent = new ProcessTaskEvent();
        processTaskEvent.setTenantId(tenantId);
        processTaskEvent.setFlowCode(flowCode);
        processTaskEvent.setNodeCode(nodeCode);
        processTaskEvent.setTaskId(taskId);
        processTaskEvent.setBusinessId(businessId);
        SpringUtils.context().publishEvent(processTaskEvent);
    }
    /**
     * åˆ é™¤æµç¨‹ç›‘听
     *
     * @param flowCode    æµç¨‹å®šä¹‰ç¼–码
     * @param businessId  ä¸šåŠ¡ID
     */
    public void processDeleteHandler(String flowCode, String businessId) {
        String tenantId = TenantHelper.getTenantId();
        log.info("发布删除流程事件, ç§Ÿæˆ·ID: {}, æµç¨‹ç¼–码: {}, ä¸šåŠ¡ID: {}", tenantId, flowCode, businessId);
        ProcessDeleteEvent processDeleteEvent = new ProcessDeleteEvent();
        processDeleteEvent.setTenantId(tenantId);
        processDeleteEvent.setFlowCode(flowCode);
        processDeleteEvent.setBusinessId(businessId);
        SpringUtils.context().publishEvent(processDeleteEvent);
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
package org.dromara.workflow.handler;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.workflow.common.enums.TaskAssigneeEnum;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.handler.PermissionHandler;
import org.dromara.warm.flow.core.service.impl.TaskServiceImpl;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * åŠžç†äººæƒé™å¤„ç†å™¨
 *
 * @author AprilWind
 */
@RequiredArgsConstructor
@Component
@Slf4j
public class WorkflowPermissionHandler implements PermissionHandler {
    /**
     * å®¡æ‰¹å‰èŽ·å–å½“å‰åŠžç†äººï¼ŒåŠžç†æ—¶ä¼šæ ¡éªŒçš„è¯¥æƒé™é›†åˆ
     * åŽç»­åœ¨{@link TaskServiceImpl#checkAuth(Task, FlowParams)} ä¸­è°ƒç”¨
     * è¿”回当前用户权限集合
     */
    @Override
    public List<String> permissions() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (ObjectUtil.isNull(loginUser)) {
            return new ArrayList<>();
        }
        // ä½¿ç”¨ä¸€ä¸ªæµæ¥æž„建权限列表
        return Stream.of(
                // è§’色权限前缀
                loginUser.getRoles().stream()
                    .map(role -> TaskAssigneeEnum.ROLE.getCode() + role.getRoleId()),
                // å²—位权限前缀
                Stream.ofNullable(loginUser.getPosts())
                    .flatMap(Collection::stream)
                    .map(post -> TaskAssigneeEnum.POST.getCode() + post.getPostId()),
                // ç”¨æˆ·å’Œéƒ¨é—¨æƒé™
                Stream.of(String.valueOf(loginUser.getUserId()),
                    TaskAssigneeEnum.DEPT.getCode() + loginUser.getDeptId()
                )
            )
            .flatMap(stream -> stream)
            .collect(Collectors.toList());
    }
    /**
     * èŽ·å–å½“å‰åŠžç†äºº
     *
     * @return å½“前办理人
     */
    @Override
    public String getHandler() {
        return LoginHelper.getUserIdStr();
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,115 @@
package org.dromara.workflow.listener;
import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.utils.StringUtils;
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.listener.GlobalListener;
import org.dromara.warm.flow.core.listener.ListenerVariable;
import org.dromara.warm.flow.orm.entity.FlowTask;
import org.dromara.workflow.handler.FlowProcessEventHandler;
import org.dromara.workflow.service.IFlwInstanceService;
import org.dromara.workflow.service.IFlwTaskService;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * å…¨å±€ä»»åŠ¡åŠžç†ç›‘å¬
 *
 * @author may
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class WorkflowGlobalListener implements GlobalListener {
    private final IFlwTaskService taskService;
    private final IFlwInstanceService instanceService;
    private final FlowProcessEventHandler flowProcessEventHandler;
    /**
     * åˆ›å»ºç›‘听器,任务创建时执行
     *
     * @param listenerVariable ç›‘听器变量
     */
    @Override
    public void create(ListenerVariable listenerVariable) {
        Instance instance = listenerVariable.getInstance();
        Definition definition = listenerVariable.getDefinition();
        String businessId = instance.getBusinessId();
        String flowStatus = instance.getFlowStatus();
        Task task = listenerVariable.getTask();
        if (task != null && BusinessStatusEnum.WAITING.getStatus().equals(flowStatus)) {
            // åˆ¤æ–­æµç¨‹çŠ¶æ€ï¼ˆå‘å¸ƒå®¡æ‰¹ä¸­äº‹ä»¶ï¼‰
            flowProcessEventHandler.processTaskHandler(definition.getFlowCode(), task.getNodeCode(), task.getId(), businessId);
        }
    }
    /**
     * å¼€å§‹ç›‘听器,任务开始办理时执行
     *
     * @param listenerVariable ç›‘听器变量
     */
    @Override
    public void start(ListenerVariable listenerVariable) {
    }
    /**
     * åˆ†æ´¾ç›‘听器,动态修改代办任务信息
     *
     * @param listenerVariable ç›‘听器变量
     */
    @Override
    public void assignment(ListenerVariable listenerVariable) {
    }
    /**
     * å®Œæˆç›‘听器,当前任务完成后执行
     *
     * @param listenerVariable ç›‘听器变量
     */
    @Override
    public void finish(ListenerVariable listenerVariable) {
        Instance instance = listenerVariable.getInstance();
        Definition definition = listenerVariable.getDefinition();
        String businessId = instance.getBusinessId();
        String flowStatus = instance.getFlowStatus();
        // åˆ¤æ–­æµç¨‹çŠ¶æ€ï¼ˆå‘å¸ƒï¼šæ’¤é”€ï¼Œé€€å›žï¼Œä½œåºŸï¼Œç»ˆæ­¢ï¼Œå·²å®Œæˆäº‹ä»¶ï¼‰
        String status = determineFlowStatus(instance, flowStatus);
        if (StringUtils.isNotBlank(status)) {
            flowProcessEventHandler.processHandler(definition.getFlowCode(), businessId, status, false);
        }
    }
    /**
     * æ ¹æ®æµç¨‹å®žä¾‹å’Œå½“前流程状态确定最终状态
     *
     * @param instance   æµç¨‹å®žä¾‹
     * @param flowStatus æµç¨‹å®žä¾‹å½“前状态
     * @return æµç¨‹æœ€ç»ˆçŠ¶æ€
     */
    private String determineFlowStatus(Instance instance, String flowStatus) {
        if (StringUtils.isNotBlank(flowStatus) && BusinessStatusEnum.initialState(flowStatus)) {
            log.info("流程实例当前状态: {}", flowStatus);
            return flowStatus;
        } else {
            Long instanceId = instance.getId();
            List<FlowTask> flowTasks = taskService.selectByInstId(instanceId);
            if (CollUtil.isEmpty(flowTasks)) {
                String status = BusinessStatusEnum.FINISH.getStatus();
                // æ›´æ–°æµç¨‹çŠ¶æ€ä¸ºå·²å®Œæˆ
                instanceService.updateStatus(instanceId, status);
                log.info("流程已结束,状态更新为: {}", status);
                return status;
            }
            log.warn("流程未结束,实例ID: {}", instanceId);
            return null;
        }
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
package org.dromara.workflow.mapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.annotation.DataPermission;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.common.mybatis.helper.DataBaseHelper;
import org.dromara.workflow.domain.FlowCategory;
import org.dromara.workflow.domain.vo.FlowCategoryVo;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * æµç¨‹åˆ†ç±»Mapper接口
 *
 * @author may
 * @date 2023-06-27
 */
public interface FlwCategoryMapper extends BaseMapperPlus<FlowCategory, FlowCategoryVo> {
    /**
     * ç»Ÿè®¡æŒ‡å®šæµç¨‹åˆ†ç±»ID的分类数量
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     * @return è¯¥æµç¨‹åˆ†ç±»ID的分类数量
     */
    @DataPermission({
        @DataColumn(key = "deptName", value = "createDept")
    })
    long countCategoryById(Long categoryId);
    /**
     * æ ¹æ®çˆ¶æµç¨‹åˆ†ç±»ID查询其所有子流程分类的列表
     *
     * @param parentId çˆ¶æµç¨‹åˆ†ç±»ID
     * @return åŒ…含子流程分类的列表
     */
    default List<FlowCategory> selectListByParentId(Long parentId) {
        return this.selectList(new LambdaQueryWrapper<FlowCategory>()
            .select(FlowCategory::getCategoryId)
            .apply(DataBaseHelper.findInSet(parentId, "ancestors")));
    }
    /**
     * æ ¹æ®çˆ¶æµç¨‹åˆ†ç±»ID查询包括父ID及其所有子流程分类ID的列表
     *
     * @param parentId çˆ¶æµç¨‹åˆ†ç±»ID
     * @return åŒ…含父ID和子流程分类ID的列表
     */
    default List<Long> selectCategoryIdsByParentId(Long parentId) {
        return Stream.concat(
            this.selectListByParentId(parentId).stream()
                .map(FlowCategory::getCategoryId),
            Stream.of(parentId)
        ).collect(Collectors.toList());
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package org.dromara.workflow.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.workflow.domain.bo.FlowInstanceBo;
import org.dromara.workflow.domain.vo.FlowInstanceVo;
/**
 * å®žä¾‹ä¿¡æ¯Mapper接口
 *
 * @author may
 * @date 2024-03-02
 */
public interface FlwInstanceMapper {
    /**
     * æµç¨‹å®žä¾‹ä¿¡æ¯
     *
     * @param page         åˆ†é¡µ
     * @param queryWrapper æ¡ä»¶
     * @return ç»“æžœ
     */
    Page<FlowInstanceVo> selectInstanceList(@Param("page") Page<FlowInstanceVo> page, @Param(Constants.WRAPPER) Wrapper<FlowInstanceBo> queryWrapper);
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
package org.dromara.workflow.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.workflow.domain.bo.FlowTaskBo;
import org.dromara.workflow.domain.vo.FlowHisTaskVo;
import org.dromara.workflow.domain.vo.FlowTaskVo;
import java.util.List;
/**
 * ä»»åŠ¡ä¿¡æ¯Mapper接口
 *
 * @author may
 * @date 2024-03-02
 */
public interface FlwTaskMapper {
    /**
     * èŽ·å–å¾…åŠžä¿¡æ¯
     *
     * @param page         åˆ†é¡µ
     * @param queryWrapper æ¡ä»¶
     * @return ç»“æžœ
     */
    Page<FlowTaskVo> getListRunTask(@Param("page") Page<FlowTaskVo> page, @Param(Constants.WRAPPER) Wrapper<FlowTaskBo> queryWrapper);
    /**
     * èŽ·å–å¾…åŠžä¿¡æ¯
     *
     * @param queryWrapper æ¡ä»¶
     * @return ç»“æžœ
     */
    List<FlowTaskVo> getListRunTask(@Param(Constants.WRAPPER) Wrapper<FlowTaskBo> queryWrapper);
    /**
     * èŽ·å–å·²åŠž
     *
     * @param page         åˆ†é¡µ
     * @param queryWrapper æ¡ä»¶
     * @return ç»“æžœ
     */
    Page<FlowHisTaskVo> getListFinishTask(@Param("page") Page<FlowTaskVo> page, @Param(Constants.WRAPPER) Wrapper<FlowTaskBo> queryWrapper);
    /**
     * æŸ¥è¯¢å½“前用户的抄送
     *
     * @param page         åˆ†é¡µ
     * @param queryWrapper æ¡ä»¶
     * @return ç»“æžœ
     */
    Page<FlowTaskVo> getTaskCopyByPage(@Param("page") Page<FlowTaskVo> page, @Param(Constants.WRAPPER) QueryWrapper<FlowTaskBo> queryWrapper);
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,102 @@
package org.dromara.workflow.service;
import cn.hutool.core.lang.tree.Tree;
import org.dromara.workflow.domain.bo.FlowCategoryBo;
import org.dromara.workflow.domain.vo.FlowCategoryVo;
import java.util.List;
/**
 * æµç¨‹åˆ†ç±»Service接口
 *
 * @author may
 */
public interface IFlwCategoryService {
    /**
     * æŸ¥è¯¢æµç¨‹åˆ†ç±»
     *
     * @param categoryId ä¸»é”®
     * @return æµç¨‹åˆ†ç±»
     */
    FlowCategoryVo queryById(Long categoryId);
    /**
     * æ ¹æ®æµç¨‹åˆ†ç±»ID查询流程分类名称
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     * @return æµç¨‹åˆ†ç±»åç§°
     */
    String selectCategoryNameById(String categoryId);
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„æµç¨‹åˆ†ç±»åˆ—表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return æµç¨‹åˆ†ç±»åˆ—表
     */
    List<FlowCategoryVo> queryList(FlowCategoryBo bo);
    /**
     * æŸ¥è¯¢æµç¨‹åˆ†ç±»æ ‘结构信息
     *
     * @param category æµç¨‹åˆ†ç±»ä¿¡æ¯
     * @return æµç¨‹åˆ†ç±»æ ‘信息集合
     */
    List<Tree<Long>> selectCategoryTreeList(FlowCategoryBo category);
    /**
     * æ ¡éªŒæµç¨‹åˆ†ç±»æ˜¯å¦æœ‰æ•°æ®æƒé™
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     */
    void checkCategoryDataScope(Long categoryId);
    /**
     * æ ¡éªŒæµç¨‹åˆ†ç±»åç§°æ˜¯å¦å”¯ä¸€
     *
     * @param category æµç¨‹åˆ†ç±»ä¿¡æ¯
     * @return ç»“æžœ
     */
    boolean checkCategoryNameUnique(FlowCategoryBo category);
    /**
     * æŸ¥è¯¢æµç¨‹åˆ†ç±»æ˜¯å¦å­˜åœ¨æµç¨‹å®šä¹‰
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     * @return ç»“æžœ true å­˜åœ¨ false ä¸å­˜åœ¨
     */
    boolean checkCategoryExistDefinition(Long categoryId);
    /**
     * æ˜¯å¦å­˜åœ¨æµç¨‹åˆ†ç±»å­èŠ‚ç‚¹
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     * @return ç»“æžœ
     */
    boolean hasChildByCategoryId(Long categoryId);
    /**
     * æ–°å¢žæµç¨‹åˆ†ç±»
     *
     * @param bo æµç¨‹åˆ†ç±»
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    int insertByBo(FlowCategoryBo bo);
    /**
     * ä¿®æ”¹æµç¨‹åˆ†ç±»
     *
     * @param bo æµç¨‹åˆ†ç±»
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    int updateByBo(FlowCategoryBo bo);
    /**
     * åˆ é™¤æµç¨‹åˆ†ç±»ä¿¡æ¯
     *
     * @param categoryId ä¸»é”®
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    int deleteWithValidById(Long categoryId);
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
package org.dromara.workflow.service;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.warm.flow.orm.entity.FlowDefinition;
import org.dromara.workflow.domain.vo.FlowDefinitionVo;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
/**
 * æµç¨‹å®šä¹‰ æœåС层
 *
 * @author may
 */
public interface IFlwDefinitionService {
    /**
     * æŸ¥è¯¢æµç¨‹å®šä¹‰åˆ—表
     *
     * @param flowDefinition å‚æ•°
     * @param pageQuery      åˆ†é¡µ
     * @return è¿”回分页列表
     */
    TableDataInfo<FlowDefinitionVo> queryList(FlowDefinition flowDefinition, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢æœªå‘布的流程定义列表
     *
     * @param flowDefinition å‚æ•°
     * @param pageQuery      åˆ†é¡µ
     * @return è¿”回分页列表
     */
    TableDataInfo<FlowDefinitionVo> unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery);
    /**
     * å‘布流程定义
     *
     * @param id æµç¨‹å®šä¹‰id
     * @return ç»“æžœ
     */
    boolean publish(Long id);
    /**
     * å¯¼å‡ºæµç¨‹å®šä¹‰
     *
     * @param id       æµç¨‹å®šä¹‰id
     * @param response å“åº”
     * @throws IOException å¼‚常
     */
    void exportDef(Long id, HttpServletResponse response) throws IOException;
    /**
     * å¯¼å…¥æµç¨‹å®šä¹‰
     *
     * @param file     æ–‡ä»¶
     * @param category åˆ†ç±»
     * @return ç»“æžœ
     */
    boolean importXml(MultipartFile file, String category);
    /**
     * åˆ é™¤æµç¨‹å®šä¹‰
     *
     * @param ids æµç¨‹å®šä¹‰id
     * @return ç»“æžœ
     */
    boolean removeDef(List<Long> ids);
    /**
     * æ–°å¢žç§Ÿæˆ·æµç¨‹å®šä¹‰
     *
     * @param tenantId ç§Ÿæˆ·id
     */
    void syncDef(String tenantId);
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,159 @@
package org.dromara.workflow.service;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.warm.flow.orm.entity.FlowInstance;
import org.dromara.workflow.domain.bo.FlowCancelBo;
import org.dromara.workflow.domain.bo.FlowInstanceBo;
import org.dromara.workflow.domain.bo.FlowInvalidBo;
import org.dromara.workflow.domain.vo.FlowInstanceVo;
import java.util.List;
import java.util.Map;
/**
 * æµç¨‹å®žä¾‹ æœåС层
 *
 * @author may
 */
public interface IFlwInstanceService {
    /**
     * åˆ†é¡µæŸ¥è¯¢æ­£åœ¨è¿è¡Œçš„æµç¨‹å®žä¾‹
     *
     * @param flowInstanceBo æµç¨‹å®žä¾‹
     * @param pageQuery      åˆ†é¡µ
     * @return ç»“æžœ
     */
    TableDataInfo<FlowInstanceVo> selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery);
    /**
     * åˆ†é¡µæŸ¥è¯¢å·²ç»“束的流程实例
     *
     * @param flowInstanceBo æµç¨‹å®žä¾‹
     * @param pageQuery      åˆ†é¡µ
     * @return ç»“æžœ
     */
    TableDataInfo<FlowInstanceVo> selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery);
    /**
     * æ ¹æ®ä¸šåŠ¡id查询流程实例详细信息
     *
     * @param businessId ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    FlowInstanceVo queryByBusinessId(Long businessId);
    /**
     * æŒ‰ç…§ä¸šåŠ¡id查询流程实例
     *
     * @param businessId ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    FlowInstance selectInstByBusinessId(String businessId);
    /**
     * æŒ‰ç…§å®žä¾‹id查询流程实例
     *
     * @param instanceId å®žä¾‹id
     * @return ç»“æžœ
     */
    FlowInstance selectInstById(Long instanceId);
    /**
     * æŒ‰ç…§å®žä¾‹id查询流程实例
     *
     * @param instanceIds å®žä¾‹id
     * @return ç»“æžœ
     */
    List<FlowInstance> selectInstListByIdList(List<Long> instanceIds);
    /**
     * æŒ‰ç…§ä¸šåŠ¡id删除流程实例
     *
     * @param businessIds ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    boolean deleteByBusinessIds(List<Long> businessIds);
    /**
     * æŒ‰ç…§å®žä¾‹id删除流程实例
     *
     * @param instanceIds å®žä¾‹id
     * @return ç»“æžœ
     */
    boolean deleteByInstanceIds(List<Long> instanceIds);
    /**
     * æ’¤é”€æµç¨‹
     *
     * @param bo å‚æ•°
     * @return ç»“æžœ
     */
    boolean cancelProcessApply(FlowCancelBo bo);
    /**
     * èŽ·å–å½“å‰ç™»é™†äººå‘èµ·çš„æµç¨‹å®žä¾‹
     *
     * @param instanceBo æµç¨‹å®žä¾‹
     * @param pageQuery  åˆ†é¡µ
     * @return ç»“æžœ
     */
    TableDataInfo<FlowInstanceVo> selectCurrentInstanceList(FlowInstanceBo instanceBo, PageQuery pageQuery);
    /**
     * èŽ·å–æµç¨‹å›¾,流程记录
     *
     * @param businessId ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    Map<String, Object> flowImage(String businessId);
    /**
     * æŒ‰ç…§å®žä¾‹id更新状态
     *
     * @param instanceId å®žä¾‹id
     * @param status     çŠ¶æ€
     */
    void updateStatus(Long instanceId, String status);
    /**
     * èŽ·å–æµç¨‹å˜é‡
     *
     * @param instanceId å®žä¾‹id
     * @return ç»“æžœ
     */
    Map<String, Object> instanceVariable(String instanceId);
    /**
     * è®¾ç½®æµç¨‹å˜é‡
     *
     * @param instanceId å®žä¾‹id
     * @param variable   æµç¨‹å˜é‡
     */
    void setVariable(Long instanceId, Map<String, Object> variable);
    /**
     * æŒ‰ä»»åŠ¡id查询实例
     *
     * @param taskId ä»»åŠ¡id
     * @return ç»“æžœ
     */
    FlowInstance selectByTaskId(Long taskId);
    /**
     * æŒ‰ä»»åŠ¡id查询实例
     *
     * @param taskIdList ä»»åŠ¡id
     * @return ç»“æžœ
     */
    List<FlowInstance> selectByTaskIdList(List<Long> taskIdList);
    /**
     * ä½œåºŸæµç¨‹
     *
     * @param bo æµç¨‹å®žä¾‹
     * @return ç»“æžœ
     */
    boolean processInvalid(FlowInvalidBo bo);
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package org.dromara.workflow.service;
import org.dromara.common.core.domain.dto.UserDTO;
import java.util.List;
/**
 * æµç¨‹è®¾è®¡å™¨-获取办理人
 *
 * @author AprilWind
 */
public interface IFlwTaskAssigneeService {
    /**
     * æ ¹æ®å­˜å‚¨æ ‡è¯†ç¬¦ï¼ˆstorageId)解析分配类型和ID,并获取对应的用户列表
     *
     * @param storageId åŒ…含分配类型和ID的字符串(例如 "user:123" æˆ– "role:456")
     * @return ä¸Žåˆ†é…ç±»åž‹å’ŒID匹配的用户列表,如果格式无效则返回空列表
     */
    List<UserDTO> fetchUsersByStorageId(String storageId);
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,190 @@
package org.dromara.workflow.service;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.warm.flow.core.entity.Node;
import org.dromara.warm.flow.orm.entity.FlowHisTask;
import org.dromara.warm.flow.orm.entity.FlowTask;
import org.dromara.workflow.domain.bo.*;
import org.dromara.workflow.domain.vo.FlowHisTaskVo;
import org.dromara.workflow.domain.vo.FlowTaskVo;
import java.util.List;
import java.util.Map;
/**
 * ä»»åŠ¡ æœåС层
 *
 * @author may
 */
public interface IFlwTaskService {
    /**
     * å¯åŠ¨ä»»åŠ¡
     *
     * @param startProcessBo å¯åŠ¨æµç¨‹å‚æ•°
     * @return ç»“æžœ
     */
    Map<String, Object> startWorkFlow(StartProcessBo startProcessBo);
    /**
     * åŠžç†ä»»åŠ¡
     *
     * @param completeTaskBo åŠžç†ä»»åŠ¡å‚æ•°
     * @return ç»“æžœ
     */
    boolean completeTask(CompleteTaskBo completeTaskBo);
    /**
     * æŸ¥è¯¢å½“前用户的待办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     * @return ç»“æžœ
     */
    TableDataInfo<FlowTaskVo> pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢å½“前租户所有待办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     * @return ç»“æžœ
     */
    TableDataInfo<FlowHisTaskVo> pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢å¾…办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     * @return ç»“æžœ
     */
    TableDataInfo<FlowTaskVo> pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢å·²åŠžä»»åŠ¡
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     * @return ç»“æžœ
     */
    TableDataInfo<FlowHisTaskVo> pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery);
    /**
     * æŸ¥è¯¢å½“前用户的抄送
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     * @return ç»“æžœ
     */
    TableDataInfo<FlowTaskVo> pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery);
    /**
     * ä¿®æ”¹ä»»åŠ¡åŠžç†äºº
     *
     * @param taskIdList ä»»åŠ¡id
     * @param userId     ç”¨æˆ·id
     * @return ç»“æžœ
     */
    boolean updateAssignee(List<Long> taskIdList, String userId);
    /**
     * é©³å›žå®¡æ‰¹
     *
     * @param bo å‚æ•°
     * @return ç»“æžœ
     */
    boolean backProcess(BackProcessBo bo);
    /**
     * èŽ·å–å¯é©³å›žçš„å‰ç½®èŠ‚ç‚¹
     *
     * @param definitionId æµç¨‹å®šä¹‰id
     * @param nowNodeCode  å½“前节点
     * @return ç»“æžœ
     */
    List<Node> getBackTaskNode(Long definitionId, String nowNodeCode);
    /**
     * ç»ˆæ­¢ä»»åŠ¡
     *
     * @param bo å‚æ•°
     * @return ç»“æžœ
     */
    boolean terminationTask(FlowTerminationBo bo);
    /**
     * æŒ‰ç…§ä»»åŠ¡id查询任务
     *
     * @param taskIdList ä»»åŠ¡id
     * @return ç»“æžœ
     */
    List<FlowTask> selectByIdList(List<Long> taskIdList);
    /**
     * æŒ‰ç…§ä»»åŠ¡id查询任务
     *
     * @param taskId ä»»åŠ¡id
     * @return ç»“æžœ
     */
    FlowTaskVo selectById(Long taskId);
    /**
     * æŒ‰ç…§ä»»åŠ¡id查询任务
     *
     * @param taskIdList ä»»åŠ¡id
     * @return ç»“æžœ
     */
    List<FlowHisTask> selectHisTaskByIdList(List<Long> taskIdList);
    /**
     * æŒ‰ç…§ä»»åŠ¡id查询任务
     *
     * @param taskId ä»»åŠ¡id
     * @return ç»“æžœ
     */
    FlowHisTask selectHisTaskById(Long taskId);
    /**
     * æŒ‰ç…§å®žä¾‹id查询任务
     *
     * @param instanceIdList æµç¨‹å®žä¾‹id
     * @return ç»“æžœ
     */
    List<FlowTask> selectByInstIdList(List<Long> instanceIdList);
    /**
     * æŒ‰ç…§å®žä¾‹id查询任务
     *
     * @param instanceId æµç¨‹å®žä¾‹id
     * @return ç»“æžœ
     */
    List<FlowTask> selectByInstId(Long instanceId);
    /**
     * ä»»åŠ¡æ“ä½œ
     *
     * @param bo            å‚æ•°
     * @param taskOperation æ“ä½œç±»åž‹ï¼Œå§”æ´¾ delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature
     * @return ç»“æžœ
     */
    boolean taskOperation(TaskOperationBo bo, String taskOperation);
    /**
     * èŽ·å–ä»»åŠ¡æ‰€æœ‰åŠžç†äºº
     *
     * @param taskIdList ä»»åŠ¡id
     * @return ç»“æžœ
     */
    Map<Long, List<UserDTO>> currentTaskAllUser(List<Long> taskIdList);
    /**
     * èŽ·å–å½“å‰ä»»åŠ¡çš„æ‰€æœ‰åŠžç†äºº
     *
     * @param taskId ä»»åŠ¡id
     * @return ç»“æžœ
     */
    List<UserDTO> currentTaskAllUser(Long taskId);
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java
@@ -5,7 +5,6 @@
import org.dromara.workflow.domain.bo.TestLeaveBo;
import org.dromara.workflow.domain.vo.TestLeaveVo;
import java.util.Collection;
import java.util.List;
/**
@@ -44,5 +43,5 @@
    /**
     * æ ¡éªŒå¹¶æ‰¹é‡åˆ é™¤è¯·å‡ä¿¡æ¯
     */
    Boolean deleteWithValidByIds(Collection<Long> ids);
    Boolean deleteWithValidByIds(List<Long> ids);
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package org.dromara.workflow.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.translation.annotation.TranslationType;
import org.dromara.common.translation.core.TranslationInterface;
import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.service.IFlwCategoryService;
import org.springframework.stereotype.Service;
/**
 * æµç¨‹åˆ†ç±»åç§°ç¿»è¯‘实现
 *
 * @author AprilWind
 */
@Slf4j
@RequiredArgsConstructor
@Service
@TranslationType(type = FlowConstant.CATEGORY_ID_TO_NAME)
public class CategoryNameTranslationImpl implements TranslationInterface<String> {
    private final IFlwCategoryService flwCategoryService;
    @Override
    public String translation(Object key, String other) {
        if (key instanceof String categoryId) {
            return flwCategoryService.selectCategoryNameById(categoryId);
        }
        return null;
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,267 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.*;
import org.dromara.common.mybatis.helper.DataBaseHelper;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.warm.flow.core.service.DefService;
import org.dromara.warm.flow.orm.entity.FlowDefinition;
import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.domain.FlowCategory;
import org.dromara.workflow.domain.bo.FlowCategoryBo;
import org.dromara.workflow.domain.vo.FlowCategoryVo;
import org.dromara.workflow.mapper.FlwCategoryMapper;
import org.dromara.workflow.service.IFlwCategoryService;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
 * æµç¨‹åˆ†ç±»Service业务层处理
 *
 * @author may
 */
@RequiredArgsConstructor
@Service
public class FlwCategoryServiceImpl implements IFlwCategoryService {
    private final FlwCategoryMapper baseMapper;
    private final DefService defService;
    /**
     * æŸ¥è¯¢æµç¨‹åˆ†ç±»
     *
     * @param categoryId ä¸»é”®
     * @return æµç¨‹åˆ†ç±»
     */
    @Override
    public FlowCategoryVo queryById(Long categoryId) {
        FlowCategoryVo category = baseMapper.selectVoById(categoryId);
        if (ObjectUtil.isNull(category)) {
            return null;
        }
        FlowCategoryVo parentCategory = baseMapper.selectVoOne(new LambdaQueryWrapper<FlowCategory>()
            .select(FlowCategory::getCategoryName).eq(FlowCategory::getCategoryId, category.getParentId()));
        category.setParentName(ObjectUtils.notNullGetter(parentCategory, FlowCategoryVo::getCategoryName));
        return category;
    }
    /**
     * æ ¹æ®æµç¨‹åˆ†ç±»ID查询流程分类名称
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     * @return æµç¨‹åˆ†ç±»åç§°
     */
    @Cacheable(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#categoryId")
    @Override
    public String selectCategoryNameById(String categoryId) {
        if (StringUtils.isBlank(categoryId)) {
            return null;
        }
        FlowCategory category = baseMapper.selectOne(new LambdaQueryWrapper<FlowCategory>()
            .select(FlowCategory::getCategoryName).eq(FlowCategory::getCategoryId, categoryId));
        return ObjectUtils.notNullGetter(category, FlowCategory::getCategoryName);
    }
    /**
     * æŸ¥è¯¢ç¬¦åˆæ¡ä»¶çš„æµç¨‹åˆ†ç±»åˆ—表
     *
     * @param bo æŸ¥è¯¢æ¡ä»¶
     * @return æµç¨‹åˆ†ç±»åˆ—表
     */
    @Override
    public List<FlowCategoryVo> queryList(FlowCategoryBo bo) {
        LambdaQueryWrapper<FlowCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }
    /**
     * æŸ¥è¯¢æµç¨‹åˆ†ç±»æ ‘结构信息
     *
     * @param category æµç¨‹åˆ†ç±»ä¿¡æ¯
     * @return æµç¨‹åˆ†ç±»æ ‘信息集合
     */
    @Override
    public List<Tree<Long>> selectCategoryTreeList(FlowCategoryBo category) {
        LambdaQueryWrapper<FlowCategory> lqw = buildQueryWrapper(category);
        List<FlowCategoryVo> categorys = baseMapper.selectVoList(lqw);
        if (CollUtil.isEmpty(categorys)) {
            return CollUtil.newArrayList();
        }
        // èŽ·å–å½“å‰åˆ—è¡¨ä¸­æ¯ä¸€ä¸ªèŠ‚ç‚¹çš„parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点
        List<Tree<Long>> treeList = CollUtil.newArrayList();
        for (FlowCategoryVo d : categorys) {
            Long parentId = d.getParentId();
            FlowCategoryVo categoryVo = StreamUtils.findFirst(categorys, it -> it.getCategoryId().longValue() == parentId);
            if (ObjectUtil.isNull(categoryVo)) {
                List<Tree<Long>> trees = TreeBuildUtils.build(categorys, parentId, (dept, tree) ->
                    tree.setId(dept.getCategoryId())
                        .setParentId(dept.getParentId())
                        .setName(dept.getCategoryName())
                        .setWeight(dept.getOrderNum()));
                Tree<Long> tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getCategoryId());
                treeList.add(tree);
            }
        }
        return treeList;
    }
    /**
     * æ ¡éªŒæµç¨‹åˆ†ç±»æ˜¯å¦æœ‰æ•°æ®æƒé™
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     */
    @Override
    public void checkCategoryDataScope(Long categoryId) {
        if (ObjectUtil.isNull(categoryId)) {
            return;
        }
        if (LoginHelper.isSuperAdmin()) {
            return;
        }
        if (baseMapper.countCategoryById(categoryId) == 0) {
            throw new ServiceException("没有权限访问流程分类数据!");
        }
    }
    /**
     * æ ¡éªŒæµç¨‹åˆ†ç±»åç§°æ˜¯å¦å”¯ä¸€
     *
     * @param category æµç¨‹åˆ†ç±»ä¿¡æ¯
     * @return ç»“æžœ
     */
    @Override
    public boolean checkCategoryNameUnique(FlowCategoryBo category) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<FlowCategory>()
            .eq(FlowCategory::getCategoryName, category.getCategoryName())
            .eq(FlowCategory::getParentId, category.getParentId())
            .ne(ObjectUtil.isNotNull(category.getCategoryId()), FlowCategory::getCategoryId, category.getCategoryId()));
        return !exist;
    }
    /**
     * æŸ¥è¯¢æµç¨‹åˆ†ç±»æ˜¯å¦å­˜åœ¨æµç¨‹å®šä¹‰
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     * @return ç»“æžœ true å­˜åœ¨ false ä¸å­˜åœ¨
     */
    @Override
    public boolean checkCategoryExistDefinition(Long categoryId) {
        FlowDefinition definition = new FlowDefinition();
        definition.setCategory(categoryId.toString());
        return defService.exists(definition);
    }
    /**
     * æ˜¯å¦å­˜åœ¨æµç¨‹åˆ†ç±»å­èŠ‚ç‚¹
     *
     * @param categoryId æµç¨‹åˆ†ç±»ID
     * @return ç»“æžœ
     */
    @Override
    public boolean hasChildByCategoryId(Long categoryId) {
        return baseMapper.exists(new LambdaQueryWrapper<FlowCategory>()
            .eq(FlowCategory::getParentId, categoryId));
    }
    private LambdaQueryWrapper<FlowCategory> buildQueryWrapper(FlowCategoryBo bo) {
        LambdaQueryWrapper<FlowCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(FlowCategory::getDelFlag, SystemConstants.NORMAL);
        lqw.eq(ObjectUtil.isNotNull(bo.getCategoryId()), FlowCategory::getCategoryId, bo.getCategoryId());
        lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), FlowCategory::getParentId, bo.getParentId());
        lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), FlowCategory::getCategoryName, bo.getCategoryName());
        lqw.orderByAsc(FlowCategory::getAncestors);
        lqw.orderByAsc(FlowCategory::getParentId);
        lqw.orderByAsc(FlowCategory::getOrderNum);
        lqw.orderByAsc(FlowCategory::getCategoryId);
        return lqw;
    }
    /**
     * æ–°å¢žæµç¨‹åˆ†ç±»
     *
     * @param bo æµç¨‹åˆ†ç±»
     * @return æ˜¯å¦æ–°å¢žæˆåŠŸ
     */
    @Override
    public int insertByBo(FlowCategoryBo bo) {
        FlowCategory info = baseMapper.selectById(bo.getParentId());
        FlowCategory category = MapstructUtils.convert(bo, FlowCategory.class);
        category.setAncestors(info.getAncestors() + StringUtils.SEPARATOR + category.getParentId());
        return baseMapper.insert(category);
    }
    /**
     * ä¿®æ”¹æµç¨‹åˆ†ç±»
     *
     * @param bo æµç¨‹åˆ†ç±»
     * @return æ˜¯å¦ä¿®æ”¹æˆåŠŸ
     */
    @CacheEvict(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#bo.categoryId")
    @Override
    public int updateByBo(FlowCategoryBo bo) {
        FlowCategory category = MapstructUtils.convert(bo, FlowCategory.class);
        FlowCategory oldCategory = baseMapper.selectById(category.getCategoryId());
        if (ObjectUtil.isNull(oldCategory)) {
            throw new ServiceException("流程分类不存在,无法修改");
        }
        if (!oldCategory.getParentId().equals(category.getParentId())) {
            // å¦‚果是新父流程分类 åˆ™æ ¡éªŒæ˜¯å¦å…·æœ‰æ–°çˆ¶æµç¨‹åˆ†ç±»æƒé™ é¿å…è¶Šæƒ
            this.checkCategoryDataScope(category.getParentId());
            FlowCategory newParentCategory = baseMapper.selectById(category.getParentId());
            if (ObjectUtil.isNotNull(newParentCategory)) {
                String newAncestors = newParentCategory.getAncestors() + StringUtils.SEPARATOR + newParentCategory.getCategoryId();
                String oldAncestors = oldCategory.getAncestors();
                category.setAncestors(newAncestors);
                updateCategoryChildren(category.getCategoryId(), newAncestors, oldAncestors);
            }
        } else {
            category.setAncestors(oldCategory.getAncestors());
        }
        return baseMapper.updateById(category);
    }
    /**
     * ä¿®æ”¹å­å…ƒç´ å…³ç³»
     *
     * @param categoryId   è¢«ä¿®æ”¹çš„æµç¨‹åˆ†ç±»ID
     * @param newAncestors æ–°çš„父ID集合
     * @param oldAncestors æ—§çš„父ID集合
     */
    private void updateCategoryChildren(Long categoryId, String newAncestors, String oldAncestors) {
        List<FlowCategory> children = baseMapper.selectList(new LambdaQueryWrapper<FlowCategory>()
            .apply(DataBaseHelper.findInSet(categoryId, "ancestors")));
        List<FlowCategory> list = new ArrayList<>();
        for (FlowCategory child : children) {
            FlowCategory category = new FlowCategory();
            category.setCategoryId(child.getCategoryId());
            category.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
            list.add(category);
        }
        if (CollUtil.isNotEmpty(list)) {
            baseMapper.updateBatchById(list);
        }
    }
    /**
     * åˆ é™¤æµç¨‹åˆ†ç±»ä¿¡æ¯
     *
     * @param categoryId ä¸»é”®
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    @CacheEvict(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#categoryId")
    @Override
    public int deleteWithValidById(Long categoryId) {
        return baseMapper.deleteById(categoryId);
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,275 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
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.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
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.enums.NodeType;
import org.dromara.warm.flow.core.enums.PublishStatus;
import org.dromara.warm.flow.core.service.DefService;
import org.dromara.warm.flow.orm.entity.FlowDefinition;
import org.dromara.warm.flow.orm.entity.FlowHisTask;
import org.dromara.warm.flow.orm.entity.FlowNode;
import org.dromara.warm.flow.orm.entity.FlowSkip;
import org.dromara.warm.flow.orm.mapper.FlowDefinitionMapper;
import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper;
import org.dromara.warm.flow.orm.mapper.FlowNodeMapper;
import org.dromara.warm.flow.orm.mapper.FlowSkipMapper;
import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.workflow.domain.FlowCategory;
import org.dromara.workflow.domain.vo.FlowDefinitionVo;
import org.dromara.workflow.mapper.FlwCategoryMapper;
import org.dromara.workflow.service.IFlwDefinitionService;
import org.dromara.workflow.utils.WorkflowUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.dromara.common.core.constant.TenantConstants.DEFAULT_TENANT_ID;
/**
 * æµç¨‹å®šä¹‰ æœåŠ¡å±‚å®žçŽ°
 *
 * @author may
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
    private final DefService defService;
    private final FlowDefinitionMapper flowDefinitionMapper;
    private final FlowHisTaskMapper flowHisTaskMapper;
    private final FlwCategoryMapper flwCategoryMapper;
    private final FlowNodeMapper flowNodeMapper;
    private final FlowSkipMapper flowSkipMapper;
    /**
     * æŸ¥è¯¢æµç¨‹å®šä¹‰åˆ—表
     *
     * @param flowDefinition æµç¨‹å®šä¹‰ä¿¡æ¯
     * @param pageQuery      åˆ†é¡µ
     * @return è¿”回分页列表
     */
    @Override
    public TableDataInfo<FlowDefinitionVo> queryList(FlowDefinition flowDefinition, PageQuery pageQuery) {
        LambdaQueryWrapper<FlowDefinition> wrapper = buildQueryWrapper(flowDefinition);
        wrapper.eq(FlowDefinition::getIsPublish, PublishStatus.PUBLISHED.getKey());
        Page<FlowDefinition> page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper);
        TableDataInfo<FlowDefinitionVo> build = TableDataInfo.build();
        build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class));
        build.setTotal(page.getTotal());
        return build;
    }
    /**
     * æŸ¥è¯¢æœªå‘布的流程定义列表
     *
     * @param flowDefinition æµç¨‹å®šä¹‰ä¿¡æ¯
     * @param pageQuery      åˆ†é¡µ
     * @return è¿”回分页列表
     */
    @Override
    public TableDataInfo<FlowDefinitionVo> unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery) {
        LambdaQueryWrapper<FlowDefinition> wrapper = buildQueryWrapper(flowDefinition);
        wrapper.in(FlowDefinition::getIsPublish, Arrays.asList(PublishStatus.UNPUBLISHED.getKey(), PublishStatus.EXPIRED.getKey()));
        Page<FlowDefinition> page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper);
        TableDataInfo<FlowDefinitionVo> build = TableDataInfo.build();
        build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class));
        build.setTotal(page.getTotal());
        return build;
    }
    private LambdaQueryWrapper<FlowDefinition> buildQueryWrapper(FlowDefinition flowDefinition) {
        LambdaQueryWrapper<FlowDefinition> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotBlank(flowDefinition.getFlowCode()), FlowDefinition::getFlowCode, flowDefinition.getFlowCode());
        wrapper.like(StringUtils.isNotBlank(flowDefinition.getFlowName()), FlowDefinition::getFlowName, flowDefinition.getFlowName());
        if (StringUtils.isNotBlank(flowDefinition.getCategory())) {
            List<Long> categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowDefinition.getCategory()));
            wrapper.in(FlowDefinition::getCategory, categoryIds);
        }
        wrapper.orderByDesc(FlowDefinition::getCreateTime);
        return wrapper;
    }
    /**
     * å‘布流程定义
     *
     * @param id æµç¨‹å®šä¹‰id
     */
    @Override
    public boolean publish(Long id) {
        List<FlowNode> flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper<FlowNode>().eq(FlowNode::getDefinitionId, id));
        List<String> errorMsg = new ArrayList<>();
        if (CollUtil.isNotEmpty(flowNodes)) {
            for (FlowNode flowNode : flowNodes) {
                String applyNodeCode = WorkflowUtils.applyNodeCode(id);
                if (StringUtils.isBlank(flowNode.getPermissionFlag()) && !applyNodeCode.equals(flowNode.getNodeCode()) && NodeType.BETWEEN.getKey().equals(flowNode.getNodeType())) {
                    errorMsg.add(flowNode.getNodeName());
                }
            }
            if (CollUtil.isNotEmpty(errorMsg)) {
                throw new ServiceException("节点【" + StringUtils.join(errorMsg, ",") + "】未配置办理人!");
            }
        }
        return defService.publish(id);
    }
    /**
     * å¯¼å…¥æµç¨‹å®šä¹‰
     *
     * @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);
        } catch (Exception e) {
            log.error("导入流程定义错误: {}", e.getMessage(), e);
            throw new RuntimeException(e);
        }
        return true;
    }
    /**
     * å¯¼å‡ºæµç¨‹å®šä¹‰
     *
     * @param id       æµç¨‹å®šä¹‰id
     * @param response å“åº”
     * @throws IOException å¼‚常
     */
    @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);
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/x-msdownload");
        response.setHeader("Content-Disposition", "attachment;");
        writer.write(document);
        writer.close();
    }
    /**
     * åˆ é™¤æµç¨‹å®šä¹‰
     *
     * @param ids æµç¨‹å®šä¹‰id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeDef(List<Long> ids) {
        LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
        wrapper.in(FlowHisTask::getDefinitionId, ids);
        List<FlowHisTask> flowHisTasks = flowHisTaskMapper.selectList(wrapper);
        if (CollUtil.isNotEmpty(flowHisTasks)) {
            List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectByIds(StreamUtils.toList(flowHisTasks, FlowHisTask::getDefinitionId));
            if (CollUtil.isNotEmpty(flowDefinitions)) {
                String join = StreamUtils.join(flowDefinitions, FlowDefinition::getFlowCode);
                log.error("流程定义【{}】已被使用不可被删除!", join);
                throw new ServiceException("流程定义【" + join + "】已被使用不可被删除!");
            }
        }
        try {
            defService.removeDef(ids);
        } catch (Exception e) {
            log.error("Error removing flow definitions: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to remove flow definitions", e);
        }
        return true;
    }
    /**
     * æ–°å¢žç§Ÿæˆ·æµç¨‹å®šä¹‰
     *
     * @param tenantId ç§Ÿæˆ·id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncDef(String tenantId) {
        List<FlowDefinition> flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper<FlowDefinition>().eq(FlowDefinition::getTenantId, DEFAULT_TENANT_ID));
        if (CollUtil.isEmpty(flowDefinitions)) {
            return;
        }
        FlowCategory flowCategory = flwCategoryMapper.selectOne(new LambdaQueryWrapper<FlowCategory>()
            .eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID).eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID));
        flowCategory.setCategoryId(null);
        flowCategory.setTenantId(tenantId);
        flwCategoryMapper.insert(flowCategory);
        List<Long> defIds = StreamUtils.toList(flowDefinitions, FlowDefinition::getId);
        List<FlowNode> flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper<FlowNode>().in(FlowNode::getDefinitionId, defIds));
        List<FlowSkip> flowSkips = flowSkipMapper.selectList(new LambdaQueryWrapper<FlowSkip>().in(FlowSkip::getDefinitionId, defIds));
        for (FlowDefinition definition : flowDefinitions) {
            FlowDefinition flowDefinition = BeanUtil.toBean(definition, FlowDefinition.class);
            flowDefinition.setId(null);
            flowDefinition.setTenantId(tenantId);
            flowDefinition.setIsPublish(0);
            flowDefinition.setCategory(String.valueOf(flowCategory.getCategoryId()));
            int insert = flowDefinitionMapper.insert(flowDefinition);
            if (insert <= 0) {
                log.info("同步流程定义【{}】失败!", definition.getFlowCode());
                continue;
            }
            log.info("同步流程定义【{}】成功!", definition.getFlowCode());
            Long definitionId = flowDefinition.getId();
            if (CollUtil.isNotEmpty(flowNodes)) {
                List<FlowNode> nodes = StreamUtils.filter(flowNodes, node -> node.getDefinitionId().equals(definition.getId()));
                if (CollUtil.isNotEmpty(nodes)) {
                    List<FlowNode> flowNodeList = BeanUtil.copyToList(nodes, FlowNode.class);
                    flowNodeList.forEach(e -> {
                        e.setId(null);
                        e.setDefinitionId(definitionId);
                        e.setTenantId(tenantId);
                        e.setPermissionFlag(null);
                    });
                    flowNodeMapper.insertOrUpdate(flowNodeList);
                }
            }
            if (CollUtil.isNotEmpty(flowSkips)) {
                List<FlowSkip> skips = StreamUtils.filter(flowSkips, skip -> skip.getDefinitionId().equals(definition.getId()));
                if (CollUtil.isNotEmpty(skips)) {
                    List<FlowSkip> flowSkipList = BeanUtil.copyToList(skips, FlowSkip.class);
                    flowSkipList.forEach(e -> {
                        e.setId(null);
                        e.setDefinitionId(definitionId);
                        e.setTenantId(tenantId);
                    });
                    flowSkipMapper.insertOrUpdate(flowSkipList);
                }
            }
        }
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,455 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
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.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.DefService;
import org.dromara.warm.flow.core.service.InsService;
import org.dromara.warm.flow.core.service.TaskService;
import org.dromara.warm.flow.orm.entity.FlowHisTask;
import org.dromara.warm.flow.orm.entity.FlowInstance;
import org.dromara.warm.flow.orm.entity.FlowTask;
import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper;
import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.domain.bo.FlowCancelBo;
import org.dromara.workflow.domain.bo.FlowInstanceBo;
import org.dromara.workflow.domain.bo.FlowInvalidBo;
import org.dromara.workflow.domain.vo.FlowHisTaskVo;
import org.dromara.workflow.domain.vo.FlowInstanceVo;
import org.dromara.workflow.domain.vo.FlowVariableVo;
import org.dromara.workflow.handler.FlowProcessEventHandler;
import org.dromara.workflow.mapper.FlwCategoryMapper;
import org.dromara.workflow.mapper.FlwInstanceMapper;
import org.dromara.workflow.service.IFlwInstanceService;
import org.dromara.workflow.service.IFlwTaskService;
import org.dromara.workflow.utils.WorkflowUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
 * æµç¨‹å®žä¾‹ æœåŠ¡å±‚å®žçŽ°
 *
 * @author may
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class FlwInstanceServiceImpl implements IFlwInstanceService {
    private final InsService insService;
    private final DefService defService;
    private final FlowHisTaskMapper flowHisTaskMapper;
    private final FlowInstanceMapper flowInstanceMapper;
    private final FlwInstanceMapper flwInstanceMapper;
    private final TaskService taskService;
    private final IFlwTaskService flwTaskService;
    private final FlowProcessEventHandler flowProcessEventHandler;
    private final FlwCategoryMapper flwCategoryMapper;
    /**
     * åˆ†é¡µæŸ¥è¯¢æ­£åœ¨è¿è¡Œçš„æµç¨‹å®žä¾‹
     *
     * @param flowInstanceBo æµç¨‹å®žä¾‹
     * @param pageQuery      åˆ†é¡µ
     */
    @Override
    public TableDataInfo<FlowInstanceVo> selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) {
        QueryWrapper<FlowInstanceBo> queryWrapper = buildQueryWrapper(flowInstanceBo);
        queryWrapper.in("fi.flow_status", BusinessStatusEnum.runningStatus());
        Page<FlowInstanceVo> page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }
    /**
     * åˆ†é¡µæŸ¥è¯¢å·²ç»“束的流程实例
     *
     * @param flowInstanceBo æµç¨‹å®žä¾‹
     * @param pageQuery      åˆ†é¡µ
     */
    @Override
    public TableDataInfo<FlowInstanceVo> selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) {
        QueryWrapper<FlowInstanceBo> queryWrapper = buildQueryWrapper(flowInstanceBo);
        queryWrapper.in("fi.flow_status", BusinessStatusEnum.finishStatus());
        Page<FlowInstanceVo> page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }
    /**
     * æ ¹æ®ä¸šåŠ¡id查询流程实例详细信息
     *
     * @param businessId ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    @Override
    public FlowInstanceVo queryByBusinessId(Long businessId) {
        FlowInstance instance = this.selectInstByBusinessId(String.valueOf(businessId));
        FlowInstanceVo instanceVo = BeanUtil.toBean(instance, FlowInstanceVo.class);
        Definition definition = defService.getById(instanceVo.getDefinitionId());
        instanceVo.setFlowName(definition.getFlowName());
        instanceVo.setFlowCode(definition.getFlowCode());
        instanceVo.setVersion(definition.getVersion());
        instanceVo.setFormCustom(definition.getFormCustom());
        instanceVo.setFormPath(definition.getFormPath());
        instanceVo.setCategory(definition.getCategory());
        return instanceVo;
    }
    /**
     * é€šç”¨æŸ¥è¯¢æ¡ä»¶
     *
     * @param flowInstanceBo æŸ¥è¯¢æ¡ä»¶
     * @return æŸ¥è¯¢æ¡ä»¶æž„造方法
     */
    private QueryWrapper<FlowInstanceBo> buildQueryWrapper(FlowInstanceBo flowInstanceBo) {
        QueryWrapper<FlowInstanceBo> queryWrapper = Wrappers.query();
        queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getNodeName()), "fi.node_name", flowInstanceBo.getNodeName());
        queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getFlowName()), "fd.flow_name", flowInstanceBo.getFlowName());
        queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getFlowCode()), "fd.flow_code", flowInstanceBo.getFlowCode());
        if (StringUtils.isNotBlank(flowInstanceBo.getCategory())) {
            List<Long> categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowInstanceBo.getCategory()));
            queryWrapper.in("fd.category", categoryIds);
        }
        queryWrapper.eq(StringUtils.isNotBlank(flowInstanceBo.getBusinessId()), "fi.business_id", flowInstanceBo.getBusinessId());
        queryWrapper.in(CollUtil.isNotEmpty(flowInstanceBo.getCreateByIds()), "fi.create_by", flowInstanceBo.getCreateByIds());
        queryWrapper.eq("fi.del_flag", "0");
        queryWrapper.orderByDesc("fi.create_time");
        return queryWrapper;
    }
    /**
     * æ ¹æ®ä¸šåŠ¡id查询流程实例
     *
     * @param businessId ä¸šåŠ¡id
     */
    @Override
    public FlowInstance selectInstByBusinessId(String businessId) {
        return flowInstanceMapper.selectOne(new LambdaQueryWrapper<FlowInstance>().eq(FlowInstance::getBusinessId, businessId));
    }
    /**
     * æŒ‰ç…§å®žä¾‹id查询流程实例
     *
     * @param instanceId å®žä¾‹id
     */
    @Override
    public FlowInstance selectInstById(Long instanceId) {
        return flowInstanceMapper.selectById(instanceId);
    }
    /**
     * æŒ‰ç…§å®žä¾‹id查询流程实例
     *
     * @param instanceIds å®žä¾‹id
     */
    @Override
    public List<FlowInstance> selectInstListByIdList(List<Long> instanceIds) {
        return flowInstanceMapper.selectByIds(instanceIds);
    }
    /**
     * æŒ‰ç…§ä¸šåŠ¡id删除流程实例
     *
     * @param businessIds ä¸šåŠ¡id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByBusinessIds(List<Long> businessIds) {
        List<FlowInstance> flowInstances = flowInstanceMapper.selectList(new LambdaQueryWrapper<FlowInstance>().in(FlowInstance::getBusinessId, businessIds));
        if (CollUtil.isEmpty(flowInstances)) {
            log.warn("未找到对应的流程实例信息,无法执行删除操作。");
            return false;
        }
        return insService.remove(StreamUtils.toList(flowInstances, FlowInstance::getId));
    }
    /**
     * æŒ‰ç…§å®žä¾‹id删除流程实例
     *
     * @param instanceIds å®žä¾‹id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByInstanceIds(List<Long> instanceIds) {
        // èŽ·å–å®žä¾‹ä¿¡æ¯
        List<Instance> instances = insService.getByIds(instanceIds);
        if (CollUtil.isEmpty(instances)) {
            log.warn("未找到对应的流程实例信息,无法执行删除操作。");
            return false;
        }
        // èŽ·å–å®šä¹‰ä¿¡æ¯
        Map<Long, Definition> definitionMap = defService.getByIds(
            StreamUtils.toList(instances, Instance::getDefinitionId)
        ).stream().collect(Collectors.toMap(Definition::getId, definition -> definition));
        // é€ä¸€è§¦å‘删除事件
        instances.forEach(instance -> {
            Definition definition = definitionMap.get(instance.getDefinitionId());
            if (ObjectUtil.isNull(definition)) {
                log.warn("实例 ID: {} å¯¹åº”的流程定义信息未找到,跳过删除事件触发。", instance.getId());
                return;
            }
            flowProcessEventHandler.processDeleteHandler(definition.getFlowCode(), instance.getBusinessId());
        });
        // åˆ é™¤å®žä¾‹
        return insService.remove(instanceIds);
    }
    /**
     * æ’¤é”€æµç¨‹
     *
     * @param bo å‚æ•°
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelProcessApply(FlowCancelBo bo) {
        try {
            Instance instance = selectInstByBusinessId(bo.getBusinessId());
            if (instance == null) {
                throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE);
            }
            Definition definition = defService.getById(instance.getDefinitionId());
            if (definition == null) {
                throw new ServiceException(ExceptionCons.NOT_FOUNT_DEF);
            }
            String message = bo.getMessage();
            BusinessStatusEnum.checkCancelStatus(instance.getFlowStatus());
            String applyNodeCode = WorkflowUtils.applyNodeCode(definition.getId());
            //撤销
            WorkflowUtils.backTask(message, instance.getId(), applyNodeCode, BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus());
            //判断或签节点是否有多个,只保留一个
            List<Task> currentTaskList = taskService.list(FlowFactory.newTask().setInstanceId(instance.getId()));
            if (CollUtil.isNotEmpty(currentTaskList)) {
                if (currentTaskList.size() > 1) {
                    currentTaskList.remove(0);
                    WorkflowUtils.deleteRunTask(StreamUtils.toList(currentTaskList, Task::getId));
                }
            }
        } catch (Exception e) {
            log.error("撤销失败: {}", e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return true;
    }
    /**
     * èŽ·å–å½“å‰ç™»é™†äººå‘èµ·çš„æµç¨‹å®žä¾‹
     *
     * @param instanceBo æµç¨‹å®žä¾‹
     * @param pageQuery  åˆ†é¡µ
     */
    @Override
    public TableDataInfo<FlowInstanceVo> selectCurrentInstanceList(FlowInstanceBo instanceBo, PageQuery pageQuery) {
        QueryWrapper<FlowInstanceBo> queryWrapper = buildQueryWrapper(instanceBo);
        queryWrapper.eq("fi.create_by", LoginHelper.getUserIdStr());
        Page<FlowInstanceVo> page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }
    /**
     * èŽ·å–æµç¨‹å›¾,流程记录
     *
     * @param businessId ä¸šåŠ¡id
     */
    @Override
    public Map<String, Object> flowImage(String businessId) {
        Map<String, Object> map = new HashMap<>(16);
        FlowInstance flowInstance = this.selectInstByBusinessId(businessId);
        if (flowInstance == null) {
            throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE);
        }
        //运行中的任务
        List<FlowHisTaskVo> list = new ArrayList<>();
        List<FlowTask> flowTaskList = flwTaskService.selectByInstId(flowInstance.getId());
        if (CollUtil.isNotEmpty(flowTaskList)) {
            List<FlowHisTaskVo> flowHisTaskVos = BeanUtil.copyToList(flowTaskList, FlowHisTaskVo.class);
            for (FlowHisTaskVo flowHisTaskVo : flowHisTaskVos) {
                flowHisTaskVo.setFlowStatus(TaskStatusEnum.WAITING.getStatus());
                flowHisTaskVo.setUpdateTime(null);
                flowHisTaskVo.setRunDuration(null);
                List<UserDTO> allUser = flwTaskService.currentTaskAllUser(flowHisTaskVo.getId());
                if (CollUtil.isNotEmpty(allUser)) {
                    String join = StreamUtils.join(allUser, e -> String.valueOf(e.getUserId()));
                    flowHisTaskVo.setApprover(join);
                }
                if (BusinessStatusEnum.isDraftOrCancelOrBack(flowInstance.getFlowStatus())) {
                    flowHisTaskVo.setApprover(LoginHelper.getUserIdStr());
                    flowHisTaskVo.setApproveName(LoginHelper.getLoginUser().getNickname());
                }
            }
            list.addAll(flowHisTaskVos);
        }
        //历史任务
        LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FlowHisTask::getInstanceId, flowInstance.getId());
        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;
    }
    /**
     * æŒ‰ç…§å®žä¾‹id更新状态
     *
     * @param instanceId å®žä¾‹id
     * @param status     çŠ¶æ€
     */
    @Override
    public void updateStatus(Long instanceId, String status) {
        LambdaUpdateWrapper<FlowInstance> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(FlowInstance::getFlowStatus, status);
        wrapper.eq(FlowInstance::getId, instanceId);
        flowInstanceMapper.update(wrapper);
    }
    /**
     * èŽ·å–æµç¨‹å˜é‡
     *
     * @param instanceId å®žä¾‹id
     */
    @Override
    public Map<String, Object> instanceVariable(String instanceId) {
        Map<String, Object> map = new HashMap<>();
        FlowInstance flowInstance = flowInstanceMapper.selectById(instanceId);
        Map<String, Object> variableMap = flowInstance.getVariableMap();
        List<FlowVariableVo> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(variableMap)) {
            for (Map.Entry<String, Object> entry : variableMap.entrySet()) {
                FlowVariableVo flowVariableVo = new FlowVariableVo();
                flowVariableVo.setKey(entry.getKey());
                flowVariableVo.setValue(entry.getValue().toString());
                list.add(flowVariableVo);
            }
        }
        map.put("variableList", list);
        map.put("variable", flowInstance.getVariable());
        return map;
    }
    /**
     * è®¾ç½®æµç¨‹å˜é‡
     *
     * @param instanceId å®žä¾‹id
     * @param variable   æµç¨‹å˜é‡
     */
    @Override
    public void setVariable(Long instanceId, Map<String, Object> variable) {
        Instance instance = insService.getById(instanceId);
        if (instance != null) {
            taskService.mergeVariable(instance, variable);
        }
    }
    /**
     * æŒ‰ä»»åŠ¡id查询实例
     *
     * @param taskId ä»»åŠ¡id
     */
    @Override
    public FlowInstance selectByTaskId(Long taskId) {
        Task task = taskService.getById(taskId);
        if (task == null) {
            FlowHisTask flowHisTask = flwTaskService.selectHisTaskById(taskId);
            if (flowHisTask != null) {
                return this.selectInstById(flowHisTask.getInstanceId());
            }
        } else {
            return this.selectInstById(task.getInstanceId());
        }
        return null;
    }
    /**
     * æŒ‰ä»»åŠ¡id查询实例
     *
     * @param taskIdList ä»»åŠ¡id
     */
    @Override
    public List<FlowInstance> selectByTaskIdList(List<Long> taskIdList) {
        if (CollUtil.isEmpty(taskIdList)) {
            return Collections.emptyList();
        }
        Set<Long> instanceIds = new HashSet<>();
        List<FlowTask> flowTaskList = flwTaskService.selectByIdList(taskIdList);
        for (FlowTask flowTask : flowTaskList) {
            instanceIds.add(flowTask.getInstanceId());
        }
        List<FlowHisTask> flowHisTaskList = flwTaskService.selectHisTaskByIdList(taskIdList);
        for (FlowHisTask flowHisTask : flowHisTaskList) {
            instanceIds.add(flowHisTask.getInstanceId());
        }
        if (!instanceIds.isEmpty()) {
            return this.selectInstListByIdList(new ArrayList<>(instanceIds));
        }
        return Collections.emptyList();
    }
    /**
     * ä½œåºŸæµç¨‹
     *
     * @param bo å‚æ•°
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean processInvalid(FlowInvalidBo bo) {
        try {
            Instance instance = insService.getById(bo.getId());
            if (instance != null) {
                BusinessStatusEnum.checkInvalidStatus(instance.getFlowStatus());
            }
            List<FlowTask> flowTaskList = flwTaskService.selectByInstId(bo.getId());
            for (FlowTask flowTask : flowTaskList) {
                FlowParams flowParams = new FlowParams();
                flowParams.message(bo.getComment());
                flowParams.flowStatus(BusinessStatusEnum.INVALID.getStatus())
                    .hisStatus(TaskStatusEnum.INVALID.getStatus());
                flowParams.ignore(true);
                taskService.termination(flowTask.getId(), flowParams);
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,158 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.dto.DeptDTO;
import org.dromara.common.core.domain.dto.TaskAssigneeDTO;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.domain.model.TaskAssigneeBody;
import org.dromara.common.core.enums.FormatsType;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.DeptService;
import org.dromara.common.core.service.TaskAssigneeService;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.warm.flow.ui.dto.HandlerFunDto;
import org.dromara.warm.flow.ui.dto.HandlerQuery;
import org.dromara.warm.flow.ui.dto.TreeFunDto;
import org.dromara.warm.flow.ui.service.HandlerSelectService;
import org.dromara.warm.flow.ui.vo.HandlerSelectVo;
import org.dromara.workflow.common.enums.TaskAssigneeEnum;
import org.dromara.workflow.service.IFlwTaskAssigneeService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
 * æµç¨‹è®¾è®¡å™¨-获取办理人权限设置列表
 *
 * @author AprilWind
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, HandlerSelectService {
    private static final String DEFAULT_GROUP_NAME = "默认分组";
    private final TaskAssigneeService taskAssigneeService;
    private final UserService userService;
    private final DeptService deptService;
    /**
     * èŽ·å–åŠžç†äººæƒé™è®¾ç½®åˆ—è¡¨tabs页签
     *
     * @return tabs页签
     */
    @Override
    public List<String> getHandlerType() {
        return TaskAssigneeEnum.getAssigneeTypeList();
    }
    /**
     * èŽ·å–åŠžç†åˆ—è¡¨, åŒæ—¶æž„建左侧部门树状结构
     *
     * @param query æŸ¥è¯¢æ¡ä»¶
     * @return HandlerSelectVo
     */
    @Override
    public HandlerSelectVo getHandlerSelect(HandlerQuery query) {
        // èŽ·å–ä»»åŠ¡åŠžç†ç±»åž‹
        TaskAssigneeEnum type = TaskAssigneeEnum.fromDesc(query.getHandlerType());
        // è½¬æ¢æŸ¥è¯¢æ¡ä»¶ä¸º TaskAssigneeBody
        TaskAssigneeBody taskQuery = BeanUtil.toBean(query, TaskAssigneeBody.class);
        // ç»Ÿä¸€æŸ¥è¯¢å¹¶æž„建业务数据
        TaskAssigneeDTO dto = fetchTaskAssigneeData(type, taskQuery);
        List<DeptDTO> depts = fetchDeptData(type);
        return getHandlerSelectVo(buildHandlerData(dto, type), buildDeptTree(depts));
    }
    /**
     * æ ¹æ®ä»»åŠ¡åŠžç†ç±»åž‹æŸ¥è¯¢å¯¹åº”çš„æ•°æ®
     */
    private TaskAssigneeDTO fetchTaskAssigneeData(TaskAssigneeEnum type, TaskAssigneeBody taskQuery) {
        return switch (type) {
            case USER -> taskAssigneeService.selectUsersByTaskAssigneeList(taskQuery);
            case ROLE -> taskAssigneeService.selectRolesByTaskAssigneeList(taskQuery);
            case DEPT -> taskAssigneeService.selectDeptsByTaskAssigneeList(taskQuery);
            case POST -> taskAssigneeService.selectPostsByTaskAssigneeList(taskQuery);
            default -> throw new ServiceException("Unsupported handler type");
        };
    }
    /**
     * æ ¹æ®ä»»åŠ¡åŠžç†ç±»åž‹èŽ·å–éƒ¨é—¨æ•°æ®
     */
    private List<DeptDTO> fetchDeptData(TaskAssigneeEnum type) {
        if (type == TaskAssigneeEnum.USER || type == TaskAssigneeEnum.DEPT || type == TaskAssigneeEnum.POST) {
            return deptService.selectDeptsByList();
        }
        return new ArrayList<>();
    }
    /**
     * æž„建部门树状结构
     */
    private TreeFunDto<DeptDTO> buildDeptTree(List<DeptDTO> depts) {
        return new TreeFunDto<>(depts)
            .setId(dept -> String.valueOf(dept.getDeptId()))
            .setName(DeptDTO::getDeptName)
            .setParentId(dept -> String.valueOf(dept.getParentId()));
    }
    /**
     * æž„建任务办理人数据
     */
    private HandlerFunDto<TaskAssigneeDTO.TaskHandler> buildHandlerData(TaskAssigneeDTO dto, TaskAssigneeEnum type) {
        return new HandlerFunDto<>(dto.getList(), dto.getTotal())
            .setStorageId(assignee -> type.getCode() + assignee.getStorageId())
            .setHandlerCode(assignee -> StringUtils.blankToDefault(assignee.getHandlerCode(), "无"))
            .setHandlerName(assignee -> StringUtils.blankToDefault(assignee.getHandlerName(), "无"))
            .setGroupName(assignee -> StringUtils.defaultIfBlank(
                Optional.ofNullable(assignee.getGroupName())
                    .map(deptService::selectDeptNameByIds)
                    .orElse(DEFAULT_GROUP_NAME), DEFAULT_GROUP_NAME))
            .setCreateTime(assignee -> DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, assignee.getCreateTime()));
    }
    /**
     * æ ¹æ®å­˜å‚¨æ ‡è¯†ç¬¦ï¼ˆstorageId)解析分配类型和ID,并获取对应的用户列表
     *
     * @param storageId åŒ…含分配类型和ID的字符串(例如 "user:123" æˆ– "role:456")
     * @return ä¸Žåˆ†é…ç±»åž‹å’ŒID匹配的用户列表,如果格式无效则返回空列表
     */
    @Override
    public List<UserDTO> fetchUsersByStorageId(String storageId) {
        String[] parts = storageId.split(StrUtil.COLON, 2);
        if (parts.length < 2) {
            return getUsersByType(TaskAssigneeEnum.USER, List.of(Long.valueOf(parts[0])));
        }
        return getUsersByType(TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON), List.of(Long.valueOf(parts[1])));
    }
    /**
     * æ ¹æ®æŒ‡å®šçš„任务分配类型(TaskAssigneeEnum)和 ID åˆ—表,获取对应的用户信息列表
     *
     * @param type ä»»åŠ¡åˆ†é…ç±»åž‹ï¼Œè¡¨ç¤ºç”¨æˆ·ã€è§’è‰²ã€éƒ¨é—¨æˆ–å…¶ä»–ï¼ˆTaskAssigneeEnum æžšä¸¾å€¼ï¼‰
     * @param ids  ä¸ŽæŒ‡å®šåˆ†é…ç±»åž‹å…³è”çš„ ID åˆ—表(例如用户ID、角色ID、部门ID等)
     * @return è¿”回包含用户信息的列表。如果类型为用户(USER),则通过用户ID列表查询;
     * å¦‚果类型为角色(ROLE),则通过角色ID列表查询;
     * å¦‚果类型为部门(DEPT),则通过部门ID列表查询;
     * å¦‚果类型为岗位(POST)或无法识别的类型,则返回空列表
     */
    private List<UserDTO> getUsersByType(TaskAssigneeEnum type, List<Long> ids) {
        return switch (type) {
            case USER -> userService.selectListByIds(ids);
            case ROLE -> userService.selectUsersByRoleIds(ids);
            case DEPT -> userService.selectUsersByDeptIds(ids);
            case POST -> userService.selectUsersByPostIds(ids);
        };
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,669 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
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.dto.FlowParams;
import org.dromara.warm.flow.core.entity.*;
import org.dromara.warm.flow.core.enums.NodeType;
import org.dromara.warm.flow.core.enums.SkipType;
import org.dromara.warm.flow.core.service.*;
import org.dromara.warm.flow.orm.entity.*;
import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper;
import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper;
import org.dromara.warm.flow.orm.mapper.FlowNodeMapper;
import org.dromara.warm.flow.orm.mapper.FlowTaskMapper;
import org.dromara.workflow.common.enums.TaskAssigneeType;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.domain.bo.*;
import org.dromara.workflow.domain.vo.FlowHisTaskVo;
import org.dromara.workflow.domain.vo.FlowTaskVo;
import org.dromara.workflow.handler.FlowProcessEventHandler;
import org.dromara.workflow.handler.WorkflowPermissionHandler;
import org.dromara.workflow.mapper.FlwCategoryMapper;
import org.dromara.workflow.mapper.FlwTaskMapper;
import org.dromara.workflow.service.IFlwTaskService;
import org.dromara.workflow.utils.WorkflowUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import static org.dromara.workflow.common.constant.FlowConstant.*;
/**
 * ä»»åŠ¡ æœåŠ¡å±‚å®žçŽ°
 *
 * @author may
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class FlwTaskServiceImpl implements IFlwTaskService {
    private final TaskService taskService;
    private final InsService insService;
    private final FlowInstanceMapper flowInstanceMapper;
    private final FlwTaskMapper flwTaskMapper;
    private final UserService userService;
    private final FlowTaskMapper flowTaskMapper;
    private final FlowHisTaskMapper flowHisTaskMapper;
    private final FlowProcessEventHandler flowProcessEventHandler;
    private final DefService defService;
    private final HisTaskService hisTaskService;
    private final IdentifierGenerator identifierGenerator;
    private final NodeService nodeService;
    private final FlowNodeMapper flowNodeMapper;
    private final FlwCategoryMapper flwCategoryMapper;
    /**
     * å¯åŠ¨ä»»åŠ¡
     *
     * @param startProcessBo å¯åŠ¨æµç¨‹å‚æ•°
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> startWorkFlow(StartProcessBo startProcessBo) {
        String businessId = startProcessBo.getBusinessId();
        if (StringUtils.isBlank(businessId)) {
            throw new ServiceException("启动工作流时必须包含业务ID");
        }
        // å¯åŠ¨æµç¨‹å®žä¾‹ï¼ˆæäº¤ç”³è¯·ï¼‰
        Map<String, Object> variables = startProcessBo.getVariables();
        // æµç¨‹å‘起人
        variables.put(INITIATOR, LoginHelper.getUserIdStr());
        // ä¸šåŠ¡id
        variables.put(BUSINESS_ID, businessId);
        FlowInstance flowInstance = flowInstanceMapper.selectOne(new LambdaQueryWrapper<>(FlowInstance.class)
            .eq(FlowInstance::getBusinessId, businessId));
        if (ObjectUtil.isNotNull(flowInstance)) {
            BusinessStatusEnum.checkStartStatus(flowInstance.getFlowStatus());
            List<Task> taskList = taskService.list(new FlowTask().setInstanceId(flowInstance.getId()));
            return Map.of(PROCESS_INSTANCE_ID, taskList.get(0).getInstanceId(), TASK_ID, taskList.get(0).getId());
        }
        FlowParams flowParams = new FlowParams();
        flowParams.flowCode(startProcessBo.getFlowCode());
        flowParams.variable(startProcessBo.getVariables());
        flowParams.flowStatus(BusinessStatusEnum.DRAFT.getStatus());
        Instance instance;
        try {
            instance = insService.start(businessId, flowParams);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        // ç”³è¯·äººæ‰§è¡Œæµç¨‹
        List<Task> taskList = taskService.list(new FlowTask().setInstanceId(instance.getId()));
        if (taskList.size() > 1) {
            throw new ServiceException("请检查流程第一个环节是否为申请人!");
        }
        return Map.of(PROCESS_INSTANCE_ID, instance.getId(), TASK_ID, taskList.get(0).getId());
    }
    /**
     * åŠžç†ä»»åŠ¡
     *
     * @param completeTaskBo åŠžç†ä»»åŠ¡å‚æ•°
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeTask(CompleteTaskBo completeTaskBo) {
        try {
            // èŽ·å–ä»»åŠ¡ID并查询对应的流程任务和实例信息
            Long taskId = completeTaskBo.getTaskId();
            List<String> messageType = completeTaskBo.getMessageType();
            String notice = completeTaskBo.getNotice();
            // èŽ·å–æŠ„é€äºº
            List<FlowCopyBo> flowCopyList = completeTaskBo.getFlowCopyList();
            FlowTask flowTask = flowTaskMapper.selectById(taskId);
            Instance ins = insService.getById(flowTask.getInstanceId());
            // èŽ·å–æµç¨‹å®šä¹‰ä¿¡æ¯
            Definition definition = defService.getById(flowTask.getDefinitionId());
            // æ£€æŸ¥æµç¨‹çŠ¶æ€æ˜¯å¦ä¸ºè‰ç¨¿ã€å·²æ’¤é”€æˆ–å·²é€€å›žçŠ¶æ€ï¼Œè‹¥æ˜¯åˆ™æ‰§è¡Œæµç¨‹æäº¤ç›‘å¬
            if (BusinessStatusEnum.isDraftOrCancelOrBack(ins.getFlowStatus())) {
                flowProcessEventHandler.processHandler(definition.getFlowCode(), ins.getBusinessId(), ins.getFlowStatus(), true);
            }
            // æž„建流程参数,包括变量、跳转类型、消息、处理人、权限等信息
            FlowParams flowParams = new FlowParams();
            flowParams.variable(completeTaskBo.getVariables());
            flowParams.skipType(SkipType.PASS.getKey());
            flowParams.message(completeTaskBo.getMessage());
            flowParams.flowStatus(BusinessStatusEnum.WAITING.getStatus()).hisStatus(TaskStatusEnum.PASS.getStatus());
            flowParams.hisTaskExt(completeTaskBo.getFileId());
            // æ‰§è¡Œä»»åŠ¡è·³è½¬ï¼Œå¹¶æ ¹æ®è¿”å›žçš„å¤„ç†äººè®¾ç½®ä¸‹ä¸€æ­¥å¤„ç†äºº
            Instance instance = taskService.skip(taskId, flowParams);
            this.setHandler(instance, flowTask, flowCopyList);
            // æ¶ˆæ¯é€šçŸ¥
            WorkflowUtils.sendMessage(definition.getFlowName(), ins.getId(), messageType, notice);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
    /**
     * è®¾ç½®åŠžç†äºº
     *
     * @param instance     å®žä¾‹
     * @param task         (当前任务)未办理的任务
     * @param flowCopyList æŠ„送人
     */
    private void setHandler(Instance instance, FlowTask task, List<FlowCopyBo> flowCopyList) {
        if (ObjectUtil.isNull(instance)) {
            return;
        }
        // æ·»åŠ æŠ„é€äºº
        this.setCopy(task, flowCopyList);
        // æ ¹æ®æµç¨‹å®žä¾‹ID查询所有关联的任务
        List<FlowTask> flowTasks = this.selectByInstId(instance.getId());
        List<User> userList = new ArrayList<>();
        // éåŽ†ä»»åŠ¡åˆ—è¡¨ï¼Œå¤„ç†æ¯ä¸ªä»»åŠ¡çš„åŠžç†äºº
        for (FlowTask flowTask : flowTasks) {
            // èŽ·å–ä¸Žå½“å‰ä»»åŠ¡å…³è”çš„ç”¨æˆ·åˆ—è¡¨
            List<User> associatedUsers = WorkflowUtils.getFlowUserService().getByAssociateds(Collections.singletonList(flowTask.getId()));
            if (CollUtil.isNotEmpty(associatedUsers)) {
                userList.addAll(WorkflowUtils.buildUser(associatedUsers, flowTask.getId()));
            }
        }
        // æ‰¹é‡åˆ é™¤çŽ°æœ‰ä»»åŠ¡çš„åŠžç†äººè®°å½•
        if (CollUtil.isNotEmpty(flowTasks)) {
            WorkflowUtils.getFlowUserService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId));
        }
        // ç¡®ä¿è¦ä¿å­˜çš„ userList ä¸ä¸ºç©º
        if (CollUtil.isNotEmpty(userList)) {
            WorkflowUtils.getFlowUserService().saveBatch(userList);
        }
    }
    /**
     * æ·»åŠ æŠ„é€äºº
     *
     * @param task         ä»»åŠ¡ä¿¡æ¯
     * @param flowCopyList æŠ„送人
     */
    public void setCopy(FlowTask task, List<FlowCopyBo> flowCopyList) {
        if (CollUtil.isEmpty(flowCopyList)) {
            return;
        }
        // æ·»åŠ æŠ„é€äººè®°å½•
        FlowHisTask flowHisTask = flowHisTaskMapper.selectList(new LambdaQueryWrapper<>(FlowHisTask.class).eq(FlowHisTask::getTaskId, task.getId())).get(0);
        FlowNode flowNode = new FlowNode();
        flowNode.setNodeCode(flowHisTask.getTargetNodeCode());
        flowNode.setNodeName(flowHisTask.getTargetNodeName());
        //生成新的任务id
        long taskId = identifierGenerator.nextId(null).longValue();
        task.setId(taskId);
        task.setNodeName("【抄送】" + task.getNodeName());
        Date updateTime = new Date(flowHisTask.getUpdateTime().getTime() - 1000);
        FlowParams flowParams = FlowParams.build();
        flowParams.skipType(SkipType.NONE.getKey());
        flowParams.hisStatus(TaskStatusEnum.COPY.getStatus());
        flowParams.message("【抄送给】" + StreamUtils.join(flowCopyList, FlowCopyBo::getUserName));
        HisTask hisTask = hisTaskService.setSkipHisTask(task, flowNode, flowParams);
        hisTask.setCreateTime(updateTime);
        hisTask.setUpdateTime(updateTime);
        hisTaskService.save(hisTask);
        List<User> userList = flowCopyList.stream()
            .map(flowCopy -> {
                FlowUser flowUser = new FlowUser();
                flowUser.setType(TaskAssigneeType.COPY.getCode());
                flowUser.setProcessedBy(String.valueOf(flowCopy.getUserId()));
                flowUser.setAssociated(taskId);
                return flowUser;
            }).collect(Collectors.toList());
        // æ‰¹é‡ä¿å­˜æŠ„送人员
        WorkflowUtils.getFlowUserService().saveBatch(userList);
    }
    /**
     * æŸ¥è¯¢å½“前用户的待办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @Override
    public TableDataInfo<FlowTaskVo> pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo);
        queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey());
        queryWrapper.in("t.processed_by", SpringUtils.getBean(WorkflowPermissionHandler.class).permissions());
        queryWrapper.in("t.flow_status", BusinessStatusEnum.WAITING.getStatus());
        Page<FlowTaskVo> page = this.getFlowTaskVoPage(pageQuery, queryWrapper);
        return TableDataInfo.build(page);
    }
    /**
     * æŸ¥è¯¢å½“前用户的已办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @Override
    public TableDataInfo<FlowHisTaskVo> pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo);
        queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey());
        queryWrapper.in("t.approver", LoginHelper.getUserIdStr());
        queryWrapper.orderByDesc("t.create_time").orderByDesc("t.update_time");
        Page<FlowHisTaskVo> page = flwTaskMapper.getListFinishTask(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }
    /**
     * æŸ¥è¯¢å¾…办任务
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @Override
    public TableDataInfo<FlowTaskVo> pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo);
        queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey());
        Page<FlowTaskVo> page = getFlowTaskVoPage(pageQuery, queryWrapper);
        return TableDataInfo.build(page);
    }
    private Page<FlowTaskVo> getFlowTaskVoPage(PageQuery pageQuery, QueryWrapper<FlowTaskBo> queryWrapper) {
        Page<FlowTaskVo> page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper);
        List<FlowTaskVo> records = page.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Long> taskIds = StreamUtils.toList(records, FlowTaskVo::getId);
            Map<Long, List<UserDTO>> listMap = currentTaskAllUser(taskIds);
            records.forEach(t -> {
                List<UserDTO> userList = listMap.getOrDefault(t.getId(), Collections.emptyList());
                if (CollUtil.isNotEmpty(userList)) {
                    t.setAssigneeIds(StreamUtils.join(userList, e -> String.valueOf(e.getUserId())));
                    t.setAssigneeNames(StreamUtils.join(userList, UserDTO::getNickName));
                }
            });
        }
        return page;
    }
    /**
     * æŸ¥è¯¢å·²åŠžä»»åŠ¡
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @Override
    public TableDataInfo<FlowHisTaskVo> pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo);
        Page<FlowHisTaskVo> page = flwTaskMapper.getListFinishTask(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }
    /**
     * æŸ¥è¯¢å½“前用户的抄送
     *
     * @param flowTaskBo å‚æ•°
     * @param pageQuery  åˆ†é¡µ
     */
    @Override
    public TableDataInfo<FlowTaskVo> pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery) {
        QueryWrapper<FlowTaskBo> queryWrapper = buildQueryWrapper(flowTaskBo);
        queryWrapper.in("t.processed_by", LoginHelper.getUserIdStr());
        Page<FlowTaskVo> page = flwTaskMapper.getTaskCopyByPage(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(page);
    }
    private QueryWrapper<FlowTaskBo> buildQueryWrapper(FlowTaskBo flowTaskBo) {
        QueryWrapper<FlowTaskBo> wrapper = Wrappers.query();
        wrapper.like(StringUtils.isNotBlank(flowTaskBo.getNodeName()), "t.node_name", flowTaskBo.getNodeName());
        wrapper.like(StringUtils.isNotBlank(flowTaskBo.getFlowName()), "t.flow_name", flowTaskBo.getFlowName());
        wrapper.like(StringUtils.isNotBlank(flowTaskBo.getFlowCode()), "t.flow_code", flowTaskBo.getFlowCode());
        wrapper.in(CollUtil.isNotEmpty(flowTaskBo.getCreateByIds()), "t.create_by", flowTaskBo.getCreateByIds());
        if (StringUtils.isNotBlank(flowTaskBo.getCategory())) {
            List<Long> categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowTaskBo.getCategory()));
            wrapper.in("t.category", categoryIds);
        }
        wrapper.orderByDesc("t.create_time");
        return wrapper;
    }
    /**
     * é©³å›žä»»åŠ¡
     *
     * @param bo å‚æ•°
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean backProcess(BackProcessBo bo) {
        try {
            Long taskId = bo.getTaskId();
            String notice = bo.getNotice();
            List<String> messageType = bo.getMessageType();
            String message = bo.getMessage();
            FlowTask task = flowTaskMapper.selectById(taskId);
            if (ObjectUtil.isNull(task)) {
                throw new ServiceException("任务不存在!");
            }
            Instance inst = insService.getById(task.getInstanceId());
            BusinessStatusEnum.checkBackStatus(inst.getFlowStatus());
            Long definitionId = task.getDefinitionId();
            Definition definition = defService.getById(definitionId);
            String applyNodeCode = WorkflowUtils.applyNodeCode(definitionId);
            FlowParams flowParams = FlowParams.build();
            flowParams.nodeCode(bo.getNodeCode());
            flowParams.message(message);
            flowParams.skipType(SkipType.REJECT.getKey());
            flowParams.flowStatus(applyNodeCode.equals(bo.getNodeCode()) ? TaskStatusEnum.BACK.getStatus() : TaskStatusEnum.WAITING.getStatus())
                .hisStatus(TaskStatusEnum.BACK.getStatus());
            taskService.skip(task.getId(), flowParams);
            Instance instance = insService.getById(inst.getId());
            this.setHandler(instance, task, null);
            // æ¶ˆæ¯é€šçŸ¥
            WorkflowUtils.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
    /**
     * èŽ·å–å¯é©³å›žçš„å‰ç½®èŠ‚ç‚¹
     *
     * @param definitionId æµç¨‹å®šä¹‰id
     * @param nowNodeCode  å½“前节点
     */
    @Override
    public List<Node> getBackTaskNode(Long definitionId, String nowNodeCode) {
        List<Node> nodeCodes = nodeService.getByNodeCodes(Collections.singletonList(nowNodeCode), definitionId);
        if (!CollUtil.isNotEmpty(nodeCodes)) {
            return nodeCodes;
        }
        //判断是否配置了固定驳回节点
        Node node = nodeCodes.get(0);
        if (StringUtils.isNotBlank(node.getAnyNodeSkip())) {
            return nodeService.getByNodeCodes(Collections.singletonList(node.getAnyNodeSkip()), definitionId);
        }
        //获取可驳回的前置节点
        List<Node> nodes = nodeService.previousNodeList(definitionId, nowNodeCode);
        if (CollUtil.isNotEmpty(nodes)) {
            return StreamUtils.filter(nodes, e -> NodeType.BETWEEN.getKey().equals(e.getNodeType()));
        }
        return nodes;
    }
    /**
     * ç»ˆæ­¢ä»»åŠ¡
     *
     * @param bo å‚æ•°
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean terminationTask(FlowTerminationBo bo) {
        try {
            Long taskId = bo.getTaskId();
            Task task = taskService.getById(taskId);
            if (task == null) {
                throw new ServiceException("任务不存在!");
            }
            Instance instance = insService.getById(task.getInstanceId());
            if (ObjectUtil.isNotNull(instance)) {
                BusinessStatusEnum.checkInvalidStatus(instance.getFlowStatus());
            }
            FlowParams flowParams = new FlowParams();
            flowParams.message(bo.getComment());
            flowParams.flowStatus(BusinessStatusEnum.TERMINATION.getStatus())
                .hisStatus(TaskStatusEnum.TERMINATION.getStatus());
            taskService.termination(taskId, flowParams);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
    /**
     * æŒ‰ç…§ä»»åŠ¡id查询任务
     *
     * @param taskIdList ä»»åŠ¡id
     */
    @Override
    public List<FlowTask> selectByIdList(List<Long> taskIdList) {
        return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class)
            .in(FlowTask::getId, taskIdList));
    }
    /**
     * æŒ‰ç…§ä»»åŠ¡id查询任务
     *
     * @param taskId ä»»åŠ¡id
     */
    @Override
    public FlowTaskVo selectById(Long taskId) {
        Task task = taskService.getById(taskId);
        if (ObjectUtil.isNull(task)) {
            return null;
        }
        FlowTaskVo flowTaskVo = BeanUtil.toBean(task, FlowTaskVo.class);
        Instance instance = insService.getById(task.getInstanceId());
        Definition definition = defService.getById(task.getDefinitionId());
        flowTaskVo.setFlowStatus(instance.getFlowStatus());
        flowTaskVo.setVersion(definition.getVersion());
        flowTaskVo.setFlowCode(definition.getFlowCode());
        flowTaskVo.setFlowName(definition.getFlowName());
        flowTaskVo.setBusinessId(instance.getBusinessId());
        List<Node> nodeList = nodeService.getByNodeCodes(Collections.singletonList(flowTaskVo.getNodeCode()), instance.getDefinitionId());
        if (CollUtil.isNotEmpty(nodeList)) {
            Node node = nodeList.get(0);
            flowTaskVo.setNodeRatio(node.getNodeRatio());
        }
        return flowTaskVo;
    }
    /**
     * æŒ‰ç…§ä»»åŠ¡id查询任务
     *
     * @param taskIdList ä»»åŠ¡id
     * @return ç»“æžœ
     */
    @Override
    public List<FlowHisTask> selectHisTaskByIdList(List<Long> taskIdList) {
        return flowHisTaskMapper.selectList(new LambdaQueryWrapper<>(FlowHisTask.class)
            .in(FlowHisTask::getId, taskIdList));
    }
    /**
     * æŒ‰ç…§ä»»åŠ¡id查询任务
     *
     * @param taskId ä»»åŠ¡id
     * @return ç»“æžœ
     */
    @Override
    public FlowHisTask selectHisTaskById(Long taskId) {
        return flowHisTaskMapper.selectOne(new LambdaQueryWrapper<>(FlowHisTask.class)
            .eq(FlowHisTask::getId, taskId));
    }
    /**
     * æŒ‰ç…§å®žä¾‹id查询任务
     *
     * @param instanceIdList æµç¨‹å®žä¾‹id
     */
    @Override
    public List<FlowTask> selectByInstIdList(List<Long> instanceIdList) {
        return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class)
            .in(FlowTask::getInstanceId, instanceIdList));
    }
    /**
     * æŒ‰ç…§å®žä¾‹id查询任务
     *
     * @param instanceId æµç¨‹å®žä¾‹id
     */
    @Override
    public List<FlowTask> selectByInstId(Long instanceId) {
        return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class)
            .eq(FlowTask::getInstanceId, instanceId));
    }
    /**
     * ä»»åŠ¡æ“ä½œ
     *
     * @param bo            å‚æ•°
     * @param taskOperation æ“ä½œç±»åž‹ï¼Œå§”æ´¾ delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean taskOperation(TaskOperationBo bo, String taskOperation) {
        FlowParams flowParams = new FlowParams();
        flowParams.message(bo.getMessage());
        if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) {
            flowParams.ignore(true);
        }
        // æ ¹æ®æ“ä½œç±»åž‹æž„建 FlowParams
        switch (taskOperation) {
            case DELEGATE_TASK, TRANSFER_TASK -> {
                ValidatorUtils.validate(bo, AddGroup.class);
                flowParams.addHandlers(Collections.singletonList(bo.getUserId()));
            }
            case ADD_SIGNATURE -> {
                ValidatorUtils.validate(bo, EditGroup.class);
                flowParams.addHandlers(bo.getUserIds());
            }
            case REDUCTION_SIGNATURE -> {
                ValidatorUtils.validate(bo, EditGroup.class);
                flowParams.reductionHandlers(bo.getUserIds());
            }
            default -> {
                log.error("Invalid operation type:{} ", taskOperation);
                throw new ServiceException("Invalid operation type " + taskOperation);
            }
        }
        Long taskId = bo.getTaskId();
        FlowTaskVo flowTaskVo = selectById(taskId);
        if ("addSignature".equals(taskOperation) || "reductionSignature".equals(taskOperation)) {
            if (flowTaskVo.getNodeRatio().compareTo(BigDecimal.ZERO) == 0) {
                throw new ServiceException(flowTaskVo.getNodeName() + "不是会签节点!");
            }
        }
        // è®¾ç½®ä»»åŠ¡çŠ¶æ€å¹¶æ‰§è¡Œå¯¹åº”çš„ä»»åŠ¡æ“ä½œ
        switch (taskOperation) {
            //委派任务
            case DELEGATE_TASK -> {
                flowParams.hisStatus(TaskStatusEnum.DEPUTE.getStatus());
                return taskService.depute(taskId, flowParams);
            }
            //转办任务
            case TRANSFER_TASK -> {
                flowParams.hisStatus(TaskStatusEnum.TRANSFER.getStatus());
                return taskService.transfer(taskId, flowParams);
            }
            //加签,增加办理人
            case ADD_SIGNATURE -> {
                flowParams.hisStatus(TaskStatusEnum.SIGN.getStatus());
                return taskService.addSignature(taskId, flowParams);
            }
            //减签,减少办理人
            case REDUCTION_SIGNATURE -> {
                flowParams.hisStatus(TaskStatusEnum.SIGN_OFF.getStatus());
                return taskService.reductionSignature(taskId, flowParams);
            }
            default -> {
                log.error("Invalid operation type:{} ", taskOperation);
                throw new ServiceException("Invalid operation type " + taskOperation);
            }
        }
    }
    /**
     * ä¿®æ”¹ä»»åŠ¡åŠžç†äººï¼ˆæ­¤æ–¹æ³•å°†ä¼šæ‰¹é‡ä¿®æ”¹æ‰€æœ‰ä»»åŠ¡çš„åŠžç†äººï¼‰
     *
     * @param taskIdList ä»»åŠ¡id
     * @param userId     ç”¨æˆ·id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAssignee(List<Long> taskIdList, String userId) {
        if (CollUtil.isEmpty(taskIdList)) {
            return false;
        }
        try {
            List<FlowTask> flowTasks = this.selectByIdList(taskIdList);
            // æ‰¹é‡åˆ é™¤çŽ°æœ‰ä»»åŠ¡çš„åŠžç†äººè®°å½•
            if (CollUtil.isNotEmpty(flowTasks)) {
                WorkflowUtils.getFlowUserService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId));
                List<User> userList = flowTasks.stream()
                    .map(flowTask -> {
                        FlowUser flowUser = new FlowUser();
                        flowUser.setType(TaskAssigneeType.APPROVER.getCode());
                        flowUser.setProcessedBy(userId);
                        flowUser.setAssociated(flowTask.getId());
                        return flowUser;
                    })
                    .collect(Collectors.toList());
                if (CollUtil.isNotEmpty(userList)) {
                    WorkflowUtils.getFlowUserService().saveBatch(userList);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return true;
    }
    /**
     * èŽ·å–ä»»åŠ¡æ‰€æœ‰åŠžç†äºº
     *
     * @param taskIdList ä»»åŠ¡id
     */
    @Override
    public Map<Long, List<UserDTO>> currentTaskAllUser(List<Long> taskIdList) {
        Map<Long, List<UserDTO>> map = new HashMap<>();
        // èŽ·å–ä¸Žå½“å‰ä»»åŠ¡å…³è”çš„ç”¨æˆ·åˆ—è¡¨
        List<User> associatedUsers = WorkflowUtils.getFlowUserService().getByAssociateds(taskIdList);
        Map<Long, List<User>> listMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated);
        for (Map.Entry<Long, List<User>> entry : listMap.entrySet()) {
            List<User> value = entry.getValue();
            if (CollUtil.isNotEmpty(value)) {
                List<UserDTO> userDTOS = userService.selectListByIds(StreamUtils.toList(value, e -> Long.valueOf(e.getProcessedBy())));
                map.put(entry.getKey(), userDTOS);
            }
        }
        return map;
    }
    /**
     * èŽ·å–å½“å‰ä»»åŠ¡çš„æ‰€æœ‰åŠžç†äºº
     *
     * @param taskId ä»»åŠ¡id
     */
    @Override
    public List<UserDTO> currentTaskAllUser(Long taskId) {
        // èŽ·å–ä¸Žå½“å‰ä»»åŠ¡å…³è”çš„ç”¨æˆ·åˆ—è¡¨
        List<User> userList = WorkflowUtils.getFlowUserService().getByAssociateds(Collections.singletonList(taskId));
        if (CollUtil.isEmpty(userList)) {
            return Collections.emptyList();
        }
        return userService.selectListByIds(StreamUtils.toList(userList, e -> Long.valueOf(e.getProcessedBy())));
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java
@@ -1,16 +1,18 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
import org.dromara.common.core.domain.event.ProcessEvent;
import org.dromara.common.core.domain.event.ProcessTaskEvent;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.service.WorkflowService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.mybatis.core.page.PageQuery;
@@ -24,7 +26,6 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
/**
@@ -82,6 +83,9 @@
     */
    @Override
    public TestLeaveVo insertByBo(TestLeaveBo bo) {
        long day = DateUtil.betweenDay(bo.getStartDate(), bo.getEndDate(), true);
        // æˆªæ­¢æ—¥æœŸä¹Ÿç®—一天
        bo.setLeaveDays((int) day + 1);
        TestLeave add = MapstructUtils.convert(bo, TestLeave.class);
        if (StringUtils.isBlank(add.getStatus())) {
            add.setStatus(BusinessStatusEnum.DRAFT.getStatus());
@@ -108,23 +112,22 @@
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        List<String> idList = StreamUtils.toList(ids, String::valueOf);
        workflowService.deleteRunAndHisInstance(idList);
    public Boolean deleteWithValidByIds(List<Long> ids) {
        workflowService.deleteInstance(ids);
        return baseMapper.deleteByIds(ids) > 0;
    }
    /**
     * æ€»ä½“流程监听(例如: æäº¤ é€€å›ž æ’¤é”€ ç»ˆæ­¢ ä½œåºŸç­‰)
     * æ­£å¸¸ä½¿ç”¨åªéœ€#processEvent.key=='leave1'
     * æ€»ä½“流程监听(例如: è‰ç¨¿ï¼Œæ’¤é”€ï¼Œé€€å›žï¼Œä½œåºŸï¼Œç»ˆæ­¢ï¼Œå·²å®Œæˆç­‰)
     * æ­£å¸¸ä½¿ç”¨åªéœ€#processEvent.flowCode=='leave1'
     * ç¤ºä¾‹ä¸ºäº†æ–¹ä¾¿åˆ™ä½¿ç”¨startsWith匹配了全部示例key
     *
     * @param processEvent å‚æ•°
     */
    @EventListener(condition = "#processEvent.key.startsWith('leave')")
    @EventListener(condition = "#processEvent.flowCode.startsWith('leave')")
    public void processHandler(ProcessEvent processEvent) {
        log.info("当前任务执行了{}", processEvent.toString());
        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessKey()));
        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessId()));
        testLeave.setStatus(processEvent.getStatus());
        if (processEvent.isSubmit()) {
            testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
@@ -134,24 +137,37 @@
    /**
     * æ‰§è¡ŒåŠžç†ä»»åŠ¡ç›‘å¬
     * ç¤ºä¾‹ï¼šä¹Ÿå¯é€šè¿‡  @EventListener(condition = "#processTaskEvent.key=='leave1'")进行判断
     * ç¤ºä¾‹ï¼šä¹Ÿå¯é€šè¿‡  @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断
     * åœ¨æ–¹æ³•中判断流程节点key
     * if ("xxx".equals(processTaskEvent.getTaskDefinitionKey())) {
     * if ("xxx".equals(processTaskEvent.getNodeCode())) {
     * //执行业务逻辑
     * }
     *
     * @param processTaskEvent å‚æ•°
     */
    @EventListener(condition = "#processTaskEvent.key.startsWith('leave')")
    @EventListener(condition = "#processTaskEvent.flowCode.startsWith('leave')")
    public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
        // æ‰€æœ‰demo案例的申请人节点id
        String[] ids = {"Activity_14633hx", "Activity_19b1i4j", "Activity_0uscrk3",
            "Activity_0uscrk3", "Activity_0x6b71j", "Activity_0zy3g6j", "Activity_06a55t0"};
        if (StringUtils.equalsAny(processTaskEvent.getTaskDefinitionKey(), ids)) {
            log.info("当前任务执行了{}", processTaskEvent.toString());
            TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey()));
            testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
            baseMapper.updateById(testLeave);
        }
        log.info("当前任务执行了{}", processTaskEvent.toString());
        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessId()));
        testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
        baseMapper.updateById(testLeave);
    }
    /**
     * ç›‘听删除流程事件
     * æ­£å¸¸ä½¿ç”¨åªéœ€#processDeleteEvent.flowCode=='leave1'
     * ç¤ºä¾‹ä¸ºäº†æ–¹ä¾¿åˆ™ä½¿ç”¨startsWith匹配了全部示例key
     *
     * @param processDeleteEvent å‚æ•°
     */
    @EventListener(condition = "#processDeleteEvent.flowCode.startsWith('leave')")
    public void processDeleteHandler(ProcessDeleteEvent processDeleteEvent) {
        log.info("监听删除流程事件,当前任务执行了{}", processDeleteEvent.toString());
        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processDeleteEvent.getBusinessId()));
        if (ObjectUtil.isNull(testLeave)) {
            return;
        }
        baseMapper.deleteById(testLeave.getId());
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java
@@ -1,14 +1,18 @@
package org.dromara.workflow.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.dto.CompleteTaskDTO;
import org.dromara.common.core.domain.dto.StartProcessDTO;
import org.dromara.common.core.service.WorkflowService;
import org.dromara.workflow.domain.ActHiProcinst;
import org.dromara.workflow.service.IActHiProcinstService;
import org.dromara.workflow.service.IActProcessInstanceService;
import org.dromara.workflow.utils.WorkflowUtils;
import org.flowable.engine.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.warm.flow.orm.entity.FlowInstance;
import org.dromara.workflow.domain.bo.CompleteTaskBo;
import org.dromara.workflow.domain.bo.StartProcessBo;
import org.dromara.workflow.service.IFlwDefinitionService;
import org.dromara.workflow.service.IFlwInstanceService;
import org.dromara.workflow.service.IFlwTaskService;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -23,19 +27,19 @@
@Service
public class WorkflowServiceImpl implements WorkflowService {
    @Autowired(required = false)
    private TaskService taskService;
    private final IActProcessInstanceService actProcessInstanceService;
    private final IActHiProcinstService actHiProcinstService;
    private final IFlwInstanceService flwInstanceService;
    private final IFlwDefinitionService flwDefinitionService;
    private final IFlwTaskService flwTaskService;
    /**
     * è¿è¡Œä¸­çš„实例 åˆ é™¤ç¨‹å®žä¾‹ï¼Œåˆ é™¤åŽ†å²è®°å½•ï¼Œåˆ é™¤ä¸šåŠ¡ä¸Žæµç¨‹å…³è”ä¿¡æ¯
     * åˆ é™¤æµç¨‹å®žä¾‹
     *
     * @param businessKeys ä¸šåŠ¡id
     * @param businessIds ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    @Override
    public boolean deleteRunAndHisInstance(List<String> businessKeys) {
        return actProcessInstanceService.deleteRunAndHisInstance(businessKeys);
    public boolean deleteInstance(List<Long> businessIds) {
        return flwInstanceService.deleteByBusinessIds(businessIds);
    }
    /**
@@ -44,78 +48,72 @@
     * @param taskId ä»»åŠ¡id
     */
    @Override
    public String getBusinessStatusByTaskId(String taskId) {
        return WorkflowUtils.getBusinessStatusByTaskId(taskId);
    public String getBusinessStatusByTaskId(Long taskId) {
        FlowInstance flowInstance = flwInstanceService.selectByTaskId(taskId);
        return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getFlowStatus() : StringUtils.EMPTY;
    }
    /**
     * èŽ·å–å½“å‰æµç¨‹çŠ¶æ€
     *
     * @param businessKey ä¸šåŠ¡id
     * @param businessId ä¸šåŠ¡id
     */
    @Override
    public String getBusinessStatus(String businessKey) {
        return WorkflowUtils.getBusinessStatus(businessKey);
    public String getBusinessStatus(String businessId) {
        FlowInstance flowInstance = flwInstanceService.selectInstByBusinessId(businessId);
        return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getFlowStatus() : StringUtils.EMPTY;
    }
    /**
     * è®¾ç½®æµç¨‹å˜é‡(全局变量)
     * è®¾ç½®æµç¨‹å˜é‡
     *
     * @param taskId       ä»»åŠ¡id
     * @param variableName å˜é‡åç§°
     * @param value        å˜é‡å€¼
     * @param instanceId æµç¨‹å®žä¾‹id
     * @param variables  æµç¨‹å˜é‡
     */
    @Override
    public void setVariable(String taskId, String variableName, Object value) {
        taskService.setVariable(taskId, variableName, value);
    }
    /**
     * è®¾ç½®æµç¨‹å˜é‡(全局变量)
     *
     * @param taskId    ä»»åŠ¡id
     * @param variables æµç¨‹å˜é‡
     */
    @Override
    public void setVariables(String taskId, Map<String, Object> variables) {
        taskService.setVariables(taskId, variables);
    }
    /**
     * è®¾ç½®æµç¨‹å˜é‡(本地变量,非全局变量)
     *
     * @param taskId       ä»»åŠ¡id
     * @param variableName å˜é‡åç§°
     * @param value        å˜é‡å€¼
     */
    @Override
    public void setVariableLocal(String taskId, String variableName, Object value) {
        taskService.setVariableLocal(taskId, variableName, value);
    }
    /**
     * è®¾ç½®æµç¨‹å˜é‡(本地变量,非全局变量)
     *
     * @param taskId    ä»»åŠ¡id
     * @param variables æµç¨‹å˜é‡
     */
    @Override
    public void setVariablesLocal(String taskId, Map<String, Object> variables) {
        taskService.setVariablesLocal(taskId, variables);
    public void setVariable(Long instanceId, Map<String, Object> variables) {
        flwInstanceService.setVariable(instanceId, variables);
    }
    /**
     * æŒ‰ç…§ä¸šåŠ¡id查询流程实例id
     *
     * @param businessKey ä¸šåŠ¡id
     * @param businessId ä¸šåŠ¡id
     * @return ç»“æžœ
     */
    @Override
    public String getInstanceIdByBusinessKey(String businessKey) {
        ActHiProcinst actHiProcinst = actHiProcinstService.selectByBusinessKey(businessKey);
        if (actHiProcinst == null) {
            return StrUtil.EMPTY;
        }
        return actHiProcinst.getId();
    public Long getInstanceIdByBusinessId(String businessId) {
        FlowInstance flowInstance = flwInstanceService.selectInstByBusinessId(businessId);
        return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getId() : null;
    }
    /**
     * æ–°å¢žç§Ÿæˆ·æµç¨‹å®šä¹‰
     *
     * @param tenantId ç§Ÿæˆ·id
     */
    @Override
    public void syncDef(String tenantId) {
        flwDefinitionService.syncDef(tenantId);
    }
    /**
     * å¯åŠ¨æµç¨‹
     *
     * @param startProcess å‚æ•°
     */
    @Override
    public Map<String, Object> startWorkFlow(StartProcessDTO startProcess) {
        return flwTaskService.startWorkFlow(BeanUtil.toBean(startProcess, StartProcessBo.class));
    }
    /**
     * åŠžç†ä»»åŠ¡
     *
     * @param completeTask å‚æ•°
     */
    @Override
    public boolean completeTask(CompleteTaskDTO completeTask) {
        return flwTaskService.completeTask(BeanUtil.toBean(completeTask, CompleteTaskBo.class));
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java
@@ -2,43 +2,42 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mail.utils.MailUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.workflow.common.constant.FlowConstant;
import org.dromara.common.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.warm.flow.core.constant.ExceptionCons;
import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.entity.Node;
import org.dromara.warm.flow.core.entity.Task;
import org.dromara.warm.flow.core.entity.User;
import org.dromara.warm.flow.core.enums.NodeType;
import org.dromara.warm.flow.core.enums.SkipType;
import org.dromara.warm.flow.core.service.NodeService;
import org.dromara.warm.flow.core.service.TaskService;
import org.dromara.warm.flow.core.service.UserService;
import org.dromara.warm.flow.core.utils.AssertUtil;
import org.dromara.warm.flow.orm.entity.FlowNode;
import org.dromara.warm.flow.orm.entity.FlowTask;
import org.dromara.warm.flow.orm.entity.FlowUser;
import org.dromara.warm.flow.orm.mapper.FlowNodeMapper;
import org.dromara.warm.flow.orm.mapper.FlowTaskMapper;
import org.dromara.workflow.common.enums.MessageTypeEnum;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.domain.ActHiTaskinst;
import org.dromara.workflow.domain.vo.MultiInstanceVo;
import org.dromara.workflow.domain.vo.ParticipantVo;
import org.dromara.workflow.flowable.cmd.UpdateHiTaskInstCmd;
import org.dromara.workflow.mapper.ActHiTaskinstMapper;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.dromara.workflow.service.IFlwTaskAssigneeService;
import org.dromara.workflow.service.IFlwTaskService;
import java.util.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
 * å·¥ä½œæµå·¥å…·
@@ -48,220 +47,84 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class WorkflowUtils {
    private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class);
    private static final ActHiTaskinstMapper ACT_HI_TASKINST_MAPPER = SpringUtils.getBean(ActHiTaskinstMapper.class);
    private static final IFlwTaskAssigneeService TASK_ASSIGNEE_SERVICE = SpringUtils.getBean(IFlwTaskAssigneeService.class);
    private static final IFlwTaskService FLW_TASK_SERVICE = SpringUtils.getBean(IFlwTaskService.class);
    private static final FlowNodeMapper FLOW_NODE_MAPPER = SpringUtils.getBean(FlowNodeMapper.class);
    private static final FlowTaskMapper FLOW_TASK_MAPPER = SpringUtils.getBean(FlowTaskMapper.class);
    private static final UserService USER_SERVICE = SpringUtils.getBean(UserService.class);
    private static final TaskService TASK_SERVICE = SpringUtils.getBean(TaskService.class);
    private static final NodeService NODE_SERVICE = SpringUtils.getBean(NodeService.class);
    /**
     * åˆ›å»ºä¸€ä¸ªæ–°ä»»åŠ¡
     *
     * @param currentTask å‚æ•°
     * èŽ·å–å·¥ä½œæµç”¨æˆ·service
     */
    public static TaskEntity createNewTask(Task currentTask) {
        TaskEntity task = null;
        if (ObjectUtil.isNotEmpty(currentTask)) {
            task = (TaskEntity) PROCESS_ENGINE.getTaskService().newTask();
            task.setCategory(currentTask.getCategory());
            task.setDescription(currentTask.getDescription());
            task.setAssignee(currentTask.getAssignee());
            task.setName(currentTask.getName());
            task.setProcessDefinitionId(currentTask.getProcessDefinitionId());
            task.setProcessInstanceId(currentTask.getProcessInstanceId());
            task.setTaskDefinitionKey(currentTask.getTaskDefinitionKey());
            task.setPriority(currentTask.getPriority());
            task.setCreateTime(new Date());
            task.setTenantId(TenantHelper.getTenantId());
            PROCESS_ENGINE.getTaskService().saveTask(task);
        }
        if (ObjectUtil.isNotNull(task)) {
            UpdateHiTaskInstCmd updateHiTaskInstCmd = new UpdateHiTaskInstCmd(Collections.singletonList(task.getId()), task.getProcessDefinitionId(), task.getProcessInstanceId());
            PROCESS_ENGINE.getManagementService().executeCommand(updateHiTaskInstCmd);
        }
        return task;
    public static UserService getFlowUserService() {
        return USER_SERVICE;
    }
    /**
     * æŠ„送任务
     * æž„建工作流用户
     *
     * @param parentTaskList çˆ¶çº§ä»»åŠ¡
     * @param userIds        äººå‘˜id
     * @param userList åŠžç†ç”¨æˆ·
     * @param taskId   ä»»åŠ¡ID
     * @return ç”¨æˆ·
     */
    public static void createCopyTask(List<Task> parentTaskList, List<Long> userIds) {
        List<Task> list = new ArrayList<>();
        String tenantId = TenantHelper.getTenantId();
        for (Task parentTask : parentTaskList) {
            for (Long userId : userIds) {
                TaskEntity newTask = (TaskEntity) PROCESS_ENGINE.getTaskService().newTask();
                newTask.setParentTaskId(parentTask.getId());
                newTask.setAssignee(userId.toString());
                newTask.setName("【抄送】-" + parentTask.getName());
                newTask.setProcessDefinitionId(parentTask.getProcessDefinitionId());
                newTask.setProcessInstanceId(parentTask.getProcessInstanceId());
                newTask.setTaskDefinitionKey(parentTask.getTaskDefinitionKey());
                newTask.setTenantId(tenantId);
                list.add(newTask);
    public static Set<User> buildUser(List<User> userList, Long taskId) {
        if (CollUtil.isEmpty(userList)) {
            return Set.of();
        }
        Set<User> list = new HashSet<>();
        Set<String> processedBySet = new HashSet<>();
        for (User user : userList) {
            // æ ¹æ® processedBy å‰ç¼€åˆ¤æ–­å¤„理人类型,分别获取用户列表
            List<UserDTO> users = TASK_ASSIGNEE_SERVICE.fetchUsersByStorageId(user.getProcessedBy());
            // è½¬æ¢ä¸º FlowUser å¹¶æ·»åŠ åˆ°ç»“æžœé›†åˆ
            if (CollUtil.isNotEmpty(users)) {
                users.forEach(dto -> {
                    String processedBy = String.valueOf(dto.getUserId());
                    if (!processedBySet.contains(processedBy)) {
                        FlowUser flowUser = new FlowUser();
                        flowUser.setType(user.getType());
                        flowUser.setProcessedBy(processedBy);
                        flowUser.setAssociated(taskId);
                        list.add(flowUser);
                        processedBySet.add(processedBy);
                    }
                });
            }
        }
        PROCESS_ENGINE.getTaskService().bulkSaveTasks(list);
        if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(parentTaskList)) {
            String processInstanceId = parentTaskList.get(0).getProcessInstanceId();
            String processDefinitionId = parentTaskList.get(0).getProcessDefinitionId();
            List<String> taskIds = StreamUtils.toList(list, Task::getId);
            ActHiTaskinst actHiTaskinst = new ActHiTaskinst();
            actHiTaskinst.setProcDefId(processDefinitionId);
            actHiTaskinst.setProcInstId(processInstanceId);
            actHiTaskinst.setScopeType(TaskStatusEnum.COPY.getStatus());
            actHiTaskinst.setTenantId(tenantId);
            LambdaUpdateWrapper<ActHiTaskinst> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.in(ActHiTaskinst::getId, taskIds);
            ACT_HI_TASKINST_MAPPER.update(actHiTaskinst, updateWrapper);
            for (Task task : list) {
                PROCESS_ENGINE.getTaskService().addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), StrUtil.EMPTY);
            }
        }
    }
    /**
     * èŽ·å–å½“å‰ä»»åŠ¡å‚ä¸Žè€…
     *
     * @param taskId ä»»åŠ¡id
     */
    public static ParticipantVo getCurrentTaskParticipant(String taskId, UserService userService) {
        ParticipantVo participantVo = new ParticipantVo();
        List<HistoricIdentityLink> linksForTask = PROCESS_ENGINE.getHistoryService().getHistoricIdentityLinksForTask(taskId);
        Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
        if (task != null && CollUtil.isNotEmpty(linksForTask)) {
            List<HistoricIdentityLink> groupList = StreamUtils.filter(linksForTask, e -> StringUtils.isNotBlank(e.getGroupId()));
            if (CollUtil.isNotEmpty(groupList)) {
                List<Long> groupIds = StreamUtils.toList(groupList, e -> Long.valueOf(e.getGroupId()));
                List<Long> userIds = userService.selectUserIdsByRoleIds(groupIds);
                if (CollUtil.isNotEmpty(userIds)) {
                    participantVo.setGroupIds(groupIds);
                    List<UserDTO> userList = userService.selectListByIds(userIds);
                    if (CollUtil.isNotEmpty(userList)) {
                        List<Long> userIdList = StreamUtils.toList(userList, UserDTO::getUserId);
                        List<String> nickNames = StreamUtils.toList(userList, UserDTO::getNickName);
                        participantVo.setCandidate(userIdList);
                        participantVo.setCandidateName(nickNames);
                        participantVo.setClaim(!StringUtils.isBlank(task.getAssignee()));
                    }
                }
            } else {
                List<HistoricIdentityLink> candidateList = StreamUtils.filter(linksForTask, e -> FlowConstant.CANDIDATE.equals(e.getType()));
                List<Long> userIdList = new ArrayList<>();
                for (HistoricIdentityLink historicIdentityLink : linksForTask) {
                    try {
                        userIdList.add(Long.valueOf(historicIdentityLink.getUserId()));
                    } catch (NumberFormatException ignored) {
                    }
                }
                List<UserDTO> userList = userService.selectListByIds(userIdList);
                if (CollUtil.isNotEmpty(userList)) {
                    List<Long> userIds = StreamUtils.toList(userList, UserDTO::getUserId);
                    List<String> nickNames = StreamUtils.toList(userList, UserDTO::getNickName);
                    participantVo.setCandidate(userIds);
                    participantVo.setCandidateName(nickNames);
                    // åˆ¤æ–­å½“前任务是否具有多个办理人
                    if (CollUtil.isNotEmpty(candidateList) && candidateList.size() > 1) {
                        // å¦‚æžœ assignee å­˜åœ¨ï¼Œåˆ™è®¾ç½®å½“前任务已经被认领
                        participantVo.setClaim(StringUtils.isNotBlank(task.getAssignee()));
                    }
                }
            }
        }
        return participantVo;
    }
    /**
     * åˆ¤æ–­å½“前节点是否为会签节点
     *
     * @param processDefinitionId æµç¨‹å®šä¹‰id
     * @param taskDefinitionKey   æµç¨‹å®šä¹‰id
     */
    public static MultiInstanceVo isMultiInstance(String processDefinitionId, String taskDefinitionKey) {
        BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId);
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(taskDefinitionKey);
        MultiInstanceVo multiInstanceVo = new MultiInstanceVo();
        //判断是否为并行会签节点
        if (flowNode.getBehavior() instanceof ParallelMultiInstanceBehavior behavior && behavior.getCollectionExpression() != null) {
            Expression collectionExpression = behavior.getCollectionExpression();
            String assigneeList = collectionExpression.getExpressionText();
            String assignee = behavior.getCollectionElementVariable();
            multiInstanceVo.setType(behavior);
            multiInstanceVo.setAssignee(assignee);
            multiInstanceVo.setAssigneeList(assigneeList);
            return multiInstanceVo;
            //判断是否为串行会签节点
        } else if (flowNode.getBehavior() instanceof SequentialMultiInstanceBehavior behavior && behavior.getCollectionExpression() != null) {
            Expression collectionExpression = behavior.getCollectionExpression();
            String assigneeList = collectionExpression.getExpressionText();
            String assignee = behavior.getCollectionElementVariable();
            multiInstanceVo.setType(behavior);
            multiInstanceVo.setAssignee(assignee);
            multiInstanceVo.setAssigneeList(assigneeList);
            return multiInstanceVo;
        }
        return null;
    }
    /**
     * èŽ·å–å½“å‰æµç¨‹çŠ¶æ€
     *
     * @param taskId ä»»åŠ¡id
     */
    public static String getBusinessStatusByTaskId(String taskId) {
        HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery().taskId(taskId).singleResult();
        HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(historicTaskInstance.getProcessInstanceId()).singleResult();
        return historicProcessInstance.getBusinessStatus();
    }
    /**
     * èŽ·å–å½“å‰æµç¨‹çŠ¶æ€
     *
     * @param businessKey ä¸šåŠ¡id
     */
    public static String getBusinessStatus(String businessKey) {
        HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult();
        return historicProcessInstance.getBusinessStatus();
        return list;
    }
    /**
     * å‘送消息
     *
     * @param list        ä»»åŠ¡
     * @param name        æµç¨‹åç§°
     * @param flowName    æµç¨‹å®šä¹‰åç§°
     * @param messageType æ¶ˆæ¯ç±»åž‹
     * @param message     æ¶ˆæ¯å†…容,为空则发送默认配置的消息内容
     */
    public static void sendMessage(List<Task> list, String name, List<String> messageType, String message, UserService userService) {
        Set<Long> userIds = new HashSet<>();
    public static void sendMessage(String flowName, Long instId, List<String> messageType, String message) {
        List<UserDTO> userList = new ArrayList<>();
        List<FlowTask> list = FLW_TASK_SERVICE.selectByInstId(instId);
        if (StringUtils.isBlank(message)) {
            message = "有新的【" + name + "】单据已经提交至您的待办,请您及时处理。";
            message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。";
        }
        for (Task t : list) {
            ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId(), userService);
            if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) {
                List<Long> userIdList = userService.selectUserIdsByRoleIds(taskParticipant.getGroupIds());
                if (CollUtil.isNotEmpty(userIdList)) {
                    userIds.addAll(userIdList);
                }
            }
            List<Long> candidate = taskParticipant.getCandidate();
            if (CollUtil.isNotEmpty(candidate)) {
                userIds.addAll(candidate);
        for (Task task : list) {
            List<UserDTO> users = FLW_TASK_SERVICE.currentTaskAllUser(task.getId());
            if (CollUtil.isNotEmpty(users)) {
                userList.addAll(users);
            }
        }
        if (CollUtil.isNotEmpty(userIds)) {
            List<UserDTO> userList = userService.selectListByIds(new ArrayList<>(userIds));
        if (CollUtil.isNotEmpty(userList)) {
            for (String code : messageType) {
                MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code);
                if (ObjectUtil.isNotEmpty(messageTypeEnum)) {
                    switch (messageTypeEnum) {
                        case SYSTEM_MESSAGE:
                            WebSocketMessageDto dto = new WebSocketMessageDto();
                            dto.setSessionKeys(new ArrayList<>(userIds));
                            SseMessageDto dto = new SseMessageDto();
                            dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList()));
                            dto.setMessage(message);
                            WebSocketUtils.publishMessage(dto);
                            SseMessageUtils.publishMessage(dto);
                            break;
                        case EMAIL_MESSAGE:
                            MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message);
@@ -269,6 +132,8 @@
                        case SMS_MESSAGE:
                            //todo çŸ­ä¿¡å‘送
                            break;
                        default:
                            throw new IllegalStateException("Unexpected value: " + messageTypeEnum);
                    }
                }
            }
@@ -276,20 +141,66 @@
    }
    /**
     * æ ¹æ®ä»»åŠ¡id查询 å½“前用户的任务,检查 å½“前人员 æ˜¯å¦æ˜¯è¯¥ taskId çš„办理人
     * é©³å›ž
     *
     * @param taskId ä»»åŠ¡id
     * @return ç»“æžœ
     * @param message        å®¡æ‰¹æ„è§
     * @param instanceId     æµç¨‹å®žä¾‹id
     * @param targetNodeCode ç›®æ ‡èŠ‚ç‚¹
     * @param flowStatus     æµç¨‹çŠ¶æ€
     * @param flowHisStatus  èŠ‚ç‚¹æ“ä½œçŠ¶æ€
     */
    public static Task getTaskByCurrentUser(String taskId) {
        TaskQuery taskQuery = QueryUtils.taskQuery();
        taskQuery.taskId(taskId).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId()));
        List<RoleDTO> roles = LoginHelper.getLoginUser().getRoles();
        if (CollUtil.isNotEmpty(roles)) {
            List<String> groupIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId()));
            taskQuery.taskCandidateGroupIn(groupIds);
    public static void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus) {
        List<FlowTask> list = FLW_TASK_SERVICE.selectByInstId(instanceId);
        if (CollUtil.isNotEmpty(list)) {
            List<FlowTask> tasks = StreamUtils.filter(list, e -> e.getNodeCode().equals(targetNodeCode));
            if (list.size() == tasks.size()) {
                return;
            }
        }
        return taskQuery.singleResult();
        for (FlowTask task : list) {
            List<UserDTO> userList = FLW_TASK_SERVICE.currentTaskAllUser(task.getId());
            FlowParams flowParams = FlowParams.build();
            flowParams.nodeCode(targetNodeCode);
            flowParams.message(message);
            flowParams.skipType(SkipType.PASS.getKey());
            flowParams.flowStatus(flowStatus).hisStatus(flowHisStatus);
            flowParams.ignore(true);
            //解决会签没权限问题
            if (CollUtil.isNotEmpty(userList)) {
                flowParams.handler(userList.get(0).getUserId().toString());
            }
            TASK_SERVICE.skip(task.getId(), flowParams);
        }
        //解决会签多人审批问题
        backTask(message, instanceId, targetNodeCode, flowStatus, flowHisStatus);
    }
    /**
     * ç”³è¯·äººèŠ‚ç‚¹ç¼–ç 
     *
     * @param definitionId æµç¨‹å®šä¹‰id
     * @return ç”³è¯·äººèŠ‚ç‚¹ç¼–ç 
     */
    public static String applyNodeCode(Long definitionId) {
        //获取已发布的流程节点
        List<FlowNode> flowNodes = FLOW_NODE_MAPPER.selectList(new LambdaQueryWrapper<FlowNode>().eq(FlowNode::getDefinitionId, definitionId));
        AssertUtil.isTrue(CollUtil.isEmpty(flowNodes), ExceptionCons.NOT_PUBLISH_NODE);
        Node startNode = flowNodes.stream().filter(t -> NodeType.isStart(t.getNodeType())).findFirst().orElse(null);
        AssertUtil.isNull(startNode, ExceptionCons.LOST_START_NODE);
        Node nextNode = NODE_SERVICE.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.NONE.getKey());
        return nextNode.getNodeCode();
    }
    /**
     * åˆ é™¤è¿è¡Œä¸­çš„任务
     *
     * @param taskIds ä»»åŠ¡id
     */
    public static void deleteRunTask(List<Long> taskIds) {
        if (CollUtil.isEmpty(taskIds)) {
            return;
        }
        USER_SERVICE.deleteByTaskIds(taskIds);
        FLOW_TASK_MAPPER.deleteByIds(taskIds);
    }
}
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.FlwCategoryMapper">
    <select id="countCategoryById" resultType="Long">
        select count(*) from flow_category where del_flag = '0' and category_id = #{categoryId}
    </select>
</mapper>
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.FlwInstanceMapper">
    <resultMap type="org.dromara.workflow.domain.vo.FlowInstanceVo" id="FlowInstanceResult">
    </resultMap>
    <select id="selectInstanceList" resultMap="FlowInstanceResult">
        select fi.id,
               fi.create_time,
               fi.update_time,
               fi.tenant_id,
               fi.del_flag,
               fi.definition_id,
               fi.business_id,
               fi.node_type,
               fi.node_code,
               fi.node_name,
               fi.variable,
               fi.flow_status,
               fi.activity_status,
               fi.create_by,
               fi.ext,
               fd.flow_name,
               fd.flow_code,
               fd.version,
               fd.form_custom,
               fd.form_path,
               fd.category
        from flow_instance fi
                 left join flow_definition fd on fi.definition_id = fd.id
                ${ew.getCustomSqlSegment}
    </select>
</mapper>
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.FlwTaskMapper">
    <resultMap type="org.dromara.workflow.domain.vo.FlowTaskVo" id="FlowTaskResult">
    </resultMap>
    <resultMap type="org.dromara.workflow.domain.vo.FlowHisTaskVo" id="FlowHisTaskResult">
    </resultMap>
    <select id="getListRunTask" resultMap="FlowTaskResult">
        select * from (
            select distinct
                t.id,
                t.node_code,
                t.node_name,
                t.node_type,
                t.definition_id,
                t.instance_id,
                t.create_time,
                t.update_time,
                t.tenant_id,
                i.business_id,
                i.flow_status,
                i.create_by,
                d.flow_name,
                d.flow_code,
                d.form_custom,
                d.category,
                COALESCE(t.form_path, d.form_path) as form_path,
                d.version,
                uu.processed_by,
                uu.type
            from flow_task as t
                    left join flow_user uu on uu.associated = t.id
                    left join flow_definition d on t.definition_id = d.id
                    left join flow_instance i on t.instance_id = i.id
            where t.node_type = 1
              and t.del_flag = '0'
              and uu.del_flag = '0'
              and uu.type in ('1','2','3')
         ) t
         ${ew.getCustomSqlSegment}
    </select>
    <select id="getListFinishTask" resultMap="FlowHisTaskResult">
        select * from (
            select
                a.id,
                a.node_code,
                a.node_name,
                a.cooperate_type,
                a.approver,
                a.collaborator,
                a.node_type,
                a.target_node_code,
                a.target_node_name,
                a.definition_id,
                a.instance_id,
                a.flow_status flow_task_status,
                a.message,
                a.ext,
                a.create_time,
                a.update_time,
                a.tenant_id,
                a.form_custom,
                a.form_path,
                b.flow_status,
                b.business_id,
                b.create_by,
                c.flow_name,
                c.flow_code,
                c.category,
                c.version
            from flow_his_task a
                    left join flow_instance b on a.instance_id = b.id
                    left join flow_definition c on a.definition_id = c.id
            where a.del_flag ='0'
              and b.del_flag = '0'
              and c.del_flag = '0'
              and a.node_type in ('1','3','4')
        ) t
        ${ew.getCustomSqlSegment}
    </select>
    <select id="getTaskCopyByPage" resultMap="FlowTaskResult">
       select * from (
            select
                b.id,
                b.update_time,
                c.business_id,
                c.flow_status,
                c.create_by,
                a.processed_by,
                a.create_time,
                b.form_custom,
                b.form_path,
                b.node_name,
                b.node_code,
                d.flow_name,
                d.flow_code,
                d.category,
                d.version
            from flow_user a
                left join flow_his_task b on a.associated = b.task_id
                left join flow_instance c on b.instance_id = c.id
                left join flow_definition d on c.definition_id=d.id
            where a.type = '4'
               and a.del_flag = '0'
               and b.del_flag = '0'
               and d.del_flag = '0'
            ) t
        ${ew.getCustomSqlSegment}
    </select>
</mapper>
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml
ÎļþÒÑɾ³ý
ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml
ÎļþÒÑɾ³ý
script/bpmn/leave1.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<definition flowCode="leave1" flowName="请假申请-普通" version="1" category="1" formCustom="N" formPath="/workflow/leaveEdit/index">
    <node nodeType="start" nodeCode="d5ee3ddf-3968-4379-a86f-9ceabde5faac" nodeName="开始" nodeRatio="0.000" coordinate="200,200|200,200" skipAnyNode="N" formCustom="N">
        <skip coordinate="220,200;310,200" skipType="PASS">dd515cdd-59f6-446f-94ca-25ca062afb42</skip>
    </node>
    <node nodeType="between" nodeCode="dd515cdd-59f6-446f-94ca-25ca062afb42" nodeName="申请人" nodeRatio="0.000" coordinate="360,200|360,200" skipAnyNode="N" formCustom="N">
        <skip coordinate="410,200;490,200" skipType="PASS">78fa8e5b-e809-44ed-978a-41092409ebcf</skip>
    </node>
    <node nodeType="between" nodeCode="78fa8e5b-e809-44ed-978a-41092409ebcf" nodeName="组长" permissionFlag="role:1" nodeRatio="0.000" coordinate="540,200|540,200" skipAnyNode="N" formCustom="N">
        <skip coordinate="590,200;670,200" skipType="PASS">a8abf15f-b83e-428a-86cc-033555ea9bbe</skip>
    </node>
    <node nodeType="between" nodeCode="a8abf15f-b83e-428a-86cc-033555ea9bbe" nodeName="部门主管" permissionFlag="role:3,role:4" nodeRatio="0.000" coordinate="720,200|720,200" skipAnyNode="N" formCustom="N">
        <skip coordinate="770,200;880,200" skipType="PASS">8b82b7d7-8660-455e-b880-d6d22ea3eb6d</skip>
    </node>
    <node nodeType="end" nodeCode="8b82b7d7-8660-455e-b880-d6d22ea3eb6d" nodeName="结束" nodeRatio="0.000" coordinate="900,200|900,200" skipAnyNode="N" formCustom="N"/>
</definition>
script/bpmn/leave2.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<definition flowCode="leave2" flowName="请假申请-排他网关" version="2" category="1" formCustom="N" formPath="/workflow/leaveEdit/index">
    <node nodeType="start" nodeCode="cef3895c-f7d8-4598-8bf3-8ec2ef6ce84a" nodeName="开始" nodeRatio="0.000" coordinate="300,240|300,240" skipAnyNode="N" formCustom="N">
        <skip coordinate="320,240;390,240" skipType="PASS">fdcae93b-b69c-498a-b231-09255e74bcbd</skip>
    </node>
    <node nodeType="between" nodeCode="fdcae93b-b69c-498a-b231-09255e74bcbd" nodeName="申请人" nodeRatio="0.000" coordinate="440,240|440,240" skipAnyNode="N" formCustom="N">
        <skip coordinate="490,240;535,240" skipType="PASS">7b8c7ead-7dc8-4951-a7f3-f0c41995909e</skip>
    </node>
    <node nodeType="serial" nodeCode="7b8c7ead-7dc8-4951-a7f3-f0c41995909e" nodeRatio="0.000" coordinate="560,240" skipAnyNode="N" formCustom="N">
        <skip coordinate="560,265;560,320;670,320" skipType="PASS" skipCondition="@@le@@|leaveDays@@le@@2">b3528155-dcb7-4445-bbdf-3d00e3499e86</skip>
        <skip coordinate="560,215;560,160;670,160|560,187" skipType="PASS" skipName="大于两天" skipCondition="@@gt@@|leaveDays@@gt@@2">5ed2362b-fc0c-4d52-831f-95208b830605</skip>
    </node>
    <node nodeType="between" nodeCode="b3528155-dcb7-4445-bbdf-3d00e3499e86" nodeName="组长" permissionFlag="3,4" nodeRatio="0.000" coordinate="720,320|720,320" skipAnyNode="N" formCustom="N">
        <skip coordinate="770,320;860,320;860,280" skipType="PASS">c9fa6d7d-2a74-4e78-b947-0cad8a6af869</skip>
    </node>
    <node nodeType="between" nodeCode="c9fa6d7d-2a74-4e78-b947-0cad8a6af869" nodeName="总经理" permissionFlag="role:1" nodeRatio="0.000" coordinate="860,240|860,240" skipAnyNode="N" formCustom="N">
        <skip coordinate="910,240;980,240" skipType="PASS">40aa65fd-0712-4d23-b6f7-d0432b920fd1</skip>
    </node>
    <node nodeType="end" nodeCode="40aa65fd-0712-4d23-b6f7-d0432b920fd1" nodeName="结束" nodeRatio="0.000" coordinate="1000,240|1000,240" skipAnyNode="N" formCustom="N"/>
    <node nodeType="between" nodeCode="5ed2362b-fc0c-4d52-831f-95208b830605" nodeName="部门领导" permissionFlag="role:1" nodeRatio="0.000" coordinate="720,160|720,160" skipAnyNode="N" formCustom="N">
        <skip coordinate="770,160;860,160;860,200" skipType="PASS">c9fa6d7d-2a74-4e78-b947-0cad8a6af869</skip>
    </node>
</definition>
script/bpmn/leave3.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<definition flowCode="leave3" flowName="请假申请-并行网关" version="1" category="1" formCustom="N" formPath="/workflow/leaveEdit/index">
    <node nodeType="start" nodeCode="a80ecf9f-f465-4ae5-a429-e30ec5d0f957" nodeName="开始" nodeRatio="0.000" coordinate="380,220|380,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="400,220;470,220" skipType="PASS">b7bbb571-06de-455c-8083-f83c07bf0b99</skip>
    </node>
    <node nodeType="between" nodeCode="b7bbb571-06de-455c-8083-f83c07bf0b99" nodeName="申请人" nodeRatio="0.000" coordinate="520,220|520,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="570,220;655,220" skipType="PASS">84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a</skip>
    </node>
    <node nodeType="parallel" nodeCode="84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a" nodeRatio="0.000" coordinate="680,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="680,195;680,140;750,140" skipType="PASS">4b7743cd-940c-431b-926f-e7b614fbf1fe</skip>
        <skip coordinate="680,245;680,300;750,300" skipType="PASS">762cb975-37d8-4276-b6db-79a4c3606394</skip>
    </node>
    <node nodeType="between" nodeCode="4b7743cd-940c-431b-926f-e7b614fbf1fe" nodeName="市场部" permissionFlag="role:1" nodeRatio="0.000" coordinate="800,140|800,140" skipAnyNode="N" formCustom="N">
        <skip coordinate="850,140;920,140;920,195" skipType="PASS">b66b6563-f9fe-41cc-a782-f7837bb6f3d2</skip>
    </node>
    <node nodeType="parallel" nodeCode="b66b6563-f9fe-41cc-a782-f7837bb6f3d2" nodeRatio="0.000" coordinate="920,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="945,220;975,220;975,220;960,220;960,220;990,220" skipType="PASS">23e7429e-2b47-4431-b93e-40db7c431ce6</skip>
    </node>
    <node nodeType="between" nodeCode="23e7429e-2b47-4431-b93e-40db7c431ce6" nodeName="CEO" permissionFlag="1" nodeRatio="0.000" coordinate="1040,220|1040,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="1090,220;1140,220" skipType="PASS">f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1</skip>
    </node>
    <node nodeType="end" nodeCode="f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1" nodeName="结束" nodeRatio="0.000" coordinate="1160,220|1160,220" skipAnyNode="N" formCustom="N"/>
    <node nodeType="between" nodeCode="762cb975-37d8-4276-b6db-79a4c3606394" nodeName="综合部" permissionFlag="role:3,role:4" nodeRatio="0.000" coordinate="800,300|800,300" skipAnyNode="N" formCustom="N">
        <skip coordinate="850,300;920,300;920,245" skipType="PASS">b66b6563-f9fe-41cc-a782-f7837bb6f3d2</skip>
    </node>
</definition>
script/bpmn/leave4.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<definition flowCode="leave4" flowName="请假申请-会签" version="1" category="103" formCustom="N" formPath="/workflow/leaveEdit/index">
    <node nodeType="start" nodeCode="9ce8bf00-f25b-4fc6-91b8-827082fc4876" nodeName="开始" nodeRatio="0.000" coordinate="320,240|320,240" skipAnyNode="N" formCustom="N">
        <skip coordinate="340,240;410,240" skipType="PASS">e90b98ef-35b4-410c-a663-bae8b7624b9f</skip>
    </node>
    <node nodeType="between" nodeCode="e90b98ef-35b4-410c-a663-bae8b7624b9f" nodeName="申请人" nodeRatio="0.000" coordinate="460,240|460,240" skipAnyNode="N" formCustom="N">
        <skip coordinate="510,240;590,240" skipType="PASS">768b5b1a-6726-4d67-8853-4cc70d5b1045</skip>
    </node>
    <node nodeType="between" nodeCode="768b5b1a-6726-4d67-8853-4cc70d5b1045" nodeName="百分之60通过" permissionFlag="${userList}" nodeRatio="60.000" coordinate="640,240|640,240" skipAnyNode="N" anyNodeSkip="e90b98ef-35b4-410c-a663-bae8b7624b9f" formCustom="N">
        <skip coordinate="690,240;770,240" skipType="PASS">2f9f2e21-9bcf-42a3-a07c-13037aad22d1</skip>
    </node>
    <node nodeType="between" nodeCode="2f9f2e21-9bcf-42a3-a07c-13037aad22d1" nodeName="全部审批通过" permissionFlag="role:1,role:3" nodeRatio="100.000" coordinate="820,240|820,240" skipAnyNode="N" formCustom="N">
        <skip coordinate="870,240;950,240" skipType="PASS">27461e01-3d9f-4530-8fe3-bd5ec7f9571f</skip>
    </node>
    <node nodeType="between" nodeCode="27461e01-3d9f-4530-8fe3-bd5ec7f9571f" nodeName="CEO" permissionFlag="1" nodeRatio="0.000" coordinate="1000,240|1000,240" skipAnyNode="N" formCustom="N">
        <skip coordinate="1050,240;1080,240;1080,240;1070,240;1070,240;1100,240" skipType="PASS">b62b88c3-8d8d-4969-911e-2aaea219e7fc</skip>
    </node>
    <node nodeType="end" nodeCode="b62b88c3-8d8d-4969-911e-2aaea219e7fc" nodeName="结束" nodeRatio="0.000" coordinate="1120,240|1120,240" skipAnyNode="N" formCustom="N"/>
</definition>
script/bpmn/leave5.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<definition flowCode="leave5" flowName="请假申请-并行会签网关" version="1" category="103" formCustom="N" formPath="/workflow/leaveEdit/index">
    <node nodeType="start" nodeCode="ebebaf26-9cb6-497e-8119-4c9fed4c597c" nodeName="开始" nodeRatio="0.000" coordinate="300,220|300,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="320,220;350,220;350,220;340,220;340,220;370,220" skipType="PASS">e1b04e96-dc81-4858-a309-2fe945d2f374</skip>
    </node>
    <node nodeType="between" nodeCode="e1b04e96-dc81-4858-a309-2fe945d2f374" nodeName="申请人" nodeRatio="0.000" coordinate="420,220|420,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="470,220;535,220" skipType="PASS">3e743f4f-51ca-41d4-8e94-21f5dd9b59c9</skip>
    </node>
    <node nodeType="parallel" nodeCode="3e743f4f-51ca-41d4-8e94-21f5dd9b59c9" nodeRatio="0.000" coordinate="560,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="560,245;560,320;650,320" skipType="PASS">c80f273e-1f17-4bd8-9ad1-04a4a94ea862</skip>
        <skip coordinate="560,195;560,120;650,120" skipType="PASS">1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4</skip>
    </node>
    <node nodeType="between" nodeCode="c80f273e-1f17-4bd8-9ad1-04a4a94ea862" nodeName="会签" permissionFlag="role:1,role:3" nodeRatio="100.000" coordinate="700,320|700,320" skipAnyNode="N" formCustom="N">
        <skip coordinate="750,320;860,320;860,245" skipType="PASS">1a20169e-3d82-4926-a151-e2daad28de1b</skip>
    </node>
    <node nodeType="parallel" nodeCode="1a20169e-3d82-4926-a151-e2daad28de1b" nodeRatio="0.000" coordinate="860,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="885,220;950,220" skipType="PASS">7a8f0473-e409-442e-a843-5c2b813d00e9</skip>
    </node>
    <node nodeType="between" nodeCode="7a8f0473-e409-442e-a843-5c2b813d00e9" nodeName="CEO" permissionFlag="1" nodeRatio="0.000" coordinate="1000,220|1000,220" skipAnyNode="N" formCustom="N">
        <skip coordinate="1050,220;1120,220" skipType="PASS">03c4d2bc-58b5-4408-a2e4-65afb046f169</skip>
    </node>
    <node nodeType="end" nodeCode="03c4d2bc-58b5-4408-a2e4-65afb046f169" nodeName="结束" nodeRatio="0.000" coordinate="1140,220|1140,220" skipAnyNode="N" formCustom="N"/>
    <node nodeType="between" nodeCode="1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4" nodeName="百分之60票签" permissionFlag="${userList}" nodeRatio="60.000" coordinate="700,120|700,120" skipAnyNode="N" anyNodeSkip="e1b04e96-dc81-4858-a309-2fe945d2f374" formCustom="N">
        <skip coordinate="750,120;860,120;860,195" skipType="PASS">1a20169e-3d82-4926-a151-e2daad28de1b</skip>
    </node>
</definition>
script/bpmn/Ä£ÐÍ.zip
Binary files differ
script/sql/oracle/oracle_ry_workflow.sql
@@ -1,261 +1,410 @@
insert into sys_menu values('11616', '工作流'  , '0',    '6', 'workflow',          '',                                 '', '1', '0', 'M', '0', '0', '',                       'workflow', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11617', '模型管理', '11616', '2', 'model',             'workflow/model/index',             '', '1', '1', 'C', '0', '0', 'workflow:model:list',    'model', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11618', '我的任务', '0', '7', 'task',              '',                                 '', '1', '0', 'M', '0', '0', '',                       'my-task', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11619', '我的待办', '11618', '2', 'taskWaiting',       'workflow/task/taskWaiting',              '', '1', '1', 'C', '0', '0', '',                       'waiting', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11632', '我的已办', '11618', '3', 'taskFinish',       'workflow/task/taskFinish',              '', '1', '1', 'C', '0', '0', '',                       'finish', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11633', '我的抄送', '11618', '4', 'taskCopyList',       'workflow/task/taskCopyList',              '', '1', '1', 'C', '0', '0', '',                       'my-copy', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '',                       'process-definition', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11621', '流程实例', '11630', '1', 'processInstance',   'workflow/processInstance/index',   '', '1', '1', 'C', '0', '0', '',                       'tree-table', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11622', '流程分类', '11616', '1', 'category',          'workflow/category/index',          '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11629', '我发起的', '11618', '1', 'myDocument',        'workflow/task/myDocument',         '', '1', '1', 'C', '0', '0', '',                       'guide', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11630', '流程监控', '11616', '4', 'monitor',           '',                                 '', '1', '0', 'M', '0', '0', '',                       'monitor', 103, 1, sysdate, NULL, NULL, '');
insert into sys_menu values('11631', '待办任务', '11630', '2', 'allTaskWaiting',    'workflow/task/allTaskWaiting',     '', '1', '1', 'C', '0', '0', '',                       'waiting', 103, 1, sysdate, NULL, NULL, '');
-- æµç¨‹åˆ†ç±»ç®¡ç†ç›¸å…³æŒ‰é’®
insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add',   '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit',  '#', 103, 1, sysdate, null, null, '');
insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove','#', 103, 1, sysdate, null, null, '');
insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export','#', 103, 1, sysdate, null, null, '');
-- è¯·å‡å•信息
create table TEST_LEAVE
create table FLOW_DEFINITION
(
    ID          NUMBER(20) not null
        constraint PK_TEST_LEAVE
        primary key,
    LEAVE_TYPE  VARCHAR2(255),
    START_DATE  DATE,
    END_DATE    DATE,
    LEAVE_DAYS  NUMBER(10),
    REMARK      VARCHAR2(255),
    STATUS      VARCHAR2(255),
    CREATE_DEPT NUMBER(20),
    CREATE_BY   NUMBER(20),
    ID NUMBER (20) not null,
    FLOW_CODE VARCHAR2 (40) not null,
    FLOW_NAME VARCHAR2 (100) not null,
    CATEGORY VARCHAR2 (100),
    VERSION VARCHAR2 (20) not null,
    IS_PUBLISH NUMBER (1) default 0 not null,
    FORM_CUSTOM VARCHAR2 (1) default 'N',
    FORM_PATH VARCHAR2 (100),
    ACTIVITY_STATUS NUMBER (1) default 1,
    LISTENER_TYPE VARCHAR2 (100),
    LISTENER_PATH VARCHAR2 (500),
    EXT VARCHAR2 (500),
    CREATE_TIME DATE,
    UPDATE_BY   NUMBER(20),
    UPDATE_TIME DATE,
    TENANT_ID   VARCHAR2(20)
    DEL_FLAG VARCHAR2 (1) default '0',
    TENANT_ID VARCHAR2 (40)
);
comment on table TEST_LEAVE is '请假申请表';
comment on column TEST_LEAVE.ID is '主键';
comment on column TEST_LEAVE.LEAVE_TYPE is '请假类型';
comment on column TEST_LEAVE.START_DATE is '开始时间';
comment on column TEST_LEAVE.END_DATE is '结束时间';
comment on column TEST_LEAVE.LEAVE_DAYS is '请假天数';
comment on column TEST_LEAVE.REMARK is '请假原因';
comment on column TEST_LEAVE.STATUS is '状态';
comment on column TEST_LEAVE.CREATE_DEPT is '创建部门';
comment on column TEST_LEAVE.CREATE_BY is '创建者';
comment on column TEST_LEAVE.CREATE_TIME is '创建时间';
comment on column TEST_LEAVE.UPDATE_BY is '更新者';
comment on column TEST_LEAVE.UPDATE_TIME is '更新时间';
comment on column TEST_LEAVE.TENANT_ID is '租户编号';
alter table FLOW_DEFINITION add constraint PK_FLOW_DEFINITION primary key (ID);
-- æµç¨‹åˆ†ç±»ä¿¡æ¯è¡¨
create table WF_CATEGORY
comment on table FLOW_DEFINITION is '流程定义表';
comment on column FLOW_DEFINITION.ID is '主键id';
comment on column FLOW_DEFINITION.FLOW_CODE is '流程编码';
comment on column FLOW_DEFINITION.FLOW_NAME is '流程名称';
comment on column FLOW_DEFINITION.CATEGORY is '流程类别';
comment on column FLOW_DEFINITION.VERSION is '流程版本';
comment on column FLOW_DEFINITION.IS_PUBLISH is '是否发布 (0未发布 1已发布 9失效)';
comment on column FLOW_DEFINITION.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)';
comment on column FLOW_DEFINITION.FORM_PATH is '审批表单路径';
comment on column FLOW_DEFINITION.ACTIVITY_STATUS is '流程激活状态(0挂起 1激活)';
comment on column FLOW_DEFINITION.LISTENER_TYPE is '监听器类型';
comment on column FLOW_DEFINITION.LISTENER_PATH is '监听器路径';
comment on column FLOW_DEFINITION.EXT is '扩展字段,预留给业务系统使用';
comment on column FLOW_DEFINITION.CREATE_TIME is '创建时间';
comment on column FLOW_DEFINITION.UPDATE_TIME is '更新时间';
comment on column FLOW_DEFINITION.DEL_FLAG is '删除标志';
comment on column FLOW_DEFINITION.TENANT_ID is '租户id';
create table FLOW_NODE
(
    ID            NUMBER(20) not null
        constraint PK_WF_CATEGORY
        primary key,
    CATEGORY_NAME VARCHAR2(255),
    CATEGORY_CODE VARCHAR2(255)
        constraint UNI_CATEGORY_CODE
        unique,
    PARENT_ID     NUMBER(20),
    SORT_NUM      NUMBER(10),
    TENANT_ID     VARCHAR2(20),
    CREATE_DEPT   NUMBER(20),
    CREATE_BY     NUMBER(20),
    CREATE_TIME   DATE,
    UPDATE_BY     NUMBER(20),
    UPDATE_TIME   DATE
    ID NUMBER (20) not null,
    NODE_TYPE NUMBER (1) not null,
    DEFINITION_ID NUMBER (20) not null,
    NODE_CODE VARCHAR2 (100) not null,
    NODE_NAME VARCHAR2 (100),
    NODE_RATIO NUMBER (6,3),
    COORDINATE VARCHAR2 (100),
    SKIP_ANY_NODE VARCHAR2 (100) default 'N',
    ANY_NODE_SKIP VARCHAR2 (100),
    LISTENER_TYPE VARCHAR2 (100),
    LISTENER_PATH VARCHAR2 (500),
    HANDLER_TYPE VARCHAR2 (100),
    HANDLER_PATH VARCHAR2 (400),
    FORM_CUSTOM VARCHAR2 (1) default 'N',
    FORM_PATH VARCHAR2 (100),
    VERSION VARCHAR2 (20),
    CREATE_TIME DATE,
    UPDATE_TIME DATE,
    DEL_FLAG VARCHAR2 (1) default '0',
    TENANT_ID VARCHAR2 (40),
    PERMISSION_FLAG VARCHAR2 (200)
);
comment on table WF_CATEGORY is '流程分类';
comment on column WF_CATEGORY.ID is '主键';
comment on column WF_CATEGORY.CATEGORY_NAME is '分类名称';
comment on column WF_CATEGORY.CATEGORY_CODE is '分类编码';
comment on column WF_CATEGORY.PARENT_ID is '父级id';
comment on column WF_CATEGORY.SORT_NUM is '排序';
comment on column WF_CATEGORY.TENANT_ID is '租户编号';
comment on column WF_CATEGORY.CREATE_DEPT is '创建部门';
comment on column WF_CATEGORY.CREATE_BY is '创建者';
comment on column WF_CATEGORY.CREATE_TIME is '创建时间';
comment on column WF_CATEGORY.UPDATE_BY is '更新者';
comment on column WF_CATEGORY.UPDATE_TIME is '更新时间';
INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, sysdate, 1, sysdate);
alter table FLOW_NODE add constraint PK_FLOW_NODE primary key (ID);
create table WF_TASK_BACK_NODE
comment on table FLOW_NODE is '流程节点表';
comment on column FLOW_NODE.ID is '主键id';
comment on column FLOW_NODE.NODE_TYPE is '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
comment on column FLOW_NODE.DEFINITION_ID is '对应flow_definition表的id';
comment on column FLOW_NODE.NODE_CODE is '流程节点编码';
comment on column FLOW_NODE.NODE_NAME is '流程节点名称';
comment on column FLOW_NODE.NODE_RATIO is '流程签署比例值';
comment on column FLOW_NODE.COORDINATE is '坐标';
comment on column FLOW_NODE.SKIP_ANY_NODE is '是否可以退回任意节点(Y是 N否)即将删除';
comment on column FLOW_NODE.ANY_NODE_SKIP is '任意结点跳转';
comment on column FLOW_NODE.LISTENER_TYPE is '监听器类型';
comment on column FLOW_NODE.LISTENER_PATH is '监听器路径';
comment on column FLOW_NODE.HANDLER_TYPE is '处理器类型';
comment on column FLOW_NODE.HANDLER_PATH is '处理器路径';
comment on column FLOW_NODE.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)';
comment on column FLOW_NODE.FORM_PATH is '审批表单路径';
comment on column FLOW_NODE.VERSION is '版本';
comment on column FLOW_NODE.CREATE_TIME is '创建时间';
comment on column FLOW_NODE.UPDATE_TIME is '更新时间';
comment on column FLOW_NODE.DEL_FLAG is '删除标志';
comment on column FLOW_NODE.TENANT_ID is '租户id';
comment on column FLOW_NODE.PERMISSION_FLAG is '权限标识(权限类型:权限标识,可以多个,用逗号隔开)';
create table FLOW_SKIP
(
    ID            NUMBER(20) not null
        constraint PK_WF_TASK_BACK_NODE
        primary key,
    NODE_ID       VARCHAR2(255) not null,
    NODE_NAME     VARCHAR2(255) not null,
    ORDER_NO      NUMBER(20) not null,
    INSTANCE_ID   VARCHAR2(255) not null,
    TASK_TYPE     VARCHAR2(255) not null,
    ASSIGNEE      VARCHAR2(2000) not null,
    TENANT_ID     VARCHAR2(20),
    CREATE_DEPT   NUMBER(20),
    CREATE_BY     NUMBER(20),
    CREATE_TIME   DATE,
    UPDATE_BY     NUMBER(20),
    UPDATE_TIME   DATE
    ID NUMBER (20) not null,
    DEFINITION_ID NUMBER (20) not null,
    NOW_NODE_CODE VARCHAR2 (100) not null,
    NOW_NODE_TYPE NUMBER (1),
    NEXT_NODE_CODE VARCHAR2 (100) not null,
    NEXT_NODE_TYPE NUMBER (1),
    SKIP_NAME VARCHAR2 (100),
    SKIP_TYPE VARCHAR2 (40),
    SKIP_CONDITION VARCHAR2 (200),
    COORDINATE VARCHAR2 (100),
    CREATE_TIME DATE,
    UPDATE_TIME DATE,
    DEL_FLAG VARCHAR2 (1) default '0',
    TENANT_ID VARCHAR2 (40)
);
comment on table WF_TASK_BACK_NODE is '节点审批记录';
comment on column WF_TASK_BACK_NODE.ID is '主键';
comment on column WF_TASK_BACK_NODE.NODE_ID is '节点id';
comment on column WF_TASK_BACK_NODE.NODE_NAME is '节点名称';
comment on column WF_TASK_BACK_NODE.ORDER_NO is '排序';
comment on column WF_TASK_BACK_NODE.INSTANCE_ID is '流程实例id';
comment on column WF_TASK_BACK_NODE.TASK_TYPE is '节点类型';
comment on column WF_TASK_BACK_NODE.ASSIGNEE is '审批人';
comment on column WF_TASK_BACK_NODE.TENANT_ID is '租户编号';
comment on column WF_TASK_BACK_NODE.CREATE_DEPT is '创建部门';
comment on column WF_TASK_BACK_NODE.CREATE_BY is '创建者';
comment on column WF_TASK_BACK_NODE.CREATE_TIME is '创建时间';
comment on column WF_TASK_BACK_NODE.UPDATE_BY is '更新者';
comment on column WF_TASK_BACK_NODE.UPDATE_TIME is '更新时间';
create table WF_DEFINITION_CONFIG
alter table FLOW_SKIP add constraint PK_FLOW_SKIP primary key (ID);
comment on table FLOW_SKIP is '节点跳转关联表';
comment on column FLOW_SKIP.ID is '主键id';
comment on column FLOW_SKIP.DEFINITION_ID is '流程定义id';
comment on column FLOW_SKIP.NOW_NODE_CODE is '当前流程节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
comment on column FLOW_SKIP.NOW_NODE_TYPE is '下一个流程节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
comment on column FLOW_SKIP.NEXT_NODE_CODE is '下一个流程节点编码';
comment on column FLOW_SKIP.NEXT_NODE_TYPE is '下一个流程节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
comment on column FLOW_SKIP.SKIP_NAME is '跳转名称';
comment on column FLOW_SKIP.SKIP_TYPE is '跳转类型 (PASS审批通过 REJECT退回)';
comment on column FLOW_SKIP.SKIP_CONDITION is '跳转条件';
comment on column FLOW_SKIP.COORDINATE is '坐标';
comment on column FLOW_SKIP.CREATE_TIME is '创建时间';
comment on column FLOW_SKIP.UPDATE_TIME is '更新时间';
comment on column FLOW_SKIP.DEL_FLAG is '删除标志';
comment on column FLOW_SKIP.TENANT_ID is '租户id';
create table FLOW_INSTANCE
(
    ID            NUMBER(20) NOT NULL
        CONSTRAINT PK_WF_DEFINITION_CONFIG
        PRIMARY KEY,
    TABLE_NAME    VARCHAR2(255) NOT NULL,
    DEFINITION_ID VARCHAR2(255) NOT NULL,
    PROCESS_KEY   VARCHAR2(255) NOT NULL,
    VERSION       NUMBER(10)    NOT NULL,
    REMARK        VARCHAR2(500),
    TENANT_ID     VARCHAR2(20),
    CREATE_DEPT   NUMBER(20),
    CREATE_BY     NUMBER(20),
    CREATE_TIME   DATE,
    UPDATE_BY     NUMBER(20),
    UPDATE_TIME   DATE,
    constraint uni_definition_id
        unique (definition_id)
    ID NUMBER not null,
    DEFINITION_ID NUMBER not null,
    BUSINESS_ID VARCHAR2 (40) not null,
    NODE_TYPE NUMBER (1),
    NODE_CODE VARCHAR2 (100),
    NODE_NAME VARCHAR2 (100),
    VARIABLE CLOB,
    FLOW_STATUS VARCHAR2 (20),
    ACTIVITY_STATUS NUMBER (1) default 1,
    CREATE_BY VARCHAR2 (64) default '',
    CREATE_TIME DATE,
    UPDATE_TIME DATE,
    EXT VARCHAR2 (500),
    DEL_FLAG VARCHAR2 (1) default '0',
    TENANT_ID VARCHAR2 (40)
);
comment on table WF_DEFINITION_CONFIG is '流程定义配置';
comment on column WF_DEFINITION_CONFIG.ID is '主键';
comment on column WF_DEFINITION_CONFIG.TABLE_NAME is '表名';
comment on column WF_DEFINITION_CONFIG.DEFINITION_ID is '流程定义ID';
comment on column WF_DEFINITION_CONFIG.PROCESS_KEY is '流程KEY';
comment on column WF_DEFINITION_CONFIG.VERSION is '流程版本';
comment on column WF_DEFINITION_CONFIG.TENANT_ID is '租户编号';
comment on column WF_DEFINITION_CONFIG.REMARK is '备注';
comment on column WF_DEFINITION_CONFIG.CREATE_DEPT is '创建部门';
comment on column WF_DEFINITION_CONFIG.CREATE_BY is '创建者';
comment on column WF_DEFINITION_CONFIG.CREATE_TIME is '创建时间';
comment on column WF_DEFINITION_CONFIG.UPDATE_BY is '更新者';
comment on column WF_DEFINITION_CONFIG.UPDATE_TIME is '更新时间';
create table WF_FORM_MANAGE
alter table FLOW_INSTANCE add constraint PK_FLOW_INSTANCE primary key (ID);
comment on table FLOW_INSTANCE is '流程实例表';
comment on column FLOW_INSTANCE.ID is '主键id';
comment on column FLOW_INSTANCE.DEFINITION_ID is '对应flow_definition表的id';
comment on column FLOW_INSTANCE.BUSINESS_ID is '业务id';
comment on column FLOW_INSTANCE.NODE_TYPE is '开始节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
comment on column FLOW_INSTANCE.NODE_CODE is '开始节点编码';
comment on column FLOW_INSTANCE.NODE_NAME is '开始节点名称';
comment on column FLOW_INSTANCE.VARIABLE is '任务变量';
comment on column FLOW_INSTANCE.FLOW_STATUS is '流程状态(0待提交 1审批中 2 å®¡æ‰¹é€šè¿‡ 3自动通过 4终止 5作废 6撤销 7取回  8已完成 9已退回 10失效)';
comment on column FLOW_INSTANCE.ACTIVITY_STATUS is '流程激活状态(0挂起 1激活)';
comment on column FLOW_INSTANCE.CREATE_BY is '创建者';
comment on column FLOW_INSTANCE.CREATE_TIME is '创建时间';
comment on column FLOW_INSTANCE.UPDATE_TIME is '更新时间';
comment on column FLOW_INSTANCE.EXT is '扩展字段,预留给业务系统使用';
comment on column FLOW_INSTANCE.DEL_FLAG is '删除标志';
comment on column FLOW_INSTANCE.TENANT_ID is '租户id';
create table FLOW_TASK
(
    ID            NUMBER(20) NOT NULL
        CONSTRAINT PK_WF_FORM_MANAGE
        PRIMARY KEY,
    FORM_NAME     VARCHAR2(255) NOT NULL,
    FORM_TYPE     VARCHAR2(255) NOT NULL,
    ROUTER        VARCHAR2(255) NOT NULL,
    REMARK        VARCHAR2(500),
    TENANT_ID     VARCHAR2(20),
    CREATE_DEPT   NUMBER(20),
    CREATE_BY     NUMBER(20),
    CREATE_TIME   DATE,
    UPDATE_BY     NUMBER(20),
    UPDATE_TIME   DATE
    ID NUMBER (20) not null,
    DEFINITION_ID NUMBER (20) not null,
    INSTANCE_ID NUMBER (20) not null,
    NODE_CODE VARCHAR2 (100),
    NODE_NAME VARCHAR2 (100),
    NODE_TYPE NUMBER (1),
    FORM_CUSTOM VARCHAR2 (1) default 'N',
    FORM_PATH VARCHAR2 (100),
    CREATE_TIME DATE,
    UPDATE_TIME DATE,
    DEL_FLAG VARCHAR2 (1) default '0',
    TENANT_ID VARCHAR2 (40)
);
comment on table WF_FORM_MANAGE is '表单管理';
comment on column WF_FORM_MANAGE.ID is '主键';
comment on column WF_FORM_MANAGE.FORM_NAME is '表单名称';
comment on column WF_FORM_MANAGE.FORM_TYPE is '表单类型';
comment on column WF_FORM_MANAGE.ROUTER is '路由地址/表单ID';
comment on column WF_FORM_MANAGE.REMARK is '备注';
comment on column WF_FORM_MANAGE.TENANT_ID is '租户编号';
comment on column WF_FORM_MANAGE.CREATE_DEPT is '创建部门';
comment on column WF_FORM_MANAGE.CREATE_BY is '创建者';
comment on column WF_FORM_MANAGE.CREATE_TIME is '创建时间';
comment on column WF_FORM_MANAGE.UPDATE_BY is '更新者';
comment on column WF_FORM_MANAGE.UPDATE_TIME is '更新时间';
alter table FLOW_TASK add constraint PK_FLOW_TASK primary key (ID);
insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, sysdate, 1, sysdate);
comment on table FLOW_TASK is '待办任务表';
comment on column FLOW_TASK.ID is '主键id';
comment on column FLOW_TASK.DEFINITION_ID is '对应flow_definition表的id';
comment on column FLOW_TASK.INSTANCE_ID is '对应flow_instance表的id';
comment on column FLOW_TASK.NODE_CODE is '节点编码';
comment on column FLOW_TASK.NODE_NAME is '节点名称';
comment on column FLOW_TASK.NODE_TYPE is '节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
comment on column FLOW_TASK.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)';
comment on column FLOW_TASK.FORM_PATH is '审批表单路径';
comment on column FLOW_TASK.CREATE_TIME is '创建时间';
comment on column FLOW_TASK.UPDATE_TIME is '更新时间';
comment on column FLOW_TASK.DEL_FLAG is '删除标志';
comment on column FLOW_TASK.TENANT_ID is '租户id';
create table WF_NODE_CONFIG
create table FLOW_HIS_TASK
(
    ID               NUMBER(20) NOT NULL
        CONSTRAINT PK_WF_NODE_CONFIG
        PRIMARY KEY,
    FORM_ID          NUMBER(20),
    FORM_TYPE        VARCHAR2(255),
    NODE_NAME        VARCHAR2(255) NOT NULL,
    NODE_ID          VARCHAR2(255) NOT NULL,
    DEFINITION_ID    VARCHAR2(255) NOT NULL,
    APPLY_USER_TASK  CHAR(1) DEFAULT '0',
    TENANT_ID        VARCHAR2(20),
    CREATE_DEPT      NUMBER(20),
    CREATE_BY        NUMBER(20),
    CREATE_TIME      DATE,
    UPDATE_BY        NUMBER(20),
    UPDATE_TIME      DATE
    ID NUMBER (20) not null,
    DEFINITION_ID NUMBER (20) not null,
    INSTANCE_ID NUMBER (20) not null,
    TASK_ID NUMBER (20) not null,
    NODE_CODE VARCHAR2 (100),
    NODE_NAME VARCHAR2 (100),
    NODE_TYPE NUMBER (1),
    TARGET_NODE_CODE VARCHAR2 (100),
    TARGET_NODE_NAME VARCHAR2 (100),
    APPROVER VARCHAR2 (40),
    COOPERATE_TYPE NUMBER (1) default 0,
    COLLABORATOR VARCHAR2 (40),
    SKIP_TYPE VARCHAR2 (10),
    FLOW_STATUS VARCHAR2 (20),
    FORM_CUSTOM VARCHAR2 (1) default 'N',
    FORM_PATH VARCHAR2 (100),
    MESSAGE VARCHAR2 (500),
    EXT VARCHAR2 (500),
    CREATE_TIME DATE,
    UPDATE_TIME DATE,
    DEL_FLAG VARCHAR2 (1) default '0',
    TENANT_ID VARCHAR2 (40)
);
comment on table WF_NODE_CONFIG is '节点配置';
comment on column WF_NODE_CONFIG.ID is '主键';
comment on column WF_NODE_CONFIG.FORM_ID is '表单id';
comment on column WF_NODE_CONFIG.FORM_TYPE is '表单类型';
comment on column WF_NODE_CONFIG.NODE_ID is '节点id';
comment on column WF_NODE_CONFIG.NODE_NAME is '节点名称';
comment on column WF_NODE_CONFIG.DEFINITION_ID is '流程定义id';
comment on column WF_NODE_CONFIG.APPLY_USER_TASK is '是否为申请人节点 ï¼ˆ0是 1否)';
comment on column WF_NODE_CONFIG.TENANT_ID is '租户编号';
comment on column WF_NODE_CONFIG.CREATE_DEPT is '创建部门';
comment on column WF_NODE_CONFIG.CREATE_BY is '创建者';
comment on column WF_NODE_CONFIG.CREATE_TIME is '创建时间';
comment on column WF_NODE_CONFIG.UPDATE_BY is '更新者';
comment on column WF_NODE_CONFIG.UPDATE_TIME is '更新时间';
alter table FLOW_HIS_TASK add constraint PK_FLOW_HIS_TASK primary key (ID);
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, sysdate, NULL, NULL, '请假申请菜单');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, sysdate, NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, sysdate, NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, sysdate, NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, sysdate, NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, sysdate, NULL, NULL, '');
comment on table FLOW_HIS_TASK is '历史任务记录表';
comment on column FLOW_HIS_TASK.ID is '主键id';
comment on column FLOW_HIS_TASK.DEFINITION_ID is '对应flow_definition表的id';
comment on column FLOW_HIS_TASK.INSTANCE_ID is '对应flow_instance表的id';
comment on column FLOW_HIS_TASK.TASK_ID is '对应flow_task表的id';
comment on column FLOW_HIS_TASK.NODE_CODE is '开始节点编码';
comment on column FLOW_HIS_TASK.NODE_NAME is '开始节点名称';
comment on column FLOW_HIS_TASK.NODE_TYPE is '开始节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
comment on column FLOW_HIS_TASK.TARGET_NODE_CODE is '目标节点编码';
comment on column FLOW_HIS_TASK.TARGET_NODE_NAME is '目标节点名称';
comment on column FLOW_HIS_TASK.SKIP_TYPE is '流转类型(PASS通过 REJECT退回 NONE无动作)';
comment on column FLOW_HIS_TASK.FLOW_STATUS is '流程状态(1审批中 2 å®¡æ‰¹é€šè¿‡ 9已退回 10失效)';
comment on column FLOW_HIS_TASK.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)';
comment on column FLOW_HIS_TASK.FORM_PATH is '审批表单路径';
comment on column FLOW_HIS_TASK.MESSAGE is '审批意见';
comment on column FLOW_HIS_TASK.EXT is '扩展字段,预留给业务系统使用';
comment on column FLOW_HIS_TASK.CREATE_TIME is '任务开始时间';
comment on column FLOW_HIS_TASK.UPDATE_TIME is '审批完成时间';
comment on column FLOW_HIS_TASK.DEL_FLAG is '删除标志';
comment on column FLOW_HIS_TASK.TENANT_ID is '租户id';
comment on column FLOW_HIS_TASK.APPROVER is '审批者';
comment on column FLOW_HIS_TASK.COOPERATE_TYPE is '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)';
comment on column FLOW_HIS_TASK.COLLABORATOR is '协作人';
INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, sysdate, NULL, NULL, '业务状态列表');
INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, sysdate, NULL, NULL, '表单类型列表');
create table FLOW_USER
(
    ID NUMBER (20) not null,
    TYPE VARCHAR2 (1) not null,
    PROCESSED_BY VARCHAR2 (80),
    ASSOCIATED NUMBER (20) not null,
    CREATE_TIME DATE,
    CREATE_BY VARCHAR2 (80),
    UPDATE_TIME DATE,
    DEL_FLAG VARCHAR2 (1) default '0',
    TENANT_ID VARCHAR2 (40)
);
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate, NULL, NULL, '已撤销');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, sysdate, NULL, NULL, '草稿');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1,sysdate, NULL, NULL, '待审核');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, sysdate, NULL, NULL, '已完成');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate, NULL, NULL, '已作废');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate, NULL, NULL, '已退回');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1,sysdate, NULL, NULL, '已终止');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, sysdate, NULL, NULL, '自定义表单');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, sysdate, NULL, NULL, '动态表单');
alter table FLOW_USER add constraint PK_FLOW_USER primary key (ID);
-- è¡¨å•管理 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11628, '表单管理', '11616', '5', 'formManage', 'workflow/formManage/index', 1, 0, 'C', '0', '0', 'workflow:formManage:list', 'tree-table', 103, 1, sysdate, null, null, '表单管理菜单');
comment on table FLOW_USER is '待办任务表';
comment on column FLOW_USER.ID is '主键id';
comment on column FLOW_USER.TYPE is '人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)';
comment on column FLOW_USER.PROCESSED_BY is '权限人)';
comment on column FLOW_USER.ASSOCIATED is '任务表id';
comment on column FLOW_USER.CREATE_TIME is '创建时间';
comment on column FLOW_USER.CREATE_BY is '节点名称';
comment on column FLOW_USER.UPDATE_TIME is '更新时间';
comment on column FLOW_USER.DEL_FLAG is '删除标志';
comment on column FLOW_USER.TENANT_ID is '租户id';
-- è¡¨å•管理按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11644, '表单管理查询', 11628, '1',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:query',        '', 103, 1, sysdate, null, null, '');
create index USER_PROCESSED_TYPE on FLOW_USER (PROCESSED_BY, TYPE);
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11645, '表单管理新增', 11628, '2',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:add',          '', 103, 1, sysdate, null, null, '');
-- ----------------------------
-- æµç¨‹åˆ†ç±»è¡¨
-- ----------------------------
CREATE TABLE flow_category
(
    category_id NUMBER (20) NOT NULL,
    tenant_id VARCHAR2 (20) DEFAULT '000000',
    parent_id NUMBER (20) DEFAULT 0,
    ancestors VARCHAR2 (500) DEFAULT '',
    category_name VARCHAR2 (30) NOT NULL,
    order_num NUMBER (4) DEFAULT 0,
    del_flag    CHAR(1) DEFAULT '0',
    create_dept NUMBER (20),
    create_by NUMBER (20),
    create_time DATE,
    update_by NUMBER (20),
    update_time DATE
);
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11646, '表单管理修改', 11628, '3',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:edit',         '', 103, 1, sysdate, null, null, '');
alter table flow_category add constraint pk_flow_category primary key (category_id);
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11647, '表单管理删除', 11628, '4',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:remove',       '', 103, 1, sysdate, null, null, '');
COMMENT ON TABLE flow_category IS '流程分类';
COMMENT ON COLUMN flow_category.category_id IS '流程分类ID';
COMMENT ON COLUMN flow_category.tenant_id IS '租户编号';
COMMENT ON COLUMN flow_category.parent_id IS '父流程分类id';
COMMENT ON COLUMN flow_category.ancestors IS '祖级列表';
COMMENT ON COLUMN flow_category.category_name IS '流程分类名称';
COMMENT ON COLUMN flow_category.order_num IS '显示顺序';
COMMENT ON COLUMN flow_category.del_flag IS '删除标志(0代表存在 2代表删除)';
COMMENT ON COLUMN flow_category.create_dept IS '创建部门';
COMMENT ON COLUMN flow_category.create_by IS '创建者';
COMMENT ON COLUMN flow_category.create_time IS '创建时间';
COMMENT ON COLUMN flow_category.update_by IS '更新者';
COMMENT ON COLUMN flow_category.update_time IS '更新时间';
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11648, '表单管理导出', 11628, '5',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:export',       'tree-table', 103, 1, sysdate, null, null, '');
INSERT INTO flow_category VALUES (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (102, '000000', 100, '0,100', '人事管理', 0, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (106, '000000', 101, '0,100,101', '换班', 3, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (107, '000000', 101, '0,100,101', '外出', 4, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (108, '000000', 102, '0,100,102', '转正', 1, '0', 103, 1, SYSDATE, NULL, NULL);
INSERT INTO flow_category VALUES (109, '000000', 102, '0,100,102', '离职', 2, '0', 103, 1, SYSDATE, NULL, NULL);
-- ----------------------------
-- è¯·å‡å•信息
-- ----------------------------
CREATE TABLE test_leave
(
    id NUMBER (20) NOT NULL,
    tenant_id VARCHAR2 (20) DEFAULT '000000',
    leave_type VARCHAR2 (255) NOT NULL,
    start_date  DATE NOT NULL,
    end_date    DATE NOT NULL,
    leave_days NUMBER (10) NOT NULL,
    remark VARCHAR2 (255),
    status VARCHAR2 (255),
    create_dept NUMBER (20),
    create_by NUMBER (20),
    create_time DATE,
    update_by NUMBER (20),
    update_time DATE
);
alter table test_leave add constraint pk_test_leave primary key (id);
COMMENT ON TABLE test_leave IS '请假申请表';
COMMENT ON COLUMN test_leave.id IS 'ID';
COMMENT ON COLUMN test_leave.tenant_id IS '租户编号';
COMMENT ON COLUMN test_leave.leave_type IS '请假类型';
COMMENT ON COLUMN test_leave.start_date IS '开始时间';
COMMENT ON COLUMN test_leave.end_date IS '结束时间';
COMMENT ON COLUMN test_leave.leave_days IS '请假天数';
COMMENT ON COLUMN test_leave.remark IS '请假原因';
COMMENT ON COLUMN test_leave.status IS '状态';
COMMENT ON COLUMN test_leave.create_dept IS '创建部门';
COMMENT ON COLUMN test_leave.create_by IS '创建者';
COMMENT ON COLUMN test_leave.create_time IS '创建时间';
COMMENT ON COLUMN test_leave.update_by IS '更新者';
COMMENT ON COLUMN test_leave.update_time IS '更新时间';
INSERT INTO sys_menu VALUES ('11616', '工作流', '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11623', '流程分类查询', '11622', '1', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:query', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11624', '流程分类新增', '11622', '2', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:add', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11625', '流程分类修改', '11622', '3', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:edit', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11626', '流程分类删除', '11622', '4', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:remove', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11627', '流程分类导出', '11622', '5', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:export', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11638', '请假申请', '5', '1', 'leave', 'workflow/leave/index', '', '1', '0', 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, SYSDATE, NULL, NULL, '请假申请菜单');
INSERT INTO sys_menu VALUES ('11639', '请假申请查询', '11638', '1', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11640', '请假申请新增', '11638', '2', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11641', '请假申请修改', '11638', '3', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11642', '请假申请删除', '11638', '4', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11643', '请假申请导出', '11638', '5', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, SYSDATE, NULL, NULL, '');
INSERT INTO sys_dict_type VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, SYSDATE, NULL, NULL, '业务状态列表');
INSERT INTO sys_dict_type VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, SYSDATE, NULL, NULL, '表单类型列表');
INSERT INTO sys_dict_type VALUES (15, '000000', '任务状态', 'wf_task_status', 103, 1, SYSDATE, NULL, NULL, '任务状态');
INSERT INTO sys_dict_data VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '已撤销');
INSERT INTO sys_dict_data VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, SYSDATE, NULL, NULL, '草稿');
INSERT INTO sys_dict_data VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '待审核');
INSERT INTO sys_dict_data VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, SYSDATE, NULL, NULL, '已完成');
INSERT INTO sys_dict_data VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '已作废');
INSERT INTO sys_dict_data VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '已退回');
INSERT INTO sys_dict_data VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '已终止');
INSERT INTO sys_dict_data VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, SYSDATE, NULL, NULL, '自定义表单');
INSERT INTO sys_dict_data VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '动态表单');
INSERT INTO sys_dict_data VALUES (48, '000000', 1, '撤销', 'cancel', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '撤销');
INSERT INTO sys_dict_data VALUES (49, '000000', 2, '通过', 'pass', 'wf_task_status', '', 'success', 'N', 103, 1, SYSDATE, NULL, NULL, '通过');
INSERT INTO sys_dict_data VALUES (50, '000000', 3, '待审核', 'waiting', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '待审核');
INSERT INTO sys_dict_data VALUES (51, '000000', 4, '作废', 'invalid', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '作废');
INSERT INTO sys_dict_data VALUES (52, '000000', 5, '退回', 'back', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '退回');
INSERT INTO sys_dict_data VALUES (53, '000000', 6, '终止', 'termination', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '终止');
INSERT INTO sys_dict_data VALUES (54, '000000', 7, '转办', 'transfer', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '转办');
INSERT INTO sys_dict_data VALUES (55, '000000', 8, '委托', 'depute', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '委托');
INSERT INTO sys_dict_data VALUES (56, '000000', 9, '抄送', 'copy', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '抄送');
INSERT INTO sys_dict_data VALUES (57, '000000', 10, '加签', 'sign', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '加签');
INSERT INTO sys_dict_data VALUES (58, '000000', 11, '减签', 'sign_off', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '减签');
INSERT INTO sys_dict_data VALUES (59, '000000', 11, '超时', 'timeout', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '超时');
script/sql/postgres/postgres_ry_workflow.sql
@@ -1,275 +1,401 @@
insert into sys_menu values('11616', '工作流'  , '0',    '6', 'workflow',          '',                                 '', '1', '0', 'M', '0', '0', '',                       'workflow', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11617', '模型管理', '11616', '2', 'model',             'workflow/model/index',             '', '1', '1', 'C', '0', '0', 'workflow:model:list',    'model', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11618', '我的任务', '0', '7', 'task',              '',                                 '', '1', '0', 'M', '0', '0', '',                       'my-task', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11619', '我的待办', '11618', '2', 'taskWaiting',       'workflow/task/taskWaiting',              '', '1', '1', 'C', '0', '0', '',                       'waiting', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11632', '我的已办', '11618', '3', 'taskFinish',       'workflow/task/taskFinish',              '', '1', '1', 'C', '0', '0', '',                       'finish', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11633', '我的抄送', '11618', '4', 'taskCopyList',       'workflow/task/taskCopyList',              '', '1', '1', 'C', '0', '0', '',                       'my-copy', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '',                       'process-definition', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11621', '流程实例', '11630', '1', 'processInstance',   'workflow/processInstance/index',   '', '1', '1', 'C', '0', '0', '',                       'tree-table', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11622', '流程分类', '11616', '1', 'category',          'workflow/category/index',          '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11629', '我发起的', '11618', '1', 'myDocument',        'workflow/task/myDocument',         '', '1', '1', 'C', '0', '0', '',                       'guide', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11630', '流程监控', '11616', '4', 'monitor',           '',                                 '', '1', '0', 'M', '0', '0', '',                       'monitor', 103, 1, now(), NULL, NULL, '');
insert into sys_menu values('11631', '待办任务', '11630', '2', 'allTaskWaiting',    'workflow/task/allTaskWaiting',     '', '1', '1', 'C', '0', '0', '',                       'waiting', 103, 1, now(), NULL, NULL, '');
-- ----------------------------
-- 0、warm-flow-all.sql,地址:https://gitee.com/dromara/warm-flow/blob/master/sql/postgresql/postgresql-warm-flow-all.sql
-- ----------------------------
CREATE TABLE flow_definition
(
    id              int8         NOT NULL,                      -- ä¸»é”®id
    flow_code       varchar(40)  NOT NULL,                      -- æµç¨‹ç¼–码
    flow_name       varchar(100) NOT NULL,                      -- æµç¨‹åç§°
    category        varchar(100) NULL,                          -- æµç¨‹ç±»åˆ«
    "version"       varchar(20)  NOT NULL,                      -- æµç¨‹ç‰ˆæœ¬
    is_publish      int2         NOT NULL DEFAULT 0,            -- æ˜¯å¦å‘布(0未发布 1已发布 9失效)
    form_custom     bpchar(1) NULL DEFAULT 'N':: character varying, -- å®¡æ‰¹è¡¨å•是否自定义(Y是 N否)
    form_path       varchar(100) NULL,                          -- å®¡æ‰¹è¡¨å•路径
    activity_status int2         NOT NULL DEFAULT 1,            -- æµç¨‹æ¿€æ´»çŠ¶æ€ï¼ˆ0挂起 1激活)
    listener_type   varchar(100) NULL,                          -- ç›‘听器类型
    listener_path   varchar(400) NULL,                          -- ç›‘听器路径
    ext             varchar(500) NULL,                          -- æ‰©å±•字段,预留给业务系统使用
    create_time     timestamp    NULL,                          -- åˆ›å»ºæ—¶é—´
    update_time     timestamp    NULL,                          -- æ›´æ–°æ—¶é—´
    del_flag        bpchar(1) NULL DEFAULT '0':: character varying,    -- åˆ é™¤æ ‡å¿—
    tenant_id       varchar(40)  NULL,                          -- ç§Ÿæˆ·id
    CONSTRAINT flow_definition_pkey PRIMARY KEY (id)
);
COMMENT ON TABLE flow_definition IS '流程定义表';
COMMENT ON COLUMN flow_definition.id IS '主键id';
COMMENT ON COLUMN flow_definition.flow_code IS '流程编码';
COMMENT ON COLUMN flow_definition.flow_name IS '流程名称';
COMMENT ON COLUMN flow_definition.category IS '流程类别';
COMMENT ON COLUMN flow_definition."version" IS '流程版本';
COMMENT ON COLUMN flow_definition.is_publish IS '是否发布(0未发布 1已发布 9失效)';
COMMENT ON COLUMN flow_definition.form_custom IS '审批表单是否自定义(Y是 N否)';
COMMENT ON COLUMN flow_definition.form_path IS '审批表单路径';
COMMENT ON COLUMN flow_definition.activity_status IS '流程激活状态(0挂起 1激活)';
COMMENT ON COLUMN flow_definition.listener_type IS '监听器类型';
COMMENT ON COLUMN flow_definition.listener_path IS '监听器路径';
COMMENT ON COLUMN flow_definition.ext IS '扩展字段,预留给业务系统使用';
COMMENT ON COLUMN flow_definition.create_time IS '创建时间';
COMMENT ON COLUMN flow_definition.update_time IS '更新时间';
COMMENT ON COLUMN flow_definition.del_flag IS '删除标志';
COMMENT ON COLUMN flow_definition.tenant_id IS '租户id';
CREATE TABLE flow_node
(
    id              int8          NOT NULL,                             -- ä¸»é”®id
    node_type       int2          NOT NULL,                             -- èŠ‚ç‚¹ç±»åž‹ï¼ˆ0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
    definition_id   int8          NOT NULL,                             -- æµç¨‹å®šä¹‰id
    node_code       varchar(100)  NOT NULL,                             -- æµç¨‹èŠ‚ç‚¹ç¼–ç 
    node_name       varchar(100)  NULL,                                 -- æµç¨‹èŠ‚ç‚¹åç§°
    permission_flag varchar(200)  NULL,                                 -- æƒé™æ ‡è¯†ï¼ˆæƒé™ç±»åž‹:权限标识,可以多个,用逗号隔开)
    node_ratio      numeric(6, 3) NULL,                                 -- æµç¨‹ç­¾ç½²æ¯”例值
    coordinate      varchar(100)  NULL,                                 -- åæ ‡
    skip_any_node   varchar(100)  NULL DEFAULT 'N':: character varying, -- æ˜¯å¦å¯ä»¥é€€å›žä»»æ„èŠ‚ç‚¹ï¼ˆY是 N否)即将删除
    any_node_skip   varchar(100)  NULL,                                 -- ä»»æ„ç»“点跳转
    listener_type   varchar(100)  NULL,                                 -- ç›‘听器类型
    listener_path   varchar(400)  NULL,                                 -- ç›‘听器路径
    handler_type    varchar(100)  NULL,                                 -- å¤„理器类型
    handler_path    varchar(400)  NULL,                                 -- å¤„理器路径
    form_custom     bpchar(1) NULL DEFAULT 'N':: character varying,         -- å®¡æ‰¹è¡¨å•是否自定义(Y是 N否)
    form_path       varchar(100)  NULL,                                 -- å®¡æ‰¹è¡¨å•路径
    "version"       varchar(20)   NOT NULL,                             -- ç‰ˆæœ¬
    create_time     timestamp     NULL,                                 -- åˆ›å»ºæ—¶é—´
    update_time     timestamp     NULL,                                 -- æ›´æ–°æ—¶é—´
    del_flag        bpchar(1) NULL DEFAULT '0':: character varying,            -- åˆ é™¤æ ‡å¿—
    tenant_id       varchar(40)   NULL,                                 -- ç§Ÿæˆ·id
    CONSTRAINT flow_node_pkey PRIMARY KEY (id)
);
COMMENT ON TABLE flow_node IS '流程节点表';
COMMENT ON COLUMN flow_node.id IS '主键id';
COMMENT ON COLUMN flow_node.node_type IS '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
COMMENT ON COLUMN flow_node.definition_id IS '流程定义id';
COMMENT ON COLUMN flow_node.node_code IS '流程节点编码';
COMMENT ON COLUMN flow_node.node_name IS '流程节点名称';
COMMENT ON COLUMN flow_node.permission_flag IS '权限标识(权限类型:权限标识,可以多个,用逗号隔开)';
COMMENT ON COLUMN flow_node.node_ratio IS '流程签署比例值';
COMMENT ON COLUMN flow_node.coordinate IS '坐标';
COMMENT ON COLUMN flow_node.skip_any_node IS '是否可以退回任意节点(Y是 N否)即将删除';
COMMENT ON COLUMN flow_node.any_node_skip IS '任意结点跳转';
COMMENT ON COLUMN flow_node.listener_type IS '监听器类型';
COMMENT ON COLUMN flow_node.listener_path IS '监听器路径';
COMMENT ON COLUMN flow_node.handler_type IS '处理器类型';
COMMENT ON COLUMN flow_node.handler_path IS '处理器路径';
COMMENT ON COLUMN flow_node.form_custom IS '审批表单是否自定义(Y是 N否)';
COMMENT ON COLUMN flow_node.form_path IS '审批表单路径';
COMMENT ON COLUMN flow_node."version" IS '版本';
COMMENT ON COLUMN flow_node.create_time IS '创建时间';
COMMENT ON COLUMN flow_node.update_time IS '更新时间';
COMMENT ON COLUMN flow_node.del_flag IS '删除标志';
COMMENT ON COLUMN flow_node.tenant_id IS '租户id';
-- æµç¨‹åˆ†ç±»ç®¡ç†ç›¸å…³æŒ‰é’®
insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1, now(), null, null, '');
insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add',   '#', 103, 1, now(), null, null, '');
insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit',  '#', 103, 1, now(), null, null, '');
insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove','#', 103, 1, now(), null, null, '');
insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export','#', 103, 1, now(), null, null, '');
CREATE TABLE flow_skip
(
    id             int8         NOT NULL,                    -- ä¸»é”®id
    definition_id  int8         NOT NULL,                    -- æµç¨‹å®šä¹‰id
    now_node_code  varchar(100) NOT NULL,                    -- å½“前流程节点的编码
    now_node_type  int2         NULL,                        -- å½“前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
    next_node_code varchar(100) NOT NULL,                    -- ä¸‹ä¸€ä¸ªæµç¨‹èŠ‚ç‚¹çš„ç¼–ç 
    next_node_type int2         NULL,                        -- ä¸‹ä¸€ä¸ªèŠ‚ç‚¹ç±»åž‹ï¼ˆ0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
    skip_name      varchar(100) NULL,                        -- è·³è½¬åç§°
    skip_type      varchar(40)  NULL,                        -- è·³è½¬ç±»åž‹ï¼ˆPASS审批通过 REJECT退回)
    skip_condition varchar(200) NULL,                        -- è·³è½¬æ¡ä»¶
    coordinate     varchar(100) NULL,                        -- åæ ‡
    create_time    timestamp    NULL,                        -- åˆ›å»ºæ—¶é—´
    update_time    timestamp    NULL,                        -- æ›´æ–°æ—¶é—´
    del_flag       bpchar(1) NULL DEFAULT '0':: character varying, -- åˆ é™¤æ ‡å¿—
    tenant_id      varchar(40)  NULL,                        -- ç§Ÿæˆ·id
    CONSTRAINT flow_skip_pkey PRIMARY KEY (id)
);
COMMENT ON TABLE flow_skip IS '节点跳转关联表';
COMMENT ON COLUMN flow_skip.id IS '主键id';
COMMENT ON COLUMN flow_skip.definition_id IS '流程定义id';
COMMENT ON COLUMN flow_skip.now_node_code IS '当前流程节点的编码';
COMMENT ON COLUMN flow_skip.now_node_type IS '当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
COMMENT ON COLUMN flow_skip.next_node_code IS '下一个流程节点的编码';
COMMENT ON COLUMN flow_skip.next_node_type IS '下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
COMMENT ON COLUMN flow_skip.skip_name IS '跳转名称';
COMMENT ON COLUMN flow_skip.skip_type IS '跳转类型(PASS审批通过 REJECT退回)';
COMMENT ON COLUMN flow_skip.skip_condition IS '跳转条件';
COMMENT ON COLUMN flow_skip.coordinate IS '坐标';
COMMENT ON COLUMN flow_skip.create_time IS '创建时间';
COMMENT ON COLUMN flow_skip.update_time IS '更新时间';
COMMENT ON COLUMN flow_skip.del_flag IS '删除标志';
COMMENT ON COLUMN flow_skip.tenant_id IS '租户id';
CREATE TABLE flow_instance
(
    id              int8         NOT NULL,                                -- ä¸»é”®id
    definition_id   int8         NOT NULL,                                -- å¯¹åº”flow_definition表的id
    business_id     varchar(40)  NOT NULL,                                -- ä¸šåŠ¡id
    node_type       int2         NOT NULL,                                -- èŠ‚ç‚¹ç±»åž‹ï¼ˆ0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
    node_code       varchar(40)  NOT NULL,                                -- æµç¨‹èŠ‚ç‚¹ç¼–ç 
    node_name       varchar(100) NULL,                                    -- æµç¨‹èŠ‚ç‚¹åç§°
    variable        text         NULL,                                    -- ä»»åŠ¡å˜é‡
    flow_status     varchar(20)  NOT NULL,                                -- æµç¨‹çŠ¶æ€ï¼ˆ0待提交 1审批中 2 å®¡æ‰¹é€šè¿‡ 8已完成 9已退回 10失效)
    activity_status int2         NOT NULL DEFAULT 1,                      -- æµç¨‹æ¿€æ´»çŠ¶æ€ï¼ˆ0挂起 1激活)
    create_by       varchar(64)  NULL     DEFAULT '':: character varying, -- åˆ›å»ºè€…
    create_time     timestamp    NULL,                                    -- åˆ›å»ºæ—¶é—´
    update_time     timestamp    NULL,                                    -- æ›´æ–°æ—¶é—´
    ext             varchar(500) NULL,                                    -- æ‰©å±•字段,预留给业务系统使用
    del_flag        bpchar(1) NULL DEFAULT '0':: character varying,              -- åˆ é™¤æ ‡å¿—
    tenant_id       varchar(40)  NULL,                                    -- ç§Ÿæˆ·id
    CONSTRAINT flow_instance_pkey PRIMARY KEY (id)
);
COMMENT ON TABLE flow_instance IS '流程实例表';
COMMENT ON COLUMN flow_instance.id IS '主键id';
COMMENT ON COLUMN flow_instance.definition_id IS '对应flow_definition表的id';
COMMENT ON COLUMN flow_instance.business_id IS '业务id';
COMMENT ON COLUMN flow_instance.node_type IS '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
COMMENT ON COLUMN flow_instance.node_code IS '流程节点编码';
COMMENT ON COLUMN flow_instance.node_name IS '流程节点名称';
COMMENT ON COLUMN flow_instance.variable IS '任务变量';
COMMENT ON COLUMN flow_instance.flow_status IS '流程状态(0待提交 1审批中 2 å®¡æ‰¹é€šè¿‡ 3自动通过 4终止 5作废 6撤销 7取回  8已完成 9已退回 10失效)';
COMMENT ON COLUMN flow_instance.activity_status IS '流程激活状态(0挂起 1激活)';
COMMENT ON COLUMN flow_instance.create_by IS '创建者';
COMMENT ON COLUMN flow_instance.create_time IS '创建时间';
COMMENT ON COLUMN flow_instance.update_time IS '更新时间';
COMMENT ON COLUMN flow_instance.ext IS '扩展字段,预留给业务系统使用';
COMMENT ON COLUMN flow_instance.del_flag IS '删除标志';
COMMENT ON COLUMN flow_instance.tenant_id IS '租户id';
CREATE TABLE flow_task
(
    id            int8         NOT NULL,                        -- ä¸»é”®id
    definition_id int8         NOT NULL,                        -- å¯¹åº”flow_definition表的id
    instance_id   int8         NOT NULL,                        -- å¯¹åº”flow_instance表的id
    node_code     varchar(100) NOT NULL,                        -- èŠ‚ç‚¹ç¼–ç 
    node_name     varchar(100) NULL,                            -- èŠ‚ç‚¹åç§°
    node_type     int2         NOT NULL,                        -- èŠ‚ç‚¹ç±»åž‹ï¼ˆ0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
    form_custom   bpchar(1) NULL DEFAULT 'N':: character varying, -- å®¡æ‰¹è¡¨å•是否自定义(Y是 N否)
    form_path     varchar(100) NULL,                            -- å®¡æ‰¹è¡¨å•路径
    create_time   timestamp    NULL,                            -- åˆ›å»ºæ—¶é—´
    update_time   timestamp    NULL,                            -- æ›´æ–°æ—¶é—´
    del_flag      bpchar(1) NULL DEFAULT '0':: character varying,    -- åˆ é™¤æ ‡å¿—
    tenant_id     varchar(40)  NULL,                            -- ç§Ÿæˆ·id
    CONSTRAINT flow_task_pkey PRIMARY KEY (id)
);
COMMENT ON TABLE flow_task IS '待办任务表';
COMMENT ON COLUMN flow_task.id IS '主键id';
COMMENT ON COLUMN flow_task.definition_id IS '对应flow_definition表的id';
COMMENT ON COLUMN flow_task.instance_id IS '对应flow_instance表的id';
COMMENT ON COLUMN flow_task.node_code IS '节点编码';
COMMENT ON COLUMN flow_task.node_name IS '节点名称';
COMMENT ON COLUMN flow_task.node_type IS '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
COMMENT ON COLUMN flow_task.form_custom IS '审批表单是否自定义(Y是 N否)';
COMMENT ON COLUMN flow_task.form_path IS '审批表单路径';
COMMENT ON COLUMN flow_task.create_time IS '创建时间';
COMMENT ON COLUMN flow_task.update_time IS '更新时间';
COMMENT ON COLUMN flow_task.del_flag IS '删除标志';
COMMENT ON COLUMN flow_task.tenant_id IS '租户id';
CREATE TABLE flow_his_task
(
    id               int8         NOT NULL,                     -- ä¸»é”®id
    definition_id    int8         NOT NULL,                     -- å¯¹åº”flow_definition表的id
    instance_id      int8         NOT NULL,                     -- å¯¹åº”flow_instance表的id
    task_id          int8         NOT NULL,                     -- å¯¹åº”flow_task表的id
    node_code        varchar(100) NULL,                         -- å¼€å§‹èŠ‚ç‚¹ç¼–ç 
    node_name        varchar(100) NULL,                         -- å¼€å§‹èŠ‚ç‚¹åç§°
    node_type        int2         NULL,                         -- å¼€å§‹èŠ‚ç‚¹ç±»åž‹ï¼ˆ0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)
    target_node_code varchar(100) NULL,                         -- ç›®æ ‡èŠ‚ç‚¹ç¼–ç 
    target_node_name varchar(100) NULL,                         -- ç»“束节点名称
    approver         varchar(40)  NULL,                         -- å®¡æ‰¹è€…
    cooperate_type   int2         NOT NULL DEFAULT 0,           -- åä½œæ–¹å¼(1审批 2转办 3委派 4会签 5票签 6加签 7减签)
    collaborator     varchar(40)  NULL,                         -- åä½œäºº(只有转办、会签、票签、委派)
    skip_type        varchar(10)  NULL,                         -- æµè½¬ç±»åž‹ï¼ˆPASS通过 REJECT退回 NONE无动作)
    flow_status      varchar(20)  NOT NULL,                     -- æµç¨‹çŠ¶æ€ï¼ˆ0待提交 1审批中 2 å®¡æ‰¹é€šè¿‡ 8已完成 9已退回 10失效)
    form_custom      bpchar(1) NULL DEFAULT 'N':: character varying, -- å®¡æ‰¹è¡¨å•是否自定义(Y是 N否)
    form_path        varchar(100) NULL,                         -- å®¡æ‰¹è¡¨å•路径
    ext              varchar(500) NULL,                         -- æ‰©å±•字段,预留给业务系统使用
    message          varchar(500) NULL,                         -- å®¡æ‰¹æ„è§
    create_time      timestamp    NULL,                         -- åˆ›å»ºæ—¶é—´
    update_time      timestamp    NULL,                         -- æ›´æ–°æ—¶é—´
    del_flag         bpchar(1) NULL DEFAULT '0':: character varying,    -- åˆ é™¤æ ‡å¿—
    tenant_id        varchar(40)  NULL,                         -- ç§Ÿæˆ·id
    CONSTRAINT flow_his_task_pkey PRIMARY KEY (id)
);
COMMENT ON TABLE flow_his_task IS '历史任务记录表';
COMMENT ON COLUMN flow_his_task.id IS '主键id';
COMMENT ON COLUMN flow_his_task.definition_id IS '对应flow_definition表的id';
COMMENT ON COLUMN flow_his_task.instance_id IS '对应flow_instance表的id';
COMMENT ON COLUMN flow_his_task.task_id IS '对应flow_task表的id';
COMMENT ON COLUMN flow_his_task.node_code IS '开始节点编码';
COMMENT ON COLUMN flow_his_task.node_name IS '开始节点名称';
COMMENT ON COLUMN flow_his_task.node_type IS '开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)';
COMMENT ON COLUMN flow_his_task.target_node_code IS '目标节点编码';
COMMENT ON COLUMN flow_his_task.target_node_name IS '结束节点名称';
COMMENT ON COLUMN flow_his_task.approver IS '审批者';
COMMENT ON COLUMN flow_his_task.cooperate_type IS '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)';
COMMENT ON COLUMN flow_his_task.collaborator IS '协作人';
COMMENT ON COLUMN flow_his_task.skip_type IS '流转类型(PASS通过 REJECT退回 NONE无动作)';
COMMENT ON COLUMN flow_his_task.flow_status IS '流程状态(1审批中 2 å®¡æ‰¹é€šè¿‡ 9已退回 10失效)';
COMMENT ON COLUMN flow_his_task.form_custom IS '审批表单是否自定义(Y是 N否)';
COMMENT ON COLUMN flow_his_task.form_path IS '审批表单路径';
COMMENT ON COLUMN flow_his_task.message IS '审批意见';
COMMENT ON COLUMN flow_his_task.ext IS '扩展字段,预留给业务系统使用';
COMMENT ON COLUMN flow_his_task.create_time IS '任务开始时间';
COMMENT ON COLUMN flow_his_task.update_time IS '审批完成时间';
COMMENT ON COLUMN flow_his_task.del_flag IS '删除标志';
COMMENT ON COLUMN flow_his_task.tenant_id IS '租户id';
CREATE TABLE flow_user
(
    id           int8        NOT NULL,                       -- ä¸»é”®id
    "type"       bpchar(1) NOT NULL,                         -- äººå‘˜ç±»åž‹ï¼ˆ1待办任务的审批人权限 2待办任务的转办人权限 3流程实例的抄送人权限 4待办任务的委托人权限)
    processed_by varchar(80) NULL,                           -- æƒé™äºº
    associated   int8        NOT NULL,                       -- ä»»åŠ¡è¡¨id
    create_time  timestamp   NULL,                           -- åˆ›å»ºæ—¶é—´
    create_by    varchar(80) NULL,                           -- åˆ›å»ºäºº
    update_time  timestamp   NULL,                           -- æ›´æ–°æ—¶é—´
    del_flag     bpchar(1) NULL DEFAULT '0':: character varying, -- åˆ é™¤æ ‡å¿—
    tenant_id    varchar(40) NULL,                           -- ç§Ÿæˆ·id
    CONSTRAINT flow_user_pk PRIMARY KEY (id)
);
CREATE INDEX user_processed_type ON flow_user USING btree (processed_by, type);
COMMENT ON TABLE flow_user IS '流程用户表';
COMMENT ON COLUMN flow_user.id IS '主键id';
COMMENT ON COLUMN flow_user."type" IS '人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)';
COMMENT ON COLUMN flow_user.processed_by IS '权限人';
COMMENT ON COLUMN flow_user.associated IS '任务表id';
COMMENT ON COLUMN flow_user.create_time IS '创建时间';
COMMENT ON COLUMN flow_user.create_by IS '创建人';
COMMENT ON COLUMN flow_user.update_time IS '更新时间';
COMMENT ON COLUMN flow_user.del_flag IS '删除标志';
COMMENT ON COLUMN flow_user.tenant_id IS '租户id';
-- ----------------------------
-- æµç¨‹åˆ†ç±»è¡¨
-- ----------------------------
CREATE TABLE flow_category
(
    category_id   int8         NOT NULL,
    tenant_id     VARCHAR(20)  DEFAULT '000000'::varchar,
    parent_id     int8         DEFAULT 0,
    ancestors     VARCHAR(500) DEFAULT ''::varchar,
    category_name VARCHAR(30)  NOT NULL,
    order_num     INT          DEFAULT 0,
    del_flag      CHAR         DEFAULT '0'::bpchar,
    create_dept   int8,
    create_by     int8,
    create_time   TIMESTAMP,
    update_by     int8,
    update_time   TIMESTAMP,
    PRIMARY KEY (category_id)
);
COMMENT ON TABLE flow_category IS '流程分类';
COMMENT ON COLUMN flow_category.category_id IS '流程分类ID';
COMMENT ON COLUMN flow_category.tenant_id IS '租户编号';
COMMENT ON COLUMN flow_category.parent_id IS '父流程分类id';
COMMENT ON COLUMN flow_category.ancestors IS '祖级列表';
COMMENT ON COLUMN flow_category.category_name IS '流程分类名称';
COMMENT ON COLUMN flow_category.order_num IS '显示顺序';
COMMENT ON COLUMN flow_category.del_flag IS '删除标志(0代表存在 2代表删除)';
COMMENT ON COLUMN flow_category.create_dept IS '创建部门';
COMMENT ON COLUMN flow_category.create_by IS '创建者';
COMMENT ON COLUMN flow_category.create_time IS '创建时间';
COMMENT ON COLUMN flow_category.update_by IS '更新者';
COMMENT ON COLUMN flow_category.update_time IS '更新时间';
INSERT INTO flow_category VALUES (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (102, '000000', 100, '0,100', '人事管理', 0, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (106, '000000', 101, '0,100,101', '换班', 3, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (107, '000000', 101, '0,100,101', '外出', 4, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (108, '000000', 102, '0,100,102', '转正', 1, '0', 103, 1, now(), NULL, NULL);
INSERT INTO flow_category VALUES (109, '000000', 102, '0,100,102', '离职', 2, '0', 103, 1, now(), NULL, NULL);
-- ----------------------------
-- è¯·å‡å•信息
create table test_leave
-- ----------------------------
CREATE TABLE test_leave
(
    id          bigint not null
        constraint test_leave_pk
            primary key,
    leave_type  varchar(255),
    start_date  timestamp,
    end_date    timestamp,
    leave_days  bigint,
    remark      varchar(255),
    status      varchar(255),
    create_dept bigint,
    create_by   bigint,
    create_time timestamp,
    update_by   bigint,
    update_time timestamp,
    tenant_id   varchar(20)
    id          int8         NOT NULL,
    tenant_id   VARCHAR(20)  DEFAULT '000000'::varchar,
    leave_type  VARCHAR(255) NOT NULL,
    start_date  TIMESTAMP    NOT NULL,
    end_date    TIMESTAMP    NOT NULL,
    leave_days  int2          NOT NULL,
    remark      VARCHAR(255),
    status      VARCHAR(255),
    create_dept int8,
    create_by   int8,
    create_time TIMESTAMP,
    update_by   int8,
    update_time TIMESTAMP,
    PRIMARY KEY (id)
);
comment on table test_leave is '请假申请表';
comment on column test_leave.id is '主键';
comment on column test_leave.leave_type is '请假类型';
comment on column test_leave.start_date is '开始时间';
comment on column test_leave.end_date is '结束时间';
comment on column test_leave.remark is '请假原因';
comment on column test_leave.status is '状态';
comment on column test_leave.create_dept is '创建部门';
comment on column test_leave.create_by is '创建者';
comment on column test_leave.create_time is '创建时间';
comment on column test_leave.update_by is '更新者';
comment on column test_leave.update_time is '更新时间';
comment on column test_leave.tenant_id is '租户编码';
COMMENT ON TABLE test_leave IS '请假申请表';
COMMENT ON COLUMN test_leave.id IS 'id';
COMMENT ON COLUMN test_leave.tenant_id IS '租户编号';
COMMENT ON COLUMN test_leave.leave_type IS '请假类型';
COMMENT ON COLUMN test_leave.start_date IS '开始时间';
COMMENT ON COLUMN test_leave.end_date IS '结束时间';
COMMENT ON COLUMN test_leave.leave_days IS '请假天数';
COMMENT ON COLUMN test_leave.remark IS '请假原因';
COMMENT ON COLUMN test_leave.status IS '状态';
COMMENT ON COLUMN test_leave.create_dept IS '创建部门';
COMMENT ON COLUMN test_leave.create_by IS '创建者';
COMMENT ON COLUMN test_leave.create_time IS '创建时间';
COMMENT ON COLUMN test_leave.update_by IS '更新者';
COMMENT ON COLUMN test_leave.update_time IS '更新时间';
alter table test_leave
    owner to postgres;
INSERT INTO sys_menu VALUES ('11616', '工作流', '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11623', '流程分类查询', '11622', '1', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:query', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11624', '流程分类新增', '11622', '2', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:add', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11625', '流程分类修改', '11622', '3', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:edit', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11626', '流程分类删除', '11622', '4', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:remove', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11627', '流程分类导出', '11622', '5', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:export', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11638', '请假申请', '5', '1', 'leave', 'workflow/leave/index', '', '1', '0', 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, now(), NULL, NULL, '请假申请菜单');
INSERT INTO sys_menu VALUES ('11639', '请假申请查询', '11638', '1', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11640', '请假申请新增', '11638', '2', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11641', '请假申请修改', '11638', '3', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11642', '请假申请删除', '11638', '4', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu VALUES ('11643', '请假申请导出', '11638', '5', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, now(), NULL, NULL, '');
-- æµç¨‹åˆ†ç±»ä¿¡æ¯è¡¨
create table wf_category
(
    id            bigint not null
        constraint wf_category_pk
            primary key,
    category_name varchar(255),
    category_code varchar(255),
    parent_id     bigint,
    sort_num      bigint,
    tenant_id     varchar(20),
    create_dept   bigint,
    create_by     bigint,
    create_time   timestamp,
    update_by     bigint,
    update_time   timestamp
);
INSERT INTO sys_dict_type VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, now(), NULL, NULL, '业务状态列表');
INSERT INTO sys_dict_type VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, now(), NULL, NULL, '表单类型列表');
INSERT INTO sys_dict_type VALUES (15, '000000', '任务状态', 'wf_task_status', 103, 1, now(), NULL, NULL, '任务状态');
INSERT INTO sys_dict_data VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已撤销');
INSERT INTO sys_dict_data VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, now(), NULL, NULL, '草稿');
INSERT INTO sys_dict_data VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '待审核');
INSERT INTO sys_dict_data VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, now(), NULL, NULL, '已完成');
INSERT INTO sys_dict_data VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已作废');
INSERT INTO sys_dict_data VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已退回');
INSERT INTO sys_dict_data VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已终止');
INSERT INTO sys_dict_data VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, now(), NULL, NULL, '自定义表单');
INSERT INTO sys_dict_data VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '动态表单');
INSERT INTO sys_dict_data VALUES (48, '000000', 1, '撤销', 'cancel', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '撤销');
INSERT INTO sys_dict_data VALUES (49, '000000', 2, '通过', 'pass', 'wf_task_status', '', 'success', 'N', 103, 1, now(), NULL, NULL, '通过');
INSERT INTO sys_dict_data VALUES (50, '000000', 3, '待审核', 'waiting', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '待审核');
INSERT INTO sys_dict_data VALUES (51, '000000', 4, '作废', 'invalid', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '作废');
INSERT INTO sys_dict_data VALUES (52, '000000', 5, '退回', 'back', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '退回');
INSERT INTO sys_dict_data VALUES (53, '000000', 6, '终止', 'termination', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '终止');
INSERT INTO sys_dict_data VALUES (54, '000000', 7, '转办', 'transfer', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '转办');
INSERT INTO sys_dict_data VALUES (55, '000000', 8, '委托', 'depute', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '委托');
INSERT INTO sys_dict_data VALUES (56, '000000', 9, '抄送', 'copy', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '抄送');
INSERT INTO sys_dict_data VALUES (57, '000000', 10, '加签', 'sign', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '加签');
INSERT INTO sys_dict_data VALUES (58, '000000', 11, '减签', 'sign_off', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '减签');
INSERT INTO sys_dict_data VALUES (59, '000000', 11, '超时', 'timeout', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '超时');
comment on table wf_category is '流程分类';
comment on column wf_category.id is '主键';
comment on column wf_category.category_name is '分类名称';
comment on column wf_category.category_code is '分类编码';
comment on column wf_category.parent_id is '父级id';
comment on column wf_category.sort_num is '排序';
comment on column wf_category.tenant_id is '租户id';
comment on column wf_category.create_dept is '创建部门';
comment on column wf_category.create_by is '创建者';
comment on column wf_category.create_time is '创建时间';
comment on column wf_category.update_by is '修改者';
comment on column wf_category.update_time is '修改时间';
alter table wf_category
    owner to postgres;
create unique index uni_category_code
    on wf_category (category_code);
INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, now(), 1, now());
create table wf_task_back_node
(
    id            bigint not null
        constraint pk_wf_task_back_node
        primary key,
    node_id       varchar(255) not null,
    node_name     varchar(255) not null,
    order_no      bigint not null,
    instance_id   varchar(255) not null,
    task_type     varchar(255) not null,
    assignee      varchar(2000) not null,
    tenant_id     varchar(20),
    create_dept   bigint,
    create_by     bigint,
    create_time   timestamp,
    update_by     bigint,
    update_time   timestamp
);
comment on table wf_task_back_node is '节点审批记录';
comment on column wf_task_back_node.id is '主键';
comment on column wf_task_back_node.node_id is '节点id';
comment on column wf_task_back_node.node_name is '节点名称';
comment on column wf_task_back_node.order_no is '排序';
comment on column wf_task_back_node.instance_id is '流程实例id';
comment on column wf_task_back_node.task_type is '节点类型';
comment on column wf_task_back_node.assignee is '审批人';
comment on column wf_task_back_node.tenant_id is '租户id';
comment on column wf_task_back_node.create_dept is '创建部门';
comment on column wf_task_back_node.create_by is '创建者';
comment on column wf_task_back_node.create_time is '创建时间';
comment on column wf_task_back_node.update_by is '修改者';
comment on column wf_task_back_node.update_time is '修改时间';
alter table wf_task_back_node
    owner to postgres;
create table wf_definition_config
(
    id            bigint not null
        constraint pk_wf_definition_config
        primary key,
    table_name    varchar(255) not null,
    definition_id varchar(255) not null,
    process_key   varchar(255) not null,
    version       bigint       not null,
    tenant_id     varchar(20),
    remark        varchar(500),
    create_dept   bigint,
    create_by     bigint,
    create_time   timestamp,
    update_by     bigint,
    update_time   timestamp
);
comment on table wf_definition_config is '流程定义配置';
comment on column wf_definition_config.id is '主键';
comment on column wf_definition_config.table_name is '表名';
comment on column wf_definition_config.definition_id is '流程定义ID';
comment on column wf_definition_config.process_key is '流程KEY';
comment on column wf_definition_config.version is '流程版本';
comment on column wf_definition_config.tenant_id is '租户id';
comment on column wf_definition_config.remark is '备注';
comment on column wf_definition_config.create_dept is '创建部门';
comment on column wf_definition_config.create_by is '创建者';
comment on column wf_definition_config.create_time is '创建时间';
comment on column wf_definition_config.update_by is '修改者';
comment on column wf_definition_config.update_time is '修改时间';
alter table wf_definition_config
    owner to postgres;
create unique index uni_definition_id
    on wf_definition_config (definition_id);
create table wf_form_manage
(
    id            bigint not null
        constraint pk_wf_form_manage
        primary key,
    form_name     varchar(255) not null,
    form_type     varchar(255) not null,
    router        varchar(255) not null,
    remark        varchar(500),
    tenant_id     varchar(20),
    create_dept   bigint,
    create_by     bigint,
    create_time   timestamp,
    update_by     bigint,
    update_time   timestamp
);
comment on table wf_form_manage is '表单管理';
comment on column wf_form_manage.id is '主键';
comment on column wf_form_manage.form_name is '表单名称';
comment on column wf_form_manage.form_type is '表单类型';
comment on column wf_form_manage.router is '路由地址/表单ID';
comment on column wf_form_manage.remark is '备注';
comment on column wf_form_manage.tenant_id is '租户id';
comment on column wf_form_manage.create_dept is '创建部门';
comment on column wf_form_manage.create_by is '创建者';
comment on column wf_form_manage.create_time is '创建时间';
comment on column wf_form_manage.update_by is '修改者';
comment on column wf_form_manage.update_time is '修改时间';
insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, now(), 1, now());
create table wf_node_config
(
    id               bigint not null
        constraint pk_wf_node_config
            primary key,
    form_id          bigint,
    form_type        varchar(255),
    node_name        varchar(255) not null,
    node_id          varchar(255) not null,
    definition_id    varchar(255) not null,
    apply_user_task  char(1) default '0',
    tenant_id        varchar(20),
    create_dept      bigint,
    create_by        bigint,
    create_time      timestamp,
    update_by        bigint,
    update_time      timestamp
);
comment on table wf_node_config is '节点配置';
comment on column wf_node_config.id is '主键';
comment on column wf_node_config.form_id is '表单id';
comment on column wf_node_config.form_type is '表单类型';
comment on column wf_node_config.node_id is '节点id';
comment on column wf_node_config.node_name is '节点名称';
comment on column wf_node_config.definition_id is '流程定义id';
comment on column wf_node_config.apply_user_task is '是否为申请人节点 ï¼ˆ0是 1否)';
comment on column wf_node_config.tenant_id is '租户id';
comment on column wf_node_config.create_dept is '创建部门';
comment on column wf_node_config.create_by is '创建者';
comment on column wf_node_config.create_time is '创建时间';
comment on column wf_node_config.update_by is '修改者';
comment on column wf_node_config.update_time is '修改时间';
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, now(), NULL, NULL, '请假申请菜单');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, now(), NULL, NULL, '');
INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, now(), NULL, NULL, '业务状态列表');
INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, now(), NULL, NULL, '表单类型列表');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已撤销');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, now(), NULL, NULL, '草稿');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1,now(), NULL, NULL, '待审核');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, now(), NULL, NULL, '已完成');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已作废');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已退回');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1,now(), NULL, NULL, '已终止');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, now(), NULL, NULL, '自定义表单');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '动态表单');
-- è¡¨å•管理 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11628, '表单管理', '11616', '5', 'formManage', 'workflow/formManage/index', 1, 0, 'C', '0', '0', 'workflow:formManage:list', 'tree-table', 103, 1, now(), null, null, '表单管理菜单');
-- è¡¨å•管理按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11644, '表单管理查询', 11628, '1',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:query',        '', 103, 1, now(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11645, '表单管理新增', 11628, '2',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:add',          '', 103, 1, now(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11646, '表单管理修改', 11628, '3',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:edit',         '', 103, 1, now(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11647, '表单管理删除', 11628, '4',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:remove',       '', 103, 1, now(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11648, '表单管理导出', 11628, '5',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:export',       'tree-table', 103, 1, now(), null, null, '');
script/sql/ry_workflow.sql
@@ -1,176 +1,251 @@
insert into sys_menu values('11616', '工作流'  , '0',    '6', 'workflow',          '',                                 '', '1', '0', 'M', '0', '0', '',                       'workflow', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11617', '模型管理', '11616', '2', 'model',             'workflow/model/index',             '', '1', '1', 'C', '0', '0', 'workflow:model:list',    'model', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11618', '我的任务', '0', '7', 'task',              '',                                 '', '1', '0', 'M', '0', '0', '',                       'my-task', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11619', '我的待办', '11618', '2', 'taskWaiting',       'workflow/task/taskWaiting',              '', '1', '1', 'C', '0', '0', '',                       'waiting', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11632', '我的已办', '11618', '3', 'taskFinish',       'workflow/task/taskFinish',              '', '1', '1', 'C', '0', '0', '',                       'finish', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11633', '我的抄送', '11618', '4', 'taskCopyList',       'workflow/task/taskCopyList',              '', '1', '1', 'C', '0', '0', '',                       'my-copy', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '',                       'process-definition', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11621', '流程实例', '11630', '1', 'processInstance',   'workflow/processInstance/index',   '', '1', '1', 'C', '0', '0', '',                       'tree-table', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11622', '流程分类', '11616', '1', 'category',          'workflow/category/index',          '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11629', '我发起的', '11618', '1', 'myDocument',        'workflow/task/myDocument',         '', '1', '1', 'C', '0', '0', '',                       'guide', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11630', '流程监控', '11616', '4', 'monitor',           '',                                 '', '1', '0', 'M', '0', '0', '',                       'monitor', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values('11631', '待办任务', '11630', '2', 'allTaskWaiting',    'workflow/task/allTaskWaiting',     '', '1', '1', 'C', '0', '0', '',                       'waiting', 103, 1, sysdate(), NULL, NULL, '');
-- ----------------------------
-- 0、warm-flow-all.sql,地址:https://gitee.com/dromara/warm-flow/blob/master/sql/mysql/warm-flow-all.sql
-- ----------------------------
CREATE TABLE `flow_definition`
(
    `id`          bigint unsigned NOT NULL COMMENT '主键id',
    `flow_code`   varchar(40)  NOT NULL COMMENT '流程编码',
    `flow_name`   varchar(100) NOT NULL COMMENT '流程名称',
    `category`   varchar(100) DEFAULT NULL COMMENT '流程类别',
    `version`     varchar(20)  NOT NULL COMMENT '流程版本',
    `is_publish`  tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否发布(0未发布 1已发布 9失效)',
    `form_custom` char(1)      DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)',
    `form_path`   varchar(100) DEFAULT NULL COMMENT '审批表单路径',
    `activity_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '流程激活状态(0挂起 1激活)',
    `listener_type`   varchar(100) DEFAULT NULL COMMENT '监听器类型',
    `listener_path`   varchar(400) DEFAULT NULL COMMENT '监听器路径',
    `ext`         varchar(500) DEFAULT NULL COMMENT '业务详情 å­˜ä¸šåŠ¡è¡¨å¯¹è±¡json字符串',
    `create_time` datetime     DEFAULT NULL COMMENT '创建时间',
    `update_time` datetime     DEFAULT NULL COMMENT '更新时间',
    `del_flag`    char(1)      DEFAULT '0' COMMENT '删除标志',
    `tenant_id` varchar(40)  DEFAULT NULL COMMENT '租户id',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  COMMENT='流程定义表';
CREATE TABLE `flow_node`
(
    `id`              bigint unsigned NOT NULL COMMENT '主键id',
    `node_type`       tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
    `definition_id`   bigint       NOT NULL COMMENT '流程定义id',
    `node_code`       varchar(100) NOT NULL COMMENT '流程节点编码',
    `node_name`       varchar(100) DEFAULT NULL COMMENT '流程节点名称',
    `permission_flag` varchar(200) DEFAULT NULL COMMENT '权限标识(权限类型:权限标识,可以多个,用逗号隔开)',
    `node_ratio`      DECIMAL(6,3) DEFAULT NULL COMMENT '流程签署比例值',
    `coordinate`      varchar(100) DEFAULT NULL COMMENT '坐标',
    `skip_any_node`   varchar(100) DEFAULT 'N' COMMENT '是否可以退回任意节点(Y是 N否)即将删除',
    `any_node_skip`   varchar(100) DEFAULT NULL COMMENT '任意结点跳转',
    `listener_type`   varchar(100) DEFAULT NULL COMMENT '监听器类型',
    `listener_path`   varchar(400) DEFAULT NULL COMMENT '监听器路径',
    `handler_type`    varchar(100)  DEFAULT NULL COMMENT '处理器类型',
    `handler_path`    varchar(400)  DEFAULT NULL COMMENT '处理器路径',
    `form_custom`     char(1)      DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)',
    `form_path`       varchar(100) DEFAULT NULL COMMENT '审批表单路径',
    `version`         varchar(20)  NOT NULL COMMENT '版本',
    `create_time`     datetime     DEFAULT NULL COMMENT '创建时间',
    `update_time`     datetime     DEFAULT NULL COMMENT '更新时间',
    `del_flag`        char(1)      DEFAULT '0' COMMENT '删除标志',
    `tenant_id`       varchar(40)  DEFAULT NULL COMMENT '租户id',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  COMMENT='流程节点表';
CREATE TABLE `flow_skip`
(
    `id`             bigint unsigned NOT NULL COMMENT '主键id',
    `definition_id`  bigint       NOT NULL COMMENT '流程定义id',
    `now_node_code`  varchar(100) NOT NULL COMMENT '当前流程节点的编码',
    `now_node_type`  tinyint(1) DEFAULT NULL COMMENT '当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
    `next_node_code` varchar(100) NOT NULL COMMENT '下一个流程节点的编码',
    `next_node_type` tinyint(1) DEFAULT NULL COMMENT '下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
    `skip_name`      varchar(100) DEFAULT NULL COMMENT '跳转名称',
    `skip_type`      varchar(40)  DEFAULT NULL COMMENT '跳转类型(PASS审批通过 REJECT退回)',
    `skip_condition` varchar(200) DEFAULT NULL COMMENT '跳转条件',
    `coordinate`     varchar(100) DEFAULT NULL COMMENT '坐标',
    `create_time`    datetime     DEFAULT NULL COMMENT '创建时间',
    `update_time`    datetime     DEFAULT NULL COMMENT '更新时间',
    `del_flag`    char(1)      DEFAULT '0' COMMENT '删除标志',
    `tenant_id`     varchar(40)  DEFAULT NULL COMMENT '租户id',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  COMMENT='节点跳转关联表';
CREATE TABLE `flow_instance`
(
    `id`            bigint      NOT NULL COMMENT '主键id',
    `definition_id` bigint      NOT NULL COMMENT '对应flow_definition表的id',
    `business_id`   varchar(40) NOT NULL COMMENT '业务id',
    `node_type`     tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
    `node_code`     varchar(40) NOT NULL COMMENT '流程节点编码',
    `node_name`     varchar(100) DEFAULT NULL COMMENT '流程节点名称',
    `variable`      text COMMENT '任务变量',
    `flow_status`   varchar(20) NOT NULL COMMENT '流程状态(0待提交 1审批中 2 å®¡æ‰¹é€šè¿‡ 3自动通过 4终止 5作废 6撤销 7取回  8已完成 9已退回 10失效)',
    `activity_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '流程激活状态(0挂起 1激活)',
    `create_by`     varchar(64)  DEFAULT '' COMMENT '创建者',
    `create_time`   datetime     DEFAULT NULL COMMENT '创建时间',
    `update_time`   datetime     DEFAULT NULL COMMENT '更新时间',
    `ext`           varchar(500) DEFAULT NULL COMMENT '扩展字段,预留给业务系统使用',
    `del_flag`    char(1)      DEFAULT '0' COMMENT '删除标志',
    `tenant_id`     varchar(40)  DEFAULT NULL COMMENT '租户id',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  COMMENT='流程实例表';
CREATE TABLE `flow_task`
(
    `id`              bigint       NOT NULL COMMENT '主键id',
    `definition_id`   bigint       NOT NULL COMMENT '对应flow_definition表的id',
    `instance_id`     bigint       NOT NULL COMMENT '对应flow_instance表的id',
    `node_code`       varchar(100) NOT NULL COMMENT '节点编码',
    `node_name`       varchar(100) DEFAULT NULL COMMENT '节点名称',
    `node_type`       tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
    `form_custom`     char(1)      DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)',
    `form_path`       varchar(100) DEFAULT NULL COMMENT '审批表单路径',
    `create_time`     datetime     DEFAULT NULL COMMENT '创建时间',
    `update_time`     datetime     DEFAULT NULL COMMENT '更新时间',
    `del_flag`        char(1)      DEFAULT '0' COMMENT '删除标志',
    `tenant_id`       varchar(40)  DEFAULT NULL COMMENT '租户id',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  COMMENT='待办任务表';
CREATE TABLE `flow_his_task`
(
    `id`               bigint(20) unsigned NOT NULL COMMENT '主键id',
    `definition_id`    bigint(20)          NOT NULL COMMENT '对应flow_definition表的id',
    `instance_id`      bigint(20)          NOT NULL COMMENT '对应flow_instance表的id',
    `task_id`          bigint(20)          NOT NULL COMMENT '对应flow_task表的id',
    `node_code`        varchar(100)                 DEFAULT NULL COMMENT '开始节点编码',
    `node_name`        varchar(100)                 DEFAULT NULL COMMENT '开始节点名称',
    `node_type`        tinyint(1)                   DEFAULT NULL COMMENT '开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
    `target_node_code` varchar(100)                 DEFAULT NULL COMMENT '目标节点编码',
    `target_node_name` varchar(100)                 DEFAULT NULL COMMENT '结束节点名称',
    `approver`         varchar(40)                  DEFAULT NULL COMMENT '审批者',
    `cooperate_type`   tinyint(1)          NOT NULL DEFAULT '0' COMMENT '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)',
    `collaborator`     varchar(40)                  DEFAULT NULL COMMENT '协作人',
    `skip_type`        varchar(10)          NOT NULL COMMENT '流转类型(PASS通过 REJECT退回 NONE无动作)',
    `flow_status`      varchar(20)          NOT NULL COMMENT '流程状态(1审批中 2 å®¡æ‰¹é€šè¿‡ 9已退回 10失效)',
    `form_custom`      char(1)      DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)',
    `form_path`        varchar(100) DEFAULT NULL COMMENT '审批表单路径',
    `message`          varchar(500)                 DEFAULT NULL COMMENT '审批意见',
    `ext`              varchar(500)                 DEFAULT NULL COMMENT '业务详情 å­˜ä¸šåŠ¡è¡¨å¯¹è±¡json字符串',
    `create_time`      datetime                     DEFAULT NULL COMMENT '任务开始时间',
    `update_time`      datetime                     DEFAULT NULL COMMENT '审批完成时间',
    `del_flag`         char(1)                      DEFAULT '0' COMMENT '删除标志',
    `tenant_id`        varchar(40)                  DEFAULT NULL COMMENT '租户id',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB  COMMENT ='历史任务记录表';
-- æµç¨‹åˆ†ç±»ç®¡ç†ç›¸å…³æŒ‰é’®
insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add',   '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit',  '#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove','#', 103, 1, sysdate(), null, null, '');
insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export','#', 103, 1, sysdate(), null, null, '');
CREATE TABLE `flow_user`
(
    `id`              bigint unsigned NOT NULL COMMENT '主键id',
    `type`            char(1)  NOT NULL COMMENT '人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)',
    `processed_by`    varchar(80) DEFAULT NULL COMMENT '权限人',
    `associated`      bigint NOT NULL COMMENT '任务表id',
    `create_time`     datetime     DEFAULT NULL COMMENT '创建时间',
    `create_by`       varchar(80) DEFAULT NULL COMMENT '创建人',
    `update_time`     datetime     DEFAULT NULL COMMENT '更新时间',
    `del_flag`        char(1)      DEFAULT '0' COMMENT '删除标志',
    `tenant_id`       varchar(40)  DEFAULT NULL COMMENT '租户id',
    PRIMARY KEY (`id`) USING BTREE,
    KEY `user_processed_type` (`processed_by`,`type`)
) ENGINE=InnoDB  COMMENT='流程用户表';
-- ----------------------------
-- æµç¨‹åˆ†ç±»è¡¨
-- ----------------------------
create table flow_category
(
    category_id   bigint(20)  not null comment '流程分类ID',
    tenant_id     varchar(20)  default '000000' comment '租户编号',
    parent_id     bigint(20)   default 0 comment '父流程分类id',
    ancestors     varchar(500) default '' comment '祖级列表',
    category_name varchar(30) not null comment '流程分类名称',
    order_num     int(4)       default 0 comment '显示顺序',
    del_flag      char(1)      default '0' comment '删除标志(0代表存在 2代表删除)',
    create_dept   bigint(20)  null comment '创建部门',
    create_by     bigint(20)  null comment '创建者',
    create_time   datetime    null comment '创建时间',
    update_by     bigint(20)  null comment '更新者',
    update_time   datetime    null comment '更新时间',
    primary key (category_id)
) engine = innodb comment = '流程分类';
INSERT INTO flow_category values (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (102, '000000', 100, '0,100', '人事管理', 0, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (106, '000000', 101, '0,100,101', '换班', 3, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (107, '000000', 101, '0,100,101', '外出', 4, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (108, '000000', 102, '0,100,102', '转正', 1, '0', 103, 1, sysdate(), null, null);
INSERT INTO flow_category values (109, '000000', 102, '0,100,102', '离职', 2, '0', 103, 1, sysdate(), null, null);
-- ----------------------------
-- è¯·å‡å•信息
-- ----------------------------
create table test_leave
(
    id          bigint                       not null comment '主键',
    leave_type  varchar(255)                 not null comment '请假类型',
    start_date   datetime                     not null comment '开始时间',
    end_date     datetime                     not null comment '结束时间',
    leave_days  int(10)                      not null comment '请假天数',
    remark      varchar(255)                 null comment '请假原因',
    status      varchar(255)                 null comment '状态',
    create_dept bigint                       null comment '创建部门',
    create_by   bigint                       null comment '创建者',
    create_time datetime                     null comment '创建时间',
    update_by   bigint                       null comment '更新者',
    update_time datetime                     null comment '更新时间',
    tenant_id   varchar(20)                  null comment '租户编号',
    PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB COMMENT = '请假申请表';
-- æµç¨‹åˆ†ç±»ä¿¡æ¯è¡¨
create table wf_category
(
    id            bigint                       not null comment '主键'
        primary key,
    category_name varchar(255)                 null comment '分类名称',
    category_code varchar(255)                 null comment '分类编码',
    parent_id     bigint                       null comment '父级id',
    sort_num      int(19)                      null comment '排序',
    tenant_id     varchar(20)                  null comment '租户编号',
    create_dept   bigint                       null comment '创建部门',
    create_by     bigint                       null comment '创建者',
    create_time   datetime                     null comment '创建时间',
    update_by     bigint                       null comment '更新者',
    update_time   datetime                     null comment '更新时间',
    constraint uni_category_code
        unique (category_code)
) engine=innodb comment= '流程分类';
INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, sysdate(), 1, sysdate());
create table wf_task_back_node
(
    id          bigint                       not null
        primary key,
    node_id     varchar(255)                 not null comment '节点id',
    node_name   varchar(255)                 not null comment '节点名称',
    order_no    int                          not null comment '排序',
    instance_id varchar(255)                 null comment '流程实例id',
    task_type   varchar(255)                 not null comment '节点类型',
    assignee    varchar(2000)                not null comment '审批人',
    tenant_id   varchar(20)                  null comment '租户编号',
    create_dept bigint                       null comment '创建部门',
    create_by   bigint                       null comment '创建者',
    create_time datetime                     null comment '创建时间',
    update_by   bigint                       null comment '更新者',
    update_time datetime                     null comment '更新时间'
)
    comment '节点审批记录';
create table wf_definition_config
(
    id            bigint                        not null comment '主键'
        primary key,
    table_name    varchar(255)                  not null comment '表名',
    definition_id varchar(255)                  not null comment '流程定义ID',
    process_key   varchar(255)                  not null comment '流程KEY',
    version       int(10)                       not null comment '流程版本',
    create_dept   bigint                        null comment '创建部门',
    create_by     bigint                        null comment '创建者',
    create_time   datetime                      null comment '创建时间',
    update_by     bigint                        null comment '更新者',
    update_time   datetime                      null comment '更新时间',
    remark        varchar(500) default ''       null comment '备注',
    tenant_id     varchar(20)                   null comment '租户编号',
    constraint uni_definition_id
        unique (definition_id)
)
    comment '流程定义配置';
create table wf_form_manage
(
    id          bigint       not null comment '主键'
        primary key,
    form_name   varchar(255) not null comment '表单名称',
    form_type   varchar(255) not null comment '表单类型',
    router      varchar(255) not null comment '路由地址/表单ID',
    remark      varchar(500) null comment '备注',
    tenant_id   varchar(20)  null comment '租户编号',
    id          bigint(20)   not null comment 'id',
    tenant_id   varchar(20) default '000000' comment '租户编号',
    leave_type  varchar(255) not null comment '请假类型',
    start_date  datetime     not null comment '开始时间',
    end_date    datetime     not null comment '结束时间',
    leave_days  int(10)      not null comment '请假天数',
    remark      varchar(255) null comment '请假原因',
    status      varchar(255) null comment '状态',
    create_dept bigint       null comment '创建部门',
    create_by   bigint       null comment '创建者',
    create_time datetime     null comment '创建时间',
    update_by   bigint       null comment '更新者',
    update_time datetime     null comment '更新时间'
)
    comment '表单管理';
    update_time datetime     null comment '更新时间',
    PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB COMMENT = '请假申请表';
insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, sysdate(), 1, sysdate());
insert into sys_menu values ('11616', '工作流', '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, sysdate(),NULL, NULL, '');
insert into sys_menu values ('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu values ('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, sysdate(), NULL, NULL, '');
-- æµç¨‹åˆ†ç±»ç®¡ç†ç›¸å…³æŒ‰é’®
insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1,sysdate(), null, null, '');
insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add', '#', 103, 1,sysdate(), null, null, '');
insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit', '#', 103, 1,sysdate(), null, null, '');
insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove', '#', 103,1, sysdate(), null, null, '');
insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export', '#', 103,1, sysdate(), null, null, '');
-- è¯·å‡æµ‹è¯•相关按钮
insert into sys_menu VALUES (11638, '请假申请',     5,    1, 'leave', 'workflow/leave/index', '', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, sysdate(), NULL, NULL, '请假申请菜单');
insert into sys_menu VALUES (11639, '请假申请查询', 11638, 1, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu VALUES (11640, '请假申请新增', 11638, 2, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu VALUES (11641, '请假申请修改', 11638, 3, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu VALUES (11642, '请假申请删除', 11638, 4, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, sysdate(), NULL, NULL, '');
insert into sys_menu VALUES (11643, '请假申请导出', 11638, 5, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, sysdate(), NULL, NULL, '');
create table wf_node_config
(
    id               bigint       not null comment '主键'
        primary key,
    form_id          bigint       null comment '表单id',
    form_type        varchar(255) null comment '表单类型',
    node_name        varchar(255) not null comment '节点名称',
    node_id          varchar(255) not null comment '节点id',
    definition_id    varchar(255) not null comment '流程定义id',
    apply_user_task  char(1)      default '0'     comment '是否为申请人节点 ï¼ˆ0是 1否)',
    create_dept      bigint       null comment '创建部门',
    create_by        bigint       null comment '创建者',
    create_time      datetime     null comment '创建时间',
    update_by        bigint       null comment '更新者',
    update_time      datetime     null comment '更新时间',
    tenant_id        varchar(20)  null comment '租户编号'
)
    comment '节点配置';
INSERT INTO sys_dict_type VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, sysdate(), NULL, NULL, '业务状态列表');
INSERT INTO sys_dict_type VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, sysdate(), NULL, NULL, '表单类型列表');
INSERT INTO sys_dict_type VALUES (15, '000000', '任务状态', 'wf_task_status', 103, 1, sysdate(), NULL, NULL, '任务状态');
INSERT INTO sys_dict_data VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL,'已撤销');
INSERT INTO sys_dict_data VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, sysdate(), NULL, NULL, '草稿');
INSERT INTO sys_dict_data VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL,'待审核');
INSERT INTO sys_dict_data VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL,'已完成');
INSERT INTO sys_dict_data VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL,'已作废');
INSERT INTO sys_dict_data VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL,'已退回');
INSERT INTO sys_dict_data VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL,NULL, '已终止');
INSERT INTO sys_dict_data VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL,'自定义表单');
INSERT INTO sys_dict_data VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL,'动态表单');
INSERT INTO sys_dict_data VALUES (48, '000000', 1, '撤销', 'cancel', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '撤销');
INSERT INTO sys_dict_data VALUES (49, '000000', 2, '通过', 'pass', 'wf_task_status', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL, '通过');
INSERT INTO sys_dict_data VALUES (50, '000000', 3, '待审核', 'waiting', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '待审核');
INSERT INTO sys_dict_data VALUES (51, '000000', 4, '作废', 'invalid', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '作废');
INSERT INTO sys_dict_data VALUES (52, '000000', 5, '退回', 'back', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '退回');
INSERT INTO sys_dict_data VALUES (53, '000000', 6, '终止', 'termination', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '终止');
INSERT INTO sys_dict_data VALUES (54, '000000', 7, '转办', 'transfer', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '转办');
INSERT INTO sys_dict_data VALUES (55, '000000', 8, '委托', 'depute', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '委托');
INSERT INTO sys_dict_data VALUES (56, '000000', 9, '抄送', 'copy', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '抄送');
INSERT INTO sys_dict_data VALUES (57, '000000', 10, '加签', 'sign', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '加签');
INSERT INTO sys_dict_data VALUES (58, '000000', 11, '减签', 'sign_off', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '减签');
INSERT INTO sys_dict_data VALUES (59, '000000', 11, '超时', 'timeout', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '超时');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, sysdate(), NULL, NULL, '请假申请菜单');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, sysdate(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, sysdate(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, sysdate(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, sysdate(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, sysdate(), NULL, NULL, '');
INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, sysdate(), NULL, NULL, '业务状态列表');
INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, sysdate(), NULL, NULL, '表单类型列表');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '已撤销');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, sysdate(), NULL, NULL, '草稿');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1,sysdate(), NULL, NULL, '待审核');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL, '已完成');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '已作废');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '已退回');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1,sysdate(), NULL, NULL, '已终止');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL, '自定义表单');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '动态表单');
-- è¡¨å•管理 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11628, '表单管理', '11616', '5', 'formManage', 'workflow/formManage/index', 1, 0, 'C', '0', '0', 'workflow:formManage:list', 'tree-table', 103, 1, sysdate(), null, null, '表单管理菜单');
-- è¡¨å•管理按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11644, '表单管理查询', 11628, '1',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:query',        '', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11645, '表单管理新增', 11628, '2',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:add',          '', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11646, '表单管理修改', 11628, '3',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:edit',         '', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11647, '表单管理删除', 11628, '4',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:remove',       '', 103, 1, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11648, '表单管理导出', 11628, '5',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:export',       'tree-table', 103, 1, sysdate(), null, null, '');
script/sql/sqlserver/sqlserver_ry_vue_5.X.sql
@@ -210,7 +210,11 @@
    'TABLE', N'sys_social',
    'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
    'MS_Description', N'社会化关系表',
    'SCHEMA', N'dbo',
    'TABLE', N'sys_social'
GO
CREATE TABLE sys_tenant
(
script/sql/sqlserver/sqlserver_ry_workflow.sql
@@ -1,456 +1,1320 @@
insert into sys_menu values('11616', '工作流'  , '0',    '6', 'workflow',          '',                                 '', '1', '0', 'M', '0', '0', '',                       'workflow', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11617', '模型管理', '11616', '2', 'model',             'workflow/model/index',             '', '1', '1', 'C', '0', '0', 'workflow:model:list',    'model', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11618', '我的任务', '0', '7', 'task',              '',                                 '', '1', '0', 'M', '0', '0', '',                       'my-task', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11619', '我的待办', '11618', '2', 'taskWaiting',       'workflow/task/taskWaiting',              '', '1', '1', 'C', '0', '0', '',                       'waiting', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11632', '我的已办', '11618', '3', 'taskFinish',       'workflow/task/taskFinish',              '', '1', '1', 'C', '0', '0', '',                       'finish', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11633', '我的抄送', '11618', '4', 'taskCopyList',       'workflow/task/taskCopyList',              '', '1', '1', 'C', '0', '0', '',                       'my-copy', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '',                       'process-definition', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11621', '流程实例', '11630', '1', 'processInstance',   'workflow/processInstance/index',   '', '1', '1', 'C', '0', '0', '',                       'tree-table', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11622', '流程分类', '11616', '1', 'category',          'workflow/category/index',          '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11629', '我发起的', '11618', '1', 'myDocument',        'workflow/task/myDocument',         '', '1', '1', 'C', '0', '0', '',                       'guide', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11630', '流程监控', '11616', '4', 'monitor',           '',                                 '', '1', '0', 'M', '0', '0', '',                       'monitor', 103, 1, getdate(), NULL, NULL, '');
insert into sys_menu values('11631', '待办任务', '11630', '2', 'allTaskWaiting',    'workflow/task/allTaskWaiting',     '', '1', '1', 'C', '0', '0', '',                       'waiting', 103, 1, getdate(), NULL, NULL, '');
CREATE TABLE flow_definition (
    id bigint NOT NULL,
    flow_code nvarchar(40) NOT NULL,
    flow_name nvarchar(100) NOT NULL,
    category nvarchar(100) NULL,
    version nvarchar(20) NOT NULL,
    is_publish tinyint DEFAULT('0') NULL,
    form_custom nchar(1) DEFAULT('N') NULL,
    form_path nvarchar(100) NULL,
    activity_status tinyint DEFAULT('1') NULL,
    listener_type nvarchar(100) NULL,
    listener_path nvarchar(400) NULL,
    ext nvarchar(500) NULL,
    create_time datetime2(7)  NULL,
    update_time datetime2(7)  NULL,
    del_flag nchar(1) DEFAULT('0') NULL,
    tenant_id nvarchar(40) NULL,
    CONSTRAINT PK__flow_def__3213E83FEE39AE33 PRIMARY KEY CLUSTERED (id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'主键id',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程编码',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'flow_code'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程名称',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'flow_name'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程类别',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'category'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程版本',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'version'
GO
EXEC sp_addextendedproperty
'MS_Description', N'是否发布(0未发布 1已发布 9失效)',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'is_publish'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批表单是否自定义(Y是 N否)',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'form_custom'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批表单路径',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'form_path'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程激活状态(0挂起 1激活)',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'activity_status'
GO
EXEC sp_addextendedproperty
'MS_Description', N'监听器类型',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'listener_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'监听器路径',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'listener_path'
GO
EXEC sp_addextendedproperty
'MS_Description', N'业务详情 å­˜ä¸šåŠ¡è¡¨å¯¹è±¡json字符串',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'ext'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'删除标志',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'del_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户id',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程定义表',
'SCHEMA', N'dbo',
'TABLE', N'flow_definition'
GO
CREATE TABLE flow_node (
    id bigint NOT NULL,
    node_type tinyint NOT NULL,
    definition_id bigint NOT NULL,
    node_code nvarchar(100) NOT NULL,
    node_name nvarchar(100) NULL,
    permission_flag nvarchar(200) NULL,
    node_ratio decimal(6,3)  NULL,
    coordinate nvarchar(100) NULL,
    skip_any_node nvarchar(100) DEFAULT('N') NULL,
    any_node_skip nvarchar(100) NULL,
    listener_type nvarchar(100) NULL,
    listener_path nvarchar(400) NULL,
    handler_type nvarchar(100) NULL,
    handler_path nvarchar(400) NULL,
    form_custom nchar(1) DEFAULT('N') NULL,
    form_path nvarchar(100) NULL,
    version nvarchar(20) NOT NULL,
    create_time datetime2(7)  NULL,
    update_time datetime2(7)  NULL,
    del_flag nchar(1) DEFAULT('0') NULL,
    tenant_id nvarchar(40) NULL,
    CONSTRAINT PK__flow_nod__3213E83F372470DE PRIMARY KEY CLUSTERED (id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'主键id',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'node_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程定义id',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'definition_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程节点编码',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'node_code'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程节点名称',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'node_name'
GO
EXEC sp_addextendedproperty
'MS_Description', N'权限标识(权限类型:权限标识,可以多个,用逗号隔开)',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'permission_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程签署比例值',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'node_ratio'
GO
EXEC sp_addextendedproperty
'MS_Description', N'坐标',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'coordinate'
GO
EXEC sp_addextendedproperty
'MS_Description', N'是否可以退回任意节点(Y是 N否)即将删除',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'skip_any_node'
GO
EXEC sp_addextendedproperty
'MS_Description', N'任意结点跳转',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'any_node_skip'
GO
EXEC sp_addextendedproperty
'MS_Description', N'监听器类型',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'listener_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'监听器路径',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'listener_path'
GO
EXEC sp_addextendedproperty
'MS_Description', N'处理器类型',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'handler_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'处理器路径',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'handler_path'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批表单是否自定义(Y是 N否)',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'form_custom'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批表单路径',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'form_path'
GO
EXEC sp_addextendedproperty
'MS_Description', N'版本',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'version'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'删除标志',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'del_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户id',
'SCHEMA', N'dbo',
'TABLE', N'flow_node',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程节点表',
'SCHEMA', N'dbo',
'TABLE', N'flow_node'
GO
CREATE TABLE flow_skip (
    id bigint NOT NULL,
    definition_id bigint NOT NULL,
    now_node_code nvarchar(100) NOT NULL,
    now_node_type tinyint  NULL,
    next_node_code nvarchar(100) NOT NULL,
    next_node_type tinyint  NULL,
    skip_name nvarchar(100) NULL,
    skip_type nvarchar(40) NULL,
    skip_condition nvarchar(200) NULL,
    coordinate nvarchar(100) NULL,
    create_time datetime2(7)  NULL,
    update_time datetime2(7)  NULL,
    del_flag nchar(1) DEFAULT('0') NULL,
    tenant_id nvarchar(40) NULL,
    CONSTRAINT PK__flow_ski__3213E83F073FEE6E PRIMARY KEY CLUSTERED (id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'主键id',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程定义id',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'definition_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'当前流程节点的编码',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'now_node_code'
GO
EXEC sp_addextendedproperty
'MS_Description', N'当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'now_node_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'下一个流程节点的编码',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'next_node_code'
GO
EXEC sp_addextendedproperty
'MS_Description', N'下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'next_node_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'跳转名称',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'skip_name'
GO
EXEC sp_addextendedproperty
'MS_Description', N'跳转类型(PASS审批通过 REJECT退回)',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'skip_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'跳转条件',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'skip_condition'
GO
EXEC sp_addextendedproperty
'MS_Description', N'坐标',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'coordinate'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'删除标志',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'del_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户id',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'节点跳转关联表',
'SCHEMA', N'dbo',
'TABLE', N'flow_skip'
GO
CREATE TABLE flow_instance (
    id bigint NOT NULL,
    definition_id bigint NOT NULL,
    business_id nvarchar(40) NOT NULL,
    node_type tinyint NOT NULL,
    node_code nvarchar(40) NOT NULL,
    node_name nvarchar(100) NULL,
    variable nvarchar(max) NULL,
    flow_status nvarchar(20) NOT NULL,
    activity_status tinyint DEFAULT('1') NULL,
    create_by nvarchar(64) NULL,
    create_time datetime2(7)  NULL,
    update_time datetime2(7)  NULL,
    ext nvarchar(500) NULL,
    del_flag nchar(1) DEFAULT('0') NULL,
    tenant_id nvarchar(40) NULL,
    CONSTRAINT PK__flow_ins__3213E83F5190FEE1 PRIMARY KEY CLUSTERED (id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
TEXTIMAGE_ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'主键id',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'对应flow_definition表的id',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'definition_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'业务id',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'business_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'node_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程节点编码',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'node_code'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程节点名称',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'node_name'
GO
EXEC sp_addextendedproperty
'MS_Description', N'任务变量',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'variable'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程状态(0待提交 1审批中 2 å®¡æ‰¹é€šè¿‡ 3自动通过 4终止 5作废 6撤销 7取回  8已完成 9已退回 10失效)',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'flow_status'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程激活状态(0挂起 1激活)',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'activity_status'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建者',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'create_by'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'扩展字段,预留给业务系统使用',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'ext'
GO
EXEC sp_addextendedproperty
'MS_Description', N'删除标志',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'del_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户id',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程实例表',
'SCHEMA', N'dbo',
'TABLE', N'flow_instance'
GO
CREATE TABLE flow_task (
    id bigint NOT NULL,
    definition_id bigint NOT NULL,
    instance_id bigint NOT NULL,
    node_code nvarchar(100) NOT NULL,
    node_name nvarchar(100) NULL,
    node_type tinyint NOT NULL,
    form_custom nchar(1) DEFAULT('N') NULL,
    form_path nvarchar(100) NULL,
    create_time datetime2(7)  NULL,
    update_time datetime2(7)  NULL,
    del_flag nchar(1) DEFAULT('0') NULL,
    tenant_id nvarchar(40) NULL,
    CONSTRAINT PK__flow_tas__3213E83F5AE1F1BA PRIMARY KEY CLUSTERED (id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'主键id',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'对应flow_definition表的id',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'definition_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'对应flow_instance表的id',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'instance_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'节点编码',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'node_code'
GO
EXEC sp_addextendedproperty
'MS_Description', N'节点名称',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'node_name'
GO
EXEC sp_addextendedproperty
'MS_Description', N'节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'node_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批表单是否自定义(Y是 N否)',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'form_custom'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批表单路径',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'form_path'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'删除标志',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'del_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户id',
'SCHEMA', N'dbo',
'TABLE', N'flow_task',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'待办任务表',
'SCHEMA', N'dbo',
'TABLE', N'flow_task'
GO
CREATE TABLE flow_his_task (
    id bigint NOT NULL,
    definition_id bigint NOT NULL,
    instance_id bigint NOT NULL,
    task_id bigint NOT NULL,
    node_code nvarchar(100) NULL,
    node_name nvarchar(100) NULL,
    node_type tinyint  NULL,
    target_node_code nvarchar(100) NULL,
    target_node_name nvarchar(100) NULL,
    approver nvarchar(40) NULL,
    cooperate_type tinyint DEFAULT('0') NULL,
    collaborator nvarchar(40) NULL,
    skip_type nvarchar(10) NOT NULL,
    flow_status nvarchar(20) NOT NULL,
    form_custom nchar(1) DEFAULT('N') NULL,
    form_path nvarchar(100) NULL,
    message nvarchar(500) NULL,
    ext nvarchar(500) NULL,
    create_time datetime2(7)  NULL,
    update_time datetime2(7)  NULL,
    del_flag nchar(1) DEFAULT('0') NULL,
    tenant_id nvarchar(40) NULL,
    CONSTRAINT PK__flow_his__3213E83F67951564 PRIMARY KEY CLUSTERED (id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'主键id',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'对应flow_definition表的id',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'definition_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'对应flow_instance表的id',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'instance_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'对应flow_task表的id',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'task_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'开始节点编码',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'node_code'
GO
EXEC sp_addextendedproperty
'MS_Description', N'开始节点名称',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'node_name'
GO
EXEC sp_addextendedproperty
'MS_Description', N'开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'node_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'目标节点编码',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'target_node_code'
GO
EXEC sp_addextendedproperty
'MS_Description', N'结束节点名称',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'target_node_name'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批者',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'approver'
GO
EXEC sp_addextendedproperty
'MS_Description', N'协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'cooperate_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'协作人',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'collaborator'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流转类型(PASS通过 REJECT退回 NONE无动作)',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'skip_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程状态(1审批中 2 å®¡æ‰¹é€šè¿‡ 9已退回 10失效)',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'flow_status'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批表单是否自定义(Y是 N否)',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'form_custom'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批表单路径',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'form_path'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批意见',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'message'
GO
EXEC sp_addextendedproperty
'MS_Description', N'业务详情 å­˜ä¸šåŠ¡è¡¨å¯¹è±¡json字符串',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'ext'
GO
EXEC sp_addextendedproperty
'MS_Description', N'任务开始时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'审批完成时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'删除标志',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'del_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户id',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'历史任务记录表',
'SCHEMA', N'dbo',
'TABLE', N'flow_his_task'
GO
CREATE TABLE flow_user (
    id bigint NOT NULL,
    type nchar(1) NOT NULL,
    processed_by nvarchar(80) NULL,
    associated bigint NOT NULL,
    create_time datetime2(7)  NULL,
    create_by nvarchar(80) NULL,
    update_time datetime2(7)  NULL,
    del_flag nchar(1) DEFAULT('0') NULL,
    tenant_id nvarchar(40) NULL,
    CONSTRAINT PK__flow_use__3213E83FFA38CA8B PRIMARY KEY CLUSTERED (id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX user_processed_type ON flow_user (processed_by ASC, type ASC)
GO
EXEC sp_addextendedproperty
'MS_Description', N'主键id',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'权限人',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'processed_by'
GO
EXEC sp_addextendedproperty
'MS_Description', N'任务表id',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'associated'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建人',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'create_by'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'删除标志',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'del_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户id',
'SCHEMA', N'dbo',
'TABLE', N'flow_user',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程用户表',
'SCHEMA', N'dbo',
'TABLE', N'flow_user'
GO
CREATE TABLE flow_category (
    category_id bigint NOT NULL,
    tenant_id nvarchar(20) DEFAULT('000000') NULL,
    parent_id bigint  DEFAULT(0) NULL,
    ancestors nvarchar(500) DEFAULT('') NULL,
    category_name nvarchar(30) NOT NULL,
    order_num int  DEFAULT(0) NULL,
    del_flag nchar(1) DEFAULT('0') NULL,
    create_dept bigint  NULL,
    create_by bigint  NULL,
    create_time datetime2(7)  NULL,
    update_by bigint  NULL,
    update_time datetime2(7)  NULL,
    CONSTRAINT PK__flow_cat__D54EE9B4AE98B9C1 PRIMARY KEY CLUSTERED (category_id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程分类ID',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'category_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户编号',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'父流程分类id',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'parent_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'祖级列表',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'ancestors'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程分类名称',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'category_name'
GO
EXEC sp_addextendedproperty
'MS_Description', N'显示顺序',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'order_num'
GO
EXEC sp_addextendedproperty
'MS_Description', N'删除标志(0代表存在 2代表删除)',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'del_flag'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建部门',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'create_dept'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建者',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'create_by'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新者',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'update_by'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新时间',
'SCHEMA', N'dbo',
'TABLE', N'flow_category',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'流程分类',
'SCHEMA', N'dbo',
'TABLE', N'flow_category'
GO
INSERT flow_category VALUES (100, N'000000', 0, N'0', N'OA审批', 0, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (101, N'000000', 100, N'0,100', N'假勤管理', 0, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (102, N'000000', 100, N'0,100', N'人事管理', 0, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (103, N'000000', 101, N'0,100,101', N'请假', 0, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (104, N'000000', 101, N'0,100,101', N'出差', 1, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (105, N'000000', 101, N'0,100,101', N'加班', 2, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (106, N'000000', 101, N'0,100,101', N'换班', 3, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (107, N'000000', 101, N'0,100,101', N'外出', 4, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (108, N'000000', 102, N'0,100,102', N'转正', 1, N'0', 103, 1, getdate(), NULL, NULL);
GO
INSERT flow_category VALUES (109, N'000000', 102, N'0,100,102', N'离职', 2, N'0', 103, 1, getdate(), NULL, NULL);
GO
CREATE TABLE test_leave (
    id bigint NOT NULL,
    tenant_id nvarchar(20) DEFAULT('000000') NULL,
    leave_type nvarchar(255) NOT NULL,
    start_date datetime2(7) NOT NULL,
    end_date datetime2(7) NOT NULL,
    leave_days int NOT NULL,
    remark nvarchar(255) NULL,
    status nvarchar(255) NULL,
    create_dept bigint  NULL,
    create_by bigint  NULL,
    create_time datetime2(7)  NULL,
    update_by bigint  NULL,
    update_time datetime2(7)  NULL,
    CONSTRAINT PK__test_lea__3213E83F348788FA PRIMARY KEY CLUSTERED (id)
    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ON [PRIMARY]
)
ON [PRIMARY]
GO
EXEC sp_addextendedproperty
'MS_Description', N'id',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'租户编号',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'tenant_id'
GO
EXEC sp_addextendedproperty
'MS_Description', N'请假类型',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'leave_type'
GO
EXEC sp_addextendedproperty
'MS_Description', N'开始时间',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'start_date'
GO
EXEC sp_addextendedproperty
'MS_Description', N'结束时间',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'end_date'
GO
EXEC sp_addextendedproperty
'MS_Description', N'请假天数',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'leave_days'
GO
EXEC sp_addextendedproperty
'MS_Description', N'请假原因',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'remark'
GO
EXEC sp_addextendedproperty
'MS_Description', N'状态',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'status'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建部门',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'create_dept'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建者',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'create_by'
GO
EXEC sp_addextendedproperty
'MS_Description', N'创建时间',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'create_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新者',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'update_by'
GO
EXEC sp_addextendedproperty
'MS_Description', N'更新时间',
'SCHEMA', N'dbo',
'TABLE', N'test_leave',
'COLUMN', N'update_time'
GO
EXEC sp_addextendedproperty
'MS_Description', N'请假申请表',
'SCHEMA', N'dbo',
'TABLE', N'test_leave'
GO
INSERT sys_menu VALUES (11616, N'工作流', 0, 6, N'workflow', NULL, N'', 1, 0, N'M', N'0', N'0', N'', N'workflow', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11618, N'我的任务', 0, 7, N'task', NULL, N'', 1, 0, N'M', N'0', N'0', N'', N'my-task', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11619, N'我的待办', 11618, 2, N'taskWaiting', N'workflow/task/taskWaiting', N'', 1, 1, N'C', N'0', N'0', N'', N'waiting', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11632, N'我的已办', 11618, 3, N'taskFinish', N'workflow/task/taskFinish', N'', 1, 1, N'C', N'0', N'0', N'', N'finish', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11633, N'我的抄送', 11618, 4, N'taskCopyList', N'workflow/task/taskCopyList', N'', 1, 1, N'C', N'0', N'0', N'', N'my-copy', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11620, N'流程定义', 11616, 3, N'processDefinition', N'workflow/processDefinition/index', N'', 1, 1, N'C', N'0', N'0', N'', N'process-definition', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11621, N'流程实例', 11630, 1, N'processInstance', N'workflow/processInstance/index', N'', 1, 1, N'C', N'0', N'0', N'', N'tree-table', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11622, N'流程分类', 11616, 1, N'category', N'workflow/category/index', N'', 1, 0, N'C', N'0', N'0', N'workflow:category:list', N'category', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11629, N'我发起的', 11618, 1, N'myDocument', N'workflow/task/myDocument', N'', 1, 1, N'C', N'0', N'0', N'', N'guide', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11630, N'流程监控', 11616, 4, N'monitor', NULL, N'', 1, 0, N'M', N'0', N'0', N'', N'monitor', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11631, N'待办任务', 11630, 2, N'allTaskWaiting', N'workflow/task/allTaskWaiting', N'', 1, 1, N'C', N'0', N'0', N'', N'waiting', 103, 1, GETDATE(), NULL, NULL, N'');
GO
-- æµç¨‹åˆ†ç±»ç®¡ç†ç›¸å…³æŒ‰é’®
insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1, getdate(), null, null, '');
insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add',   '#', 103, 1, getdate(), null, null, '');
insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit',  '#', 103, 1, getdate(), null, null, '');
insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove','#', 103, 1, getdate(), null, null, '');
insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export','#', 103, 1, getdate(), null, null, '');
-- è¯·å‡å•信息
create table test_leave
(
    id          bigint        not null
        primary key,
    leave_type  nvarchar(255) not null,
    start_date  datetime2     not null,
    end_date    datetime2     not null,
    leave_days  int           not null,
    remark      nvarchar(255),
    status      nvarchar(255),
    create_dept bigint,
    create_by   bigint,
    create_time datetime2,
    update_by   bigint,
    update_time datetime2,
    tenant_id   nvarchar(20)
)
go
INSERT sys_menu VALUES (11623, N'流程分类查询', 11622, 1, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:query', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11624, N'流程分类新增', 11622, 2, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:add', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11625, N'流程分类修改', 11622, 3, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:edit', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11626, N'流程分类删除', 11622, 4, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:remove', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11627, N'流程分类导出', 11622, 5, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:export', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
exec sp_addextendedproperty 'MS_Description', N'请假申请表', 'SCHEMA', 'dbo', 'TABLE', 'test_leave'
go
-- è¯·å‡æµ‹è¯•相关按钮
INSERT sys_menu VALUES (11638, N'请假申请', 5, 1, N'leave', N'workflow/leave/index', N'', 1, 0, N'C', N'0', N'0', N'workflow:leave:list', N'#', 103, 1, GETDATE(), NULL, NULL, N'请假申请菜单');
GO
INSERT sys_menu VALUES (11639, N'请假申请查询', 11638, 1, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:query', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11640, N'请假申请新增', 11638, 2, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:add', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11641, N'请假申请修改', 11638, 3, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:edit', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11642, N'请假申请删除', 11638, 4, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:remove', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
GO
INSERT sys_menu VALUES (11643, N'请假申请导出', 11638, 5, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:export', N'#', 103, 1, GETDATE(), NULL, NULL, N'');
exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'id'
go
INSERT sys_dict_type VALUES (13, N'000000', N'业务状态', N'wf_business_status', 103, 1, GETDATE(), NULL, NULL, N'业务状态列表');
GO
INSERT sys_dict_type VALUES (14, N'000000', N'表单类型', N'wf_form_type', 103, 1, GETDATE(), NULL, NULL, N'表单类型列表');
GO
INSERT sys_dict_type VALUES (15, N'000000', N'任务状态', N'wf_task_status', 103, 1, GETDATE(), NULL, NULL, N'任务状态');
GO
exec sp_addextendedproperty 'MS_Description', N'请假类型', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN',
     'leave_type'
go
exec sp_addextendedproperty 'MS_Description', N'开始时间', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN',
     'start_date'
go
exec sp_addextendedproperty 'MS_Description', N'结束时间', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'end_date'
go
exec sp_addextendedproperty 'MS_Description', N'请假天数', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN',
     'leave_days'
go
exec sp_addextendedproperty 'MS_Description', N'请假原因', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'remark'
go
exec sp_addextendedproperty 'MS_Description', N'状态', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'status'
go
exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN',
     'create_dept'
go
exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'create_by'
go
exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN',
     'create_time'
go
exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'update_by'
go
exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN',
     'update_time'
go
exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'tenant_id'
go
-- æµç¨‹åˆ†ç±»ä¿¡æ¯è¡¨
create table wf_category
(
    id            bigint not null
        primary key,
    category_name nvarchar(255),
    category_code nvarchar(255)
        constraint uni_category_code
        unique,
    parent_id     bigint,
    sort_num      int,
    tenant_id     nvarchar(20),
    create_dept   bigint,
    create_by     bigint,
    create_time   datetime2,
    update_by     bigint,
    update_time   datetime2
)
go
exec sp_addextendedproperty 'MS_Description', N'流程分类', 'SCHEMA', 'dbo', 'TABLE', 'wf_category'
go
exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'id'
go
exec sp_addextendedproperty 'MS_Description', N'分类名称', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN',
     'category_name'
go
exec sp_addextendedproperty 'MS_Description', N'分类编码', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN',
     'category_code'
go
exec sp_addextendedproperty 'MS_Description', N'父级id', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'parent_id'
go
exec sp_addextendedproperty 'MS_Description', N'排序', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'sort_num'
go
exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN',
     'tenant_id'
go
exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN',
     'create_dept'
go
exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'create_by'
go
exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN',
     'create_time'
go
exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'update_by'
go
exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN',
     'update_time'
go
INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, getdate(), 1, getdate());
create table wf_task_back_node
(
    id            bigint not null primary key,
    node_id       nvarchar(255) not null,
    node_name     nvarchar(255) not null,
    order_no      int not null,
    instance_id   nvarchar(255) not null,
    task_type     nvarchar(255) not null,
    assignee      nvarchar(2000) not null,
    tenant_id     nvarchar(20),
    create_dept   bigint,
    create_by     bigint,
    create_time   datetime2,
    update_by     bigint,
    update_time   datetime2
)
go
exec sp_addextendedproperty 'MS_Description', N'节点审批记录', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node'
go
exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'id'
go
exec sp_addextendedproperty 'MS_Description', N'节点id', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN',
     'node_id'
go
exec sp_addextendedproperty 'MS_Description', N'节点名称', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN',
     'node_name'
go
exec sp_addextendedproperty 'MS_Description', N'排序', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'order_no'
go
exec sp_addextendedproperty 'MS_Description', N'流程实例id', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'instance_id'
go
exec sp_addextendedproperty 'MS_Description', N'节点类型', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'task_type'
go
exec sp_addextendedproperty 'MS_Description', N'审批人', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'assignee'
go
exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN',
     'tenant_id'
go
exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN',
     'create_dept'
go
exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'create_by'
go
exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN',
     'create_time'
go
exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'update_by'
go
exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN',
     'update_time'
go
create table wf_definition_config
(
    id            bigint not null primary key,
    table_name    nvarchar(255)  not null,
    definition_id nvarchar(255)  not null
        constraint uni_definition_id
        unique,
    process_key   nvarchar(255)  not null,
    version       bigint         not null,
    remark        nvarchar(500) DEFAULT ('') null,
    tenant_id     nvarchar(20),
    create_dept   bigint,
    create_by     bigint,
    create_time   datetime2,
    update_by     bigint,
    update_time   datetime2
)
go
exec sp_addextendedproperty 'MS_Description', N'流程定义配置', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config'
go
exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', 'id'
go
exec sp_addextendedproperty 'MS_Description', N'表名', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'table_name'
go
exec sp_addextendedproperty 'MS_Description', N'流程定义ID', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'definition_id'
go
exec sp_addextendedproperty 'MS_Description', N'流程KEY', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'process_key'
go
exec sp_addextendedproperty 'MS_Description', N'流程版本', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'version'
go
exec sp_addextendedproperty 'MS_Description', N'备注', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'remark'
go
exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'tenant_id'
go
exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'create_dept'
go
exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', 'create_by'
go
exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'create_time'
go
exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', 'update_by'
go
exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN',
     'update_time'
go
create table wf_form_manage
(
    id            bigint not null primary key,
    form_name     nvarchar(255) not null,
    form_type     nvarchar(255) not null,
    router        nvarchar(255) not null,
    remark        nvarchar(500) null,
    tenant_id     nvarchar(20),
    create_dept   bigint,
    create_by     bigint,
    create_time   datetime2,
    update_by     bigint,
    update_time   datetime2
)
go
exec sp_addextendedproperty 'MS_Description', N'表单管理', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage'
go
exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', 'id'
go
exec sp_addextendedproperty 'MS_Description', N'表单名称', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN',
     'form_name'
go
exec sp_addextendedproperty 'MS_Description', N'表单类型', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN',
     'form_type'
go
exec sp_addextendedproperty 'MS_Description', N'路由地址/表单ID', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN',
     'router'
go
exec sp_addextendedproperty 'MS_Description', N'备注', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN',
     'remark'
go
exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN',
     'tenant_id'
go
exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN',
     'create_dept'
go
exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', 'create_by'
go
exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN',
     'create_time'
go
exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', 'update_by'
go
exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN',
     'update_time'
go
insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, getdate(), 1, getdate());
create table wf_node_config
(
    id               bigint not null primary key,
    form_id          bigint,
    form_type        nvarchar(255) ,
    node_name        nvarchar(255) not null,
    node_id          nvarchar(255) not null,
    definition_id    nvarchar(255) not null,
    apply_user_task  nchar default ('0')  null,
    tenant_id        nvarchar(20),
    create_dept      bigint,
    create_by        bigint,
    create_time      datetime2,
    update_by        bigint,
    update_time      datetime2
)
go
exec sp_addextendedproperty 'MS_Description', N'节点配置', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config'
go
exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', 'id'
go
exec sp_addextendedproperty 'MS_Description', N'表单id', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'form_id'
go
exec sp_addextendedproperty 'MS_Description', N'表单类型', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'form_type'
go
exec sp_addextendedproperty 'MS_Description', N'节点名称', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'node_name'
go
exec sp_addextendedproperty 'MS_Description', N'节点id', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'node_id'
go
exec sp_addextendedproperty 'MS_Description', N'流程定义id', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'definition_id'
go
exec sp_addextendedproperty 'MS_Description', N'是否为申请人节点 ï¼ˆ0是 1否)', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'apply_user_task'
go
exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'tenant_id'
go
exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'create_dept'
go
exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', 'create_by'
go
exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'create_time'
go
exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', 'update_by'
go
exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN',
     'update_time'
go
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, getdate(), NULL, NULL, '请假申请菜单');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, getdate(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, getdate(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, getdate(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, getdate(), NULL, NULL, '');
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, getdate(), NULL, NULL, '');
INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, getdate(), NULL, NULL, '业务状态列表');
INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, getdate(), NULL, NULL, '表单类型列表');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, getdate(), NULL, NULL, '已撤销');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, getdate(), NULL, NULL, '草稿');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1,getdate(), NULL, NULL, '待审核');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, getdate(), NULL, NULL, '已完成');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, getdate(), NULL, NULL, '已作废');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, getdate(), NULL, NULL, '已退回');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1,getdate(), NULL, NULL, '已终止');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, getdate(), NULL, NULL, '自定义表单');
INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, getdate(), NULL, NULL, '动态表单');
-- è¡¨å•管理 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11628, '表单管理', '11616', '5', 'formManage', 'workflow/formManage/index', 1, 0, 'C', '0', '0', 'workflow:formManage:list', 'tree-table', 103, 1, getdate(), null, null, '表单管理菜单');
-- è¡¨å•管理按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11644, '表单管理查询', 11628, '1',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:query',        '', 103, 1, getdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11645, '表单管理新增', 11628, '2',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:add',          '', 103, 1, getdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11646, '表单管理修改', 11628, '3',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:edit',         '', 103, 1, getdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11647, '表单管理删除', 11628, '4',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:remove',       '', 103, 1, getdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(11648, '表单管理导出', 11628, '5',  '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:export',       'tree-table', 103, 1, getdate(), null, null, '');
INSERT sys_dict_data VALUES (39, N'000000', 1, N'已撤销', N'cancel', N'wf_business_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'已撤销');
GO
INSERT sys_dict_data VALUES (40, N'000000', 2, N'草稿', N'draft', N'wf_business_status', N'', N'info', N'N', 103, 1, GETDATE(), NULL, NULL, N'草稿');
GO
INSERT sys_dict_data VALUES (41, N'000000', 3, N'待审核', N'waiting', N'wf_business_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'待审核');
GO
INSERT sys_dict_data VALUES (42, N'000000', 4, N'已完成', N'finish', N'wf_business_status', N'', N'success', N'N', 103, 1, GETDATE(), NULL, NULL, N'已完成');
GO
INSERT sys_dict_data VALUES (43, N'000000', 5, N'已作废', N'invalid', N'wf_business_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'已作废');
GO
INSERT sys_dict_data VALUES (44, N'000000', 6, N'已退回', N'back', N'wf_business_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'已退回');
GO
INSERT sys_dict_data VALUES (45, N'000000', 7, N'已终止', N'termination', N'wf_business_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'已终止');
GO
INSERT sys_dict_data VALUES (46, N'000000', 1, N'自定义表单', N'static', N'wf_form_type', N'', N'success', N'N', 103, 1, GETDATE(), NULL, NULL, N'自定义表单');
GO
INSERT sys_dict_data VALUES (47, N'000000', 2, N'动态表单', N'dynamic', N'wf_form_type', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'动态表单');
GO
INSERT sys_dict_data VALUES (48, N'000000', 1, N'撤销', N'cancel', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'撤销');
GO
INSERT sys_dict_data VALUES (49, N'000000', 2, N'通过', N'pass', N'wf_task_status', N'', N'success', N'N', 103, 1, GETDATE(), NULL, NULL, N'通过');
GO
INSERT sys_dict_data VALUES (50, N'000000', 3, N'待审核', N'waiting', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'待审核');
GO
INSERT sys_dict_data VALUES (51, N'000000', 4, N'作废', N'invalid', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'作废');
GO
INSERT sys_dict_data VALUES (52, N'000000', 5, N'退回', N'back', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'退回');
GO
INSERT sys_dict_data VALUES (53, N'000000', 6, N'终止', N'termination', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'终止');
GO
INSERT sys_dict_data VALUES (54, N'000000', 7, N'转办', N'transfer', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'转办');
GO
INSERT sys_dict_data VALUES (55, N'000000', 8, N'委托', N'depute', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'委托');
GO
INSERT sys_dict_data VALUES (56, N'000000', 9, N'抄送', N'copy', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'抄送');
GO
INSERT sys_dict_data VALUES (57, N'000000', 10, N'加签', N'sign', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'加签');
GO
INSERT sys_dict_data VALUES (58, N'000000', 11, N'减签', N'sign_off', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'减签');
GO
INSERT sys_dict_data VALUES (59, N'000000', 11, N'超时', N'timeout', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'超时');
GO