@steedos-labs/plugin-workflow 3.0.18 → 3.0.19
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/main/default/manager/instance_tasks_manager.js +11 -0
- package/main/default/manager/push_manager.js +4 -1
- package/main/default/manager/uuflow_manager.js +72 -3
- package/main/default/routes/am.router.js +2 -1
- package/main/default/routes/api_workflow_engine.router.js +19 -1
- package/main/default/routes/designer.router.js +26 -0
- package/main/default/utils/designerManager.js +84 -46
- package/package.json +1 -1
- package/public/applications/designer/5410/en-us/javascript-packed.js +1 -1
- package/public/applications/designer/5410/zh-cn/javascript-packed.js +1 -1
- package/public/workflow/index.css +17 -0
- package/src/util/templateConverter.js +2 -1
|
@@ -117,22 +117,30 @@ async function insert_many_instance_tasks(insId, traceId, approveIds) {
|
|
|
117
117
|
* @returns 更新后的instance_tasks
|
|
118
118
|
*/
|
|
119
119
|
async function update_instance_tasks(insId, traceId, approveId, doc) {
|
|
120
|
+
console.time(`update_instance_tasks ${approveId}`);
|
|
120
121
|
let taskDoc = doc
|
|
121
122
|
if (!taskDoc) {
|
|
123
|
+
console.time(`update_instance_tasks_makeTaskDoc ${approveId}`);
|
|
122
124
|
taskDoc = await _makeTaskDoc(insId, traceId, approveId)
|
|
123
125
|
delete taskDoc._id
|
|
126
|
+
console.timeEnd(`update_instance_tasks_makeTaskDoc ${approveId}`);
|
|
124
127
|
}
|
|
128
|
+
console.time(`update_instance_tasks_update ${approveId}`);
|
|
125
129
|
const result = await _update(approveId, taskDoc)
|
|
130
|
+
console.timeEnd(`update_instance_tasks_update ${approveId}`);
|
|
126
131
|
|
|
127
132
|
// 如果任务已完成,更新相关通知为已读
|
|
128
133
|
if (taskDoc.is_finished) {
|
|
134
|
+
console.time(`update_instance_tasks_notifications ${approveId}`);
|
|
129
135
|
const instance = taskDoc.instance || insId
|
|
130
136
|
const handler = taskDoc.handler
|
|
131
137
|
if (instance && handler) {
|
|
132
138
|
await _updateNotificationsAsRead(instance, handler)
|
|
133
139
|
}
|
|
140
|
+
console.timeEnd(`update_instance_tasks_notifications ${approveId}`);
|
|
134
141
|
}
|
|
135
142
|
|
|
143
|
+
console.timeEnd(`update_instance_tasks ${approveId}`);
|
|
136
144
|
return result
|
|
137
145
|
}
|
|
138
146
|
|
|
@@ -265,6 +273,9 @@ async function direct_remove_many_instance_tasks(approveIds) {
|
|
|
265
273
|
* @returns 1
|
|
266
274
|
*/
|
|
267
275
|
async function count_instance_tasks(query) {
|
|
276
|
+
if(process.env.STEEDOS_WORKFLOW_DISABLE_BADGE === 'true'){
|
|
277
|
+
return 0;
|
|
278
|
+
}
|
|
268
279
|
const result = await _count(query)
|
|
269
280
|
return result
|
|
270
281
|
}
|
|
@@ -55,6 +55,9 @@ const settings = require('@steedos/objectql').getSteedosConfig();
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
async function count_instance_tasks(query) {
|
|
58
|
+
if(process.env.STEEDOS_WORKFLOW_DISABLE_BADGE === 'true'){
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
58
61
|
return await getObject('instance_tasks').count(query)
|
|
59
62
|
}
|
|
60
63
|
|
|
@@ -539,7 +542,7 @@ pushManager.send_email_to_SMTP = async function (subject, content, to_user, repl
|
|
|
539
542
|
subject: subject, // 主题
|
|
540
543
|
html: content
|
|
541
544
|
};
|
|
542
|
-
await
|
|
545
|
+
await broker.call('@builder6/email.send', mailOptions)
|
|
543
546
|
|
|
544
547
|
} catch (error) {
|
|
545
548
|
console.error(error.stack);
|
|
@@ -18,7 +18,14 @@ const moment = require('moment')
|
|
|
18
18
|
const { getObject } = require('@steedos/objectql');
|
|
19
19
|
const { evaluate } = require('amis-formula');
|
|
20
20
|
|
|
21
|
-
const UUFlowManager = {
|
|
21
|
+
const UUFlowManager = {
|
|
22
|
+
stats: {
|
|
23
|
+
getFlow: 0,
|
|
24
|
+
getFlowVersion: 0,
|
|
25
|
+
getForm: 0,
|
|
26
|
+
getFormVersion: 0
|
|
27
|
+
}
|
|
28
|
+
};
|
|
22
29
|
|
|
23
30
|
/**
|
|
24
31
|
* Check user authorization
|
|
@@ -158,6 +165,7 @@ UUFlowManager.getSpaceUser = async function (space_id, user_id, options = {}) {
|
|
|
158
165
|
* @throws {Error} If flow not found
|
|
159
166
|
*/
|
|
160
167
|
UUFlowManager.getFlow = async function (flow_id, options = {}) {
|
|
168
|
+
UUFlowManager.stats.getFlow++;
|
|
161
169
|
if (process.env.STEEDOS_DEBUG) {
|
|
162
170
|
const now = new Date().toISOString();
|
|
163
171
|
console.time('UUFlowManager.getFlow' + now);
|
|
@@ -185,6 +193,7 @@ UUFlowManager.getFlow = async function (flow_id, options = {}) {
|
|
|
185
193
|
* @throws {Error} If version not found
|
|
186
194
|
*/
|
|
187
195
|
UUFlowManager.getFlowVersion = function (flow, flow_version) {
|
|
196
|
+
UUFlowManager.stats.getFlowVersion++;
|
|
188
197
|
let flow_v = null;
|
|
189
198
|
|
|
190
199
|
if (flow_version === flow.current._id) {
|
|
@@ -1079,6 +1088,7 @@ UUFlowManager.getUpdatedValues = function (instance, approve_id) {
|
|
|
1079
1088
|
* @throws {Error} If form not found
|
|
1080
1089
|
*/
|
|
1081
1090
|
UUFlowManager.getForm = async function (form_id, options = {}) {
|
|
1091
|
+
UUFlowManager.stats.getForm++;
|
|
1082
1092
|
if (process.env.STEEDOS_DEBUG) {
|
|
1083
1093
|
console.time('UUFlowManager.getForm');
|
|
1084
1094
|
}
|
|
@@ -1105,6 +1115,7 @@ UUFlowManager.getForm = async function (form_id, options = {}) {
|
|
|
1105
1115
|
* @throws {Error} If version not found
|
|
1106
1116
|
*/
|
|
1107
1117
|
UUFlowManager.getFormVersion = function (form, form_version) {
|
|
1118
|
+
UUFlowManager.stats.getFormVersion++;
|
|
1108
1119
|
let form_v = null;
|
|
1109
1120
|
|
|
1110
1121
|
if (form_version === form.current._id) {
|
|
@@ -1292,6 +1303,14 @@ UUFlowManager.getApproveValues = async function (approve_values, permissions, fo
|
|
|
1292
1303
|
* @returns {Object} Updated instance
|
|
1293
1304
|
*/
|
|
1294
1305
|
UUFlowManager.workflow_engine = async function (approve_from_client, current_user_info, current_user, auto_submitted = false) {
|
|
1306
|
+
// Reset stats at the beginning of workflow_engine
|
|
1307
|
+
UUFlowManager.stats = {
|
|
1308
|
+
getFlow: 0,
|
|
1309
|
+
getFlowVersion: 0,
|
|
1310
|
+
getForm: 0,
|
|
1311
|
+
getFormVersion: 0
|
|
1312
|
+
};
|
|
1313
|
+
const t0 = Date.now();
|
|
1295
1314
|
// Extract data from approve_from_client
|
|
1296
1315
|
const {
|
|
1297
1316
|
instance: instance_id,
|
|
@@ -1306,21 +1325,24 @@ UUFlowManager.workflow_engine = async function (approve_from_client, current_use
|
|
|
1306
1325
|
|
|
1307
1326
|
// Get instance, space, flow and related data
|
|
1308
1327
|
const instance = await UUFlowManager.getInstance(instance_id);
|
|
1328
|
+
console.log(`[workflow/engine] [workflow_engine] getInstance took ${Date.now() - t0}ms`);
|
|
1309
1329
|
const space_id = instance.space;
|
|
1310
1330
|
const flow_id = instance.flow;
|
|
1311
|
-
const
|
|
1312
|
-
const applicant_id = instance.applicant;
|
|
1331
|
+
const t1 = Date.now();
|
|
1313
1332
|
const flow = await UUFlowManager.getFlow(flow_id);
|
|
1314
1333
|
const space_user = await UUFlowManager.getSpaceUser(space_id, current_user);
|
|
1315
1334
|
const space_user_org_info = await UUFlowManager.getSpaceUserOrgInfo(space_user);
|
|
1316
1335
|
const trace = await UUFlowManager.getTrace(instance, trace_id);
|
|
1317
1336
|
const approve = await UUFlowManager.getApprove(trace, approve_id);
|
|
1337
|
+
console.log(`[workflow/engine] [workflow_engine] load related data took ${Date.now() - t1}ms`);
|
|
1318
1338
|
|
|
1319
1339
|
// Validate instance state and permissions
|
|
1340
|
+
const t2 = Date.now();
|
|
1320
1341
|
UUFlowManager.isTraceNotFinished(trace);
|
|
1321
1342
|
UUFlowManager.isApproveNotFinished(approve);
|
|
1322
1343
|
UUFlowManager.isInstancePending(instance);
|
|
1323
1344
|
UUFlowManager.isHandlerOrAgent(approve, current_user);
|
|
1345
|
+
console.log(`[workflow/engine] [workflow_engine] validate took ${Date.now() - t2}ms`);
|
|
1324
1346
|
|
|
1325
1347
|
// Get current step info
|
|
1326
1348
|
const step = await UUFlowManager.getStep(instance, flow, trace.step);
|
|
@@ -1332,6 +1354,7 @@ UUFlowManager.workflow_engine = async function (approve_from_client, current_use
|
|
|
1332
1354
|
const setObj = {};
|
|
1333
1355
|
let key_str = "";
|
|
1334
1356
|
|
|
1357
|
+
const t3 = Date.now();
|
|
1335
1358
|
// Find the approve to update
|
|
1336
1359
|
for (let i = 0; i < trace_approves.length; i++) {
|
|
1337
1360
|
if (trace_approves[i]._id === approve_id) {
|
|
@@ -1372,18 +1395,24 @@ UUFlowManager.workflow_engine = async function (approve_from_client, current_use
|
|
|
1372
1395
|
setObj.modified_by = current_user;
|
|
1373
1396
|
|
|
1374
1397
|
// Update instance
|
|
1398
|
+
const t3_1 = Date.now();
|
|
1375
1399
|
const instancesCollection = await getCollection('instances');
|
|
1376
1400
|
await instancesCollection.updateOne(
|
|
1377
1401
|
{ _id: instance_id, "traces._id": trace_id },
|
|
1378
1402
|
{ $set: setObj }
|
|
1379
1403
|
);
|
|
1404
|
+
console.log(`[workflow/engine] [workflow_engine] first updateOne took ${Date.now() - t3_1}ms`);
|
|
1380
1405
|
|
|
1381
1406
|
// Update instance tasks
|
|
1407
|
+
const t3_2 = Date.now();
|
|
1382
1408
|
await update_instance_tasks(instance_id, trace_id, approve_id);
|
|
1409
|
+
console.log(`[workflow/engine] [workflow_engine] first update_instance_tasks took ${Date.now() - t3_2}ms`);
|
|
1383
1410
|
break;
|
|
1384
1411
|
}
|
|
1385
1412
|
}
|
|
1413
|
+
console.log(`[workflow/engine] [workflow_engine] update instance(first part) took ${Date.now() - t3}ms`);
|
|
1386
1414
|
|
|
1415
|
+
const t4 = Date.now();
|
|
1387
1416
|
// Reload instance and revalidate after update
|
|
1388
1417
|
const updatedInstance = await UUFlowManager.getInstance(instance_id);
|
|
1389
1418
|
const updatedTrace = await UUFlowManager.getTrace(updatedInstance, trace_id);
|
|
@@ -1393,6 +1422,7 @@ UUFlowManager.workflow_engine = async function (approve_from_client, current_use
|
|
|
1393
1422
|
UUFlowManager.isApproveNotFinished(updatedApprove);
|
|
1394
1423
|
UUFlowManager.isInstancePending(updatedInstance);
|
|
1395
1424
|
UUFlowManager.isHandlerOrAgent(updatedApprove, current_user);
|
|
1425
|
+
console.log(`[workflow/engine] [workflow_engine] reload and revalidate took ${Date.now() - t4}ms`);
|
|
1396
1426
|
|
|
1397
1427
|
// Prepare final update object
|
|
1398
1428
|
const updateObj = { $set: {} };
|
|
@@ -1406,11 +1436,14 @@ UUFlowManager.workflow_engine = async function (approve_from_client, current_use
|
|
|
1406
1436
|
throw new Error('不能指定多个后续步骤');
|
|
1407
1437
|
}
|
|
1408
1438
|
|
|
1439
|
+
const t5 = Date.now();
|
|
1409
1440
|
// Validate next step users
|
|
1410
1441
|
for (const next_step_user of next_steps[0].users || []) {
|
|
1411
1442
|
await UUFlowManager.getSpaceUser(space_id, next_step_user);
|
|
1412
1443
|
}
|
|
1444
|
+
console.log(`[workflow/engine] [workflow_engine] validate next step users took ${Date.now() - t5}ms`);
|
|
1413
1445
|
|
|
1446
|
+
const t6 = Date.now();
|
|
1414
1447
|
// Handle different step types
|
|
1415
1448
|
if (["start", "submit", "condition"].includes(step_type)) {
|
|
1416
1449
|
Object.assign(updateObj, await UUFlowManager.engine_step_type_is_start_or_submit_or_condition(
|
|
@@ -1433,23 +1466,33 @@ UUFlowManager.workflow_engine = async function (approve_from_client, current_use
|
|
|
1433
1466
|
} else if (step_type === "end") {
|
|
1434
1467
|
throw new Error('end结点出现approve,服务器错误');
|
|
1435
1468
|
}
|
|
1469
|
+
console.log(`[workflow/engine] [workflow_engine] engine_step_type_... took ${Date.now() - t6}ms`);
|
|
1436
1470
|
|
|
1471
|
+
const t7 = Date.now();
|
|
1437
1472
|
// Calculate keywords and extras
|
|
1438
1473
|
const form = await UUFlowManager.getForm(updatedInstance.form);
|
|
1439
1474
|
updateObj.$set.keywords = await UUFlowManager.caculateKeywords(updateObj.$set.values, form, updatedInstance.form_version);
|
|
1440
1475
|
updateObj.$set.extras = await UUFlowManager.caculateExtras(updateObj.$set.values, form, updatedInstance.form_version);
|
|
1476
|
+
console.log(`[workflow/engine] [workflow_engine] caculateKeywords and extras took ${Date.now() - t7}ms`);
|
|
1441
1477
|
|
|
1478
|
+
const t8 = Date.now();
|
|
1442
1479
|
// Update instance
|
|
1480
|
+
const t8_1 = Date.now();
|
|
1443
1481
|
const instancesCollection = await getCollection('instances');
|
|
1444
1482
|
await instancesCollection.updateOne({ _id: instance_id }, updateObj);
|
|
1483
|
+
console.log(`[workflow/engine] [workflow_engine] second updateOne took ${Date.now() - t8_1}ms`);
|
|
1445
1484
|
|
|
1446
1485
|
// Insert new instance tasks if needed
|
|
1447
1486
|
if (updateObj.$push?.traces?.approves) {
|
|
1487
|
+
const t8_2 = Date.now();
|
|
1448
1488
|
const newTrace = updateObj.$push.traces;
|
|
1449
1489
|
const approveIds = newTrace.approves.map(a => a._id);
|
|
1450
1490
|
await insert_many_instance_tasks(instance_id, newTrace._id, approveIds);
|
|
1491
|
+
console.log(`[workflow/engine] [workflow_engine] second insert_many_instance_tasks took ${Date.now() - t8_2}ms`);
|
|
1451
1492
|
}
|
|
1493
|
+
console.log(`[workflow/engine] [workflow_engine] update instance(second part) took ${Date.now() - t8}ms`);
|
|
1452
1494
|
|
|
1495
|
+
const t9 = Date.now();
|
|
1453
1496
|
// Get final updated instance
|
|
1454
1497
|
const finalInstance = await UUFlowManager.getInstance(instance_id);
|
|
1455
1498
|
const finalInstanceTrace = _.find(finalInstance.traces, t => t._id === trace_id);
|
|
@@ -1480,7 +1523,9 @@ UUFlowManager.workflow_engine = async function (approve_from_client, current_use
|
|
|
1480
1523
|
await pushManager.send_instance_notification("submit_pending_inbox", finalInstance, description, current_user_info);
|
|
1481
1524
|
}
|
|
1482
1525
|
}
|
|
1526
|
+
console.log(`[workflow/engine] [workflow_engine] send_instance_notification took ${Date.now() - t9}ms`);
|
|
1483
1527
|
|
|
1528
|
+
const t10 = Date.now();
|
|
1484
1529
|
// Send message to current user and trigger webhook
|
|
1485
1530
|
await pushManager.send_message_current_user(current_user_info);
|
|
1486
1531
|
|
|
@@ -1494,6 +1539,8 @@ UUFlowManager.workflow_engine = async function (approve_from_client, current_use
|
|
|
1494
1539
|
|
|
1495
1540
|
await pushManager.triggerWebhook(flow_id, finalInstance, approve_from_client, 'engine_submit', current_user, to_users);
|
|
1496
1541
|
await UUFlowManager.distributedInstancesRemind(finalInstance);
|
|
1542
|
+
console.log(`[workflow/engine] [workflow_engine] others took ${Date.now() - t10}ms`);
|
|
1543
|
+
console.log(`[workflow/engine] stats: ${JSON.stringify(UUFlowManager.stats)}`);
|
|
1497
1544
|
|
|
1498
1545
|
return finalInstance;
|
|
1499
1546
|
};
|
|
@@ -1519,11 +1566,14 @@ UUFlowManager.engine_step_type_is_start_or_submit_or_condition = async function
|
|
|
1519
1566
|
space_user_org_info, judge, instance, flow, step,
|
|
1520
1567
|
current_user, current_user_info, auto_submitted
|
|
1521
1568
|
) {
|
|
1569
|
+
console.time(`engine_step_type_is_start_or_submit_or_condition ${approve_id}`);
|
|
1522
1570
|
const setObj = {};
|
|
1523
1571
|
const updateObj = {};
|
|
1524
1572
|
const setTraceObj = {};
|
|
1525
1573
|
const space_id = instance.space;
|
|
1526
1574
|
|
|
1575
|
+
console.time(`start_submit_validate_next_step ${approve_id}`);
|
|
1576
|
+
const t0 = Date.now();
|
|
1527
1577
|
// Validate next steps
|
|
1528
1578
|
const nextSteps = await UUFlowManager.getNextSteps(instance, flow, step, "");
|
|
1529
1579
|
for (const approve_next_step of next_steps) {
|
|
@@ -1537,9 +1587,12 @@ UUFlowManager.engine_step_type_is_start_or_submit_or_condition = async function
|
|
|
1537
1587
|
const next_step = await UUFlowManager.getStep(instance, flow, next_step_id);
|
|
1538
1588
|
const next_step_type = next_step.step_type;
|
|
1539
1589
|
const next_step_name = next_step.name;
|
|
1590
|
+
console.log(`[workflow/engine] [step_start_submit] validate and get next step took ${Date.now() - t0}ms`);
|
|
1591
|
+
console.timeEnd(`start_submit_validate_next_step ${approve_id}`);
|
|
1540
1592
|
|
|
1541
1593
|
// Handle end step
|
|
1542
1594
|
if (next_step_type === "end") {
|
|
1595
|
+
console.time(`start_submit_handle_end_step ${approve_id}`);
|
|
1543
1596
|
const instance_traces = instance.traces;
|
|
1544
1597
|
|
|
1545
1598
|
// Update current trace and approve
|
|
@@ -1602,7 +1655,10 @@ UUFlowManager.engine_step_type_is_start_or_submit_or_condition = async function
|
|
|
1602
1655
|
setObj.current_step_name = next_step_name;
|
|
1603
1656
|
setObj.final_decision = 'approved';
|
|
1604
1657
|
setObj.current_step_auto_submit = false;
|
|
1658
|
+
console.timeEnd(`start_submit_handle_end_step ${approve_id}`);
|
|
1605
1659
|
} else {
|
|
1660
|
+
console.time(`start_submit_handle_next_step ${approve_id}`);
|
|
1661
|
+
const t1 = Date.now();
|
|
1606
1662
|
// Handle non-end steps
|
|
1607
1663
|
const next_step_users = next_steps[0].users;
|
|
1608
1664
|
|
|
@@ -1619,6 +1675,7 @@ UUFlowManager.engine_step_type_is_start_or_submit_or_condition = async function
|
|
|
1619
1675
|
if (!UUFlowManager.checkNestStepUsersIsValid(next_step_users, next_user_ids, next_step)) {
|
|
1620
1676
|
throw new Error("指定的下一步处理人有误");
|
|
1621
1677
|
}
|
|
1678
|
+
console.log(`[workflow/engine] [step_start_submit] validate next step users internal took ${Date.now() - t1}ms`);
|
|
1622
1679
|
|
|
1623
1680
|
// Update current trace and approve
|
|
1624
1681
|
const instance_traces = instance.traces;
|
|
@@ -1665,6 +1722,7 @@ UUFlowManager.engine_step_type_is_start_or_submit_or_condition = async function
|
|
|
1665
1722
|
const usersCollection = await getCollection('users');
|
|
1666
1723
|
const spaceUsersCollection = await getCollection('space_users');
|
|
1667
1724
|
|
|
1725
|
+
let tLoop = Date.now();
|
|
1668
1726
|
for (let idx = 0; idx < next_step_users.length; idx++) {
|
|
1669
1727
|
const next_step_user_id = next_step_users[idx];
|
|
1670
1728
|
const user_info = await usersCollection.findOne(
|
|
@@ -1718,6 +1776,7 @@ UUFlowManager.engine_step_type_is_start_or_submit_or_condition = async function
|
|
|
1718
1776
|
UUFlowManager.setRemindInfo(updated_values, newApprove);
|
|
1719
1777
|
newTrace.approves.push(newApprove);
|
|
1720
1778
|
}
|
|
1779
|
+
console.log(`[workflow/engine] [step_start_submit] next_step_users loop took ${Date.now() - tLoop}ms`);
|
|
1721
1780
|
|
|
1722
1781
|
// Prepare instance update
|
|
1723
1782
|
setObj.state = "pending";
|
|
@@ -1739,20 +1798,30 @@ UUFlowManager.engine_step_type_is_start_or_submit_or_condition = async function
|
|
|
1739
1798
|
updateObj.$push = { traces: newTrace };
|
|
1740
1799
|
setObj.current_step_name = next_step_name;
|
|
1741
1800
|
setObj.current_step_auto_submit = await UUFlowManager.getCurrentStepAutoSubmit(flow.timeout_auto_submit, next_step.lines);
|
|
1801
|
+
console.timeEnd(`start_submit_handle_next_step ${approve_id}`);
|
|
1742
1802
|
}
|
|
1743
1803
|
|
|
1744
1804
|
// Apply trace updates
|
|
1805
|
+
console.time(`start_submit_trace_updateOne ${approve_id}`);
|
|
1806
|
+
const t2 = Date.now();
|
|
1745
1807
|
const instancesCollection = await getCollection('instances');
|
|
1746
1808
|
await instancesCollection.updateOne(
|
|
1747
1809
|
{ _id: instance_id },
|
|
1748
1810
|
{ $set: setTraceObj }
|
|
1749
1811
|
);
|
|
1812
|
+
console.log(`[workflow/engine] [step_start_submit] trace updateOne took ${Date.now() - t2}ms`);
|
|
1813
|
+
console.timeEnd(`start_submit_trace_updateOne ${approve_id}`);
|
|
1750
1814
|
|
|
1751
1815
|
// Update instance tasks
|
|
1816
|
+
console.time(`start_submit_update_instance_tasks ${approve_id}`);
|
|
1817
|
+
const t3 = Date.now();
|
|
1752
1818
|
await update_instance_tasks(instance_id, trace_id, approve_id);
|
|
1819
|
+
console.log(`[workflow/engine] [step_start_submit] update_instance_tasks took ${Date.now() - t3}ms`);
|
|
1820
|
+
console.timeEnd(`start_submit_update_instance_tasks ${approve_id}`);
|
|
1753
1821
|
|
|
1754
1822
|
// Combine all updates
|
|
1755
1823
|
updateObj.$set = setObj;
|
|
1824
|
+
console.timeEnd(`engine_step_type_is_start_or_submit_or_condition ${approve_id}`);
|
|
1756
1825
|
return updateObj;
|
|
1757
1826
|
};
|
|
1758
1827
|
|
|
@@ -44,6 +44,7 @@ router.get('/am/designer/startup', async function (req, res) {
|
|
|
44
44
|
let userId = req.user.userId;
|
|
45
45
|
let queryParams = req.query;
|
|
46
46
|
let companyId = queryParams["companyId"];
|
|
47
|
+
let flowId = queryParams["flowId"];
|
|
47
48
|
let isCompanyAdmin = false;
|
|
48
49
|
let spaceIds = [];
|
|
49
50
|
let spaces = [];
|
|
@@ -71,7 +72,7 @@ router.get('/am/designer/startup', async function (req, res) {
|
|
|
71
72
|
spaceIds = _.pluck(spaces, '_id');
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
let changeSet = await designerManager.getByAdminSpaceIds(spaceIds, companyId, isCompanyAdmin)
|
|
75
|
+
let changeSet = await designerManager.getByAdminSpaceIds(spaceIds, companyId, isCompanyAdmin, flowId)
|
|
75
76
|
changeSet['Spaces'] = spaces
|
|
76
77
|
changeSet['sync_token'] = new Date().getTime() / 1000
|
|
77
78
|
res.send(changeSet)
|
|
@@ -54,6 +54,8 @@ const afterHook = require('./afterHook');
|
|
|
54
54
|
* }
|
|
55
55
|
*/
|
|
56
56
|
router.post('/api/workflow/engine', requireAuthentication, afterHook, async function (req, res) {
|
|
57
|
+
const startTime = Date.now();
|
|
58
|
+
console.log(`[workflow/engine] start`);
|
|
57
59
|
try {
|
|
58
60
|
let userSession = req.user;
|
|
59
61
|
const spaceId = userSession.spaceId;
|
|
@@ -66,11 +68,17 @@ router.post('/api/workflow/engine', requireAuthentication, afterHook, async func
|
|
|
66
68
|
|
|
67
69
|
// beforeStepSubmit
|
|
68
70
|
const insId = approve_from_client.instance;
|
|
69
|
-
const
|
|
71
|
+
const t1 = Date.now();
|
|
72
|
+
const instanceDoc = await objectql.getObject('instances').findOne(insId, { fields: ['flow', 'flow_version'] });
|
|
73
|
+
console.log(`[workflow/engine] getObject instances took ${Date.now() - t1}ms`);
|
|
70
74
|
const flowId = instanceDoc.flow;
|
|
75
|
+
const t2 = Date.now();
|
|
71
76
|
await excuteTriggers({ when: 'beforeStepSubmit', userId, flowId, insId });
|
|
77
|
+
console.log(`[workflow/engine] beforeStepSubmit took ${Date.now() - t2}ms`);
|
|
72
78
|
// beforeEnd
|
|
79
|
+
const t3 = Date.now();
|
|
73
80
|
const flowDoc = await objectql.getObject('flows').findOne(flowId);
|
|
81
|
+
console.log(`[workflow/engine] beforeEnd find logic took ${Date.now() - t3}ms`);
|
|
74
82
|
const next_steps = approve_from_client["next_steps"];
|
|
75
83
|
const next_step_id = next_steps[0]["step"];
|
|
76
84
|
const next_step = getStep(instanceDoc, flowDoc, next_step_id);
|
|
@@ -78,17 +86,26 @@ router.post('/api/workflow/engine', requireAuthentication, afterHook, async func
|
|
|
78
86
|
if (next_step_type == "end") {
|
|
79
87
|
await excuteTriggers({ when: 'beforeEnd', userId, flowId, insId });
|
|
80
88
|
}
|
|
89
|
+
console.log(`[workflow/engine] beforeEnd logic took ${Date.now() - t3}ms`);
|
|
81
90
|
|
|
82
91
|
try {
|
|
92
|
+
const t4 = Date.now();
|
|
83
93
|
const instance = await UUFlowManager.workflow_engine(approve_from_client, userSession, userId);
|
|
94
|
+
console.log(`[workflow/engine] workflow_engine took ${Date.now() - t4}ms`);
|
|
84
95
|
// afterStepSubmit
|
|
96
|
+
const t5 = Date.now();
|
|
85
97
|
await excuteTriggers({ when: 'afterStepSubmit', userId, flowId, insId });
|
|
98
|
+
console.log(`[workflow/engine] afterStepSubmit took ${Date.now() - t5}ms`);
|
|
86
99
|
// afterEnd
|
|
87
100
|
if (instance.state === 'completed') {
|
|
101
|
+
const t6 = Date.now();
|
|
88
102
|
await excuteTriggers({ when: 'afterEnd', userId, flowId, insId });
|
|
103
|
+
console.log(`[workflow/engine] afterEnd took ${Date.now() - t6}ms`);
|
|
89
104
|
}
|
|
105
|
+
console.log(`[workflow/engine] total took ${Date.now() - startTime}ms`);
|
|
90
106
|
res.status(200).send({});
|
|
91
107
|
} catch (e) {
|
|
108
|
+
console.log(`[workflow/engine] inner catch total took ${Date.now() - startTime}ms`);
|
|
92
109
|
console.error(e);
|
|
93
110
|
res.status(200).send({
|
|
94
111
|
errors: [{ errorMessage: e.message }]
|
|
@@ -96,6 +113,7 @@ router.post('/api/workflow/engine', requireAuthentication, afterHook, async func
|
|
|
96
113
|
}
|
|
97
114
|
|
|
98
115
|
} catch (e) {
|
|
116
|
+
console.log(`[workflow/engine] outer catch total took ${Date.now() - startTime}ms`);
|
|
99
117
|
res.status(200).send({
|
|
100
118
|
errors: [{ errorMessage: e.message }]
|
|
101
119
|
});
|
|
@@ -137,6 +137,32 @@ var DesignerAPI = {
|
|
|
137
137
|
}
|
|
138
138
|
}, 100);
|
|
139
139
|
|
|
140
|
+
var closeBtnInterval = setInterval(function(){
|
|
141
|
+
var iframeWin = $(self)[0].contentWindow;
|
|
142
|
+
var iframeDoc = iframeWin.document;
|
|
143
|
+
var closeBtn = $(iframeDoc).find(".htv3.designer.square.sc-view.sc-button-view.button.sc-huge-size");
|
|
144
|
+
if(closeBtn.length > 0){
|
|
145
|
+
clearInterval(closeBtnInterval);
|
|
146
|
+
var lastBtn = closeBtn.last()[0];
|
|
147
|
+
|
|
148
|
+
var newBtn = iframeDoc.createElement("div");
|
|
149
|
+
newBtn.setAttribute("role", "button");
|
|
150
|
+
newBtn.className = lastBtn.className;
|
|
151
|
+
newBtn.style.cssText = lastBtn.style.cssText;
|
|
152
|
+
newBtn.innerHTML = '<div class="left"></div><div class="middle"></div><div class="right"></div><label class="sc-button-label sc-huge-size ellipsis">关闭</label>';
|
|
153
|
+
|
|
154
|
+
if(lastBtn.parentNode){
|
|
155
|
+
lastBtn.parentNode.replaceChild(newBtn, lastBtn);
|
|
156
|
+
|
|
157
|
+
newBtn.onclick = function(e){
|
|
158
|
+
e.preventDefault();
|
|
159
|
+
e.stopPropagation();
|
|
160
|
+
window.close();
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}, 100);
|
|
165
|
+
|
|
140
166
|
});
|
|
141
167
|
var designer = {
|
|
142
168
|
urlQuery:function(name){
|
|
@@ -4,82 +4,120 @@ const lodash = require('lodash');
|
|
|
4
4
|
|
|
5
5
|
const { _makeNewID, getCollection } = require('./collection');
|
|
6
6
|
|
|
7
|
-
async function getByAdminSpaceIds(spaceIds, companyId, isCompanyAdmin) {
|
|
7
|
+
async function getByAdminSpaceIds(spaceIds, companyId, isCompanyAdmin, flowId) {
|
|
8
8
|
let filters = _makeInFilters('space', spaceIds);
|
|
9
9
|
let spaceFilters = filters;
|
|
10
10
|
if (isCompanyAdmin && companyId) {
|
|
11
11
|
filters = `(${filters}) and ((company_id eq '${companyId}') or (company_id eq null))`;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
spaceUsers = await getObject('space_users').find({
|
|
13
|
+
|
|
14
|
+
const spaceUsersPromise = getObject('space_users').find({
|
|
17
15
|
filters: spaceFilters,
|
|
18
16
|
fields: ['name', 'email', 'space', 'organization', 'organizations', 'user', 'user_accepted', 'company_id']
|
|
19
17
|
})
|
|
20
|
-
userIds = _.pluck(spaceUsers, 'user');
|
|
21
|
-
|
|
22
|
-
let usersCollection = await getCollection('users');
|
|
23
|
-
let users = await usersCollection.find({
|
|
24
|
-
_id: {
|
|
25
|
-
$in: userIds
|
|
26
|
-
}
|
|
27
|
-
}, {
|
|
28
|
-
fields: {
|
|
29
|
-
'photo': 1,
|
|
30
|
-
'google_id': 1,
|
|
31
|
-
'imo_uid': 1,
|
|
32
|
-
'company': 1,
|
|
33
|
-
'name': 1,
|
|
34
|
-
'locale': 1,
|
|
35
|
-
'steedos_id': 1,
|
|
36
|
-
'primary_email_verified': 1,
|
|
37
|
-
'is_paid_user': 1,
|
|
38
|
-
'mobile': 1,
|
|
39
|
-
'email': 1,
|
|
40
|
-
'created': 1,
|
|
41
|
-
'modified': 1,
|
|
42
|
-
'created_by': 1,
|
|
43
|
-
'modified_by': 1,
|
|
44
|
-
'email_notification': 1,
|
|
45
|
-
'qq_open_id': 1
|
|
46
|
-
}
|
|
47
|
-
}).toArray();
|
|
48
18
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
19
|
+
const usersPromise = spaceUsersPromise.then(async (spaceUsers) => {
|
|
20
|
+
let userIds = _.pluck(spaceUsers, 'user');
|
|
21
|
+
let usersCollection = await getCollection('users');
|
|
22
|
+
return await usersCollection.find({
|
|
23
|
+
_id: {
|
|
24
|
+
$in: userIds
|
|
25
|
+
}
|
|
26
|
+
}, {
|
|
27
|
+
fields: {
|
|
28
|
+
'photo': 1,
|
|
29
|
+
'google_id': 1,
|
|
30
|
+
'imo_uid': 1,
|
|
31
|
+
'company': 1,
|
|
32
|
+
'name': 1,
|
|
33
|
+
'locale': 1,
|
|
34
|
+
'steedos_id': 1,
|
|
35
|
+
'primary_email_verified': 1,
|
|
36
|
+
'is_paid_user': 1,
|
|
37
|
+
'mobile': 1,
|
|
38
|
+
'email': 1,
|
|
39
|
+
'created': 1,
|
|
40
|
+
'modified': 1,
|
|
41
|
+
'created_by': 1,
|
|
42
|
+
'modified_by': 1,
|
|
43
|
+
'email_notification': 1,
|
|
44
|
+
'qq_open_id': 1
|
|
45
|
+
}
|
|
46
|
+
}).toArray();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
let flowsFilters = filters;
|
|
50
|
+
if (flowId) {
|
|
51
|
+
flowsFilters = `(${flowsFilters}) and (_id eq '${flowId}')`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const flowsPromise = getObject('flows').find({
|
|
55
|
+
filters: flowsFilters,
|
|
55
56
|
fields: ['name', 'name_formula', 'code_formula', 'space', 'description', 'is_valid', 'form', 'flowtype', 'state', 'is_deleted', 'created', 'created_by', 'help_text', 'current_no', 'current', 'perms', 'error_message', 'app', 'distribute_optional_users', 'company_id']
|
|
56
57
|
})
|
|
57
|
-
|
|
58
|
+
|
|
59
|
+
let formsPromise;
|
|
60
|
+
if (flowId) {
|
|
61
|
+
formsPromise = flowsPromise.then(async (flows) => {
|
|
62
|
+
let formsFilters = filters;
|
|
63
|
+
if (flows.length > 0) {
|
|
64
|
+
const formIds = _.pluck(flows, 'form');
|
|
65
|
+
if (formIds && formIds.length > 0) {
|
|
66
|
+
formsFilters = `(${formsFilters}) and (_id eq '${formIds[0]}')`
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
formsFilters = `(1 eq 0)`
|
|
70
|
+
}
|
|
71
|
+
return await getObject('forms').find({
|
|
72
|
+
filters: formsFilters,
|
|
73
|
+
fields: ['name', 'state', 'is_deleted', 'is_valid', 'space', 'description', 'help_text', 'created', 'created_by', 'error_message', 'current', 'enable_workflow', 'enable_view_others', 'app', 'category', 'is_subform', 'instance_style', 'company_id']
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
} else {
|
|
77
|
+
formsPromise = getObject('forms').find({
|
|
78
|
+
filters: filters,
|
|
79
|
+
fields: ['name', 'state', 'is_deleted', 'is_valid', 'space', 'description', 'help_text', 'created', 'created_by', 'error_message', 'current', 'enable_workflow', 'enable_view_others', 'app', 'category', 'is_subform', 'instance_style', 'company_id']
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const rolesPromise = getObject('flow_roles').find({
|
|
58
84
|
filters: filters
|
|
59
85
|
});
|
|
60
|
-
|
|
86
|
+
const organizationsPromise = getObject('organizations').find({
|
|
61
87
|
filters: spaceFilters
|
|
62
88
|
});
|
|
63
|
-
|
|
89
|
+
const positionsPromise = getObject('flow_positions').find({
|
|
64
90
|
filters: filters
|
|
65
91
|
});
|
|
66
|
-
|
|
92
|
+
const categoriesPromise = getObject('categories').find({
|
|
67
93
|
filters: _makeInFilters('space', spaceIds)
|
|
68
94
|
});
|
|
69
95
|
|
|
70
|
-
|
|
96
|
+
const hrRolesPromise = getObject('roles').find({
|
|
71
97
|
filters: filters
|
|
72
98
|
})
|
|
73
99
|
|
|
100
|
+
let [spaceUsers, users, forms, flows, organizations, positions, roles, categories, hrRoles] = await Promise.all([
|
|
101
|
+
spaceUsersPromise,
|
|
102
|
+
usersPromise,
|
|
103
|
+
formsPromise,
|
|
104
|
+
flowsPromise,
|
|
105
|
+
organizationsPromise,
|
|
106
|
+
positionsPromise,
|
|
107
|
+
rolesPromise,
|
|
108
|
+
categoriesPromise,
|
|
109
|
+
hrRolesPromise
|
|
110
|
+
]);
|
|
111
|
+
|
|
74
112
|
if (_.isArray(roles)) {
|
|
75
|
-
|
|
113
|
+
await Promise.all(roles.map(async (role) => {
|
|
76
114
|
if (role && role.company_id) {
|
|
77
115
|
let company = await getObject('company').findOne(role.company_id, { fields: ['name'] }) //, 'abbreviation'
|
|
78
116
|
if (company && (company.name || company.abbreviation)) {
|
|
79
117
|
role.name = `${role.name} (${company.abbreviation || company.name})`
|
|
80
118
|
}
|
|
81
119
|
}
|
|
82
|
-
}
|
|
120
|
+
}))
|
|
83
121
|
}
|
|
84
122
|
|
|
85
123
|
return {
|