Commit 5332e543d259e38631880ae0eeb81b87969cc41f

Authored by YunaiV
1 parent 348762ae

优化 bpm 高亮流程图的前端

yudao-admin-ui/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue
@@ -14,25 +14,34 @@ export default { @@ -14,25 +14,34 @@ export default {
14 name: "MyProcessViewer", 14 name: "MyProcessViewer",
15 componentName: "MyProcessViewer", 15 componentName: "MyProcessViewer",
16 props: { 16 props: {
17 - value: String, // xml 字符串  
18 - prefix: { 17 + value: { // BPMN XML 字符串
19 type: String, 18 type: String,
20 - default: "camunda"  
21 }, 19 },
22 - taskData: { 20 + prefix: { // 使用哪个引擎
  21 + type: String,
  22 + default: "camunda",
  23 + },
  24 + activityData: { // 活动的数据。传递时,可高亮流程
  25 + type: Array,
  26 + default: () => [],
  27 + },
  28 + processInstanceData: { // 流程实例的数据。传递时,可展示流程发起人等信息
  29 + type: Object,
  30 + },
  31 + taskData: { // 任务实例的数据。传递时,可展示 UserTask 审核相关的信息
23 type: Array, 32 type: Array,
24 - default: () => [] 33 + default: () => [],
25 } 34 }
26 }, 35 },
27 data() { 36 data() {
28 return { 37 return {
29 xml: '', 38 xml: '',
30 - tasks: [], 39 + activityList: [],
31 }; 40 };
32 }, 41 },
33 mounted() { 42 mounted() {
34 this.xml = this.value; 43 this.xml = this.value;
35 - this.tasks = this.taskData; 44 + this.activityList = this.activityData;
36 // 初始化 45 // 初始化
37 this.initBpmnModeler(); 46 this.initBpmnModeler();
38 this.createNewDiagram(this.xml); 47 this.createNewDiagram(this.xml);
@@ -49,8 +58,8 @@ export default { @@ -49,8 +58,8 @@ export default {
49 this.xml = newValue; 58 this.xml = newValue;
50 this.createNewDiagram(this.xml); 59 this.createNewDiagram(this.xml);
51 }, 60 },
52 - taskData: function (newTaskData) {  
53 - this.tasks = newTaskData; 61 + activityData: function (newActivityData) {
  62 + this.activityList = newActivityData;
54 this.createNewDiagram(this.xml); 63 this.createNewDiagram(this.xml);
55 } 64 }
56 }, 65 },
@@ -83,8 +92,9 @@ export default { @@ -83,8 +92,9 @@ export default {
83 } 92 }
84 }, 93 },
85 /* 高亮流程图 */ 94 /* 高亮流程图 */
  95 + // TODO 芋艿:如果多个 endActivity 的话,目前的逻辑可能有一定的问题。https://www.jdon.com/workflow/multi-events.html
