n20-common-lib 2.8.18 → 2.8.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n20-common-lib",
3
- "version": "2.8.18",
3
+ "version": "2.8.20",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -0,0 +1,678 @@
1
+ <template>
2
+ <div class="n20-approval-img-por">
3
+ <svg v-pre style="display: none">
4
+ <symbol id="symbol_node_User">
5
+ <g transform="translate(8, 6)">
6
+ <path
7
+ d="M8.62859063,8.46867126 L8.63329414,8.24055098 C9.71745339,7.48328573 10.2442466,6.14748866 10.2442466,4.16966236 C10.2442466,2.26238871 9.05190661,1.12413909 7.0529145,1.12413909 L6.94473376,1.12413909 C4.9480934,1.12413909 3.75340165,2.26238871 3.75340165,4.16966236 C3.75340165,6.13808165 4.28489838,7.47387871 5.37846464,8.23584747 L5.37846464,8.4663195 C3.55820594,8.71090206 1.73324375,9.43524274 1.73324375,10.5429195 C1.73324375,12.0927264 3.50411558,12.8782127 6.99882412,12.8782127 C10.4935327,12.8782127 12.2644045,12.0927264 12.2644045,10.5429195 C12.2644045,9.4375945 10.4441458,8.71325383 8.62859063,8.46867126 Z"
8
+ />
9
+ </g>
10
+ </symbol>
11
+ <symbol id="symbol_node_Department">
12
+ <g transform="translate(8,6)">
13
+ <path
14
+ d="M7.04500001,8.5975 C7.04341917,8.43233903 7.11928944,8.27597225 7.25,8.175 C8.13981911,7.5076991 8.659503,6.45719523 8.65,5.34499999 L8.65,3.7075 C8.65,1.93500001 7.2825,0.500000006 5.59250001,0.500000006 L5.0925,0.500000006 C3.40500001,0.500000006 2.03749999,1.93500001 2.03749999,3.7075 L2.03749999,5.34499999 C2.02858505,6.45763799 2.54923878,7.50822626 3.44000001,8.175 C3.56977164,8.27648552 3.64467827,8.43277221 3.6425,8.5975 C3.64849065,8.83992543 3.4853373,9.05399926 3.25,9.1125 C1.335,9.50000001 0,10.4025 0,11.4525 C0,12.86 2.3925,14 5.3425,14 C8.29249999,14 10.6875,12.86 10.6875,11.4525 C10.6875,10.4025 9.35250001,9.5025 7.4375,9.1125 C7.20216271,9.05399926 7.03900935,8.83992543 7.04500001,8.5975 Z M11.84,5.75000001 C11.7079451,5.71733762 11.6061675,5.61208512 11.5779553,5.47900848 C11.549743,5.34593185 11.6000579,5.20843574 11.7075,5.125 C12.3007336,4.67960715 12.6476383,3.97930492 12.6425,3.2375 L12.6425,2.1375 C12.6690444,0.984062183 11.7559203,0.0272961173 10.6025,0 L10.2725,0 C9.40687566,0.0115235348 8.64254102,0.567494343 8.365,1.3875 C8.87621704,2.05264244 9.15230637,2.86860072 9.15,3.7075 L9.15,5.10250001 L9.1675,5.11749999 C9.26100971,5.18903404 9.3126331,5.30253015 9.30510153,5.42002253 C9.29756997,5.53751492 9.23187787,5.6434908 9.13,5.7025 C9.04235466,6.75161502 8.54690721,7.72455893 7.75,8.4125 C8.58510108,8.82290154 9.50732647,9.0245043 10.4375,9 C12.405,9 14,8.24999999 14,7.3025 C14,6.6025 13.11,6 11.84,5.75000001 Z"
15
+ />
16
+ </g>
17
+ </symbol>
18
+ </svg>
19
+ <div ref="activiti-svg-wrap" class="activiti-svg-wrap"></div>
20
+ <div class="flex-box activiti-svg-zoom">
21
+ <el-button type="text" icon="el-icon-zoom-out" style="font-size: 18px" @click="scaleMinus" />
22
+ <el-slider
23
+ v-model="zoomValue"
24
+ class="m-l m-r"
25
+ :min="min"
26
+ :max="max"
27
+ :step="step"
28
+ :format-tooltip="$options.filters.zoomFormat"
29
+ style="width: 200px"
30
+ />
31
+ <el-button type="text" icon="el-icon-zoom-in" style="font-size: 18px" @click="scaleAdd" />
32
+ <span class="m-l-s m-r-s" style="display: inline-block; width: 38px; line-height: 38px">{{
33
+ zoomValue | zoomFormat
34
+ }}</span>
35
+ <el-button type="text" icon="el-icon-full-screen" style="font-size: 16px" @click="scaleReset" />
36
+ </div>
37
+ <el-popover ref="title-pop" v-model="msgV" trigger="manual" placement="top">
38
+ <div class="activiti-msg">
39
+ <div v-if="assigneeEnd" class="m-t-ss m-b-ss">
40
+ <table cellspacing="0" style="border-collapse: collapse; min-width: 460px">
41
+ <tr>
42
+ <td class="text-c">{{ '已审批人' | $lc }}</td>
43
+ <td class="text-c">{{ '审批类型' | $lc }}</td>
44
+ <td class="text-c">{{ '审批意见' | $lc }}</td>
45
+ <td class="text-c">{{ '审批时间' | $lc }}</td>
46
+ </tr>
47
+ <tr v-for="(item, i) in assigneeEnd" :key="i">
48
+ <td>{{ item.assignee }}</td>
49
+ <td class="text-c">{{ item.optResult }}</td>
50
+ <td>{{ item.suggestion }}</td>
51
+ <td>{{ item.endTime }}</td>
52
+ </tr>
53
+ </table>
54
+ </div>
55
+ <div v-if="assignee" :class="{ 'm-t-s': assigneeEnd }">{{ assignee }}</div>
56
+
57
+ <div v-if="taskCandidate" class="m-t-ss m-b-ss">
58
+ <div v-if="taskCandidate.cltNames.length">待审批单位:{{ taskCandidate.cltNames.join('、') }}</div>
59
+ <div v-if="taskCandidate.roleNames.length">待审批角色:{{ taskCandidate.roleNames.join('、') }}</div>
60
+ <div v-if="taskCandidate.unames.length">待审批人:{{ taskCandidate.unames.join('、') }}</div>
61
+ </div>
62
+ </div>
63
+ </el-popover>
64
+ <el-popover ref="addTask-pop" v-model="addTaskV" trigger="manual" placement="bottom">
65
+ <div @click.stop>
66
+ <div class="m-b el-dialog__title">{{ '加签流程' | $lc }}</div>
67
+ <div class="p-a" style="text-align: center">
68
+ <svg v-if="addTaskList.length" :width="addTaskList.length * 160 - 50" height="82">
69
+ <template v-for="(item, i) in addTaskList">
70
+ <g
71
+ v-if="i > 0"
72
+ :key="i + '-flow'"
73
+ class="djs-element djs-connection activiti-line-achieve"
74
+ :class="{
75
+ 'activiti-line-reject': item.examineType === 'reject'
76
+ }"
77
+ :data-element-id="item.addTaskDefId + '-flow'"
78
+ :transform="`matrix(1 0 0 1 ${i * 160 - 60} 1)`"
79
+ >
80
+ <path
81
+ d="m0,40L60,40"
82
+ style="fill: none; stroke-width: 1px; stroke: black; stroke-linejoin: round"
83
+ :style="{
84
+ 'marker-end': `url(#${markerId})`
85
+ }"
86
+ />
87
+ </g>
88
+ <g
89
+ :key="i"
90
+ class="djs-element djs-shape activiti-node-achieve"
91
+ :class="{
92
+ 'activiti-node-at': dataPro.currentActivityIdList.includes(item.addTaskDefId),
93
+ 'activiti-node-reject': item.examineType === 'reject'
94
+ }"
95
+ :data-element-id="item.addTaskDefId"
96
+ :transform="`matrix(1 0 0 1 ${1 + i * 160} 1)`"
97
+ @mouseenter="(ev) => addElIn(item.addTaskDefId, ev)"
98
+ @mouseleave="msgV = false"
99
+ >
100
+ <rect
101
+ x="0"
102
+ y="0"
103
+ width="100"
104
+ height="80"
105
+ rx="10"
106
+ ry="10"
107
+ style="stroke: black; stroke-width: 1px; fill: white; fill-opacity: 0.95"
108
+ />
109
+ <text
110
+ lineheight="1.2"
111
+ class="djs-label"
112
+ style="
113
+ font-family: Arial, sans-serif;
114
+ font-size: 12px;
115
+ font-weight: normal;
116
+ text-anchor: middle;
117
+ fill: black;
118
+ "
119
+ >
120
+ <tspan x="50" y="43.6">{{ item.taskName.slice(0, 7) }}</tspan>
121
+ <tspan x="50" y="58">{{ item.taskName.slice(7) }}</tspan>
122
+ </text>
123
+ <use xlink:href="#symbol_node_User" style="fill: rgb(102, 102, 102)" />
124
+ </g>
125
+ </template>
126
+ </svg>
127
+ </div>
128
+ </div>
129
+ </el-popover>
130
+ </div>
131
+ </template>
132
+
133
+ <script>
134
+ import { $lc } from '../../../utils/i18n/index'
135
+ import importG from '../../../utils/importGlobal.js'
136
+ export default {
137
+ filters: {
138
+ zoomFormat(val) {
139
+ return parseInt(val * 10) + '0%'
140
+ }
141
+ },
142
+ props: {
143
+ dataPro: {
144
+ type: Object,
145
+ default: undefined
146
+ }
147
+ },
148
+ data() {
149
+ this.svgW = undefined
150
+ this.svgC = undefined
151
+ return {
152
+ assignee: undefined,
153
+ assigneeEnd: undefined,
154
+ taskCandidate: undefined,
155
+ min: 0.4,
156
+ max: 2,
157
+ step: 0.1,
158
+ zoomValue: 1,
159
+ markerId: '',
160
+ msgV: false,
161
+ addTaskV: false,
162
+ addTaskList: []
163
+ }
164
+ },
165
+ watch: {
166
+ zoomValue() {
167
+ this.scaleSvg()
168
+ }
169
+ },
170
+ async mounted() {
171
+ this.svgW = this.$refs['activiti-svg-wrap']
172
+ let {
173
+ flowString,
174
+ seqRecords,
175
+ taskDefIdMap = {},
176
+ currAssMap = {},
177
+ currentActivityIdList = [],
178
+ addTask = {},
179
+ addTaskPre = {},
180
+ unApplayUserTaskCandidate = {}
181
+ } = this.dataPro
182
+ let flowSvg = flowString
183
+ if (flowString.includes('bpmn2:definitions')) {
184
+ let { default: bpmn2svg } = await importG('bpmn2svg', () =>
185
+ import(/*webpackChunkName: "bpmn2svg"*/ '../../../../bpmn2svg/bpmn2svg.umd.js')
186
+ )
187
+ flowSvg = await bpmn2svg(flowString)
188
+ }
189
+ this.setSvgAttrs(flowSvg)
190
+ this.setPendingUserInfo(unApplayUserTaskCandidate)
191
+ try {
192
+ for (let k in addTask) {
193
+ let line = this.svgW.querySelector(`[data-element-id="${k}"] path`)
194
+ if (line) {
195
+ this.addNode(k, line, addTask[k])
196
+ }
197
+ }
198
+ for (let k in addTaskPre) {
199
+ let g = this.svgW.querySelector(`[data-element-id="${k}"]`)
200
+ if (g) {
201
+ this.addNode(k, g, addTaskPre[k], 'addTaskPre')
202
+ }
203
+ }
204
+
205
+ seqRecords.forEach((obj) => {
206
+ this.setTaskRecord(obj)
207
+ })
208
+
209
+ // 非加签节点添加事件
210
+ currentActivityIdList.forEach((currentActivityId) => {
211
+ let assignee = currAssMap[currentActivityId]
212
+ let assigneeEnd = taskDefIdMap[currentActivityId]
213
+ let task = this.svgW.querySelector(`[data-element-id="${currentActivityId}"]`)
214
+ if (task) {
215
+ task.classList.add('activiti-node-at')
216
+ if (!currentActivityId.includes('@addTaskType')) {
217
+ this.addEvent(task, { assignee, assigneeEnd }, 'pending')
218
+ }
219
+ }
220
+ })
221
+ for (let k in taskDefIdMap) {
222
+ if (!currentActivityIdList.includes(k)) {
223
+ let taskK = this.svgW.querySelector(`[data-element-id="${k}"]`)
224
+ if (taskK) {
225
+ if (!k.includes('@addTaskType')) {
226
+ this.addEvent(taskK, taskDefIdMap[k])
227
+ }
228
+ }
229
+ }
230
+ }
231
+ } catch (error) {
232
+ console.warn('setTaskErr:', error)
233
+ }
234
+
235
+ let { default: panzoom } = await importG('panzoom', () => import(/*webpackChunkName: "panzoom"*/ 'panzoom'))
236
+
237
+ this.svgPanzoom = panzoom(this.svgC, {
238
+ maxZoom: this.max,
239
+ minZoom: this.min,
240
+ bounds: true,
241
+ boundsPadding: 0.1,
242
+ beforeWheel: function (e) {
243
+ return !e.ctrlKey
244
+ }
245
+ })
246
+ this.svgPanzoom.on('zoom', (e) => {
247
+ let { scale } = e.getTransform()
248
+ this.zoomValue = scale
249
+ })
250
+
251
+ document.body.addEventListener('click', this.addTaskFn)
252
+ },
253
+
254
+ deactivated() {
255
+ this.msgV = false
256
+ this.addTaskV = false
257
+ },
258
+ beforeDestroy() {
259
+ this.msgV = false
260
+ this.svgPanzoom && this.svgPanzoom.dispose()
261
+ document.body.removeEventListener('click', this.addTaskFn)
262
+ },
263
+ methods: {
264
+ addTaskFn() {
265
+ this.addTaskV = false
266
+ },
267
+ setPendingUserInfo(data) {
268
+ if (data) {
269
+ Object.keys(data).forEach((id) => {
270
+ let task = this.svgW.querySelector(`[data-element-id="${id}"]`)
271
+ if (task) {
272
+ this.addEvent(task, { taskCandidate: data[id] }, 'unApply')
273
+ }
274
+ })
275
+ }
276
+ },
277
+ setSvgAttrs(str) {
278
+ this.svgW.innerHTML = str
279
+ this.svgC = this.svgW.querySelector('svg')
280
+ let width = this.svgC.getAttribute('width')
281
+ let height = this.svgC.getAttribute('height')
282
+ let viewBox = this.svgC.getAttribute('viewBox').split(' ')
283
+ viewBox = [Number(viewBox[0]) - 16, Number(viewBox[1]) - 16, Number(viewBox[2]) + 32, Number(viewBox[3]) + 32]
284
+ viewBox = viewBox.join(' ')
285
+
286
+ this.svgC.setAttribute('width', Number(width) + 32)
287
+ this.svgC.setAttribute('height', Number(height) + 32)
288
+ this.svgC.setAttribute('viewBox', viewBox)
289
+
290
+ let marker = this.svgC.querySelector('defs marker')
291
+ marker && (this.markerId = marker.getAttribute('id'))
292
+ },
293
+ setTaskRecord(obj) {
294
+ let { resouceTaskDefId: from, targetTaskDefId: to, seqDefid: line, type: type } = obj
295
+ if (type === '0') {
296
+ this.svgW.querySelector(`[data-element-id="${from}"]`).classList.add('activiti-node-achieve')
297
+ this.svgW.querySelector(`[data-element-id="${to}"]`).classList.add('activiti-node-achieve')
298
+ this.svgW.querySelector(`[data-element-id="${line}"]`).classList.add('activiti-line-achieve')
299
+ } else {
300
+ this.svgW.querySelector(`[data-element-id="${from}"]`).classList.add('activiti-node-reject')
301
+ if (type === '1') {
302
+ this.svgW.querySelector(`[data-element-id="${to}"]`).classList.add('activiti-node-reject')
303
+ this.setRejectLink(from, to, $lc('驳回至发起人'))
304
+ } else if (type === '2') {
305
+ this.setRejectLink(from, to, $lc('驳回至上一步'))
306
+ } else if (type === '3') {
307
+ this.setRejectLink(from, to, $lc('驳回至'))
308
+ } else if (type === '4') {
309
+ this.setPropelLink(from, to, $lc('推进至'))
310
+ }
311
+ }
312
+ },
313
+ setRejectLink(from, to, msg) {
314
+ const fromO = this.getElRect(from)
315
+ const toO = this.getElRect(to)
316
+ let oTop = Math.min(fromO.top, toO.top) - 12
317
+ let fromXC = fromO.left + fromO.with / 2
318
+ let toXC = toO.left + toO.with / 2
319
+
320
+ let oRight = Math.max(fromO.right, toO.right) + 12
321
+ let fromYC = fromO.top + fromO.height / 2
322
+ let toYC = toO.top + toO.height / 2
323
+
324
+ let d
325
+ if (fromXC !== toXC) {
326
+ d = `M${fromXC},${fromO.top} L${fromXC},${oTop} L${toXC},${oTop} L${toXC},${toO.top}`
327
+ } else {
328
+ d = `M${fromO.right},${fromYC} L${oRight},${fromYC} L${oRight},${toYC} L${toO.right},${toYC}`
329
+ }
330
+
331
+ let path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
332
+ path.setAttribute('class', 'activiti-line-reject')
333
+ path.setAttribute('d', d)
334
+ path.style.markerEnd = `url('#${this.markerId}')`
335
+ this.svgC.appendChild(path)
336
+
337
+ if (msg) {
338
+ let text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
339
+ text.setAttribute('class', 'activiti-text-reject')
340
+ if (fromXC !== toXC) {
341
+ text.setAttribute('x', (fromXC + toXC) / 2)
342
+ text.setAttribute('y', oTop + 6)
343
+ } else {
344
+ text.setAttribute('y', (fromYC + toYC) / 2)
345
+ text.setAttribute('x', oRight + 8)
346
+ text.setAttribute('writing-mode', 'tb')
347
+ }
348
+ text.textContent = msg
349
+ this.svgC.appendChild(text)
350
+
351
+ let textO = text.getBBox()
352
+ let rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
353
+ rect.setAttribute('class', 'activiti-text-bg-reject')
354
+ rect.setAttribute('x', textO.x)
355
+ rect.setAttribute('y', textO.y)
356
+ rect.setAttribute('width', textO.width)
357
+ rect.setAttribute('height', textO.height)
358
+ this.svgC.insertBefore(rect, text)
359
+ }
360
+ },
361
+ setPropelLink(from, to, msg) {
362
+ const fromO = this.getElRect(from)
363
+ const toO = this.getElRect(to)
364
+ let oBottom = Math.min(fromO.bottom, toO.bottom) + 12
365
+ let fromXC = fromO.left + fromO.with / 2
366
+ let toXC = toO.left + toO.with / 2
367
+
368
+ let oLeft = Math.max(fromO.left, toO.left) - 12
369
+ let fromYC = fromO.top + fromO.height / 2
370
+ let toYC = toO.top + toO.height / 2
371
+
372
+ let d
373
+ if (fromXC !== toXC) {
374
+ d = `M${fromXC},${fromO.bottom} L${fromXC},${oBottom} L${toXC},${oBottom} L${toXC},${toO.bottom}`
375
+ } else {
376
+ d = `M${fromO.left},${fromYC} L${oLeft},${fromYC} L${oLeft},${toYC} L${toO.left},${toYC}`
377
+ }
378
+
379
+ let path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
380
+ path.setAttribute('class', 'activiti-line-propel')
381
+ path.setAttribute('d', d)
382
+ path.style.markerEnd = `url('#${this.markerId}')`
383
+ this.svgC.appendChild(path)
384
+
385
+ if (msg) {
386
+ let text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
387
+ text.setAttribute('class', 'activiti-text-propel')
388
+ if (fromXC !== toXC) {
389
+ text.setAttribute('x', (fromXC + toXC) / 2)
390
+ text.setAttribute('y', oBottom + 6)
391
+ } else {
392
+ text.setAttribute('y', (fromYC + toYC) / 2)
393
+ text.setAttribute('x', oLeft + 8)
394
+ text.setAttribute('writing-mode', 'tb')
395
+ }
396
+ text.textContent = msg
397
+ this.svgC.appendChild(text)
398
+
399
+ let textO = text.getBBox()
400
+ let rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
401
+ rect.setAttribute('class', 'activiti-text-bg-reject')
402
+ rect.setAttribute('x', textO.x)
403
+ rect.setAttribute('y', textO.y)
404
+ rect.setAttribute('width', textO.width)
405
+ rect.setAttribute('height', textO.height)
406
+ this.svgC.insertBefore(rect, text)
407
+ }
408
+ },
409
+ getElRect(id) {
410
+ let g = this.svgW.querySelector(`[data-element-id="${id}"]`)
411
+ let rect = {
412
+ with: 100,
413
+ height: 80,
414
+ left: undefined,
415
+ top: undefined
416
+ }
417
+ if (id.includes('@addTaskType')) {
418
+ rect = {
419
+ with: 20,
420
+ height: 20,
421
+ left: Number(g.getAttribute('data-element-left')),
422
+ top: Number(g.getAttribute('data-element-top'))
423
+ }
424
+ rect.right = rect.left + rect.with
425
+ rect.bottom = rect.top + rect.height
426
+ return rect
427
+ }
428
+
429
+ if (g.querySelector('circle')) {
430
+ rect.with = 36
431
+ rect.height = 36
432
+ }
433
+ let matrix = g.getAttribute('transform')
434
+ if (matrix) {
435
+ matrix = matrix.replace(/matrix\(|\)/g, '')
436
+ matrix = matrix.split(' ')
437
+ rect.left = Number(matrix[4])
438
+ rect.top = Number(matrix[5])
439
+ rect.right = rect.left + rect.with
440
+ rect.bottom = rect.top + rect.height
441
+ }
442
+ return rect
443
+ },
444
+ addNode(id, line, list, addType) {
445
+ let centreD
446
+
447
+ // 前加签,"加号"位置
448
+ if (addType === 'addTaskPre') {
449
+ let matrix = line.getAttribute('transform')
450
+ if (matrix) {
451
+ matrix = matrix.replace(/matrix\(|\)/g, '')
452
+ matrix = matrix.split(' ')
453
+ let left = Number(matrix[4])
454
+ let top = Number(matrix[5])
455
+ centreD = [left + 100, top]
456
+ }
457
+ } else {
458
+ let D = line.getAttribute('d')
459
+ let Ds = D.replace(/\s+/g, '')
460
+ .split(/[A-z]/)
461
+ .filter((d) => !!d)
462
+
463
+ if (Ds.length === 2) {
464
+ let Ds1 = Ds[0].split(',')
465
+ let Ds2 = Ds[1].split(',')
466
+ centreD = [(Number(Ds1[0]) + Number(Ds2[0])) / 2, (Number(Ds1[1]) + Number(Ds2[1])) / 2]
467
+ } else if (Ds.length > 2) {
468
+ let Ds2 = Ds[1].split(',')
469
+ centreD = [Number(Ds2[0]), Number(Ds2[1])]
470
+ }
471
+ }
472
+
473
+ if (centreD) {
474
+ let circleG = document.createElementNS('http://www.w3.org/2000/svg', 'g')
475
+ circleG.classList.add('activiti-node-achieve')
476
+ circleG.setAttribute('data-element-left', centreD[0] - 10)
477
+ circleG.setAttribute('data-element-top', centreD[1] - 10)
478
+
479
+ circleG.setAttribute('data-element-id', list?.[0]?.addTaskDefId || '')
480
+ let cEl = `<circle class="add-and" r="10" cx="${centreD[0]}" cy="${
481
+ centreD[1]
482
+ }" stroke-width="1" stroke="#666" fill="#fff"></circle>
483
+ <line class="add-and" x1="${centreD[0] - 7}" y1="${centreD[1]}" x2="${centreD[0] + 7}" y2="${
484
+ centreD[1]
485
+ }" stroke-width="1" stroke="#666" fill="none"></line>
486
+ <line class="add-and" x1="${centreD[0]}" y1="${centreD[1] - 7}" x2="${centreD[0]}" y2="${
487
+ centreD[1] + 7
488
+ }" stroke-width="1" stroke="#666" fill="none"></line>
489
+ `
490
+ circleG.innerHTML = cEl
491
+ this.svgC.appendChild(circleG)
492
+
493
+ circleG.addEventListener('click', (el) => {
494
+ if (el.currentTarget.getAttribute('class').includes('activiti-node-reject')) {
495
+ list.forEach((c) => (c.examineType = 'reject'))
496
+ }
497
+
498
+ // 合并驳回再次加签的节点
499
+ let _list = []
500
+ list.forEach((item) => {
501
+ if (!_list.some((_item) => _item.addTaskDefId === item.addTaskDefId)) {
502
+ _list.push(item)
503
+ }
504
+ })
505
+
506
+ this.addTaskList = _list
507
+ this.addTaskV = false
508
+ this.$nextTick(() => {
509
+ this.$refs['addTask-pop'].doDestroy()
510
+ this.$refs['addTask-pop'].referenceElm = circleG
511
+ this.addTaskV = true
512
+ })
513
+ el.stopPropagation()
514
+ })
515
+ }
516
+ },
517
+ addElIn(id, ev) {
518
+ if (this.dataPro.currentActivityIdList.some((cId) => cId === id) /*待审批*/) {
519
+ this.assignee = this.dataPro.currAssMap[id]
520
+ this.assigneeEnd = this.dataPro.taskDefIdMap[id]
521
+
522
+ this.$nextTick(() => {
523
+ this.$refs['title-pop'].doDestroy()
524
+ this.$refs['title-pop'].referenceElm = ev.currentTarget
525
+ this.msgV = true
526
+ })
527
+ } else if (this.dataPro.taskDefIdMap[id] /*已审批*/) {
528
+ this.assigneeEnd = this.dataPro.taskDefIdMap[id]
529
+ this.$nextTick(() => {
530
+ this.$refs['title-pop'].doDestroy()
531
+ this.$refs['title-pop'].referenceElm = ev.currentTarget
532
+ this.msgV = true
533
+ })
534
+ }
535
+ },
536
+ addEvent(task, list, type) {
537
+ task.addEventListener('mouseenter', () => {
538
+ if (type === 'pending') {
539
+ this.assignee = list.assignee
540
+ this.assigneeEnd = list.assigneeEnd
541
+ this.taskCandidate = undefined
542
+ } else if (type === 'unApply') {
543
+ this.assignee = undefined
544
+ this.assigneeEnd = undefined
545
+ this.taskCandidate = list.taskCandidate
546
+ } else {
547
+ this.assignee = undefined
548
+ this.assigneeEnd = list
549
+ }
550
+ this.$nextTick(() => {
551
+ this.$refs['title-pop'].doDestroy()
552
+ this.$refs['title-pop'].referenceElm = task
553
+ this.msgV = true
554
+ })
555
+ })
556
+ task.addEventListener('mouseleave', () => {
557
+ this.msgV = false
558
+ })
559
+ },
560
+ scaleMinus() {
561
+ let newVal = this.zoomValue - this.step
562
+ if (this.min <= newVal) {
563
+ this.zoomValue = newVal
564
+ } else {
565
+ this.zoomValue = this.min
566
+ }
567
+ },
568
+ scaleAdd() {
569
+ let newVal = this.zoomValue + this.step
570
+ if (newVal < this.max) {
571
+ this.zoomValue = newVal
572
+ } else {
573
+ this.zoomValue = this.max
574
+ }
575
+ },
576
+ scaleReset() {
577
+ this.zoomValue = 1
578
+ },
579
+ scaleSvg() {
580
+ this.svgPanzoom && this.svgPanzoom.zoomAbs(0, 0, this.zoomValue)
581
+ }
582
+ }
583
+ }
584
+ </script>
585
+
586
+ <style scoped>
587
+ .n20-approval-img-por {
588
+ width: 100%;
589
+ height: 100%;
590
+ position: relative;
591
+ }
592
+ .activiti-svg-wrap {
593
+ width: 100%;
594
+ height: 100%;
595
+ min-height: 200px;
596
+ overflow: auto;
597
+ }
598
+
599
+ .activiti-msg th,
600
+ .activiti-msg td {
601
+ padding: 6px 8px;
602
+ border: 1px solid var(--border-color-base);
603
+ }
604
+
605
+ .activiti-svg-zoom {
606
+ position: absolute;
607
+ z-index: 9;
608
+ right: 0;
609
+ bottom: 0;
610
+ }
611
+
612
+ .n20-approval-img-por .djs-hit,
613
+ .n20-approval-img-por .djs-hit-all,
614
+ .n20-approval-img-por .djs-outline {
615
+ display: none !important;
616
+ }
617
+ .n20-approval-img-por use {
618
+ fill: #b2b2b2 !important;
619
+ }
620
+ .activiti-node-achieve circle,
621
+ .activiti-node-achieve rect,
622
+ .activiti-node-achieve polygon,
623
+ .activiti-node-achieve .add-and,
624
+ .activiti-line-achieve path {
625
+ stroke: #3cb495 !important;
626
+ }
627
+ .activiti-node-achieve use {
628
+ fill: #3cb495 !important;
629
+ }
630
+ .activiti-node-reject circle,
631
+ .activiti-node-reject rect,
632
+ .activiti-node-reject .add-and {
633
+ stroke: #ea5454 !important;
634
+ }
635
+ .activiti-node-reject use {
636
+ fill: #ea5454 !important;
637
+ }
638
+ .activiti-node-at rect,
639
+ .activiti-node-at .add-and {
640
+ stroke: #fe943c !important;
641
+ }
642
+ .activiti-node-at use {
643
+ fill: #fe943c !important;
644
+ }
645
+ .activiti-line-reject,
646
+ .activiti-line-reject path {
647
+ fill: none;
648
+ stroke-width: 1px;
649
+ stroke: #ea5454 !important;
650
+ stroke-linejoin: round;
651
+ /* marker-end: url('#sequenceflow-end-white-black-3aw0mc6w8vg7jarca1qf355gu'); */
652
+ }
653
+ .activiti-text-reject {
654
+ fill: #ea5454 !important;
655
+ font-family: Arial, sans-serif;
656
+ font-size: 12px;
657
+ font-weight: normal;
658
+ text-anchor: middle;
659
+ }
660
+ .activiti-line-propel,
661
+ .activiti-line-propel path {
662
+ fill: none;
663
+ stroke-width: 1px;
664
+ stroke: #3cb495 !important;
665
+ stroke-linejoin: round;
666
+ /* marker-end: url('#sequenceflow-end-white-black-3aw0mc6w8vg7jarca1qf355gu'); */
667
+ }
668
+ .activiti-text-propel {
669
+ fill: #3cb495 !important;
670
+ font-family: Arial, sans-serif;
671
+ font-size: 12px;
672
+ font-weight: normal;
673
+ text-anchor: middle;
674
+ }
675
+ .activiti-text-bg-reject {
676
+ fill: #ffffff;
677
+ }
678
+ </style>
@@ -127,13 +127,25 @@
127
127
  </div>
