@steedos-labs/plugin-workflow 3.0.0-beta.8 → 3.0.0

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 (72) hide show
  1. package/main/default/client/instance.client.js +6 -6
  2. package/main/default/client/object_workflows.client.js +8 -7
  3. package/main/default/manager/import.js +17 -1
  4. package/main/default/manager/push_manager.js +20 -12
  5. package/main/default/manager/uuflowManagerForInitApproval.js +794 -0
  6. package/main/default/manager/uuflow_manager.js +53 -4
  7. package/main/default/manager/workflow_manager.js +1 -1
  8. package/main/default/methods/trace_approve_cc.js +568 -0
  9. package/main/default/objectTranslations/flows.en/flows.en.objectTranslation.yml +19 -0
  10. package/main/default/objectTranslations/flows.zh-CN/flows.zh-CN.objectTranslation.yml +19 -0
  11. package/main/default/objectTranslations/instance_tasks.en/instance_tasks.en.objectTranslation.yml +211 -0
  12. package/main/default/objectTranslations/instance_tasks.zh-CN/instance_tasks.zh-CN.objectTranslation.yml +211 -0
  13. package/main/default/objectTranslations/instances.en/instances.en.objectTranslation.yml +212 -0
  14. package/main/default/objectTranslations/instances.zh-CN/instances.zh-CN.objectTranslation.yml +209 -0
  15. package/main/default/objects/categories.object.yml +1 -0
  16. package/main/default/objects/flows/buttons/del.button.yml +7 -10
  17. package/main/default/objects/flows/buttons/design_form_layout.button.js +5 -2
  18. package/main/default/objects/flows/buttons/distributeAdmin.button.yml +5 -5
  19. package/main/default/objects/flows/buttons/newexport.button.yml +1 -1
  20. package/main/default/objects/flows/buttons/newimport.button.yml +2 -1
  21. package/main/default/objects/flows/flows.object.yml +12 -4
  22. package/main/default/objects/forms/forms.object.yml +39 -0
  23. package/main/default/objects/instance_tasks/buttons/instance_new.button.yml +3 -5
  24. package/main/default/objects/instances/buttons/instance_cc.button.yml +7 -7
  25. package/main/default/objects/instances/buttons/instance_delete.button.yml +2 -2
  26. package/main/default/objects/instances/buttons/instance_delete_many.button.yml +6 -6
  27. package/main/default/objects/instances/buttons/instance_distribute.button.yml +14 -13
  28. package/main/default/objects/instances/buttons/instance_flow_chart.button.yml +1 -1
  29. package/main/default/objects/instances/buttons/instance_forward.button.yml +8 -8
  30. package/main/default/objects/instances/buttons/instance_new.button.yml +3 -5
  31. package/main/default/objects/instances/buttons/instance_reassign.button.yml +1 -16
  32. package/main/default/objects/instances/buttons/instance_related.button.yml +4 -4
  33. package/main/default/objects/instances/buttons/instance_relocate.button.yml +9 -12
  34. package/main/default/objects/instances/buttons/instance_retrieve.button.yml +106 -2
  35. package/main/default/objects/instances/buttons/instance_save.button.yml +3 -9
  36. package/main/default/objects/instances/buttons/instance_submit.button.yml +1 -1
  37. package/main/default/objects/instances/buttons/instance_terminate.button.yml +7 -10
  38. package/main/default/objects/instances/listviews/monitor.listview.yml +0 -1
  39. package/main/default/pages/flowdetail.page.amis.json +9 -9
  40. package/main/default/pages/instance_detail.page.amis.json +3 -3
  41. package/main/default/pages/instance_tasks_detail.page.amis.json +3 -3
  42. package/main/default/pages/instance_tasks_list.page.amis.json +147 -110
  43. package/main/default/pages/instances_list.page.amis.json +146 -110
  44. package/main/default/routes/am.router.js +49 -2
  45. package/main/default/routes/api_cc.router.js +5 -12
  46. package/main/default/routes/api_flow_permission.router.js +7 -2
  47. package/main/default/routes/api_get_object_workflows.router.js +79 -22
  48. package/main/default/routes/api_object_workflow_drafts.router.js +18 -19
  49. package/main/default/routes/api_workflow_chart.router.js +682 -0
  50. package/main/default/routes/api_workflow_engine.router.js +1 -1
  51. package/main/default/routes/api_workflow_instance_return.router.js +164 -167
  52. package/main/default/routes/api_workflow_next_step_users.router.js +13 -8
  53. package/main/default/routes/api_workflow_reassign.router.js +200 -196
  54. package/main/default/routes/api_workflow_relocate.router.js +2 -2
  55. package/main/default/routes/api_workflow_retrieve.router.js +246 -237
  56. package/main/default/routes/export.router.js +5 -4
  57. package/main/default/routes/flow_form_design.ejs +33 -8
  58. package/main/default/routes/flow_form_design.router.js +4 -3
  59. package/main/default/routes/import.router.js +6 -7
  60. package/main/default/services/flows.service.js +1 -1
  61. package/main/default/translations/en.translation.yml +5 -0
  62. package/main/default/translations/zh-CN.translation.yml +2 -1
  63. package/main/default/triggers/amis_form_design.trigger.js +27 -5
  64. package/main/default/triggers/instances.trigger.js +9 -7
  65. package/main/default/utils/designerManager.js +12 -5
  66. package/package.json +4 -4
  67. package/package.service.js +21 -7
  68. package/public/workflow/index.css +4 -0
  69. package/src/instance_record_queue.js +1 -3
  70. package/src/rests/api_workflow_instance_batch_remove.js +4 -3
  71. package/src/webhook_queue.js +283 -0
  72. package/main/default/manager/index.js +0 -23
