Browse Source

first commit

master
zhouhaibin 5 months ago
commit
a80e7ef519
  1. 13
      .gitee/ISSUE_TEMPLATE.zh-CN.md
  2. 15
      .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md
  3. 30
      .gitignore
  4. 10
      CHANGELOG.md
  5. 21
      LICENSE
  6. 89
      README.md
  7. 324
      db/activiti/activiti.mysql.create.engine.sql
  8. 155
      db/activiti/activiti.mysql.create.history.sql
  9. 442
      db/easy-cms.sql
  10. 6264
      db/easy-vben.sql
  11. 193
      db/quartz.sql
  12. 83
      easy-activiti/pom.xml
  13. 139
      easy-activiti/src/main/java/com/easy/admin/activiti/config/ActivitiConfig.java
  14. 32
      easy-activiti/src/main/java/com/easy/admin/activiti/config/factory/CustomGroupEntityManagerFactory.java
  15. 31
      easy-activiti/src/main/java/com/easy/admin/activiti/config/factory/CustomUserEntityManagerFactory.java
  16. 66
      easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomGroupEntityManager.java
  17. 226
      easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomProcessDiagramCanvas.java
  18. 37
      easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomProcessDiagramGenerator.java
  19. 367
      easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomProcessDiagramGeneratorImpl.java
  20. 129
      easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomUserEntityManager.java
  21. 65
      easy-activiti/src/main/java/com/easy/admin/activiti/config/util/ActivitiUserUtil.java
  22. 25
      easy-activiti/src/main/java/com/easy/admin/activiti/constant/ActivitiModelConst.java
  23. 19
      easy-activiti/src/main/java/com/easy/admin/activiti/constant/ActivitiTaskStatusConst.java
  24. 50
      easy-activiti/src/main/java/com/easy/admin/activiti/constant/ActivitiVariableConst.java
  25. 45
      easy-activiti/src/main/java/com/easy/admin/activiti/constant/ActivitiWorkflowConst.java
  26. 30
      easy-activiti/src/main/java/com/easy/admin/activiti/constant/status/ActivitiSuspensionStatus.java
  27. 32
      easy-activiti/src/main/java/com/easy/admin/activiti/constant/status/ActivitiTaskStatus.java
  28. 47
      easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiHistoricController.java
  29. 60
      easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiHistoryTaskInstanceController.java
  30. 152
      easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiModelController.java
  31. 128
      easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiProcessController.java
  32. 47
      easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiProcessDefinitionController.java
  33. 39
      easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiProcessTraceController.java
  34. 88
      easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiTaskController.java
  35. 38
      easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiVariableController.java
  36. 33
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiHistoricMapper.java
  37. 33
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiHistoryTaskInstanceMapper.java
  38. 44
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiModelMapper.java
  39. 39
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiProcessDefinitionMapper.java
  40. 42
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiProcessMapper.java
  41. 44
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiTaskMapper.java
  42. 24
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiHistoricMapper.xml
  43. 36
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiHistoryTaskInstanceMapper.xml
  44. 25
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiModelMapper.xml
  45. 19
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiProcessDefinitionMapper.xml
  46. 36
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiProcessMapper.xml
  47. 47
      easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiTaskMapper.xml
  48. 105
      easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiFormPropertyVO.java
  49. 188
      easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiHistoric.java
  50. 352
      easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiHistoryTaskInstance.java
  51. 51
      easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiModel.java
  52. 183
      easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiProcess.java
  53. 103
      easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiProcessDefinitionVO.java
  54. 352
      easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiTask.java
  55. 106
      easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiTaskInfo.java
  56. 30
      easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiHistoricService.java
  57. 39
      easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiHistoryTaskInstanceService.java
  58. 106
      easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiModelService.java
  59. 48
      easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiProcessDefinitionService.java
  60. 74
      easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiProcessService.java
  61. 21
      easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiProcessTraceService.java
  62. 54
      easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiTaskService.java
  63. 36
      easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiHistoricServiceImpl.java
  64. 86
      easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiHistoryTaskInstanceServiceImpl.java
  65. 377
      easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiModelServiceImpl.java
  66. 287
      easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiProcessDefinitionServiceImpl.java
  67. 169
      easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiProcessServiceImpl.java
  68. 134
      easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiProcessTraceServiceImpl.java
  69. 229
      easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiTaskServiceImpl.java
  70. 74
      easy-activiti/src/main/resources/message/revocation-notice.html
  71. 2154
      easy-activiti/src/main/resources/stencilset.json
  72. 13
      easy-api/Dockerfile
  73. 122
      easy-api/pom.xml
  74. 26
      easy-api/src/main/java/com/easy/admin/Application.java
  75. 19
      easy-api/src/main/java/com/easy/admin/WebStartApplication.java
  76. 38
      easy-api/src/main/java/com/easy/admin/easyapi/config/web/EasyErrorController.java
  77. 157
      easy-api/src/main/java/com/easy/admin/easyapi/config/web/ExceptionControllerAdvice.java
  78. 55
      easy-api/src/main/java/com/easy/admin/easyapi/config/web/ResponseResultHandler.java
  79. 40
      easy-api/src/main/java/com/easy/admin/easyapi/config/web/WebConfig.java
  80. 120
      easy-api/src/main/resources/application-dev.yml
  81. 101
      easy-api/src/main/resources/application-prod.yml
  82. 101
      easy-api/src/main/resources/application-test.yml
  83. 69
      easy-api/src/main/resources/application.yml
  84. 1
      easy-api/src/main/resources/config/mail.setting
  85. BIN
      easy-api/src/main/resources/images/verification/original/bg1.png
  86. BIN
      easy-api/src/main/resources/images/verification/original/bg10.png
  87. BIN
      easy-api/src/main/resources/images/verification/original/bg11.png
  88. BIN
      easy-api/src/main/resources/images/verification/original/bg12.png
  89. BIN
      easy-api/src/main/resources/images/verification/original/bg13.png
  90. BIN
      easy-api/src/main/resources/images/verification/original/bg14.png
  91. BIN
      easy-api/src/main/resources/images/verification/original/bg15.png
  92. BIN
      easy-api/src/main/resources/images/verification/original/bg16.png
  93. BIN
      easy-api/src/main/resources/images/verification/original/bg17.png
  94. BIN
      easy-api/src/main/resources/images/verification/original/bg18.png
  95. BIN
      easy-api/src/main/resources/images/verification/original/bg19.png
  96. BIN
      easy-api/src/main/resources/images/verification/original/bg2.png
  97. BIN
      easy-api/src/main/resources/images/verification/original/bg20.png
  98. BIN
      easy-api/src/main/resources/images/verification/original/bg3.png
  99. BIN
      easy-api/src/main/resources/images/verification/original/bg4.png
  100. BIN
      easy-api/src/main/resources/images/verification/original/bg5.png

13
.gitee/ISSUE_TEMPLATE.zh-CN.md

@ -0,0 +1,13 @@
### 该问题是怎么引起的?
### 重现步骤
### 报错信息

15
.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md

@ -0,0 +1,15 @@
### 相关的Issue
### 原因(目的、解决的问题等)
### 描述(做了什么,变更了什么)
### 测试用例(新增、改动、可能影响的功能)

30
.gitignore

@ -0,0 +1,30 @@
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
*/target
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### mac ###
.DS_Store
*/.DS_Store
### project ###
logs

10
CHANGELOG.md

@ -0,0 +1,10 @@
# 更新日志
### 1.1.0
`2023-08-15`
- 🌟 修复一些问题
- 🌟新增CMS模块
### 🔥🔥🔥 1.0.0 正式版发布 🔥🔥🔥
`2022-07-31`
- 🌟 版本发布

21
LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 tengchong
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

89
README.md