128
128
  </div>
129
129
  </el-popover>
130
+
131
+ <el-popover ref="child-pop" popper-class="n20-approval-child" v-model="childV" trigger="manual" placement="bottom">
132
+ <div v-click-outside="clickOut" v-if="childV">
133
+ <div>{{ childTitle }}</div>
134
+ <child :data-pro="childDataPro"></child>
135
+ </div>
136
+ </el-popover>
130
137
  </div>
131
138
  </template>
132
139
 
133
140
  <script>
134
- import { $lc } from '../../../utils/i18n/index'
135
- import importG from '../../../utils/importGlobal.js'
141
+ import axios from '../../../utils/axios.js';
142
+ import { $lc } from '../../../utils/i18n/index';
143
+ import importG from '../../../utils/importGlobal.js';
144
+ import child from './child.vue';
136
145
  export default {
146
+ components: {
147
+ child
148
+ },
137
149
  filters: {
138
150
  zoomFormat(val) {
139
151
  return parseInt(val * 10) + '0%'
@@ -159,7 +171,10 @@ export default {
159
171
  markerId: '',
160
172
  msgV: false,
161
173
  addTaskV: false,
162
- addTaskList: []
174
+ addTaskList: [],
175
+ childV: false,
176
+ childTitle: '',
177
+ childDataPro: undefined
163
178
  }
164
179
  },
165
180
  watch: {
@@ -224,6 +239,7 @@ export default {
224
239
  if (taskK) {
225
240
  if (!k.includes('@addTaskType')) {
226
241
  this.addEvent(taskK, taskDefIdMap[k])
242
+ this.addChildEvent(taskK, taskDefIdMap[k])
227
243
  }
228
244
  }
229
245
  }
@@ -253,10 +269,12 @@ export default {
253
269
 
254
270
  deactivated() {
255
271
  this.msgV = false
272
+ this.childV = false
256
273
  this.addTaskV = false
257
274
  },
258
275
  beforeDestroy() {
259
276
  this.msgV = false
277
+ this.childV = false
260
278
  this.svgPanzoom && this.svgPanzoom.dispose()
261
279
  document.body.removeEventListener('click', this.addTaskFn)
262
280
  },
@@ -557,6 +575,54 @@ export default {
557
575
  this.msgV = false
558
576
  })
559
577
  },
578
+ addChildEvent(task, list) {
579
+ task.addEventListener('click', () => {
580
+ if (list[0]?.subProcInitId) {
581
+ this.childTitle = list[0]?.taskName
582
+ this.getFlowData(list[0]?.subProcInitId, task)
583
+ }
584
+ })
585
+ },
586
+ clickOut() {
587
+ let elPoppers = []
588
+ document.querySelectorAll('.el-popper.n20-approval-child').forEach((e) => {
589
+ e.style.display !== 'none' && elPoppers.push(e)
590
+ })
591
+
592
+ if (elPoppers.length === 1) {
593
+ this.childV = !this.childV
594
+ }
595
+ },
596
+ getFlowData(procInstId, task) {
597
+ axios
598
+ .get(
599
+ '/bems/activiti/sample/Q004_1',
600
+ {
601
+ procInstId
602
+ },
603
+ { noMsg: true, loading: false }
604
+ )
605
+ .then((res) => {
606
+ // 区分后加签还是前加签(addTaskPreItem)
607
+ if (res.data && res.data.addTask) {
608
+ let addTaskPre = {}
609
+ for (let k in res.data.addTask) {
610
+ let item = res.data.addTask[k]
611
+ let addTaskPreItem = item.filter((c) => /@2@addTaskType/.test(c.addTaskDefId))
612
+
613
+ if (addTaskPreItem.length) {
614
+ addTaskPre[k] = addTaskPreItem
615
+ delete res.data.addTask[k]
616
+ }
617
+ }
618
+ res.data['addTaskPre'] = addTaskPre
619
+ }
620
+ this.childDataPro = res.data
621
+ this.childV = !this.childV
622
+ this.$refs['child-pop'].doDestroy()
623
+ this.$refs['child-pop'].referenceElm = task
624
+ })
625
+ },
560
626
  scaleMinus() {
561
627
  let newVal = this.zoomValue - this.step
562
628
  if (this.min <= newVal) {
package/src/index.js CHANGED
@@ -108,7 +108,6 @@ import VTableLoading from './directives/loading/index.js'
108
108
  import watermark from './directives/watermark/index.js'
109
109
 
110
110
  /** 注入方法 */
111
- import dayjs from 'dayjs'
112
111
  import _numerify from 'numerify'
113
112
  import getJsonc from './assets/getJsonc.js'
114
113
  import realUrl from './assets/realUrl.js'
@@ -126,6 +125,8 @@ import { msgPor, msgboxPor } from './utils/msgboxPor.js'
126
125
  import N from './utils/numberPor.js' // 扩展Number
127
126
  import { closeTab, linkGo, linkPush } from './utils/urlToGo'
128
127
 
128
+ import { dayjs, relativeDate, relativeNowDate } from './utils/date.js'
129
+
129
130
  function numerify(input, formatType, roundingFunction) {
130
131
  return _numerify(input, formatType, roundingFunction)
131
132
  }
@@ -139,8 +140,8 @@ import i18n, { $l } from './utils/i18n'
139
140
  import fitlers from './fitlers'
140
141
 
141
142
  /** 修正ElementUI的问题 */
143
+ import monitor from './utils/monitor.js'
142
144
  import repairEl from './utils/repairElementUI'
143
-
144
145
  const components = [
145
146
  DynamicField,
146
147
  DynamicFieldOptions,
@@ -237,9 +238,8 @@ const install = function (Vue, opts = { prefix: 'Cl', i18nConfig: {} }) {
237
238
  Vue.component(name, component)
238
239
  })
239
240
 
240
-
241
241
  Object.keys(fitlers).forEach((key) => {
242
- Vue.filter(key+'Format', fitlers[key])
242
+ Vue.filter(key + 'Format', fitlers[key])
243
243
  })
244
244
 
245
245
  Vue.use(HoverTooltip)
@@ -271,6 +271,7 @@ export default {
271
271
  version,
272
272
  install
273
273
  }
274
+
274
275
  const linkClose = closeTab
275
276
  export {
276
277
  $l,
@@ -372,10 +373,13 @@ export {
372
373
  linkGo,
373
374
  linkPush,
374
375
  list2tree,
376
+ monitor,
375
377
  numerify,
376
378
  operatingStatus,
377
379
  realUrl,
378
380
  refreshTab,
381
+ relativeDate,
382
+ relativeNowDate,
379
383
  repairEl,
380
384
  // 页签/路由
381
385
  setTabs,
@@ -2550,7 +2550,9 @@ export function getSign(plain, dn) {
2550
2550
  }
2551
2551
  }
2552
2552
  if (sginCert) {
2553
- sginCert.clearPinCache()
2553
+ if (window.VUE_APP_NetSign_ARG_CLEAR) {
2554
+ sginCert.clearPinCache()
2555
+ }
2554
2556
  return sginCert.signMessage(
2555
2557
  plain,
2556
2558
  process.env.VUE_APP_NetSign_ARG_PLAIN ?? window.VUE_APP_NetSign_ARG_PLAIN ?? false
package/src/utils/auth.js CHANGED
@@ -28,6 +28,7 @@ const auth = {
28
28
  this.tokenVal = ''
29
29
  Cookies.remove(this.cokenKey)
30
30
  STORAGE.removeItem(this.stokenKey)
31
+ localStorage.removeItem('currentMenu')
31
32
  type !== 'NoToLogin' && auth.toLogin()
32
33
  },
33
34
  setLoginPath(router) {
@@ -56,10 +57,12 @@ const auth = {
56
57
  reqLang = langMap[langKey]
57
58
  },
58
59
  setHeaders(headers, desc) {
60
+ let OperationDesc = localStorage.getItem('currentMenu')
61
+
59
62
  let token = auth.getToken()
60
63
  let defaultHd = {
61
64
  Authorization: token ? 'Bearer ' + token : 'Basic TlNUQzpWVkIxVG1sVlVURlNMemxyTkhoc2VtNXdObFJaUVQwOQ==',
62
- OperationDesc: desc ? encodeURI(desc) : 'default',
65
+ OperationDesc: desc ? encodeURI(desc) : OperationDesc ? encodeURI(OperationDesc) : 'default',
63
66
  timestamp: Date.now(),
64
67
  requestKey: Date.now(),
65
68
  lang: reqLang
@@ -0,0 +1,37 @@
1
+ import dayjs from 'dayjs'
2
+ import 'dayjs/locale/zh-cn'
3
+
4
+ import relativeTime from 'dayjs/plugin/relativeTime'
5
+
6
+ dayjs.locale('zh-cn')
7
+
8
+ dayjs.extend(relativeTime)
9
+
10
+ /**
11
+ * @description 获取相对于当前时间的相对时间
12
+ * @param {Date} oldDate 指定时间
13
+ * @param {String} direction 方向 before:之前 to:之后
14
+ * @param {Boolean} postfix 是否添加后缀
15
+ * @returns {String} 时间差
16
+ */
17
+ const relativeNowDate = (oldDate, direction = 'before', postfix) => {
18
+ if (!oldDate) return ''
19
+ return direction === 'before' ? dayjs(oldDate).fromNow(postfix) : dayjs(oldDate).toNow(postfix)
20
+ }
21
+
22
+ /**
23
+ *
24
+ * @param {Date} oldDate 指定时间
25
+ * @param {Date} nowDate 指定时间
26
+ * @param {String} direction 方向 before:之前 to:之后
27
+ * @param {Boolean} postfix 是否添加后缀
28
+ * @returns
29
+ */
30
+ const relativeDate = (oldDate, nowDate, direction = 'before', postfix) => {
31
+ if (!oldDate) return ''
32
+ return direction === 'before'
33
+ ? dayjs(oldDate).from(dayjs(nowDate), postfix)
34
+ : dayjs(oldDate).to(dayjs(nowDate), postfix)
35
+ }
36
+
37
+ export { dayjs, relativeDate, relativeNowDate }
@@ -0,0 +1,42 @@
1
+ // 监控类 用户点击菜单时记录当前菜单,用于统一请求体的OperationDesc
2
+ class Monitor {
3
+ constructor(opt) {
4
+ this.opt = opt
5
+ this.init()
6
+ }
7
+ init() {
8
+ this.clickEvent()
9
+ }
10
+ setRouter(router) {
11
+ this.router = router
12
+ }
13
+ clickEvent() {
14
+ // 监听点击事件
15
+ document.addEventListener('click', (e) => {
16
+ const currentMenu = this.router.currentRoute
17
+ const { meta } = currentMenu
18
+ window.localStorage.setItem('currentMenu', meta?.desc)
19
+ })
20
+ }
21
+ }
22
+
23
+ // 监控单例模式
24
+ const monitor = (() => {
25
+ let instance = null
26
+ function createInstance() {
27
+ const monitor = new Monitor()
28
+ return monitor
29
+ }
30
+ return {
31
+ getInstance: () => {
32
+ if (!instance) {
33
+ instance = createInstance()
34
+ }
35
+ return instance
36
+ }
37
+ }
38
+ })()
39
+
40
+ const monitorInstance = monitor.getInstance()
41
+
42
+ export default monitorInstance