@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.
Files changed (33) hide show
  1. package/designer/dist/amis-renderer/amis-renderer.js +1 -1
  2. package/designer/dist/assets/{index-0cQynRDB.js → index-D5-hZ3Ut.js} +199 -159
  3. package/designer/dist/index.html +1 -1
  4. package/main/default/manager/instance_tasks_manager.js +36 -32
  5. package/main/default/manager/push_manager.js +63 -63
  6. package/main/default/manager/uuflowManagerForInitApproval.js +192 -98
  7. package/main/default/manager/uuflow_manager.js +31 -32
  8. package/main/default/objectTranslations/instances.en/instances.en.objectTranslation.yml +9 -0
  9. package/main/default/objectTranslations/instances.zh-CN/instances.zh-CN.objectTranslation.yml +9 -0
  10. package/main/default/objects/instance_tasks/buttons/instance_new.button.js +3 -0
  11. package/main/default/objects/instance_tasks/buttons/instance_new.button.yml +1 -1
  12. package/main/default/objects/instances/buttons/instance_cc.button.yml +1 -0
  13. package/main/default/objects/instances/buttons/instance_delete.button.yml +1 -1
  14. package/main/default/objects/instances/buttons/instance_distribute.button.yml +2 -1
  15. package/main/default/objects/instances/buttons/instance_export.button.js +1 -6
  16. package/main/default/objects/instances/buttons/instance_export.button.yml +12 -9
  17. package/main/default/objects/instances/buttons/instance_forward.button.yml +2 -1
  18. package/main/default/objects/instances/buttons/instance_new.button.js +3 -0
  19. package/main/default/objects/instances/buttons/instance_reassign.button.yml +2 -1
  20. package/main/default/objects/instances/buttons/instance_relocate.button.yml +3 -1
  21. package/main/default/objects/instances/buttons/instance_return.button.yml +1 -0
  22. package/main/default/objects/instances/buttons/instance_terminate.button.yml +1 -0
  23. package/main/default/objects/instances/listviews/monitor.listview.yml +13 -0
  24. package/main/default/objects/instances/listviews/outbox.listview.yml +36 -0
  25. package/main/default/routes/api_workflow_instance_terminate.router.js +26 -27
  26. package/main/default/routes/api_workflow_nav.router.js +65 -55
  27. package/main/default/routes/api_workflow_reassign.router.js +20 -17
  28. package/main/default/routes/api_workflow_redirect.router.js +11 -1
  29. package/main/default/routes/api_workflow_relocate.router.js +9 -4
  30. package/package.json +1 -1
  31. package/public/amis-renderer/amis-renderer.js +1 -1
  32. package/src/instance_record_queue.js +142 -12
  33. 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 (['user', 'group'].includes(wField.type) && ['lookup', 'master_detail'].includes(oFieldType)
199
- && (['users', 'organizations'].includes(oField.reference_to) || ('space_users' == oField.reference_to && 'user' == oField.reference_to_field))) {
200
- if (!_.isEmpty(wfValue)) {
201
- if (oField.multiple && wField.is_multiselect) {
202
- value = _.compact(_.pluck(wfValue, 'id'))
203
- } else if (!oField.multiple && !wField.is_multiselect) {
204
- value = wfValue.id
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
- _.each(tr, function (v, k) {
799
- tableFieldMap.forEach(function (tfm) {
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
- newTr[oTdCode] = v;
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
- filters: [
69
- ['handler', '=', userId],
70
- ['is_finished', '=', false],
71
- ['space', '=', spaceId],
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
- filters: [
83
- ['handler', '=', userId],
84
- ['is_finished', '=', false],
85
- ['space', '=', spaceId],
86
- ]
80
+ handler: userId,
81
+ is_finished: false,
82
+ space: spaceId,
87
83
  });
88
84
  badgeValue.workflow = taskCount;
89
85