@ -0,0 +1,89 @@
<h1 align="center">Easy Vben</h1>
<div align="center">
</div>
基于SpringBoot2、Druid、Mybatis Plus、Apache Shiro、Activiti、Beetl、HuTool、Quartz等开源框架开发,内置权限、部门、参数、字典、定时任务、代码生成等模块。
建议与 [Easy-Vben-Admin](https://github.com/TengChongChong/Easy-Vben-Admin) 前端开源项目一起使用
## 文档
[在线文档](http://ev-doc.easy-frame.top/ '在线文档')
## 下载
从 码云 仓库中直接安装最新的代码
```
$ git clone --depth=1 https://github.com/TengChongChong/Easy-Vben.git easy-vben
```
## 目录结构
```
├── db # Sql脚本
│ ├── activiti # 工作流
│ ├── easy-vben.sql # 基础 sql
│ ├── easy-cms.sql # CMS sql
│ └── quartz.sql # 定时任务
├── easy-activiti # 工作流
├── easy-api # 入口
├── easy-cms # CMS
├── easy-common # 工具
│ ├── easy-core # 基础
│ ├── easy-mybatis # MyBatis
│ └── easy-redis # Redis
├── easy-file # 文件
├── easy-generator # 代码生成
├── easy-sample # 示例
├── easy-scheduler # 定时任务
└── easy-sys # 系统
```
## 创建数据库
- 创建数据库并执行`/easy-admin/db/easy-vben.sql`初始化表
- 如需使用CMS功能执行`/easy-admin/db/easy-cms.sql`初始化表
- 执行`/easy-admin/db/activiti/*`创建工作流表
- 执行`/easy-admin/db/quartz.sql`创建定时任务表
## 配置数据源&Redis
打开`/easy-admin/easy-api/src/main/resources/application-dev.yml`文件,修改`Redis`与`数据源`配置。 如果你使用默认的参数安装的`Redis`和`MySQL`
只需修改`spring.datasource.password`即可。
```yaml {19}
spring:
# Redis
redis:
# 数据库索引(默认为0)
database: 0
# 服务器地址
host: 127.0.0.1
# 服务器连接端口
port: 6379
# 服务器连接密码(默认为空)
password:
# 数据源,集成多数据源,此处仅需配置主数据源
datasource:
dynamic:
datasource:
master:
url: jdbc:mysql://localhost:3306/easy-admin?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMulQueries=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullDatabaseMeansCurrent=true&useInformationSchema=true
username: root
password: xxx
```
多数据源配置请参考[多数据源配置](xxx, '多数据源配置')
## 配置上传的文件存放路径
打开`/easy-admin/easy-api/src/main/resources/application-dev.yml`文件,修改文件存放路径
```yaml {3}
project:
# 文件上传路径(不要写以~开头的路径会导致无法访问)
file-upload-path: /Users/tengchong/development/easy-admin
```
> 此路径会被添加为静态资源映射地址
## 启动服务
执行`com.easy.admin.Application`启动服务

324
db/activiti/activiti.mysql.create.engine.sql

@ -0,0 +1,324 @@
create table act_ge_property (
name_ varchar(64),
value_ varchar(300),
rev_ integer,
primary key (name_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
insert into act_ge_property
values ('schema.version', '5.22.0.0', 1);
insert into act_ge_property
values ('schema.history', 'create(5.22.0.0)', 1);
insert into act_ge_property
values ('next.dbid', '1', 1);
create table act_ge_bytearray (
id_ varchar(64),
rev_ integer,
name_ varchar(255),
deployment_id_ varchar(64),
bytes_ longblob,
generated_ tinyint,
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_re_deployment (
id_ varchar(64),
name_ varchar(255),
category_ varchar(255),
tenant_id_ varchar(255) default '',
deploy_time_ timestamp(3) null,
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_re_model (
id_ varchar(64) not null,
rev_ integer,
name_ varchar(255),
key_ varchar(255),
category_ varchar(255),
create_time_ timestamp(3) null,
last_update_time_ timestamp(3) null,
version_ integer,
meta_info_ varchar(4000),
deployment_id_ varchar(64),
editor_source_value_id_ varchar(64),
editor_source_extra_value_id_ varchar(64),
tenant_id_ varchar(255) default '',
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_ru_execution (
id_ varchar(64),
rev_ integer,
proc_inst_id_ varchar(64),
business_key_ varchar(255),
parent_id_ varchar(64),
proc_def_id_ varchar(64),
super_exec_ varchar(64),
act_id_ varchar(255),
is_active_ tinyint,
is_concurrent_ tinyint,
is_scope_ tinyint,
is_event_scope_ tinyint,
suspension_state_ integer,
cached_ent_state_ integer,
tenant_id_ varchar(255) default '',
name_ varchar(255),
lock_time_ timestamp(3) null,
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_ru_job (
id_ varchar(64) not null,
rev_ integer,
type_ varchar(255) not null,
lock_exp_time_ timestamp(3) null,
lock_owner_ varchar(255),
exclusive_ boolean,
execution_id_ varchar(64),
process_instance_id_ varchar(64),
proc_def_id_ varchar(64),
retries_ integer,
exception_stack_id_ varchar(64),
exception_msg_ varchar(4000),
duedate_ timestamp(3) null,
repeat_ varchar(255),
handler_type_ varchar(255),
handler_cfg_ varchar(4000),
tenant_id_ varchar(255) default '',
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_re_procdef (
id_ varchar(64) not null,
rev_ integer,
category_ varchar(255),
name_ varchar(255),
key_ varchar(255) not null,
version_ integer not null,
deployment_id_ varchar(64),
resource_name_ varchar(4000),
dgrm_resource_name_ varchar(4000),
description_ varchar(4000),
has_start_form_key_ tinyint,
has_graphical_notation_ tinyint,
suspension_state_ integer,
tenant_id_ varchar(255) default '',
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_ru_task (
id_ varchar(64),
rev_ integer,
execution_id_ varchar(64),
proc_inst_id_ varchar(64),
proc_def_id_ varchar(64),
name_ varchar(255),
parent_task_id_ varchar(64),
description_ varchar(4000),
task_def_key_ varchar(255),
owner_ varchar(255),
assignee_ varchar(255),
delegation_ varchar(64),
priority_ integer,
create_time_ timestamp(3) null,
due_date_ datetime(3),
category_ varchar(255),
suspension_state_ integer,
tenant_id_ varchar(255) default '',
form_key_ varchar(255),
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_ru_identitylink (
id_ varchar(64),
rev_ integer,
group_id_ varchar(255),
type_ varchar(255),
user_id_ varchar(255),
task_id_ varchar(64),
proc_inst_id_ varchar(64),
proc_def_id_ varchar(64),
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_ru_variable (
id_ varchar(64) not null,
rev_ integer,
type_ varchar(255) not null,
name_ varchar(255) not null,
execution_id_ varchar(64),
proc_inst_id_ varchar(64),
task_id_ varchar(64),
bytearray_id_ varchar(64),
double_ double,
long_ bigint,
text_ varchar(4000),
text2_ varchar(4000),
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_ru_event_subscr (
id_ varchar(64) not null,
rev_ integer,
event_type_ varchar(255) not null,
event_name_ varchar(255),
execution_id_ varchar(64),
proc_inst_id_ varchar(64),
activity_id_ varchar(64),
configuration_ varchar(255),
created_ timestamp(3) not null default current_timestamp(3),
proc_def_id_ varchar(64),
tenant_id_ varchar(255) default '',
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_evt_log (
log_nr_ bigint auto_increment,
type_ varchar(64),
proc_def_id_ varchar(64),
proc_inst_id_ varchar(64),
execution_id_ varchar(64),
task_id_ varchar(64),
time_stamp_ timestamp(3) not null,
user_id_ varchar(255),
data_ longblob,
lock_owner_ varchar(255),
lock_time_ timestamp(3) null,
is_processed_ tinyint default 0,
primary key (log_nr_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_procdef_info (
id_ varchar(64) not null,
proc_def_id_ varchar(64) not null,
rev_ integer,
info_json_id_ varchar(64),
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create index act_idx_exec_buskey on act_ru_execution(business_key_);
create index act_idx_task_create on act_ru_task(create_time_);
create index act_idx_ident_lnk_user on act_ru_identitylink(user_id_);
create index act_idx_ident_lnk_group on act_ru_identitylink(group_id_);
create index act_idx_event_subscr_config_ on act_ru_event_subscr(configuration_);
create index act_idx_variable_task_id on act_ru_variable(task_id_);
create index act_idx_athrz_procedef on act_ru_identitylink(proc_def_id_);
create index act_idx_info_procdef on act_procdef_info(proc_def_id_);
alter table act_ge_bytearray
add constraint act_fk_bytearr_depl
foreign key (deployment_id_)
references act_re_deployment (id_);
alter table act_re_procdef
add constraint act_uniq_procdef
unique (key_,version_, tenant_id_);
alter table act_ru_execution
add constraint act_fk_exe_procinst
foreign key (proc_inst_id_)
references act_ru_execution (id_) on delete cascade on update cascade;
alter table act_ru_execution
add constraint act_fk_exe_parent
foreign key (parent_id_)
references act_ru_execution (id_);
alter table act_ru_execution
add constraint act_fk_exe_super
foreign key (super_exec_)
references act_ru_execution (id_);
alter table act_ru_execution
add constraint act_fk_exe_procdef
foreign key (proc_def_id_)
references act_re_procdef (id_);
alter table act_ru_identitylink
add constraint act_fk_tskass_task
foreign key (task_id_)
references act_ru_task (id_);
alter table act_ru_identitylink
add constraint act_fk_athrz_procedef
foreign key (proc_def_id_)
references act_re_procdef(id_);
alter table act_ru_identitylink
add constraint act_fk_idl_procinst
foreign key (proc_inst_id_)
references act_ru_execution (id_);
alter table act_ru_task
add constraint act_fk_task_exe
foreign key (execution_id_)
references act_ru_execution (id_);
alter table act_ru_task
add constraint act_fk_task_procinst
foreign key (proc_inst_id_)
references act_ru_execution (id_);
alter table act_ru_task
add constraint act_fk_task_procdef
foreign key (proc_def_id_)
references act_re_procdef (id_);
alter table act_ru_variable
add constraint act_fk_var_exe
foreign key (execution_id_)
references act_ru_execution (id_);
alter table act_ru_variable
add constraint act_fk_var_procinst
foreign key (proc_inst_id_)
references act_ru_execution(id_);
alter table act_ru_variable
add constraint act_fk_var_bytearray
foreign key (bytearray_id_)
references act_ge_bytearray (id_);
alter table act_ru_job
add constraint act_fk_job_exception
foreign key (exception_stack_id_)
references act_ge_bytearray (id_);
alter table act_ru_event_subscr
add constraint act_fk_event_exec
foreign key (execution_id_)
references act_ru_execution(id_);
alter table act_re_model
add constraint act_fk_model_source
foreign key (editor_source_value_id_)
references act_ge_bytearray (id_);
alter table act_re_model
add constraint act_fk_model_source_extra
foreign key (editor_source_extra_value_id_)
references act_ge_bytearray (id_);
alter table act_re_model
add constraint act_fk_model_deployment
foreign key (deployment_id_)
references act_re_deployment (id_);
alter table act_procdef_info
add constraint act_fk_info_json_ba
foreign key (info_json_id_)
references act_ge_bytearray (id_);
alter table act_procdef_info
add constraint act_fk_info_procdef
foreign key (proc_def_id_)
references act_re_procdef (id_);
alter table act_procdef_info
add constraint act_uniq_info_procdef
unique (proc_def_id_);

155
db/activiti/activiti.mysql.create.history.sql

@ -0,0 +1,155 @@
create table act_hi_procinst (
id_ varchar(64) not null,
proc_inst_id_ varchar(64) not null,
business_key_ varchar(255),
proc_def_id_ varchar(64) not null,
start_time_ datetime(3) not null,
end_time_ datetime(3),
duration_ bigint,
start_user_id_ varchar(255),
start_act_id_ varchar(255),
end_act_id_ varchar(255),
super_process_instance_id_ varchar(64),
delete_reason_ varchar(4000),
tenant_id_ varchar(255) default '',
name_ varchar(255),
primary key (id_),
unique (proc_inst_id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_hi_actinst (
id_ varchar(64) not null,
proc_def_id_ varchar(64) not null,
proc_inst_id_ varchar(64) not null,
execution_id_ varchar(64) not null,
act_id_ varchar(255) not null,
task_id_ varchar(64),
call_proc_inst_id_ varchar(64),
act_name_ varchar(255),
act_type_ varchar(255) not null,
assignee_ varchar(255),
start_time_ datetime(3) not null,
end_time_ datetime(3),
duration_ bigint,
tenant_id_ varchar(255) default '',
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_hi_taskinst (
id_ varchar(64) not null,
proc_def_id_ varchar(64),
task_def_key_ varchar(255),
proc_inst_id_ varchar(64),
execution_id_ varchar(64),
name_ varchar(255),
parent_task_id_ varchar(64),
description_ varchar(4000),
owner_ varchar(255),
assignee_ varchar(255),
start_time_ datetime(3) not null,
claim_time_ datetime(3),
end_time_ datetime(3),
duration_ bigint,
delete_reason_ varchar(4000),
priority_ integer,
due_date_ datetime(3),
form_key_ varchar(255),
category_ varchar(255),
tenant_id_ varchar(255) default '',
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_hi_varinst (
id_ varchar(64) not null,
proc_inst_id_ varchar(64),
execution_id_ varchar(64),
task_id_ varchar(64),
name_ varchar(255) not null,
var_type_ varchar(100),
rev_ integer,
bytearray_id_ varchar(64),
double_ double,
long_ bigint,
text_ varchar(4000),
text2_ varchar(4000),
create_time_ datetime(3),
last_updated_time_ datetime(3),
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_hi_detail (
id_ varchar(64) not null,
type_ varchar(255) not null,
proc_inst_id_ varchar(64),
execution_id_ varchar(64),
task_id_ varchar(64),
act_inst_id_ varchar(64),
name_ varchar(255) not null,
var_type_ varchar(255),
rev_ integer,
time_ datetime(3) not null,
bytearray_id_ varchar(64),
double_ double,
long_ bigint,
text_ varchar(4000),
text2_ varchar(4000),
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_hi_comment (
id_ varchar(64) not null,
type_ varchar(255),
time_ datetime(3) not null,
user_id_ varchar(255),
task_id_ varchar(64),
proc_inst_id_ varchar(64),
action_ varchar(255),
message_ varchar(4000),
full_msg_ longblob,
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_hi_attachment (
id_ varchar(64) not null,
rev_ integer,
user_id_ varchar(255),
name_ varchar(255),
description_ varchar(4000),
type_ varchar(255),
task_id_ varchar(64),
proc_inst_id_ varchar(64),
url_ varchar(4000),
content_id_ varchar(64),
time_ datetime(3),
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create table act_hi_identitylink (
id_ varchar(64),
group_id_ varchar(255),
type_ varchar(255),
user_id_ varchar(255),
task_id_ varchar(64),
proc_inst_id_ varchar(64),
primary key (id_)
) engine=InnoDB default charset=utf8 collate utf8_bin;
create index act_idx_hi_pro_inst_end on act_hi_procinst(end_time_);
create index act_idx_hi_pro_i_buskey on act_hi_procinst(business_key_);
create index act_idx_hi_act_inst_start on act_hi_actinst(start_time_);
create index act_idx_hi_act_inst_end on act_hi_actinst(end_time_);
create index act_idx_hi_detail_proc_inst on act_hi_detail(proc_inst_id_);
create index act_idx_hi_detail_act_inst on act_hi_detail(act_inst_id_);
create index act_idx_hi_detail_time on act_hi_detail(time_);
create index act_idx_hi_detail_name on act_hi_detail(name_);
create index act_idx_hi_detail_task_id on act_hi_detail(task_id_);
create index act_idx_hi_procvar_proc_inst on act_hi_varinst(proc_inst_id_);
create index act_idx_hi_procvar_name_type on act_hi_varinst(name_, var_type_);
create index act_idx_hi_procvar_task_id on act_hi_varinst(task_id_);
create index act_idx_hi_act_inst_procinst on act_hi_actinst(proc_inst_id_, act_id_);
create index act_idx_hi_act_inst_exec on act_hi_actinst(execution_id_, act_id_);
create index act_idx_hi_ident_lnk_user on act_hi_identitylink(user_id_);
create index act_idx_hi_ident_lnk_task on act_hi_identitylink(task_id_);
create index act_idx_hi_ident_lnk_procinst on act_hi_identitylink(proc_inst_id_);
create index act_idx_hi_task_inst_procinst on act_hi_taskinst(proc_inst_id_);

442
db/easy-cms.sql

File diff suppressed because one or more lines are too long

6264
db/easy-vben.sql

File diff suppressed because one or more lines are too long

193
db/quartz.sql

@ -0,0 +1,193 @@
/*
Navicat Premium Data Transfer
Source Server : - MySql
Source Server Type : MySQL
Source Server Version : 80016
Source Host : 127.0.0.1:3306
Source Schema : easy-admin
Target Server Type : MySQL
Target Server Version : 80016
File Encoding : 65001
Date: 26/04/2021 11:14:06
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for qrtz_blob_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_blob_triggers`;
CREATE TABLE `qrtz_blob_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`blob_data` blob,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_calendars
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_calendars`;
CREATE TABLE `qrtz_calendars` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`calendar_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`calendar` blob NOT NULL,
PRIMARY KEY (`sched_name`,`calendar_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_cron_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_cron_triggers`;
CREATE TABLE `qrtz_cron_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`cron_expression` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`time_zone_id` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_fired_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_fired_triggers`;
CREATE TABLE `qrtz_fired_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`entry_id` varchar(95) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`instance_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`fired_time` bigint(13) NOT NULL,
`sched_time` bigint(13) NOT NULL,
`priority` int(11) NOT NULL,
`state` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`job_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`is_nonconcurrent` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`requests_recovery` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`sched_name`,`entry_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_job_details
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_job_details`;
CREATE TABLE `qrtz_job_details` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`job_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`description` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`job_class_name` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`is_durable` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`is_nonconcurrent` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`is_update_data` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`requests_recovery` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`job_data` blob,
PRIMARY KEY (`sched_name`,`job_name`,`job_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_locks
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_locks`;
CREATE TABLE `qrtz_locks` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`lock_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`sched_name`,`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_paused_trigger_grps
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`;
CREATE TABLE `qrtz_paused_trigger_grps` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`sched_name`,`trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_scheduler_state
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_scheduler_state`;
CREATE TABLE `qrtz_scheduler_state` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`instance_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`last_checkin_time` bigint(13) NOT NULL,
`checkin_interval` bigint(13) NOT NULL,
PRIMARY KEY (`sched_name`,`instance_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_simple_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simple_triggers`;
CREATE TABLE `qrtz_simple_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`repeat_count` bigint(7) NOT NULL,
`repeat_interval` bigint(12) NOT NULL,
`times_triggered` bigint(10) NOT NULL,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_simprop_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simprop_triggers`;
CREATE TABLE `qrtz_simprop_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`str_prop_1` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`str_prop_2` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`str_prop_3` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`int_prop_1` int(11) DEFAULT NULL,
`int_prop_2` int(11) DEFAULT NULL,
`long_prop_1` bigint(20) DEFAULT NULL,
`long_prop_2` bigint(20) DEFAULT NULL,
`dec_prop_1` decimal(13,4) DEFAULT NULL,
`dec_prop_2` decimal(13,4) DEFAULT NULL,
`bool_prop_1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`bool_prop_2` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-- ----------------------------
-- Table structure for qrtz_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_triggers`;
CREATE TABLE `qrtz_triggers` (
`sched_name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`job_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`job_group` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`description` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`next_fire_time` bigint(13) DEFAULT NULL,
`prev_fire_time` bigint(13) DEFAULT NULL,
`priority` int(11) DEFAULT NULL,
`trigger_state` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`trigger_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`start_time` bigint(13) NOT NULL,
`end_time` bigint(13) DEFAULT NULL,
`calendar_name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`misfire_instr` smallint(2) DEFAULT NULL,
`job_data` blob,
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
KEY `sched_name` (`sched_name`,`job_name`,`job_group`),
CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `job_name`, `job_group`) REFERENCES `qrtz_job_details` (`sched_name`, `job_name`, `job_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
SET FOREIGN_KEY_CHECKS = 1;

83
easy-activiti/pom.xml

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>easy-vben</artifactId>
<groupId>com.easy.admin</groupId>
<version>1.1.0</version>
</parent>
<artifactId>easy-activiti</artifactId>
<packaging>jar</packaging>
<description>工作流相关功能</description>
<properties>
<activiti.version>5.22.0</activiti.version>
<groovy.version>3.0.0</groovy.version>
</properties>
<dependencies>
<dependency>
<groupId>com.easy.admin</groupId>
<artifactId>easy-sys</artifactId>
</dependency>
<!-- Activiti modeler 可视化依赖 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
<exclusions>
<!-- mybatis 已由mybatis plus 引入 -->
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-modeler</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-diagram-rest</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy.version}</version>
<type>pom</type>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>

139
easy-activiti/src/main/java/com/easy/admin/activiti/config/ActivitiConfig.java

@ -0,0 +1,139 @@
package com.easy.admin.activiti.config;
import cn.hutool.core.date.DatePattern;
import com.easy.admin.activiti.config.factory.CustomGroupEntityManagerFactory;
import com.easy.admin.activiti.config.factory.CustomUserEntityManagerFactory;
import com.easy.admin.activiti.config.manager.CustomProcessDiagramGenerator;
import com.easy.admin.activiti.constant.ActivitiWorkflowConst;
import org.activiti.engine.*;
import org.activiti.engine.form.AbstractFormType;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.form.DateFormType;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
/**
* Activiti Config
*
* @author TengChongChong
* @date 2019-07-01
*/
@Configuration
public class ActivitiConfig {
@Autowired
private CustomUserEntityManagerFactory customUserEntityManagerFactory;
@Autowired
private CustomGroupEntityManagerFactory customGroupEntityManagerFactory;
@Autowired
private CustomProcessDiagramGenerator customProcessDiagramGenerator;
/**
* 流程引擎设置
*
* @param dataSource 数据源
* @param transactionManager transactionManager
* @return ProcessEngineConfiguration
*/
@Bean
public ProcessEngineConfiguration processEngineConfiguration(DataSource dataSource,
PlatformTransactionManager transactionManager) {
SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
processEngineConfiguration.setDataSource(dataSource);
// 如果表不存在,就抛出异常
processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE);
//指定数据库
processEngineConfiguration.setDatabaseType("mysql");
processEngineConfiguration.setTransactionManager(transactionManager);
// 流程图字体
processEngineConfiguration.setActivityFontName(ActivitiWorkflowConst.TYPEFACE);
processEngineConfiguration.setAnnotationFontName(ActivitiWorkflowConst.TYPEFACE);
processEngineConfiguration.setLabelFontName(ActivitiWorkflowConst.TYPEFACE);
// 用户验证表改成使用视图
processEngineConfiguration.setDbIdentityUsed(false);
//自定义用户和组
List<SessionFactory> customSessionFactories = new ArrayList<>();
customSessionFactories.add(customUserEntityManagerFactory);
customSessionFactories.add(customGroupEntityManagerFactory);
processEngineConfiguration.setCustomSessionFactories(customSessionFactories);
// 自定义日期格式化
List<AbstractFormType> customFormTypes = new ArrayList<>();
customFormTypes.add(new DateFormType(DatePattern.NORM_DATE_PATTERN));
processEngineConfiguration.setCustomFormTypes(customFormTypes);
//自定义流程图样式
processEngineConfiguration.setProcessDiagramGenerator(customProcessDiagramGenerator);
return processEngineConfiguration;
}
/**
* 流程引擎与spring整合使用factoryBean
*
* @param processEngineConfiguration processEngineConfiguration
* @return ProcessEngineFactoryBean
*/
@Bean
public ProcessEngineFactoryBean processEngine(ProcessEngineConfiguration processEngineConfiguration) {
ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean();
processEngineFactoryBean.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);
return processEngineFactoryBean;
}
@Bean
public RepositoryService repositoryService(ProcessEngine processEngine) {
return processEngine.getRepositoryService();
}
@Bean
public RuntimeService runtimeService(ProcessEngine processEngine) {
return processEngine.getRuntimeService();
}
@Bean
public TaskService taskService(ProcessEngine processEngine) {
return processEngine.getTaskService();
}
@Bean
public HistoryService historyService(ProcessEngine processEngine) {
return processEngine.getHistoryService();
}
@Bean
public FormService formService(ProcessEngine processEngine) {
return processEngine.getFormService();
}
@Bean
public IdentityService identityService(ProcessEngine processEngine) {
return processEngine.getIdentityService();
}
@Bean
public ManagementService managementService(ProcessEngine processEngine) {
return processEngine.getManagementService();
}
@Bean
public DynamicBpmnService dynamicBpmnService(ProcessEngine processEngine) {
return processEngine.getDynamicBpmnService();
}
}

32
easy-activiti/src/main/java/com/easy/admin/activiti/config/factory/CustomGroupEntityManagerFactory.java

@ -0,0 +1,32 @@
package com.easy.admin.activiti.config.factory;
import com.easy.admin.activiti.config.manager.CustomGroupEntityManager;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.GroupIdentityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 自定义实现Activiti角色管理接口
*
* @author TengChongChong
* @date 2020/3/13
*/
@Service
public class CustomGroupEntityManagerFactory implements SessionFactory {
@Autowired
private CustomGroupEntityManager customGroupEntityManager;
@Override
public Class<?> getSessionType() {
return GroupIdentityManager.class;
}
@Override
public Session openSession() {
return customGroupEntityManager;
}
}

31
easy-activiti/src/main/java/com/easy/admin/activiti/config/factory/CustomUserEntityManagerFactory.java

@ -0,0 +1,31 @@
package com.easy.admin.activiti.config.factory;
import com.easy.admin.activiti.config.manager.CustomUserEntityManager;
import org.activiti.engine.impl.interceptor.Session;
import org.activiti.engine.impl.interceptor.SessionFactory;
import org.activiti.engine.impl.persistence.entity.UserIdentityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 自定义实现Activiti用户管理接口
*
* @author TengChongChong
* @date 2020/3/13
*/
@Service
public class CustomUserEntityManagerFactory implements SessionFactory {
@Autowired
private CustomUserEntityManager customUserEntityManager;
@Override
public Class<?> getSessionType() {
return UserIdentityManager.class;
}
@Override
public Session openSession() {
return customUserEntityManager;
}
}

66
easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomGroupEntityManager.java

@ -0,0 +1,66 @@
package com.easy.admin.activiti.config.manager;
import cn.hutool.core.util.StrUtil;
import com.easy.admin.activiti.config.util.ActivitiUserUtil;
import com.easy.admin.auth.service.SysRoleService;
import org.activiti.engine.identity.Group;
import org.activiti.engine.impl.GroupQueryImpl;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.persistence.entity.GroupEntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* 自定义角色EntityManager
*
* @author TengChongChong
* @date 2020/3/13
*/
@Component
public class CustomGroupEntityManager extends GroupEntityManager {
@Autowired
private SysRoleService roleService;
public CustomGroupEntityManager() {
}
/**
* 根据用户Id获取所属用户组集合
*
* @param userId 用户id
* @return 用户组集合
*/
@Override
public List<Group> findGroupsByUser(String userId) {
if (StrUtil.isBlank(userId)) {
return null;
}
List<String> list = roleService.selectRoleCodeByUserId(userId);
List<Group> groups = ActivitiUserUtil.toActivitiGroups(list);
return groups;
}
@Override
public List<Group> findGroupByQueryCriteria(GroupQueryImpl query, Page page) {
throw new RuntimeException("not implement method.");
}
@Override
public long findGroupCountByQueryCriteria(GroupQueryImpl query) {
throw new RuntimeException("not implement method.");
}
@Override
public List<Group> findGroupsByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults) {
throw new RuntimeException("not implement method.");
}
@Override
public long findGroupCountByNativeQuery(Map<String, Object> parameterMap) {
throw new RuntimeException("not implement method.");
}
}

226
easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomProcessDiagramCanvas.java

@ -0,0 +1,226 @@
package com.easy.admin.activiti.config.manager;
import com.easy.admin.activiti.constant.ActivitiWorkflowConst;
import org.activiti.bpmn.model.AssociationDirection;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.image.exception.ActivitiImageException;
import org.activiti.image.impl.DefaultProcessDiagramCanvas;
import org.activiti.image.util.ReflectUtil;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
/**
* 重写DefaultProcessDiagramCanvas类drawHighLight和drawSequenceflow方法实现走过的历史节点高亮功能
*
* @author TengChongChong
* @date 2020/6/3
*/
public class CustomProcessDiagramCanvas extends DefaultProcessDiagramCanvas {
protected static Color LABEL_COLOR = new Color(0, 0, 0);
private static volatile boolean flag = false;
protected String activityFontName = ActivitiWorkflowConst.TYPEFACE;
protected String labelFontName = ActivitiWorkflowConst.TYPEFACE;
protected String annotationFontName = ActivitiWorkflowConst.TYPEFACE;
public CustomProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType) {
super(width, height, minX, minY, imageType);
}
public CustomProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType,
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName,
customClassLoader);
}
public void drawHighLight(boolean isStartOrEnd, int x, int y, int width, int height, Color color) {
Paint originalPaint = g.getPaint();
Stroke originalStroke = g.getStroke();
g.setPaint(color);
g.setStroke(MULTI_INSTANCE_STROKE);
if (isStartOrEnd) {
// 开始、结束节点画圆
g.drawOval(x, y, width, height);
} else {
// 非开始、结束节点画圆角矩形
RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 5, 5);
g.draw(rect);
}
g.setPaint(originalPaint);
g.setStroke(originalStroke);
}
public void drawSequenceflow(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault,
boolean highLighted, double scaleFactor, Color color) {
drawConnection(xPoints, yPoints, conditional, isDefault, "sequenceFlow", AssociationDirection.ONE, highLighted,
scaleFactor, color);
}
public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault,
String connectionType, AssociationDirection associationDirection, boolean highLighted, double scaleFactor,
Color color) {
Paint originalPaint = g.getPaint();
Stroke originalStroke = g.getStroke();
g.setPaint(CONNECTION_COLOR);
if ("association".equals(connectionType)) {
g.setStroke(ASSOCIATION_STROKE);
} else if (highLighted) {
g.setPaint(color);
g.setStroke(HIGHLIGHT_FLOW_STROKE);
}
for (int i = 1; i < xPoints.length; i++) {
int sourceX = xPoints[i - 1];
int sourceY = yPoints[i - 1];
int targetX = xPoints[i];
int targetY = yPoints[i];
Line2D.Double line = new Line2D.Double(sourceX, sourceY, targetX, targetY);
g.draw(line);
}
if (isDefault) {
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
drawDefaultSequenceFlowIndicator(line, scaleFactor);
}
if (conditional) {
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
drawConditionalSequenceFlowIndicator(line, scaleFactor);
}
if (associationDirection.equals(AssociationDirection.ONE)
|| associationDirection.equals(AssociationDirection.BOTH)) {
Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2], yPoints[xPoints.length - 2],
xPoints[xPoints.length - 1], yPoints[xPoints.length - 1]);
drawArrowHead(line, scaleFactor);
}
if (associationDirection.equals(AssociationDirection.BOTH)) {
Line2D.Double line = new Line2D.Double(xPoints[1], yPoints[1], xPoints[0], yPoints[0]);
drawArrowHead(line, scaleFactor);
}
g.setPaint(originalPaint);
g.setStroke(originalStroke);
}
public void drawLabel(boolean highLighted, String text, GraphicInfo graphicInfo, boolean centered) {
float interline = 1.0f;
// text
if (text != null && text.length() > 0) {
Paint originalPaint = g.getPaint();
Font originalFont = g.getFont();
if (highLighted) {
g.setPaint(ActivitiWorkflowConst.COLOR_NORMAL);
} else {
g.setPaint(LABEL_COLOR);
}
g.setFont(new Font(labelFontName, Font.BOLD, 10));
int wrapWidth = 100;
int textY = (int) graphicInfo.getY();
// TODO: use drawMultilineText()
AttributedString as = new AttributedString(text);
as.addAttribute(TextAttribute.FOREGROUND, g.getPaint());
as.addAttribute(TextAttribute.FONT, g.getFont());
AttributedCharacterIterator aci = as.getIterator();
FontRenderContext frc = new FontRenderContext(null, true, false);
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
while (lbm.getPosition() < text.length()) {
TextLayout tl = lbm.nextLayout(wrapWidth);
textY += tl.getAscent();
Rectangle2D bb = tl.getBounds();
double tX = graphicInfo.getX();
if (centered) {
tX += (int) (graphicInfo.getWidth() / 2 - bb.getWidth() / 2);
}
tl.draw(g, (float) tX, textY);
textY += tl.getDescent() + tl.getLeading() + (interline - 1.0f) * tl.getAscent();
}
// restore originals
g.setFont(originalFont);
g.setPaint(originalPaint);
}
}
@Override
public BufferedImage generateBufferedImage(String imageType) {
if (closed) {
throw new ActivitiImageException("ProcessDiagramGenerator already closed");
}
// Try to remove white space
minX = Math.max(minX, ActivitiWorkflowConst.PROCESS_PADDING);
minY = Math.max(minY, ActivitiWorkflowConst.PROCESS_PADDING);
return processDiagram.getSubimage(
minX - ActivitiWorkflowConst.PROCESS_PADDING,
minY - ActivitiWorkflowConst.PROCESS_PADDING,
canvasWidth - minX + ActivitiWorkflowConst.PROCESS_PADDING,
canvasHeight - minY + ActivitiWorkflowConst.PROCESS_PADDING);
}
@Override
public void initialize(String imageType) {
this.processDiagram = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
this.g = processDiagram.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setPaint(Color.black);
Font font = new Font(activityFontName, Font.BOLD, FONT_SIZE);
g.setFont(font);
this.fontMetrics = g.getFontMetrics();
LABEL_FONT = new Font(labelFontName, Font.ITALIC, 10);
ANNOTATION_FONT = new Font(annotationFontName, Font.PLAIN, FONT_SIZE);
//优化加载速度
if (flag) {
return;
}
try {
USERTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/userTask.png", customClassLoader));
SCRIPTTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/scriptTask.png", customClassLoader));
SERVICETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/serviceTask.png", customClassLoader));
RECEIVETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/receiveTask.png", customClassLoader));
SENDTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/sendTask.png", customClassLoader));
MANUALTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/manualTask.png", customClassLoader));
BUSINESS_RULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/businessRuleTask.png", customClassLoader));
SHELL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/shellTask.png", customClassLoader));
CAMEL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/camelTask.png", customClassLoader));
MULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/muleTask.png", customClassLoader));
TIMER_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/timer.png", customClassLoader));
COMPENSATE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/compensate-throw.png", customClassLoader));
COMPENSATE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/compensate.png", customClassLoader));
ERROR_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/error-throw.png", customClassLoader));
ERROR_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/error.png", customClassLoader));
MESSAGE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/message-throw.png", customClassLoader));
MESSAGE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/message.png", customClassLoader));
SIGNAL_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/signal-throw.png", customClassLoader));
SIGNAL_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/signal.png", customClassLoader));
flag = true;
} catch (IOException e) {
flag = false;
LOGGER.warn("Could not load image for process diagram creation: {}", e.getMessage());
}
}
}

37
easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomProcessDiagramGenerator.java

@ -0,0 +1,37 @@
package com.easy.admin.activiti.config.manager;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.image.ProcessDiagramGenerator;
import java.awt.*;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
/**
* 重写ProcessDiagramGenerator接口中的generateDiagram方法增加color参数
*
* @author TengChongChong
* @date 2020/6/3
*/
public interface CustomProcessDiagramGenerator extends ProcessDiagramGenerator {
/**
* 生成流程图
*
* @param bpmnModel 模型
* @param imageType 图片类型
* @param highLightedActivities 高亮事件
* @param highLightedFlows 高亮箭头
* @param activityFontName 字体
* @param labelFontName label 字体
* @param annotationFontName annotation 字体
* @param customClassLoader classLoader
* @param scaleFactor 比例
* @param colors 颜色
* @param currIds id
* @return InputStream
*/
InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities,
List<String> highLightedFlows, String activityFontName, String labelFontName, String annotationFontName,
ClassLoader customClassLoader, double scaleFactor, Color[] colors, Set<String> currIds);
}

367
easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomProcessDiagramGeneratorImpl.java

@ -0,0 +1,367 @@
package com.easy.admin.activiti.config.manager;
import com.easy.admin.activiti.constant.ActivitiWorkflowConst;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* 实现自定义的CustomProcessDiagramGenerator类
*
* @author TengChongChong
* @date 2020/6/3
*/
@Component
public class CustomProcessDiagramGeneratorImpl extends DefaultProcessDiagramGenerator implements CustomProcessDiagramGenerator {
static {
new CustomProcessDiagramCanvas(
10, 10, 0, 0, "png",
ActivitiWorkflowConst.TYPEFACE, ActivitiWorkflowConst.TYPEFACE, ActivitiWorkflowConst.TYPEFACE, null
);
}
public CustomProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType,
List<String> highLightedActivities, List<String> highLightedFlows, String activityFontName,
String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor,
Color[] colors, Set<String> currIds) {
if (null == highLightedActivities) {
highLightedActivities = Collections.<String>emptyList();
}
if (null == highLightedFlows) {
highLightedFlows = Collections.<String>emptyList();
}
prepareBpmnModel(bpmnModel);
CustomProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
// Draw pool shape, if process is participant in collaboration
for (Pool pool : bpmnModel.getPools()) {
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
processDiagramCanvas.drawPoolOrLane(pool.getName(), graphicInfo);
}
// Draw lanes
for (Process process : bpmnModel.getProcesses()) {
for (Lane lane : process.getLanes()) {
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(lane.getId());
processDiagramCanvas.drawPoolOrLane(lane.getName(), graphicInfo);
}
}
// Draw activities and their sequence-flows
for (Process process : bpmnModel.getProcesses()) {
List<FlowNode> flowNodeList = process.findFlowElementsOfType(FlowNode.class);
for (FlowNode flowNode : flowNodeList) {
drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, highLightedFlows, scaleFactor, colors, currIds);
}
}
// Draw artifacts
for (Process process : bpmnModel.getProcesses()) {
for (Artifact artifact : process.getArtifacts()) {
drawArtifact(processDiagramCanvas, bpmnModel, artifact);
}
List<SubProcess> subProcesses = process.findFlowElementsOfType(SubProcess.class, true);
if (subProcesses != null) {
for (SubProcess subProcess : subProcesses) {
for (Artifact subProcessArtifact : subProcess.getArtifacts()) {
drawArtifact(processDiagramCanvas, bpmnModel, subProcessArtifact);
}
}
}
}
return processDiagramCanvas;
}
protected void drawActivity(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode,
List<String> highLightedActivities, List<String> highLightedFlows, double scaleFactor, Color[] colors, Set<String> currIds) {
ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass());
if (drawInstruction != null) {
drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode);
// Gather info on the multi instance marker
boolean multiInstanceSequential = false, multiInstanceParallel = false, collapsed = false;
if (flowNode instanceof Activity) {
Activity activity = (Activity) flowNode;
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics();
if (multiInstanceLoopCharacteristics != null) {
multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential();
multiInstanceParallel = !multiInstanceSequential;
}
}
// Gather info on the collapsed marker
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
if (flowNode instanceof SubProcess) {
collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded();
} else if (flowNode instanceof CallActivity) {
collapsed = true;
}
if (scaleFactor == 1.0) {
// Actually draw the markers
processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(),
multiInstanceSequential, multiInstanceParallel, collapsed);
}
// Draw highlighted activities
if (highLightedActivities.contains(flowNode.getId())) {
if (!CollectionUtils.isEmpty(currIds)
&& currIds.contains(flowNode.getId())
&& !(flowNode instanceof Gateway)) {
//非结束节点,并且是当前节点
drawHighLight((flowNode instanceof StartEvent), processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId()), colors[1]);
} else {
//普通节点
drawHighLight((flowNode instanceof StartEvent) || (flowNode instanceof EndEvent), processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId()), colors[0]);
}
}
}
// Outgoing transitions of activity
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
String flowId = sequenceFlow.getId();
boolean highLighted = (highLightedFlows.contains(flowId));
String defaultFlow = null;
if (flowNode instanceof Activity) {
defaultFlow = ((Activity) flowNode).getDefaultFlow();
} else if (flowNode instanceof Gateway) {
defaultFlow = ((Gateway) flowNode).getDefaultFlow();
}
boolean isDefault = false;
if (defaultFlow != null && defaultFlow.equalsIgnoreCase(flowId)) {
isDefault = true;
}
String sourceRef = sequenceFlow.getSourceRef();
String targetRef = sequenceFlow.getTargetRef();
FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef);
FlowElement targetElement = bpmnModel.getFlowElement(targetRef);
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(flowId);
if (graphicInfoList != null && !graphicInfoList.isEmpty()) {
graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList);
int[] xPoints = new int[graphicInfoList.size()];
int[] yPoints = new int[graphicInfoList.size()];
for (int i = 1; i < graphicInfoList.size(); i++) {
GraphicInfo graphicInfo = graphicInfoList.get(i);
GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1);
if (i == 1) {
xPoints[0] = (int) previousGraphicInfo.getX();
yPoints[0] = (int) previousGraphicInfo.getY();
}
xPoints[i] = (int) graphicInfo.getX();
yPoints[i] = (int) graphicInfo.getY();
}
// 画高亮线
processDiagramCanvas.drawSequenceflow(xPoints, yPoints, false, isDefault, highLighted, scaleFactor, colors[0]);
// 解决流程图连线名称不显示的BUG
GraphicInfo lineCenter = getLineCenter(graphicInfoList);
processDiagramCanvas.drawLabel(highLighted, sequenceFlow.getName(), lineCenter, Math.abs(xPoints[1] - xPoints[0]) >= 5);
}
}
// Nested elements
if (flowNode instanceof FlowElementsContainer) {
for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) {
if (nestedFlowElement instanceof FlowNode) {
drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement,
highLightedActivities, highLightedFlows, scaleFactor);
}
}
}
}
protected void drawHighLight(boolean isStartOrEnd, CustomProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo, Color color) {
processDiagramCanvas.drawHighLight(isStartOrEnd, (int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), color);
}
protected static CustomProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType,
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
// We need to calculate maximum values to know how big the image will be in its entirety
double minX = Double.MAX_VALUE;
double maxX = 0;
double minY = Double.MAX_VALUE;
double maxY = 0;
for (Pool pool : bpmnModel.getPools()) {
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
minX = graphicInfo.getX();
maxX = graphicInfo.getX() + graphicInfo.getWidth();
minY = graphicInfo.getY();
maxY = graphicInfo.getY() + graphicInfo.getHeight();
}
List<FlowNode> flowNodes = gatherAllFlowNodes(bpmnModel);
for (FlowNode flowNode : flowNodes) {
GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
// width
if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) {
maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth();
}
if (flowNodeGraphicInfo.getX() < minX) {
minX = flowNodeGraphicInfo.getX();
}
// height
if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) {
maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight();
}
if (flowNodeGraphicInfo.getY() < minY) {
minY = flowNodeGraphicInfo.getY();
}
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());
if (graphicInfoList != null) {
for (GraphicInfo graphicInfo : graphicInfoList) {
// width
if (graphicInfo.getX() > maxX) {
maxX = graphicInfo.getX();
}
if (graphicInfo.getX() < minX) {
minX = graphicInfo.getX();
}
// height
if (graphicInfo.getY() > maxY) {
maxY = graphicInfo.getY();
}
if (graphicInfo.getY() < minY) {
minY = graphicInfo.getY();
}
}
}
}
}
List<Artifact> artifacts = gatherAllArtifacts(bpmnModel);
for (Artifact artifact : artifacts) {
GraphicInfo artifactGraphicInfo = bpmnModel.getGraphicInfo(artifact.getId());
if (artifactGraphicInfo != null) {
// width
if (artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth() > maxX) {
maxX = artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth();
}
if (artifactGraphicInfo.getX() < minX) {
minX = artifactGraphicInfo.getX();
}
// height
if (artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight() > maxY) {
maxY = artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight();
}
if (artifactGraphicInfo.getY() < minY) {
minY = artifactGraphicInfo.getY();
}
}
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId());
if (graphicInfoList != null) {
for (GraphicInfo graphicInfo : graphicInfoList) {
// width
if (graphicInfo.getX() > maxX) {
maxX = graphicInfo.getX();
}
if (graphicInfo.getX() < minX) {
minX = graphicInfo.getX();
}
// height
if (graphicInfo.getY() > maxY) {
maxY = graphicInfo.getY();
}
if (graphicInfo.getY() < minY) {
minY = graphicInfo.getY();
}
}
}
}
int nrOfLanes = 0;
for (Process process : bpmnModel.getProcesses()) {
for (Lane l : process.getLanes()) {
nrOfLanes++;
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId());
// // width
if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) {
maxX = graphicInfo.getX() + graphicInfo.getWidth();
}
if (graphicInfo.getX() < minX) {
minX = graphicInfo.getX();
}
// height
if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) {
maxY = graphicInfo.getY() + graphicInfo.getHeight();
}
if (graphicInfo.getY() < minY) {
minY = graphicInfo.getY();
}
}
}
// Special case, see https://activiti.atlassian.net/browse/ACT-1431
if (flowNodes.isEmpty() && bpmnModel.getPools().isEmpty() && nrOfLanes == 0) {
// Nothing to show
minX = 0;
minY = 0;
}
return new CustomProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY,
imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
}
@Override
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities,
List<String> highLightedFlows, String activityFontName, String labelFontName, String annotationFontName,
ClassLoader customClassLoader, double scaleFactor, Color[] colors, Set<String> currIds) {
CustomProcessDiagramCanvas customProcessDiagramCanvas = generateProcessDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows,
activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor, colors, currIds);
BufferedImage bufferedImage = customProcessDiagramCanvas.generateBufferedImage(imageType);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imOut;
try {
imOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(bufferedImage, "PNG", imOut);
} catch (IOException e) {
e.printStackTrace();
}
InputStream is = new ByteArrayInputStream(bs.toByteArray());
return is;
}
@Override
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
return generateDiagram(bpmnModel, imageType, Collections.<String>emptyList(), Collections.<String>emptyList(),
activityFontName, labelFontName, annotationFontName, customClassLoader, 1.0, new Color[]{Color.BLACK, Color.BLACK}, null);
}
}

129
easy-activiti/src/main/java/com/easy/admin/activiti/config/manager/CustomUserEntityManager.java

@ -0,0 +1,129 @@
package com.easy.admin.activiti.config.manager;
import cn.hutool.core.util.StrUtil;
import com.easy.admin.activiti.config.util.ActivitiUserUtil;
import com.easy.admin.activiti.constant.ActivitiWorkflowConst;
import com.easy.admin.auth.model.SysUser;
import com.easy.admin.auth.service.SysRoleService;
import com.easy.admin.auth.service.SysUserService;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.UserQueryImpl;
import org.activiti.engine.impl.persistence.entity.IdentityInfoEntity;
import org.activiti.engine.impl.persistence.entity.UserEntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 自定义用户EntityManager
*
* @author TengChongChong
* @date 2020/3/13
*/
@Component
public class CustomUserEntityManager extends UserEntityManager {
@Autowired
private SysUserService userService;
@Autowired
private SysRoleService roleService;
/**
* 根据userId获取用户Activiti信息
*
* @param userId 用户id
* @return 用户信息Activiti
*/
@Override
public User findUserById(String userId) {
SysUser user = userService.getUser(userId);
return ActivitiUserUtil.toActivitiUser(user);
}
/**
* 根据userId获取用户所属用户组集合
*
* @param userId 用户id
* @return 用户组集合
*/
@Override
public List<Group> findGroupsByUser(String userId) {
if (StrUtil.isBlank(userId)) {
return null;
}
List<String> list = roleService.selectRoleCodeByUserId(userId);
return ActivitiUserUtil.toActivitiGroups(list);
}
/**
* 查找用户
*
* @param query 查询条件
* @param page 分页
* @return 用户集合
*/
@Override
public List<User> findUserByQueryCriteria(UserQueryImpl query, Page page) {
SysUser user = getUser(query.getId());
List<User> list = new ArrayList<>();
list.add(ActivitiUserUtil.toActivitiUser(user));
return list;
}
/**
* 根据userId获取用户信息
*
* @param userId 用户id
* @return SysUser
*/
private SysUser getUser(String userId) {
SysUser user = new SysUser();
// 判断是否是系统管理员
if (ActivitiWorkflowConst.INTERFACE_SYSTEM_ID.equals(userId)) {
user.setId(ActivitiWorkflowConst.INTERFACE_SYSTEM_ID);
user.setNickname(ActivitiWorkflowConst.INTERFACE_SYSTEM_NAME);
user.setPassword("");
user.setEmail("");
} else {
user = userService.getUser(userId);
}
return user;
}
@Override
public long findUserCountByQueryCriteria(UserQueryImpl query) {
throw new RuntimeException("not implement method.");
}
@Override
public IdentityInfoEntity findUserInfoByUserIdAndKey(String userId, String key) {
throw new RuntimeException("not implement method.");
}
@Override
public List<String> findUserInfoKeysByUserIdAndType(String userId, String type) {
throw new RuntimeException("not implement method.");
}
@Override
public List<User> findPotentialStarterUsers(String proceDefId) {
throw new RuntimeException("not implement method.");
}
@Override
public List<User> findUsersByNativeQuery(Map<String, Object> parameterMap,
int firstResult, int maxResults) {
throw new RuntimeException("not implement method.");
}
@Override
public long findUserCountByNativeQuery(Map<String, Object> parameterMap) {
throw new RuntimeException("not implement method.");
}
}

65
easy-activiti/src/main/java/com/easy/admin/activiti/config/util/ActivitiUserUtil.java

@ -0,0 +1,65 @@
package com.easy.admin.activiti.config.util;
import com.easy.admin.auth.model.SysUser;
import org.activiti.engine.identity.Group;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import java.util.ArrayList;
import java.util.List;
/**
* 将业务系统中用户与角色转为Activiti所需的类型
*
* @author TengChongChong
* @date 2020/3/13
*/
public class ActivitiUserUtil {
/**
* 将SysUser转为Activiti中的UserEntity
*
* @param sysUser SysUser
* @return UserEntity
*/
public static UserEntity toActivitiUser(SysUser sysUser) {
UserEntity userEntity = new UserEntity();
userEntity.setId(sysUser.getId());
userEntity.setFirstName(sysUser.getNickname());
userEntity.setLastName(sysUser.getNickname());
userEntity.setPassword(sysUser.getPassword());
userEntity.setEmail(sysUser.getEmail());
userEntity.setRevision(1);
return userEntity;
}
/**
* 获取Activiti中的GroupEntity
*
* @param code 标识
* @return GroupEntity
*/
public static GroupEntity toActivitiGroup(String code) {
GroupEntity groupEntity = new GroupEntity();
groupEntity.setRevision(1);
groupEntity.setType("assignment");
groupEntity.setId(code);
return groupEntity;
}
/**
* 将一组角色标识转为Activiti中的角色标识
*
* @param roleCodeList 角色标识集合
* @return List<Group>
*/
public static List<Group> toActivitiGroups(List<String> roleCodeList) {
List<Group> groups = new ArrayList<>();
for (String code : roleCodeList) {
// GroupEntity groupEntity = toActivitiGroup(enterpriseBasicId, code);
GroupEntity groupEntity = toActivitiGroup(code);
groups.add(groupEntity);
}
return groups;
}
}

25
easy-activiti/src/main/java/com/easy/admin/activiti/constant/ActivitiModelConst.java

@ -0,0 +1,25 @@
package com.easy.admin.activiti.constant;
/**
* Activiti 流程模型
*
* @author TengChongChong
* @date 2019-07-03
*/
public class ActivitiModelConst {
/**
* 模型属性 - MetaInfo
*/
public static final String NAME = "name";
public static final String ID = "id";
public static final String VERSION = "version";
public static final String DESCRIPTION = "description";
/**
* 模型属性 - properties
*/
public static final String PROPERTIES = "properties";
public static final String PROPERTIES_PROCESS_ID = "process_id";
public static final String PROPERTIES_PROCESS_AUTHOR = "process_author";
public static final String PROPERTIES_DOCUMENTATION = "documentation";
}

19
easy-activiti/src/main/java/com/easy/admin/activiti/constant/ActivitiTaskStatusConst.java

@ -0,0 +1,19 @@
package com.easy.admin.activiti.constant;
/**
* 任务状态
*
* @author TengChongChong
* @date 2020/3/31
*/
public class ActivitiTaskStatusConst {
/**
* 待签收
*/
public static final String WAITING_CLAIM = "waitingClaim";
/**
* 已签收
*/
public static final String CLAIMED = "claimed";
}

50
easy-activiti/src/main/java/com/easy/admin/activiti/constant/ActivitiVariableConst.java

@ -0,0 +1,50 @@
package com.easy.admin.activiti.constant;
/**
* 流程参数key
*
* @author TengChongChong
* @date 2020/4/27
*/
public class ActivitiVariableConst {
/**
* 业务数据ID
*/
public static final String BUSINESS_KEY = "businessKey";
/**
* 业务标题
*/
public static final String BUSINESS_TITLE = "businessTitle";
/**
* 业务数据详情url
*/
public static final String BUSINESS_DETAILS_URL = "businessDetailsPath";
/**
* 流程发起人id
*/
public static final String APPLY_USER_ID = "applyUserId";
/**
* 流程发起人昵称
*/
public static final String APPLY_USER_NICKNAME = "applyUserNickname";
/**
* 流程发起人所在部门ID
*/
public static final String DEPT_ID = "deptId";
/**
* 流程发起人所在部门type code
*/
public static final String DEPT_TYPE_CODE = "deptTypeCode";
/**
* 流程发起人所在部门type name
*/
public static final String DEPT_TYPE_NAME = "deptTypeName";
/**
* 流程发起人所在部门名称
*/
public static final String DEPT_NAME = "deptName";
/**
* 流程发起人所属角色 eg: role1,role2,role3
*/
public static final String USER_ROLE_CODES = "userRoleCodes";
}

45
easy-activiti/src/main/java/com/easy/admin/activiti/constant/ActivitiWorkflowConst.java

@ -0,0 +1,45 @@
package com.easy.admin.activiti.constant;
import java.awt.*;
/**
* 工作流
*
* @author TengChongChong
* @date 2020/3/13
*/
public class ActivitiWorkflowConst {
/**
* 系统管理员id
*/
public static final String INTERFACE_SYSTEM_ID = "1";
/**
* 系统管理员名称
*/
public static final String INTERFACE_SYSTEM_NAME = "系统管理员";
/**
* 系统管理员角色标识
*/
public static final String SYS_ADMIN_ROLE = "sys:admin";
/**
* 字体
*/
public static final String TYPEFACE = "宋体";
/**
* 流程图颜色 - 走过的节点
*/
public static final Color COLOR_NORMAL = new Color(83, 195, 27);
/**
* 流程图颜色 - 当前节点
*/
public static final Color COLOR_CURRENT = new Color(25, 144, 255);
/**
* 定义生成流程图时的边距像素
*/
public static final int PROCESS_PADDING = 5;
}

30
easy-activiti/src/main/java/com/easy/admin/activiti/constant/status/ActivitiSuspensionStatus.java

@ -0,0 +1,30 @@
package com.easy.admin.activiti.constant.status;
/**
* 挂起状态
*
* @author TengChongChong
* @date 2020/5/22
*/
public enum ActivitiSuspensionStatus {
// 激活
ACTIVATION(1, "激活"),
// 挂起
SUSPENSION(2, "挂起");
int code;
String message;
ActivitiSuspensionStatus(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

32
easy-activiti/src/main/java/com/easy/admin/activiti/constant/status/ActivitiTaskStatus.java

@ -0,0 +1,32 @@
package com.easy.admin.activiti.constant.status;
/**
* 任务状态
*
* @author TengChongChong
* @date 2020/5/22
*/
public enum ActivitiTaskStatus {
// 办理中
IN_PROCESS("1", "办理中"),
// 已撤销
RESCINDED("-1", "已撤销"),
// 已办结
COMPLETED("2", "已办结");
String code;
String message;
ActivitiTaskStatus(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
}

47
easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiHistoricController.java

@ -0,0 +1,47 @@
package com.easy.admin.activiti.controller;
import com.easy.admin.activiti.model.ActivitiHistoric;
import com.easy.admin.activiti.model.ActivitiTask;
import com.easy.admin.activiti.service.ActivitiHistoricService;
import com.easy.admin.common.core.annotation.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 流程历史活动记录
*
* @author TengChongChong
* @date 2020/5/7
*/
@RestController
@ResponseResult
@RequestMapping("/api/auth/activiti/historic")
public class ActivitiHistoricController {
@Autowired
private ActivitiHistoricService service;
/**
* 查询数据
*
* @param processInstanceId 流程实例ID
* @return List<Historic>
*/
@GetMapping("processInstanceId/{processInstanceId}")
public List<ActivitiHistoric> select(@PathVariable("processInstanceId") String processInstanceId) {
return service.select(processInstanceId);
}
/**
* 根据业务id查询流程实例
*
* @param businessKey 业务id
* @return Task
*/
@GetMapping("task")
public ActivitiTask selectTask(String businessKey){
return service.selectTask(businessKey);
}
}

60
easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiHistoryTaskInstanceController.java

@ -0,0 +1,60 @@
package com.easy.admin.activiti.controller;
import com.easy.admin.activiti.model.ActivitiHistoryTaskInstance;
import com.easy.admin.activiti.service.ActivitiHistoryTaskInstanceService;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.annotation.ResponseResult;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 历史任务实例
*
* @author TengChongChong
* @date 2020/5/14
*/
@RestController
@ResponseResult
@RequestMapping("/api/auth/activiti/history/task-instance")
public class ActivitiHistoryTaskInstanceController {
@Autowired
private ActivitiHistoryTaskInstanceService service;
/**
* 我发起的
*
* @param task 查询条件
* @return Page<HistoryTaskInstance>
*/
@GetMapping("my")
@RequiresPermissions("activiti:historic:select:my")
public Page<ActivitiHistoryTaskInstance> selectMy(ActivitiHistoryTaskInstance task, Page<ActivitiHistoryTaskInstance> page) {
return service.selectMy(task, page);
}
/**
* 我办理的
*
* @param task 查询条件
* @return Page<HistoryTaskInstance>
*/
@GetMapping("participate")
@RequiresPermissions("activiti:historic:select:participate")
public Page<ActivitiHistoryTaskInstance> selectParticipate(ActivitiHistoryTaskInstance task, Page<ActivitiHistoryTaskInstance> page) {
return service.selectParticipate(task, page);
}
/**
* 所有任务
*
* @param task 查询条件
* @return Page<HistoryTaskInstance>
*/
@GetMapping("all")
@RequiresPermissions("activiti:historic:select:all")
public Page<ActivitiHistoryTaskInstance> selectAll(ActivitiHistoryTaskInstance task, Page<ActivitiHistoryTaskInstance> page) {
return service.selectAll(task, page);
}
}

152
easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiModelController.java

@ -0,0 +1,152 @@
package com.easy.admin.activiti.controller;
import com.easy.admin.activiti.model.ActivitiModel;
import com.easy.admin.activiti.service.ActivitiModelService;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.annotation.ResponseResult;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.engine.impl.persistence.entity.ModelEntity;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* Activiti 流程模型
*
* @author TengChongChong
* @date 2019-07-03
*/
@RestController
@RequestMapping("/api/auth/activiti/model")
public class ActivitiModelController {
@Autowired
private ActivitiModelService service;
/**
* 列表
*
* @param object 查询条件
* @return Page<ActivitiModel>
*/
@RequestMapping()
@ResponseResult
@RequiresPermissions("activiti:model:select")
public Page<ActivitiModel> select(ActivitiModel object, Page<ActivitiModel> page) {
return service.select(object, page);
}
/**
* 详情
*
* @param id id
* @return String
*/
@GetMapping("{id}")
@ResponseResult
@RequiresPermissions("activiti:model:select")
public ModelEntity get(@PathVariable("id") String id) {
return service.get(id);
}
/**
* 详情
*
* @param id id
* @return String
*/
@GetMapping("{id}/json")
@ResponseResult
@RequiresPermissions("activiti:model:select")
public ObjectNode getModel(@PathVariable("id") String id) {
return service.getModel(id);
}
/**
* 删除
*
* @param ids 数据ids
* @return true/false
*/
@DeleteMapping("{ids}")
@ResponseResult
@RequiresPermissions("activiti:model:remove")
public boolean remove(@PathVariable("ids") String ids) {
return service.remove(ids);
}
/**
* 保存
*
* @param object 表单内容
* @return ModelEntity
*/
@PostMapping()
@ResponseResult
@RequiresPermissions("activiti:model:save")
public ModelEntity saveData(@RequestBody @Valid ActivitiModel object) {
return service.saveData(object);
}
@PutMapping("{id}")
@ResponseResult
@RequiresPermissions("activiti:model:save")
public boolean saveModel(@PathVariable("id") String id, String name,
String description,
@RequestParam("json_xml") String jsonXml,
@RequestParam("svg_xml") String svgXml) {
service.saveModel(id, name, description, jsonXml, svgXml);
return true;
}
/**
* 读取stencilset.json文件
*
* @return 文件内容
*/
@GetMapping("stencilset")
public String getStencilset() {
return service.getStencilset();
}
/**
* 部署流程
*
* @param id 模型id
* @return true/false
*/
@PostMapping("deployment/process/{id}")
@ResponseResult
@RequiresPermissions("activiti:model:save")
public boolean deploymentProcess(@PathVariable("id") String id) {
return service.deploymentProcess(id);
}
/**
* 导出模型
*
* @param id 模型id
* @return sys download id
*/
@GetMapping("export/{id}")
@ResponseResult
@RequiresPermissions("activiti:model:select")
public String export(@PathVariable("id") String id) {
return service.export(id);
}
/**
* 根据模型标识查询流程定义ID
*
* @param key 模型标识
* @return 流程定义ID
*/
@GetMapping("process/definition/id/{key}")
@ResponseResult
@RequiresPermissions("activiti:model:select")
public String selectProcessDefinitionId(@PathVariable("key") String key) {
return service.selectProcessDefinitionId(key);
}
}

128
easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiProcessController.java

@ -0,0 +1,128 @@
package com.easy.admin.activiti.controller;
import com.easy.admin.activiti.model.ActivitiProcess;
import com.easy.admin.activiti.service.ActivitiProcessService;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.common.select.Select;
import com.easy.admin.common.core.constant.CommonConst;
import com.easy.admin.common.core.annotation.ResponseResult;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* 流程
*
* @author TengChongChong
* @date 2019-07-12
*/
@RestController
public class ActivitiProcessController {
@Autowired
private ActivitiProcessService service;
/**
* 查询数据
*
* @param activitiProcess 查询条件
* @return 数据
*/
@GetMapping("/api/auth/activiti/process")
@ResponseResult
@RequiresPermissions("activiti:process:select")
public Page<ActivitiProcess> select(ActivitiProcess activitiProcess, Page<ActivitiProcess> page) {
return service.select(activitiProcess, page);
}
/**
* 删除
*
* @param deploymentIds 部署ds
* @return true/false
*/
@DeleteMapping("/api/auth/activiti/process/{deploymentIds}")
@ResponseResult
@RequiresPermissions("activiti:process:remove")
public boolean remove(@PathVariable("deploymentIds") String deploymentIds) {
return service.remove(deploymentIds);
}
/**
* 流程转模型
*
* @param activitiProcess process
* @return true/false
*/
@PostMapping("/api/auth/activiti/process/convert/to/model")
@ResponseResult
@RequiresPermissions("activiti:model:save")
public boolean convertToModel(@RequestBody ActivitiProcess activitiProcess) {
return service.convertToModel(activitiProcess);
}
/**
* 查看流程图片
*
* @param deploymentId 部署id
* @param resourceName 资源名称
*/
@GetMapping("/api/activiti/process/{deploymentId}/{resourceName}/image/stream")
public void getImageStream(@PathVariable("deploymentId") String deploymentId,
@PathVariable("resourceName") String resourceName, HttpServletResponse response) throws IOException {
InputStream inputStream = service.getImageStream(deploymentId, resourceName);
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes, 0, CommonConst.BYTE1024)) != -1) {
response.getOutputStream().write(bytes, 0, len);
}
}
/**
* 挂起流程
*
* @param processDefinitionId 流程id
* @param suspendProcessInstances 如果为true将同时挂起此流程正在进行的任务
* @return true/false
*/
@PostMapping("/api/auth/activiti/process/suspend/{processDefinitionId}/{suspendProcessInstances}")
@ResponseResult
@RequiresPermissions("activiti:process:suspend")
public boolean suspend(@PathVariable("processDefinitionId") String processDefinitionId,
@PathVariable("suspendProcessInstances") boolean suspendProcessInstances) {
service.suspend(processDefinitionId, suspendProcessInstances);
return true;
}
/**
* 激活流程
*
* @param processDefinitionId 流程id
* @param suspendProcessInstances 如果为true将同时激活此流程正在进行的任务
* @return true/false
*/
@PostMapping("/api/auth/activiti/process/activation/{processDefinitionId}/{suspendProcessInstances}")
@ResponseResult
@RequiresPermissions("activiti:process:activation")
public boolean activation(@PathVariable("processDefinitionId") String processDefinitionId,
@PathVariable("suspendProcessInstances") boolean suspendProcessInstances) {
service.activation(processDefinitionId, suspendProcessInstances);
return true;
}
/**
* 查询流程数据用于放到select的option中
*
* @return List<Select>
*/
@GetMapping("/api/auth/activiti/process/process/for/select")
@ResponseResult
public List<Select> selectProcessForSelect() {
return service.selectProcessForSelect();
}
}

