版权声明:作者:jiankunking 出处:http://blog.csdn.net/jiankunking 本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
/**更新请假状态,启动流程实例,让启动的流程实例关联业务*/
@Override
public void saveStartProcess(WorkflowBean workflowBean) {
//1:获取请假单ID,使用请假单ID,查询请假单的对象LeaveBill
Long id = workflowBean.getId();
LeaveBill leaveBill = leaveBillDao.findLeaveBillById(id);
//2:更新请假单的请假状态从0变成1(初始录入-->审核中)
leaveBill.setState(1);
//3:使用当前对象获取到流程定义的key(对象的名称就是流程定义的key)
String key = leaveBill.getClass().getSimpleName();
/**
* 4:从Session中获取当前任务的办理人,使用流程变量设置下一个任务的办理人
* inputUser是流程变量的名称,
* 获取的办理人是流程变量的值
*/
Map<String, Object> variables = new HashMap<String,Object>();
variables.put("inputUser", SessionContext.get().getName());//表示惟一用户
/**
* 5: (1)使用流程变量设置字符串(格式:LeaveBill.id的形式),通过设置,让启动的流程(流程实例)关联业务
(2)使用正在执行对象表中的一个字段BUSINESS_KEY(Activiti提供的一个字段),让启动的流程(流程实例)关联业务
*/
//格式:LeaveBill.id的形式(使用流程变量)
String objId = key+"."+id;
variables.put("objId", objId);
//6:使用流程定义的key,启动流程实例,同时设置流程变量,同时向正在执行的执行对象表中的字段BUSINESS_KEY添加业务数据,同时让流程关联业务
runtimeService.startProcessInstanceByKey(key,objId,variables);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
这里写图片描述
/**二:已知任务ID,查询ProcessDefinitionEntiy对象,从而获取当前任务完成之后的连线名称,并放置到List<String>集合中*/
@Override
public List<String> findOutComeListByTaskId(String taskId) {
//返回存放连线的名称集合
List<String> list = new ArrayList<String>();
//1:使用任务ID,查询任务对象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//2:获取流程定义ID
String processDefinitionId = task.getProcessDefinitionId();
//3:查询ProcessDefinitionEntiy对象
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
//使用任务对象Task获取流程实例ID
String processInstanceId = task.getProcessInstanceId();
//使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
//获取当前活动的id
String activityId = pi.getActivityId();
//4:获取当前的活动
ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
//5:获取当前活动完成之后连线的名称
List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions();
if(pvmList!=null && pvmList.size()>0){
for(PvmTransition pvm:pvmList){
String name = (String) pvm.getProperty("name");
if(StringUtils.isNotBlank(name)){
list.add(name);
}
else{
list.add("默认提交");
}
}
}
return list;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
批注部分:
这里写图片描述
这里写图片描述
这里写图片描述
/**指定连线的名称完成任务*/
@Override
public void saveSubmitTask(WorkflowBean workflowBean) {
//获取任务ID
String taskId = workflowBean.getTaskId();
//获取连线的名称
String outcome = workflowBean.getOutcome();
//批注信息
String message = workflowBean.getComment();
//获取请假单ID
Long id = workflowBean.getId();
/**
* 1:在完成之前,添加一个批注信息,向act_hi_comment表中添加数据,用于记录对当前申请人的一些审核信息
*/
//使用任务ID,查询任务对象,获取流程流程实例ID
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//获取流程实例ID
String processInstanceId = task.getProcessInstanceId();
/**
* 注意:添加批注的时候,由于Activiti底层代码是使用:
* String userId = Authentication.getAuthenticatedUserId();
CommentEntity comment = new CommentEntity();
comment.setUserId(userId);
所有需要从Session中获取当前登录人,作为该任务的办理人(审核人),对应act_hi_comment表中的User_ID的字段,不过不添加审核人,该字段为null
所以要求,添加配置执行使用Authentication.setAuthenticatedUserId();添加当前任务的审核人
* */
Authentication.setAuthenticatedUserId(SessionContext.get().getName());
taskService.addComment(taskId, processInstanceId, message);
/**
* 2:如果连线的名称是“默认提交”,那么就不需要设置,如果不是,就需要设置流程变量
* 在完成任务之前,设置流程变量,按照连线的名称,去完成任务
流程变量的名称:outcome
流程变量的值:连线的名称
*/
Map<String, Object> variables = new HashMap<String,Object>();
if(outcome!=null && !outcome.equals("默认提交")){
variables.put("outcome", outcome);
}
//3:使用任务ID,完成当前人的个人任务,同时流程变量
taskService.complete(taskId, variables);
//4:当任务完成之后,需要指定下一个任务的办理人(使用类)-----已经开发完成
/**
* 5:在完成任务之后,判断流程是否结束
如果流程结束了,更新请假单表的状态从1变成2(审核中-->审核完成)
*/
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
//流程结束了
if(pi==null){
//更新请假单表的状态从1变成2(审核中-->审核完成)
LeaveBill bill = leaveBillDao.findLeaveBillById(id);
bill.setState(2);
}
}
/**获取批注信息,传递的是当前任务ID,获取历史任务ID对应的批注*/
@Override
public List<Comment> findCommentByTaskId(String taskId) {
List<Comment> list = new ArrayList<Comment>();
//使用当前的任务ID,查询当前流程对应的历史任务ID
//使用当前任务ID,获取当前任务对象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//获取流程实例ID
String processInstanceId = task.getProcessInstanceId();
// //使用流程实例ID,查询历史任务,获取历史任务对应的每个任务ID
// List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()//历史任务表查询
// .processInstanceId(processInstanceId)//使用流程实例ID查询
// .list();
// //遍历集合,获取每个任务ID
// if(htiList!=null && htiList.size()>0){
// for(HistoricTaskInstance hti:htiList){
// //任务ID
// String htaskId = hti.getId();
// //获取批注信息
// List<Comment> taskList = taskService.getTaskComments(htaskId);//对用历史完成后的任务ID
// list.addAll(taskList);
// }
// }
list = taskService.getProcessInstanceComments(processInstanceId);
return list;
}
/**使用请假单ID,查询历史批注信息*/
@Override
public List<Comment> findCommentByLeaveBillId(Long id) {
//使用请假单ID,查询请假单对象
LeaveBill leaveBill = leaveBillDao.findLeaveBillById(id);
//获取对象的名称
String objectName = leaveBill.getClass().getSimpleName();
//组织流程表中的字段中的值
String objId = objectName+"."+id;
/**1:使用历史的流程实例查询,返回历史的流程实例对象,获取流程实例ID*/
// HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()//对应历史的流程实例表
// .processInstanceBusinessKey(objId)//使用BusinessKey字段查询
// .singleResult();
// //流程实例ID
// String processInstanceId = hpi.getId();
/**2:使用历史的流程变量查询,返回历史的流程变量的对象,获取流程实例ID*/
HistoricVariableInstance hvi = historyService.createHistoricVariableInstanceQuery()//对应历史的流程变量表
.variableValueEquals("objId", objId)//使用流程变量的名称和流程变量的值查询
.singleResult();
//流程实例ID
String processInstanceId = hvi.getProcessInstanceId();
List<Comment> list = taskService.getProcessInstanceComments(processInstanceId);
return list;
}
/**1:获取任务ID,获取任务对象,使用任务对象获取流程定义ID,查询流程定义对象*/
@Override
public ProcessDefinition findProcessDefinitionByTaskId(String taskId) {
//使用任务ID,查询任务对象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//获取流程定义ID
String processDefinitionId = task.getProcessDefinitionId();
//查询流程定义的对象
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()//创建流程定义查询对象,对应表act_re_procdef
.processDefinitionId(processDefinitionId)//使用流程定义ID查询
.singleResult();
return pd;
}
/**
* 二:查看当前活动,获取当期活动对应的坐标x,y,width,height,将4个值存放到Map<String,Object>中
map集合的key:表示坐标x,y,width,height
map集合的value:表示坐标对应的值
*/
@Override
public Map<String, Object> findCoordingByTask(String taskId) {
//存放坐标
Map<String, Object> map = new HashMap<String,Object>();
//使用任务ID,查询任务对象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//获取流程定义的ID
String processDefinitionId = task.getProcessDefinitionId();
//获取流程定义的实体对象(对应.bpmn文件中的数据)
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processDefinitionId);
//流程实例ID
String processInstanceId = task.getProcessInstanceId();
//使用流程实例ID,查询正在执行的执行对象表,获取当前活动对应的流程实例对象
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//创建流程实例查询
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
//获取当前活动的ID
String activityId = pi.getActivityId();
//获取当前活动对象
ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);//活动ID
//获取坐标
map.put("x", activityImpl.getX());
map.put("y", activityImpl.getY());
map.put("width", activityImpl.getWidth());
map.put("height", activityImpl.getHeight());
return map;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
本文部分内容整理自itcast讲义,在此表示感谢。
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
/**更新请假状态,启动流程实例,让启动的流程实例关联业务*/
@Override
public void saveStartProcess(WorkflowBean workflowBean) {
//1:获取请假单ID,使用请假单ID,查询请假单的对象LeaveBill
Long id = workflowBean.getId();
LeaveBill leaveBill = leaveBillDao.findLeaveBillById(id);
//2:更新请假单的请假状态从0变成1(初始录入-->审核中)
leaveBill.setState(1);
//3:使用当前对象获取到流程定义的key(对象的名称就是流程定义的key)
String key = leaveBill.getClass().getSimpleName();
/**
* 4:从Session中获取当前任务的办理人,使用流程变量设置下一个任务的办理人
* inputUser是流程变量的名称,
* 获取的办理人是流程变量的值
*/
Map<String, Object> variables = new HashMap<String,Object>();
variables.put("inputUser", SessionContext.get().getName());//表示惟一用户
/**
* 5: (1)使用流程变量设置字符串(格式:LeaveBill.id的形式),通过设置,让启动的流程(流程实例)关联业务
(2)使用正在执行对象表中的一个字段BUSINESS_KEY(Activiti提供的一个字段),让启动的流程(流程实例)关联业务
*/
//格式:LeaveBill.id的形式(使用流程变量)
String objId = key+"."+id;
variables.put("objId", objId);
//6:使用流程定义的key,启动流程实例,同时设置流程变量,同时向正在执行的执行对象表中的字段BUSINESS_KEY添加业务数据,同时让流程关联业务
runtimeService.startProcessInstanceByKey(key,objId,variables);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
这里写图片描述
/**二:已知任务ID,查询ProcessDefinitionEntiy对象,从而获取当前任务完成之后的连线名称,并放置到List<String>集合中*/
@Override
public List<String> findOutComeListByTaskId(String taskId) {
//返回存放连线的名称集合
List<String> list = new ArrayList<String>();
//1:使用任务ID,查询任务对象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//2:获取流程定义ID
String processDefinitionId = task.getProcessDefinitionId();
//3:查询ProcessDefinitionEntiy对象
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
//使用任务对象Task获取流程实例ID
String processInstanceId = task.getProcessInstanceId();
//使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
//获取当前活动的id
String activityId = pi.getActivityId();
//4:获取当前的活动
ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
//5:获取当前活动完成之后连线的名称
List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions();
if(pvmList!=null && pvmList.size()>0){
for(PvmTransition pvm:pvmList){
String name = (String) pvm.getProperty("name");
if(StringUtils.isNotBlank(name)){
list.add(name);
}
else{
list.add("默认提交");
}
}
}
return list;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
批注部分:
这里写图片描述
这里写图片描述
这里写图片描述
/**指定连线的名称完成任务*/
@Override
public void saveSubmitTask(WorkflowBean workflowBean) {
//获取任务ID
String taskId = workflowBean.getTaskId();
//获取连线的名称
String outcome = workflowBean.getOutcome();
//批注信息
String message = workflowBean.getComment();
//获取请假单ID
Long id = workflowBean.getId();
/**
* 1:在完成之前,添加一个批注信息,向act_hi_comment表中添加数据,用于记录对当前申请人的一些审核信息
*/
//使用任务ID,查询任务对象,获取流程流程实例ID
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//获取流程实例ID
String processInstanceId = task.getProcessInstanceId();
/**
* 注意:添加批注的时候,由于Activiti底层代码是使用:
* String userId = Authentication.getAuthenticatedUserId();
CommentEntity comment = new CommentEntity();
comment.setUserId(userId);
所有需要从Session中获取当前登录人,作为该任务的办理人(审核人),对应act_hi_comment表中的User_ID的字段,不过不添加审核人,该字段为null
所以要求,添加配置执行使用Authentication.setAuthenticatedUserId();添加当前任务的审核人
* */
Authentication.setAuthenticatedUserId(SessionContext.get().getName());
taskService.addComment(taskId, processInstanceId, message);
/**
* 2:如果连线的名称是“默认提交”,那么就不需要设置,如果不是,就需要设置流程变量
* 在完成任务之前,设置流程变量,按照连线的名称,去完成任务
流程变量的名称:outcome
流程变量的值:连线的名称
*/
Map<String, Object> variables = new HashMap<String,Object>();
if(outcome!=null && !outcome.equals("默认提交")){
variables.put("outcome", outcome);
}
//3:使用任务ID,完成当前人的个人任务,同时流程变量
taskService.complete(taskId, variables);
//4:当任务完成之后,需要指定下一个任务的办理人(使用类)-----已经开发完成
/**
* 5:在完成任务之后,判断流程是否结束
如果流程结束了,更新请假单表的状态从1变成2(审核中-->审核完成)
*/
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
//流程结束了
if(pi==null){
//更新请假单表的状态从1变成2(审核中-->审核完成)
LeaveBill bill = leaveBillDao.findLeaveBillById(id);
bill.setState(2);
}
}
/**获取批注信息,传递的是当前任务ID,获取历史任务ID对应的批注*/
@Override
public List<Comment> findCommentByTaskId(String taskId) {
List<Comment> list = new ArrayList<Comment>();
//使用当前的任务ID,查询当前流程对应的历史任务ID
//使用当前任务ID,获取当前任务对象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//获取流程实例ID
String processInstanceId = task.getProcessInstanceId();
// //使用流程实例ID,查询历史任务,获取历史任务对应的每个任务ID
// List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()//历史任务表查询
// .processInstanceId(processInstanceId)//使用流程实例ID查询
// .list();
// //遍历集合,获取每个任务ID
// if(htiList!=null && htiList.size()>0){
// for(HistoricTaskInstance hti:htiList){
// //任务ID
// String htaskId = hti.getId();
// //获取批注信息
// List<Comment> taskList = taskService.getTaskComments(htaskId);//对用历史完成后的任务ID
// list.addAll(taskList);
// }
// }
list = taskService.getProcessInstanceComments(processInstanceId);
return list;
}
/**使用请假单ID,查询历史批注信息*/
@Override
public List<Comment> findCommentByLeaveBillId(Long id) {
//使用请假单ID,查询请假单对象
LeaveBill leaveBill = leaveBillDao.findLeaveBillById(id);
//获取对象的名称
String objectName = leaveBill.getClass().getSimpleName();
//组织流程表中的字段中的值
String objId = objectName+"."+id;
/**1:使用历史的流程实例查询,返回历史的流程实例对象,获取流程实例ID*/
// HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()//对应历史的流程实例表
// .processInstanceBusinessKey(objId)//使用BusinessKey字段查询
// .singleResult();
// //流程实例ID
// String processInstanceId = hpi.getId();
/**2:使用历史的流程变量查询,返回历史的流程变量的对象,获取流程实例ID*/
HistoricVariableInstance hvi = historyService.createHistoricVariableInstanceQuery()//对应历史的流程变量表
.variableValueEquals("objId", objId)//使用流程变量的名称和流程变量的值查询
.singleResult();
//流程实例ID
String processInstanceId = hvi.getProcessInstanceId();
List<Comment> list = taskService.getProcessInstanceComments(processInstanceId);
return list;
}
/**1:获取任务ID,获取任务对象,使用任务对象获取流程定义ID,查询流程定义对象*/
@Override
public ProcessDefinition findProcessDefinitionByTaskId(String taskId) {
//使用任务ID,查询任务对象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//获取流程定义ID
String processDefinitionId = task.getProcessDefinitionId();
//查询流程定义的对象
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()//创建流程定义查询对象,对应表act_re_procdef
.processDefinitionId(processDefinitionId)//使用流程定义ID查询
.singleResult();
return pd;
}
/**
* 二:查看当前活动,获取当期活动对应的坐标x,y,width,height,将4个值存放到Map<String,Object>中
map集合的key:表示坐标x,y,width,height
map集合的value:表示坐标对应的值
*/
@Override
public Map<String, Object> findCoordingByTask(String taskId) {
//存放坐标
Map<String, Object> map = new HashMap<String,Object>();
//使用任务ID,查询任务对象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任务ID查询
.singleResult();
//获取流程定义的ID
String processDefinitionId = task.getProcessDefinitionId();
//获取流程定义的实体对象(对应.bpmn文件中的数据)
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processDefinitionId);
//流程实例ID
String processInstanceId = task.getProcessInstanceId();
//使用流程实例ID,查询正在执行的执行对象表,获取当前活动对应的流程实例对象
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//创建流程实例查询
.processInstanceId(processInstanceId)//使用流程实例ID查询
.singleResult();
//获取当前活动的ID
String activityId = pi.getActivityId();
//获取当前活动对象
ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);//活动ID
//获取坐标
map.put("x", activityImpl.getX());
map.put("y", activityImpl.getY());
map.put("width", activityImpl.getWidth());
map.put("height", activityImpl.getHeight());
return map;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
本文部分内容整理自itcast讲义,在此表示感谢。