@@ -1,75 +1,24 @@
1
1
  {
2
2
  "type": "page",
3
- "title": "Welcome to Steedos",
4
3
  "body": [
5
4
  {
6
5
  "type": "service",
7
- "pageGridClassName": "h-full m-0",
6
+ "className": "h-full",
8
7
  "body": [
9
8
  {
10
- "type": "steedos-object-listview",
11
- "objectApiName": "instances",
12
- "columnsTogglable": false,
13
- "filterVisible": true,
14
- "visibleOn": "${!!!flowId}",
15
- "showHeader": true,
16
- "id": "u:d29cef0d1007",
17
- "showDisplayAs": true,
18
- "className": "h-full w-full bg-white",
19
- "hiddenColumnOperation": true,
20
- "formFactor": "LARGE",
21
- "headerToolbarItems": [
22
- {
23
- "type": "button",
24
- "label": "",
25
- "icon": "fa fa-bars",
26
- "className": "bg-white p-2 rounded border-gray-300 text-gray-500",
27
- "align": "right",
28
- "onEvent": {
29
- "click": {
30
- "actions": [
31
- {
32
- "actionType": "custom",
33
- "script": "console.log(event.target);document.querySelector('.instances-customPage').classList.toggle('instances-sidebar-open');if(window.innerWidth < 768){document.querySelector('.isInset').classList.toggle('inset-0')}"
34
- }
35
- ]
36
- }
37
- },
38
- "id": "u:115e270cae4d"
39
- }
40
- ],
41
- "listName": "completed",
42
- "rebuildOn": "${flowId || categoryId}",
43
- "adaptor": "//在列表上加流程表单字段时,group和user需要特殊处理\nif (api.body.self.listName == \"monitor\") {\n _.each(payload.data.rows, function (item, index) {\n if (item.values) {\n const form_fields = api.body.self.form_fields;\n _.each(item.values, function (field, field_code) {\n const form_field = _.find(form_fields, { code: field_code });\n if (form_field && form_field.type == \"group\") {\n if (form_field.is_multiselect) {\n item.values[field_code] = field && field.length > 0 ? _.map(field, 'fullname').toString() : \"\";\n } else {\n item.values[field_code] = field ? field.fullname : \"\";\n }\n } else if (form_field && form_field.type == \"user\") {\n if (form_field.is_multiselect) {\n item.values[field_code] = field && field.length > 0 ? _.map(field, 'name').toString() : \"\";\n } else {\n item.values[field_code] = field ? field.name : \"\";\n }\n }\n })\n }\n })\n}\n",
44
- "crudDataFilter": "if (data && data.flowId && (data.listName == 'inbox' || 'monitor') && window.innerWidth > 768) {\r\n var api = {\r\n url: \"${context.rootUrl}/graphql\",\r\n method: \"post\",\r\n dataType: \"json\",\r\n data: {\r\n \"query\": '{flow: flows__findOne(id:\"' + data.flowId + '\"){form__expand{current}}}'\r\n },\r\n headers: {\r\n Authorization:\r\n \"Bearer ${context.tenantId},${context.authToken}\",\r\n },\r\n };\r\n return env.fetcher(api).then((result) => {\r\n if (result.data && result.data.flow && result.data.flow.form__expand.current.fields && result.data.flow.form__expand.current.fields.length > 0) {\r\n let fields = result.data.flow.form__expand.current.fields;\r\n fields.forEach(function (field) {\r\n if (field.is_list_display) {\r\n crud.columns.push({\r\n \"name\": \"values.\" + field.code,\r\n \"label\": field.name || field.code,\r\n \"width\": \"unset\",\r\n \"type\": \"text\",\r\n \"className\": \" whitespace-nowrap\",\r\n \"static\": true,\r\n \"options\": null\r\n });\r\n }\r\n })\r\n let schemaApiService = data._scoped.parent.getComponentById(\"instances_list_service\");\r\n schemaApiService && schemaApiService.setData({ form_fields: fields, isFlowDataDone: true });\r\n // crud.api.sendOn = \"this.isFlowDataDone\";\r\n }\r\n return crud;\r\n });\r\n} else {\r\n let schemaApiService = data._scoped.parent.getComponentById(\"instances_list_service\");\r\n schemaApiService && schemaApiService.setData({ isFlowDataDone: true });\r\n // crud.api.sendOn = \"this.isFlowDataDone\";\r\n return crud;\r\n}\r\n"
45
- },
46
- {
47
- "type": "service",
48
- "visibleOn": "${!!flowId}",
49
- "schemaApi": {
50
- "url": "/graphql?flowId=${flowId}&categoryId=${categoryId}",
51
- "method": "post",
52
- "data": {
53
- "query": "{flow: flows__findOne(id:\"${flowId}\"){form__expand{current}}}"
54
- },
55
- "adaptor": "const schema = window.SteedosWorkflow.Instance.getListViewSchema(payload.data.flow); return schema;"
56
- }
57
- },
58
- {
59
- "type": "action",
9
+ "type": "wrapper",
10
+ "size": "none",
11
+ "className": "flex flex-1 overflow-hidden h-full",
60
12
  "body": [
61
13
  {
62
- "type": "action",
63
- "className": {
64
- "mobileCss": "${window:innerWidth < 768}",
65
- "pcCss": "${window:innerWidth > 768}",
66
- "instances-sidebar-wrapper px-0 fixed z-20 h-full h-fill ease-in-out duration-300 flex flex-col overflow-y-auto bg-white block -translate-x-0 py-0": "true"
67
- },
14
+ "type": "wrapper",
15
+ "size": "none",
16
+ "className": "instances-sidebar-wrapper flex-shrink-0 min-w-[240px] overflow-y-auto sm:rounded shadow bg-white my-4 ml-4 mr-1 lg:order-first lg:flex lg:flex-col ",
68
17
  "body": [
69
18
  {
70
19
  "type": "service",
71
20
  "id": "u:aa4f4dc5f439",
72
- "className": "w-full h-full border-r",
21
+ "className": "bg-none",
73
22
  "onEvent": {
74
23
  "@data.changed.instances": {
75
24
  "actions": [
@@ -92,7 +41,7 @@
92
41
  "hideRoot": true,
93
42
  "showIcon": true,
94
43
  "initiallyOpen": false,
95
- "value": "${CONCATENATE('/app/', appId, '/', objectName, '/grid/', listViewId, '?additionalFilters=', additionalFilters,'&flowId=',flowId,'&categoryId=',categoryId)}",
44
+ "value": "${value}",
96
45
  "size": "md",
97
46
  "onEvent": {
98
47
  "change": {
@@ -108,7 +57,7 @@
108
57
  },
109
58
  {
110
59
  "actionType": "custom",
111
- "script": "if (window.innerWidth < 768) { document.querySelector('.instances-customPage').classList.remove('instances-sidebar-open'); document.querySelector('.isInset').classList.remove('inset-0') }\n//获取上一次的flowId和categoryId\nconst lastFlowId = event.data.flowId;\nconst lastCategoryId = event.data.categoryId;\n//从value中获取最新的flowId\nvar flowIdRegex = /&flowId=([^&]+)/;\nvar flowIdMatch = event.data.value.match(flowIdRegex);\nconst flowId = flowIdMatch && flowIdMatch.length > 0 ? flowIdMatch[1] : \"\";\n//从value中获取最新的categoryId\nvar categoryIdRegex = /&categoryId=([^&]+)/;\nvar categoryIdMatch = event.data.value.match(categoryIdRegex);\nconst categoryId = categoryIdMatch && categoryIdMatch.length > 0 ? categoryIdMatch[1] : \"\";\n//获取上一次的listname和最新的listname\nconst lastListName = event.data.listName;\nconst listName = event.data.value.split('?')[0].split('instances/grid/')[1];\n//切换流程时清除过滤条件\nif (lastListName == \"monitor\" && listName == \"monitor\" && (flowId != lastFlowId || categoryId != lastCategoryId)) {\n listViewPropsStoreKey = window.location.pathname + \"/crud\";\n sessionStorage.removeItem(listViewPropsStoreKey);\n sessionStorage.removeItem(listViewPropsStoreKey + \"/query\");\n}"
60
+ "script": "if (window.innerWidth < 768) { document.querySelector('.instances-customPage').classList.remove('instances-sidebar-open'); }\n//获取上一次的flowId和categoryId\nconst lastFlowId = event.data.flowId;\nconst lastCategoryId = event.data.categoryId;\n//从value中获取最新的flowId\nvar flowIdRegex = /&flowId=([^&]+)/;\nvar flowIdMatch = event.data.value.match(flowIdRegex);\nconst flowId = flowIdMatch && flowIdMatch.length > 0 ? flowIdMatch[1] : \"\";\n//从value中获取最新的categoryId\nvar categoryIdRegex = /&categoryId=([^&]+)/;\nvar categoryIdMatch = event.data.value.match(categoryIdRegex);\nconst categoryId = categoryIdMatch && categoryIdMatch.length > 0 ? categoryIdMatch[1] : \"\";\n//获取上一次的listname和最新的listname\nconst lastListName = event.data.listName;\nconst listName = event.data.value.split('?')[0].split('instances/grid/')[1];\n//切换流程时清除过滤条件\nif (lastListName == \"monitor\" && listName == \"monitor\" && (flowId != lastFlowId || categoryId != lastCategoryId)) {\n listViewPropsStoreKey = window.location.pathname + \"/crud\";\n sessionStorage.removeItem(listViewPropsStoreKey);\n sessionStorage.removeItem(listViewPropsStoreKey + \"/query\");\n}"
112
61
  },
113
62
  {
114
63
  "actionType": "setValue",
@@ -141,7 +90,8 @@
141
90
  {
142
91
  "type": "tpl",
143
92
  "className": "flex-1 w-6/12",
144
- "tpl": "${label}"
93
+ "tpl": "${label}",
94
+ "id": "u:9dee51f00db4"
145
95
  },
146
96
  {
147
97
  "type": "tpl",
@@ -156,9 +106,11 @@
156
106
  "mode": "text",
157
107
  "text": "${tag | toInt}",
158
108
  "overflowCount": 999
159
- }
109
+ },
110
+ "id": "u:2329cd1fecc2"
160
111
  }
161
- ]
112
+ ],
113
+ "id": "u:545154bcc334"
162
114
  },
163
115
  "unfoldedLevel": 2,
164
116
  "source": "${options}"
@@ -170,29 +122,96 @@
170
122
  "headers": {
171
123
  "Authorization": "Bearer ${context.tenantId},${context.authToken}"
172
124
  },
173
- "messages": {}
125
+ "messages": {},
126
+ "adaptor": "payload.data.value = window.location.pathname + decodeURIComponent(window.location.search); return payload;"
174
127
  },
175
- "messages": {}
128
+ "messages": {},
129
+ "dsType": "api"
176
130
  }
177
- ]
178
- }
179
- ],
180
- "onEvent": {
181
- "click": {
182
- "actions": [
131
+ ],
132
+ "id": "u:fd659f5c3657",
133
+ "isFixedHeight": false,
134
+ "isFixedWidth": false
135
+ },
136
+ {
137
+ "type": "button",
138
+ "className": "instances-sidebar-overlay",
139
+ "id": "u:773b1d00aab2",
140
+ "visibleOn": "${isMobile}",
141
+ "body": [],
142
+ "onEvent": {
143
+ "click": {
144
+ "actions": [
145
+ {
146
+ "actionType": "custom",
147
+ "script": "document.querySelector('.instances-customPage').classList.toggle('instances-sidebar-open');"
148
+ }
149
+ ]
150
+ }
151
+ }
152
+ },
153
+ {
154
+ "type": "wrapper",
155
+ "size": "none",
156
+ "className": "flex-1 focus:outline-none lg:order-last w-96",
157
+ "body": [
183
158
  {
184
- "actionType": "custom",
185
- "script": " if(window.innerWidth < 768){ document.querySelector('.instances-customPage').classList.remove('instances-sidebar-open');document.querySelector('.isInset').classList.remove('inset-0') }"
159
+ "type": "steedos-object-listview",
160
+ "objectApiName": "instances",
161
+ "columnsTogglable": false,
162
+ "filterVisible": true,
163
+ "visibleOn": "${!!!flowId}",
164
+ "showHeader": true,
165
+ "id": "u:d29cef0d1007",
166
+ "showDisplayAs": true,
167
+ "hiddenColumnOperation": true,
168
+ "formFactor": "LARGE",
169
+ "headerToolbarItems": [
170
+ {
171
+ "type": "button",
172
+ "label": "",
173
+ "align": "left",
174
+ "icon": "fa fa-bars",
175
+ "className": "bg-white p-2 rounded border-gray-300 text-gray-500",
176
+ "onEvent": {
177
+ "click": {
178
+ "actions": [
179
+ {
180
+ "actionType": "custom",
181
+ "script": "document.querySelector('.instances-customPage').classList.toggle('instances-sidebar-open');"
182
+ }
183
+ ]
184
+ }
185
+ },
186
+ "id": "u:6f237cc36419"
187
+ }
188
+ ],
189
+ "listName": "completed",
190
+ "rebuildOn": "${flowId || categoryId}",
191
+ "adaptor": "//在列表上加流程表单字段时,group和user需要特殊处理\nif (api.body.self.listName == \"monitor\") {\n _.each(payload.data.rows, function (item, index) {\n if (item.values) {\n const form_fields = api.body.self.form_fields;\n _.each(item.values, function (field, field_code) {\n const form_field = _.find(form_fields, { code: field_code });\n if (form_field && form_field.type == \"group\") {\n if (form_field.is_multiselect) {\n item.values[field_code] = field && field.length > 0 ? _.map(field, 'fullname').toString() : \"\";\n } else {\n item.values[field_code] = field ? field.fullname : \"\";\n }\n } else if (form_field && form_field.type == \"user\") {\n if (form_field.is_multiselect) {\n item.values[field_code] = field && field.length > 0 ? _.map(field, 'name').toString() : \"\";\n } else {\n item.values[field_code] = field ? field.name : \"\";\n }\n }\n })\n }\n })\n}\n",
192
+ "crudDataFilter": "if (data && data.flowId && (data.listName == 'inbox' || 'monitor') && window.innerWidth > 768) {\r\n var api = {\r\n url: \"${context.rootUrl}/graphql\",\r\n method: \"post\",\r\n dataType: \"json\",\r\n data: {\r\n \"query\": '{flow: flows__findOne(id:\"' + data.flowId + '\"){form__expand{current}}}'\r\n },\r\n headers: {\r\n Authorization:\r\n \"Bearer ${context.tenantId},${context.authToken}\",\r\n },\r\n };\r\n return env.fetcher(api).then((result) => {\r\n if (result.data && result.data.flow && result.data.flow.form__expand.current.fields && result.data.flow.form__expand.current.fields.length > 0) {\r\n let fields = result.data.flow.form__expand.current.fields;\r\n fields.forEach(function (field) {\r\n if (field.is_list_display) {\r\n crud.columns.push({\r\n \"name\": \"values.\" + field.code,\r\n \"label\": field.name || field.code,\r\n \"width\": \"unset\",\r\n \"type\": \"text\",\r\n \"className\": \" whitespace-nowrap\",\r\n \"static\": true,\r\n \"options\": null\r\n });\r\n }\r\n })\r\n let schemaApiService = data._scoped.parent.getComponentById(\"instances_list_service\");\r\n schemaApiService && schemaApiService.setData({ form_fields: fields, isFlowDataDone: true });\r\n // crud.api.sendOn = \"this.isFlowDataDone\";\r\n }\r\n return crud;\r\n });\r\n} else {\r\n let schemaApiService = data._scoped.parent.getComponentById(\"instances_list_service\");\r\n schemaApiService && schemaApiService.setData({ isFlowDataDone: true });\r\n // crud.api.sendOn = \"this.isFlowDataDone\";\r\n return crud;\r\n}\r\n"
193
+ },
194
+ {
195
+ "type": "service",
196
+ "visibleOn": "${!!flowId && listName == 'monitor'}",
197
+ "schemaApi": {
198
+ "url": "/graphql?flowId=${flowId}&categoryId=${categoryId}",
199
+ "method": "post",
200
+ "data": {
201
+ "query": "{flow: flows__findOne(id:\"${flowId}\"){form__expand{current}}}"
202
+ },
203
+ "adaptor": "const schema = window.SteedosWorkflow.Instance.getListViewSchema(payload.data.flow); return schema;"
204
+ },
205
+ "id": "u:30c21a4ee7cb",
206
+ "dsType": "api"
186
207
  }
187
- ]
208
+ ],
209
+ "id": "u:ca495ec221e7"
188
210
  }
189
- },
190
- "className": {
191
- "absolute isInset": "true"
192
- }
211
+ ],
212
+ "id": "u:9526a450d59b"
193
213
  }
194
214
  ],
195
- "className": "h-full w-full p-0 m-0",
196
215
  "id": "instances_list_service",
197
216
  "onEvent": {
198
217
  "@data.changed.steedos_keyvalues": {
@@ -211,46 +230,64 @@
211
230
  }
212
231
  },
213
232
  "data": {
233
+ "isMobile": "${window:innerWidth <= 768}",
214
234
  "isFlowDataDone": false
215
- }
235
+ },
236
+ "dsType": "api"
216
237
  }
217
238
  ],
218
239
  "regions": [
219
240
  "body"
220
241
  ],
221
242
  "data": {
222
- "objectName": "instance_tasks",
243
+ "objectName": "instances",
223
244
  "initialValues": {},
224
245
  "title": "",
225
- "context": {
226
- "rootUrl": "http://127.0.0.1:5000",
227
- "tenantId": "644484b7aff6100247b3e6cf",
228
- "userId": "6c017281-b966-49fe-aa2b-f09b835feed7",
229
- "authToken": "ec7b993f86f01162b471f17d9063241beb7c57987a45d40f911e40269ca2e21b8f806cba87de7be1a07c41"
230
- }
246
+ "context": {}
231
247
  },
232
- "id": "u:7e20ab64163e",
248
+ "id": "u:b7167e2fcaf0",
249
+ "name": "page_instances_list",
250
+ "bodyClassName": "p-0",
233
251
  "asideResizor": false,
234
252
  "pullRefresh": {
235
253
  "disabled": true
236
254
  },
237
- "bodyClassName": {
238
- "p-0 instances-customPage instances-sidebar": "true",
239
- "pc instances-sidebar-open instances-minwidth": "${window:innerWidth > 768}"
255
+ "className": {
256
+ "instances-customPage h-full": true,
257
+ "instances-list-mobile": "${window:innerWidth < 768}",
258
+ "instances-list-pc instances-sidebar-open": "${window:innerWidth > 768}"
240
259
  },
260
+ "style": {},
261
+ "dsType": "api",
241
262
  "css": {
242
- ".instances-customPage.instances-sidebar.instances-sidebar-open.pc": {
243
- "margin-left": "240px"
263
+ ".instances-customPage.instances-list-mobile .instances-sidebar-wrapper": {
264
+ "z-index": "601",
265
+ "top": "50px",
266
+ "left": "0px",
267
+ "bottom": "0px",
268
+ "position": "fixed",
269
+ "margin": "0px"
270
+ },
271
+ ".instances-customPage.instances-list-mobile .instances-sidebar-overlay": {
272
+ "z-index": "600",
273
+ "position": "fixed",
274
+ "bottom": "0px",
275
+ "right": "0px",
276
+ "left": "0px",
277
+ "top": "50px",
278
+ "display": "none"
244
279
  },
245
- ".instances-sidebar-wrapper": {
280
+ ".instances-customPage.instances-list-mobile.instances-sidebar-open .instances-sidebar-overlay": {
281
+ "display": "block"
282
+ },
283
+ ".instances-customPage .instances-sidebar-wrapper": {
246
284
  "transition": "0.5s ease transform",
247
285
  "will-change": "transform",
248
286
  "transform": "translate(-100%,0)",
249
287
  "-webkit-transform": "translate(-100%,0)",
250
288
  "-moz-transform": "translate(-100%,0)",
251
289
  "-ms-transform": "translate(-100%,0)",
252
- "-o-transform": "translate(-100%,0)",
253
- "width": "240px"
290
+ "-o-transform": "translate(-100%,0)"
254
291
  },
255
292
  ".instances-customPage.instances-sidebar-open .instances-sidebar-wrapper": {
256
293
  "transform": "translate(0,0)",
@@ -259,20 +296,19 @@
259
296
  "-ms-transform": "translate(0,0)",
260
297
  "-o-transform": "translate(0,0)"
261
298
  },
262
- ".pcCss": {
263
- "top": "90px",
264
- "left": "0px"
265
- },
266
- ".sidebar .pcCss": {
267
- "left": "220px"
268
- },
269
- ".mobileCss": {
270
- "top": "50px",
271
- "left": "0px",
272
- "padding-bottom": "65px"
299
+ ".instances-customPage.instances-list-pc .instances-sidebar-wrapper": {
300
+ "min-width": "0px",
301
+ "width": "0px"
273
302
  },
274
- ".instances-minwidth": {
275
- "min-width": "388px"
303
+ ".instances-customPage.instances-list-pc.instances-sidebar-open .instances-sidebar-wrapper": {
304
+ "min-width": "240px"
305
+ }
306
+ },
307
+ "themeCss": {
308
+ "baseControlClassName": {
309
+ "padding-and-margin:default": {
310
+ "padding": "${displayAs == 'grid'?'':'0px'}"
311
+ }
276
312
  }
277
313
  }
278
314
  }
@@ -3,6 +3,7 @@ const objectql = require("@steedos/objectql");
3
3
  const _ = require('underscore');
4
4
  const bodyParser = require('body-parser');
5
5
  const steedosI18n = require("@steedos/i18n");
6
+ const lodash = require('lodash');
6
7
  const { _makeNewID, getCollection } = require('../utils/collection');
7
8
 
8
9
  const designerManager = require('../utils/designerManager');
@@ -83,6 +84,7 @@ router.get('/am/designer/startup', async function (req, res) {
83
84
  router.post('/am/forms', async function (req, res) {
84
85
  try {
85
86
  let userId = req.user.userId;
87
+ let language = req.user.language;
86
88
  let data = req.body;
87
89
  let formCollection = await getCollection('forms');
88
90
  let flowCollection = await getCollection('flows');
@@ -151,11 +153,56 @@ router.post('/am/forms', async function (req, res) {
151
153
  modified_by: userId,
152
154
  fields: form["current"]["fields"]
153
155
  };
156
+ let amis_schema = null;
154
157
  if (objectName) {
155
158
  current.fields = Object.values(formFields).concat(tables);
159
+ amis_schema = {
160
+ type: 'steedos-flow-form',
161
+ id: "instanceForm",
162
+ name: newForm.name,
163
+ label: newForm.name,
164
+ description: newForm.description,
165
+ className: "steedos-flow-form steedos-flow-layout-page",
166
+ body: []
167
+ }
168
+
169
+ const getFieldEditTpl = async (field) => {
170
+ if(field.steedos_field){
171
+ const config = field.steedos_field;
172
+ if(config.type === 'formula' || config.type === 'summary'){
173
+ if(config.data_type == 'boolean'){
174
+ config.type = "checkbox"
175
+ }else if(config.data_type == 'number' || config.data_type == 'currency' ){
176
+ config.type = 'number'
177
+ }else if(config.data_type == 'percent'){
178
+ config.type = "number"
179
+ }else {
180
+ config.type = config.data_type
181
+ }
182
+ }
183
+ if(config.type === 'autonumber'){
184
+ config.type = "text"
185
+ }
186
+ return {
187
+ type: `sfield-${lodash.toLower(lodash.camelCase(field.steedos_field.type))}`,
188
+ config: config
189
+ }
190
+ }
191
+ }
192
+
193
+ if (current.fields) {
194
+ for (let i = 0; i < current.fields.length; i++) {
195
+ const temp = await getFieldEditTpl(current.fields[i]);
196
+ if (temp) {
197
+ amis_schema.body.push(temp);
198
+ }
199
+ }
200
+ }
156
201
  }
157
202
  newForm.current = current;
158
203
  newForm.historys = [];
204
+ newForm.amis_schema = amis_schema ? JSON.stringify(amis_schema) : amis_schema
205
+ newForm.current.amis_schema = newForm.amis_schema;
159
206
  await objectql.getObject('forms').insert(newForm);
160
207
  const insertedForm = await formCollection.findOne({_id: newForm._id})
161
208
  insertedForms.push(insertedForm);
@@ -181,7 +228,7 @@ router.post('/am/forms', async function (req, res) {
181
228
  name: form["name"],
182
229
  app: form["app"],
183
230
  category: form["category"],
184
- enable_amisform: useAmis
231
+ enable_amisform: false
185
232
  }
186
233
  if (companyId) {
187
234
  flow.company_id = companyId;
@@ -208,7 +255,7 @@ router.post('/am/forms', async function (req, res) {
208
255
  flow.perms = flowPerms;
209
256
  let flow_current = {
210
257
  _id: _makeNewID(),
211
- steps: await designerManager.makeSteps(userId, newForm.current.fields),
258
+ steps: await designerManager.makeSteps(userId, newForm.current.fields, language),
212
259
  _rev: 1,
213
260
  flow: flow._id,
214
261
  form_version: form["current"]["id"],
@@ -1,15 +1,15 @@
1
1
  /*
2
2
  * @Author: baozhoutao@steedos.com
3
3
  * @Date: 2022-09-15 13:09:51
4
- * @LastEditors: baozhoutao@steedos.com
5
- * @LastEditTime: 2023-02-07 18:12:15
4
+ * @LastEditors: 孙浩林 sunhaolin@steedos.com
5
+ * @LastEditTime: 2025-10-03 15:11:56
6
6
  * @Description:
7
7
  */
8
8
  const express = require("express");
9
9
  const router = express.Router();
10
10
  const { requireAuthentication } = require("@steedos/auth");
11
11
  const objectql = require('@steedos/objectql')
12
- const _ = require('lodash');
12
+ const { cc_do } = require('../methods/trace_approve_cc');
13
13
 
14
14
  router.post('/api/workflow/v2/cc_do', requireAuthentication, async function (req, res) {
15
15
  try {
@@ -17,15 +17,8 @@ router.post('/api/workflow/v2/cc_do', requireAuthentication, async function (req
17
17
  const { instanceId, traceId, approveId, usersId, description } = req.body;
18
18
  const approve = await objectql.getSteedosSchema().broker.call('instance.getApprove', {instanceId, traceId, approveId})
19
19
  try {
20
- Meteor.call('cc_do', approve, usersId, description, {userId: userSession.userId}, (error, result)=>{
21
- if(error){
22
- res.status(200).send({
23
- error: error.message
24
- });
25
- }else{
26
- res.status(200).send(result);
27
- }
28
- })
20
+ const result = await cc_do(approve, usersId, description, {userId: userSession.userId})
21
+ res.status(200).send(result);
29
22
  } catch (error) {
30
23
  console.error(error);
31
24
  res.status(200).send({
@@ -1,8 +1,8 @@
1
1
  /*
2
2
  * @Author: baozhoutao@steedos.com
3
3
  * @Date: 2023-03-18 15:05:39
4
- * @LastEditors: baozhoutao@steedos.com
5
- * @LastEditTime: 2023-03-18 15:25:49
4
+ * @LastEditors: 孙浩林 sunhaolin@steedos.com
5
+ * @LastEditTime: 2025-10-08 09:35:17
6
6
  * @Description:
7
7
  */
8
8
  const express = require("express");
@@ -13,9 +13,14 @@ const _ = require('lodash');
13
13
 
14
14
  router.get('/api/workflow/v2/flow_permissions/:flow', requireAuthentication, async function (req, res) {
15
15
  let userSession = req.user;
16
+ const { is_space_admin } = userSession;
16
17
  const { flow } = req.params;
17
18
  try {
18
19
  const permissions = await PermissionManager.getFlowPermissions(flow, userSession.userId);
20
+ // 工作区管理员默认对流程有管理权限
21
+ if (is_space_admin && !_.includes(permissions, 'admin')) {
22
+ permissions.push('admin');
23
+ }
19
24
  res.status(200).send({
20
25
  permissions: permissions
21
26
  })
@@ -8,34 +8,91 @@
8
8
  const express = require("express");
9
9
  const router = express.Router();
10
10
  const { requireAuthentication } = require("@steedos/auth");
11
- const objectql = require('@steedos/objectql')
11
+ const { getCollection } = require('../utils/collection');
12
12
  const _ = require('lodash');
13
- const Fiber = function(fun){console.log('TODO Fiber...')}
14
13
 
15
- router.get('/api/workflow/v2/get_object_workflows', requireAuthentication, async function (req, res) {
16
- try {
17
- let userSession = req.user;
18
- const { spaceId, userId } = userSession;
19
- Fiber(async function () {
20
- try {
21
- Meteor.call('object_workflows.get', spaceId, userId, (error, result)=>{
22
- if(error){
23
- res.status(200).send({
24
- error: error.message
14
+ async function getObjectWorkflows(spaceId, userId) {
15
+ // 参数检查
16
+ if (typeof spaceId !== 'string') {
17
+ throw new Error('spaceId must be a string');
18
+ }
19
+ if (typeof userId !== 'string') {
20
+ throw new Error('userId must be a string');
21
+ }
22
+
23
+ // 获取space_users集合
24
+ const spaceUsersCollection = await getCollection('space_users');
25
+ const curSpaceUser = await spaceUsersCollection.findOne(
26
+ { space: spaceId, user: userId },
27
+ { projection: { organizations: 1 } }
28
+ );
29
+
30
+ if (!curSpaceUser) {
31
+ throw new Error('not-authorized');
32
+ }
33
+
34
+ // 获取organizations集合
35
+ const organizationsCollection = await getCollection('organizations');
36
+ const organizations = await organizationsCollection.find({
37
+ _id: {
38
+ $in: curSpaceUser.organizations
39
+ }
40
+ }, { projection: { parents: 1 } }).toArray();
41
+
42
+ // 获取object_workflows集合
43
+ const objectWorkflowsCollection = await getCollection('object_workflows');
44
+ let ows = await objectWorkflowsCollection.find(
45
+ { space: spaceId },
46
+ { projection: { object_name: 1, flow_id: 1, space: 1, sync_direction: 1 } }
47
+ ).toArray();
48
+
49
+ // 获取flows集合
50
+ const flowsCollection = await getCollection('flows');
51
+
52
+ // 使用Promise.all并行处理每个工作流
53
+ ows = await Promise.all(ows.map(async (o) => {
54
+ const fl = await flowsCollection.findOne(
55
+ { _id: o.flow_id, state: 'enabled' },
56
+ { projection: { name: 1, perms: 1, forbid_initiate_instance: 1 } }
57
+ );
58
+
59
+ if (fl) {
60
+ o.flow_name = fl.name;
61
+ o.can_add = false;
62
+ o.forbid_initiate_instance = fl.forbid_initiate_instance;
63
+
64
+ const perms = fl.perms;
65
+ if (perms) {
66
+ if (perms.users_can_add && perms.users_can_add.includes(userId)) {
67
+ o.can_add = true;
68
+ } else if (perms.orgs_can_add && perms.orgs_can_add.length > 0) {
69
+ if (curSpaceUser && curSpaceUser.organizations &&
70
+ _.intersection(curSpaceUser.organizations, perms.orgs_can_add).length > 0) {
71
+ o.can_add = true;
72
+ } else if (organizations) {
73
+ o.can_add = _.some(organizations, (org) => {
74
+ return org.parents && _.intersection(org.parents, perms.orgs_can_add).length > 0;
25
75
  });
26
- }else{
27
- res.status(200).send(result);
28
76
  }
29
- })
30
- } catch (error) {
31
- console.error(error);
32
- res.status(200).send({
33
- error: error.message
34
- });
77
+ }
35
78
  }
79
+ }
80
+ return o;
81
+ }));
36
82
 
37
- }).run()
38
-
83
+ // 过滤掉没有flow_name的工作流
84
+ ows = ows.filter(n => n.flow_name);
85
+
86
+ return ows;
87
+ }
88
+
89
+
90
+ router.get('/api/workflow/v2/get_object_workflows', requireAuthentication, async function (req, res) {
91
+ try {
92
+ let userSession = req.user;
93
+ const { spaceId, userId } = userSession;
94
+ const result = await getObjectWorkflows(spaceId, userId);
95
+ return res.status(200).send(result);
39
96
  } catch (error) {
40
97
  console.error(error);
41
98
  res.status(200).send({