Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
bdc
/
bdcdj-web
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
c9014f84
authored
2024-02-20 15:39:12 +0800
by
tianhaohao@pashanhoo.com
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
1111
1 parent
4f079afb
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
2 additions
and
642 deletions
src/views/djbworkflow/mixin/index.js
src/views/workflow/components/processViewer.vue
src/views/workflow/mixin/index.js
src/views/djbworkflow/mixin/index.js
View file @
c9014f8
...
...
@@ -90,7 +90,7 @@ export default {
case
"B1"
:
getWorkFlowImage
(
this
.
bsmSlsq
,
this
.
bestepid
?
this
.
bestepid
:
''
).
then
(
res
=>
{
let
{
result
}
=
res
this
.
$popupDialog
(
"流程图"
,
"workflow/
components/processViewer
"
,
{
this
.
$popupDialog
(
"流程图"
,
"workflow/
top/processViewer/index
"
,
{
xml
:
result
.
xml
,
finishedInfo
:
{
finishedTaskSet
:
result
.
finishedActivityIds
,
...
...
src/views/workflow/components/processViewer.vue
deleted
100644 → 0
View file @
4f079af
<!--
* @Description:
* @Autor: renchao
* @LastEditTime: 2023-05-17 10:41:15
-->
<
template
>
<div>
<div
class=
"process-viewer"
>
<div
v-show=
"!isLoading"
ref=
"processCanvas"
class=
"process-canvas"
style=
"height: 280px"
/>
<!-- 自定义箭头样式,用于成功状态下流程连线箭头 -->
<defs
ref=
"customSuccessDefs"
>
<marker
id=
"sequenceflow-end-white-success"
view-box=
"0 0 20 20"
ref-x=
"11"
ref-y=
"10"
marker-width=
"10"
marker-height=
"10"
orient=
"auto"
>
<path
class=
"success-arrow"
d=
"M 1 5 L 11 10 L 1 15 Z"
style=
"
stroke-width: 1px;
stroke-linecap: round;
stroke-dasharray: 10000, 1;
"
/>
</marker>
<marker
id=
"conditional-flow-marker-white-success"
view-box=
"0 0 20 20"
ref-x=
"-1"
ref-y=
"10"
marker-width=
"10"
marker-height=
"10"
orient=
"auto"
>
<path
class=
"success-conditional"
d=
"M 0 10 L 8 6 L 16 10 L 8 14 Z"
style=
"
stroke-width: 1px;
stroke-linecap: round;
stroke-dasharray: 10000, 1;
"
/>
</marker>
</defs>
<!-- 自定义箭头样式,用于失败状态下流程连线箭头 -->
<defs
ref=
"customFailDefs"
>
<marker
id=
"sequenceflow-end-white-fail"
view-box=
"0 0 20 20"
ref-x=
"11"
ref-y=
"10"
marker-width=
"10"
marker-height=
"10"
orient=
"auto"
>
<path
class=
"fail-arrow"
d=
"M 1 5 L 11 10 L 1 15 Z"
style=
"
stroke-width: 1px;
stroke-linecap: round;
stroke-dasharray: 10000, 1;
"
/>
</marker>
<marker
id=
"conditional-flow-marker-white-fail"
view-box=
"0 0 20 20"
ref-x=
"-1"
ref-y=
"10"
marker-width=
"10"
marker-height=
"10"
orient=
"auto"
>
<path
class=
"fail-conditional"
d=
"M 0 10 L 8 6 L 16 10 L 8 14 Z"
style=
"
stroke-width: 1px;
stroke-linecap: round;
stroke-dasharray: 10000, 1;
"
/>
</marker>
</defs>
<div
style=
"position: absolute; top: 0px; left: 0px; width: 100%"
>
<el-row
type=
"flex"
justify=
"end"
>
<el-button-group
key=
"scale-control"
size=
"medium"
>
<el-button
size=
"medium"
type=
"default"
:plain=
"true"
:disabled=
"defaultZoom
<
= 0.3"
icon="el-icon-zoom-out"
@click="processZoomOut()"
/>
<el-button
size=
"medium"
type=
"default"
style=
"width: 90px"
>
{{
Math
.
floor
(
this
.
defaultZoom
*
10
*
10
)
+
"%"
}}
</el-button>
<el-button
size=
"medium"
type=
"default"
:plain=
"true"
:disabled=
"defaultZoom >= 3.9"
icon=
"el-icon-zoom-in"
@
click=
"processZoomIn()"
/>
<el-button
size=
"medium"
type=
"default"
icon=
"el-icon-c-scale-to-original"
@
click=
"processReZoom()"
/>
<slot
/>
</el-button-group>
</el-row>
</div>
</div>
<!-- 已完成节点悬浮弹窗 -->
<div
class=
"information-list"
>
<el-select
v-model=
"selectValue"
@
change=
"handleSelect"
>
<el-option
v-for=
"item in selectOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
>
</el-option>
</el-select>
<div
class=
"cutline"
>
<p
class=
"cutlines"
>
图例
</p>
<div
v-for=
"item in cutlinelist"
:key=
"item.value"
class=
"concent"
:style=
"
{ backgroundColor: item.backgroundColor,borderColor:item.color }">
{{
item
.
value
}}
</div>
</div>
<el-table
height=
"190"
:data=
"taskCommentList"
size=
"mini"
border
header-cell-class-name=
"table-header-gray"
>
<el-table-column
label=
"序号"
header-align=
"center"
align=
"center"
type=
"index"
width=
"55px"
/>
<el-table-column
label=
"环节"
prop=
"name"
align=
"center"
/>
<el-table-column
label=
"转入时间"
prop=
"createTime"
:formatter=
"formatDate"
width=
"160"
align=
"center"
/>
<el-table-column
label=
"认领时间"
prop=
"claimTime"
:formatter=
"formatDate"
width=
"160"
align=
"center"
/>
<el-table-column
label=
"转出时间"
prop=
"endTime"
:formatter=
"formatDate"
width=
"160"
align=
"center"
/>
<el-table-column
label=
"经办人"
prop=
"agent"
align=
"center"
/>
<el-table-column
label=
"操作方式"
prop=
"controls"
align=
"center"
/>
<el-table-column
label=
"意见"
prop=
"idea"
align=
"center"
/>
</el-table>
</div>
</div>
</
template
>
<
script
>
import
"@/styles/package/theme/index.scss"
;
import
BpmnViewer
from
"bpmn-js/lib/Viewer"
;
import
MoveCanvasModule
from
"diagram-js/lib/navigation/movecanvas"
;
export
default
{
props
:
{
formData
:
{
type
:
Object
,
default
:
{},
},
},
data
()
{
return
{
dlgTitle
:
undefined
,
defaultZoom
:
1
,
// 是否正在加载流程图
isLoading
:
true
,
bpmnViewer
:
undefined
,
// 已完成流程元素
processNodeInfo
:
undefined
,
// 当前任务id
selectTaskId
:
undefined
,
// 任务节点审批记录
taskList
:
[],
taskCommentList
:
[],
// 已完成任务悬浮延迟Timer
hoverTimer
:
null
,
// 下拉
selectValue
:
""
,
selectOptions
:
[],
cutlinelist
:[
{
value
:
"完成节点"
,
color
:
"#4eb819"
,
backgroundColor
:
"rgba(78, 184, 25,0.2)"
},
{
value
:
"当前节点"
,
color
:
"#409EFF"
,
backgroundColor
:
"rgba(64, 158, 255,0.2)"
},
{
value
:
"挂起节点"
,
color
:
"#E6A23C"
,
backgroundColor
:
"rgba(230, 162, 60,0.2)"
},
{
value
:
"阻塞节点"
,
color
:
"#F56C6C"
,
backgroundColor
:
"rgb(245, 108, 108,0.2)"
},
{
value
:
"未激活节点"
,
color
:
"#000000"
,
backgroundColor
:
"none"
,
}
],
};
},
created
()
{
this
.
$nextTick
(()
=>
{
// 获取流程记录
this
.
getCommentList
();
this
.
setProcessStatus
(
this
.
formData
.
finishedInfo
);
this
.
importXML
(
this
.
formData
.
xml
);
});
},
destroyed
()
{
this
.
clearViewer
();
},
methods
:
{
/**
* @description: formatDate
* @param {*} row
* @param {*} column
* @author: renchao
*/
formatDate
(
row
,
column
)
{
let
data
=
row
[
column
.
property
];
if
(
data
==
null
)
{
return
null
;
}
let
dt
=
new
Date
(
data
);
return
(
dt
.
getFullYear
()
+
"-"
+
(
dt
.
getMonth
()
+
1
)
+
"-"
+
dt
.
getDate
()
+
" "
+
dt
.
getHours
()
+
":"
+
dt
.
getMinutes
()
+
":"
+
dt
.
getSeconds
()
);
},
/**
* @description: processReZoom
* @author: renchao
*/
processReZoom
()
{
this
.
defaultZoom
=
1
;
this
.
bpmnViewer
.
get
(
"canvas"
).
zoom
(
"fit-viewport"
,
"auto"
);
},
/**
* @description: processZoomIn
* @param {*} zoomStep
* @author: renchao
*/
processZoomIn
(
zoomStep
=
0.1
)
{
const
newZoom
=
Math
.
floor
(
this
.
defaultZoom
*
100
+
zoomStep
*
100
)
/
100
;
if
(
newZoom
>
4
)
{
throw
new
Error
(
"[Process Designer Warn ]: The zoom ratio cannot be greater than 4"
);
}
this
.
defaultZoom
=
newZoom
;
this
.
bpmnViewer
.
get
(
"canvas"
).
zoom
(
this
.
defaultZoom
);
},
/**
* @description: processZoomOut
* @param {*} zoomStep
* @author: renchao
*/
processZoomOut
(
zoomStep
=
0.1
)
{
const
newZoom
=
Math
.
floor
(
this
.
defaultZoom
*
100
-
zoomStep
*
100
)
/
100
;
if
(
newZoom
<
0.2
)
{
throw
new
Error
(
"[Process Designer Warn ]: The zoom ratio cannot be scss than 0.2"
);
}
this
.
defaultZoom
=
newZoom
;
this
.
bpmnViewer
.
get
(
"canvas"
).
zoom
(
this
.
defaultZoom
);
},
/**
* @description: getOperationTagType
* @param {*} type
* @author: renchao
*/
getOperationTagType
(
type
)
{
return
"success"
;
},
// 流程图预览清空
/**
* @description: 流程图预览清空
* @param {*} e
* @author: renchao
*/
clearViewer
(
a
)
{
if
(
this
.
$refs
.
processCanvas
)
{
this
.
$refs
.
processCanvas
.
innerHTML
=
""
;
}
if
(
this
.
bpmnViewer
)
{
this
.
bpmnViewer
.
destroy
();
}
this
.
bpmnViewer
=
null
;
},
// 添加自定义箭头
/**
* @description: 添加自定义箭头
* @author: renchao
*/
addCustomDefs
()
{
const
canvas
=
this
.
bpmnViewer
.
get
(
"canvas"
);
const
svg
=
canvas
.
_svg
;
const
customSuccessDefs
=
this
.
$refs
.
customSuccessDefs
;
const
customFailDefs
=
this
.
$refs
.
customFailDefs
;
svg
.
appendChild
(
customSuccessDefs
);
svg
.
appendChild
(
customFailDefs
);
},
// 任务悬浮弹窗
/**
* @description: 任务悬浮弹窗
* @param {*} element
* @author: renchao
*/
onSelectElement
(
element
)
{
this
.
selectTaskId
=
undefined
;
this
.
dlgTitle
=
undefined
;
let
allfinishedTaskSet
=
[
...
this
.
processNodeInfo
.
finishedTaskSet
,
...
this
.
processNodeInfo
.
unfinishedTaskSet
,
];
if
(
this
.
processNodeInfo
==
null
||
allfinishedTaskSet
==
null
)
return
;
if
(
element
==
null
||
allfinishedTaskSet
.
indexOf
(
element
.
id
)
===
-
1
)
{
return
;
}
this
.
selectTaskId
=
element
.
id
;
this
.
selectValue
=
element
.
id
;
this
.
dlgTitle
=
element
.
businessObject
?
element
.
businessObject
.
name
:
undefined
;
// 计算当前悬浮任务审批记录,如果记录为空不显示弹窗
this
.
taskCommentList
=
(
this
.
taskList
||
[]).
filter
((
item
)
=>
{
return
item
.
taskDefinitionKey
===
this
.
selectTaskId
;
});
if
(
this
.
taskCommentList
.
length
==
0
)
{
this
.
taskCommentList
=
this
.
taskList
;
}
},
// 下拉列表切换
/**
* @description: 下拉列表切换
* @param {*} val
* @author: renchao
*/
handleSelect
(
val
)
{
this
.
taskCommentList
=
(
this
.
taskList
||
[]).
filter
((
item
)
=>
{
return
item
.
taskDefinitionKey
===
val
;
});
if
(
this
.
taskCommentList
.
length
==
0
)
{
this
.
taskCommentList
=
this
.
taskList
;
}
},
// 显示流程图
/**
* @description: 显示流程图
* @param {*} xml
* @author: renchao
*/
async
importXML
(
xml
)
{
let
xmlData
=
this
.
$x2js
.
xml2js
(
xml
).
definitions
.
process
;
this
.
selectOptions
=
xmlData
.
userTask
.
map
((
item
)
=>
{
return
{
value
:
item
.
_id
,
label
:
item
.
_name
};
});
this
.
selectOptions
=
[
{
value
:
xmlData
.
startEvent
.
_id
,
label
:
"浏览记录"
},
...
this
.
selectOptions
,
];
this
.
selectOptions
=
this
.
selectOptions
.
map
((
item
)
=>
{
if
(
this
.
formData
.
finishedInfo
.
finishedTaskSet
.
includes
(
item
.
value
))
{
return
item
;
}
if
(
this
.
formData
.
finishedInfo
.
unfinishedTaskSet
.
includes
(
item
.
value
)
)
{
return
item
;
}
})
.
filter
(
Boolean
);
this
.
selectValue
=
xmlData
.
startEvent
.
_id
;
this
.
clearViewer
(
"a"
);
if
(
xml
!=
null
&&
xml
!==
""
)
{
try
{
this
.
bpmnViewer
=
new
BpmnViewer
({
additionalModules
:
[
// 移动整个画布
MoveCanvasModule
,
],
container
:
this
.
$refs
.
processCanvas
,
});
// 任务节点悬浮事件
this
.
bpmnViewer
.
on
(
"element.click"
,
({
element
})
=>
{
this
.
onSelectElement
(
element
);
});
await
this
.
bpmnViewer
.
importXML
(
xml
);
this
.
isLoading
=
true
;
this
.
addCustomDefs
();
}
catch
(
e
)
{
this
.
clearViewer
(
"b"
);
}
finally
{
this
.
isLoading
=
false
;
this
.
setProcessStatus
(
this
.
processNodeInfo
);
this
.
$nextTick
(()
=>
{
this
.
processReZoom
();
});
}
}
},
// 获取流程记录
/**
* @description: 获取流程记录
* @author: renchao
*/
getCommentList
()
{
this
.
formData
.
allCommentList
.
forEach
(
async
(
item
,
index
)
=>
{
// item.comments.forEach(element => {
// if(element.type=="COMPLETE"){
// this.formData.allCommentList[index].idea=element.message
// this.formData.allCommentList[index].controls="完成"
// }
// });
let
type
=
item
.
comments
[
item
.
comments
.
length
-
1
].
type
;
this
.
formData
.
allCommentList
[
index
].
idea
=
item
.
comments
[
item
.
comments
.
length
-
1
].
message
;
// 操作方式
let
controls
=
""
;
// 正在办理
// 已完结
// 已退回
switch
(
type
)
{
case
"COMPLETE"
:
controls
=
"完成"
;
break
;
case
"CLAIM"
:
controls
=
"完成"
;
break
;
case
"ASSIGN"
:
controls
=
"转办"
;
break
;
case
"DELEGATE"
:
controls
=
"委派"
;
break
;
case
"UNCLAIM"
:
controls
=
"取消认领"
;
break
;
case
"STOP"
:
controls
=
"终止"
;
break
;
case
"BACK"
:
controls
=
"退回"
;
break
;
}
this
.
formData
.
allCommentList
[
index
].
controls
=
controls
;
this
.
formData
.
allCommentList
[
index
].
agent
=
item
.
assignee
.
name
;
});
this
.
formData
.
handlinglist
.
forEach
(
async
(
item
,
index
)
=>
{
if
(
item
.
assignee
.
name
)
{
this
.
formData
.
handlinglist
[
index
].
agent
=
item
.
assignee
.
name
;
}
else
{
let
str
=
""
;
item
.
countersign
.
forEach
((
item
)
=>
{
str
+=
item
.
name
+
","
;
});
str
=
str
.
slice
(
0
,
-
1
);
this
.
formData
.
allCommentList
[
index
].
agent
=
str
;
}
});
this
.
taskList
=
[
...
this
.
formData
.
allCommentList
,
...
this
.
formData
.
handlinglist
,
];
// this.taskList =this.formData.allCommentList;
// 处理数据之后赋值
this
.
taskCommentList
=
this
.
taskList
;
this
.
taskCommentList
=
this
.
taskCommentList
.
sort
(
this
.
sortDownDate
);
},
/**
* 时间排序函数
* @description: formatDate
* @param {*} row
* @param {*} column
* @author: renchao
*/
sortDownDate
(
a
,
b
)
{
return
Date
.
parse
(
a
.
createTime
)
-
Date
.
parse
(
b
.
createTime
);
},
// 设置流程图元素状态
/**
* @description: 设置流程图元素状态
* @param {*} processNodeInfo
* @author: renchao
*/
setProcessStatus
(
processNodeInfo
)
{
this
.
processNodeInfo
=
processNodeInfo
;
if
(
this
.
isLoading
||
this
.
processNodeInfo
==
null
||
this
.
bpmnViewer
==
null
)
return
;
const
{
finishedTaskSet
,
rejectedTaskSet
,
unfinishedTaskSet
,
finishedSequenceFlowSet
,
}
=
this
.
processNodeInfo
;
const
canvas
=
this
.
bpmnViewer
.
get
(
"canvas"
);
const
elementRegistry
=
this
.
bpmnViewer
.
get
(
"elementRegistry"
);
if
(
Array
.
isArray
(
finishedSequenceFlowSet
))
{
finishedSequenceFlowSet
.
forEach
((
item
)
=>
{
if
(
item
!=
null
)
{
canvas
.
addMarker
(
item
,
"success"
);
const
element
=
elementRegistry
.
get
(
item
);
const
conditionExpression
=
element
.
businessObject
.
conditionExpression
;
if
(
conditionExpression
)
{
canvas
.
addMarker
(
item
,
"condition-expression"
);
}
}
});
}
if
(
Array
.
isArray
(
finishedTaskSet
))
{
finishedTaskSet
.
forEach
((
item
)
=>
canvas
.
addMarker
(
item
,
"success"
));
}
if
(
Array
.
isArray
(
unfinishedTaskSet
))
{
unfinishedTaskSet
.
forEach
((
item
)
=>
canvas
.
addMarker
(
item
,
"primary"
));
}
if
(
Array
.
isArray
(
rejectedTaskSet
))
{
rejectedTaskSet
.
forEach
((
item
)
=>
{
if
(
item
!=
null
)
{
const
element
=
elementRegistry
.
get
(
item
);
if
(
element
.
type
.
includes
(
"Task"
))
{
canvas
.
addMarker
(
item
,
"danger"
);
}
else
{
canvas
.
addMarker
(
item
,
"warning"
);
}
}
});
}
},
},
};
</
script
>
<
style
scoped
lang=
"scss"
>
.information-list
{
height
:
220px
;
margin-top
:
10px
;
p
{
font-size
:
16px
;
line-height
:
24px
;
}
}
/
deep
/
.bjs-powered-by
{
display
:
none
;
}
//
/
deep
/
.information-list
{
//
height
:
170px
;
//
overflow
:
visible
;
//
}
.cutline
{
float
:
right
;
width
:
30%
;
height
:
30px
;
display
:
flex
;
margin-right
:
30px
;
justify-content
:
space-between
;
.cutlines{
line-height
:
30px
;
font-weight
:
600
;
margin-right
:
50px
;
}
.concent
{
line-height
:
30px
;
line-height
:
14px
;
text-align
:
center
;
align-items
:
center
;
margin
:
auto
;
padding
:
3px
;
border-radius
:
4px
;
border
:
1px
solid
#fff
;
}
}
</
style
>
src/views/workflow/mixin/index.js
View file @
c9014f8
...
...
@@ -86,7 +86,7 @@ export default {
case
"B1"
:
getWorkFlowImage
(
this
.
bsmSlsq
,
this
.
bestepid
?
this
.
bestepid
:
''
).
then
(
res
=>
{
let
{
result
}
=
res
this
.
$popupDialog
(
"流程图"
,
"workflow/
components/processViewer
"
,
{
this
.
$popupDialog
(
"流程图"
,
"workflow/
top/processViewer/index
"
,
{
xml
:
result
.
xml
,
finishedInfo
:
{
finishedTaskSet
:
result
.
finishedActivityIds
,
...
...
Please
register
or
sign in
to post a comment