@ -0,0 +1,13 @@ |
|||
### 该问题是怎么引起的? |
|||
|
|||
|
|||
|
|||
### 重现步骤 |
|||
|
|||
|
|||
|
|||
### 报错信息 |
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,15 @@ |
|||
### 相关的Issue |
|||
|
|||
|
|||
### 原因(目的、解决的问题等) |
|||
|
|||
|
|||
### 描述(做了什么,变更了什么) |
|||
|
|||
|
|||
### 测试用例(新增、改动、可能影响的功能) |
|||
|
|||
|
|||
|
|||
|
|||
|
@ -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 |
@ -0,0 +1,10 @@ |
|||
# 更新日志 |
|||
|
|||
### 1.1.0 |
|||
`2023-08-15` |
|||
- 🌟 修复一些问题 |
|||
- 🌟新增CMS模块 |
|||
|
|||
### 🔥🔥🔥 1.0.0 正式版发布 🔥🔥🔥 |
|||
`2022-07-31` |
|||
- 🌟 版本发布 |
@ -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. |
@ -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`启动服务 |
@ -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_); |
|||
|
@ -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_); |
@ -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; |
@ -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> |
@ -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(); |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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."); |
|||
} |
|||
} |
@ -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()); |
|||
} |
|||
} |
|||
} |
@ -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); |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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."); |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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"; |
|||
} |
@ -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"; |
|||
} |
@ -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"; |
|||
} |
@ -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; |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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(); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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(); |
|||
} |
|||
} |
@ -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); |
|||
} |
@ -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 |
|||
); |
|||
|
|||
} |
@ -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); |
|||
} |
@ -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); |
|||
} |
@ -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(); |
|||
} |
@ -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); |
|||
} |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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 + |
|||
'}'; |
|||
} |
|||
} |
@ -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; |
|||
/** |
|||
* 活动类型:如startEvent、userTask |
|||
*/ |
|||
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; |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
|
|||
|
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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 + |
|||
'}'; |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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); |
|||
} |
@ -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); |
|||
} |
@ -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); |
|||
} |
@ -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); |
|||
} |
@ -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(); |
|||
} |
@ -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; |
|||
} |
@ -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); |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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 流程模型 |
|||
* 部分代码来源于 Activiti(StencilsetRestResource.java、ModelEditorJsonRestResource.java、ModelSaveRestResource.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(); |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
|
|||
} |
@ -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(); |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
|
|||
|
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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> |
@ -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 |
@ -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> |
@ -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); |
|||
|
|||
|
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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("/**"); |
|||
} |
|||
} |
@ -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 |
@ -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/ |
@ -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/ |
@ -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 |
@ -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 |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 69 KiB |