@steedos-labs/plugin-workflow 3.0.64 → 3.0.66

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.
Files changed (26) hide show
  1. package/designer/dist/amis-renderer/amis-renderer.css +1 -1
  2. package/designer/dist/amis-renderer/amis-renderer.js +1 -1
  3. package/designer/dist/assets/{index-IqLl5PBH.js → index-DX2PUSq4.js} +148 -148
  4. package/designer/dist/assets/index-YXPc2HMf.css +1 -0
  5. package/designer/dist/index.html +2 -2
  6. package/main/default/client/socket.client.js +43 -13
  7. package/main/default/manager/uuflow_manager.js +9 -2
  8. package/main/default/objects/flows/flows.object.yml +4 -9
  9. package/main/default/objects/instance_tasks/listviews/inbox.listview.yml +4 -1
  10. package/main/default/pages/flow_selector.page.amis.json +2 -2
  11. package/main/default/pages/flow_selector_mobile.page.amis.json +2 -2
  12. package/main/default/pages/page_instance_print.page.amis.json +108 -32
  13. package/main/default/routes/api_workflow_approve_save.router.js +7 -0
  14. package/main/default/routes/api_workflow_forward.router.js +4 -4
  15. package/main/default/routes/api_workflow_forward_refill.router.js +1 -1
  16. package/main/default/routes/api_workflow_instance_forward.router.js +4 -4
  17. package/main/default/routes/api_workflow_retrieve.router.js +64 -33
  18. package/main/default/services/instance.service.js +1 -0
  19. package/main/default/test/test_socket_reconnect.js +105 -0
  20. package/main/default/utils/designerManager.js +12 -0
  21. package/package.json +1 -1
  22. package/public/amis-renderer/amis-renderer.css +1 -1
  23. package/public/amis-renderer/amis-renderer.js +1 -1
  24. package/public/workflow/index.css +14 -10
  25. package/src/instance_record_queue.js +326 -207
  26. package/designer/dist/assets/index-DvvBwwsG.css +0 -1
@@ -89,16 +89,16 @@
89
89
  "name": "radios",
90
90
  "type": "radios",
91
91
  "label": false,
92
- "value": "190",
92
+ "value": "210",
93
93
  "className": "mr-0",
94
94
  "options": [
95
95
  {
96
96
  "label": "A4纵向",
97
- "value": "190"
97
+ "value": "210"
98
98
  },
99
99
  {
100
100
  "label": "A4横向",
101
- "value": "277"
101
+ "value": "297"
102
102
  }
103
103
  ],
104
104
  "mode": "inline",
@@ -107,7 +107,7 @@
107
107
  "actions": [
108
108
  {
109
109
  "actionType": "custom",
110
- "script": "doAction({actionType: 'setValue', componentId: 'u:print-width', args: {value: Number(event.data.value)}}); $('.steedos-instance-related-view-wrapper .instance-form').css('width', event.data.value + 'mm'); $('.steedos-instance-related-view-wrapper .instance-approve-history').css('width', event.data.value + 'mm'); var orientation = event.data.value === '277' ? 'landscape' : 'portrait'; var styleEl = document.getElementById('print-page-orientation'); if (!styleEl) { styleEl = document.createElement('style'); styleEl.id = 'print-page-orientation'; document.head.appendChild(styleEl); } styleEl.textContent = '@page { size: A4 ' + orientation + '; }';"
110
+ "script": "doAction({actionType: 'setValue', componentId: 'u:print-width', args: {value: Number(event.data.value)}}); $('.steedos-instance-related-view-wrapper').css('width', event.data.value + 'mm'); var orientation = event.data.value === '297' ? 'landscape' : 'portrait'; var styleEl = document.getElementById('print-page-orientation'); if (!styleEl) { styleEl = document.createElement('style'); styleEl.id = 'print-page-orientation'; document.head.appendChild(styleEl); } styleEl.textContent = '@page { size: A4 ' + orientation + '; }';"
111
111
  }
112
112
  ]
113
113
  }
@@ -117,7 +117,7 @@
117
117
  "name": "width",
118
118
  "type": "input-number",
119
119
  "id": "u:print-width",
120
- "value": "190",
120
+ "value": "210",
121
121
  "mode": "inline",
122
122
  "className": "w-20 mr-0",
123
123
  "min": "100",
