Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
datax-cloud
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
黄营
datax-cloud
Commits
91ca57bb
Commit
91ca57bb
authored
Sep 14, 2020
by
yuwei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
项目初始化
parent
52c2029f
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
491 additions
and
76 deletions
+491
-76
VariablesEnum.java
...va/cn/datax/service/workflow/api/enums/VariablesEnum.java
+18
-6
FlowDefinitionVo.java
...va/cn/datax/service/workflow/api/vo/FlowDefinitionVo.java
+3
-2
FlowHistTaskVo.java
...java/cn/datax/service/workflow/api/vo/FlowHistTaskVo.java
+68
-0
FlowInstanceVo.java
...java/cn/datax/service/workflow/api/vo/FlowInstanceVo.java
+52
-0
FlowTaskVo.java
...ain/java/cn/datax/service/workflow/api/vo/FlowTaskVo.java
+61
-0
FlowDefinitionController.java
...service/workflow/controller/FlowDefinitionController.java
+5
-3
FlowInstanceController.java
...x/service/workflow/controller/FlowInstanceController.java
+21
-2
FlowTaskController.java
...datax/service/workflow/controller/FlowTaskController.java
+11
-5
FlowDefinitionService.java
...datax/service/workflow/service/FlowDefinitionService.java
+2
-1
FlowInstanceService.java
...n/datax/service/workflow/service/FlowInstanceService.java
+19
-2
FlowTaskService.java
...va/cn/datax/service/workflow/service/FlowTaskService.java
+8
-3
FlowDefinitionServiceImpl.java
...vice/workflow/service/impl/FlowDefinitionServiceImpl.java
+31
-14
FlowInstanceServiceImpl.java
...ervice/workflow/service/impl/FlowInstanceServiceImpl.java
+25
-7
FlowTaskServiceImpl.java
...ax/service/workflow/service/impl/FlowTaskServiceImpl.java
+30
-18
BeanCopyUtil.java
...in/java/cn/datax/service/workflow/utils/BeanCopyUtil.java
+55
-0
BeanCopyUtilCallBack.java
...rvice/workflow/utils/functional/BeanCopyUtilCallBack.java
+17
-0
instance.js
datax-ui/src/api/workflow/instance.js
+9
-0
DefinitionList.vue
datax-ui/src/views/workflow/definition/DefinitionList.vue
+20
-11
InstanceList.vue
datax-ui/src/views/workflow/instance/InstanceList.vue
+36
-2
No files found.
datax-modules/workflow-service-parent/workflow-service-api/src/main/java/cn/datax/service/workflow/api/enums/VariablesEnum.java
View file @
91ca57bb
...
...
@@ -5,8 +5,23 @@ package cn.datax.service.workflow.api.enums;
*/
public
enum
VariablesEnum
{
/** 用户编号 */
userId
,
/** 开始 */
start
,
/** 提交节点 */
submitNode
,
/** 初审节点 */
initialAuditNode
,
/** 终审节点 */
finalAuditNode
,
/** 通过结束节点 */
approveEnd
,
/** 不通过结束节点 */
rejectEnd
,
/** 活动主题*/
businessName
,
...
...
@@ -15,8 +30,5 @@ public enum VariablesEnum {
businessType
,
/** 主键id*/
businessKey
,
/** 审批状态*/
auditStatus
;
businessKey
;
}
datax-modules/workflow-service-parent/workflow-service-api/src/main/java/cn/datax/service/workflow/api/vo/FlowDefinitionVo.java
View file @
91ca57bb
...
...
@@ -12,10 +12,11 @@ public class FlowDefinitionVo implements Serializable {
private
String
id
;
private
String
Key
;
private
String
name
;
private
int
version
;
private
String
description
;
private
Integer
version
;
private
String
category
;
private
String
deploymentId
;
private
String
resourceName
;
private
String
diagramResourceName
;
private
int
suspensionState
;
private
Integer
suspensionState
;
}
datax-modules/workflow-service-parent/workflow-service-api/src/main/java/cn/datax/service/workflow/api/vo/FlowHistTaskVo.java
0 → 100644
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
api
.
vo
;
import
cn.datax.service.workflow.api.enums.VariablesEnum
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.util.Date
;
import
java.util.Map
;
@Data
public
class
FlowHistTaskVo
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
private
String
id
;
private
Integer
revision
;
private
String
executionId
;
private
String
processInstanceId
;
private
String
processDefinitionId
;
private
String
taskDefinitionId
;
private
String
scopeId
;
private
String
subScopeId
;
private
String
scopeType
;
private
String
scopeDefinitionId
;
private
Date
createTime
;
private
Date
endTime
;
private
String
durationInMillis
;
private
String
deleteReason
;
private
String
name
;
private
String
parentTaskId
;
private
String
description
;
private
String
owner
;
private
String
assignee
;
private
String
taskDefinitionKey
;
private
String
formKey
;
private
Integer
priority
;
private
String
dueDate
;
private
Date
claimTime
;
private
String
category
;
private
String
tenantId
;
private
Date
lastUpdateTime
;
private
String
queryVariables
;
private
Date
time
;
private
Date
startTime
;
private
String
workTimeInMillis
;
private
Boolean
inserted
;
private
String
idPrefix
;
private
Boolean
updated
;
private
Boolean
deleted
;
private
Integer
revisionNext
;
/**
* 业务相关
*/
private
String
businessKey
;
private
String
businessType
;
private
String
businessName
;
private
Map
<
String
,
Object
>
variables
;
public
void
setVariables
(
Map
<
String
,
Object
>
variables
)
{
this
.
variables
=
variables
;
if
(
null
!=
variables
){
//放入业务常量
this
.
businessKey
=
(
String
)
variables
.
get
(
VariablesEnum
.
businessKey
.
toString
());
this
.
businessType
=
(
String
)
variables
.
get
(
VariablesEnum
.
businessType
.
toString
());
this
.
businessName
=
(
String
)
variables
.
get
(
VariablesEnum
.
businessName
.
toString
());
}
}
}
datax-modules/workflow-service-parent/workflow-service-api/src/main/java/cn/datax/service/workflow/api/vo/FlowInstanceVo.java
View file @
91ca57bb
...
...
@@ -3,9 +3,61 @@ package cn.datax.service.workflow.api.vo;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.util.Date
;
import
java.util.Map
;
@Data
public
class
FlowInstanceVo
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
private
String
id
;
private
String
processDefinitionKey
;
private
String
processDefinitionId
;
private
String
businessKey
;
private
String
processDefinitionName
;
private
Date
startTime
;
private
String
deploymentId
;
private
String
description
;
private
String
name
;
private
Integer
processDefinitionVersion
;
private
Map
<
String
,
Object
>
processVariables
;
private
String
startUserId
;
private
String
callbackId
;
private
String
callbackType
;
private
String
tenantId
;
private
String
localizedDescription
;
private
String
localizedName
;
private
String
processInstanceId
;
private
String
activityId
;
private
String
parentId
;
private
String
rootProcessInstanceId
;
private
String
superExecutionId
;
private
Integer
suspensionState
;
private
Boolean
isSuspended
;
private
Boolean
isEnded
;
}
datax-modules/workflow-service-parent/workflow-service-api/src/main/java/cn/datax/service/workflow/api/vo/FlowTaskVo.java
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
api
.
vo
;
import
cn.datax.service.workflow.api.enums.VariablesEnum
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.util.Date
;
import
java.util.Map
;
@Data
public
class
FlowTaskVo
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
private
String
id
;
private
String
owner
;
private
Integer
assigneeUpdatedCount
;
private
String
originalAssignee
;
private
String
assignee
;
private
String
parentTaskId
;
private
String
name
;
private
String
localizedName
;
private
String
description
;
private
String
localizedDescription
;
private
Integer
priority
;
private
Date
createTime
;
private
Date
dueDate
;
private
Integer
suspensionState
;
private
String
category
;
private
Boolean
isIdentityLinksInitialized
;
private
String
executionId
;
private
String
processInstanceId
;
private
String
processDefinitionId
;
private
String
taskDefinitionId
;
private
String
scopeId
;
private
String
subScopeId
;
private
String
scopeType
;
private
String
scopeDefinitionId
;
private
String
taskDefinitionKey
;
private
String
formKey
;
private
Boolean
isCanceled
;
private
Boolean
isCountEnabled
;
private
Integer
variableCount
;
private
Integer
identityLinkCount
;
private
Integer
subTaskCount
;
private
Date
claimTime
;
private
String
tenantId
;
private
String
eventName
;
private
String
eventHandlerId
;
private
String
idPrefix
;
private
Boolean
forcedUpdate
;
private
Boolean
isInserted
;
private
Boolean
isUpdated
;
private
Boolean
isDeleted
;
/**
* 业务相关
*/
private
String
businessKey
;
private
String
businessType
;
private
String
businessName
;
private
Map
<
String
,
Object
>
variables
;
public
void
setVariables
(
Map
<
String
,
Object
>
variables
)
{
this
.
variables
=
variables
;
if
(
null
!=
variables
){
//放入业务常量
this
.
businessKey
=
(
String
)
variables
.
get
(
VariablesEnum
.
businessKey
.
toString
());
this
.
businessType
=
(
String
)
variables
.
get
(
VariablesEnum
.
businessType
.
toString
());
this
.
businessName
=
(
String
)
variables
.
get
(
VariablesEnum
.
businessName
.
toString
());
}
}
}
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/controller/FlowDefinitionController.java
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
controller
;
import
cn.datax.common.base.BaseController
;
import
cn.datax.common.core.JsonPage
;
import
cn.datax.common.core.R
;
import
cn.datax.service.workflow.api.query.FlowDefinitionQuery
;
import
cn.datax.service.workflow.api.vo.FlowDefinitionVo
;
import
cn.datax.service.workflow.service.FlowDefinitionService
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParams
;
import
io.swagger.annotations.ApiOperation
;
import
org.flowable.engine.repository.ProcessDefinition
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
...
...
@@ -34,8 +35,9 @@ public class FlowDefinitionController extends BaseController {
})
@GetMapping
(
"/page"
)
public
R
page
(
FlowDefinitionQuery
flowDefinitionQuery
)
{
Page
<
ProcessDefinition
>
page
=
flowDefinitionService
.
page
(
flowDefinitionQuery
);
return
R
.
ok
().
setData
(
page
);
Page
<
FlowDefinitionVo
>
page
=
flowDefinitionService
.
page
(
flowDefinitionQuery
);
JsonPage
<
FlowDefinitionVo
>
jsonPage
=
new
JsonPage
<>(
page
.
getCurrent
(),
page
.
getSize
(),
page
.
getTotal
(),
page
.
getRecords
());
return
R
.
ok
().
setData
(
jsonPage
);
}
@PostMapping
(
"/import/file"
)
...
...
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/controller/FlowInstanceController.java
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
controller
;
import
cn.datax.common.base.BaseController
;
import
cn.datax.common.core.JsonPage
;
import
cn.datax.common.core.R
;
import
cn.datax.service.workflow.api.dto.ProcessInstanceCreateRequest
;
import
cn.datax.service.workflow.api.query.FlowInstanceQuery
;
import
cn.datax.service.workflow.api.vo.FlowInstanceVo
;
import
cn.datax.service.workflow.service.FlowInstanceService
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParams
;
...
...
@@ -12,6 +15,9 @@ import io.swagger.annotations.ApiOperation;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.InputStream
;
@Api
(
tags
=
{
"流程实例"
})
@RestController
@RequestMapping
(
"/instances"
)
...
...
@@ -34,8 +40,9 @@ public class FlowInstanceController extends BaseController {
})
@GetMapping
(
"/page"
)
public
R
page
(
FlowInstanceQuery
flowInstanceQuery
)
{
flowInstanceService
.
page
(
flowInstanceQuery
);
return
R
.
ok
();
Page
<
FlowInstanceVo
>
page
=
flowInstanceService
.
page
(
flowInstanceQuery
);
JsonPage
<
FlowInstanceVo
>
jsonPage
=
new
JsonPage
<>(
page
.
getCurrent
(),
page
.
getSize
(),
page
.
getTotal
(),
page
.
getRecords
());
return
R
.
ok
().
setData
(
jsonPage
);
}
@ApiOperation
(
value
=
"激活流程实例"
,
notes
=
"根据url的id来指定激活流程实例"
)
...
...
@@ -61,4 +68,16 @@ public class FlowInstanceController extends BaseController {
flowInstanceService
.
deleteProcessInstance
(
processInstanceId
,
null
);
return
R
.
ok
();
}
@ApiOperation
(
value
=
"流程追踪"
)
@ApiImplicitParam
(
name
=
"processInstanceId"
,
value
=
"流程实例ID"
,
required
=
true
,
dataType
=
"String"
,
paramType
=
"path"
)
@GetMapping
(
"/track"
)
public
void
track
(
String
processInstanceId
,
HttpServletResponse
response
)
throws
Exception
{
InputStream
resourceAsStream
=
flowInstanceService
.
createImage
(
processInstanceId
);
byte
[]
b
=
new
byte
[
1024
];
int
len
=
-
1
;
while
((
len
=
resourceAsStream
.
read
(
b
,
0
,
1024
))
!=
-
1
)
{
response
.
getOutputStream
().
write
(
b
,
0
,
len
);
}
}
}
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/controller/FlowTaskController.java
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
controller
;
import
cn.datax.common.base.BaseController
;
import
cn.datax.common.core.JsonPage
;
import
cn.datax.common.core.R
;
import
cn.datax.service.workflow.api.query.FlowTaskQuery
;
import
cn.datax.service.workflow.api.vo.FlowHistTaskVo
;
import
cn.datax.service.workflow.api.vo.FlowTaskVo
;
import
cn.datax.service.workflow.service.FlowTaskService
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParams
;
...
...
@@ -21,14 +25,15 @@ public class FlowTaskController extends BaseController {
@Autowired
private
FlowTaskService
flowTaskService
;
@ApiOperation
(
value
=
"分页查询
代
办任务"
)
@ApiOperation
(
value
=
"分页查询
待
办任务"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
"flowTaskQuery"
,
value
=
"查询实体flowTaskQuery"
,
required
=
true
,
dataTypeClass
=
FlowTaskQuery
.
class
)
})
@GetMapping
(
"/pageTodo"
)
public
R
pageTodo
(
FlowTaskQuery
flowTaskQuery
)
{
flowTaskService
.
pageTodo
(
flowTaskQuery
);
return
R
.
ok
();
Page
<
FlowTaskVo
>
page
=
flowTaskService
.
pageTodo
(
flowTaskQuery
);
JsonPage
<
FlowTaskVo
>
jsonPage
=
new
JsonPage
<>(
page
.
getCurrent
(),
page
.
getSize
(),
page
.
getTotal
(),
page
.
getRecords
());
return
R
.
ok
().
setData
(
jsonPage
);
}
@ApiOperation
(
value
=
"分页查询已办任务"
)
...
...
@@ -37,7 +42,8 @@ public class FlowTaskController extends BaseController {
})
@GetMapping
(
"/pageDone"
)
public
R
pageDone
(
FlowTaskQuery
flowTaskQuery
)
{
flowTaskService
.
pageDone
(
flowTaskQuery
);
return
R
.
ok
();
Page
<
FlowHistTaskVo
>
page
=
flowTaskService
.
pageDone
(
flowTaskQuery
);
JsonPage
<
FlowHistTaskVo
>
jsonPage
=
new
JsonPage
<>(
page
.
getCurrent
(),
page
.
getSize
(),
page
.
getTotal
(),
page
.
getRecords
());
return
R
.
ok
().
setData
(
jsonPage
);
}
}
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/service/FlowDefinitionService.java
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
service
;
import
cn.datax.service.workflow.api.query.FlowDefinitionQuery
;
import
cn.datax.service.workflow.api.vo.FlowDefinitionVo
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
org.flowable.engine.repository.ProcessDefinition
;
...
...
@@ -14,7 +15,7 @@ public interface FlowDefinitionService {
* @param flowDefinitionQuery
* @return
*/
Page
<
ProcessDefinition
>
page
(
FlowDefinitionQuery
flowDefinitionQuery
);
Page
<
FlowDefinitionVo
>
page
(
FlowDefinitionQuery
flowDefinitionQuery
);
/**
* 部署流程资源
...
...
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/service/FlowInstanceService.java
View file @
91ca57bb
...
...
@@ -2,6 +2,8 @@ package cn.datax.service.workflow.service;
import
cn.datax.service.workflow.api.dto.ProcessInstanceCreateRequest
;
import
cn.datax.service.workflow.api.query.FlowInstanceQuery
;
import
cn.datax.service.workflow.api.vo.FlowInstanceVo
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
java.io.InputStream
;
...
...
@@ -10,8 +12,9 @@ public interface FlowInstanceService {
/**
* 分页查询流程实例
* @param flowInstanceQuery
* @return
*/
void
page
(
FlowInstanceQuery
flowInstanceQuery
);
Page
<
FlowInstanceVo
>
page
(
FlowInstanceQuery
flowInstanceQuery
);
/**
* 激活流程实例
...
...
@@ -48,5 +51,19 @@ public interface FlowInstanceService {
* 终止流程
* @param processInstanceId
*/
void
stopProcessInstanceById
(
String
processInstanceId
)
;
void
stopProcessInstanceById
(
String
processInstanceId
);
/**
* 本人发起的流程实例
* @param flowInstanceQuery
* @return
*/
void
pageMyStartedProcessInstance
(
FlowInstanceQuery
flowInstanceQuery
);
/**
* 本人参与的流程实例
* @param flowInstanceQuery
* @return
*/
void
pageMyInvolvedProcessInstance
(
FlowInstanceQuery
flowInstanceQuery
);
}
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/service/FlowTaskService.java
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
service
;
import
cn.datax.service.workflow.api.query.FlowTaskQuery
;
import
cn.datax.service.workflow.api.vo.FlowHistTaskVo
;
import
cn.datax.service.workflow.api.vo.FlowTaskVo
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
public
interface
FlowTaskService
{
/**
* 分页查询
代
办任务
* 分页查询
待
办任务
* @param flowTaskQuery
* @return
*/
void
pageTodo
(
FlowTaskQuery
flowTaskQuery
);
Page
<
FlowTaskVo
>
pageTodo
(
FlowTaskQuery
flowTaskQuery
);
/**
* 分页查询已办任务
* @param flowTaskQuery
* @return
*/
void
pageDone
(
FlowTaskQuery
flowTaskQuery
);
Page
<
FlowHistTaskVo
>
pageDone
(
FlowTaskQuery
flowTaskQuery
);
}
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/service/impl/FlowDefinitionServiceImpl.java
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
service
.
impl
;
import
cn.datax.service.workflow.api.query.FlowDefinitionQuery
;
import
cn.datax.service.workflow.api.vo.FlowDefinitionVo
;
import
cn.datax.service.workflow.service.FlowDefinitionService
;
import
cn.datax.service.workflow.utils.BeanCopyUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
lombok.extern.slf4j.Slf4j
;
import
org.flowable.engine.RepositoryService
;
import
org.flowable.engine.repository.Deployment
;
import
org.flowable.engine.repository.DeploymentBuilder
;
import
org.flowable.engine.repository.ProcessDefinition
;
import
org.flowable.engine.repository.ProcessDefinitionQuery
;
import
org.flowable.engine.repository.*
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
...
...
@@ -29,22 +28,40 @@ public class FlowDefinitionServiceImpl implements FlowDefinitionService {
public
static
final
String
RESOURCE_TYPE_XML
=
"xml"
;
@Override
public
Page
<
ProcessDefinition
>
page
(
FlowDefinitionQuery
flowDefinitionQuery
)
{
ProcessDefinitionQuery
processDefinitionQuery
=
repositoryService
.
createProcessDefinitionQuery
();
public
Page
<
FlowDefinitionVo
>
page
(
FlowDefinitionQuery
flowDefinitionQuery
)
{
NativeProcessDefinitionQuery
nativeProcessDefinitionQuery
=
repositoryService
.
createNativeProcessDefinitionQuery
();
String
sqlCount
=
"SELECT COUNT(RES.ID_) FROM ACT_RE_PROCDEF RES "
+
"LEFT JOIN ACT_RE_DEPLOYMENT RED ON RES.DEPLOYMENT_ID_ = RED.ID_ "
+
"WHERE 1=1 "
;
String
sqlList
=
"SELECT RES.* FROM ACT_RE_PROCDEF RES "
+
"LEFT JOIN ACT_RE_DEPLOYMENT RED ON RES.DEPLOYMENT_ID_ = RED.ID_ "
+
"WHERE 1=1 "
;
if
(
StrUtil
.
isNotBlank
(
flowDefinitionQuery
.
getName
()))
{
processDefinitionQuery
.
processDefinitionNameLike
(
flowDefinitionQuery
.
getName
());
sqlCount
+=
"AND RES.NAME_ like #{name} "
;
sqlList
+=
"AND RES.NAME_ like #{name} "
;
}
if
(
StrUtil
.
isNotBlank
(
flowDefinitionQuery
.
getKey
())){
processDefinitionQuery
.
processDefinitionKeyLike
(
flowDefinitionQuery
.
getKey
());
sqlCount
+=
"AND RES.KEY_ like #{key} "
;
sqlList
+=
"AND RES.KEY_ like #{key} "
;
}
if
(
StrUtil
.
isNotBlank
(
flowDefinitionQuery
.
getCategoryId
())){
processDefinitionQuery
.
processDefinitionCategory
(
flowDefinitionQuery
.
getCategoryId
());
sqlCount
+=
"AND RED.CATEGORY_ = #{category} "
;
sqlList
+=
"AND RED.CATEGORY_ = #{category} "
;
}
long
count
=
processDefinitionQuery
.
count
();
List
<
ProcessDefinition
>
processDefinitionList
=
processDefinitionQuery
.
listPage
((
flowDefinitionQuery
.
getPageNum
()
-
1
)
*
flowDefinitionQuery
.
getPageSize
(),
flowDefinitionQuery
.
getPageSize
());
ProcessDefinition
processDefinition
=
processDefinitionList
.
get
(
0
);
Page
<
ProcessDefinition
>
page
=
new
Page
<>(
flowDefinitionQuery
.
getPageNum
(),
flowDefinitionQuery
.
getPageSize
());
page
.
setRecords
(
processDefinitionList
);
sqlList
+=
"ORDER BY RES.ID_ ASC "
;
long
count
=
nativeProcessDefinitionQuery
.
sql
(
sqlCount
)
.
parameter
(
"name"
,
flowDefinitionQuery
.
getName
())
.
parameter
(
"key"
,
flowDefinitionQuery
.
getKey
())
.
parameter
(
"category"
,
flowDefinitionQuery
.
getCategoryId
())
.
count
();
List
<
ProcessDefinition
>
processDefinitionList
=
nativeProcessDefinitionQuery
.
sql
(
sqlList
)
.
parameter
(
"name"
,
flowDefinitionQuery
.
getName
())
.
parameter
(
"key"
,
flowDefinitionQuery
.
getKey
())
.
parameter
(
"category"
,
flowDefinitionQuery
.
getCategoryId
())
.
listPage
((
flowDefinitionQuery
.
getPageNum
()
-
1
)
*
flowDefinitionQuery
.
getPageSize
(),
flowDefinitionQuery
.
getPageSize
());
List
<
FlowDefinitionVo
>
flowDefinitionVoList
=
BeanCopyUtil
.
copyListProperties
(
processDefinitionList
,
FlowDefinitionVo:
:
new
);
Page
<
FlowDefinitionVo
>
page
=
new
Page
<>(
flowDefinitionQuery
.
getPageNum
(),
flowDefinitionQuery
.
getPageSize
());
page
.
setRecords
(
flowDefinitionVoList
);
page
.
setTotal
(
count
);
return
page
;
}
...
...
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/service/impl/FlowInstanceServiceImpl.java
View file @
91ca57bb
...
...
@@ -3,7 +3,9 @@ package cn.datax.service.workflow.service.impl;
import
cn.datax.common.utils.SecurityUtil
;
import
cn.datax.service.workflow.api.dto.ProcessInstanceCreateRequest
;
import
cn.datax.service.workflow.api.query.FlowInstanceQuery
;
import
cn.datax.service.workflow.api.vo.FlowInstanceVo
;
import
cn.datax.service.workflow.service.FlowInstanceService
;
import
cn.datax.service.workflow.utils.BeanCopyUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
lombok.extern.slf4j.Slf4j
;
...
...
@@ -15,6 +17,7 @@ import org.flowable.engine.RepositoryService;
import
org.flowable.engine.RuntimeService
;
import
org.flowable.engine.history.HistoricActivityInstance
;
import
org.flowable.engine.history.HistoricProcessInstance
;
import
org.flowable.engine.history.HistoricProcessInstanceQuery
;
import
org.flowable.engine.runtime.ProcessInstance
;
import
org.flowable.engine.runtime.ProcessInstanceBuilder
;
import
org.flowable.engine.runtime.ProcessInstanceQuery
;
...
...
@@ -44,16 +47,18 @@ public class FlowInstanceServiceImpl implements FlowInstanceService {
private
static
final
String
FONT_NAME
=
"宋体"
;
@Override
public
void
page
(
FlowInstanceQuery
flowInstanceQuery
)
{
public
Page
<
FlowInstanceVo
>
page
(
FlowInstanceQuery
flowInstanceQuery
)
{
ProcessInstanceQuery
processInstanceQuery
=
runtimeService
.
createProcessInstanceQuery
();
if
(
StrUtil
.
isNotBlank
(
flowInstanceQuery
.
getName
())){
processInstanceQuery
.
processInstanceNameLike
(
flowInstanceQuery
.
getName
());
}
long
count
=
processInstanceQuery
.
count
();
List
<
ProcessInstance
>
processInstanceList
=
processInstanceQuery
.
orderByStartTime
().
desc
().
listPage
((
flowInstanceQuery
.
getPageNum
()
-
1
)
*
flowInstanceQuery
.
getPageSize
(),
flowInstanceQuery
.
getPageSize
());
Page
<
ProcessInstance
>
page
=
new
Page
<>(
flowInstanceQuery
.
getPageNum
(),
flowInstanceQuery
.
getPageSize
());
page
.
setRecords
(
processInstanceList
);
List
<
FlowInstanceVo
>
flowInstanceVoList
=
BeanCopyUtil
.
copyListProperties
(
processInstanceList
,
FlowInstanceVo:
:
new
);
Page
<
FlowInstanceVo
>
page
=
new
Page
<>(
flowInstanceQuery
.
getPageNum
(),
flowInstanceQuery
.
getPageSize
());
page
.
setRecords
(
flowInstanceVoList
);
page
.
setTotal
(
count
);
return
page
;
}
@Override
...
...
@@ -142,8 +147,21 @@ public class FlowInstanceServiceImpl implements FlowInstanceService {
}
}
// // 本人参与的流程实例
// historyService.createHistoricProcessInstanceQuery().involvedUser(SecurityUtil.getUserId()).orderByProcessInstanceStartTime().desc().list();
// // 本人发起的流程实例
// historyService.createHistoricProcessInstanceQuery().startedBy(SecurityUtil.getUserId()).orderByProcessInstanceStartTime().desc().list();
@Override
public
void
pageMyStartedProcessInstance
(
FlowInstanceQuery
flowInstanceQuery
)
{
HistoricProcessInstanceQuery
historicProcessInstanceQuery
=
historyService
.
createHistoricProcessInstanceQuery
();
historicProcessInstanceQuery
.
startedBy
(
SecurityUtil
.
getUserId
());
long
count
=
historicProcessInstanceQuery
.
count
();
List
<
HistoricProcessInstance
>
historicProcessInstanceList
=
historicProcessInstanceQuery
.
orderByProcessInstanceStartTime
().
desc
()
.
listPage
((
flowInstanceQuery
.
getPageNum
()
-
1
)
*
flowInstanceQuery
.
getPageSize
(),
flowInstanceQuery
.
getPageSize
());
}
@Override
public
void
pageMyInvolvedProcessInstance
(
FlowInstanceQuery
flowInstanceQuery
)
{
HistoricProcessInstanceQuery
historicProcessInstanceQuery
=
historyService
.
createHistoricProcessInstanceQuery
();
historicProcessInstanceQuery
.
involvedUser
(
SecurityUtil
.
getUserId
());
long
count
=
historicProcessInstanceQuery
.
count
();
List
<
HistoricProcessInstance
>
historicProcessInstanceList
=
historicProcessInstanceQuery
.
orderByProcessInstanceStartTime
().
desc
()
.
listPage
((
flowInstanceQuery
.
getPageNum
()
-
1
)
*
flowInstanceQuery
.
getPageSize
(),
flowInstanceQuery
.
getPageSize
());
}
}
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/service/impl/FlowTaskServiceImpl.java
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
service
.
impl
;
import
cn.datax.common.utils.SecurityUtil
;
import
cn.datax.service.workflow.api.enums.VariablesEnum
;
import
cn.datax.service.workflow.api.query.FlowTaskQuery
;
import
cn.datax.service.workflow.api.vo.FlowHistTaskVo
;
import
cn.datax.service.workflow.api.vo.FlowTaskVo
;
import
cn.datax.service.workflow.service.FlowTaskService
;
import
cn.hutool.core.bean.BeanUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
org.apache.commons.lang3.StringUtils
;
import
org.flowable.engine.HistoryService
;
import
org.flowable.engine.TaskService
;
import
org.flowable.task.api.Task
;
...
...
@@ -15,6 +18,7 @@ import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.ArrayList
;
import
java.util.List
;
@Service
...
...
@@ -27,9 +31,9 @@ public class FlowTaskServiceImpl implements FlowTaskService {
private
HistoryService
historyService
;
@Override
public
void
pageTodo
(
FlowTaskQuery
flowTaskQuery
)
{
public
Page
<
FlowTaskVo
>
pageTodo
(
FlowTaskQuery
flowTaskQuery
)
{
TaskQuery
taskQuery
=
taskService
.
createTaskQuery
();
taskQuery
.
taskCandidateOrAssigned
(
flowTaskQuery
.
getUserId
()).
taskCandidateGroupIn
(
flowTaskQuery
.
getGroup
Ids
());
taskQuery
.
taskCandidateOrAssigned
(
SecurityUtil
.
getUserId
()).
taskCandidateGroupIn
(
SecurityUtil
.
getUserRole
Ids
());
if
(
StrUtil
.
isNotBlank
(
flowTaskQuery
.
getBusinessKey
())){
taskQuery
.
processInstanceBusinessKey
(
flowTaskQuery
.
getBusinessKey
());
}
...
...
@@ -43,41 +47,49 @@ public class FlowTaskServiceImpl implements FlowTaskService {
.
orderByTaskPriority
().
desc
()
.
orderByTaskCreateTime
().
desc
()
.
listPage
((
flowTaskQuery
.
getPageNum
()
-
1
)
*
flowTaskQuery
.
getPageSize
(),
flowTaskQuery
.
getPageSize
());
List
<
FlowTaskVo
>
list
=
new
ArrayList
<>();
taskList
.
stream
().
forEach
(
task
->
{
System
.
out
.
println
(
task
);
System
.
out
.
println
(
task
.
getProcessVariables
());
System
.
out
.
println
(
"-----------------"
);
FlowTaskVo
flowTaskVo
=
new
FlowTaskVo
();
BeanUtil
.
copyProperties
(
task
,
flowTaskVo
,
"variables"
);
//放入流程参数
flowTaskVo
.
setVariables
(
task
.
getProcessVariables
());
list
.
add
(
flowTaskVo
);
});
long
count
=
taskQuery
.
count
();
Page
<
Task
>
page
=
new
Page
<>(
flowTaskQuery
.
getPageNum
(),
flowTaskQuery
.
getPageSize
());
page
.
setRecords
(
taskL
ist
);
Page
<
FlowTaskVo
>
page
=
new
Page
<>(
flowTaskQuery
.
getPageNum
(),
flowTaskQuery
.
getPageSize
());
page
.
setRecords
(
l
ist
);
page
.
setTotal
(
count
);
return
page
;
}
@Override
public
void
pageDone
(
FlowTaskQuery
flowTaskQuery
)
{
public
Page
<
FlowHistTaskVo
>
pageDone
(
FlowTaskQuery
flowTaskQuery
)
{
HistoricTaskInstanceQuery
historicTaskInstanceQuery
=
historyService
.
createHistoricTaskInstanceQuery
();
historicTaskInstanceQuery
.
taskAssignee
(
flowTaskQuery
.
getUserId
());
if
(
Str
ingUtils
.
isNotBlank
(
flowTaskQuery
.
getBusinessKey
()))
{
historicTaskInstanceQuery
.
taskAssignee
(
SecurityUtil
.
getUserId
());
if
(
Str
Util
.
isNotBlank
(
flowTaskQuery
.
getBusinessKey
()))
{
historicTaskInstanceQuery
.
processInstanceBusinessKey
(
flowTaskQuery
.
getBusinessKey
());
}
if
(
Str
ingUtils
.
isNotBlank
(
flowTaskQuery
.
getBusinessName
()))
{
if
(
Str
Util
.
isNotBlank
(
flowTaskQuery
.
getBusinessName
()))
{
historicTaskInstanceQuery
.
processVariableValueEquals
(
VariablesEnum
.
businessType
.
toString
(),
flowTaskQuery
.
getBusinessName
());
}
if
(
Str
ingUtils
.
isNotBlank
(
flowTaskQuery
.
getBusinessType
()))
{
if
(
Str
Util
.
isNotBlank
(
flowTaskQuery
.
getBusinessType
()))
{
historicTaskInstanceQuery
.
processVariableValueLike
(
VariablesEnum
.
businessName
.
toString
(),
flowTaskQuery
.
getBusinessType
());
}
List
<
HistoricTaskInstance
>
historicTaskInstanceList
=
historicTaskInstanceQuery
.
finished
()
.
includeProcessVariables
().
orderByHistoricTaskInstanceEndTime
().
desc
()
.
listPage
((
flowTaskQuery
.
getPageNum
()
-
1
)
*
flowTaskQuery
.
getPageSize
(),
flowTaskQuery
.
getPageSize
());
List
<
FlowHistTaskVo
>
list
=
new
ArrayList
<>();
historicTaskInstanceList
.
stream
().
forEach
(
task
->
{
System
.
out
.
println
(
task
);
System
.
out
.
println
(
task
.
getProcessVariables
());
System
.
out
.
println
(
"-----------------"
);
FlowHistTaskVo
flowHistTaskVo
=
new
FlowHistTaskVo
();
BeanUtil
.
copyProperties
(
task
,
flowHistTaskVo
,
"variables"
);
//放入流程参数
flowHistTaskVo
.
setVariables
(
task
.
getProcessVariables
());
list
.
add
(
flowHistTaskVo
);
});
long
count
=
historicTaskInstanceQuery
.
count
();
Page
<
HistoricTaskInstance
>
page
=
new
Page
<>(
flowTaskQuery
.
getPageNum
(),
flowTaskQuery
.
getPageSize
());
page
.
setRecords
(
historicTaskInstanceL
ist
);
Page
<
FlowHistTaskVo
>
page
=
new
Page
<>(
flowTaskQuery
.
getPageNum
(),
flowTaskQuery
.
getPageSize
());
page
.
setRecords
(
l
ist
);
page
.
setTotal
(
count
);
return
page
;
}
}
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/utils/BeanCopyUtil.java
0 → 100644
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
utils
;
import
cn.datax.service.workflow.utils.functional.BeanCopyUtilCallBack
;
import
cn.hutool.core.bean.BeanUtil
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.function.Supplier
;
/**
* BeanUtil 扩展
*/
public
class
BeanCopyUtil
extends
BeanUtil
{
/**
* 集合数据的拷贝
* @param sources: 数据源类
* @param target: 目标类::new(eg: UserVO::new)
* @return
*/
public
static
<
S
,
T
>
List
<
T
>
copyListProperties
(
List
<
S
>
sources
,
Supplier
<
T
>
target
)
{
return
copyListProperties
(
sources
,
target
,
null
,
null
);
}
/**
* 集合数据的拷贝
* @param sources: 数据源类
* @param target: 目标类::new(eg: UserVO::new)
* @param ignoreProperties 忽略属性
* @return
*/
public
static
<
S
,
T
>
List
<
T
>
copyListProperties
(
List
<
S
>
sources
,
Supplier
<
T
>
target
,
String
...
ignoreProperties
)
{
return
copyListProperties
(
sources
,
target
,
null
,
ignoreProperties
);
}
/**
* 带回调函数的集合数据的拷贝(可自定义字段拷贝规则)
* @param sources: 数据源类
* @param target: 目标类::new(eg: UserVO::new)
* @param callBack: 回调函数 属性字段要借助回调函数拷贝
* @param ignoreProperties 忽略属性
* @return
*/
public
static
<
S
,
T
>
List
<
T
>
copyListProperties
(
List
<
S
>
sources
,
Supplier
<
T
>
target
,
BeanCopyUtilCallBack
<
S
,
T
>
callBack
,
String
...
ignoreProperties
)
{
List
<
T
>
list
=
new
ArrayList
<>(
sources
.
size
());
for
(
S
source
:
sources
)
{
T
t
=
target
.
get
();
copyProperties
(
source
,
t
,
ignoreProperties
);
list
.
add
(
t
);
if
(
callBack
!=
null
)
{
// 回调
callBack
.
callBack
(
source
,
t
);
}
}
return
list
;
}
}
datax-modules/workflow-service-parent/workflow-service/src/main/java/cn/datax/service/workflow/utils/functional/BeanCopyUtilCallBack.java
0 → 100644
View file @
91ca57bb
package
cn
.
datax
.
service
.
workflow
.
utils
.
functional
;
/**
* 拷贝函数
* @param <S>
* @param <T>
*/
@FunctionalInterface
public
interface
BeanCopyUtilCallBack
<
S
,
T
>
{
/**
* 定义默认回调方法
* @param t
* @param s
*/
void
callBack
(
S
t
,
T
s
);
}
datax-ui/src/api/workflow/instance.js
View file @
91ca57bb
...
...
@@ -28,3 +28,12 @@ export function suspendInstance(processInstanceId) {
method
:
'put'
})
}
export
function
flowTrack
(
processInstanceId
)
{
return
request
({
url
:
'/workflow/instances/track'
,
method
:
'get'
,
responseType
:
'blob'
,
params
:
{
processInstanceId
:
processInstanceId
}
})
}
datax-ui/src/views/workflow/definition/DefinitionList.vue
View file @
91ca57bb
...
...
@@ -145,12 +145,14 @@
@
click=
"handleResource(scope.row)"
>
流程图
</el-button>
<el-button
v-if=
"scope.row.suspensionState === 2"
size=
"mini"
type=
"text"
icon=
"el-icon-view"
@
click=
"handleActivate(scope.row)"
>
激活
</el-button>
<el-button
v-if=
"scope.row.suspensionState === 1"
size=
"mini"
type=
"text"
icon=
"el-icon-view"
...
...
@@ -208,7 +210,7 @@
</div>
</el-dialog>
<!-- 流程图对话框 -->
<el-dialog
:title=
"dialog.title"
:visible
.
sync=
"dialog.resource"
width=
"
4
00px"
append-to-body
>
<el-dialog
:title=
"dialog.title"
:visible
.
sync=
"dialog.resource"
width=
"
6
00px"
append-to-body
>
<el-image
:src=
"flowSrc"
>
<div
slot=
"error"
class=
"image-slot"
>
<i
class=
"el-icon-picture-outline"
></i>
...
...
@@ -244,16 +246,15 @@ export default {
multiple
:
true
,
// 表格头
tableColumns
:
[
{
prop
:
'gbTypeCode'
,
label
:
'标准类别编码'
,
show
:
true
},
{
prop
:
'gbTypeName'
,
label
:
'标准类别名称'
,
show
:
true
},
{
prop
:
'gbCode'
,
label
:
'标准编码'
,
show
:
true
},
{
prop
:
'gbName'
,
label
:
'标准名称'
,
show
:
true
},
{
prop
:
'id'
,
label
:
'流程定义ID'
,
show
:
true
},
{
prop
:
'description'
,
label
:
'流程名称'
,
show
:
true
},
{
prop
:
'version'
,
label
:
'版本'
,
show
:
true
},
{
prop
:
's
tatus
'
,
prop
:
's
uspensionState
'
,
label
:
'状态'
,
show
:
true
},
{
prop
:
'createTime'
,
label
:
'创建时间'
,
show
:
true
}
show
:
true
,
formatter
:
this
.
statusFormatter
}
],
// 默认选择中表格头
checkedTableColumns
:
[],
...
...
@@ -293,7 +294,7 @@ export default {
dialogDefinitionForm
:
{},
dialogDefinitionRules
:
{
name
:
[
{
required
:
true
,
message
:
'
分类
名称不能为空'
,
trigger
:
'blur'
}
{
required
:
true
,
message
:
'
模板
名称不能为空'
,
trigger
:
'blur'
}
]
},
flowSrc
:
''
...
...
@@ -420,7 +421,7 @@ export default {
if
(
response
.
success
)
{
this
.
$message
.
success
(
'部署成功'
)
this
.
dialog
.
definition
=
false
this
.
get
Tree
()
this
.
get
List
()
}
else
{
this
.
$message
.
error
(
'部署失败'
)
}
...
...
@@ -485,6 +486,7 @@ export default {
flowResource
(
row
.
id
).
then
(
response
=>
{
const
blob
=
new
Blob
([
response
])
this
.
flowSrc
=
window
.
URL
.
createObjectURL
(
blob
)
this
.
dialog
.
title
=
'流程部署资源'
this
.
dialog
.
resource
=
true
})
},
...
...
@@ -543,6 +545,13 @@ export default {
console
.
log
(
`当前页:
${
val
}
`
)
this
.
queryParams
.
pageNum
=
val
this
.
getList
()
},
statusFormatter
(
row
,
column
,
cellValue
,
index
)
{
if
(
cellValue
===
1
)
{
return
<
el
-
tag
type
=
'success'
>
激活
<
/el-tag
>
}
else
if
(
cellValue
===
2
)
{
return
<
el
-
tag
type
=
'warning'
>
挂起
<
/el-tag
>
}
}
}
}
...
...
datax-ui/src/views/workflow/instance/InstanceList.vue
View file @
91ca57bb
...
...
@@ -52,9 +52,17 @@
size=
"mini"
type=
"text"
icon=
"el-icon-view"
@
click=
"handleTrack(scope.row)"
>
流程追踪
</el-button>
<el-button
v-if=
"scope.row.suspensionState === 2"
size=
"mini"
type=
"text"
icon=
"el-icon-view"
@
click=
"handleActivate(scope.row)"
>
激活
</el-button>
<el-button
v-if=
"scope.row.suspensionState === 1"
size=
"mini"
type=
"text"
icon=
"el-icon-view"
...
...
@@ -81,11 +89,22 @@
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
/>
<!-- 流程图对话框 -->
<el-dialog
:title=
"dialog.title"
:visible
.
sync=
"dialog.track"
width=
"600px"
append-to-body
>
<el-image
:src=
"flowSrc"
>
<div
slot=
"error"
class=
"image-slot"
>
<i
class=
"el-icon-picture-outline"
></i>
</div>
</el-image>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"dialog.track = false"
>
取 消
</el-button>
</div>
</el-dialog>
</el-card>
</template>
<
script
>
import
{
pageInstance
,
delInstance
,
activateInstance
,
suspendInstance
}
from
'@/api/workflow/instance'
import
{
pageInstance
,
delInstance
,
activateInstance
,
suspendInstance
,
flowTrack
}
from
'@/api/workflow/instance'
export
default
{
name
:
'InstanceList'
,
...
...
@@ -124,7 +143,14 @@ export default {
pageNum
:
1
,
pageSize
:
20
,
name
:
''
}
},
dialog
:
{
// 是否显示弹出层
track
:
false
,
// 弹出层标题
title
:
''
},
flowSrc
:
''
}
},
created
()
{
...
...
@@ -163,6 +189,14 @@ export default {
this
.
single
=
selection
.
length
!==
1
this
.
multiple
=
!
selection
.
length
},
handleTrack
(
row
)
{
flowTrack
(
row
.
id
).
then
(
response
=>
{
const
blob
=
new
Blob
([
response
])
this
.
flowSrc
=
window
.
URL
.
createObjectURL
(
blob
)
this
.
dialog
.
title
=
'流程追踪'
this
.
dialog
.
track
=
true
})
},
handleActivate
(
row
)
{
this
.
$confirm
(
'激活流程实例?'
,
'提示'
,
{
confirmButtonText
:
'确定'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment