@lambo-design-mobile/workflow-approve 1.0.0-beta.22 → 1.0.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/api.js +108 -23
- package/package.json +3 -3
- package/src/FlowApproval.vue +728 -65
- package/src/FlowApproval1.vue +1186 -0
- package/src/FlowNodeCell.vue +2 -2
- package/src/SelectHandle.vue +83 -38
- package/src/SelectHandleCard.vue +5 -1
- package/src/SelectOrganize.vue +8 -4
- package/src/WorkflowDiagram.vue +408 -37
- package/src/js/global.js +21 -7
- package/src/utils/const.js +36 -0
package/src/WorkflowDiagram.vue
CHANGED
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
<div class="containers">
|
|
11
11
|
<div ref="canvas" class="canvas"></div>
|
|
12
12
|
</div>
|
|
13
|
+
<div v-if="predictButtonEnabled" class="predict-toggle">
|
|
14
|
+
<van-button
|
|
15
|
+
type="primary"
|
|
16
|
+
size="small"
|
|
17
|
+
:loading="loadingFutureNodes"
|
|
18
|
+
@click="toggleNodeDisplay"
|
|
19
|
+
>
|
|
20
|
+
{{ showAllNodes ? '显示预测路线' : '显示设计路线' }}
|
|
21
|
+
</van-button>
|
|
22
|
+
</div>
|
|
13
23
|
|
|
14
24
|
<!--审批流程追踪-->
|
|
15
25
|
<div class="title-info">
|
|
@@ -74,7 +84,8 @@
|
|
|
74
84
|
</template>
|
|
75
85
|
<script>
|
|
76
86
|
import Viewer from "bpmn-js/lib/Viewer";
|
|
77
|
-
import {
|
|
87
|
+
import { Toast } from "vant";
|
|
88
|
+
import {getHisAudit, getPrintData, printData, renderFutureNode} from "../api";
|
|
78
89
|
import ApprovalNodeCell from "./ApprovalNodeCell.vue";
|
|
79
90
|
import { getAuditStatus } from './js/global';
|
|
80
91
|
import FlowNodeCell from "./FlowNodeCell.vue"; // 根据路径修改
|
|
@@ -90,6 +101,11 @@ export default {
|
|
|
90
101
|
type: String,
|
|
91
102
|
required: false,
|
|
92
103
|
},
|
|
104
|
+
taskId: {
|
|
105
|
+
type: String,
|
|
106
|
+
required: false,
|
|
107
|
+
default: '',
|
|
108
|
+
},
|
|
93
109
|
taskNode: {
|
|
94
110
|
type: String,
|
|
95
111
|
required: false,
|
|
@@ -98,18 +114,48 @@ export default {
|
|
|
98
114
|
type: String,
|
|
99
115
|
required: true,
|
|
100
116
|
},
|
|
117
|
+
predictButtonEnabled: {
|
|
118
|
+
type: Boolean,
|
|
119
|
+
default: false,
|
|
120
|
+
},
|
|
101
121
|
},
|
|
102
122
|
mounted() {
|
|
103
123
|
this.getPrintData()
|
|
104
124
|
// this.getHisAudit()
|
|
105
125
|
this.onTrack()
|
|
106
126
|
},
|
|
127
|
+
beforeDestroy() {
|
|
128
|
+
this.removeTouchGesture();
|
|
129
|
+
if (this.bpmnViewer) {
|
|
130
|
+
this.bpmnViewer.destroy();
|
|
131
|
+
this.bpmnViewer = null;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
107
134
|
data() {
|
|
108
135
|
return {
|
|
109
136
|
showTaskNodeDetail: false,
|
|
110
137
|
nodeDetailsList: [],
|
|
111
138
|
currentIndex: 0,
|
|
112
139
|
auditData: [],
|
|
140
|
+
tableData: [],
|
|
141
|
+
|
|
142
|
+
bpmnViewer: null,
|
|
143
|
+
diagramReady: false,
|
|
144
|
+
|
|
145
|
+
// 预测路线相关状态
|
|
146
|
+
showAllNodes: true,
|
|
147
|
+
loadingFutureNodes: false,
|
|
148
|
+
futureNodeData: null,
|
|
149
|
+
|
|
150
|
+
// 已办/待办集合(用于预测路线显示时保留已执行路径)
|
|
151
|
+
doneLightSet: new Set(),
|
|
152
|
+
doneTaskSet: new Set(),
|
|
153
|
+
donePointIdSet: new Set(),
|
|
154
|
+
doneNodeIdSet: new Set(),
|
|
155
|
+
todoPointIdSet: new Set(),
|
|
156
|
+
|
|
157
|
+
// 触摸手势事件句柄(用于重复初始化时清理)
|
|
158
|
+
touchGestureHandlers: null,
|
|
113
159
|
}
|
|
114
160
|
},
|
|
115
161
|
computed: {
|
|
@@ -125,8 +171,9 @@ export default {
|
|
|
125
171
|
getPrintData() {
|
|
126
172
|
getPrintData(this.applyId, this.procId).then(resp => {
|
|
127
173
|
if (resp.data.code === '200') {
|
|
128
|
-
|
|
129
|
-
this.
|
|
174
|
+
const data = Array.isArray(resp.data.data) ? resp.data.data : [];
|
|
175
|
+
this.tableData = data;
|
|
176
|
+
this.auditData = data;
|
|
130
177
|
}
|
|
131
178
|
})
|
|
132
179
|
},
|
|
@@ -137,16 +184,317 @@ export default {
|
|
|
137
184
|
}
|
|
138
185
|
})
|
|
139
186
|
},
|
|
140
|
-
|
|
187
|
+
|
|
188
|
+
// 切换“设计路线 / 预测路线”显示
|
|
189
|
+
async toggleNodeDisplay() {
|
|
190
|
+
if (this.showAllNodes) {
|
|
191
|
+
const success = await this.loadFutureNodes();
|
|
192
|
+
if (!success) return;
|
|
193
|
+
this.showAllNodes = false;
|
|
194
|
+
this.$emit('toggle-predictive', {showPredictive: true, futureNodeData: this.futureNodeData});
|
|
195
|
+
} else {
|
|
196
|
+
this.showAllNodesInDiagram();
|
|
197
|
+
this.showAllNodes = true;
|
|
198
|
+
this.$emit('toggle-predictive', {showPredictive: false, futureNodeData: null});
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
// 加载未来节点(预测路线)数据
|
|
203
|
+
async loadFutureNodes() {
|
|
204
|
+
if (!this.instanceId || !this.taskId) {
|
|
205
|
+
Toast('缺少必要参数:流程实例ID或当前任务ID');
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
if (!this.diagramReady) {
|
|
209
|
+
Toast('流程图尚未加载完成,请稍后重试');
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
this.loadingFutureNodes = true;
|
|
214
|
+
try {
|
|
215
|
+
const resp = await renderFutureNode(this.instanceId, this.taskId);
|
|
216
|
+
if (resp.data.code === '200' && resp.data.data) {
|
|
217
|
+
const futureData = resp.data.data;
|
|
218
|
+
const currentNodeId = futureData.currentNodeId;
|
|
219
|
+
const elementRegistry = this.bpmnViewer && this.bpmnViewer.get('elementRegistry');
|
|
220
|
+
if (currentNodeId && elementRegistry) {
|
|
221
|
+
const currentElement = elementRegistry.get(currentNodeId);
|
|
222
|
+
if (currentElement && this.isElementInSubProcess(currentElement)) {
|
|
223
|
+
Toast('预测路线暂不支持子流程节点,请查看设计路线');
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
this.futureNodeData = futureData;
|
|
228
|
+
this.showFutureNodesOnly();
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
Toast.fail(`加载预测路线失败:${resp.data.message || '未知错误'}`);
|
|
232
|
+
return false;
|
|
233
|
+
} catch (error) {
|
|
234
|
+
Toast.fail(`加载预测路线失败:${error.message || '未知错误'}`);
|
|
235
|
+
return false;
|
|
236
|
+
} finally {
|
|
237
|
+
this.loadingFutureNodes = false;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
// 只显示预测路线相关节点(并保留已办路径)
|
|
242
|
+
showFutureNodesOnly() {
|
|
243
|
+
if (!this.futureNodeData || !this.bpmnViewer) return;
|
|
244
|
+
|
|
245
|
+
const elementRegistry = this.bpmnViewer.get('elementRegistry');
|
|
246
|
+
|
|
247
|
+
// 获取所有元素
|
|
248
|
+
const allElements = elementRegistry.getAll();
|
|
249
|
+
|
|
250
|
+
// 从后端数据中提取节点和边信息
|
|
251
|
+
const {nodes = [], edges = [], futureNodeIds = []} = this.futureNodeData;
|
|
252
|
+
|
|
253
|
+
// 构建节点ID到节点数据的映射
|
|
254
|
+
const nodeMap = new Map();
|
|
255
|
+
nodes.forEach(node => {
|
|
256
|
+
nodeMap.set(node.id, node);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// 构建边ID到边数据的映射
|
|
260
|
+
const edgeMap = new Map();
|
|
261
|
+
edges.forEach(edge => {
|
|
262
|
+
edgeMap.set(edge.id, edge);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// 已办连线和节点集合(使用 Set 便于判断)
|
|
266
|
+
const doneLightSet = this.doneLightSet instanceof Set ? this.doneLightSet : new Set(this.doneLightSet || []);
|
|
267
|
+
const doneNodeSet = this.doneNodeIdSet instanceof Set ? this.doneNodeIdSet : new Set(this.doneNodeIdSet || []);
|
|
268
|
+
const hiddenNodeSet = new Set(this.futureNodeData.hiddenNodeIds || []);
|
|
269
|
+
const hiddenEdgeSet = new Set(this.futureNodeData.hiddenEdgeIds || []);
|
|
270
|
+
|
|
271
|
+
const futureNodeIdSet = new Set(futureNodeIds || []);
|
|
272
|
+
void futureNodeIdSet;
|
|
273
|
+
|
|
274
|
+
const visibleSubProcessIds = new Set(this.futureNodeData.visibleSubProcessIds || []);
|
|
275
|
+
|
|
276
|
+
// 遍历所有元素
|
|
277
|
+
allElements.forEach(element => {
|
|
278
|
+
const gfx = elementRegistry.getGraphics(element);
|
|
279
|
+
if (!gfx) return;
|
|
280
|
+
|
|
281
|
+
// 开始事件和结束事件
|
|
282
|
+
if (element.type === 'bpmn:StartEvent' || element.type === 'bpmn:EndEvent') {
|
|
283
|
+
const nodeData = nodeMap.get(element.id) || {};
|
|
284
|
+
const nodeFutureVisible = nodeData.hasOwnProperty('futureVisible')
|
|
285
|
+
? nodeData.futureVisible
|
|
286
|
+
: !hiddenNodeSet.has(element.id);
|
|
287
|
+
const parentSubProcess = element.parent && element.parent.type === 'bpmn:SubProcess' ? element.parent : null;
|
|
288
|
+
const parentVisible = parentSubProcess ? visibleSubProcessIds.has(parentSubProcess.id) : true;
|
|
289
|
+
const parentDone = parentSubProcess && doneNodeSet.has(parentSubProcess.id);
|
|
290
|
+
if (parentSubProcess && !parentVisible && !parentDone) {
|
|
291
|
+
gfx.style.display = 'none';
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const shouldDisplay = nodeFutureVisible || doneNodeSet.has(element.id);
|
|
295
|
+
if (!shouldDisplay) {
|
|
296
|
+
gfx.style.display = 'none';
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
gfx.style.display = '';
|
|
300
|
+
gfx.style.opacity = '1';
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// 处理任务节点
|
|
305
|
+
if (element.type === 'bpmn:UserTask' ||
|
|
306
|
+
element.type === 'bpmn:ServiceTask' ||
|
|
307
|
+
element.type === 'bpmn:Task' ||
|
|
308
|
+
element.type === 'bpmn:CallActivity') {
|
|
309
|
+
|
|
310
|
+
const nodeData = nodeMap.get(element.id) || {};
|
|
311
|
+
const nodeFutureVisible = nodeData.hasOwnProperty('futureVisible')
|
|
312
|
+
? nodeData.futureVisible
|
|
313
|
+
: !hiddenNodeSet.has(element.id);
|
|
314
|
+
const parentId = nodeData.parentSubProcessId;
|
|
315
|
+
const parentIsDone = parentId && doneNodeSet.has(parentId);
|
|
316
|
+
const isDoneTask = doneNodeSet.has(element.id) || parentIsDone;
|
|
317
|
+
const shouldDisplay = nodeFutureVisible || isDoneTask;
|
|
318
|
+
|
|
319
|
+
if (!shouldDisplay) {
|
|
320
|
+
gfx.style.display = 'none';
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
gfx.style.display = '';
|
|
325
|
+
gfx.style.opacity = '1';
|
|
326
|
+
|
|
327
|
+
if (nodeData.futureHighlight) {
|
|
328
|
+
const visualElement = gfx.querySelector('.djs-visual > :nth-child(1)');
|
|
329
|
+
if (visualElement) {
|
|
330
|
+
visualElement.style.stroke = '#FFD700';
|
|
331
|
+
visualElement.style.strokeWidth = '2px';
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// 处理连线
|
|
337
|
+
if (element.type === 'bpmn:SequenceFlow') {
|
|
338
|
+
const edgeData = edgeMap.get(element.id) || {};
|
|
339
|
+
|
|
340
|
+
// 修改:严格判断连线是否已办,只有连线本身在 doneLightSet 中才视为已办
|
|
341
|
+
const isDoneLine = doneLightSet.has(element.id);
|
|
342
|
+
|
|
343
|
+
const edgeFutureVisible = edgeData.hasOwnProperty('futureVisible')
|
|
344
|
+
? edgeData.futureVisible
|
|
345
|
+
: !hiddenEdgeSet.has(element.id);
|
|
346
|
+
|
|
347
|
+
if (!(edgeFutureVisible || isDoneLine)) {
|
|
348
|
+
gfx.style.display = 'none';
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
gfx.style.display = '';
|
|
353
|
+
gfx.style.opacity = '1';
|
|
354
|
+
|
|
355
|
+
const shouldHighlight = edgeData.futureHighlight === true;
|
|
356
|
+
if (shouldHighlight) {
|
|
357
|
+
const canvas = this.bpmnViewer.get('canvas');
|
|
358
|
+
if (canvas && canvas.hasMarker(element.id, 'done-line')) {
|
|
359
|
+
canvas.removeMarker(element.id, 'done-line');
|
|
360
|
+
}
|
|
361
|
+
const visualElement = gfx.querySelector('.djs-visual > :nth-child(1)');
|
|
362
|
+
if (visualElement) {
|
|
363
|
+
visualElement.style.stroke = '#FFD700';
|
|
364
|
+
visualElement.style.strokeWidth = '2px';
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// 处理网关节点
|
|
370
|
+
if (typeof element.type === 'string' && element.type.includes('Gateway')) {
|
|
371
|
+
const nodeData = nodeMap.get(element.id) || {};
|
|
372
|
+
const nodeFutureVisible = nodeData.hasOwnProperty('futureVisible')
|
|
373
|
+
? nodeData.futureVisible
|
|
374
|
+
: !hiddenNodeSet.has(element.id);
|
|
375
|
+
|
|
376
|
+
// 检查是否同时连接到已办节点和预测路径上的节点
|
|
377
|
+
const hasIncomingDone = element.incoming?.some(conn => {
|
|
378
|
+
const source = conn.source;
|
|
379
|
+
return doneLightSet.has(conn.id) || (source && doneNodeSet.has(source.id));
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const hasOutgoingFuture = element.outgoing?.some(conn => {
|
|
383
|
+
const target = conn.target;
|
|
384
|
+
const connData = edgeMap.get(conn.id) || {};
|
|
385
|
+
return connData.futureVisible || (target && nodeMap.get(target.id)?.futureVisible);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// 严格网关显示条件:预测可见 / 已办 / 同时连接已办与预测(避免孤立网关)
|
|
389
|
+
const shouldDisplay = nodeFutureVisible || doneNodeSet.has(element.id) || (hasIncomingDone && hasOutgoingFuture);
|
|
390
|
+
if (!shouldDisplay) {
|
|
391
|
+
gfx.style.display = 'none';
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
gfx.style.display = '';
|
|
395
|
+
gfx.style.opacity = '1';
|
|
396
|
+
const visualElement = gfx.querySelector('.djs-visual > :nth-child(1)');
|
|
397
|
+
if (visualElement) {
|
|
398
|
+
if (nodeData.futureHighlight) {
|
|
399
|
+
visualElement.style.stroke = '#FFD700';
|
|
400
|
+
visualElement.style.strokeWidth = '2px';
|
|
401
|
+
} else {
|
|
402
|
+
visualElement.style.stroke = '#000000';
|
|
403
|
+
visualElement.style.strokeWidth = '2px';
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// 处理子流程节点(SubProcess)
|
|
409
|
+
if (element.type === 'bpmn:SubProcess') {
|
|
410
|
+
const nodeData = nodeMap.get(element.id) || {};
|
|
411
|
+
const nodeFutureVisible = nodeData.hasOwnProperty('futureVisible')
|
|
412
|
+
? nodeData.futureVisible
|
|
413
|
+
: visibleSubProcessIds.has(element.id);
|
|
414
|
+
const shouldDisplay = nodeFutureVisible || doneNodeSet.has(element.id);
|
|
415
|
+
if (!shouldDisplay) {
|
|
416
|
+
gfx.style.display = 'none';
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
gfx.style.display = '';
|
|
420
|
+
gfx.style.opacity = '1';
|
|
421
|
+
const visualElement = gfx.querySelector('.djs-visual > :nth-child(1)');
|
|
422
|
+
if (visualElement) {
|
|
423
|
+
if (nodeData.futureHighlight) {
|
|
424
|
+
visualElement.style.stroke = '#FFD700';
|
|
425
|
+
visualElement.style.strokeWidth = '2px';
|
|
426
|
+
} else {
|
|
427
|
+
visualElement.style.stroke = '#000000';
|
|
428
|
+
visualElement.style.strokeWidth = '2px';
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// 处理 label(如连线名称)
|
|
434
|
+
if (element.type === 'label' && element.labelTarget) {
|
|
435
|
+
const target = element.labelTarget;
|
|
436
|
+
const targetEdgeData = edgeMap.get(target.id) || {};
|
|
437
|
+
const futureLabelVisible = targetEdgeData.hasOwnProperty('futureLabelVisible')
|
|
438
|
+
? targetEdgeData.futureLabelVisible
|
|
439
|
+
: false;
|
|
440
|
+
const targetIsDoneLine = doneLightSet.has(target.id);
|
|
441
|
+
gfx.style.display = (futureLabelVisible || targetIsDoneLine) ? '' : 'none';
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
},
|
|
445
|
+
|
|
446
|
+
// 恢复显示全部节点(设计路线)
|
|
447
|
+
showAllNodesInDiagram() {
|
|
448
|
+
if (!this.bpmnViewer) return;
|
|
449
|
+
this.futureNodeData = null;
|
|
450
|
+
this.showTaskNodeDetail = false;
|
|
451
|
+
this.nodeDetailsList = [];
|
|
452
|
+
this.currentIndex = 0;
|
|
453
|
+
|
|
454
|
+
// 重新加载流程图是最可靠的恢复方式(避免样式残留)
|
|
455
|
+
this.onTrack();
|
|
456
|
+
},
|
|
457
|
+
|
|
458
|
+
isElementInSubProcess(element) {
|
|
459
|
+
let parent = element && element.parent;
|
|
460
|
+
while (parent) {
|
|
461
|
+
if (parent.type === 'bpmn:SubProcess') {
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
parent = parent.parent;
|
|
465
|
+
}
|
|
466
|
+
return false;
|
|
467
|
+
},
|
|
468
|
+
|
|
469
|
+
removeTouchGesture() {
|
|
470
|
+
if (!this.touchGestureHandlers) return;
|
|
471
|
+
const {container, onTouchStart, onTouchMove, onTouchEnd} = this.touchGestureHandlers;
|
|
472
|
+
if (container) {
|
|
473
|
+
container.removeEventListener('touchstart', onTouchStart);
|
|
474
|
+
container.removeEventListener('touchmove', onTouchMove);
|
|
475
|
+
container.removeEventListener('touchend', onTouchEnd);
|
|
476
|
+
}
|
|
477
|
+
this.touchGestureHandlers = null;
|
|
478
|
+
},
|
|
479
|
+
|
|
480
|
+
async onTrack() {
|
|
481
|
+
this.removeTouchGesture();
|
|
482
|
+
if (this.bpmnViewer) {
|
|
483
|
+
this.bpmnViewer.destroy();
|
|
484
|
+
this.bpmnViewer = null;
|
|
485
|
+
}
|
|
486
|
+
this.diagramReady = false;
|
|
487
|
+
|
|
141
488
|
// 初始化 Viewer
|
|
142
489
|
this.bpmnViewer = new Viewer({
|
|
143
490
|
container: this.$refs.canvas
|
|
144
491
|
});
|
|
145
492
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
493
|
+
try {
|
|
494
|
+
// 获取并加载流程数据
|
|
495
|
+
const resp = await printData(this.applyId, this.instanceId, this.procId);
|
|
496
|
+
const result = resp && resp.data;
|
|
497
|
+
if (result && result.code === '200') {
|
|
150
498
|
const bpmnXmlStr = result.data.processXml;
|
|
151
499
|
await this.bpmnViewer.importXML(bpmnXmlStr);
|
|
152
500
|
|
|
@@ -154,48 +502,58 @@ export default {
|
|
|
154
502
|
canvas.zoom('fit-viewport', 'auto');
|
|
155
503
|
canvas.zoom(0.6); // 放大视图
|
|
156
504
|
|
|
157
|
-
|
|
505
|
+
// 给流程节点添加固定样式
|
|
158
506
|
this.doPrint(result.data.historicData);
|
|
507
|
+
this.diagramReady = true;
|
|
159
508
|
|
|
160
509
|
// 添加手势缩放和移动功能
|
|
161
510
|
this.addTouchGesture();
|
|
162
511
|
// 监听元素点击事件
|
|
163
512
|
this.addElementClickListener();
|
|
164
513
|
|
|
514
|
+
return;
|
|
165
515
|
}
|
|
166
|
-
}).catch(err => {
|
|
167
|
-
console.error("Error fetching BPMN data:", err);
|
|
168
|
-
});
|
|
169
516
|
|
|
517
|
+
this.diagramReady = false;
|
|
518
|
+
Toast.fail(`加载流程图失败:${(result && result.message) || '未知错误'}`);
|
|
519
|
+
} catch (err) {
|
|
520
|
+
this.diagramReady = false;
|
|
521
|
+
console.error("Error fetching BPMN data:", err);
|
|
522
|
+
Toast.fail(`加载流程图失败:${err.message || '未知错误'}`);
|
|
523
|
+
}
|
|
170
524
|
},
|
|
171
525
|
doPrint(printData) {
|
|
172
|
-
const {doneLightSet, donePointSet, doneTaskSet, todoPointSet} =
|
|
173
|
-
|
|
526
|
+
const {doneLightSet, donePointSet, doneTaskSet, todoPointSet} = printData || {};
|
|
527
|
+
|
|
528
|
+
// 保存已办连线和节点集合,供预测路线显示时使用
|
|
529
|
+
this.doneLightSet = new Set(doneLightSet || []);
|
|
530
|
+
this.doneTaskSet = new Set(doneTaskSet || []);
|
|
531
|
+
this.donePointIdSet = new Set(donePointSet || []);
|
|
532
|
+
this.doneNodeIdSet = new Set([
|
|
533
|
+
...this.doneTaskSet,
|
|
534
|
+
...this.donePointIdSet
|
|
535
|
+
]);
|
|
536
|
+
this.todoPointIdSet = new Set(todoPointSet || []);
|
|
537
|
+
|
|
174
538
|
const canvas = this.bpmnViewer.get("canvas");
|
|
175
539
|
const elementRegistry = this.bpmnViewer.get('elementRegistry');
|
|
176
540
|
elementRegistry.filter((item) => item.type === 'bpmn:UserTask');
|
|
177
|
-
for (
|
|
178
|
-
if (
|
|
179
|
-
canvas.addMarker(doneLightSet[k], "done-line");
|
|
180
|
-
}
|
|
541
|
+
for (const id of this.doneLightSet) {
|
|
542
|
+
if (id) canvas.addMarker(id, "done-line");
|
|
181
543
|
}
|
|
182
|
-
for (
|
|
183
|
-
if (
|
|
184
|
-
canvas.addMarker(donePointSet[k], "done-point");
|
|
185
|
-
}
|
|
544
|
+
for (const id of this.donePointIdSet) {
|
|
545
|
+
if (id) canvas.addMarker(id, "done-point");
|
|
186
546
|
}
|
|
187
|
-
for (
|
|
188
|
-
if (
|
|
189
|
-
canvas.addMarker(doneTaskSet[k], "done-task");
|
|
190
|
-
}
|
|
547
|
+
for (const id of this.doneTaskSet) {
|
|
548
|
+
if (id) canvas.addMarker(id, "done-task");
|
|
191
549
|
}
|
|
192
|
-
for (
|
|
193
|
-
if (
|
|
194
|
-
canvas.addMarker(todoPointSet[k], "todo-point");
|
|
195
|
-
}
|
|
550
|
+
for (const id of this.todoPointIdSet) {
|
|
551
|
+
if (id) canvas.addMarker(id, "todo-point");
|
|
196
552
|
}
|
|
197
553
|
},
|
|
198
554
|
addTouchGesture() {
|
|
555
|
+
if (!this.bpmnViewer) return;
|
|
556
|
+
this.removeTouchGesture();
|
|
199
557
|
const canvas = this.bpmnViewer.get('canvas');
|
|
200
558
|
const container = this.$refs.canvas;
|
|
201
559
|
let initialDistance = null;
|
|
@@ -208,7 +566,7 @@ export default {
|
|
|
208
566
|
return Math.sqrt(dx * dx + dy * dy);
|
|
209
567
|
};
|
|
210
568
|
|
|
211
|
-
|
|
569
|
+
const onTouchStart = (event) => {
|
|
212
570
|
if (event.touches.length === 2) {
|
|
213
571
|
initialDistance = calculateDistance(event.touches[0], event.touches[1]);
|
|
214
572
|
} else if (event.touches.length === 1) {
|
|
@@ -218,9 +576,9 @@ export default {
|
|
|
218
576
|
};
|
|
219
577
|
isPanning = true;
|
|
220
578
|
}
|
|
221
|
-
}
|
|
579
|
+
};
|
|
222
580
|
|
|
223
|
-
|
|
581
|
+
const onTouchMove = (event) => {
|
|
224
582
|
if (event.touches.length === 2 && initialDistance !== null) {
|
|
225
583
|
const currentDistance = calculateDistance(event.touches[0], event.touches[1]);
|
|
226
584
|
const zoomFactor = currentDistance / initialDistance;
|
|
@@ -250,18 +608,25 @@ export default {
|
|
|
250
608
|
|
|
251
609
|
event.preventDefault(); // 阻止默认的触摸事件
|
|
252
610
|
}
|
|
253
|
-
}
|
|
611
|
+
};
|
|
254
612
|
|
|
255
|
-
|
|
613
|
+
const onTouchEnd = () => {
|
|
256
614
|
initialDistance = null; // 重置初始距离
|
|
257
615
|
isPanning = false; // 停止平移
|
|
258
|
-
}
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
container.addEventListener('touchstart', onTouchStart);
|
|
619
|
+
container.addEventListener('touchmove', onTouchMove);
|
|
620
|
+
container.addEventListener('touchend', onTouchEnd);
|
|
621
|
+
|
|
622
|
+
this.touchGestureHandlers = {container, onTouchStart, onTouchMove, onTouchEnd};
|
|
259
623
|
},
|
|
260
624
|
addElementClickListener() {
|
|
261
625
|
const eventBus = this.bpmnViewer.get('eventBus');
|
|
262
626
|
eventBus.on('element.click', (event) => {
|
|
263
627
|
const elementId = event.element.id;
|
|
264
|
-
|
|
628
|
+
const tableData = Array.isArray(this.tableData) ? this.tableData : [];
|
|
629
|
+
let matchedRecords = tableData.filter(item => item.taskNode === elementId);
|
|
265
630
|
|
|
266
631
|
if (matchedRecords.length > 0) {
|
|
267
632
|
const getTime = (record) => {
|
|
@@ -293,6 +658,12 @@ export default {
|
|
|
293
658
|
<style scoped>
|
|
294
659
|
@import 'styles/global.css';
|
|
295
660
|
|
|
661
|
+
.predict-toggle {
|
|
662
|
+
display: flex;
|
|
663
|
+
justify-content: center;
|
|
664
|
+
margin-top: 12px;
|
|
665
|
+
}
|
|
666
|
+
|
|
296
667
|
.canvas {
|
|
297
668
|
width: 100%;
|
|
298
669
|
height: 250px;
|
package/src/js/global.js
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
export function getAuditStatus(auditResult) {
|
|
1
|
+
export function getAuditStatus(auditResult, handleName, rejectName) {
|
|
2
|
+
handleName = handleName ? handleName : '通过'
|
|
3
|
+
rejectName = rejectName ? rejectName : '驳回'
|
|
2
4
|
const statusMap = {
|
|
3
5
|
'00': { text: '流程发起', icon: "faqi", color: '#0d88ff', type: 'success' },
|
|
4
|
-
'
|
|
5
|
-
'
|
|
6
|
-
'
|
|
6
|
+
'10': { text: '首节点自动跳过', icon: "tiaoguo", color: '#0d88ff', type: 'success' },
|
|
7
|
+
'11': { text: '与上一环节办理人相同自动跳过', icon: "tiaoguo", color: '#0d88ff', type: 'success' },
|
|
8
|
+
'12': { text: '与发起人相同自动跳过', icon: "tiaoguo", color: '#0d88ff', type: 'success' },
|
|
9
|
+
'13': { text: '办理人为空自动跳过', icon: "tiaoguo", color: '#0d88ff', type: 'success' },
|
|
10
|
+
'14': { text: '符合流程变量条件自动跳过', icon: "tiaoguo", color: '#0d88ff', type: 'success' },
|
|
11
|
+
'30': { text: `${handleName}`, icon: "tongguo", color: '#0d88ff', type: 'success' },
|
|
12
|
+
'31': { text: '同意', icon: "tongyi", color: '#0d88ff', type: 'success' },
|
|
13
|
+
'32': { text: '不同意', icon: "butongyi", color: '#ed4014', type: 'warning' },
|
|
14
|
+
'40': { text: `${rejectName}上一节点`, icon: "bohui", color: '#ed4014', type: 'danger' },
|
|
15
|
+
'50': { text: `${rejectName}到原点`, icon: "bohui", color: '#ed4014', type: 'danger' },
|
|
7
16
|
'51': { text: '流程作废', icon: "liuchengzuofei", color: '#ed4014', type: 'danger' },
|
|
8
|
-
'60': { text: '撤回', icon: "chehui", color: '#
|
|
17
|
+
'60': { text: '撤回', icon: "chehui", color: '#0d88ff', type: 'primary' },
|
|
18
|
+
'61': { text: '交回', icon: "jiaohui", color: '#0d88ff', type: 'primary' },
|
|
19
|
+
'62': { text: '撤回委派', icon: "chehuiweipai", color: '#ed4014', type: 'warning' },
|
|
20
|
+
'63': { text: '委派', icon: "weipai", color: '#0d88ff', type: 'primary' },
|
|
9
21
|
'80': { text: '跳转指定节点', icon: "tiaozhuan", color: '#0d88ff', type: 'primary' },
|
|
10
|
-
'
|
|
22
|
+
'82': { text: '指定他人处理', icon: "zhiding", color: '#0d88ff', type: 'primary' },
|
|
23
|
+
'83': { text: '减签', icon: "jianqian", color: '#ed4014', type: 'warning' },
|
|
24
|
+
'90': { text: `${rejectName}指定节点`, icon: "bohui", color: '#ed4014', type: 'primary' },
|
|
11
25
|
};
|
|
12
26
|
|
|
13
27
|
return {
|
|
@@ -16,4 +30,4 @@ export function getAuditStatus(auditResult) {
|
|
|
16
30
|
color: (statusMap[auditResult] && statusMap[auditResult].color) || '#ff9900',
|
|
17
31
|
type: (statusMap[auditResult] && statusMap[auditResult].type) || 'warning',
|
|
18
32
|
};
|
|
19
|
-
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const NodeType = {
|
|
2
|
+
UserTask: 'userTask',
|
|
3
|
+
MultiNode: 'multiNode',
|
|
4
|
+
SequentialMultiNode: 'sequentialMultiNode'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// 流程信息按钮
|
|
8
|
+
export const WorkflowInfoButtons = {
|
|
9
|
+
ProcessTrace: 'processTrace',// 流程跟踪图
|
|
10
|
+
AuditHistory: 'auditHistory',// 审批历史
|
|
11
|
+
AuditOpinion: 'auditOpinion',// 审批意见
|
|
12
|
+
AttachmentFile: 'attachmentFile',// 附件
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// 流程操作按钮
|
|
16
|
+
export const WorkflowOperationButtons = {
|
|
17
|
+
AuditTo30: 'auditTo30',// 通过
|
|
18
|
+
AuditTo70: 'auditTo70',// 驳回原点
|
|
19
|
+
AuditTo40: 'auditTo40',// 驳回上一节点
|
|
20
|
+
AuditTo90: 'auditTo90',// 驳回指定节点
|
|
21
|
+
AuditTo80: 'auditTo80',// 跳转指定节点
|
|
22
|
+
AuditTo82: 'auditTo82',// 转办
|
|
23
|
+
AuditTo50: 'auditTo50',// 人工终止
|
|
24
|
+
DelegateTask: 'delegateTask',// 委派
|
|
25
|
+
RevokeDelegateTask: 'revokeDelegateTask',// 撤回委派
|
|
26
|
+
AppointTask: 'appointTask',// 交回委派
|
|
27
|
+
AddMultitaskInstance: 'addMultitaskInstance',// 会签加签
|
|
28
|
+
ReductionMultitaskInstance: 'reductionMultitaskInstance',// 会签减签
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 流程流转控制按钮
|
|
32
|
+
export const WorkflowControlButtons = {
|
|
33
|
+
RejectProcessControl: 'rejectProcessControl',// 允许驳回时控制流转
|
|
34
|
+
AppointHandler: 'appointHandler',// 指定下一环节的办理人
|
|
35
|
+
AppointTimeoutTime: 'appointTimeoutTime',// 指定下一环节办理时限(含预警时间)
|
|
36
|
+
}
|