@steedos-labs/plugin-workflow 3.0.58 → 3.0.60
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/designer/dist/amis-renderer/amis-renderer.js +1 -1
- package/designer/dist/assets/{index-0cQynRDB.js → index-D5-hZ3Ut.js} +199 -159
- package/designer/dist/index.html +1 -1
- package/main/default/manager/instance_tasks_manager.js +36 -32
- package/main/default/manager/push_manager.js +63 -63
- package/main/default/manager/uuflowManagerForInitApproval.js +192 -98
- package/main/default/manager/uuflow_manager.js +31 -32
- package/main/default/objectTranslations/instances.en/instances.en.objectTranslation.yml +9 -0
- package/main/default/objectTranslations/instances.zh-CN/instances.zh-CN.objectTranslation.yml +9 -0
- package/main/default/objects/instance_tasks/buttons/instance_new.button.js +3 -0
- package/main/default/objects/instance_tasks/buttons/instance_new.button.yml +1 -1
- package/main/default/objects/instances/buttons/instance_cc.button.yml +1 -0
- package/main/default/objects/instances/buttons/instance_delete.button.yml +1 -1
- package/main/default/objects/instances/buttons/instance_distribute.button.yml +2 -1
- package/main/default/objects/instances/buttons/instance_export.button.js +1 -6
- package/main/default/objects/instances/buttons/instance_export.button.yml +12 -9
- package/main/default/objects/instances/buttons/instance_forward.button.yml +2 -1
- package/main/default/objects/instances/buttons/instance_new.button.js +3 -0
- package/main/default/objects/instances/buttons/instance_reassign.button.yml +2 -1
- package/main/default/objects/instances/buttons/instance_relocate.button.yml +3 -1
- package/main/default/objects/instances/buttons/instance_return.button.yml +1 -0
- package/main/default/objects/instances/buttons/instance_terminate.button.yml +1 -0
- package/main/default/objects/instances/listviews/monitor.listview.yml +13 -0
- package/main/default/objects/instances/listviews/outbox.listview.yml +36 -0
- package/main/default/routes/api_workflow_instance_terminate.router.js +26 -27
- package/main/default/routes/api_workflow_nav.router.js +65 -55
- package/main/default/routes/api_workflow_reassign.router.js +20 -17
- package/main/default/routes/api_workflow_redirect.router.js +11 -1
- package/main/default/routes/api_workflow_relocate.router.js +9 -4
- package/package.json +1 -1
- package/public/amis-renderer/amis-renderer.js +1 -1
- package/src/instance_record_queue.js +142 -12
- package/src/rests/badgeRecalcExecute.js +7 -11
|
@@ -195,17 +195,132 @@ const getRecordFieldValue = async function (oField, wField, ofValue, wfValue, sp
|
|
|
195
195
|
let value;
|
|
196
196
|
var oFieldType = oField.data_type || oField.type;
|
|
197
197
|
// 表单选人选组字段 至 对象 lookup master_detail类型字段同步
|
|
198
|
-
if (['
|
|
199
|
-
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
198
|
+
if (['lookup', 'master_detail'].includes(oFieldType) && !_.isEmpty(wfValue)) {
|
|
199
|
+
// 检查是否是表单的 member/memberMulti 类型字段(对应对象的 users reference_to)
|
|
200
|
+
if ((wField.type === 'user' || wField.code === 'member' || wField.code === 'memberMulti') &&
|
|
201
|
+
['users', 'space_users'].includes(oField.reference_to)) {
|
|
202
|
+
let referToField = oField.reference_to_field || '_id'
|
|
203
|
+
|
|
204
|
+
// 判断是否是新对象格式:{id, name, ...} 或 [{id, name, ...}]
|
|
205
|
+
let isNewObjectFormat = false;
|
|
206
|
+
if (Array.isArray(wfValue)) {
|
|
207
|
+
// 数组格式:检查第一个元素是否有 id 属性
|
|
208
|
+
isNewObjectFormat = wfValue.length > 0 && typeof wfValue[0] === 'object' && wfValue[0] !== null && wfValue[0].id;
|
|
209
|
+
} else if (typeof wfValue === 'object' && wfValue !== null) {
|
|
210
|
+
// 对象格式:检查是否有 id 属性(不是 _id)
|
|
211
|
+
isNewObjectFormat = wfValue.id || wfValue._id;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (isNewObjectFormat) {
|
|
215
|
+
// 处理新对象格式:{id, name, sort_no, organization, organizations, hr, roles}
|
|
216
|
+
if (Array.isArray(wfValue)) {
|
|
217
|
+
// 多选:数组对象格式
|
|
218
|
+
if (oField.multiple) {
|
|
219
|
+
value = _.compact(_.pluck(wfValue, wfValue[0]?.id ? 'id' : '_id'))
|
|
220
|
+
} else {
|
|
221
|
+
// 单选但是数组:取第一个
|
|
222
|
+
value = wfValue.length > 0 ? (wfValue[0].id || wfValue[0]._id) : null
|
|
223
|
+
}
|
|
224
|
+
} else {
|
|
225
|
+
// 单选:对象格式
|
|
226
|
+
const idValue = wfValue.id || wfValue._id;
|
|
227
|
+
if (oField.multiple) {
|
|
228
|
+
// 多选但是单个对象:包装成数组
|
|
229
|
+
value = idValue ? [idValue] : null;
|
|
230
|
+
} else {
|
|
231
|
+
// 单选对象
|
|
232
|
+
value = referToField === '_id' && wfValue._id ? wfValue._id : (referToField === '_id' ? wfValue.id : wfValue[referToField])
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// 处理字符串格式:直接的 ID 或 ID 字符串(和 lookup 字段一样的值)
|
|
237
|
+
else if (typeof wfValue === 'string') {
|
|
238
|
+
// 字符串:可能是单个 ID 或逗号分隔的 ID 列表
|
|
239
|
+
if (oField.multiple) {
|
|
240
|
+
// 多选:返回原字符串或转换为数组
|
|
241
|
+
value = wfValue.includes(',') ? wfValue.split(',').map(v => v.trim()) : wfValue;
|
|
242
|
+
} else {
|
|
243
|
+
// 单选:返回第一个 ID
|
|
244
|
+
value = wfValue.includes(',') ? wfValue.split(',')[0].trim() : wfValue;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// 处理数组格式:字符串数组
|
|
248
|
+
else if (Array.isArray(wfValue)) {
|
|
249
|
+
// 字符串数组:["user1", "user2"]
|
|
250
|
+
const stringArray = wfValue.filter(v => typeof v === 'string');
|
|
251
|
+
if (stringArray.length > 0) {
|
|
252
|
+
if (oField.multiple) {
|
|
253
|
+
value = stringArray;
|
|
254
|
+
} else {
|
|
255
|
+
value = stringArray[0];
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// 检查是否是表单的 org/orgMulti 类型字段(对应对象的 organizations reference_to)
|
|
261
|
+
else if ((wField.type === 'group' || wField.code === 'org' || wField.code === 'orgMulti') &&
|
|
262
|
+
oField.reference_to === 'organizations') {
|
|
263
|
+
let referToField = oField.reference_to_field || '_id'
|
|
264
|
+
|
|
265
|
+
// 判断是否是新对象格式:{id, name, fullname} 或 [{id, name, fullname}]
|
|
266
|
+
let isNewObjectFormat = false;
|
|
267
|
+
if (Array.isArray(wfValue)) {
|
|
268
|
+
// 数组格式:检查第一个元素是否有 id 属性
|
|
269
|
+
isNewObjectFormat = wfValue.length > 0 && typeof wfValue[0] === 'object' && wfValue[0] !== null && wfValue[0].id;
|
|
270
|
+
} else if (typeof wfValue === 'object' && wfValue !== null) {
|
|
271
|
+
// 对象格式:检查是否有 id 属性(不是 _id)
|
|
272
|
+
isNewObjectFormat = wfValue.id || wfValue._id;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (isNewObjectFormat) {
|
|
276
|
+
// 处理新对象格式:{id, name, fullname}
|
|
277
|
+
if (Array.isArray(wfValue)) {
|
|
278
|
+
// 多选:数组对象格式
|
|
279
|
+
if (oField.multiple) {
|
|
280
|
+
value = _.compact(_.pluck(wfValue, wfValue[0]?.id ? 'id' : '_id'))
|
|
281
|
+
} else {
|
|
282
|
+
// 单选但是数组:取第一个
|
|
283
|
+
value = wfValue.length > 0 ? (wfValue[0].id || wfValue[0]._id) : null
|
|
284
|
+
}
|
|
285
|
+
} else {
|
|
286
|
+
// 单选:对象格式
|
|
287
|
+
const idValue = wfValue.id || wfValue._id;
|
|
288
|
+
if (oField.multiple) {
|
|
289
|
+
// 多选但是单个对象:包装成数组
|
|
290
|
+
value = idValue ? [idValue] : null;
|
|
291
|
+
} else {
|
|
292
|
+
// 单选对象
|
|
293
|
+
value = referToField === '_id' && wfValue._id ? wfValue._id : (referToField === '_id' ? wfValue.id : wfValue[referToField])
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// 处理字符串格式:直接的 ID 或 ID 字符串(和 lookup 字段一样的值)
|
|
298
|
+
else if (typeof wfValue === 'string') {
|
|
299
|
+
// 字符串:可能是单个 ID 或逗号分隔的 ID 列表
|
|
300
|
+
if (oField.multiple) {
|
|
301
|
+
// 多选:返回原字符串或转换为数组
|
|
302
|
+
value = wfValue.includes(',') ? wfValue.split(',').map(v => v.trim()) : wfValue;
|
|
303
|
+
} else {
|
|
304
|
+
// 单选:返回第一个 ID
|
|
305
|
+
value = wfValue.includes(',') ? wfValue.split(',')[0].trim() : wfValue;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// 处理数组格式:字符串数组
|
|
309
|
+
else if (Array.isArray(wfValue)) {
|
|
310
|
+
// 字符串数组:["org1", "org2"]
|
|
311
|
+
const stringArray = wfValue.filter(v => typeof v === 'string');
|
|
312
|
+
if (stringArray.length > 0) {
|
|
313
|
+
if (oField.multiple) {
|
|
314
|
+
value = stringArray;
|
|
315
|
+
} else {
|
|
316
|
+
value = stringArray[0];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
205
319
|
}
|
|
206
320
|
}
|
|
207
321
|
}
|
|
208
322
|
else if (!oField.multiple && ['lookup', 'master_detail'].includes(oFieldType) && _.isString(oField.reference_to) && _.isString(wfValue)) {
|
|
323
|
+
// 当是对象类型的 member/org 字段时,应该已在上面处理了,这里只处理字符串值
|
|
209
324
|
var oCollection = objectql.getObject(oField.reference_to)
|
|
210
325
|
var referObjectNameFieldKey = await getObjectNameFieldKey(oField.reference_to);
|
|
211
326
|
if (oCollection && referObjectNameFieldKey) {
|
|
@@ -793,16 +908,31 @@ InstanceRecordQueue.syncValues = async function (field_map_back, values, ins, ob
|
|
|
793
908
|
for (const tfc of _.uniq(tableFieldCodes)) {
|
|
794
909
|
var c = JSON.parse(tfc);
|
|
795
910
|
obj[c.object_table_field_code] = [];
|
|
911
|
+
const tableFields = objectFields[c.object_table_field_code] && objectFields[c.object_table_field_code].children
|
|
912
|
+
? objectFields[c.object_table_field_code].children
|
|
913
|
+
: [];
|
|
914
|
+
|
|
796
915
|
for (const tr of values[c.workflow_table_field_code]) {
|
|
797
916
|
var newTr = {};
|
|
798
|
-
|
|
799
|
-
|
|
917
|
+
for (const [k, v] of Object.entries(tr)) {
|
|
918
|
+
var matched = false;
|
|
919
|
+
for (const tfm of tableFieldMap) {
|
|
800
920
|
if (tfm.workflow_field == (c.workflow_table_field_code + '.$.' + k)) {
|
|
801
921
|
var oTdCode = tfm.object_field.split('.$.')[1];
|
|
802
|
-
|
|
922
|
+
var oField = _.find(tableFields, f => f.name === oTdCode);
|
|
923
|
+
var wField = getFormField(formFields, k);
|
|
924
|
+
|
|
925
|
+
// 调用 getRecordFieldValue 进行字段值转换,而不是直接赋值
|
|
926
|
+
if (oField && wField) {
|
|
927
|
+
newTr[oTdCode] = await getRecordFieldValue(oField, wField, null, v, spaceId, enableAmisform);
|
|
928
|
+
} else {
|
|
929
|
+
newTr[oTdCode] = v;
|
|
930
|
+
}
|
|
931
|
+
matched = true;
|
|
932
|
+
break;
|
|
803
933
|
}
|
|
804
|
-
}
|
|
805
|
-
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
806
936
|
if (!_.isEmpty(newTr)) {
|
|
807
937
|
obj[c.object_table_field_code].push(newTr);
|
|
808
938
|
}
|
|
@@ -65,12 +65,10 @@ async function recalcUserBadge(userId, dryRun, categoriesCol, spaceUsersCol, opt
|
|
|
65
65
|
if (categoryIds.length === 0) continue;
|
|
66
66
|
|
|
67
67
|
const categoryBadge = await count_instance_tasks({
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
['category', 'in', categoryIds],
|
|
73
|
-
]
|
|
68
|
+
handler: userId,
|
|
69
|
+
is_finished: false,
|
|
70
|
+
space: spaceId,
|
|
71
|
+
category: { $in: categoryIds },
|
|
74
72
|
});
|
|
75
73
|
|
|
76
74
|
badgeValue[appName] = categoryBadge;
|
|
@@ -79,11 +77,9 @@ async function recalcUserBadge(userId, dryRun, categoriesCol, spaceUsersCol, opt
|
|
|
79
77
|
|
|
80
78
|
// 2. Total workflow badge for this space
|
|
81
79
|
const taskCount = await count_instance_tasks({
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
['space', '=', spaceId],
|
|
86
|
-
]
|
|
80
|
+
handler: userId,
|
|
81
|
+
is_finished: false,
|
|
82
|
+
space: spaceId,
|
|
87
83
|
});
|
|
88
84
|
badgeValue.workflow = taskCount;
|
|
89
85
|
|