Commit 31031b39 authored by yang's avatar yang

修改工作流功能文档

parent 2ff9aace
# 使用Groovy脚本创建DTO及其他对象
Groovy脚本是Idea内置支持的拓展语言,所以,该脚本只适用于Idea使用,Eclepse推荐使用系统内置的DTO创建工具
1. 创建database
使用Idea右侧的工具栏创建一个database,配置数据库连接,连接到指定的数据库
*若是没有database选项,请检查是否已经开启database插件:setting->plugins*
![创建database](/assets/database_add.png)
![配置database](/assets/database_config.png)
2. 导入Groovy脚本
在database下的table中随便选择一张表,右击,Scripted Extensions ->Go to Script Directory,复制脚本到指定目录下
![导入Groovy脚本](/assets/database_add_script.png)
3. 生成DTO、Mapper、Service、ServiceImpl对象
在database下的table中选择需要创建DTO的表,右击,Scripted Extensions ->Generate Hel.groovy, 弹出文件选框,选择到指定的目录下
*会自动在指定目录下创建dto、mapper、service、service.impl四个包路径*
![生成](/assets/database_script.png)
\ No newline at end of file
......@@ -3,196 +3,226 @@
### 工作流开发
#### 工作流开发整体思路
工作流的开发大致分为以下几步:
* 流程设计
* 实现启动接口
* 调用实现类
* 启动工作流
* 流程部署
* 流程启动
下面以付款申请流程为例。
#### 一、流程设计
1. 开始设计流程之前,先在工作流配置界面进行新建模型操作,输入完整界面上各个字段信息后进行保存。
**唯一标识****分类**两个字段需要特别注意,这两个字段用于后台业务代码区分具体是哪一个工作流信息。
界面如下图所示:
![新建模型界面](/assets/wfl_payment_req_create.png)
一、流程设计
1 新建工作流并填写对应的信息
![](/assets/wfl_demo_1.png)
![](/assets/wfl_demo_2.png)
\*这里需要注意分类跟唯一标识这个字段,后面编写实现类的时候需要传入分类跟唯一标识。
2 保存之后点击对应工作流的第一个图标,即可编辑对应的工作流节点,下面将详细介绍一些常用的工作流属性(新建工作流的时候可参考已实现工作流)
* ID:自动生成,节点唯一标识
* 名称:当前节点中文描述
* 文档:消息机制,可在上下文中取到,如:我是${name},name为实现类里面配置的参数
* 审批方式:默认为全部通过
* 审批方式变量:当审批方式选择一定比例时,可设置变量如0.4,表示当审批人数达到这个比例后将会通过
* 审批规则:选择对应的审批人,可在审批规则中定义
* 加签:若勾选,则当前审批者可添加审批人
* 表单url:表示审批流程中可插入的页面,能让审判者读阅
* 执行监听器:执行监听器start跟end两种分别代表在该节点之前跟在该节点之后,在代理表达式里面可调用对应自己写的java类,格式如下:${endActionEventTask}
* 任务监听器:任务监听器可参考执行监听器
下图是一个完整的工作流流程设计
![](/assets/wfl_demo_3.png)
二、实现启动接口
* 编写一个自己的实现类,实现IActivitiCommonService接口
![](/assets/wfl_demo_4.png)
实现类代码如下
2. 模型新建之后,需要设计具体的业务流程
![进入模型界面](/assets/wfl_payment_req_modify_btn.png)
从左边选择相应的节点,描述出整个业务的流程
![描述模型界面](/assets/wfl_payment_req_draw.png)
**各个流程节点的相关配置信息将在后面进行详细的介绍**
#### 二、流程部署
流程设计好以后,点击流程设计页面操作栏的最后一个按钮(勾)即可发布流程
`未发布过的流程或者改动过的流程,勾会以绿色展示,反之灰色`
发布以后可以在流程部署页面查看部署情况
`如果有旧的流程启动了,发布的新版不会影响旧流程的运行`
部署按钮见下图
![部署模型界面](/assets/wfl_payment_req_deploy.png)
#### 三、流程启动
流程启动一般是在前端发送请求到后端,后端进行处理后,触发工作流启动。
请求处理类:
```java
@Override
public void paymentApproval(IRequest iRequest, HttpSession session, List<HlsCusConContractCashflow> list) {
// ...
Map<String, Object> params = new HashMap<String, Object>();
// 注意此处的workFlowType,该参数将和另一个业务类中的Code对应
params.put("workFlowType", "PAY_PAYMENT");
params.put("cshPaymentReqLn", ss.get(0));
// 启动工作流流程
activitiStartService.start(iRequest, list, params);
// ...
}
```
业务实现类:
```java
@Service
@Transactional
public class PrjActivitStartServiceImpl implements IActivitiCommonService
{
private static final String workFlowType = "PRJ_PROJECT";
@Autowired
private IActivitiService activitiService;
@Autowired
private IReProcdefService reProcdefService;
@Autowired
private PrjProjectService projectService;
@Autowired
private PrjProjectMeetingMapper meetingMapper;
@Override
public String getWorkFlowType() { return workFlowType; }
@Override
public void process(IRequest iRequest, List list, Map params)
{
ProcessInstanceCreateRequest processInstanceCreateRequest = getProcessInstanceCreateRequest((PrjProject)list.get(0),iRequest);
activitiService.startProcess(iRequest, processInstanceCreateRequest);
public class PaymentActivitStartServiceImpl implements IActivitiCommonService {
// 该数据对应了请求响应启动工作流时传入的workFlowType
private static final String workFlowType = "PAY_PAYMENT";
@Override
public String getWorkFlowType() {
return workFlowType;
}
// 启动工作流时,会自动调用该方法
@Override
public void process(IRequest iRequest, List list,Map params) {
ProcessInstanceCreateRequest createRequest = getProcessInstanceCreateRequest(list,iRequest,params);
// 启动流程
activitiService.startProcess(iRequest, createRequest);
}
private ProcessInstanceCreateRequest getProcessInstanceCreateRequest(PrjProject prjProject, IRequest iRequest)
{
public ProcessInstanceCreateRequest getProcessInstanceCreateRequest(List<HlsCusConContractCashflow> list, IRequest iRequest, Map params) {
ProcessInstanceCreateRequest createRequest = new ProcessInstanceCreateRequest();
PrjProject project=projectService.selectByPrimaryKey(iRequest,prjProject);
ReProcdef reProcdefs ;
reProcdefs = reProcdefService.queryReProcdef("PRJ_PROJECT_APPROVE","PRJ_PROJECT");
// 此处的两个参数,分别对应了新建模型时输入的**唯一标识**以及**分类**
ReProcdef reProcdefs = reProcdefService.queryReProcdef("CSH_PAYMENT_REQ_WORK_FLOW","CSH_PAYMENT");
SysUser sysUser = sysUserService.selectUserById(iRequest.getUserId());
String id = reProcdefs.getId_();
String name = reProcdefs.getName_();
createRequest.setProcessDefinitionId(id);
createRequest.setBusinessKey(prjProject.getProjectId().toString());
String name = reProcdefs.getName_();
createRequest.setProcessDefinitionId(id);
createRequest.setBusinessKey(list.get(0).getContract_id().toString());
List<RestVariable> variables = new ArrayList<RestVariable>();
List<RestVariable> transientVariables = new ArrayList<RestVariable>();
RestVariable restVariable1 = new RestVariable();
RestVariable restVariable2 = new RestVariable();
RestVariable restVariable3 = new RestVariable();
RestVariable restVariable2 = new RestVariable();
RestVariable restVariable3 = new RestVariable();
RestVariable restVariable4 = new RestVariable();
RestVariable restVariable5 = new RestVariable();
RestVariable restVariable6 = new RestVariable();
restVariable1.setName("processDefinitionId");
restVariable1.setValue(id); variables.add(restVariable1);
restVariable2.setName("prjProject");
JSONObject jsonObject= new JSONObject().fromObject(prjProject);
restVariable2.setValue(jsonObject.toString());
variables.add(restVariable2);
restVariable3.setName("iRequest");
restVariable3.setValue(iRequest);
variables.add(restVariable3);
restVariable4.setName("projectNum");
restVariable4.setValue(project.getProjectNumber());
variables.add(restVariable4);
restVariable5.setName("projectName");
restVariable5.setValue(project.getProjectName());
variables.add(restVariable5);
restVariable6.setName("startUserName");
restVariable6.setValue(iRequest.getEmployeeCode());
variables.add(restVariable6);
RestVariable restVariable7 = new RestVariable();
RestVariable restVariable8 = new RestVariable();
RestVariable restVariable9 = new RestVariable();
restVariable7.setName("documentCategory");
restVariable7.setValue(project.getDocumentCategory());
variables.add(restVariable7);
restVariable8.setName("documentType");
restVariable8.setValue(project.getDocumentType());
variables.add(restVariable8);
restVariable9.setName("documentId");
restVariable9.setValue(project.getProjectId());
variables.add(restVariable9);
RestVariable restVariable10 = new RestVariable();
restVariable10.setName("doubleFlag");
PrjProjectMeeting meeting = new PrjProjectMeeting();
meeting.setProjectId(prjProject.getProjectId());
List<PrjProjectMeeting> list = meetingMapper.select(meeting);
if(list.size() >0) {
restVariable10.setValue("Y");
}
else{
restVariable10.setValue("N");
}
variables.add(restVariable10);
RestVariable restVariable11 = new RestVariable();
restVariable11.setName("pName");
restVariable11.setValue(name);
variables.add(restVariable11);
createRequest.setVariables(variables);
createRequest.setTransientVariables(transientVariables);
return createRequest;
}}
RestVariable restVariable5 = new RestVariable();
RestVariable restVariable13 = new RestVariable();
RestVariable restVariable20 = new RestVariable();
RestVariable restVariable = new RestVariable();
```
HlsCusCshPaymentReqLn cshPaymentReqLn = (HlsCusCshPaymentReqLn)params.get("cshPaymentReqLn");
restVariable.setName("paymentRedId");
restVariable.setValue(cshPaymentReqLn.getPayment_req_id());
variables.add(restVariable);
* 关键参数讲解:
private static final String workFlowType = "PRJ\_PROJECT";在启动工作流的时候工作流会根据这个类型找到对应的实现类,
在启动工作流的时候会调用process方法,该方法会调用getProcessInstanceCreateRequest方法,在getProcessInstanceCreateRequest方法里面
可以将自己工作流所需参数都放到里面去,可以在后面的流程中取到自己所需参数。
reProcdefs = reProcdefService.queryReProcdef\("PRJ\_PROJECT\_APPROVE","PRJ\_PROJECT"\);参数一为创建工作流时候的唯一标志,参数二为工作流的分类
restVariable20.setName("contractId");
restVariable20.setValue(cshPaymentReqLn.getSource_doc_id());
variables.add(restVariable20);
三 调用实现类并启动工作流
restVariable1.setName("processDefinitionId");
restVariable1.setValue(id);
variables.add(restVariable1);
```
Map<String,Object> params = new HashMap<String,Object>();
params.put("workFlowType","PRJ_PROJECT");
activitiStartService.start(iRequest,projects,params);
restVariable2.setName("contractCashflows");
restVariable2.setValue(list);
variables.add(restVariable2);
```
* 代码解析
params.put\("workFlowType","PRJ\_PROJECT"\);放入的为工作流实现类的类型
#### 工作流功能详解
一、配置审批方式
![](/assets/wfl_demo_2-1.png)
如上图,在选择审批方式的时候,一共有五种审批方式,这里面的审批方式可在下图中的功能里面配置,如下图所示,
![](/assets/wfl_demo_2-2.png)
![](/assets/wfl_demo_2-3.png)
这里面配置的审批方式会在设计节点的时候查询出来,可在这里删除或者添加新的审批方式,审批方式中的通过条件中,里面的一个变量为系统内置变量,具体含义可在IActivitiConstants.java文件中查看,如下图所示,
![](/assets/wfl_demo_2-4.png)
restVariable3.setName("iRequest");
restVariable3.setValue(iRequest);
variables.add(restVariable3);
二、配置审批规则
在流程设计的时候,点击审批规则会弹出下面的选择框,如下图所示,
![](/assets/wfl_demo_2-5.png)
审批规则是一个combobox,这里面的选项是在审批规则的功能里面进行配置,如下图所示
![](/assets/wfl_demo_2-6.png)
![](/assets/wfl_demo_2-7.png)
我们可以看到,这里我们需要配置三个选项,分别是代码,描述,表达式,这里表达式对应某个变量或者我们后台写的service,我们通过service取得对应这个审批规则下所有的审批人员,我们可以看到方法后面还跟了一个参数,这个参数在我们选择的时候会放到表单属性里面,在我们介绍表单属性的会具体介绍
double sumAmount = 0L;
for(HlsCusConContractCashflow contractCashflow:list){
sumAmount = add(sumAmount,contractCashflow.getAmount());
}
// 注意此处的sumAmount,在流程设计的过程中将会被使用到
restVariable4.setName("sumAmount");
restVariable4.setValue(new BigDecimal(sumAmount).toPlainString());
variables.add(restVariable4);
三、表单属性
点击表单属性,弹出下图,
![](/assets/wfl_demo_2-9.png)
这里面可以根据业务场景自行配置表单属性,但是这里有两个比较重要的表单属性是必须要配置的,一个为配置审批规则的时候自动生成的表单属性,一个为配置审批选项时需要配置的审批按钮(如:同意,拒绝),分别如下图所示,
![](/assets/wfl_demo_2-10.png)
![](/assets/wfl_demo_2-11.png)
restVariable5.setName("startUserName");
restVariable5.setValue(iRequest.getEmployeeCode());
variables.add(restVariable5);
第一个图里面的表单属性是在我们配置完审批规则的时候会自动生成的,无须我们自行配置,我们可以看到我们这里选择的是按岗位进行审批,所以这里面生成一个岗位代码,工作流在找节点的时候就会调用我们配置的service传入这个code进行查询,将该节点的审批人员查询出来。
RestVariable restVariable6 = new RestVariable();
RestVariable restVariable7 = new RestVariable();
RestVariable restVariable8 = new RestVariable();
restVariable6.setName("documentCategory");
restVariable6.setValue("CSH_PAYMENT_REQ");
variables.add(restVariable6);
restVariable7.setName("documentType");
restVariable7.setValue("PAYMENT_REQ");
variables.add(restVariable7);
restVariable8.setName("documentId");
restVariable8.setValue(cshPaymentReqLn.getPayment_req_id());
variables.add(restVariable8);
RestVariable restVariable9 = new RestVariable();
restVariable9.setName("pName");
restVariable9.setValue(name);
variables.add(restVariable9);
第二图为审批人员在审批页面可点击的审批按钮,我们配置了哪些,在审批页面就会出来对应哪些按钮,加签与转交跟这个是一样的,也会生成对应的按钮,这里需要注意的是对应的按钮代码是固定的,我们需要配置对应的代码才会出现对应的按钮
RestVariable restVariable10 = new RestVariable();
restVariable10.setName("cshPaymentReqLn");
restVariable10.setValue(cshPaymentReqLn);
variables.add(restVariable10);
RestVariable restVariable11 = new RestVariable();
restVariable11.setName("ContractId");
restVariable11.setValue(cshPaymentReqLn.getContract_id());
variables.add(restVariable11);
restVariable13.setName("startUserDescription");
restVariable13.setValue(sysUser.getDescription());
variables.add(restVariable13);
createRequest.setVariables(variables);
createRequest.setTransientVariables(transientVariables);
return createRequest;
}
private double add(Double a, Double b) {
BigDecimal aa = new BigDecimal(a.toString());
BigDecimal bb = new BigDecimal(b.toString());
return aa.add(bb).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
```
**在该业务实现代码中,所有通过variables.add进行添加的参数,都可以在工作流设计时直接通过${ PARAM_NAME }使用,详细的用法在后面会进行介绍**
--- ---
### 流程设计详细
上面介绍了整个工作流流程启动的流程,但是在流程的设计过程并没有进行介绍,接下来将对流程图的设计以及流程的监听事件等进行介绍。
- 节点
首先进入流程的详细界面,选择一个人工节点,如下图:
![查看人工节点](/assets/wfl_payment_req_detail.png)
可以看到右侧有许多的配置属性,下面是几个常用的属性的用途:
* ID:自动生成,节点唯一标识
* 名称:当前节点中文描述
* 文档:消息机制,可在上下文中取到,如:我是${name},name为实现类里面配置的参数
* 审批方式:默认为全部通过
* 审批方式变量:当审批方式选择一定比例时,可设置变量如0.4,表示当审批人数达到这个比例后将会通过
* 审批规则:选择对应的审批人,可在审批规则中定义
* 加签:若勾选,则当前审批者可添加审批人
* 表单url:表示审批流程中可插入的页面,能让审判者读阅
* 执行监听器:执行监听器start跟end两种分别代表在该节点之前跟在该节点之后,在代理表达式里面可调用对应自己写的java类,格式如下:${endActionEventTask},endActionEventTask为监听类在spring容器中的名称,一般为首字母小写之后的类名。
* 任务监听器:任务监听器可参考执行监听器
1. 文档
可以看到右侧有对该流程的一些配置信息,先看文档,文档中的内容最终可以通过消息机制,当流程完成该流程时会在界面上显示文档中的内容。
![文档](/assets/wfl_payment_req_doc.png)
在文档中的内容,可以通过前面介绍的${}方式,直接使用在**业务代码**中添加的参数信息。
2. 审批方式
![](/assets/wfl_demo_2-1.png)
如上图,在选择审批方式的时候,一共有五种审批方式,这里面的审批方式可在下图中的功能里面配置,如下图所示,
![](/assets/wfl_demo_2-2.png)
![](/assets/wfl_demo_2-3.png)
这里面配置的审批方式会在设计节点的时候查询出来,可在这里删除或者添加新的审批方式,审批方式中的通过条件中,里面的一个变量为系统内置变量,具体含义可在IActivitiConstants.java文件中查看,如下图所示,
![](/assets/wfl_demo_2-4.png)
3. 审批规则
在流程设计的时候,点击审批规则会弹出下面的选择框,如下图所示,
![](/assets/wfl_demo_2-5.png)
审批规则是一个combobox,这里面的选项是在审批规则的功能里面进行配置,如下图所示
![](/assets/wfl_demo_2-6.png)
![](/assets/wfl_demo_2-7.png)
我们可以看到,这里我们需要配置三个选项,分别是代码,描述,表达式,这里表达式对应某个变量或者我们后台写的service,我们通过service取得对应这个审批规则下所有的审批人员,我们可以看到方法后面还跟了一个参数,这个参数在我们选择的时候会放到表单属性里面,在我们介绍表单属性的会具体介绍
4. 表单属性
在右侧点击表单属性可以弹出表单属性的详细信息。(表单属性可以通过审批方式及审批规则自动添加,也可以手动填写)如图:
![表单属性](/assets/wfl_payment_req_form.png)
| 表单属性id | 表单名 | 类型 | 描述 |
| --------- | ------ | ---- | ---- |
| APPROVAL_STRATEGY | ALL_APPROVAL | String | 审批策略为全部通过,指定的所有的审批人全都同意 |
| APPROVAL_CANDIDATE_RULE | - | Enum | 审批候选人,使用Enum类型,可以指定职位或者指定人进行审批,在其中设置id为APPOINTED_EMPLOYEE或APPOINTED_POSITION,表单名为{"parameter":[{"employeeCode":"//指定的employeeCode"}],"businessRules":[]} |
另外若是想在审批页面指定出现哪些按钮,可以通过下图的方式进行配置
![](/assets/wfl_demo_2-11.png)
这里需要注意的是对应的按钮代码是固定的,我们需要配置对应的代码才会出现对应的按钮
5. 任务监听
在右侧点击任务监听后,弹出任务监听详细信息,可以通过选择不同的事件(create创建、assignment分配、complete完成、delete删除)并且配置Delegate expression(这个代理表达式使用${}包裹类名,但是类名为spring容器中对应的处理类的名称,如${approveActionEventTask},一般为对应处理类的名称首字母小写)
- 网关
网关相当于一个if条件判断,通过在网关延伸出的流程线条上可以指定在什么条件流程会朝该方向进行。
通过选中网关延伸出的线条,点击右侧的跳转条件,可以设置跳转到该方向的条件。值得注意的是,在这里设置的条件可以使用上面描述的**业务代码**中设置的任何的参数,使用方式见下图:
![](/assets/wfl_payment_req_condition.png)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment