@steedos-labs/plugin-workflow 3.0.59 → 3.0.61

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 (28) 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-0cQynRDB.js → index-CugibT25.js} +220 -180
  4. package/designer/dist/assets/index-DIAKZCeb.css +1 -0
  5. package/designer/dist/index.html +2 -2
  6. package/main/default/manager/instance_tasks_manager.js +36 -32
  7. package/main/default/manager/push_manager.js +63 -63
  8. package/main/default/manager/uuflowManagerForInitApproval.js +192 -98
  9. package/main/default/manager/uuflow_manager.js +35 -32
  10. package/main/default/objectTranslations/instances.en/instances.en.objectTranslation.yml +9 -0
  11. package/main/default/objectTranslations/instances.zh-CN/instances.zh-CN.objectTranslation.yml +9 -0
  12. package/main/default/objects/instance_tasks/buttons/instance_new.button.yml +1 -1
  13. package/main/default/objects/instances/buttons/instance_export.button.js +1 -6
  14. package/main/default/objects/instances/buttons/instance_export.button.yml +12 -9
  15. package/main/default/objects/instances/buttons/instance_relocate.button.yml +1 -0
  16. package/main/default/objects/instances/listviews/monitor.listview.yml +13 -0
  17. package/main/default/objects/instances/listviews/outbox.listview.yml +36 -0
  18. package/main/default/routes/api_workflow_instance_terminate.router.js +26 -27
  19. package/main/default/routes/api_workflow_nav.router.js +13 -12
  20. package/main/default/routes/api_workflow_reassign.router.js +20 -17
  21. package/main/default/routes/api_workflow_redirect.router.js +11 -1
  22. package/main/default/routes/api_workflow_relocate.router.js +9 -4
  23. package/package.json +1 -1
  24. package/public/amis-renderer/amis-renderer.css +1 -1
  25. package/public/amis-renderer/amis-renderer.js +1 -1
  26. package/src/instance_record_queue.js +231 -27
  27. package/src/rests/badgeRecalcExecute.js +7 -11
  28. package/designer/dist/assets/index-DEEcIiu0.css +0 -1
@@ -23,6 +23,19 @@ filters: !!js/function |
23
23
  });
24
24
  return result.filter;
25
25
  }
26
+ requestAdaptor: |-
27
+ var searchFlow = selfData.__searchable__flow;
28
+ var flowIds = [];
29
+ if (searchFlow) {
30
+ flowIds = Array.isArray(searchFlow) ? searchFlow.slice() : [searchFlow];
31
+ }
32
+ flowIds = flowIds.filter(function(id) { return !!id; });
33
+ try {
34
+ window.postMessage({
35
+ type: 'page.dataProvider.setData',
36
+ data: { monitorExportFlowIds: flowIds.length > 0 ? flowIds : '' }
37
+ }, '*');
38
+ } catch(e) {}
26
39
  sort: [['submit_date','desc']]
27
40
  searchable_fields:
28
41
  - field: flow
@@ -0,0 +1,36 @@
1
+ name: outbox
2
+ label: 已审批
3
+ columns:
4
+ - field: name
5
+ wrap: true
6
+ width: 300
7
+ - submitter_name
8
+ - submit_date
9
+ - flow_name
10
+ - current_step_name
11
+ - modified
12
+ mobile_columns:
13
+ - name
14
+ - flow_name
15
+ - current_step_name
16
+ - submitter_name
17
+ - modified
18
+ filter_scope: space
19
+ filters: !!js/function |
20
+ function(filters, data){
21
+ var result = Steedos.authRequest(`/api/workflow/v2/\${data.listName}/filter?app=\${data.appId}&additionalFilters=\${data.additionalFilters || ""}`, {
22
+ type: 'get', async: false
23
+ });
24
+ return result.filter;
25
+ }
26
+ sort: [['modified','desc']]
27
+ searchable_fields:
28
+ - field: flow
29
+ - field: name
30
+ - field: submitter_name
31
+ - field: applicant_organization_name
32
+ - field: submit_date
33
+ - field: instance_state
34
+ extra_columns:
35
+ - extras
36
+ disableSwitch: true
@@ -24,7 +24,7 @@ router.post("/api/workflow/v2/instance/terminate", requireAuthentication, async
24
24
  try {
25
25
  const userSession = req.user;
26
26
  const { terminate_reason, instance_id } = req.body;
27
-
27
+
28
28
  if (!terminate_reason) {
29
29
  throw new Error("还未填写强制结束申请单的理由,操作失败");
30
30
  }
@@ -67,9 +67,9 @@ router.post("/api/workflow/v2/instance/terminate", requireAuthentication, async
67
67
 
68
68
  // Check permissions
69
69
  const permissions = await PermissionManager.getFlowPermissions(flow_id, current_user);
70
- const hasPermission = permissions.includes("admin") ||
71
- space.admins.includes(current_user) ||
72
- instance.submitter === current_user ||
70
+ const hasPermission = permissions.includes("admin") ||
71
+ space.admins.includes(current_user) ||
72
+ instance.submitter === current_user ||
73
73
  instance.applicant === current_user;
74
74
  if (!hasPermission) {
75
75
  throw new Error("无权终止此申请单");
@@ -147,7 +147,7 @@ router.post("/api/workflow/v2/instance/terminate", requireAuthentication, async
147
147
  const old_inbox_users = instance.inbox_users || [];
148
148
  const old_cc_users = instance.cc_users || [];
149
149
  const old_outbox_users = instance.outbox_users || [];
150
-
150
+
151
151
  const tempUsers = [];
152
152
  instance_trace.approves.forEach(approve => {
153
153
  tempUsers.push(approve.user);
@@ -167,6 +167,7 @@ router.post("/api/workflow/v2/instance/terminate", requireAuthentication, async
167
167
 
168
168
  // Update instance
169
169
  const instancesCollection = await getCollection('instances');
170
+
170
171
  const result = await instancesCollection.updateOne(
171
172
  { _id: instance_id },
172
173
  { $set: setObj }
@@ -178,30 +179,28 @@ router.post("/api/workflow/v2/instance/terminate", requireAuthentication, async
178
179
 
179
180
  // Send notifications
180
181
  const updatedInstance = await UUFlowManager.getInstance(instance_id);
181
- await pushManager.send_instance_notification(
182
- "submit_terminate_applicant",
183
- updatedInstance,
184
- terminate_reason,
185
- current_user_info
186
- );
187
-
188
- // Notify all involved users
182
+
183
+ // Send notifications + webhook (并行)
189
184
  const usersToNotify = _.uniq([...old_inbox_users, ...old_cc_users]);
190
- await Promise.all(
191
- usersToNotify.map(user_id =>
185
+ await Promise.all([
186
+ pushManager.send_instance_notification(
187
+ "submit_terminate_applicant",
188
+ updatedInstance,
189
+ terminate_reason,
190
+ current_user_info
191
+ ),
192
+ ...usersToNotify.map(user_id =>
192
193
  pushManager.send_message_to_specifyUser("terminate_approval", user_id)
194
+ ),
195
+ pushManager.triggerWebhook(
196
+ updatedInstance.flow,
197
+ updatedInstance,
198
+ {},
199
+ "terminate",
200
+ current_user,
201
+ []
193
202
  )
194
- );
195
-
196
- // Trigger webhook
197
- await pushManager.triggerWebhook(
198
- updatedInstance.flow,
199
- updatedInstance,
200
- {},
201
- "terminate",
202
- current_user,
203
- []
204
- );
203
+ ]);
205
204
  }
206
205
 
207
206
  res.status(200).send({});
@@ -213,4 +212,4 @@ router.post("/api/workflow/v2/instance/terminate", requireAuthentication, async
213
212
  }
214
213
  });
215
214
 
216
- exports.default = router;
215
+ exports.default = router;
@@ -329,18 +329,19 @@ router.get('/api/:appId/workflow/nav', requireAuthentication, async function (re
329
329
  "icon": "fa fa-check"
330
330
  });
331
331
 
332
- options.push({
333
- "label": t('monitor', {}, userSession.language),
334
- "icon": "fa fa-eye",
335
- "options":{
336
- "level":1,
337
- "to": `/app/${appId}/instances/view/none?side_object=instances&side_listview_id=monitor&additionalFilters=`,
338
- },
339
- "value": `/app/${appId}/instances/view/none?side_object=instances&side_listview_id=monitor&additionalFilters=`,
340
- "children": monitorResult.schema,
341
- "unfolded": monitorResult.monitorIsUnfolded,
342
- "visible": monitorResult.hasFlowsPer
343
- });
332
+ if (monitorResult.hasFlowsPer) {
333
+ options.push({
334
+ "label": t('monitor', {}, userSession.language),
335
+ "icon": "fa fa-eye",
336
+ "options":{
337
+ "level":1,
338
+ "to": `/app/${appId}/instances/view/none?side_object=instances&side_listview_id=monitor&additionalFilters=`,
339
+ },
340
+ "value": `/app/${appId}/instances/view/none?side_object=instances&side_listview_id=monitor&additionalFilters=`,
341
+ "children": monitorResult.schema,
342
+ "unfolded": monitorResult.monitorIsUnfolded
343
+ });
344
+ }
344
345
 
345
346
  const myfileChildren = [];
346
347
  if (!isWorkflowReadonly) {
@@ -3,7 +3,7 @@
3
3
  * @Date: 2022-12-24 14:38:27
4
4
  * @LastEditors: 孙浩林 sunhaolin@steedos.com
5
5
  * @LastEditTime: 2025-10-08 14:50:07
6
- * @Description:
6
+ * @Description:
7
7
  */
8
8
  'use strict';
9
9
  // @ts-check
@@ -49,10 +49,12 @@ router.post('/api/workflow/reassign', requireAuthentication, async function (req
49
49
  const spaceUsersCollection = await getCollection('space_users');
50
50
  const organizationsCollection = await getCollection('organizations');
51
51
 
52
- for (const instance_from_client of hashData['Instances']) {
52
+ for (const instance_from_client of hashData['Instances']) {
53
53
  var _users, approve_users_handlers, assignee_appr, current_space_user, current_user_organization, i, inbox_users, inbox_users_from_client, ins, instance, instance_id, last_trace, last_trace_from_client, new_inbox_users, not_in_inbox_users, now, permissions, r, reassign_reason, setObj, space, space_id;
54
54
  instance_id = instance_from_client['_id'];
55
+
55
56
  instance = await UUFlowManager.getInstance(instance_id);
57
+
56
58
  space_id = instance.space;
57
59
  // 验证instance为审核中状态
58
60
  await UUFlowManager.isInstancePending(instance);
@@ -66,7 +68,7 @@ router.post('/api/workflow/reassign', requireAuthentication, async function (req
66
68
  }
67
69
  // 验证login user_id对该流程有管理申请单的权限
68
70
  permissions = await PermissionManager.getFlowPermissions(instance.flow, current_user);
69
-
71
+
70
72
  if ((!permissions.includes("admin")) && !is_space_admin) {
71
73
  throw new Error("用户没有对当前流程的管理权限");
72
74
  }
@@ -191,6 +193,7 @@ router.post('/api/workflow/reassign', requireAuthentication, async function (req
191
193
  last_trace.approves.push(new_appr);
192
194
  newApproveIds.push(new_appr._id)
193
195
  };
196
+
194
197
  instance.outbox_users.push(current_user);
195
198
  instance.outbox_users = instance.outbox_users.concat(approve_users_handlers);
196
199
  setObj.outbox_users = _.uniq(instance.outbox_users);
@@ -213,25 +216,25 @@ router.post('/api/workflow/reassign', requireAuthentication, async function (req
213
216
 
214
217
  if (r) {
215
218
  ins = await UUFlowManager.getInstance(instance_id);
216
- // 给被删除的inbox_users 和 当前用户 发送push
217
- await pushManager.send_message_current_user(current_user_info);
218
- for (const user_id of not_in_inbox_users) {
219
- if (user_id !== current_user) {
220
- await pushManager.send_message_to_specifyUser("current_user", user_id);
221
- }
222
- };
219
+
223
220
  // 提取instances.outbox_users数组和填单人、申请人
224
221
  _users = new Array;
225
222
  _users.push(ins.applicant);
226
223
  _users.push(ins.submitter);
227
224
  _users = _.uniq(_users.concat(ins.outbox_users));
228
- for (const user_id of _users) {
229
- await pushManager.send_message_to_specifyUser("current_user", user_id);
230
- };
231
- // 给新加入的inbox_users发送push message
232
- await pushManager.send_instance_notification("reassign_new_inbox_users", ins, reassign_reason, current_user_info);
233
- // 如果已经配置webhook并已激活则触发
234
- await pushManager.triggerWebhook(ins.flow, ins, {}, 'reassign', current_user, ins.inbox_users);
225
+
226
+ // 所有通知+webhook 并行
227
+ await Promise.all([
228
+ pushManager.send_message_current_user(current_user_info),
229
+ ...not_in_inbox_users
230
+ .filter(user_id => user_id !== current_user)
231
+ .map(user_id => pushManager.send_message_to_specifyUser("current_user", user_id)),
232
+ ..._users.map(user_id =>
233
+ pushManager.send_message_to_specifyUser("current_user", user_id)
234
+ ),
235
+ pushManager.send_instance_notification("reassign_new_inbox_users", ins, reassign_reason, current_user_info),
236
+ pushManager.triggerWebhook(ins.flow, ins, {}, 'reassign', current_user, ins.inbox_users)
237
+ ]);
235
238
  }
236
239
  };
237
240
 
@@ -30,7 +30,17 @@ router.get('/api/workflow/instances/redirect/:insId', requireAuthentication, asy
30
30
  if(ins.submitter === userId){
31
31
  redirectUrl = `/app/approve_workflow/instances/view/${insId}?side_object=instance_tasks&side_listview_id=${ins.state === 'completed' ? 'completed' : 'pending'}`
32
32
  }else{
33
- redirectUrl = `/app/approve_workflow/instance_tasks/view/${insId}?side_object=instance_tasks&side_listview_id=outbox`
33
+ const tasks2 = await db.instance_tasks.find({
34
+ instance: insId,
35
+ is_finished: true,
36
+ handler: userId,
37
+ space: spaceId
38
+ }, {_id: 1}).toArray();
39
+ if(tasks2.length > 0){
40
+ redirectUrl = `/app/approve_workflow/instance_tasks/view/${tasks2[0]._id}?side_object=instance_tasks&side_listview_id=outbox`
41
+ }else{
42
+ redirectUrl = `/app/approve_workflow/instances/view/${insId}?side_object=instance_tasks&side_listview_id=outbox`
43
+ }
34
44
  }
35
45
  }
36
46
 
@@ -1,6 +1,6 @@
1
1
  /*
2
- * @Author: sunhaolin@hotoa.com
3
- * @Date: 2022-03-26 10:49:51
2
+ * @Author: sunhaolin@hotoa.com
3
+ * @Date: 2022-03-26 10:49:51
4
4
  * @Last Modified by: sunhaolin@hotoa.com
5
5
  * @Last Modified time: 2022-03-26 10:53:33
6
6
  */
@@ -18,7 +18,7 @@ const afterHook = require('./afterHook');
18
18
  * body {
19
19
  * Instances: [
20
20
  * {
21
- *
21
+ *
22
22
  * }
23
23
  * ]
24
24
  * }
@@ -35,9 +35,12 @@ router.post('/api/workflow/relocate', requireAuthentication, afterHook, async fu
35
35
  const instance_from_client = hashData['Instances'][0];
36
36
  // beforeEnd
37
37
  const insId = instance_from_client._id;
38
+
38
39
  const instanceDoc = (await objectql.getObject('instances').find({ filters: [['_id', '=', insId]], fields: ['flow', 'flow_version'] }))[0];
40
+
39
41
  const flowId = instanceDoc.flow;
40
42
  const flowDoc = await objectql.getObject('flows').findOne(flowId);
43
+
41
44
  const next_step_id = instance_from_client["relocate_next_step"];
42
45
  const next_step = getStep(instanceDoc, flowDoc, next_step_id);
43
46
  const next_step_type = next_step["step_type"];
@@ -46,10 +49,12 @@ router.post('/api/workflow/relocate', requireAuthentication, afterHook, async fu
46
49
  }
47
50
 
48
51
  await UUFlowManager.relocate(instance_from_client, userSession)
52
+
49
53
  // afterEnd
50
54
  if (next_step_type === 'end') {
51
55
  await excuteTriggers({ when: 'afterEnd', userId, flowId, insId });
52
56
  }
57
+
53
58
  res.status(200).send({});
54
59
 
55
60
  } catch (e) {
@@ -58,4 +63,4 @@ router.post('/api/workflow/relocate', requireAuthentication, afterHook, async fu
58
63
  });
59
64
  }
60
65
  });
61
- exports.default = router;
66
+ exports.default = router;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos-labs/plugin-workflow",
3
- "version": "3.0.59",
3
+ "version": "3.0.61",
4
4
  "main": "package.service.js",
5
5
  "license": "MIT",
6
6
  "files": [