@@ -126,7 +126,7 @@
126
126
  "actions": [
127
127
  {
128
128
  "actionType": "custom",
129
- "script": "$('.steedos-instance-related-view-wrapper .instance-form').css('width', event.data.value + 'mm'); $('.steedos-instance-related-view-wrapper .instance-approve-history').css('width', event.data.value + 'mm');"
129
+ "script": "$('.steedos-instance-related-view-wrapper').css('width', event.data.value + 'mm');"
130
130
  }
131
131
  ]
132
132
  }
@@ -183,7 +183,7 @@
183
183
  "body": [
184
184
  {
185
185
  "type": "wrapper",
186
- "className": "steedos-instance-print-wrapper steedos-instance-detail-wrapper m-0 p-0 flex-1 focus:outline-none lg:order-last sm:m-4 shadow sm:rounded",
186
+ "className": "steedos-instance-print-wrapper steedos-instance-detail-wrapper m-0 p-0 flex-1 focus:outline-none lg:order-last sm:m-4 sm:rounded",
187
187
  "body": [
188
188
  {
189
189
  "type": "service",
@@ -233,28 +233,45 @@
233
233
  },
234
234
  "editorState": "default",
235
235
  "css": {
236
+ "body": {
237
+ "background-color": "#C0C0C0"
238
+ },
239
+ "body > .bg-slate-50": {
240
+ "background-color": "transparent !important"
241
+ },
242
+ ".steedos-instance-related-view-wrapper": {
243
+ "width": "210mm",
244
+ "margin": "0 auto",
245
+ "background-color": "#fff"
246
+ },
236
247
  ".steedos-instance-related-view-wrapper > .antd-Page-content": {
237
- "display": "inline-block",
238
- "transition": "width 0.5s ease-in-out",
239
- "width": "unset"
248
+ "transition": "width 0.5s ease-in-out"
240
249
  },
241
250
  ".steedos-instance-related-view-wrapper .instance-form": {
242
- "width": "190mm",
251
+ "width": "100%",
252
+ "margin": "0 auto",
253
+ "padding": "0 15px",
243
254
  "transition": "width 0.5s ease-in-out"
244
255
  },
245
256
  ".steedos-instance-related-view-wrapper .instance-approve-history": {
246
- "width": "190mm",
257
+ "width": "100%",
258
+ "margin": "0 auto",
259
+ "padding": "0 15px",
247
260
  "transition": "width 0.5s ease-in-out"
248
261
  },
249
- ".steedos-instance-related-view-wrapper .steedos-amis-instance-view-content": {
250
- "display": "inline-block"
262
+ ".steedos-instance-related-view-wrapper .instance-name": {
263
+ "margin": "10px 0 5px 0"
264
+ },
265
+ ".steedos-instance-related-view-wrapper .table-page-title": {
266
+ "display": "none !important"
267
+ },
268
+ ".steedos-instance-related-view-wrapper .table-page-body.form-table > tbody > tr:first-child": {
269
+ "visibility": "collapse"
251
270
  },
252
271
  ".steedos-amis-instance-view-body": {
253
- "padding": "unset",
254
- "margin": "1rem",
255
- "display": "flex",
256
- "flex-direction": "column",
257
- "align-items": "center"
272
+ "padding": "0",
273
+ "margin": "0",
274
+ "align-items": "stretch"
258
275
  },
259
276
  ".steedos-global-header-root": {
260
277
  "display": "none"
@@ -341,6 +358,9 @@
341
358
  "display": "block !important",
342
359
  "width": "100% !important"
343
360
  },
361
+ ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table th": {
362
+ "white-space": "normal !important"
363
+ },
344
364
  ".antd-Table-content-colDragLine": {
345
365
  "display": "none !important"
346
366
  },
@@ -350,23 +370,39 @@
350
370
  "height": "auto !important",
351
371
  "overflow": "visible !important",
352
372
  "display": "block !important",
353
- "position": "static !important"
373
+ "position": "static !important",
374
+ "background-color": "#fff !important"
354
375
  },
355
376
  ".resize-sensor, .no-print, .antd-Page-toolbar, .steedos-global-header-root": {
356
377
  "display": "none !important"
357
378
  },
358
- ".steedos-instance-related-view-wrapper, .steedos-instance-related-view-wrapper .antd-Page-content, .steedos-instance-related-view-wrapper .antd-Page-main, .steedos-instance-related-view-wrapper .antd-Page-body, .steedos-instance-related-view-wrapper .steedos-instance-detail-wrapper, .steedos-instance-related-view-wrapper .antd-Service, .steedos-instance-related-view-wrapper .antd-Wrapper, .steedos-instance-related-view-wrapper .steedos-amis-instance-view, .steedos-instance-related-view-wrapper .steedos-amis-instance-view-body, .steedos-instance-related-view-wrapper .steedos-amis-instance-view-content, .steedos-instance-related-view-wrapper .liquid-amis-container": {
379
+ ".steedos-instance-related-view-wrapper": {
359
380
  "display": "block !important",
360
381
  "height": "auto !important",
361
- "width": "100% !important",
382
+ "margin": "0 auto !important",
362
383
  "overflow": "visible !important",
363
384
  "flex": "none !important",
364
385
  "position": "static !important"
365
386
  },
387
+ ".steedos-instance-related-view-wrapper .antd-Page-content, .steedos-instance-related-view-wrapper .antd-Page-main, .steedos-instance-related-view-wrapper .antd-Page-body, .steedos-instance-related-view-wrapper .steedos-instance-detail-wrapper, .steedos-instance-related-view-wrapper .antd-Service, .steedos-instance-related-view-wrapper .antd-Wrapper, .steedos-instance-related-view-wrapper .steedos-amis-instance-view, .steedos-instance-related-view-wrapper .steedos-amis-instance-view-body, .steedos-instance-related-view-wrapper .steedos-amis-instance-view-content, .steedos-instance-related-view-wrapper .liquid-amis-container": {
388
+ "display": "block !important",
389
+ "height": "auto !important",
390
+ "width": "100% !important",
391
+ "overflow": "visible !important",
392
+ "flex": "none !important",
393
+ "position": "static !important",
394
+ "padding": "0 !important",
395
+ "margin": "0 !important"
396
+ },
366
397
  ".steedos-instance-related-view-wrapper .instance-form": {
367
398
  "margin": "0 auto",
368
- "width": "100% !important",
369
- "max-width": "100% !important"
399
+ "padding": "0 15px !important",
400
+ "width": "100% !important"
401
+ },
402
+ ".steedos-instance-related-view-wrapper .instance-approve-history": {
403
+ "margin": "0 auto",
404
+ "padding": "0 15px !important",
405
+ "width": "100% !important"
370
406
  },
371
407
  ".steedos-instance-related-view-wrapper .instance-form-view": {
372
408
  "table-layout": "fixed !important",
@@ -377,35 +413,75 @@
377
413
  "display": "block !important"
378
414
  },
379
415
  ".steedos-instance-related-view-wrapper .antd-Table-contentWrap": {
380
- "overflow-y": "visible !important",
381
416
  "overflow-x": "auto !important",
382
417
  "display": "block !important",
383
418
  "width": "100% !important",
384
419
  "height": "auto !important"
385
420
  },
421
+ ".steedos-instance-related-view-wrapper .instance-form .td-childfield": {
422
+ "overflow-x": "auto !important",
423
+ "overflow-y": "visible !important"
424
+ },
386
425
  ".steedos-instance-related-view-wrapper .instance-form-view td": {
387
426
  "border-width": "1px !important"
388
427
  },
389
428
  ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table": {
390
429
  "-webkit-print-color-adjust": "exact !important",
391
430
  "print-color-adjust": "exact !important",
392
- "table-layout": "fixed !important",
431
+ "table-layout": "auto !important",
393
432
  "width": "100% !important",
394
- "min-width": "0 !important"
433
+ "border-collapse": "collapse !important"
434
+ },
435
+ ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table thead": {
436
+ "display": "table-row-group !important"
395
437
  },
396
438
  ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table th": {
397
439
  "border-left": "1px solid #000 !important",
398
- "border-bottom": "1px solid #000 !important"
440
+ "border-right": "1px solid #000 !important",
441
+ "border-bottom": "1px solid #000 !important",
442
+ "border-top": "none !important",
443
+ "white-space": "normal !important"
444
+ },
445
+ ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table th:first-child, .steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table td:first-child": {
446
+ "border-left": "none !important"
447
+ },
448
+ ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table th:last-child, .steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table td:last-child": {
449
+ "border-right": "none !important"
399
450
  },
400
451
  ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table td": {
401
- "border-left": "1px solid #000 !important",
402
- "border-bottom": "1px solid #000 !important"
452
+ "border": "1px solid #000 !important"
403
453
  },
404
- ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table th.antd-Table-operationCell, .steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table td.antd-Table-operationCell": {
454
+ ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table th.antd-Table-operationCell, .steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table td.antd-Table-operationCell, .steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table td.steedos-input-table-column-operation": {
405
455
  "display": "none !important"
406
456
  },
457
+ ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table tbody td .antd-Form-static": {
458
+ "word-break": "normal !important",
459
+ "white-space": "normal !important",
460
+ "overflow": "visible !important",
461
+ "text-overflow": "clip !important",
462
+ "max-width": "none !important"
463
+ },
464
+ ".steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table tbody td .antd-PlainField, .steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table tbody td .antd-TplField, .steedos-instance-related-view-wrapper .steedos-input-table .antd-Table-table tbody td .antd-Words-field": {
465
+ "white-space": "normal !important",
466
+ "overflow": "visible !important",
467
+ "text-overflow": "clip !important",
468
+ "max-width": "none !important",
469
+ "display": "inline !important"
470
+ },
407
471
  ".steedos-instance-related-view-wrapper .instance-approve-history .antd-Table-table tr td": {
408
472
  "border-bottom": "1px solid #e8e8e8 !important"
473
+ },
474
+ ".antd-Table-content.scroll-end": {
475
+ "direction": "rtl !important"
476
+ },
477
+ ".antd-Table-content.scroll-end table": {
478
+ "direction": "ltr !important"
479
+ },
480
+ ".steedos-instance-related-view-wrapper .table-page-body.form-table > tbody > tr:first-child": {
481
+ "display": "none !important"
482
+ },
483
+ ".steedos-instance-related-view-wrapper .table-page-body.form-table > tbody > tr:nth-child(2) td": {
484
+ "border-top": "none !important"
409
485
  }