86 async highlightDiagram() { 96 async highlightDiagram() {
87 - let activityList = this.tasks; 97 + let activityList = this.activityList;
88 if (activityList.length === 0) { 98 if (activityList.length === 0) {
89 return; 99 return;
90 } 100 }
@@ -99,6 +109,7 @@ export default { @@ -99,6 +109,7 @@ export default {
99 if (!activity) { 109 if (!activity) {
100 return; 110 return;
101 } 111 }
  112 + // TODO 芋艿:
102 if (activity.task) { 113 if (activity.task) {
103 const result = activity.task.result; 114 const result = activity.task.result;
104 if (result === 1) { 115 if (result === 1) {
@@ -111,16 +122,17 @@ export default { @@ -111,16 +122,17 @@ export default {
111 canvas.addMarker(n.id, 'highlight-cancel'); 122 canvas.addMarker(n.id, 'highlight-cancel');
112 } 123 }
113 } 124 }
114 -  
115 n.outgoing?.forEach(nn => { 125 n.outgoing?.forEach(nn => {
116 - let targetTask = activityList.find(m => m.key === nn.targetRef.id)  
117 - if (targetTask) {  
118 - canvas.addMarker(nn.id, targetTask.endTime ? 'highlight' : 'highlight-todo'); 126 + let targetActivity = activityList.find(m => m.key === nn.targetRef.id)
  127 + if (targetActivity) {
  128 + debugger
  129 + canvas.addMarker(nn.id, targetActivity.endTime ? 'highlight' : 'highlight-todo');
119 } else if (nn.targetRef.$type === 'bpmn:ExclusiveGateway') { 130 } else if (nn.targetRef.$type === 'bpmn:ExclusiveGateway') {
120 - // canvas.addMarker(nn.id, 'highlight'); 131 + debugger
121 canvas.addMarker(nn.id, activity.endTime ? 'highlight' : 'highlight-todo'); 132 canvas.addMarker(nn.id, activity.endTime ? 'highlight' : 'highlight-todo');
122 canvas.addMarker(nn.targetRef.id, activity.endTime ? 'highlight' : 'highlight-todo'); 133 canvas.addMarker(nn.targetRef.id, activity.endTime ? 'highlight' : 'highlight-todo');
123 } else if (nn.targetRef.$type === 'bpmn:EndEvent') { 134 } else if (nn.targetRef.$type === 'bpmn:EndEvent') {
  135 + debugger
124 if (!todoActivity && endActivity.key === n.id) { 136 if (!todoActivity && endActivity.key === n.id) {
125 canvas.addMarker(nn.id, 'highlight'); 137 canvas.addMarker(nn.id, 'highlight');
126 canvas.addMarker(nn.targetRef.id, 'highlight'); 138 canvas.addMarker(nn.targetRef.id, 'highlight');
@@ -133,28 +145,33 @@ export default { @@ -133,28 +145,33 @@ export default {
133 }); 145 });
134 } else if (n.$type === 'bpmn:ExclusiveGateway') { // 排它网关 146 } else if (n.$type === 'bpmn:ExclusiveGateway') { // 排它网关
135 n.outgoing?.forEach(nn => { 147 n.outgoing?.forEach(nn => {
136 - let targetTask = activityList.find(m => m.key === nn.targetRef.id) 148 + let targetTask = activityList.find(m => m.key === nn.targetRef.id);
137 if (targetTask) { 149 if (targetTask) {
138 canvas.addMarker(nn.id, targetTask.endTime ? 'highlight' : 'highlight-todo'); 150 canvas.addMarker(nn.id, targetTask.endTime ? 'highlight' : 'highlight-todo');
139 } 151 }
140 }) 152 })
141 } else if (n.$type === 'bpmn:ParallelGateway') { // 并行网关 153 } else if (n.$type === 'bpmn:ParallelGateway') { // 并行网关
142 - if (activity) {  
143 - canvas.addMarker(n.id, activity.endTime ? 'highlight' : 'highlight-todo')  
144 - n.outgoing?.forEach(nn => {  
145 - const targetTask = activityList.find(m => m.key === nn.targetRef.id)  
146 - if (targetTask) {  
147 - canvas.addMarker(nn.id, targetTask.endTime ? 'highlight' : 'highlight-todo')  
148 - canvas.addMarker(nn.targetRef.id, targetTask.endTime ? 'highlight' : 'highlight-todo')  
149 - }  
150 - }) 154 + if (!activity) {
  155 + return
151 } 156 }
  157 + // 设置【bpmn:ParallelGateway】并行网关的高亮
  158 + canvas.addMarker(n.id, this.getActivityHighlightCss(activity));
  159 + n.outgoing?.forEach(nn => {
  160 + // 获得连线是否有指向目标。如果有,则进行高亮
  161 + const targetActivity = activityList.find(m => m.key === nn.targetRef.id)
  162 + if (targetActivity) {
  163 + canvas.addMarker(nn.id, this.getActivityHighlightCss(targetActivity)); // 高亮【bpmn:SequenceFlow】连线
  164 + // 高亮【...】目标。其中 ... 可以是 bpm:UserTask、也可以是其它的。当然,如果是 bpm:UserTask 的话,其实不做高亮也没问题,因为上面有逻辑做了这块。
  165 + canvas.addMarker(nn.targetRef.id, this.getActivityHighlightCss(targetActivity));
  166 + }
  167 + })
152 } else if (n.$type === 'bpmn:StartEvent') { // 开始节点 168 } else if (n.$type === 'bpmn:StartEvent') { // 开始节点
153 n.outgoing?.forEach(nn => { // outgoing 例如说【bpmn:SequenceFlow】连线 169 n.outgoing?.forEach(nn => { // outgoing 例如说【bpmn:SequenceFlow】连线
154 - let fromTask = activityList.find(m => m.key === nn.targetRef.id)  
155 - if (fromTask) {  
156 - canvas.addMarker(nn.id, 'highlight');  
157 - canvas.addMarker(n.id, 'highlight'); 170 + // 获得连线是否有指向目标。如果有,则进行高亮
  171 + let targetActivity = activityList.find(m => m.key === nn.targetRef.id);
  172 + if (targetActivity) {
  173 + canvas.addMarker(nn.id, 'highlight'); // 高亮【bpmn:SequenceFlow】连线
  174 + canvas.addMarker(n.id, 'highlight'); // 高亮【bpmn:StartEvent】开始节点(自己)
158 } 175 }
159 }); 176 });
160 } else if (n.$type === 'bpmn:EndEvent') { // 结束节点 177 } else if (n.$type === 'bpmn:EndEvent') { // 结束节点
@@ -169,10 +186,19 @@ export default { @@ -169,10 +186,19 @@ export default {
169 } 186 }
170 }) 187 })
171 }, 188 },
  189 + getActivityHighlightCss(activity) {
  190 + return activity.endTime ? 'highlight' : 'highlight-todo';
  191 + },
  192 + getTaskHighlightCss(task) {
  193 + if (!task) {
  194 + return '';
  195 + }
  196 + return '';
  197 + },
172 initModelListeners() { 198 initModelListeners() {
173 const EventBus = this.bpmnModeler.get("eventBus"); 199 const EventBus = this.bpmnModeler.get("eventBus");
174 const that = this; 200 const that = this;
175 - // 注册需要的监听事件, 将. 替换为 - , 避免解析异常 201 + // 注册需要的监听事件
176 EventBus.on('element.hover', function(eventObj) { 202 EventBus.on('element.hover', function(eventObj) {
177 let element = eventObj ? eventObj.element : null; 203 let element = eventObj ? eventObj.element : null;
178 that.elementHover(element); 204 that.elementHover(element);
@@ -209,6 +235,32 @@ export default { @@ -209,6 +235,32 @@ export default {
209 235
210 <style> 236 <style>
211 237
  238 +/** 处理中 */
  239 +.highlight-todo.djs-connection > .djs-visual > path {
  240 + stroke: orange !important;
  241 + stroke-dasharray: 4px !important;
  242 + fill-opacity: 0.2 !important;
  243 +}
  244 +.highlight-todo.djs-shape .djs-visual > :nth-child(1) {
  245 + fill: orange !important;
  246 + stroke: orange !important;
  247 + stroke-dasharray: 4px !important;
  248 + fill-opacity: 0.2 !important;
  249 +}
  250 +
  251 +/deep/.highlight-todo.djs-connection > .djs-visual > path {
  252 + stroke: orange !important;
  253 + stroke-dasharray: 4px !important;
  254 + fill-opacity: 0.2 !important;
  255 + marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);
  256 +}
  257 +/deep/.highlight-todo.djs-shape .djs-visual > :nth-child(1) {
  258 + fill: orange !important;
  259 + stroke: orange !important;
  260 + stroke-dasharray: 4px !important;
  261 + fill-opacity: 0.2 !important;
  262 +}
  263 +
212 /** 通过 */ 264 /** 通过 */
213 .highlight.djs-shape .djs-visual > :nth-child(1) { 265 .highlight.djs-shape .djs-visual > :nth-child(1) {
214 fill: green !important; 266 fill: green !important;
@@ -248,32 +300,6 @@ export default { @@ -248,32 +300,6 @@ export default {
248 stroke: green !important; 300 stroke: green !important;
249 } 301 }
250 302
251 -/** 处理中 */  
252 -.highlight-todo.djs-connection > .djs-visual > path {  
253 - stroke: orange !important;  
254 - stroke-dasharray: 4px !important;  
255 - fill-opacity: 0.2 !important;  
256 -}  
257 -.highlight-todo.djs-shape .djs-visual > :nth-child(1) {  
258 - fill: orange !important;  
259 - stroke: orange !important;  
260 - stroke-dasharray: 4px !important;  
261 - fill-opacity: 0.2 !important;  
262 -}  
263 -  
264 -/deep/.highlight-todo.djs-connection > .djs-visual > path {  
265 - stroke: orange !important;  
266 - stroke-dasharray: 4px !important;  
267 - fill-opacity: 0.2 !important;  
268 - marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);  
269 -}  
270 -/deep/.highlight-todo.djs-shape .djs-visual > :nth-child(1) {  
271 - fill: orange !important;  
272 - stroke: orange !important;  
273 - stroke-dasharray: 4px !important;  
274 - fill-opacity: 0.2 !important;  
275 -}  
276 -  
277 /** 不通过 */ 303 /** 不通过 */
278 .highlight-reject.djs-shape .djs-visual > :nth-child(1) { 304 .highlight-reject.djs-shape .djs-visual > :nth-child(1) {
279 fill: red !important; 305 fill: red !important;
yudao-admin-ui/src/views/bpm/processInstance/detail.vue
@@ -74,7 +74,7 @@ @@ -74,7 +74,7 @@
74 <div slot="header" class="clearfix"> 74 <div slot="header" class="clearfix">
75 <span class="el-icon-picture-outline">流程图</span> 75 <span class="el-icon-picture-outline">流程图</span>
76 </div> 76 </div>
77 - <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" :taskData="activityList" /> 77 + <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" :activityData="activityList"/>
78 </el-card> 78 </el-card>
79 79
80 <!-- 对话框(转派审批人) --> 80 <!-- 对话框(转派审批人) -->