47
easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiProcessDefinitionController.java

@ -0,0 +1,47 @@
package com.easy.admin.activiti.controller;
import cn.hutool.json.JSONObject;
import com.easy.admin.activiti.model.ActivitiProcessDefinitionVO;
import com.easy.admin.activiti.service.ActivitiProcessDefinitionService;
import com.easy.admin.common.core.annotation.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* 启动流程
*
* @author TengChongChong
* @date 2020/3/26
*/
@RestController
@ResponseResult
@RequestMapping("/api/auth/activiti/process/definition")
public class ActivitiProcessDefinitionController {
@Autowired
private ActivitiProcessDefinitionService service;
/**
* 读取流程表单
*
* @param processDefinitionId 流程id
* @return JSONObject
*/
@GetMapping("start/form/{processDefinitionId}")
public JSONObject readStartForm(@PathVariable("processDefinitionId") String processDefinitionId) {
return service.readStartForm(processDefinitionId);
}
/**
* 启动流程
*
* @param activitiProcessDefinitionVO 流程数据
* @return JSONObject
*/
@PostMapping("process/instance")
public JSONObject startProcessInstance(@RequestBody @Valid ActivitiProcessDefinitionVO activitiProcessDefinitionVO) {
return service.startProcessInstance(activitiProcessDefinitionVO);
}
}

39
easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiProcessTraceController.java

@ -0,0 +1,39 @@
package com.easy.admin.activiti.controller;
import com.easy.admin.activiti.service.ActivitiProcessTraceService;
import com.easy.admin.common.core.annotation.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 流程跟踪
*
* @author TengChongChong
* @date 2019-07-12
*/
@RestController
@ResponseResult
@RequestMapping("/api/activiti/process/trace")
public class ActivitiProcessTraceController {
@Autowired
ActivitiProcessTraceService service;
/**
* 查看流程实例进度
*
* @param processInstanceId 流程实例ID
* @param response response
* @throws IOException ex
*/
@GetMapping(value = "process/progress/image/{processInstanceId}")
public void processProgressImage(@PathVariable("processInstanceId") String processInstanceId, HttpServletResponse response) throws IOException {
service.readProcessImg(processInstanceId, response);
}
}

88
easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiTaskController.java

@ -0,0 +1,88 @@
package com.easy.admin.activiti.controller;
import cn.hutool.json.JSONObject;
import com.easy.admin.activiti.model.ActivitiTask;
import com.easy.admin.activiti.model.ActivitiTaskInfo;
import com.easy.admin.activiti.service.ActivitiTaskService;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.annotation.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 待办任务
*
* @author TengChongChong
* @date 2020/3/26
*/
@RestController
@ResponseResult
@RequestMapping("/api/auth/activiti/task")
public class ActivitiTaskController {
@Autowired
private ActivitiTaskService service;
/**
* 查询数据
*
* @param status 任务状态
* @param activitiTask 查询条件
* @return Page<Task>
*/
@GetMapping("status/{status}")
public Page<ActivitiTask> select(@PathVariable("status") String status, ActivitiTask activitiTask, Page<ActivitiTask> page) {
activitiTask.setStatus(status);
return service.select(activitiTask, page);
}
/**
* 签收任务
*
* @param taskId 任务id
* @return true/false
*/
@PostMapping("claim/task/{taskId}")
public boolean claimTask(@PathVariable("taskId") String taskId) {
service.claimTask(taskId);
return true;
}
/**
* 获取任务信息
*
* @param taskId 任务Id
* @return ActivitiTaskInfo
*/
@GetMapping("{taskId}")
public ActivitiTaskInfo getTaskInfo(@PathVariable("taskId") String taskId) {
return service.readTaskForm(taskId);
}
/**
* 流转任务
*
* @param taskId 任务Id
* @param params params
* @return true/false
*/
@PostMapping("complete/task/{taskId}")
public boolean completeTask(@PathVariable("taskId") String taskId, @RequestBody JSONObject params) {
service.completeTask(taskId, params);
return true;
}
/**
* 撤销申请
*
* @param processInstanceId 流程实例ID
* @param params {deleteReason: "xxx"}
* @return true/false
*/
@PostMapping("revoke/{processInstanceId}")
public boolean revoke(@PathVariable("processInstanceId") String processInstanceId,
@RequestBody JSONObject params) {
service.revoke(processInstanceId, params.getStr("deleteReason"));
return true;
}
}

38
easy-activiti/src/main/java/com/easy/admin/activiti/controller/ActivitiVariableController.java

@ -0,0 +1,38 @@
package com.easy.admin.activiti.controller;
import com.easy.admin.common.core.annotation.ResponseResult;
import org.activiti.engine.HistoryService;
import org.activiti.engine.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 流程相关变量
*
* @author TengChongChong
* @date 2020/5/7
*/
@RestController
@ResponseResult
@RequestMapping("/api/auth/activiti/variable")
public class ActivitiVariableController {
@Autowired
private HistoryService service;
/**
* 查询数据
*
* @param processInstanceId 流程实例ID
* @return 数据
*/
@GetMapping("processInstanceId/{processInstanceId}")
public List<HistoricVariableInstance> select(@PathVariable("processInstanceId") String processInstanceId) {
return service.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).orderByVariableName().asc().list();
}
}

33
easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiHistoricMapper.java

@ -0,0 +1,33 @@
package com.easy.admin.activiti.dao;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.easy.admin.activiti.model.ActivitiHistoric;
import com.easy.admin.activiti.model.ActivitiTask;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 流程历史活动记录
*
* @author TengChongChong
* @date 2020/5/7
*/
public interface ActivitiHistoricMapper extends BaseMapper<ActivitiHistoric> {
/**
* 获取列表数据
*
* @param queryWrapper 查询条件
* @return 数据列表
*/
List<ActivitiHistoric> select(@Param("ew") QueryWrapper<ActivitiHistoric> queryWrapper);
/**
* 根据业务id查询流程实例
*
* @param businessKey 业务id
* @return 流程实例
*/
ActivitiTask selectTask(@Param("businessKey") String businessKey);
}

33
easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiHistoryTaskInstanceMapper.java

@ -0,0 +1,33 @@
package com.easy.admin.activiti.dao;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.easy.admin.activiti.model.ActivitiHistoryTaskInstance;
import com.easy.admin.common.core.common.pagination.Page;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 流程历史活动记录
*
* @author TengChongChong
* @date 2020/5/14
*/
public interface ActivitiHistoryTaskInstanceMapper extends BaseMapper<ActivitiHistoryTaskInstance> {
/**
* 查询历史任务
*
* @param page 分页
* @param queryWrapper 查询条件
* @param historyOrderType 历史排序规则desc/asc
* @return 数据列表
*/
List<ActivitiHistoryTaskInstance> select(
Page<ActivitiHistoryTaskInstance> page,
@Param("ew") QueryWrapper<ActivitiHistoryTaskInstance> queryWrapper,
@Param("historyOrderType") String historyOrderType
);
}

44
easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiModelMapper.java

@ -0,0 +1,44 @@
package com.easy.admin.activiti.dao;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.easy.admin.activiti.model.ActivitiModel;
import com.easy.admin.common.core.common.pagination.Page;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 流程模型
*
* @author TengChong
* @date 2020-05-08
*/
public interface ActivitiModelMapper extends BaseMapper<ActivitiModel> {
/**
* 获取列表数据
*
* @param page 分页
* @param queryWrapper 查询条件
* @return 数据列表
*/
List<ActivitiModel> select(Page<ActivitiModel> page, @Param("ew") QueryWrapper<ActivitiModel> queryWrapper);
/**
* 获取列表数据
*
* @param key 模型标识
* @param suspensionState 流程状态
* @return 流程定义ID
*/
String selectProcessDefinitionId(@Param("key") String key, @Param("suspensionState") int suspensionState);
/**
* 检查流程标识是否存在
*
* @param queryWrapper 查询条件
* @return true/false
*/
Integer selectCountByKey(@Param("ew") QueryWrapper<ActivitiModel> queryWrapper);
}

39
easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiProcessDefinitionMapper.java

@ -0,0 +1,39 @@
package com.easy.admin.activiti.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.easy.admin.activiti.model.ActivitiProcess;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 启动流程
*
* @author TengChongChong
* @date 2020/5/7
*/
public interface ActivitiProcessDefinitionMapper extends BaseMapper<ActivitiProcess> {
/**
* 检查业务数据是否提交过流程一条数据只能提交一次
*
* @param businessKey 业务数据id
* @return 数量
*/
int countBusinessKey(@Param("businessKey") String businessKey);
/**
* 根据流程实例ID查询任务ID
*
* @param processInstanceId 流程实例ID
* @return 任务ID
*/
String selectTaskId(@Param("processInstanceId") String processInstanceId);
/**
* 根据任务id查询候选人列表
*
* @param taskId 任务ID
* @return 候选人id列表
*/
List<String> selectCandidate(@Param("taskId") String taskId);
}

42
easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiProcessMapper.java

@ -0,0 +1,42 @@
package com.easy.admin.activiti.dao;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.easy.admin.activiti.model.ActivitiProcess;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.common.select.Select;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 流程管理
*
* @author TengChongChong
* @date 2020/5/22
*/
public interface ActivitiProcessMapper extends BaseMapper<ActivitiProcess> {
/**
* 获取列表数据
*
* @param page 分页
* @param queryWrapper 查询条件
* @return 数据列表
*/
List<ActivitiProcess> select(Page<ActivitiProcess> page, @Param("ew") QueryWrapper<ActivitiProcess> queryWrapper);
/**
* 查询详情
*
* @param id 流程实例ID
* @return 流程详情
*/
ActivitiProcess getById(@Param("id") String id);
/**
* 查询流程数据用于放到select的option中
*
* @return 数据集合
*/
List<Select> selectProcessForSelect();
}

44
easy-activiti/src/main/java/com/easy/admin/activiti/dao/ActivitiTaskMapper.java

@ -0,0 +1,44 @@
package com.easy.admin.activiti.dao;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.easy.admin.activiti.model.ActivitiTask;
import com.easy.admin.common.core.common.pagination.Page;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 流程跟踪
*
* @author TengChong
* @date 2020-04-26
*/
public interface ActivitiTaskMapper extends BaseMapper<ActivitiTask> {
/**
* 获取列表数据
*
* @param page 分页
* @param queryWrapper 查询条件
* @return 数据列表
*/
List<ActivitiTask> select(Page<ActivitiTask> page, @Param("ew") QueryWrapper<ActivitiTask> queryWrapper);
List<ActivitiTask> select(@Param("ew") QueryWrapper<ActivitiTask> queryWrapper);
/**
* 根据任务ID查询流程定义ID
*
* @param taskId 任务ID
* @param activation 激活流程状态
* @return Task
*/
ActivitiTask selectProcessDefinitionId(@Param("taskId") String taskId, @Param("activation") int activation);
/**
* 查询任务信息
*
* @param processInstanceId 流程实例ID
* @return 任务信息
*/
ActivitiTask selectTask(@Param("processInstanceId") String processInstanceId);
}

24
easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiHistoricMapper.xml

@ -0,0 +1,24 @@
<?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="com.easy.admin.activiti.dao.ActivitiHistoricMapper">
<select id="select" resultType="com.easy.admin.activiti.model.ActivitiHistoric">
select aha.id_, aha.proc_def_id_ as process_definition_id, arp.name_ as process_definition_name, aha.proc_inst_id_ as process_instance_id, aha.execution_id_,
aha.act_id_ as activity_id, aha.task_id_, aha.call_proc_inst_id_ as call_process_instance_id, aha.act_name_ as activity_name,
aha.act_type_ as activity_type, su.nickname as assignee_, aha.start_time_, aha.end_time_, aha.duration_, aha.tenant_id_
from act_hi_actinst aha
left join sys_user su on su.id = aha.assignee_
left join act_re_procdef arp on aha.proc_def_id_ = arp.id_
<where>
${ew.sqlSegment}
</where>
</select>
<select id="selectTask" resultType="com.easy.admin.activiti.model.ActivitiTask">
select distinct ahp.proc_inst_id_ as process_instance_id, aht.execution_id_
from act_hi_procinst ahp
left join act_hi_taskinst aht on ahp.proc_inst_id_ = aht.proc_inst_id_
where ahp.business_key_ = #{businessKey}
</select>
</mapper>

36
easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiHistoryTaskInstanceMapper.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="com.easy.admin.activiti.dao.ActivitiHistoryTaskInstanceMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.easy.admin.activiti.model.ActivitiHistoryTaskInstance">
</resultMap>
<select id="select" resultType="com.easy.admin.activiti.model.ActivitiHistoryTaskInstance">
select * from (
select aht.id_, aht.proc_def_id_ as process_definition_id, aht.task_def_key_ as task_definition_key, aht.proc_inst_id_ as process_instance_id,
aht.execution_id_, aht.name_, aht.parent_task_id_, aht.description_, aht.owner_, aht.assignee_, aht.start_time_, aht.claim_time_,
ahp.end_time_, ahp.delete_reason_, aht.duration_,aht.priority_, aht.due_date_, aht.form_key_, aht.category_, aht.tenant_id_,
arp.name_ as process_definition_name, arp.version_ as process_version, arp.suspension_state_ as process_suspension_state,
if(ahp.end_time_ is not null, '--', concat(art.name_, '[', ifnull(su_assignee.nickname, '未签收'), ']')) as name,
arv_businessTitle.text_ as business_title, su.nickname as apply_user,
@rownum:=@rownum+1 rownum,if(@mno=aht.proc_inst_id_ or (@mno is null and aht.proc_inst_id_ is null),
@rank:=@rank+1,@rank:=1) as ranker
-- row_number() over (partition by aht.proc_inst_id_ order by aht.start_time_ ${historyOrderType}) as ranker
from act_hi_taskinst aht
left join act_ru_task art on art.proc_inst_id_ = aht.proc_inst_id_
left join act_re_procdef arp on aht.proc_def_id_ = arp.id_
left join act_hi_procinst ahp on ahp.proc_inst_id_ = aht.proc_inst_id_
left join act_hi_varinst arv_businessTitle on arv_businessTitle.execution_id_ = aht.execution_id_ and arv_businessTitle.name_ = 'businessTitle'
left join act_hi_varinst arv_businessDetailsPath on arv_businessDetailsPath.execution_id_ = aht.execution_id_ and arv_businessDetailsPath.name_ = 'businessDetailsPath'
left join act_hi_varinst arv_applyUserId on arv_applyUserId.execution_id_ = aht.execution_id_ and arv_applyUserId.name_ = 'applyUserId'
left join sys_user su on su.id = arv_applyUserId.text_
left join sys_user su_assignee on su_assignee.id = art.assignee_
<where>
${ew.sqlSegment}
</where>
ORDER BY aht.proc_inst_id_,aht.start_time_ desc
) t where ranker = 1
</select>
</mapper>

25
easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiModelMapper.xml

@ -0,0 +1,25 @@
<?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="com.easy.admin.activiti.dao.ActivitiModelMapper">
<select id="selectProcessDefinitionId" resultType="java.lang.String">
select arp.id_
from act_re_procdef arp
where arp.suspension_state_ = #{suspensionState} and arp.deployment_id_ = (select deployment_id_ from act_re_model where key_ = #{key});
</select>
<select id="select" resultType="com.easy.admin.activiti.model.ActivitiModel">
select arm.id_, arm.rev_, arm.name_, arm.key_, arm.category_, arm.create_time_, arm.last_update_time_,
arm.version_, arm.meta_info_, arm.deployment_id_, arm.editor_source_value_id_,
arm.editor_source_extra_value_id_, arm.tenant_id_
from act_re_model arm
<where>
${ew.sqlSegment}
</where>
</select>
<select id="selectCountByKey" resultType="java.lang.Integer">
select count(1) from act_re_model
<where>
${ew.sqlSegment}
</where>
</select>
</mapper>

19
easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiProcessDefinitionMapper.xml