410
486
  }
411
487
  },
@@ -415,7 +491,7 @@
415
491
  "actions": [
416
492
  {
417
493
  "actionType": "custom",
418
- "script": "document.querySelectorAll('link[rel=\"stylesheet\"]').forEach(link => { if (link.href.includes('salesforce-lightning-design-system.min.css')) { link.remove(); } }); var styleEl = document.createElement('style'); styleEl.id = 'print-page-orientation'; styleEl.textContent = '@page { size: A4 portrait; }'; document.head.appendChild(styleEl);"
494
+ "script": "document.querySelectorAll('link[rel=\"stylesheet\"]').forEach(link => { if (link.href.includes('salesforce-lightning-design-system.min.css')) { link.remove(); } }); for(var si=0;si<document.styleSheets.length;si++){try{var sh=document.styleSheets[si];if(!sh.href||!sh.href.match(/index-[A-Za-z0-9]+\\.css/))continue;for(var ri=sh.cssRules.length-1;ri>=0;ri--){var sel=sh.cssRules[ri].selectorText||'';if(sel.match(/^::?-webkit-scrollbar/))sh.deleteRule(ri);}}catch(e){}} var styleEl=document.createElement('style'); styleEl.id='print-page-orientation'; styleEl.textContent='@page { size: A4 portrait; }'; document.head.appendChild(styleEl); document.addEventListener('scroll',function(e){var t=e.target;if(t&&t.classList&&t.classList.contains('antd-Table-content')){if(window._isPrinting)return;var sl=t.scrollLeft;var max=t.scrollWidth-t.clientWidth;if(sl>0&&sl>=max-1){t.classList.add('scroll-end');}else{t.classList.remove('scroll-end');}}},true); window.addEventListener('beforeprint',function(){window._isPrinting=true;}); window.addEventListener('afterprint',function(){window._isPrinting=false;});"
419
495
  },
420
496
  {
421
497
  "actionType": "custom",
@@ -52,6 +52,13 @@ router.post('/api/workflow/v2/approve/save', requireAuthentication, afterHook, a
52
52
  });
53
53
  const lang = current_user.locale == 'zh-cn' ? 'zh-CN' : 'en';
54
54
 
55
+ // 传阅(cc)类型:已结束的流程直接返回成功,不做任何操作
56
+ if (current_approve.type === 'cc' && instance.state !== 'pending') {
57
+ return res.status(200).send({
58
+ 'instance': instance
59
+ });
60
+ }
61
+
55
62
  try {
56
63
  await UUFlowManager.isInstancePending(instance, lang);
57
64
  await UUFlowManager.isTraceNotFinished(current_trace);
@@ -185,7 +185,7 @@ router.post('/api/workflow/forward', requireAuthentication, async function (req,
185
185
  })
186
186
 
187
187
  select_to_input_fields.forEach(function (field) {
188
- if (old_values[field.code]) {
188
+ if (old_values[field.code] != null) {
189
189
  new_values[field.code] = old_values[field.code];
190
190
  }
191
191
  })
@@ -200,7 +200,7 @@ router.post('/api/workflow/forward', requireAuthentication, async function (req,
200
200
  }
201
201
  var key = f.code;
202
202
  var old_v = old_values[key];
203
- if (old_v) {
203
+ if (old_v != null) {
204
204
  var fieldOptions = f.options && f.options.split && f.options.split("\n").map(function (n) {
205
205
  var itemSplits = n.split(":");
206
206
  return {
@@ -242,7 +242,7 @@ router.post('/api/workflow/forward', requireAuthentication, async function (req,
242
242
  }
243
243
  var key = f.code;
244
244
  var old_v = old_table_row_values[key];
245
- if (old_v) {
245
+ if (old_v != null) {
246
246
  var fieldOptions = f.options && f.options.split && f.options.split("\n").map(function (n) {
247
247
  var itemSplits = n.split(":");
248
248
  return {
@@ -287,7 +287,7 @@ router.post('/api/workflow/forward', requireAuthentication, async function (req,
287
287
  }
288
288
  var key = field.code;
289
289
  var old_v = old_values[key];
290
- if (old_v) {
290
+ if (old_v != null) {
291
291
  // 校验 单选,多选,下拉框 字段值是否在新表单对应字段的可选值范围内
292
292
  var fieldOptions = field.options && field.options.split && field.options.split("\n").map(function (n) {
293
293
  var itemSplits = n.split(":");
@@ -89,7 +89,7 @@ router.post('/api/workflow/forward_refill', requireAuthentication, async functio
89
89
  table_data = (approve != null ? approve.values[subTable] : void 0) || [];
90
90
  row_data = {};
91
91
  columns.forEach(function (column) {
92
- return row_data[column] = forward_ins_values[column] || "";
92
+ return row_data[column] = forward_ins_values[column] ?? "";
93
93
  });
94
94
  if (row_data && row_data !== {}) {
95
95
  table_data.push(row_data);
@@ -203,7 +203,7 @@ router.post("/api/workflow/v2/instance/forward", requireAuthentication, async fu
203
203
 
204
204
  // Process select to input fields
205
205
  for (const field of select_to_input_fields) {
206
- if (old_values[field.code]) {
206
+ if (old_values[field.code] != null) {
207
207
  new_values[field.code] = old_values[field.code];
208
208
  }
209
209
  }
@@ -218,7 +218,7 @@ router.post("/api/workflow/v2/instance/forward", requireAuthentication, async fu
218
218
  }
219
219
  const key = f.code;
220
220
  let old_v = old_values[key];
221
- if (old_v) {
221
+ if (old_v != null) {
222
222
  const fieldOptions = _.isArray(f.options) ? f.options : f.options?.split("\n").map(n => {
223
223
  const itemSplits = n.split(":");
224
224
  return {
@@ -258,7 +258,7 @@ router.post("/api/workflow/v2/instance/forward", requireAuthentication, async fu
258
258
  }
259
259
  const key = f.code;
260
260
  let old_v = old_table_row_values[key];
261
- if (old_v) {
261
+ if (old_v != null) {
262
262
  const fieldOptions = f.options?.split("\n").map(n => {
263
263
  const itemSplits = n.split(":");
264
264
  return {
@@ -301,7 +301,7 @@ router.post("/api/workflow/v2/instance/forward", requireAuthentication, async fu
301
301
  }
302
302
  const key = field.code;
303
303
  let old_v = old_values[key];
304
- if (old_v) {
304
+ if (old_v != null) {
305
305
  const fieldOptions = _.isArray(field.options) ? field.options : field.options?.split("\n").map(n => {
306
306
  const itemSplits = n.split(":");
307
307
  return {
@@ -69,6 +69,18 @@ router.post('/api/workflow/retrieve', requireAuthentication, async function (req
69
69
  previous_trace = _.find(traces, function (t) {
70
70
  return t._id === previous_trace_id;
71
71
  });
72
+
73
+ // 滑步处理:如果前一步是被跳过的(skipped),沿 previous_trace_ids 向前回溯,
74
+ // 找到用户实际操作过的那个 trace,收集中间所有被跳过的 trace
75
+ var skipped_trace_ids = []; // 记录滑步跳过的中间 trace id
76
+ while (previous_trace && previous_trace.judge === 'skipped' && previous_trace.previous_trace_ids && previous_trace.previous_trace_ids.length > 0) {
77
+ skipped_trace_ids.push(previous_trace._id);
78
+ var prev_id = previous_trace.previous_trace_ids[0];
79
+ previous_trace = _.find(traces, function (t) {
80
+ return t._id === prev_id;
81
+ });
82
+ }
83
+
72
84
  previous_trace_step_id = previous_trace.step;
73
85
  previous_trace_name = previous_trace.name;
74
86
  flow = await UUFlowManager.getFlow(instance.flow);
@@ -76,6 +88,18 @@ router.post('/api/workflow/retrieve', requireAuthentication, async function (req
76
88
  if (previous_step.step_type === "counterSign") {
77
89
  throw new Error('会签不能取回');
78
90
  }
91
+ // 校验当前步骤(下一步)是否已读(取回到填写申请步骤时不受此限制)
92
+ if (previous_step.step_type !== "start") {
93
+ var is_read = false;
94
+ _.each(last_trace.approves, function (ap) {
95
+ if (ap.is_read === true) {
96
+ is_read = true;
97
+ }
98
+ });
99
+ if (is_read) {
100
+ throw new Error('下一步处理人已读,不能取回');
101
+ }
102
+ }
79
103
  // 取回步骤的前一个步骤处理人唯一(即排除掉传阅和转发的approve后,剩余的approve只有一个)并且是当前用户
80
104
  previous_trace_approves = _.filter(previous_trace.approves, function (a) {
81
105
  return a.type !== 'cc' && a.type !== 'distribute' && a.type !== 'forward' && ['approved', 'submitted', 'rejected'].includes(a.judge);
@@ -110,9 +134,12 @@ router.post('/api/workflow/retrieve', requireAuthentication, async function (req
110
134
  let retrieve_appr_id = ''
111
135
 
112
136
 
137
+ // 需要标记为 retrieved 的 trace id 集合:当前步骤 + 滑步跳过的中间步骤
138
+ var traces_to_retrieve = [last_trace_id].concat(skipped_trace_ids);
139
+
113
140
  for (const t of traces) {
114
141
  var current_space_user, current_user_organization, retrieve_appr;
115
- if (t._id === last_trace_id) {
142
+ if (traces_to_retrieve.includes(t._id)) {
116
143
  if (!t.approves) {
117
144
  t.approves = new Array;
118
145
  }
@@ -131,40 +158,44 @@ router.post('/api/workflow/retrieve', requireAuthentication, async function (req
131
158
  finishedApproveIds.push(appr._id)
132
159
  }
133
160
  });
134
- // 在同一trace下插入取回操作者的approve记录
135
- current_space_user = await UUFlowManager.getSpaceUser(space_id, current_user);
136
161
 
137
- current_user_organization = await organizationsCollection.findOne({ _id: current_space_user.organization }, {
138
- projection: {
139
- name: 1,
140
- fullname: 1
141
- }
142
- })
162
+ // 只在最后一个trace(当前步骤)插入取回操作者的approve记录
163
+ if (t._id === last_trace_id) {
164
+ current_space_user = await UUFlowManager.getSpaceUser(space_id, current_user);
165
+
166
+ current_user_organization = await organizationsCollection.findOne({ _id: current_space_user.organization }, {
167
+ projection: {
168
+ name: 1,
169
+ fullname: 1
170
+ }
171
+ })
172
+
173
+ retrieve_appr = new Object;
174
+ retrieve_appr._id = _makeNewID();
175
+ retrieve_appr.instance = instance_id;
176
+ retrieve_appr.trace = t._id;
177
+ retrieve_appr.is_finished = true;
178
+ retrieve_appr.user = current_user;
179
+ retrieve_appr.user_name = current_user_info.name;
180
+ retrieve_appr.handler = current_user;
181
+ retrieve_appr.handler_name = current_user_info.name;
182
+ retrieve_appr.handler_organization = current_space_user.organization;
183
+ retrieve_appr.handler_organization_name = current_user_organization.name;
184
+ retrieve_appr.handler_organization_fullname = current_user_organization.fullname;
185
+ retrieve_appr.start_date = now;
186
+ retrieve_appr.finish_date = now;
187
+ retrieve_appr.due_date = t.due_date;
188
+ retrieve_appr.read_date = now;
189
+ retrieve_appr.judge = "retrieved";
190
+ retrieve_appr.is_read = true;
191
+ retrieve_appr.description = retrieve_comment;
192
+ retrieve_appr.is_error = false;
193
+ retrieve_appr.values = new Object;
194
+ retrieve_appr.cost_time = retrieve_appr.finish_date - retrieve_appr.start_date;
195
+ t.approves.push(retrieve_appr);
196
+ }
143
197
 
144
- retrieve_appr = new Object;
145
- retrieve_appr._id = _makeNewID();
146
- retrieve_appr.instance = instance_id;
147
- retrieve_appr.trace = t._id;
148
- retrieve_appr.is_finished = true;
149
- retrieve_appr.user = current_user;
150
- retrieve_appr.user_name = current_user_info.name;
151
- retrieve_appr.handler = current_user;
152
- retrieve_appr.handler_name = current_user_info.name;
153
- retrieve_appr.handler_organization = current_space_user.organization;
154
- retrieve_appr.handler_organization_name = current_user_organization.name;
155
- retrieve_appr.handler_organization_fullname = current_user_organization.fullname;
156
- retrieve_appr.start_date = now;
157
- retrieve_appr.finish_date = now;
158
- retrieve_appr.due_date = t.due_date;
159
- retrieve_appr.read_date = now;
160
- retrieve_appr.judge = "retrieved";
161
- retrieve_appr.is_read = true;
162
- retrieve_appr.description = retrieve_comment;
163
- retrieve_appr.is_error = false;
164
- retrieve_appr.values = new Object;
165
- retrieve_appr.cost_time = retrieve_appr.finish_date - retrieve_appr.start_date;
166
- t.approves.push(retrieve_appr);
167
- // 更新当前trace记录
198
+ // 更新trace记录
168
199
  t.is_finished = true;
169
200
  t.finish_date = now;
170
201
  t.judge = "retrieved";
@@ -145,6 +145,7 @@ module.exports = {
145
145
  filter.push(['handler', '=', userId]);
146
146
  filter.push(['is_finished', '=', true]);
147
147
  filter.push(['is_latest_approve', '=', true]);
148
+ filter.push(['type', '!=', 'draft']);
148
149
  break;
149
150
  case 'draft':
150
151
  filter.push(['submitter', '=', userId]);
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Socket 重连相关 Bug 测试脚本
3
+ *
4
+ * 测试两个问题:
5
+ * Bug 1: Socket 重连后,badge 数据没变化时仍触发左侧菜单重载(显示 loading)
6
+ * Bug 2: 初始加载时若 socket 已连接,connection-init listener 未注册,
7
+ * 导致重连后不会重新 subscribe,badge 推送完全收不到
8
+ *
9
+ * 使用方式:
10
+ * 1. 在审批中心页面(如 /app/approve_workflow/instance_tasks/...)打开浏览器控制台
11
+ * 2. 粘贴本脚本执行,或通过 MCP Chrome evaluate_script 注入
12
+ * 3. 返回 { bug1, bug2 } 测试结果
13
+ *
14
+ * 预期(修复前):bug1.passed = false, bug2.passed = false
15
+ * 预期(修复后):bug1.passed = true, bug2.passed = true
16
+ */
17
+
18
+ async function testSocketReconnectBugs() {
19
+ const results = {
20
+ bug1: { name: 'Badge 未变化时不应触发菜单重载', passed: false, detail: '' },
21
+ bug2: { name: '重连后应能收到 badge 推送', passed: false, detail: '' },
22
+ };
23
+
24
+ const socket = window.socket;
25
+ if (!socket) {
26
+ results.bug1.detail = results.bug2.detail = 'window.socket 不存在';
27
+ return results;
28
+ }
29
+
30
+ // ======== Bug 1 测试 ========
31
+ // 断开 → 重连 → 等待 badge 事件 → 检查是否触发了 approval-tree-menu:reload
32
+ {
33
+ let menuReloadFired = false;
34
+ let badgeReceived = false;
35
+
36
+ const onMessage = (event) => {
37
+ const msg = event.data;
38
+ if (msg && msg.type === 'approval-tree-menu:reload') {
39
+ menuReloadFired = true;
40
+ }
41
+ };
42
+ window.addEventListener('message', onMessage);
43
+
44
+ const onBadge = () => { badgeReceived = true; };
45
+ socket.on('s:workflow:badge:change', onBadge);
46
+
47
+ // 断开并重连
48
+ socket.disconnect();
49
+ await sleep(500);
50
+ socket.connect();
51
+
52
+ // 等待重连 + 服务端3秒延迟推送 badge + 1秒余量
53
+ await sleep(5000);
54
+
55
+ socket.off('s:workflow:badge:change', onBadge);
56
+ window.removeEventListener('message', onMessage);
57
+
58
+ if (!badgeReceived) {
59
+ // 如果连 badge 事件都没收到,说明 Bug 2 存在,Bug 1 无法独立判断
60
+ results.bug1.detail = '未收到 badge 事件(可能因 Bug 2),无法独立判断 Bug 1';
61
+ results.bug1.passed = null; // 未知
62
+ } else if (menuReloadFired) {
63
+ results.bug1.detail = '重连后 badge 数据未变化,但 approval-tree-menu:reload 被触发了(Bug 存在)';
64
+ results.bug1.passed = false;
65
+ } else {
66
+ results.bug1.detail = '重连后 badge 数据未变化,approval-tree-menu:reload 未触发(正常)';
67
+ results.bug1.passed = true;
68
+ }
69
+ }
70
+
71
+ // ======== Bug 2 测试 ========
72
+ // 再次断开 → 重连 → 检查是否重新 subscribe 并收到 badge 事件
73
+ {
74
+ let badgeReceived = false;
75
+
76
+ const onBadge = () => { badgeReceived = true; };
77
+ socket.on('s:workflow:badge:change', onBadge);
78
+
79
+ socket.disconnect();
80
+ await sleep(500);
81
+ socket.connect();
82
+
83
+ // 等待重连 + 服务端3秒延迟推送 + 1秒余量
84
+ await sleep(5000);
85
+
86
+ socket.off('s:workflow:badge:change', onBadge);
87
+
88
+ if (badgeReceived) {
89
+ results.bug2.detail = '重连后成功收到 badge 推送(正常)';
90
+ results.bug2.passed = true;
91
+ } else {
92
+ results.bug2.detail = '重连后未收到 badge 推送,subscribe 可能丢失(Bug 存在)';
93
+ results.bug2.passed = false;
94
+ }
95
+ }
96
+
97
+ return results;
98
+ }
99
+
100
+ function sleep(ms) {
101
+ return new Promise(resolve => setTimeout(resolve, ms));
102
+ }
103
+
104
+ // 导出给 MCP 调用
105
+ window._testSocketReconnectBugs = testSocketReconnectBugs;
@@ -247,6 +247,18 @@ async function updateForm(formId, form, forms, flows, currentUserId) {
247
247
  }
248
248
  } else {
249
249
  current = ff.current;
250
+ // 即使表单不升级,也要更新关联流程的修改时间和修改人
251
+ let flowCursor = await flowCollection.find({form: formId});
252
+ let flowList = await flowCursor.toArray();
253
+ for (let flow of flowList) {
254
+ await flowCollection.updateOne({_id: flow._id}, {
255
+ $set: {
256
+ 'modified': now,
257
+ 'modified_by': currentUserId
258
+ }
259
+ });
260
+ flows.push(await flowCollection.findOne({_id: flow._id}));
261
+ }
250
262
  }
251
263
 
252
264
  current.modified = now;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos-labs/plugin-workflow",
3
- "version": "3.0.64",
3
+ "version": "3.0.66",
4
4
  "main": "package.service.js",
5
5
  "license": "MIT",
6
6
  "files": [