c9014f84 by tianhaohao@pashanhoo.com

1111

1 parent 4f079afb
......@@ -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,
......
<!--
* @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>
......@@ -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,
......