@ -0,0 +1,19 @@
<?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="com.easy.admin.activiti.dao.ActivitiProcessDefinitionMapper">
<select id="countBusinessKey" resultType="java.lang.Integer">
select count(1) from act_hi_procinst where business_key_ = #{businessKey}
</select>
<select id="selectCandidate" resultType="java.lang.String">
select distinct id from(
select user_id as id from sys_user_role sur
where sur.role_id in (select group_id_ from act_ru_identitylink ari where type_ = 'candidate' and task_id_ = #{taskId} and group_id_ is not null)
union all
select su.id as id from sys_user su where su.id in (select user_id_ from act_ru_identitylink ari where type_ = 'candidate' and task_id_ = #{taskId} and user_id_ is not null)
) t
</select>
<select id="selectTaskId" resultType="java.lang.String">
select id_ from act_ru_task where proc_inst_id_ = #{processInstanceId}
</select>
</mapper>

36
easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiProcessMapper.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="com.easy.admin.activiti.dao.ActivitiProcessMapper">
<resultMap id="BaseResultMap" type="com.easy.admin.activiti.model.ActivitiProcess">
<id column="id_" jdbcType="VARCHAR" property="processDefinitionId"/>
<result column="category_" jdbcType="VARCHAR" property="category"/>
<result column="name_" jdbcType="VARCHAR" property="name"/>
<result column="key_" jdbcType="VARCHAR" property="key"/>
<result column="version_" jdbcType="INTEGER" property="version"/>
<result column="deployment_id_" jdbcType="VARCHAR" property="deploymentId"/>
<result column="resource_name_" jdbcType="VARCHAR" property="resourceName"/>
<result column="dgrm_resource_name_" jdbcType="VARCHAR" property="dgrmResourceName"/>
<result column="description_" jdbcType="VARCHAR" property="description"/>
<result column="has_start_form_key_" jdbcType="INTEGER" property="hasStartFormKey"/>
<result column="has_graphical_notation_" jdbcType="INTEGER" property="hasGraphicalNotation"/>
<result column="suspension_state_" jdbcType="INTEGER" property="suspensionState"/>
<result column="tenant_id_" jdbcType="VARCHAR" property="tenantId"/>
</resultMap>
<select id="select" resultType="com.easy.admin.activiti.model.ActivitiProcess">
select arp.id_ as process_definition_id, arp.name_, arp.key_, arp.version_, arp.has_start_form_key_, arp.suspension_state_,
arp.resource_name_ as resourceName, arp.dgrm_resource_name_ as dgrmResourceName, arp.deployment_id_, ard.deploy_time_
from act_re_procdef arp
left join act_re_deployment ard on arp.deployment_id_ = ard.id_
<where>
${ew.sqlSegment}
</where>
</select>
<select id="getById" resultType="com.easy.admin.activiti.model.ActivitiProcess">
select arp.* from act_re_procdef arp where arp.id_ = #{id}
</select>
<select id="selectProcessForSelect" resultType="com.easy.admin.common.core.common.select.Select">
select arp.id_ as value, concat(arp.name_, ' v' , arp.version_) as label from act_re_procdef arp order by arp.key_
</select>
</mapper>

47
easy-activiti/src/main/java/com/easy/admin/activiti/dao/mapping/ActivitiTaskMapper.xml

@ -0,0 +1,47 @@
<?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="com.easy.admin.activiti.dao.ActivitiTaskMapper">
<select id="select" resultType="com.easy.admin.activiti.model.ActivitiTask">
select distinct
art.id_, art.rev_, art.execution_id_, art.proc_inst_id_ as process_instance_id, art.proc_def_id_ as process_definition_id, art.name_,
art.parent_task_id_, art.description_, art.task_def_key_ as task_definition_key, art.owner_, art.assignee_, art.delegation_, art.priority_,
art.create_time_, art.due_date_, art.category_, art.suspension_state_, art.tenant_id_, art.form_key_,
arp.name_ as processDefinitionName, arv_businessKey.text_ as businessKey, arp.version_,
arv_businessTitle.text_ as businessTitle, arv_businessDetailsPath.text_ as businessDetailsPath,
su.nickname as applyUser, arv_applyUserId.text_ as _applyUserId
from act_ru_task art
inner join act_ru_identitylink ari on ari.task_id_ = art.id_
left join act_re_procdef arp on art.proc_def_id_ = arp.id_
left join act_ru_variable arv_businessKey on arv_businessKey.execution_id_ = art.execution_id_ and arv_businessKey.name_ = 'businessKey'
left join act_ru_variable arv_businessTitle on arv_businessTitle.execution_id_ = art.execution_id_ and arv_businessTitle.name_ = 'businessTitle'
left join act_ru_variable arv_businessDetailsPath on arv_businessDetailsPath.execution_id_ = art.execution_id_ and arv_businessDetailsPath.name_ = 'businessDetailsPath'
left join act_ru_variable arv_applyUserId on arv_applyUserId.execution_id_ = art.execution_id_ and arv_applyUserId.name_ = 'applyUserId'
left join sys_user su on su.id = arv_applyUserId.text_
<where>
${ew.sqlSegment}
</where>
</select>
<select id="selectProcessDefinitionId" resultType="com.easy.admin.activiti.model.ActivitiTask">
select art.proc_def_id_ as process_definition_id, art.proc_inst_id_ as process_instance_id
from act_ru_task art
left join act_re_procdef arp on art.proc_def_id_ = arp.id_
where art.id_ = #{taskId} and arp.suspension_state_ = #{activation}
</select>
<select id="selectTask" resultType="com.easy.admin.activiti.model.ActivitiTask">
select art.id_, art.rev_, art.execution_id_, art.proc_inst_id_ as process_instance_id, art.proc_def_id_ as process_definition_id, art.name_,
art.create_time_, arp.name_ as processDefinitionName, arp.version_ as processVersion,
arv_businessTitle.text_ as businessTitle, arv_businessDetailsPath.text_ as businessDetailsPath,
su.nickname as applyUser, arv_applyUserId.text_ as _applyUserId
from act_ru_task art
left join act_re_procdef arp on art.proc_def_id_ = arp.id_
left join act_ru_variable arv_businessDetailsPath on arv_businessDetailsPath.execution_id_ = art.execution_id_ and arv_businessDetailsPath.name_ = 'businessDetailsPath'
left join act_ru_variable arv_businessTitle on arv_businessTitle.execution_id_ = art.execution_id_ and arv_businessTitle.name_ = 'businessTitle'
left join act_ru_variable arv_applyUserId on arv_applyUserId.execution_id_ = art.execution_id_ and arv_applyUserId.name_ = 'applyUserId'
left join sys_user su on su.id = arv_applyUserId.text_
where art.proc_inst_id_ = #{processInstanceId}
</select>
</mapper>

105
easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiFormPropertyVO.java

@ -0,0 +1,105 @@
package com.easy.admin.activiti.model;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.FormType;
import org.activiti.engine.impl.form.DateFormType;
import org.activiti.engine.impl.form.EnumFormType;
/**
* 流程动态表单
*
* @author TengChongChong
* @date 2021/1/18
*/
public class ActivitiFormPropertyVO implements FormProperty {
protected String id;
protected String name;
protected String typeCode;
protected FormType type;
protected Boolean required;
protected Boolean readable;
protected Boolean writable;
protected String value;
private String datePattern;
protected Object values;
public ActivitiFormPropertyVO(FormProperty formProperty) {
this.id = formProperty.getId();
this.name = formProperty.getName();
this.type = formProperty.getType();
this.typeCode = formProperty.getType().getName();
this.required = formProperty.isRequired();
this.readable = formProperty.isReadable();
this.writable = formProperty.isWritable();
if (formProperty.getType() instanceof EnumFormType) {
this.values = formProperty.getType().getInformation("values");
} else if (formProperty.getType() instanceof DateFormType) {
this.datePattern = (String) formProperty.getType().getInformation("datePattern");
}
}
@Override
public String getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public FormType getType() {
return type;
}
@Override
public String getValue() {
return value;
}
@Override
public boolean isRequired() {
return required;
}
@Override
public boolean isReadable() {
return readable;
}
@Override
public boolean isWritable() {
return writable;
}
public String getTypeCode() {
return typeCode;
}
public Object getValues() {
return values;
}
public String getDatePattern() {
return datePattern;
}
@Override
public String toString() {
return "FormPropertyVO{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", typeCode='" + typeCode + '\'' +
", type=" + type +
", required=" + required +
", readable=" + readable +
", writable=" + writable +
", value='" + value + '\'' +
", datePattern='" + datePattern + '\'' +
", values=" + values +
'}';
}
}

188
easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiHistoric.java

@ -0,0 +1,188 @@
package com.easy.admin.activiti.model;
import java.util.Date;
/**
* 流程历史活动记录
*
* @author TengChongChong
* @date 2020/5/7
*/
public class ActivitiHistoric {
/**
* id
*/
protected String id;
/**
* 执行实例ID
*/
private String executionId;
/**
* 流程实例ID
*/
private String processInstanceId;
/**
* 流程定义ID
*/
private String processDefinitionId;
/**
* 流程名称
*/
private String processDefinitionName;
/**
* 活动ID节点定义ID
*/
private String activityId;
/**
* 活动名称节点定义名称
*/
protected String activityName;
/**
* 活动类型如startEventuserTask
*/
protected String activityType;
/**
* 代理人员节点签收人
*/
protected String assignee;
/**
* 任务ID任务实例ID
*/
protected String taskId;
/**
* 请求流程实例ID调用外部流程的流程实例ID
*/
protected String calledProcessInstanceId;
/**
* 开始时间
*/
private Date startTime;
/**
* 结束时间
*/
private Date endTime;
/**
* 耗时毫秒
*/
private long duration;
public ActivitiHistoric() {
}
public ActivitiHistoric(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getExecutionId() {
return executionId;
}
public void setExecutionId(String executionId) {
this.executionId = executionId;
}
public String getProcessInstanceId() {
return processInstanceId;
}
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public String getProcessDefinitionId() {
return processDefinitionId;
}
public void setProcessDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public String getProcessDefinitionName() {
return processDefinitionName;
}
public void setProcessDefinitionName(String processDefinitionName) {
this.processDefinitionName = processDefinitionName;
}
public String getActivityId() {
return activityId;
}
public void setActivityId(String activityId) {
this.activityId = activityId;
}
public String getActivityName() {
return activityName;
}
public void setActivityName(String activityName) {
this.activityName = activityName;
}
public String getActivityType() {
return activityType;
}
public void setActivityType(String activityType) {
this.activityType = activityType;
}
public String getAssignee() {
return assignee;
}
public void setAssignee(String assignee) {
this.assignee = assignee;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getCalledProcessInstanceId() {
return calledProcessInstanceId;
}
public void setCalledProcessInstanceId(String calledProcessInstanceId) {
this.calledProcessInstanceId = calledProcessInstanceId;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
}

352
easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiHistoryTaskInstance.java

@ -0,0 +1,352 @@
package com.easy.admin.activiti.model;
import java.util.Date;
/**
* 历史任务实例
*
* @author TengChongChong
* @date 2020/5/14
*/
public class ActivitiHistoryTaskInstance {
/**
* id
*/
protected String id;
/**
* 流程定义ID
*/
private String processDefinitionId;
/**
* 流程名称
*/
private String processDefinitionName;
/**
* 流程版本
*/
private Integer processVersion;
/**
* key
*/
private String taskDefinitionKey;
/**
* 执行实例ID
*/
private String executionId;
/**
* 流程实例ID
*/
private String processInstanceId;
/**
* 节点名称
*/
private String name;
/**
* 父任务id
*/
private String parentTaskId;
/**
* 节点说明
*/
private String description;
/**
* 实际签收人 任务的拥有者签收人默认为空只有在委托时才有值
*/
private String owner;
/**
* 签收人或委托人
*/
private String assignee;
/**
* 开始时间
*/
private Date startTime;
/**
* 签收时间
*/
private Date claimTime;
/**
* 办结时间
*/
private Date endTime;
/**
* 耗时
*/
private String duration;
/**
* 删除原因
*/
private String deleteReason;
/**
* 优先级别默认为50
*/
private int priority = 50;
/**
* 应完成时间过期时间表明任务应在多长时间内完成
*/
private Date dueDate;
/**
* 外置表单key
*/
private String formKey;
/**
* 分类
*/
private String category;
/**
* 租户id
*/
private String tenantId;
/**
* 业务数据ID
*/
private String businessKey;
/**
* 业务标题
*/
private String businessTitle;
/**
* 业务数据详情url
*/
private String businessDetailsPath;
/**
* 发起人
*/
private String applyUser;
/**
* 流程状态
*/
private Integer processSuspensionState;
/**
* 任务状态
*/
private String taskStatus;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProcessDefinitionId() {
return processDefinitionId;
}
public void setProcessDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public String getTaskDefinitionKey() {
return taskDefinitionKey;
}
public void setTaskDefinitionKey(String taskDefinitionKey) {
this.taskDefinitionKey = taskDefinitionKey;
}
public String getExecutionId() {
return executionId;
}
public void setExecutionId(String executionId) {
this.executionId = executionId;
}
public String getProcessInstanceId() {
return processInstanceId;
}
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getParentTaskId() {
return parentTaskId;
}
public void setParentTaskId(String parentTaskId) {
this.parentTaskId = parentTaskId;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getAssignee() {
return assignee;
}
public void setAssignee(String assignee) {
this.assignee = assignee;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getClaimTime() {
return claimTime;
}
public void setClaimTime(Date claimTime) {
this.claimTime = claimTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getDeleteReason() {
return deleteReason;
}
public void setDeleteReason(String deleteReason) {
this.deleteReason = deleteReason;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public Date getDueDate() {
return dueDate;
}
public void setDueDate(Date dueDate) {
this.dueDate = dueDate;
}
public String getFormKey() {
return formKey;
}
public void setFormKey(String formKey) {
this.formKey = formKey;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
public String getProcessDefinitionName() {
return processDefinitionName;
}
public void setProcessDefinitionName(String processDefinitionName) {
this.processDefinitionName = processDefinitionName;
}
public String getBusinessKey() {
return businessKey;
}
public void setBusinessKey(String businessKey) {
this.businessKey = businessKey;
}
public String getBusinessTitle() {
return businessTitle;
}
public void setBusinessTitle(String businessTitle) {
this.businessTitle = businessTitle;
}
public String getBusinessDetailsPath() {
return businessDetailsPath;
}
public void setBusinessDetailsPath(String businessDetailsPath) {
this.businessDetailsPath = businessDetailsPath;
}
public String getApplyUser() {
return applyUser;
}
public void setApplyUser(String applyUser) {
this.applyUser = applyUser;
}
public Integer getProcessSuspensionState() {
return processSuspensionState;
}
public void setProcessSuspensionState(Integer processSuspensionState) {
this.processSuspensionState = processSuspensionState;
}
public String getTaskStatus() {
return taskStatus;
}
public void setTaskStatus(String taskStatus) {
this.taskStatus = taskStatus;
}
public Integer getProcessVersion() {
return processVersion;
}
public void setProcessVersion(Integer processVersion) {
this.processVersion = processVersion;
}
}

51
easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiModel.java

@ -0,0 +1,51 @@
package com.easy.admin.activiti.model;
import com.baomidou.mybatisplus.annotation.TableField;
import org.activiti.engine.impl.persistence.entity.ModelEntity;
/**
* Activiti 流程模型
*
* @author TengChongChong
* @date 2019-07-02
*/
public class ActivitiModel extends ModelEntity {
/**
* 描述
*/
@TableField(exist=false)
private String description;
/**
* 模型路径
*/
private String path;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public ModelEntity getModelEntity(){
ModelEntity modelEntity = new ModelEntity();
modelEntity.setName(this.name);
modelEntity.setKey(this.key);
modelEntity.setCategory(this.category);
modelEntity.setMetaInfo(this.metaInfo);
return modelEntity;
}
}

183
easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiProcess.java

@ -0,0 +1,183 @@
package com.easy.admin.activiti.model;
import java.util.Date;
/**
* 流程
*
* @author TengChongChong
* @date 2019-07-12
*/
public class ActivitiProcess {
/**
* 流程定义ID
*/
private String processDefinitionId;
/**
* 命名空间
*/
private String category;
/**
* 名称
*/
private String name;
/**
* 标识
*/
private String key;
/**
* 版本号
*/
private int version;
/**
* 部署id
*/
private String deploymentId;
/**
* 资源文件名称
*/
private String resourceName;
/**
* 图片资源文件名称
*/
private String dgrmResourceName;
/**
* 描述
*/
private String description;
/**
* 启动节点有无外置表单
*/
private Integer hasStartFormKey;
private Integer hasGraphicalNotation;
/**
* 挂起状态
*/
private Integer suspensionState;
/**
* 租户id
*/
private String tenantId;
/**
* 部署时间
*/
private Date deployTime;
public String getProcessDefinitionId() {
return processDefinitionId;
}
public void setProcessDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public String getDeploymentId() {
return deploymentId;
}
public void setDeploymentId(String deploymentId) {
this.deploymentId = deploymentId;
}
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public String getDgrmResourceName() {
return dgrmResourceName;
}
public void setDgrmResourceName(String dgrmResourceName) {
this.dgrmResourceName = dgrmResourceName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getHasStartFormKey() {
return hasStartFormKey;
}
public void setHasStartFormKey(Integer hasStartFormKey) {
this.hasStartFormKey = hasStartFormKey;
}
public Integer getHasGraphicalNotation() {
return hasGraphicalNotation;
}
public void setHasGraphicalNotation(Integer hasGraphicalNotation) {
this.hasGraphicalNotation = hasGraphicalNotation;
}
public Integer getSuspensionState() {
return suspensionState;
}
public void setSuspensionState(Integer suspensionState) {
this.suspensionState = suspensionState;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
public Date getDeployTime() {
return deployTime;
}
public void setDeployTime(Date deployTime) {
this.deployTime = deployTime;
}
}

103
easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiProcessDefinitionVO.java

@ -0,0 +1,103 @@
package com.easy.admin.activiti.model;
import cn.hutool.json.JSONObject;
import javax.validation.constraints.NotBlank;
/**
* 流程发起
*
* @author TengChongChong
* @date 2021/1/16
*/
public class ActivitiProcessDefinitionVO {
/**
* 流程ID
*/
@NotBlank(message = "流程ID不能为空")
String processDefinitionId;
/**
* 业务数据ID
*/
@NotBlank(message = "业务数据ID不能为空")
String businessKey;
/**
* 业务标题
*/
@NotBlank(message = "业务标题不能为空")
String businessTitle;
/**
* 业务数据详情url
*/
@NotBlank(message = "业务数据详情Path不能为空")
String businessDetailsPath;
/**
* 扩展参数
*/
JSONObject extentParams;
/**
* 包含流程发起表单数据
*/
private Boolean hasFormData;
public String getProcessDefinitionId() {
return processDefinitionId;
}
public void setProcessDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public String getBusinessKey() {
return businessKey;
}
public void setBusinessKey(String businessKey) {
this.businessKey = businessKey;
}
public String getBusinessTitle() {
return businessTitle;
}
public void setBusinessTitle(String businessTitle) {
this.businessTitle = businessTitle;
}
public String getBusinessDetailsPath() {
return businessDetailsPath;
}
public void setBusinessDetailsPath(String businessDetailsPath) {
this.businessDetailsPath = businessDetailsPath;
}
public JSONObject getExtentParams() {
return extentParams;
}
public void setExtentParams(JSONObject extentParams) {
this.extentParams = extentParams;
}
public Boolean getHasFormData() {
return hasFormData;
}
public void setHasFormData(Boolean hasFormData) {
this.hasFormData = hasFormData;
}
@Override
public String toString() {
return "ProcessDefinitionVO{" +
"processDefinitionId='" + processDefinitionId + '\'' +
", businessKey='" + businessKey + '\'' +
", businessTitle='" + businessTitle + '\'' +
", businessDetailsPath='" + businessDetailsPath + '\'' +
", extentParams=" + extentParams +
", hasFormData=" + hasFormData +
'}';
}
}

352
easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiTask.java

@ -0,0 +1,352 @@
package com.easy.admin.activiti.model;
import java.util.Date;
/**
* 待办任务 Task
*
* @author TengChongChong
* @date 2020/3/27
*/
public class ActivitiTask {
/**
* 任务id
*/
private String id;
/**
* 版本
*/
private int revision;
/**
* 实际签收人 任务的拥有者签收人默认为空只有在委托时才有值
*/
private String owner;
/**
* 签收人或委托人
*/
private String assignee;
/**
* 父任务id
*/
private String parentTaskId;
/**
* 任务标题
*/
private String name;
/**
* 自定义名称
*/
private String localizedName;
/**
* 任务说明
*/
private String description;
/**
* 自定义任务说明
*/
private String localizedDescription;
/**
* 创建时间
*/
private Date createTime;
/**
* 优先级别默认为50
*/
private int priority = 50;
/**
* 执行实例ID
*/
private String executionId;
/**
* 流程实例ID
*/
private String processInstanceId;
/**
* 流程定义ID
*/
private String processDefinitionId;
/**
* 流程名称
*/
private String processDefinitionName;
/**
* 流程版本
*/
private Integer processVersion;
/**
* 任务唯一id
*/
private String taskDefinitionKey;
/**
* 表单 key
*/
private String formKey;
/**
* 是否删除
*/
private boolean isDeleted;
/**
* 事件名称
*/
private String eventName;
/**
* 强制更新
*/
private boolean forcedUpdate;
/**
* 状态
*/
private String status;
/**
* 业务数据ID
*/
private String businessKey;
/**
* 业务标题
*/
private String businessTitle;
/**
* 业务数据详情url
*/
private String businessDetailsPath;
/**
* 发起人
*/
private String applyUser;
/**
* 发起人用户id
*/
private String applyUserId;
/**
* 申请人头像
*/
private String avatar;
public int getRevision() {
return revision;
}
public void setRevision(int revision) {
this.revision = revision;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getAssignee() {
return assignee;
}
public void setAssignee(String assignee) {
this.assignee = assignee;
}
public String getParentTaskId() {
return parentTaskId;
}
public void setParentTaskId(String parentTaskId) {
this.parentTaskId = parentTaskId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocalizedName() {
return localizedName;
}
public void setLocalizedName(String localizedName) {
this.localizedName = localizedName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLocalizedDescription() {
return localizedDescription;
}
public void setLocalizedDescription(String localizedDescription) {
this.localizedDescription = localizedDescription;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getExecutionId() {
return executionId;
}
public void setExecutionId(String executionId) {
this.executionId = executionId;
}
public String getProcessInstanceId() {
return processInstanceId;
}
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public String getProcessDefinitionId() {
return processDefinitionId;
}
public void setProcessDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public String getTaskDefinitionKey() {
return taskDefinitionKey;
}
public void setTaskDefinitionKey(String taskDefinitionKey) {
this.taskDefinitionKey = taskDefinitionKey;
}
public String getFormKey() {
return formKey;
}
public void setFormKey(String formKey) {
this.formKey = formKey;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
public boolean isForcedUpdate() {
return forcedUpdate;
}
public void setForcedUpdate(boolean forcedUpdate) {
this.forcedUpdate = forcedUpdate;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getBusinessTitle() {
return businessTitle;
}
public void setBusinessTitle(String businessTitle) {
this.businessTitle = businessTitle;
}
public String getProcessDefinitionName() {
return processDefinitionName;
}
public void setProcessDefinitionName(String processDefinitionName) {
this.processDefinitionName = processDefinitionName;
}
public String getApplyUser() {
return applyUser;
}
public void setApplyUser(String applyUser) {
this.applyUser = applyUser;
}
public String getBusinessKey() {
return businessKey;
}
public void setBusinessKey(String businessKey) {
this.businessKey = businessKey;
}
public String getBusinessDetailsPath() {
return businessDetailsPath;
}
public void setBusinessDetailsPath(String businessDetailsPath) {
this.businessDetailsPath = businessDetailsPath;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getApplyUserId() {
return applyUserId;
}
public void setApplyUserId(String applyUserId) {
this.applyUserId = applyUserId;
}
public Integer getProcessVersion() {
return processVersion;
}
public void setProcessVersion(Integer processVersion) {
this.processVersion = processVersion;
}
}

106
easy-activiti/src/main/java/com/easy/admin/activiti/model/ActivitiTaskInfo.java

@ -0,0 +1,106 @@
package com.easy.admin.activiti.model;
import com.easy.admin.auth.model.SysUser;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 任务办理详情
*
* @author tengchong
* @date 2022/7/12
*/
public class ActivitiTaskInfo {
/**
* 是否有表单
*/
private boolean hasTaskForm;
/**
* 表单
*/
private List<ActivitiFormPropertyVO> taskFormData;
/**
* 发起时表单
*/
private List<ActivitiFormPropertyVO> startFormData;
/**
* 流程变量
*/
private Map<String, Object> variables;
/**
* 发起人
*/
private SysUser applyUser;
/**
* 业务数据id
*/
private String businessKey;
/**
* 发起时间
*/
private Date createDate;
public ActivitiTaskInfo() {
this.hasTaskForm = false;
}
public boolean isHasTaskForm() {
return hasTaskForm;
}
public void setHasTaskForm(boolean hasTaskForm) {
this.hasTaskForm = hasTaskForm;
}
public List<ActivitiFormPropertyVO> getTaskFormData() {
return taskFormData;
}
public void setTaskFormData(List<ActivitiFormPropertyVO> taskFormData) {
this.taskFormData = taskFormData;
}
public Map<String, Object> getVariables() {
return variables;
}
public void setVariables(Map<String, Object> variables) {
this.variables = variables;
}
public SysUser getApplyUser() {
return applyUser;
}
public void setApplyUser(SysUser applyUser) {
this.applyUser = applyUser;
}
public List<ActivitiFormPropertyVO> getStartFormData() {
return startFormData;
}
public void setStartFormData(List<ActivitiFormPropertyVO> startFormData) {
this.startFormData = startFormData;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public String getBusinessKey() {
return businessKey;
}
public void setBusinessKey(String businessKey) {
this.businessKey = businessKey;
}
}

30
easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiHistoricService.java

@ -0,0 +1,30 @@
package com.easy.admin.activiti.service;
import com.easy.admin.activiti.model.ActivitiHistoric;
import com.easy.admin.activiti.model.ActivitiTask;
import java.util.List;
/**
* 流程历史活动记录
*
* @author TengChongChong
* @date 2020/5/7
*/
public interface ActivitiHistoricService {
/**
* 查询
*
* @param processInstanceId 流程实例ID
* @return List<Historic>
*/
List<ActivitiHistoric> select(String processInstanceId);
/**
* 根据业务id查询流程实例
*
* @param businessKey 业务id
* @return 流程实例
*/
ActivitiTask selectTask(String businessKey);
}

39
easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiHistoryTaskInstanceService.java

@ -0,0 +1,39 @@
package com.easy.admin.activiti.service;
import com.easy.admin.activiti.model.ActivitiHistoryTaskInstance;
import com.easy.admin.common.core.common.pagination.Page;
/**
* 历史任务实例
*
* @author TengChongChong
* @date 2020/5/14
*/
public interface ActivitiHistoryTaskInstanceService {
/**
* 我发起的办理中+已办结的任务
*
* @param object 查询条件
* @param page 分页
* @return Page
*/
Page<ActivitiHistoryTaskInstance> selectMy(ActivitiHistoryTaskInstance object, Page<ActivitiHistoryTaskInstance> page);
/**
* 用户参与过的任务
*
* @param object 查询条件
* @param page 分页
* @return Page
*/
Page<ActivitiHistoryTaskInstance> selectParticipate(ActivitiHistoryTaskInstance object, Page<ActivitiHistoryTaskInstance> page);
/**
* 所有任务包含办理中和已办结一般分配给管理员
*
* @param object 查询条件
* @param page 分页
* @return Page
*/
Page<ActivitiHistoryTaskInstance> selectAll(ActivitiHistoryTaskInstance object, Page<ActivitiHistoryTaskInstance> page);
}

106
easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiModelService.java

@ -0,0 +1,106 @@
package com.easy.admin.activiti.service;
import com.easy.admin.activiti.model.ActivitiModel;
import com.easy.admin.common.core.common.pagination.Page;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.engine.impl.persistence.entity.ModelEntity;
/**
* Activiti 流程模型
*
* @author TengChongChong
* @date 2019-07-02
*/
public interface ActivitiModelService {
/**
* 列表
*
* @param activitiModel 查询条件
* @param page 分页
* @return page
*/
Page<ActivitiModel> select(ActivitiModel activitiModel, Page<ActivitiModel> page);
/**
* 详情
*
* @param id 数据id
* @return 详细信息
*/
ModelEntity get(String id);
/**
* 获取模型信息
*
* @param id 数据id
* @return 模型信息
*/
ObjectNode getModel(String id);
/**
* 删除
*
* @param ids 数据ids
* @return true/false
*/
boolean remove(String ids);
/**
* 保存
*
* @param activitiModel 提交数据
* @return 保存后信息
*/
ModelEntity saveData(ActivitiModel activitiModel);
/**
* 保存模型
*
* @param id 模型id
* @param name 名称
* @param description 描述
* @param jsonXml json
* @param svgXml svg
*/
void saveModel(String id, String name, String description, String jsonXml, String svgXml);
/**
* 读取stencilset.json文件
*
* @return 文件内容
*/
String getStencilset();
/**
* 部署流程
*
* @param id 模型id
* @return true/false
*/
boolean deploymentProcess(String id);
/**
* 导出模型
*
* @param id 模型id
* @return sys download id
*/
String export(String id);
/**
* 根据模型标识查询流程定义ID
*
* @param key 模型标识
* @return 流程定义ID
*/
String selectProcessDefinitionId(String key);
/**
* 检查流程标识是否存在
*
* @param key 标识
* @param id id
* @return true/false
*/
boolean checkKeyIsExistence(String key, String id);
}

48
easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiProcessDefinitionService.java

@ -0,0 +1,48 @@
package com.easy.admin.activiti.service;
import cn.hutool.json.JSONObject;
import com.easy.admin.activiti.model.ActivitiProcessDefinitionVO;
import org.activiti.engine.repository.ProcessDefinition;
/**
* 启动流程
*
* @author TengChongChong
* @date 2020/3/26
*/
public interface ActivitiProcessDefinitionService {
/**
* 读取流程起点动态表单
*
* @param processDefinitionId 流程id
* @return JSONObject
*/
JSONObject readStartForm(String processDefinitionId);
/**
* 启动流程
* 先验证有无动态表单如果没有自动提交如果有返回表单地址
*
* @param activitiProcessDefinitionVO 流程数据
* @return 实例ID或动态表单url
*/
JSONObject startProcessInstance(ActivitiProcessDefinitionVO activitiProcessDefinitionVO);
JSONObject startProcessInstanceHuzhou(ActivitiProcessDefinitionVO activitiProcessDefinitionVO);
/**
* 检查任务是否满足自动签收条件
* 如下一个节点角色+候选人总共为1个用户则自动签收
*
* @param processInstanceId 流程实例ID
* @return true/false
*/
boolean autoClaimTask(String processInstanceId);
/**
* 根据流程定义ID获取流程
*
* @param processDefinitionId 流程定义ID
* @return ProcessDefinition
*/
ProcessDefinition getProcessDefinition(String processDefinitionId);
}

74
easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiProcessService.java

@ -0,0 +1,74 @@
package com.easy.admin.activiti.service;
import com.easy.admin.activiti.model.ActivitiProcess;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.common.select.Select;
import java.io.InputStream;
import java.util.List;
/**
* 流程
*
* @author TengChongChong
* @date 2019-07-12
*/
public interface ActivitiProcessService {
/**
* 查询数据
*
* @param activitiProcess 查询条件
* @param page 分页
* @return 数据
*/
Page<ActivitiProcess> select(ActivitiProcess activitiProcess, Page<ActivitiProcess> page);
/**
* 删除
*
* @param deploymentIds 部署ids
* @return true/false
*/
boolean remove(String deploymentIds);
/**
* 流程转模型
*
* @param activitiProcess process
* @return true/false
*/
boolean convertToModel(ActivitiProcess activitiProcess);
/**
* 查看流程图片
*
* @param deploymentId 部署id
* @param resourceName 资源名称
* @return true/false
*/
InputStream getImageStream(String deploymentId, String resourceName);
/**
* 挂起流程
*
* @param processDefinitionId 流程id
* @param suspendProcessInstances 如果为true将同时挂起此流程正在进行的任务
*/
void suspend(String processDefinitionId, boolean suspendProcessInstances);
/**
* 激活流程
*
* @param processDefinitionId 流程id
* @param activateProcessInstances 如果为true将同时激活此流程正在进行的任务
*/
void activation(String processDefinitionId, boolean activateProcessInstances);
/**
* 查询流程数据用于放到select的option中
*
* @return 数据集合
*/
List<Select> selectProcessForSelect();
}

21
easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiProcessTraceService.java

@ -0,0 +1,21 @@
package com.easy.admin.activiti.service;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 流程跟踪
*
* @author TengChongChong
* @date 2020/4/29
*/
public interface ActivitiProcessTraceService {
/**
* 查看流程实例进度
* @param processInstanceId 流程实例ID
* @param response response
* @throws IOException exception
*/
void readProcessImg(String processInstanceId, HttpServletResponse response) throws IOException;
}

54
easy-activiti/src/main/java/com/easy/admin/activiti/service/ActivitiTaskService.java

@ -0,0 +1,54 @@
package com.easy.admin.activiti.service;
import cn.hutool.json.JSONObject;
import com.easy.admin.activiti.model.ActivitiTask;
import com.easy.admin.activiti.model.ActivitiTaskInfo;
import com.easy.admin.common.core.common.pagination.Page;
/**
* 待办任务
*
* @author TengChongChong
* @date 2020/3/27
*/
public interface ActivitiTaskService {
/**
* 查询待办任务
*
* @param activitiTask 查询条件
* @param page 分页
* @return Page
*/
Page<ActivitiTask> select(ActivitiTask activitiTask, Page<ActivitiTask> page);
/**
* 签收任务
*
* @param taskId 任务id
*/
void claimTask(String taskId);
/**
* 读取用户任务的表单字段
*
* @param taskId 任务Id
* @return ActivitiTaskInfo
*/
ActivitiTaskInfo readTaskForm(String taskId);
/**
* 流转任务
*
* @param taskId 任务Id
* @param params params
*/
void completeTask(String taskId, JSONObject params);
/**
* 撤销申请
*
* @param processInstanceId 流程实例ID
* @param deleteReason 撤销原因
*/
void revoke(String processInstanceId, String deleteReason);
}

36
easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiHistoricServiceImpl.java

@ -0,0 +1,36 @@
package com.easy.admin.activiti.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.admin.activiti.dao.ActivitiHistoricMapper;
import com.easy.admin.activiti.model.ActivitiHistoric;
import com.easy.admin.activiti.model.ActivitiTask;
import com.easy.admin.activiti.service.ActivitiHistoricService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 流程历史活动记录
*
* @author TengChongChong
* @date 2020/5/7
*/
@Service
public class ActivitiHistoricServiceImpl extends ServiceImpl<ActivitiHistoricMapper, ActivitiHistoric> implements ActivitiHistoricService {
@Override
public List<ActivitiHistoric> select(String processInstanceId) {
QueryWrapper<ActivitiHistoric> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("aha.proc_inst_id_", processInstanceId);
queryWrapper.orderByAsc("aha.start_time_");
List<ActivitiHistoric> activitiHistoricList = baseMapper.select(queryWrapper);
return activitiHistoricList;
}
@Override
public ActivitiTask selectTask(String businessKey) {
return baseMapper.selectTask(businessKey);
}
}

86
easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiHistoryTaskInstanceServiceImpl.java

@ -0,0 +1,86 @@
package com.easy.admin.activiti.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.admin.activiti.constant.status.ActivitiTaskStatus;
import com.easy.admin.activiti.dao.ActivitiHistoryTaskInstanceMapper;
import com.easy.admin.activiti.model.ActivitiHistoryTaskInstance;
import com.easy.admin.activiti.service.ActivitiHistoryTaskInstanceService;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.auth.model.SysUser;
import com.easy.admin.util.ShiroUtil;
import org.springframework.stereotype.Service;
/**
* 历史任务实例
*
* @author TengChongChong
* @date 2020/5/14
*/
@Service
public class ActivitiHistoryTaskInstanceServiceImpl extends ServiceImpl<ActivitiHistoryTaskInstanceMapper, ActivitiHistoryTaskInstance> implements ActivitiHistoryTaskInstanceService {
@Override
public Page<ActivitiHistoryTaskInstance> selectMy(ActivitiHistoryTaskInstance task, Page<ActivitiHistoryTaskInstance> page) {
SysUser currentUser = ShiroUtil.getCurrentUser();
QueryWrapper<ActivitiHistoryTaskInstance> queryWrapper = getQueryWrapper(task);
queryWrapper.eq("arv_applyUserId.text_", currentUser.getId());
page.setDefaultDesc("start_time_");
page.setRecords(baseMapper.select(page, queryWrapper, "asc"));
return page;
}
@Override
public Page<ActivitiHistoryTaskInstance> selectParticipate(ActivitiHistoryTaskInstance task, Page<ActivitiHistoryTaskInstance> page) {
SysUser currentUser = ShiroUtil.getCurrentUser();
QueryWrapper<ActivitiHistoryTaskInstance> queryWrapper = getQueryWrapper(task);
queryWrapper.eq("aht.assignee_", currentUser.getId());
page.setDefaultDesc("start_time_");
page.setRecords(baseMapper.select(page, queryWrapper, "desc"));
return page;
}
@Override
public Page<ActivitiHistoryTaskInstance> selectAll(ActivitiHistoryTaskInstance task, Page<ActivitiHistoryTaskInstance> page) {
QueryWrapper<ActivitiHistoryTaskInstance> queryWrapper = getQueryWrapper(task);
page.setDefaultDesc("start_time_");
page.setRecords(baseMapper.select(page, queryWrapper, "desc"));
return page;
}
/**
* 获取查询条件
*
* @param task 查询条件
* @return QueryWrapper
*/
private QueryWrapper<ActivitiHistoryTaskInstance> getQueryWrapper(ActivitiHistoryTaskInstance task) {
QueryWrapper<ActivitiHistoryTaskInstance> queryWrapper = new QueryWrapper<>();
// 查询条件
if (task != null) {
// 名称
if (StrUtil.isNotBlank(task.getBusinessTitle())) {
queryWrapper.like("arv_businessTitle.text_", "%" + task.getBusinessTitle() + "%");
}
// 流水
if (StrUtil.isNotBlank(task.getProcessInstanceId())) {
queryWrapper.eq("aht.proc_inst_id_", task.getProcessInstanceId());
}
// 任务状态
if (task.getTaskStatus() != null) {
if (ActivitiTaskStatus.IN_PROCESS.getCode().equals(task.getTaskStatus()) ) {
queryWrapper.isNull("ahp.end_time_");
} else if (ActivitiTaskStatus.COMPLETED.getCode().equals(task.getTaskStatus())) {
queryWrapper.isNotNull("ahp.end_time_").isNull("ahp.delete_reason_");
} else if (ActivitiTaskStatus.RESCINDED.getCode().equals(task.getTaskStatus())) {
queryWrapper.isNotNull("ahp.delete_reason_");
}
}
// 流程
if (StrUtil.isNotBlank(task.getProcessDefinitionId())) {
queryWrapper.eq("aht.proc_def_id_", task.getProcessDefinitionId());
}
}
return queryWrapper;
}
}

377
easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiModelServiceImpl.java

@ -0,0 +1,377 @@
package com.easy.admin.activiti.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.admin.activiti.constant.ActivitiModelConst;
import com.easy.admin.activiti.constant.status.ActivitiSuspensionStatus;
import com.easy.admin.activiti.dao.ActivitiModelMapper;
import com.easy.admin.activiti.model.ActivitiModel;
import com.easy.admin.activiti.service.ActivitiModelService;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.constant.CommonConst;
import com.easy.admin.common.core.exception.EasyException;
import com.easy.admin.file.model.FileDownload;
import com.easy.admin.file.service.FileDownloadService;
import com.easy.admin.file.storage.FileStorageFactory;
import com.easy.admin.util.ShiroUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.persistence.entity.ModelEntity;
import org.activiti.engine.repository.Deployment;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import static org.activiti.editor.constants.ModelDataJsonConstants.MODEL_DESCRIPTION;
import static org.activiti.editor.constants.ModelDataJsonConstants.MODEL_NAME;
/**
* Activiti 流程模型
* 部分代码来源于 ActivitiStencilsetRestResource.javaModelEditorJsonRestResource.javaModelSaveRestResource.java
*
* @author TengChongChong
* @date 2019-07-02
*/
@Service
public class ActivitiModelServiceImpl extends ServiceImpl<ActivitiModelMapper, ActivitiModel> implements ActivitiModelService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private RepositoryService repositoryService;
@Autowired
private FileDownloadService fileDownloadService;
@Autowired
private ObjectMapper objectMapper;
/**
* 文件存储
*/
@Autowired
private FileStorageFactory fileStorageFactory;
@Override
public Page<ActivitiModel> select(ActivitiModel activitiModel, Page<ActivitiModel> page) {
QueryWrapper<ActivitiModel> queryWrapper = new QueryWrapper<>();
if (activitiModel != null) {
// 名称
if (StrUtil.isNotBlank(activitiModel.getName())) {
queryWrapper.like("arm.name_", activitiModel.getName());
}
// key
if (StrUtil.isNotBlank(activitiModel.getKey())) {
queryWrapper.like("arm.key_", activitiModel.getKey());
}
}
page.setDefaultDesc("arm.create_time_");
page.setRecords(baseMapper.select(page, queryWrapper));
return page;
}
@Override
public ModelEntity get(String id) {
return (ModelEntity) repositoryService.getModel(id);
}
@Override
public ObjectNode getModel(String id) {
org.activiti.engine.repository.Model model = repositoryService.getModel(id);
ObjectNode objectNode;
if (model == null) {
throw new EasyException("模型信息不存在");
}
if (StrUtil.isNotBlank(model.getMetaInfo())) {
try {
objectNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
} catch (IOException e) {
logger.debug("读取模型信息失败[{}]", model.getId(), e);
throw new EasyException("读取模型信息失败[" + model.getId() + "]");
}
} else {
objectNode = objectMapper.createObjectNode();
objectNode.put("name", model.getName());
}
objectNode.put("modelId", model.getId());
ObjectNode editorJsonNode;
try {
editorJsonNode = (ObjectNode) objectMapper.readTree(new String(repositoryService.getModelEditorSource(model.getId()), StandardCharsets.UTF_8));
} catch (IOException e) {
logger.debug("读取模型信息失败[{}]", model.getId(), e);
throw new EasyException("读取模型信息失败[" + model.getId() + "]");
}
objectNode.set("model", editorJsonNode);
return objectNode;
}
@Override
public boolean remove(String ids) {
if (StrUtil.isBlank(ids)) {
throw new EasyException("获取数据ids失败");
}
List<String> idArray = Arrays.asList(ids.split(CommonConst.SPLIT));
idArray.forEach(id -> repositoryService.deleteModel(id));
return true;
}
@Override
public ModelEntity saveData(ActivitiModel activitiModel) {
if (StrUtil.isBlank(activitiModel.getKey())) {
throw new EasyException("标识不能为空");
}
if (StrUtil.isBlank(activitiModel.getName())) {
throw new EasyException("名称不能为空");
}
if (StrUtil.isBlank(activitiModel.getId())) {
activitiModel.setId(null);
}
if (StrUtil.isBlank(activitiModel.getCategory())) {
activitiModel.setCategory(null);
}
if (checkKeyIsExistence(activitiModel.getKey(), activitiModel.getId())) {
throw new EasyException("标识已存在,请修改后重试");
}
//流程版本
int revision = 1;
ObjectNode modelNode = objectMapper.createObjectNode();
modelNode.put(ModelDataJsonConstants.MODEL_NAME, activitiModel.getName());
modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, activitiModel.getDescription());
modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);
activitiModel.setMetaInfo(modelNode.toString());
// 保存模型信息
ModelEntity modelEntity = activitiModel.getModelEntity();
repositoryService.saveModel(modelEntity);
activitiModel.setId(modelEntity.getId());
setModelEditorSource(activitiModel);
return modelEntity;
}
private void setModelEditorSource(ActivitiModel activitiModel) {
if (StrUtil.isNotBlank(activitiModel.getPath())) {
InputStream bpmnStream;
try {
bpmnStream = new FileInputStream(activitiModel.getPath());
} catch (FileNotFoundException e) {
throw new EasyException("读取模型文件失败,文件不存在");
}
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
// 读取bpmn.xml
InputStreamReader inputStreamReader = new InputStreamReader(bpmnStream, StandardCharsets.UTF_8);
XMLStreamReader xmlStreamReader;
try {
xmlStreamReader = xmlInputFactory.createXMLStreamReader(inputStreamReader);
} catch (XMLStreamException xmlStreamException) {
throw new EasyException("保存模型信息失败" + xmlStreamException.getMessage());
}
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xmlStreamReader);
bpmnModel.getMainProcess();
// xml 转 json
BpmnJsonConverter bpmnJsonConverter = new BpmnJsonConverter();
ObjectNode objectNode = bpmnJsonConverter.convertToJson(bpmnModel);
// 修改标识、名称、描述信息
ObjectNode properties = objectMapper.createObjectNode();
properties.put(ActivitiModelConst.PROPERTIES_PROCESS_ID, activitiModel.getKey());
properties.put(ActivitiModelConst.NAME, activitiModel.getName());
properties.put(ActivitiModelConst.PROPERTIES_PROCESS_AUTHOR, ShiroUtil.getCurrentUser().getNickname());
properties.put(ActivitiModelConst.PROPERTIES_DOCUMENTATION, activitiModel.getDescription());
objectNode.set(ActivitiModelConst.PROPERTIES, properties);
repositoryService.addModelEditorSource(activitiModel.getId(), objectNode.toString().getBytes(StandardCharsets.UTF_8));
} else {
// ModelEditorSource
String modelId = activitiModel.getId();
// 流程属性
ObjectNode properties = objectMapper.createObjectNode();
properties.put(ActivitiModelConst.PROPERTIES_PROCESS_ID, activitiModel.getKey());
properties.put(ActivitiModelConst.NAME, activitiModel.getName());
properties.put(ActivitiModelConst.PROPERTIES_PROCESS_AUTHOR, ShiroUtil.getCurrentUser().getNickname());
properties.put(ActivitiModelConst.PROPERTIES_DOCUMENTATION, activitiModel.getDescription());
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put(ActivitiModelConst.ID, "canvas");
editorNode.put("resourceId", "canvas");
editorNode.set(ActivitiModelConst.PROPERTIES, properties);
ObjectNode stencilSetNode = objectMapper.createObjectNode();
stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
editorNode.set("stencilset", stencilSetNode);
repositoryService.addModelEditorSource(modelId, editorNode.toString().getBytes(StandardCharsets.UTF_8));
}
}
@Override
public void saveModel(String id, String name, String description, String jsonXml, String svgXml) {
org.activiti.engine.repository.Model model = repositoryService.getModel(id);
if (model == null) {
throw new EasyException("获取模型信息失败[modelId = " + id + "]");
}
ObjectNode modelJson;
try {
modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
} catch (IOException e) {
throw new EasyException("获取模型MetaInfo失败");
}
modelJson.put(MODEL_NAME, name);
modelJson.put(MODEL_DESCRIPTION, description);
model.setMetaInfo(modelJson.toString());
model.setName(name);
model.setVersion(model.getVersion() + 1);
// 保存
repositoryService.saveModel(model);
try {
repositoryService.addModelEditorSource(model.getId(), jsonXml.getBytes(StandardCharsets.UTF_8));
InputStream svgStream = new ByteArrayInputStream(svgXml.getBytes(StandardCharsets.UTF_8));
TranscoderInput input = new TranscoderInput(svgStream);
PNGTranscoder transcoder = new PNGTranscoder();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(outStream);
transcoder.transcode(input, output);
final byte[] result = outStream.toByteArray();
repositoryService.addModelEditorSourceExtra(model.getId(), result);
outStream.close();
} catch (IOException | TranscoderException e) {
logger.info("保存模型信息失败", e);
throw new EasyException(e.getMessage());
}
}
@Override
public String getStencilset() {
InputStream stencilSetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");
if (stencilSetStream == null) {
throw new EasyException("读取stencilset.json失败");
}
try {
return IOUtils.toString(stencilSetStream, "utf-8");
} catch (Exception e) {
throw new ActivitiException("读取失败", e);
}
}
@Override
public boolean deploymentProcess(String id) {
if (StrUtil.isBlank(id)) {
throw new EasyException("获取模型id信息失败");
}
// 获取模型信息
org.activiti.engine.repository.Model model = repositoryService.getModel(id);
if (model == null) {
throw new EasyException("模型信息不存在");
}
byte[] bytes = repositoryService.getModelEditorSource(id);
if (bytes == null) {
throw new EasyException("模型信息为空");
}
// 读取模型信息
JsonNode jsonNode;
try {
jsonNode = new ObjectMapper().readTree(bytes);
} catch (IOException e) {
logger.debug("读取模型信息失败", e);
throw new EasyException("读取模型信息失败" + e.getMessage());
}
if (jsonNode == null) {
throw new EasyException("读取模型信息失败");
}
// 验证模型结构
BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(jsonNode);
if (bpmnModel.getProcesses().isEmpty()) {
throw new EasyException("请至少设计一条主线流程");
}
byte[] modelBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
// 部署流程
String processName = model.getKey() + ".bpmn20.xml";
// todo: 这里设置的name没有生效
Deployment deployment = repositoryService.createDeployment().name(model.getName())
.addString(processName, new String(modelBytes, StandardCharsets.UTF_8))
.deploy();
// 设置模型关联的流程id
model.setDeploymentId(deployment.getId());
repositoryService.saveModel(model);
return true;
}
@Override
public boolean checkKeyIsExistence(String key, String id) {
QueryWrapper<ActivitiModel> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("key_", key);
if (StrUtil.isNotBlank(id)) {
queryWrapper.ne("id_", id);
}
return baseMapper.selectCountByKey(queryWrapper) > 0;
}
@Override
public String selectProcessDefinitionId(String key) {
String processDefinitionId = baseMapper.selectProcessDefinitionId(key, ActivitiSuspensionStatus.ACTIVATION.getCode());
if (StrUtil.isBlank(processDefinitionId)) {
throw new EasyException("流程不存在或未部署,请联系系统管理员");
}
return processDefinitionId;
}
@Override
public String export(String id) {
org.activiti.engine.repository.Model model = repositoryService.getModel(id);
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
JsonNode editorNode = null;
try {
editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(model.getId()));
} catch (IOException e) {
e.printStackTrace();
}
BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
byte[] bpmnModelXmlByte = xmlConverter.convertToXML(bpmnModel);
InputStream inputStream = new ByteArrayInputStream(bpmnModelXmlByte);
String objectName = fileStorageFactory.getFileStorage().getTemporaryPath() + IdUtil.randomUUID() + ".bpmn20.xml";
// 保存文件
fileStorageFactory.getFileStorage().uploadFile(
fileStorageFactory.getFileStorageProperties().getDefaultBucket(),
objectName,
inputStream
);
// 保存下载信息
return fileDownloadService.saveData(
new FileDownload(
model.getName() + "(" + model.getKey() + ") v." + model.getVersion() + ".bpmn20.xml",
fileStorageFactory.getFileStorageProperties().getDefaultBucket(),
objectName
)
).getId();
}
}

287
easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiProcessDefinitionServiceImpl.java

@ -0,0 +1,287 @@
package com.easy.admin.activiti.service.impl;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.admin.activiti.constant.ActivitiVariableConst;
import com.easy.admin.activiti.dao.ActivitiProcessDefinitionMapper;
import com.easy.admin.activiti.model.ActivitiFormPropertyVO;
import com.easy.admin.activiti.model.ActivitiProcess;
import com.easy.admin.activiti.model.ActivitiProcessDefinitionVO;
import com.easy.admin.activiti.service.ActivitiProcessDefinitionService;
import com.easy.admin.common.core.constant.CommonConst;
import com.easy.admin.common.core.exception.EasyException;
import com.easy.admin.auth.model.SysRole;
import com.easy.admin.auth.model.SysUser;
import com.easy.admin.auth.service.SysRoleService;
import com.easy.admin.util.ShiroUtil;
import org.activiti.engine.FormService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.StartFormData;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 启动流程
*
* @author TengChongChong
* @date 2020/3/26
*/
@Service
public class ActivitiProcessDefinitionServiceImpl extends ServiceImpl<ActivitiProcessDefinitionMapper, ActivitiProcess> implements ActivitiProcessDefinitionService {
@Autowired
private RepositoryService repositoryService;
@Autowired
private IdentityService identityService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private FormService formService;
@Autowired
private SysRoleService sysRoleService;
@Autowired
private org.activiti.engine.TaskService taskService;
@Override
public JSONObject readStartForm(String processDefinitionId) {
JSONObject res = new JSONObject();
ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId);
boolean hasStartFormKey = processDefinition.hasStartFormKey();
// 是否有hasStartFormKey属性
if (hasStartFormKey) {
Object renderedStartForm = formService.getRenderedStartForm(processDefinitionId);
res.set("startFormData", renderedStartForm);
} else {
// 动态表单
StartFormData startFormData = formService.getStartFormData(processDefinitionId);
res.set("startFormData", startFormData);
}
res.set("processDefinitionId", processDefinitionId);
res.set("hasStartFormKey", hasStartFormKey);
res.set("processDefinition", processDefinition);
return res;
}
@Override
public JSONObject startProcessInstance(ActivitiProcessDefinitionVO activitiProcessDefinitionVO) {
if (checkBusinessKey(activitiProcessDefinitionVO.getBusinessKey())) {
throw new EasyException("[" + activitiProcessDefinitionVO.getBusinessKey() + "]已提交过申请,请勿重复提交");
}
SysUser currentUser = ShiroUtil.getCurrentUser();
JSONObject result = new JSONObject();
ProcessDefinition processDefinition = getProcessDefinition(activitiProcessDefinitionVO.getProcessDefinitionId());
if (activitiProcessDefinitionVO.getHasFormData() == null || !activitiProcessDefinitionVO.getHasFormData()) {
StartFormData startFormData = formService.getStartFormData(activitiProcessDefinitionVO.getProcessDefinitionId());
if (startFormData.getFormProperties() != null && !startFormData.getFormProperties().isEmpty()) {
List<ActivitiFormPropertyVO> activitiFormPropertyVOList = new ArrayList<>();
for (FormProperty formProperty : startFormData.getFormProperties()) {
activitiFormPropertyVOList.add(new ActivitiFormPropertyVO(formProperty));
}
// 有动态表单
result.set("hasStartForm", true);
result.set("startFormData", activitiFormPropertyVOList);
return result;
}
}
// 当前用户
identityService.setAuthenticatedUserId(currentUser.getId());
// 流程变量
Map<String, Object> variables = new HashMap<>();
if (activitiProcessDefinitionVO.getExtentParams() != null) {
// 扩展参数必须是JSON格式
variables = activitiProcessDefinitionVO.getExtentParams();
}
variables.put(ActivitiVariableConst.BUSINESS_TITLE, activitiProcessDefinitionVO.getBusinessTitle());
variables.put(ActivitiVariableConst.BUSINESS_DETAILS_URL, activitiProcessDefinitionVO.getBusinessDetailsPath());
variables = setUserInfo(variables, currentUser);
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), activitiProcessDefinitionVO.getBusinessKey(), variables);
result.set("processInstanceId", processInstance.getId());
autoClaimTask(processInstance.getId());
return result;
}
@Override
public JSONObject startProcessInstanceHuzhou(ActivitiProcessDefinitionVO activitiProcessDefinitionVO) {
if (checkBusinessKey(activitiProcessDefinitionVO.getBusinessKey())) {
throw new EasyException("[" + activitiProcessDefinitionVO.getBusinessKey() + "]已提交过申请,请勿重复提交");
}
SysUser currentUser = ShiroUtil.getCurrentUser();
JSONObject result = new JSONObject();
ProcessDefinition processDefinition = getProcessDefinition(activitiProcessDefinitionVO.getProcessDefinitionId());
if (activitiProcessDefinitionVO.getHasFormData() == null || !activitiProcessDefinitionVO.getHasFormData()) {
StartFormData startFormData = formService.getStartFormData(activitiProcessDefinitionVO.getProcessDefinitionId());
if (startFormData.getFormProperties() != null && !startFormData.getFormProperties().isEmpty()) {
List<ActivitiFormPropertyVO> activitiFormPropertyVOList = new ArrayList<>();
for (FormProperty formProperty : startFormData.getFormProperties()) {
activitiFormPropertyVOList.add(new ActivitiFormPropertyVO(formProperty));
}
// 有动态表单
result.set("hasStartForm", true);
result.set("startFormData", activitiFormPropertyVOList);
return result;
}
}
// 当前用户
identityService.setAuthenticatedUserId(currentUser.getId());
// 流程变量
Map<String, Object> variables = new HashMap<>();
if (activitiProcessDefinitionVO.getExtentParams() != null) {
// 扩展参数必须是JSON格式
variables = activitiProcessDefinitionVO.getExtentParams();
}
variables.put(ActivitiVariableConst.BUSINESS_TITLE, activitiProcessDefinitionVO.getBusinessTitle());
variables.put(ActivitiVariableConst.BUSINESS_DETAILS_URL, activitiProcessDefinitionVO.getBusinessDetailsPath());
variables = setUserInfo(variables, currentUser);
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), activitiProcessDefinitionVO.getBusinessKey(), variables);
String processInstanceId = processInstance.getId();
Task task = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.orderByTaskCreateTime()
.desc()
.list()
.get(0);
String taskId = task.getId();
variables.clear();
autoClaimTask(processInstance.getId());
Authentication.setAuthenticatedUserId(currentUser.getId());//添加审批人
taskService.setVariableLocal(taskId,"approvalStatue","1");//添加审批状态 通过
String comment = "同意";
taskService.addComment(taskId,processInstanceId,comment);//添加审批意见
taskService.complete(taskId, variables);
result.set("processInstanceId", processInstance.getId());
return result;
}
/**
* 检查任务是否满足自动签收条件
* 如下一个节点角色+候选人总共为1个用户则自动签收
*
* @param processInstanceId 流程实例ID
* @return true/false
*/
@Override
public boolean autoClaimTask(String processInstanceId) {
String taskId = baseMapper.selectTaskId(processInstanceId);
if (StrUtil.isNotBlank(taskId)) {
// 查询可以签收此任务的所有用户列表,去重计数
List<String> candidateList = baseMapper.selectCandidate(taskId);
if (candidateList.size() == 1) {
// 只有一个候选人
taskService.claim(taskId, candidateList.get(0));
return true;
}
}
return false;
}
/**
* 设置一些用户信息角色机构用户基本信息等
*
* @param variables 流程参数
* @param currentUser 当前用户
* @return 流程参数
*/
private Map<String, Object> setUserInfo(Map<String, Object> variables, SysUser currentUser) {
List<String> roleCodeList = ShiroUtil.getRoleCodes(currentUser.getRoleList());
// 流程发起人ID
variables.put(ActivitiVariableConst.APPLY_USER_ID, currentUser.getId());
// 流程发起人昵称
variables.put(ActivitiVariableConst.APPLY_USER_NICKNAME, currentUser.getNickname());
// 流程发起人所在部门ID
variables.put(ActivitiVariableConst.DEPT_ID, currentUser.getDeptId());
// 流程发起人所在部门type code
variables.put(ActivitiVariableConst.DEPT_TYPE_CODE, currentUser.getDept().getTypeCode());
// 流程发起人所在部门type 名称
variables.put(ActivitiVariableConst.DEPT_TYPE_NAME, currentUser.getDept().getTypeName());
// 流程发起人所在部门名称
variables.put(ActivitiVariableConst.DEPT_NAME, currentUser.getDept().getName());
// 流程发起人所属角色 eg: role1,role2,role3
variables.put(ActivitiVariableConst.USER_ROLE_CODES, ArrayUtil.join(roleCodeList.toArray(), CommonConst.SPLIT));
// 设置角色快速判断参数,如isRole1、isRole2等,如果角色标识使用:隔开,则改为驼峰命名 eg: sys:admin => isSysAdmin
for (SysRole role : currentUser.getRoleList()) {
variables.put(convertRoleCode(role.getCode()), CommonConst.TRUE);
}
// 将此用户没有的角色也设置参数,防止使用时参数不存在
List<String> allRoleCode = sysRoleService.selectAllRoleCodes();
String[] currentUserRoleCodes = ArrayUtil.toArray(roleCodeList, String.class);
for (String role : allRoleCode) {
if (!ArrayUtil.contains(currentUserRoleCodes, role)) {
variables.put(convertRoleCode(role), CommonConst.FALSE);
}
}
return variables;
}
/**
* 转换角色标识
*
* @param roleCode 角色标识 eg: sys:admin
* @return 转换后的标识 eg: isSysAdmin
*/
private String convertRoleCode(String roleCode) {
// 角色分隔符
String roleSplit = ":";
StringBuilder tempRole = new StringBuilder();
tempRole.append("is");
if (roleCode.contains(roleSplit)) {
for (String role : roleCode.split(roleSplit)) {
tempRole.append(StrUtil.upperFirst(role));
}
} else {
tempRole.append(StrUtil.upperFirst(roleCode));
}
return tempRole.toString();
}
/**
* 根据流程id获取流程
*
* @param processDefinitionId 流程定义ID
* @return ProcessDefinition
*/
@Override
public ProcessDefinition getProcessDefinition(String processDefinitionId) {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
if (processDefinition == null) {
throw new EasyException("流程[" + processDefinitionId + "]不存在,请检查此流程状态");
}
if (processDefinition.isSuspended()) {
throw new EasyException("流程[" + processDefinition.getName() + "]已挂起,请联系管理员");
}
return processDefinition;
}
/**
* 检查业务数据是否提交过流程一条数据只能提交一次
*
* @param businessKey 业务数据id
* @return true/false
*/
private boolean checkBusinessKey(String businessKey) {
return baseMapper.countBusinessKey(businessKey) > 0;
}
}

169
easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiProcessServiceImpl.java

@ -0,0 +1,169 @@
package com.easy.admin.activiti.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.admin.activiti.constant.ActivitiModelConst;
import com.easy.admin.activiti.dao.ActivitiProcessMapper;
import com.easy.admin.activiti.model.ActivitiProcess;
import com.easy.admin.activiti.service.ActivitiModelService;
import com.easy.admin.activiti.service.ActivitiProcessService;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.common.select.Select;
import com.easy.admin.common.core.constant.CommonConst;
import com.easy.admin.common.core.exception.EasyException;
import com.easy.admin.util.ShiroUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
/**
* 流程
*
* @author TengChongChong
* @date 2019-07-12
*/
@Service
public class ActivitiProcessServiceImpl extends ServiceImpl<ActivitiProcessMapper, ActivitiProcess> implements ActivitiProcessService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private RepositoryService repositoryService;
@Autowired
private ActivitiModelService activitiModelService;
@Autowired
private ObjectMapper objectMapper;
@Override
public Page<ActivitiProcess> select(ActivitiProcess activitiProcess, Page<ActivitiProcess> page) {
QueryWrapper<ActivitiProcess> queryWrapper = new QueryWrapper<>();
if (activitiProcess != null) {
if (StrUtil.isNotBlank(activitiProcess.getKey())) {
queryWrapper.like("arp.key_", activitiProcess.getKey());
}
if (StrUtil.isNotBlank(activitiProcess.getName())) {
queryWrapper.like("arp.name_", activitiProcess.getName());
}
if (StrUtil.isNotBlank(activitiProcess.getProcessDefinitionId())) {
queryWrapper.like("arp.id_", activitiProcess.getProcessDefinitionId());
}
if (activitiProcess.getSuspensionState() != null) {
queryWrapper.like("arp.suspension_state_", activitiProcess.getSuspensionState());
}
}
// 根据流程实例ID排序
page.setDefaultDesc("ard.deploy_time_");
page.setRecords(baseMapper.select(page, queryWrapper));
return page;
}
@Override
public boolean remove(String deploymentIds) {
if (StrUtil.isBlank(deploymentIds)) {
throw new EasyException("获取数据ids失败");
}
List<String> idArray = Arrays.asList(deploymentIds.split(CommonConst.SPLIT));
idArray.forEach(deploymentId -> repositoryService.deleteDeployment(deploymentId, true));
return true;
}
@Override
public boolean convertToModel(ActivitiProcess activitiProcess) {
if (StrUtil.isBlank(activitiProcess.getProcessDefinitionId())) {
throw new EasyException("获取流程id失败");
}
if (StrUtil.isBlank(activitiProcess.getKey())) {
throw new EasyException("标识不能为空");
}
if (StrUtil.isBlank(activitiProcess.getName())) {
throw new EasyException("名称不能为空");
}
// 查询流程信息
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(activitiProcess.getProcessDefinitionId()).singleResult();
// 检查标识是否存在
if (activitiModelService.checkKeyIsExistence(activitiProcess.getKey(), null)) {
throw new EasyException("标识已存在,请修改后重试");
}
InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
try {
// 读取bpmn.xml
InputStreamReader inputStreamReader = new InputStreamReader(bpmnStream, StandardCharsets.UTF_8);
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(inputStreamReader);
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xmlStreamReader);
// xml 转 json
BpmnJsonConverter bpmnJsonConverter = new BpmnJsonConverter();
ObjectNode objectNode = bpmnJsonConverter.convertToJson(bpmnModel);
// 设置 Model 信息
Model model = repositoryService.newModel();
model.setKey(activitiProcess.getKey());
model.setName(activitiProcess.getName());
model.setVersion(1);
// MetaInfo
ObjectNode modelNode = new ObjectMapper().createObjectNode();
modelNode.put(ActivitiModelConst.NAME, model.getName());
modelNode.put(ActivitiModelConst.VERSION, model.getVersion());
modelNode.put(ActivitiModelConst.DESCRIPTION, activitiProcess.getDescription());
model.setMetaInfo(modelNode.toString());
// 保存模型
repositoryService.saveModel(model);
// 修改标识、名称、描述信息
ObjectNode properties = objectMapper.createObjectNode();
properties.put(ActivitiModelConst.PROPERTIES_PROCESS_ID, model.getKey());
properties.put(ActivitiModelConst.NAME, model.getName());
properties.put(ActivitiModelConst.PROPERTIES_PROCESS_AUTHOR, ShiroUtil.getCurrentUser().getNickname());
properties.put(ActivitiModelConst.PROPERTIES_DOCUMENTATION, activitiProcess.getDescription());
objectNode.set(ActivitiModelConst.PROPERTIES, properties);
repositoryService.addModelEditorSource(model.getId(), objectNode.toString().getBytes(StandardCharsets.UTF_8));
return true;
} catch (XMLStreamException e) {
logger.debug("流程转模型失败[" + processDefinition.getId() + "]", e);
throw new EasyException("流程转模型失败[" + processDefinition.getId() + "]" + e.getMessage());
}
}
@Override
public InputStream getImageStream(String deploymentId, String resourceName) {
return repositoryService.getResourceAsStream(deploymentId, resourceName);
}
@Override
public void suspend(String processDefinitionId, boolean suspendProcessInstances) {
repositoryService.suspendProcessDefinitionById(processDefinitionId);
}
@Override
public void activation(String processDefinitionId, boolean activateProcessInstances) {
repositoryService.activateProcessDefinitionById(processDefinitionId, activateProcessInstances, null);
}
@Override
public List<Select> selectProcessForSelect() {
return baseMapper.selectProcessForSelect();
}
}

134
easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiProcessTraceServiceImpl.java

@ -0,0 +1,134 @@
package com.easy.admin.activiti.service.impl;
import com.easy.admin.activiti.config.manager.CustomProcessDiagramGenerator;
import com.easy.admin.activiti.constant.ActivitiWorkflowConst;
import com.easy.admin.activiti.service.ActivitiProcessTraceService;
import com.easy.admin.common.core.constant.CommonConst;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 流程跟踪
*
* @author TengChongChong
* @date 2020/4/29
*/
@Service
public class ActivitiProcessTraceServiceImpl implements ActivitiProcessTraceService {
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ProcessEngineConfiguration processEngineConfiguration;
/**
* 读取动态流程图
*/
@Override
public void readProcessImg(String processInstanceId, HttpServletResponse response) throws IOException {
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
// 高亮环节id集合
List<String> highLightedActivitis = new ArrayList<String>();
// 高亮线路id集合
List<String> highLightedFlows = getHighLightedFlows(definitionEntity, highLightedActivitList);
for (HistoricActivityInstance tempActivity : highLightedActivitList) {
String activityId = tempActivity.getActivityId();
highLightedActivitis.add(activityId);
}
Set<String> currIds = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).list()
.stream().map(e -> e.getActivityId()).collect(Collectors.toSet());
CustomProcessDiagramGenerator diagramGenerator = (CustomProcessDiagramGenerator) processEngineConfiguration.getProcessDiagramGenerator();
InputStream imageStream = diagramGenerator.generateDiagram(
bpmnModel,
"png",
highLightedActivitis,
highLightedFlows,
ActivitiWorkflowConst.TYPEFACE,
ActivitiWorkflowConst.TYPEFACE,
ActivitiWorkflowConst.TYPEFACE,
null,
1.0,
new Color[]{ActivitiWorkflowConst.COLOR_NORMAL, ActivitiWorkflowConst.COLOR_CURRENT},
currIds);
// 输出资源内容到相应对象
byte[] b = new byte[1024];
int len;
while ((len = imageStream.read(b, 0, CommonConst.BYTE1024)) != -1) {
response.getOutputStream().write(b, 0, len);
}
}
/**
* 获取需要高亮的线
*
* @param processDefinitionEntity 流程实例
* @param historicActivityInstances 历史活动
* @return 高亮 flows
*/
private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity,
List<HistoricActivityInstance> historicActivityInstances) {
// 用以保存高亮的线flowId
List<String> highFlows = new ArrayList<>();
// 对历史流程节点进行遍历
for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
HistoricActivityInstance iThisHis = historicActivityInstances.get(i);
// 用以保存后结束时间相同的节点
List<ActivityImpl> endTimeNodes = new ArrayList<>();
if (iThisHis.getEndTime() != null) {
// 对历史流程节点进行遍历
for (int j = i + 1; j < historicActivityInstances.size(); j++) {
HistoricActivityInstance jThisHis = historicActivityInstances.get(j);
// 如果第2个节点结束时间相同保存
if (iThisHis.getEndTime().compareTo(jThisHis.getStartTime()) == 0) {
ActivityImpl jActivity = processDefinitionEntity.findActivity(jThisHis.getActivityId());
endTimeNodes.add(jActivity);
}
}
ActivityImpl iActivity = processDefinitionEntity.findActivity(iThisHis.getActivityId());
// 取出节点的所有出去的线
List<PvmTransition> pvmTransitions = iActivity.getOutgoingTransitions();
for (PvmTransition pvmTransition : pvmTransitions) {
// 对所有的线进行遍历
ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();
// 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示
if (endTimeNodes.contains(pvmActivityImpl)) {
highFlows.add(pvmTransition.getId());
}
}
}
}
return highFlows;
}
}

229
easy-activiti/src/main/java/com/easy/admin/activiti/service/impl/ActivitiTaskServiceImpl.java

@ -0,0 +1,229 @@
package com.easy.admin.activiti.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.admin.activiti.constant.ActivitiTaskStatusConst;
import com.easy.admin.activiti.constant.ActivitiVariableConst;
import com.easy.admin.activiti.constant.ActivitiWorkflowConst;
import com.easy.admin.activiti.constant.status.ActivitiSuspensionStatus;
import com.easy.admin.activiti.dao.ActivitiTaskMapper;
import com.easy.admin.activiti.model.ActivitiFormPropertyVO;
import com.easy.admin.activiti.model.ActivitiTask;
import com.easy.admin.activiti.model.ActivitiTaskInfo;
import com.easy.admin.activiti.service.ActivitiProcessDefinitionService;
import com.easy.admin.activiti.service.ActivitiTaskService;
import com.easy.admin.auth.model.SysUser;
import com.easy.admin.auth.service.SysUserService;
import com.easy.admin.common.core.common.pagination.Page;
import com.easy.admin.common.core.exception.EasyException;
import com.easy.admin.core.mail.MailTemplate;
import com.easy.admin.sys.common.constant.MessageConst;
import com.easy.admin.sys.model.SysMessage;
import com.easy.admin.sys.service.SysMessageService;
import com.easy.admin.util.ShiroUtil;
import org.activiti.engine.FormService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.StartFormData;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* 待办任务
*
* @author TengChongChong
* @date 2020/3/27
*/
@Service
public class ActivitiTaskServiceImpl extends ServiceImpl<ActivitiTaskMapper, ActivitiTask> implements ActivitiTaskService {
@Autowired
private org.activiti.engine.TaskService taskService;
@Autowired
private FormService formService;
@Autowired
private SysUserService sysUserService;
@Autowired
private ActivitiProcessDefinitionService activitiProcessDefinitionService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private SysMessageService sysMessageService;
@Override
public Page<ActivitiTask> select(ActivitiTask activitiTask, Page<ActivitiTask> page) {
QueryWrapper<ActivitiTask> queryWrapper = new QueryWrapper<>();
SysUser currentUser = ShiroUtil.getCurrentUser();
// 查询条件
if (activitiTask != null) {
// 名称
if (StrUtil.isNotBlank(activitiTask.getBusinessTitle())) {
queryWrapper.like("arv_businessTitle.text_", "%" + activitiTask.getBusinessTitle() + "%");
}
// 流水
if (StrUtil.isNotBlank(activitiTask.getProcessInstanceId())) {
queryWrapper.eq("art.proc_inst_id_", activitiTask.getProcessInstanceId());
}
if (StrUtil.isNotBlank(activitiTask.getStatus())) {
if (ActivitiTaskStatusConst.WAITING_CLAIM.equals(activitiTask.getStatus())) {
// 待签收
queryWrapper.isNull("art.assignee_")
.eq("ari.type_", "candidate")
.and(i -> i.eq("ari.user_id_", currentUser.getId()).or().in("ari.group_id_", ShiroUtil.getRoleIds(currentUser.getRoleList()).toArray()));
} else if (ActivitiTaskStatusConst.CLAIMED.equals(activitiTask.getStatus())) {
// 待办任务:签收人或委托人为当前用户
queryWrapper.and(i -> i.eq("art.assignee_", currentUser.getId()).or().eq("art.owner_", currentUser.getId()));
} else {
return null;
}
}
}
// 待签、待办中只查询激活流程实例数据,已挂起的不查询
queryWrapper.eq("arp.suspension_state_", ActivitiSuspensionStatus.ACTIVATION.getCode());
page.setDefaultDesc("art.id_");
page.setRecords(baseMapper.select(page, queryWrapper));
return page;
}
@Override
public void claimTask(String taskId) {
taskService.claim(taskId, ShiroUtil.getCurrentUser().getId());
}
@Override
public ActivitiTaskInfo readTaskForm(String taskId) {
ActivitiTaskInfo taskInfo = new ActivitiTaskInfo();
org.activiti.engine.task.Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new EasyException("任务[" + taskId + "]已办理或不存在");
}
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
taskInfo.setBusinessKey(processInstance.getBusinessKey());
TaskFormData taskFormData = formService.getTaskFormData(taskId);
if (taskFormData.getFormProperties() != null && !taskFormData.getFormProperties().isEmpty()) {
List<ActivitiFormPropertyVO> activitiFormPropertyVOList = new ArrayList<>();
for (FormProperty formProperty : taskFormData.getFormProperties()) {
activitiFormPropertyVOList.add(new ActivitiFormPropertyVO(formProperty));
}
// 有动态表单
taskInfo.setHasTaskForm(true);
taskInfo.setTaskFormData(activitiFormPropertyVOList);
}
taskInfo.setCreateDate(task.getCreateTime());
// 流程发起信息
StartFormData startTaskFormData = formService.getStartFormData(task.getProcessDefinitionId());
// 有动态表单
if (startTaskFormData.getFormProperties() != null && !startTaskFormData.getFormProperties().isEmpty()) {
List<ActivitiFormPropertyVO> activitiFormPropertyVOList = new ArrayList<>();
for (FormProperty formProperty : startTaskFormData.getFormProperties()) {
activitiFormPropertyVOList.add(new ActivitiFormPropertyVO(formProperty));
}
taskInfo.setHasTaskForm(true);
taskInfo.setStartFormData(activitiFormPropertyVOList);
}
// 获取流程参数
Map<String, Object> variables = taskService.getVariables(taskId);
taskInfo.setVariables(variables);
// 设置发起人信息
if (variables.get(ActivitiVariableConst.APPLY_USER_ID) != null) {
taskInfo.setApplyUser(sysUserService.getUser((String) variables.get(ActivitiVariableConst.APPLY_USER_ID)));
}
return taskInfo;
}
@Override
public void completeTask(String taskId, JSONObject params) {
// 流程定义ID
ActivitiTask activitiTask = baseMapper.selectProcessDefinitionId(taskId, ActivitiSuspensionStatus.ACTIVATION.getCode());
if (activitiTask == null) {
throw new EasyException("任务不存在,请检查后重试");
}
if (StrUtil.isNotBlank(activitiTask.getProcessDefinitionId())) {
// 检查流程状态
activitiProcessDefinitionService.getProcessDefinition(activitiTask.getProcessDefinitionId());
// 获取提交表单数据
Map<String, String> formValues = Convert.toMap(String.class, String.class, params) ;
formService.submitTaskFormData(taskId, formValues);
// 自动签收
activitiProcessDefinitionService.autoClaimTask(activitiTask.getProcessInstanceId());
}
}
@Override
public void revoke(String processInstanceId, String deleteReason) {
// 检查是否可以撤销
Subject subject = SecurityUtils.getSubject();
ActivitiTask activitiTask = baseMapper.selectTask(processInstanceId);
if(activitiTask == null){
throw new EasyException("撤销失败,流程未发起或已办结");
}
boolean isApplyUser = activitiTask.getApplyUserId().equals(ShiroUtil.getCurrentUser().getId());
boolean isAdmin = subject.hasRole(ActivitiWorkflowConst.SYS_ADMIN_ROLE);
if (!isAdmin && !isApplyUser) {
throw new EasyException("撤销失败,你无权撤销此申请");
}
// 系统管理员或发起人可以撤销
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
if (isAdmin && !isApplyUser) {
// 是管理员,但是不是发起人,撤销后给发起人发消息
sendMessage(activitiTask, deleteReason);
}
}
/**
* 发送申请被管理员撤销信息
*
* @param activitiTask 任务
* @param deleteReason 撤销原因
*/
private void sendMessage(ActivitiTask activitiTask, String deleteReason) {
SysUser currentUser = ShiroUtil.getCurrentUser();
// 设置模板引擎变量
Map<String,Object> params = new HashMap<>(4);
params.put("processDefinitionName", activitiTask.getProcessDefinitionName());
params.put("processVersion", activitiTask.getProcessVersion());
params.put("createTime", DateUtil.format(activitiTask.getCreateTime(), DatePattern.NORM_DATETIME_MINUTE_PATTERN));
params.put("processInstanceId", activitiTask.getProcessInstanceId());
params.put("businessDetailsPath", activitiTask.getBusinessDetailsPath());
params.put("businessTitle", activitiTask.getBusinessTitle());
params.put("deleteDate", DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN));
params.put("deleteUser", currentUser.getNickname());
params.put("deleteReason", deleteReason);
SysMessage sysMessage = new SysMessage();
sysMessage.setTitle("你发起的[" + activitiTask.getProcessDefinitionName() + "]" + activitiTask.getBusinessTitle() + "被" + currentUser.getNickname() + "]撤销");
// 重要
sysMessage.setImportant(MessageConst.IMPORTANT_YES);
sysMessage.setContent(MailTemplate.getContent("/message/revocation-notice.html", params));
// 接收人
sysMessage.setReceivers(Collections.singletonList(activitiTask.getApplyUserId()));
// 立即发出
sysMessage.setStatus(MessageConst.STATUS_HAS_BEEN_SENT);
// 消息类型 - 通知
sysMessage.setType(MessageConst.TYPE_NOTICE);
sysMessageService.saveData(sysMessage);
}
}

74
easy-activiti/src/main/resources/message/revocation-notice.html

@ -0,0 +1,74 @@
<div class="ant-row">
<div class="ant-col ant-col-sm-24">
<div class="ant-row ant-form-item">
<div class="ant-col ant-col-6 ant-form-item-label">
<label title="流程" class="">流程</label>
</div>
<div class="ant-col ant-col-18 ant-form-item-control-wrapper">
<div class="ant-form-item-control">
<span class="ant-form-item-children"> ${processDefinitionName} </span>
</div>
</div>
</div>
<div class="ant-row ant-form-item">
<div class="ant-col ant-col-6 ant-form-item-label">
<label title="发起时间" class="">发起时间</label>
</div>
<div class="ant-col ant-col-18 ant-form-item-control-wrapper">
<div class="ant-form-item-control">
<span class="ant-form-item-children"> ${createTime} </span>
</div>
</div>
</div>
<div class="ant-row ant-form-item">
<div class="ant-col ant-col-6 ant-form-item-label">
<label title="流水号" class="">流水号</label>
</div>
<div class="ant-col ant-col-18 ant-form-item-control-wrapper">
<div class="ant-form-item-control">
<span class="ant-form-item-children"> ${processInstanceId} </span>
</div>
</div>
</div>
<div class="ant-row ant-form-item">
<div class="ant-col ant-col-6 ant-form-item-label">
<label title="业务" class="">业务</label>
</div>
<div class="ant-col ant-col-18 ant-form-item-control-wrapper">
<div class="ant-form-item-control">
<span class="ant-form-item-children"> ${businessTitle} </span>
</div>
</div>
</div>
<div class="ant-row ant-form-item">
<div class="ant-col ant-col-6 ant-form-item-label">
<label title="撤销时间" class="">撤销时间</label>
</div>
<div class="ant-col ant-col-18 ant-form-item-control-wrapper">
<div class="ant-form-item-control">
<span class="ant-form-item-children"> ${deleteDate} </span>
</div>
</div>
</div>
<div class="ant-row ant-form-item">
<div class="ant-col ant-col-6 ant-form-item-label">
<label title="撤销人" class="">撤销人</label>
</div>
<div class="ant-col ant-col-18 ant-form-item-control-wrapper">
<div class="ant-form-item-control">
<span class="ant-form-item-children"> ${deleteUser} </span>
</div>
</div>
</div>
<div class="ant-row ant-form-item">
<div class="ant-col ant-col-6 ant-form-item-label">
<label title="撤销原由" class="">撤销原由</label>
</div>
<div class="ant-col ant-col-18 ant-form-item-control-wrapper">
<div class="ant-form-item-control">
<span class="ant-form-item-children"> ${deleteReason} </span>
</div>
</div>
</div>
</div>
</div>

2154
easy-activiti/src/main/resources/stencilset.json

File diff suppressed because one or more lines are too long

13
easy-api/Dockerfile

@ -0,0 +1,13 @@
FROM openjdk:8
WORKDIR /easy-vben
ARG JAR_FILE=target/easy-api.jar
COPY ${JAR_FILE} app.jar
EXPOSE 80
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms2000m -Xmx4000m -Djava.security.egd=file:/dev/./urandom"
CMD java $JAVA_OPTS -jar app.jar

122
easy-api/pom.xml

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.easy.admin</groupId>
<artifactId>easy-vben</artifactId>
<version>1.1.0</version>
</parent>
<artifactId>easy-api</artifactId>
<packaging>jar</packaging>
<!-- <packaging>war</packaging>-->
<description>Easy Api</description>
<dependencies>
<dependency>
<groupId>com.easy.admin</groupId>
<artifactId>easy-sys</artifactId>
</dependency>
<dependency>
<groupId>com.easy.admin</groupId>
<artifactId>easy-file</artifactId>
</dependency>
<dependency>
<groupId>com.easy.admin</groupId>
<artifactId>easy-generator</artifactId>
</dependency>
<dependency>
<groupId>com.easy.admin</groupId>
<artifactId>easy-scheduler</artifactId>
</dependency>
<dependency>
<groupId>com.easy.admin</groupId>
<artifactId>easy-activiti</artifactId>
</dependency>
<dependency>
<groupId>com.easy.admin</groupId>
<artifactId>easy-sample</artifactId>
</dependency>
<dependency>
<groupId>com.easy.admin</groupId>
<artifactId>easy-cms</artifactId>
</dependency>
<dependency>
<groupId>com.easy.admin</groupId>
<!-- easy-xxx 请替换为实际名称 -->
<artifactId>huzhou</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.easy.admin</groupId>-->
<!-- <artifactId>easy-huozhou</artifactId>-->
<!-- </dependency>-->
</dependencies>
<build>
<finalName>${project.name}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/webapp</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<finalName>${project.build.finalName}</finalName>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<repositories>
<!--阿里云主仓库,代理了maven central和jcenter仓库-->
<repository>
<id>aliyun</id>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<profiles>
<profile>
<id>dev</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>dev</profiles.active>
</properties>
<activation>
<!-- 默认环境 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
</project>

26
easy-api/src/main/java/com/easy/admin/Application.java

@ -0,0 +1,26 @@
package com.easy.admin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 启动类
*
* @author TengChongChong
* @date 2020/06/12
*/
@EnableCaching
@EnableTransactionManagement
//@MapperScan("com.easy.admin.modules.huzhou.dao")
@SpringBootApplication()
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

19
easy-api/src/main/java/com/easy/admin/WebStartApplication.java

@ -0,0 +1,19 @@
package com.easy.admin;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
* web 容器下启动类
* war 方式部署情况下使用
*
* @author TengChongChong
* @date 2020/06/12
*/
public class WebStartApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}

38
easy-api/src/main/java/com/easy/admin/easyapi/config/web/EasyErrorController.java

@ -0,0 +1,38 @@
package com.easy.admin.easyapi.config.web;
import com.easy.admin.common.core.util.Response;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* 自定义容器级错误响应内容
*
* @author TengChongChong
* @date 2018/10/22
*/
@Controller
public class EasyErrorController extends BasicErrorController {
public EasyErrorController() {
super(new DefaultErrorAttributes(), new ErrorProperties());
}
/**
* 自定义ajax响应内容
*/
@Override
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
HttpStatus status = getStatus(request);
// 响应数据
Map<String, Object> map = getErrorAttributes(request, ErrorAttributeOptions.defaults());
return new ResponseEntity(Response.failError("00" + map.get("status"), map.get("error") + " - " + map.get("path")), status);
}
}

157
easy-api/src/main/java/com/easy/admin/easyapi/config/web/ExceptionControllerAdvice.java

@ -0,0 +1,157 @@
package com.easy.admin.easyapi.config.web;
import cn.hutool.core.util.StrUtil;
import com.easy.admin.common.core.common.status.ResultCode;
import com.easy.admin.common.core.exception.EasyException;
import com.easy.admin.common.core.util.Response;
import com.easy.admin.sys.model.SysException;
import com.easy.admin.auth.model.SysUser;
import com.easy.admin.sys.service.SysExceptionService;
import com.easy.admin.util.ShiroUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
/**
* 通用异常处理(应用级异常)
*
* @author TengChongChong
* @date 2018/10/22
*/
@RestControllerAdvice
public class ExceptionControllerAdvice {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private SysExceptionService sysExceptionService;
/**
* 拦截业务异常
*/
@ExceptionHandler(EasyException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Response easyException(HttpServletRequest request, EasyException e) {
logger.debug("业务异常", e);
return Response.failError(null, e.getCode(), e.getMessage(), e.getShowType());
}
/**
* 拦截未经认证异常未登录
*/
@ExceptionHandler(UnauthenticatedException.class)
public Response unauthenticatedException(UnauthenticatedException e) {
return Response.failError(ResultCode.UNAUTHORIZED.getCode(), "你尚未登录,请登录后重试");
}
/**
* 权限异常已登录无权限
*/
@ExceptionHandler({UnauthorizedException.class})
@ResponseStatus(HttpStatus.FORBIDDEN)
public Response unauthorizedException(HttpServletRequest request, UnauthorizedException e) {
// 你无权限访问此资源
return Response.failError(ResultCode.FORBIDDEN.getCode(), "无权限访问[" + request.getMethod() + "]" + request.getRequestURI());
}
/**
* 登录异常
*/
@ExceptionHandler(AuthenticationException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Response authenticationException(HttpServletRequest request, AuthenticationException e) {
if (e.getCause() != null && e.getCause() instanceof EasyException) {
logger.error("登录异常:" + e.getCause().getMessage());
EasyException easyException = (EasyException) e.getCause();
return Response.failError(null, easyException.getCode(), easyException.getMessage(), easyException.getShowType());
} else {
logger.error("登录异常:" + e.getMessage());
return Response.failError(e.getMessage(), Response.SHOW_TYPE_WARNING);
}
}
/**
* 缺少请求体异常
*
* @param e 缺少请求体异常
* @return ResponseResult
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public Response parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
return Response.failError(ResultCode.BAD_REQUEST.getCode(), "参数体为空或参数类型错误[" + e.getMessage() + "]");
}
/**
* 参数效验异常
*
* @param e 参数验证异常
* @return ResponseInfo
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Response parameterExceptionHandler(MethodArgumentNotValidException e) {
// 获取异常信息
BindingResult exceptions = e.getBindingResult();
// 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
if (exceptions.hasErrors()) {
List<ObjectError> errors = exceptions.getAllErrors();
if (!errors.isEmpty()) {
// 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可
FieldError fieldError = (FieldError) errors.get(0);
return Response.failError(ResultCode.BAD_REQUEST.getCode(), fieldError.getDefaultMessage());
}
}
return Response.failError(ResultCode.BAD_REQUEST.getCode(), "参数效验异常[" + e.getMessage() + "]");
}
/**
* 未知异常
*/
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Object handleException(HttpServletRequest request, RuntimeException e) {
logger.debug("未知异常", e);
// 将异常记录到表中
saveLog(HttpStatus.INTERNAL_SERVER_ERROR.value(), request.getMethod() + " " + request.getRequestURI(), e);
return Response.failError(e.getMessage());
}
/**
* 保存异常信息
*
* @param code 错误代码
* @param uri 请求地址
* @param e 异常信息
*/
private void saveLog(int code, String uri, RuntimeException e) {
SysException sysException = new SysException();
sysException.setCode(code);
sysException.setMessage(e.getMessage());
sysException.setUrl(uri);
sysException.setTriggerTime(new Date());
sysException.setType(e.getClass().getName());
sysException.setTrace(StrUtil.join("\n\t", e.getStackTrace()));
SysUser currentUser = ShiroUtil.getCurrentUser();
if (currentUser != null) {
sysException.setUserId(currentUser.getId());
}
sysExceptionService.saveData(sysException);
}
}

55
easy-api/src/main/java/com/easy/admin/easyapi/config/web/ResponseResultHandler.java

@ -0,0 +1,55 @@
package com.easy.admin.easyapi.config.web;
import com.easy.admin.common.core.constant.CommonConst;
import com.easy.admin.common.core.util.Response;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.servlet.http.HttpServletRequest;
/**
* 重写返回体
*
* @author TengChongChong
* @date 2020/12/28
*/
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
/**
* 请求是否包含注解标记没有就直接返回
*
* @param returnType methodParameter
* @param converterType converterType
* @return true/false
*/
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
// 是包含注解标记
Boolean needPack = (Boolean) request.getAttribute(CommonConst.RESPONSE_RESULT_ANN);
return needPack != null && needPack;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof Response) {
// 如果已包装,直接返回
return body;
}
// 如果方法返回为String类型对象,会使用StringHttpMessageConverter,这时候就会报错:类型转换异常
if (selectedConverterType == StringHttpMessageConverter.class) {
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
return Response.success(body).toString();
}
return Response.success(body);
}
}

40
easy-api/src/main/java/com/easy/admin/easyapi/config/web/WebConfig.java

@ -0,0 +1,40 @@
package com.easy.admin.easyapi.config.web;
import com.easy.admin.common.core.interceptor.ResponseResultInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* web config
*
* @author TengChongChong
* @date 2019-03-16
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private ResponseResultInterceptor responseResultInterceptor;
@Override
public void addCorsMappings(CorsRegistry registry) {
//设置允许跨域的路径
registry.addMapping("/**")
//设置允许跨域请求的域名
.allowedOriginPatterns("*")
//是否允许证书 不再默认开启
.allowCredentials(true)
//设置允许的方法
.allowedMethods("*")
//跨域允许时间
.maxAge(3600);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加拦截器,配置拦截地址
registry.addInterceptor(responseResultInterceptor).addPathPatterns("/**");
}
}

120
easy-api/src/main/resources/application-dev.yml

@ -0,0 +1,120 @@
project:
# 项目访问url,无需 / 结尾
url: http://127.0.0.1:8080
# 前端访问url
front-end-url: http://localhost:3100
node: 127.0.0.1:${server.port}
springdoc:
api-docs:
#是否开启文档功能
enabled: true
#包扫描路径
packagesToScan: com.easy.admin
server:
# 端口号
port: 8080
# servlet:
# context-path: /guoyan #可以修改/jeecg-boot
logging:
file:
path: logs
spring:
jackson:
date-format: yyyy-MM-dd
time-zone: GMT+8
# elasticsearch:
# rest:
# # 连接超时时间
# connection-timeout: 1s
# username:
# password:
# # 读取超时时间
# read-timeout: 30s
# # es rest 接口地址,多个用逗号隔开
# uris: ${ES_HOST:127.0.0.1}:${ES_PORT:9200}
# Redis
redis:
# 数据库索引(默认为0)
database: 9
# 服务器地址
host: 127.0.0.1
# 服务器连接端口
port: 6379
# 服务器连接密码(默认为空)
password:
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
# 连接超时时间 单位: 秒
timeout: 10
# 默认的数据过期时间 30 分钟 单位: 秒
expire: 1800
datasource:
dynamic:
datasource:
master:
# url: jdbc:mysql://${DB_HOST:218.246.6.173}:${DB_PORT:3306}/${DB_NAME:guoyan_huzhou}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMulQueries=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullDatabaseMeansCurrent=true&useInformationSchema=true
# username: ${DB_USERNAME:root}
# password: ${DB_PASSWORD:1q2w#E$R1qaz@WSX}
url: jdbc:mariadb://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:easy_java}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMulQueries=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullDatabaseMeansCurrent=true&useInformationSchema=true
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:root}
# url: jdbc:mariadb://${DB_HOST:218.246.6.173}:${DB_PORT:3306}/${DB_NAME:easy-vben}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMulQueries=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullDatabaseMeansCurrent=true&useInformationSchema=true
# username: ${DB_USERNAME:root}
# password: ${DB_PASSWORD:Yun1993.}
# oss 对象存储
file:
storage:
# 文件存储方式:local - 本地存储 / oss - 对象存储
# type: oss
type: local
# 文件存放(local - 默认文件夹名称 / oss - 默认bucket名称),命名规范:只能包括小写字母、数字和短划线(-);必须以小写字母或者数字开头和结尾;长度为3~63个字符。
default-bucket: easy-default
# local - 本地存储
local:
# 用于存放上传的文件、临时文件等,以目录分隔符结尾(不要写以~开头的路径会导致无法访问)
path: /Users/tengchong/development/easy-vben/
# oss - 对象存储
# oss:
# # 对象存储类型,暂时仅支持 minio
# type: minio
# # oss api
# endpoint: http://127.0.0.1:9000
# # accessKey
# access-key: tZje4eJbaR52LU5Ynmgl
# # secretKey
# secret-key: LSYcLw9iLDwLrLTN8znE8xC5oG4AO2Fw12dPhfmX
# 打印sql语句,调试用
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
aj:
captcha:
# 滑动验证,底图路径,不配置将使用默认图片
jigsaw: classpath:images/verification
async:
executor:
thread:
# 配置核心线程数
core-pool-size: 5
# 配置最大线程数
max-pool-size: 5
# 配置队列大小
queue-capacity: 999
# 配置线程池中的线程的名称前缀
name-prefix: async-
# 配置线程最大空闲时间 s
keep-alive-seconds: 30
jeecg:
path:
#文件上传根目录 设置
# upload: /opt/upFiles
upload: D:/ce
uploadType: local

101
easy-api/src/main/resources/application-prod.yml

@ -0,0 +1,101 @@
project:
# 项目访问url
url: http://127.0.0.1
# 前端访问url
front-end-url: http://localhost:3100
# 文件上传路径(不要写以~开头的路径会导致无法访问)
file-upload-path: /Users/guoyan/development/easy-vben
node: 127.0.0.1:${server.port}
springdoc:
api-docs:
#是否开启文档功能
enabled: true
#包扫描路径
packagesToScan: com.easy.admin
server:
# 端口号
port: 9001
logging:
file:
path: logs
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
elasticsearch:
rest:
# 连接超时时间
connection-timeout: 1s
username:
password:
# 读取超时时间
read-timeout: 30s
# es rest 接口地址,多个用逗号隔开
uris: ${ES_HOST:127.0.0.1}:${ES_PORT:9200}
# Redis
redis:
# 数据库索引(默认为0)
database: 9
# 服务器地址
host: 127.0.0.1
# 服务器连接端口
port: 6379
# 服务器连接密码(默认为空)
password: 1q2wE$R1qaz@WSX
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
# 连接超时时间 单位: 秒
timeout: 10
# 默认的数据过期时间 30 分钟 单位: 秒
expire: 1800
datasource:
dynamic:
datasource:
master:
url: jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:guoyan_huzhou}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMulQueries=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullDatabaseMeansCurrent=true&useInformationSchema=true
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:1q2w#E$R1qaz@WSX}
aj:
captcha:
# 滑动验证,底图路径,不配置将使用默认图片
jigsaw: classpath:images/verification
async:
executor:
thread:
# 配置核心线程数
core-pool-size: 5
# 配置最大线程数
max-pool-size: 5
# 配置队列大小
queue-capacity: 999
# 配置线程池中的线程的名称前缀
name-prefix: async-
# 配置线程最大空闲时间 s
keep-alive-seconds: 30
jeecg:
uploadType: local
path:
#文件上传根目录 设置
upload: /opt/guoyan/upload
#webapp文件路径
webapp: /opt/guoyan/webapp
file:
storage:
# 文件存储方式:local - 本地存储 / oss - 对象存储
# type: oss
type: local
# 文件存放(local - 默认文件夹名称 / oss - 默认bucket名称),命名规范:只能包括小写字母、数字和短划线(-);必须以小写字母或者数字开头和结尾;长度为3~63个字符。
default-bucket: easy-default
# local - 本地存储
local:
# 用于存放上传的文件、临时文件等,以目录分隔符结尾(不要写以~开头的路径会导致无法访问)
path: /Users/guoyan/development/easy-vben/

101
easy-api/src/main/resources/application-test.yml

@ -0,0 +1,101 @@
project:
# 项目访问url
url: http://127.0.0.1
# 前端访问url
front-end-url: http://localhost:3100
# 文件上传路径(不要写以~开头的路径会导致无法访问)
file-upload-path: /Users/guoyan/development/easy-vben
node: 127.0.0.1:${server.port}
springdoc:
api-docs:
#是否开启文档功能
enabled: true
#包扫描路径
packagesToScan: com.easy.admin
server:
# 端口号
port: 9004
logging:
file:
path: logs
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
elasticsearch:
rest:
# 连接超时时间
connection-timeout: 1s
username:
password:
# 读取超时时间
read-timeout: 30s
# es rest 接口地址,多个用逗号隔开
uris: ${ES_HOST:127.0.0.1}:${ES_PORT:9200}
# Redis
redis:
# 数据库索引(默认为0)
database: 9
# 服务器地址
host: 127.0.0.1
# 服务器连接端口
port: 6379
# 服务器连接密码(默认为空)
password: 1q2wE$R1qaz@WSX
jedis:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
# 连接超时时间 单位: 秒
timeout: 10
# 默认的数据过期时间 30 分钟 单位: 秒
expire: 1800
datasource:
dynamic:
datasource:
master:
url: jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:guoyan_test}?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMulQueries=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullDatabaseMeansCurrent=true&useInformationSchema=true
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:1q2w#E$R1qaz@WSX}
aj:
captcha:
# 滑动验证,底图路径,不配置将使用默认图片
jigsaw: classpath:images/verification
async:
executor:
thread:
# 配置核心线程数
core-pool-size: 5
# 配置最大线程数
max-pool-size: 5
# 配置队列大小
queue-capacity: 999
# 配置线程池中的线程的名称前缀
name-prefix: async-
# 配置线程最大空闲时间 s
keep-alive-seconds: 30
jeecg:
uploadType: local
path:
#文件上传根目录 设置
upload: /opt/guoyantest/upload
#webapp文件路径
webapp: /opt/guoyantest/webapp
file:
storage:
# 文件存储方式:local - 本地存储 / oss - 对象存储
# type: oss
type: local
# 文件存放(local - 默认文件夹名称 / oss - 默认bucket名称),命名规范:只能包括小写字母、数字和短划线(-);必须以小写字母或者数字开头和结尾;长度为3~63个字符。
default-bucket: easy-default
# local - 本地存储
local:
# 用于存放上传的文件、临时文件等,以目录分隔符结尾(不要写以~开头的路径会导致无法访问)
path: /Users/guoyan/development/easy-vben/

69
easy-api/src/main/resources/application.yml

@ -0,0 +1,69 @@
project:
# 版本号
version: 0.5.0
# 项目访问url
url: http://127.0.0.1
spring:
profiles:
# dev - 开发模式 / prod - 生产模式
active: dev
mvc:
static-path-pattern: /static/**
servlet:
multipart:
# 上传文件总的最大值
max-request-size: 1000MB
# 单个文件的最大值
max-file-size: 1000MB
web:
resources:
static-locations:
[ "classpath:/static/", "classpath:/themes/", "file:${file.storage.local.path}", "file:${beetl.theme-root}/" ]
datasource:
druid:
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
# druid连接池监控
stat-view-servlet:
enabled: true
url-pattern: /druid/*
reset-enable: true
login-username: druid
login-password: druid
dynamic:
primary: 'master'
# druid连接池监控
druid:
connection-properties:
# 慢SQL记录
druid.stat.mergeSql: true
druid.stat.slowSqlMillis: 2000
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计
filters: stat,slf4j,config
# 初始化时建立物理连接的个数
initial-size: 5
# 最小连接池数量
min-idle: 5
# 最大连接池数量
max-active: 30
# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
max-pool-prepared-statement-per-connection-size: 50
# 获取连接时最大等待时间,单位毫秒
max-wait: 60000
# 连接保持空闲而不被驱逐的最小时间
min-evictable-idle-time-millis: 300000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
pool-prepared-statements: true
test-on-borrow: false
test-on-return: false
test-while-idle: true
use-global-data-source-stat: true
validation-query: select 1 from dual
beetl:
theme:
# 主题文件Root目录,为了不影响项目使用jar部署,CMS主题项目将放到项目外部,此处进作为示例。
root: /Users/tengchong/workspaces/github/easy-vben/easy-cms/src/main/themes

1
easy-api/src/main/resources/config/mail.setting

@ -0,0 +1 @@
# 邮件服务器的SMTP地址,可选,默认为smtp.<发件人邮箱后缀> #host = smtp.yeah.net host = smtp.sina.com # 邮件服务器的SMTP端口,可选,默认25 # 注: 出于安全考虑,阿里云默认封禁TCP 25端口出方向的访问流量。如必须使用请参考https://help.aliyun.com/knowledge_detail/56130.html解封 # port = 25 port = 587 # 发件人(必须正确,否则发送失败) #from = EasyFrame<tengchongchong@yeah.net> from = EasyFrame<easyframe@sina.com> # 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助) pass = easyframe123

BIN
easy-api/src/main/resources/images/verification/original/bg1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg11.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg12.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg14.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg15.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg17.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg19.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg20.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
easy-api/src/main/resources/images/verification/original/bg5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save