@steedos-labs/plugin-workflow 3.0.40 → 3.0.42
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.css +1 -1
- package/designer/dist/amis-renderer/amis-renderer.js +1 -1
- package/designer/dist/assets/index-B1eKIobX.css +1 -0
- package/designer/dist/assets/{index-DRUi3eGk.js → index-BsqTuhsm.js} +165 -165
- package/designer/dist/index.html +2 -2
- package/main/default/applications/approve_workflow.app.yml +1 -160
- package/main/default/applications/desktop.app.yml +21 -0
- package/main/default/client/socket.client.js +2 -5
- package/main/default/manager/handlers_manager.js +5 -2
- package/main/default/manager/uuflow_manager.js +6 -0
- package/main/default/manager/workflow_manager.js +5 -1
- package/main/default/objects/instances/buttons/instance_delete.button.yml +7 -1
- package/main/default/objects/instances/buttons/instance_new.button.yml +2 -2
- package/main/default/objects/instances/listviews/monitor.listview.yml +3 -1
- package/main/default/routes/api_auto_number.router.js +8 -2
- package/main/default/routes/api_workflow_nav.router.js +1 -0
- package/main/default/routes/api_workflow_next_step_users.router.js +18 -2
- package/main/default/test/test_badge_draft.js +12 -26
- package/main/default/test/test_badge_update.js +10 -54
- package/package.json +1 -1
- package/public/amis-renderer/amis-renderer.css +1 -1
- package/public/amis-renderer/amis-renderer.js +1 -1
- package/public/workflow/index.css +21 -276
- package/designer/dist/assets/index-BIbXABqz.css +0 -1
package/designer/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/api/workflow/designer-v2/vite.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>designer</title>
|
|
8
|
-
<script type="module" crossorigin src="/api/workflow/designer-v2/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/api/workflow/designer-v2/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/api/workflow/designer-v2/assets/index-BsqTuhsm.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/api/workflow/designer-v2/assets/index-B1eKIobX.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
|
@@ -23,166 +23,7 @@ nav_schema: {
|
|
|
23
23
|
"ignoreNavSchema": true
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
"type": "
|
|
27
|
-
"size": "none",
|
|
28
|
-
"className": "instances-sidebar-wrapper mt-1 bg-white",
|
|
29
|
-
"body": [
|
|
30
|
-
{
|
|
31
|
-
"type": "button",
|
|
32
|
-
"label": "刷新",
|
|
33
|
-
"className": "instance-nav-reload hidden",
|
|
34
|
-
"onEvent": {
|
|
35
|
-
"click": {
|
|
36
|
-
"actions": [
|
|
37
|
-
{
|
|
38
|
-
"actionType": "reload",
|
|
39
|
-
"componentId": "u:instanceNav"
|
|
40
|
-
}
|
|
41
|
-
]
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"type": "button",
|
|
47
|
-
"label": "刷新树",
|
|
48
|
-
"className": "instance-tree-reload hidden",
|
|
49
|
-
"onEvent": {
|
|
50
|
-
"click": {
|
|
51
|
-
"actions": [
|
|
52
|
-
{
|
|
53
|
-
"actionType": "custom",
|
|
54
|
-
"script": "try{ var opts = window.__latestNavOptions; var data = window.__latestNavData; if(!Array.isArray(opts)){ console.log('[tree-reload] no global options'); return; } opts = JSON.parse(JSON.stringify(opts)); var tree = window.__navTreeComponent; if(!tree || !tree.props || !tree.props.formItem){ console.log('[tree-reload] no saved tree ref, trying amisScoped'); var s = window.amisScoped || (document.querySelector('[data-amisScoped]') && document.querySelector('[data-amisScoped]').__amisScoped); if(s){ tree = s.getComponentById('u:instanceNavTree'); } } if(tree && tree.props && tree.props.formItem){ tree.props.formItem.setOptions(opts, undefined, data || {}); console.log('[tree-reload] setOptions done, count:', opts.length); if(tree.forceUpdate){ tree.forceUpdate(); console.log('[tree-reload] forceUpdate called'); } } else { console.log('[tree-reload] FAIL: cannot find tree component'); } }catch(e){ console.warn('[tree-reload error]', e); }"
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
"type": "service",
|
|
62
|
-
"id": "u:instanceNav",
|
|
63
|
-
"className": "bg-white",
|
|
64
|
-
"onEvent": {
|
|
65
|
-
"@data.changed.instances": {
|
|
66
|
-
"actions": [
|
|
67
|
-
{
|
|
68
|
-
"actionType": "reload"
|
|
69
|
-
}
|
|
70
|
-
]
|
|
71
|
-
},
|
|
72
|
-
"fetchInited": {
|
|
73
|
-
"actions": [
|
|
74
|
-
{
|
|
75
|
-
"actionType": "custom",
|
|
76
|
-
"script": "try{ var s = event.context && event.context.scoped; if(!s){ var amisScoped = window.amisScoped || (document.querySelector('[data-amisScoped]') && document.querySelector('[data-amisScoped]').__amisScoped); if(amisScoped){ s = amisScoped; } } if(s){ var tree = s.getComponentById('u:instanceNavTree'); if(tree && tree.props && tree.props.formItem){ window.__navTreeComponent = tree; var opts = event.data && event.data.options; if(Array.isArray(opts)){ opts = JSON.parse(JSON.stringify(opts)); tree.props.formItem.setOptions(opts, undefined, event.data); if(tree.forceUpdate){ setTimeout(function(){ tree.forceUpdate(); }, 100); } } } } var _navComp = s && s.getComponentById('u:instanceNav'); if(_navComp && _navComp.props && _navComp.props.store){ window.__instanceNavStore = _navComp.props.store; } if(!window._instanceNavRouteListenerAdded){ window._instanceNavRouteListenerAdded = true; window._wasOnApproveWorkflow = true; window.addEventListener('message', function(evt){ if(!evt.data || !evt.data.type) return; if(evt.data.type === 'ROUTE_CHANGE'){ var isOnApprove = window.location.pathname.indexOf('/app/approve_workflow') === 0; var wasOn = window._wasOnApproveWorkflow; window._wasOnApproveWorkflow = isOnApprove; if(!isOnApprove) return; var isPop = evt.data.navigationType === 'POP'; if(wasOn && !isPop) return; clearTimeout(window._instanceNavReloadTimer); window._instanceNavReloadTimer = setTimeout(function(){ var _val = window.location.pathname + decodeURIComponent(window.location.search); _val = _val.replace(new RegExp('/view/(?!none)[^?#/]+'), '/view/none'); var opts = window.__latestNavOptions; if(opts){ var _fn = function(o,v){ for(var i=0;i<o.length;i++){ if(o[i].value===v) return v; if(o[i].children){ var f=_fn(o[i].children,v); if(f) return f; } } return null; }; var _fl = function(o,sid,sobj){ for(var i=0;i<o.length;i++){ var v=o[i].value; if(v){ var m1=v.match(/side_listview_id=([^&]*)/); var m2=v.match(/side_object=([^&]*)/); if(m1&&m2&&m1[1]===sid&&m2[1]===sobj) return v; } if(o[i].children){ var f=_fl(o[i].children,sid,sobj); if(f) return f; } } return null; }; if(!_fn(opts,_val)){ var lm=_val.match(/side_listview_id=([^&]*)/); var om=_val.match(/side_object=([^&]*)/); if(lm&&om){ var pm=_fl(opts,lm[1],om[1]); if(pm) _val=pm; } } } var store = window.__instanceNavStore; if(store && store.updateData){ store.updateData({ value: _val, _ts: Date.now() }, undefined, false); } var _tree = window.__navTreeComponent; if(_tree && _tree.props && _tree.props.setPrinstineValue){ _tree.props.setPrinstineValue(_val); } }, 300); } }); } }catch(e){ console.warn('[fetchInited error]', e); }"
|
|
77
|
-
}
|
|
78
|
-
]
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
"body": [
|
|
82
|
-
{
|
|
83
|
-
"type": "input-tree",
|
|
84
|
-
"name": "instanceNavTree",
|
|
85
|
-
"treeContainerClassName": "h-full bg-white",
|
|
86
|
-
"className": "instance-box-tree h-full w-full p-0 bg-white",
|
|
87
|
-
"id": "u:instanceNavTree",
|
|
88
|
-
"stacked": true,
|
|
89
|
-
"multiple": false,
|
|
90
|
-
"enableNodePath": false,
|
|
91
|
-
"hideRoot": true,
|
|
92
|
-
"showIcon": true,
|
|
93
|
-
"initiallyOpen": false,
|
|
94
|
-
"virtualThreshold": 100000,
|
|
95
|
-
"value": "${value}",
|
|
96
|
-
"size": "md",
|
|
97
|
-
"onEvent": {
|
|
98
|
-
"change": {
|
|
99
|
-
"actions": [
|
|
100
|
-
{
|
|
101
|
-
"actionType": "setValue",
|
|
102
|
-
"componentId": "instances_list_service",
|
|
103
|
-
"args": {
|
|
104
|
-
"value": {
|
|
105
|
-
"isFlowDataDone": false
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
"actionType": "custom",
|
|
111
|
-
"script": "//获取上一次的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
|
-
},
|
|
113
|
-
{
|
|
114
|
-
"actionType": "setValue",
|
|
115
|
-
"componentId": "instances_list_service",
|
|
116
|
-
"args": {
|
|
117
|
-
"value": {
|
|
118
|
-
"additionalFilters": [
|
|
119
|
-
"${event.data.options.name}",
|
|
120
|
-
"=",
|
|
121
|
-
"${event.data.options.value}"
|
|
122
|
-
]
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
"expression": "${event.data.options.level>=10}"
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
"args": {
|
|
129
|
-
"link": "${event.data.value}",
|
|
130
|
-
"blank": false
|
|
131
|
-
},
|
|
132
|
-
"actionType": "link"
|
|
133
|
-
}
|
|
134
|
-
]
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
"menuTpl": {
|
|
138
|
-
"type": "wrapper",
|
|
139
|
-
"className": "flex items-center py-1.5 px-3 m-0 rounded-md transition-colors duration-150",
|
|
140
|
-
"body": [
|
|
141
|
-
{
|
|
142
|
-
"type": "tpl",
|
|
143
|
-
"className": "flex-1 leading-6 truncate instance-menu-label",
|
|
144
|
-
"tpl": "${label}",
|
|
145
|
-
"id": "u:9dee51f00db4"
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
"type": "tpl",
|
|
149
|
-
"className": "ml-auto",
|
|
150
|
-
"tpl": "",
|
|
151
|
-
"badge": {
|
|
152
|
-
"className": "h-0",
|
|
153
|
-
"offset": [
|
|
154
|
-
-5,
|
|
155
|
-
0
|
|
156
|
-
],
|
|
157
|
-
"mode": "text",
|
|
158
|
-
"text": "${tag | toInt}",
|
|
159
|
-
"overflowCount": 999
|
|
160
|
-
},
|
|
161
|
-
"id": "u:2329cd1fecc2"
|
|
162
|
-
}
|
|
163
|
-
],
|
|
164
|
-
"id": "u:545154bcc334"
|
|
165
|
-
},
|
|
166
|
-
"unfoldedLevel": 2,
|
|
167
|
-
"source": "${options}"
|
|
168
|
-
}
|
|
169
|
-
],
|
|
170
|
-
"api": {
|
|
171
|
-
"method": "get",
|
|
172
|
-
"url": "${context.rootUrl}/api/${appId}/workflow/nav",
|
|
173
|
-
"headers": {
|
|
174
|
-
"Authorization": "Bearer ${context.tenantId},${context.authToken}"
|
|
175
|
-
},
|
|
176
|
-
"trackExpression": "false",
|
|
177
|
-
"messages": {},
|
|
178
|
-
"adaptor": "var _val = window.location.pathname + decodeURIComponent(window.location.search); _val = _val.replace(new RegExp('/view/(?!none)[^?#/]+'), '/view/none'); console.log('[adaptor] computed value:', _val); function _findNode(opts, val){ for(var i=0;i<opts.length;i++){ if(opts[i].value===val) return opts[i].value; if(opts[i].children){ var f=_findNode(opts[i].children,val); if(f) return f; } } return null; } function _findByListview(opts, sid, sobj){ for(var i=0;i<opts.length;i++){ var v=opts[i].value; if(v){ var m1=v.match(/side_listview_id=([^&]*)/); var m2=v.match(/side_object=([^&]*)/); if(m1&&m2&&m1[1]===sid&&m2[1]===sobj){ return v; } } if(opts[i].children){ var f=_findByListview(opts[i].children,sid,sobj); if(f) return f; } } return null; } if(payload.data.options){ var exactMatch=_findNode(payload.data.options, _val); if(!exactMatch){ console.log('[adaptor] no exact match, trying partial match'); var lm=_val.match(/side_listview_id=([^&]*)/); var om=_val.match(/side_object=([^&]*)/); if(lm&&om){ var partialMatch=_findByListview(payload.data.options, lm[1], om[1]); if(partialMatch){ console.log('[adaptor] partial match found:', partialMatch); _val=partialMatch; } else { console.log('[adaptor] no partial match either, listview='+lm[1]+' object='+om[1]); } } } else { console.log('[adaptor] exact match found'); } } payload.data.value = _val; payload.data._ts = Date.now(); if(payload.data.options){ payload.data.options = JSON.parse(JSON.stringify(payload.data.options)); window.__latestNavOptions = payload.data.options; window.__latestNavData = payload.data; console.log('[adaptor] saved options to global, count:', payload.data.options.length); } return payload;"
|
|
179
|
-
},
|
|
180
|
-
"messages": {},
|
|
181
|
-
"dsType": "api"
|
|
182
|
-
}
|
|
183
|
-
],
|
|
184
|
-
"isFixedHeight": false,
|
|
185
|
-
"isFixedWidth": false
|
|
26
|
+
"type": "approval-tree-menu"
|
|
186
27
|
}
|
|
187
28
|
],
|
|
188
29
|
"isFixedHeight": false,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
code: desktop
|
|
2
|
+
enable_nav_schema: true
|
|
3
|
+
nav_schema: {
|
|
4
|
+
"type": "wrapper",
|
|
5
|
+
"size": "none",
|
|
6
|
+
"body": [
|
|
7
|
+
{
|
|
8
|
+
"type": "steedos-app-menu",
|
|
9
|
+
"stacked": true,
|
|
10
|
+
"appId": "approve_workflow",
|
|
11
|
+
"ignoreNavSchema": true
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"type": "approval-tree-menu",
|
|
15
|
+
"apiUrl": "/api/approve_workflow/workflow/nav",
|
|
16
|
+
"navigateMode": "router"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"isFixedHeight": false,
|
|
20
|
+
"isFixedWidth": false
|
|
21
|
+
}
|
|
@@ -45,11 +45,7 @@ window.waitForThing(window, 'socket').then(()=>{
|
|
|
45
45
|
};
|
|
46
46
|
if (isFirstRun === false && shouldReloadView()) {
|
|
47
47
|
window.$(".list-view-btn-reload").click()
|
|
48
|
-
|
|
49
|
-
clearTimeout(window.__navRetryTimer)
|
|
50
|
-
window.__navReloadTimer = setTimeout(function(){ window.$(".instance-nav-reload").click() }, 500)
|
|
51
|
-
// Retry: reload tree only (no API request) to pick up data already in Service store
|
|
52
|
-
window.__navRetryTimer = setTimeout(function(){ window.$(".instance-tree-reload").click() }, 2000)
|
|
48
|
+
window.postMessage({ type: "approval-tree-menu:reload" }, "*")
|
|
53
49
|
}
|
|
54
50
|
isFirstRun = false;
|
|
55
51
|
});
|
|
@@ -62,6 +58,7 @@ window.waitForThing(window, 'socket').then(()=>{
|
|
|
62
58
|
};
|
|
63
59
|
if (shouldReloadView()) {
|
|
64
60
|
window.$(".list-view-btn-reload").click()
|
|
61
|
+
window.postMessage({ type: "approval-tree-menu:reload" }, "*")
|
|
65
62
|
}
|
|
66
63
|
});
|
|
67
64
|
|
|
@@ -159,7 +159,11 @@ getHandlersManager.getHandlers = async function (instance_id, step_id, login_use
|
|
|
159
159
|
|
|
160
160
|
// 拟稿时, 可以设定后续每个步骤的处理人 #1926
|
|
161
161
|
if (instance.step_approve && !_.isEmpty(instance.step_approve[`${step_id}_options`])) {
|
|
162
|
-
|
|
162
|
+
const res = instance.step_approve[`${step_id}_options`];
|
|
163
|
+
|
|
164
|
+
if(res != null && res.length > 0 && res[0] != null){
|
|
165
|
+
return res;
|
|
166
|
+
}
|
|
163
167
|
}
|
|
164
168
|
|
|
165
169
|
let approve_users = [];
|
|
@@ -195,7 +199,6 @@ getHandlersManager.getHandlers = async function (instance_id, step_id, login_use
|
|
|
195
199
|
current_step = _.find(current_steps, function (step) {
|
|
196
200
|
return step._id === step_id;
|
|
197
201
|
});
|
|
198
|
-
|
|
199
202
|
if (current_step.step_type === "condition") {
|
|
200
203
|
const unfinished_trace = _.find(instance.traces, function (trace) {
|
|
201
204
|
return trace.is_finished === false;
|
|
@@ -1603,6 +1603,12 @@ function isNormalApprove(approve) {
|
|
|
1603
1603
|
* This prevents infinite loops caused by circular flow definitions.
|
|
1604
1604
|
*/
|
|
1605
1605
|
UUFlowManager.handleSkipProcessed = async function (instance_id, flow, maxDepth = 20) {
|
|
1606
|
+
// 环境变量控制是否启用滑步功能,默认启用
|
|
1607
|
+
const skipProcessedEnabled = process.env.WORKFLOW_SKIP_PROCESSED_ENABLED;
|
|
1608
|
+
if (skipProcessedEnabled === 'false' || skipProcessedEnabled === '0') {
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1606
1612
|
if (maxDepth <= 0) {
|
|
1607
1613
|
console.warn('[workflow/engine] [handleSkipProcessed] Max recursion depth reached');
|
|
1608
1614
|
return;
|
|
@@ -415,7 +415,11 @@ WorkflowManager.getFormulaUserObject = async function (spaceId, userId) {
|
|
|
415
415
|
return WorkflowManager.getFormulaUsers(spaceId, userId);
|
|
416
416
|
} else {
|
|
417
417
|
const users = await WorkflowManager.getFormulaUsers(spaceId, [userId]);
|
|
418
|
-
|
|
418
|
+
// console.log(`getFormulaUserObject users`, users)
|
|
419
|
+
return users && users.length > 0 ? users[0] : {
|
|
420
|
+
organization: {},
|
|
421
|
+
hr: {}
|
|
422
|
+
};
|
|
419
423
|
}
|
|
420
424
|
};
|
|
421
425
|
|
|
@@ -29,13 +29,19 @@ amis_schema: |-
|
|
|
29
29
|
"actionType": "custom",
|
|
30
30
|
"script": "SteedosWorkflow.Instance.changed=false; navigate('/app/approve_workflow/instances/view/none?side_object=instances&side_listview_id=draft&additionalFilters=&flowId=&categoryId=')"
|
|
31
31
|
},
|
|
32
|
+
{
|
|
33
|
+
"actionType": "wait",
|
|
34
|
+
"args": {
|
|
35
|
+
"time": 500
|
|
36
|
+
}
|
|
37
|
+
},
|
|
32
38
|
{
|
|
33
39
|
"actionType": "custom",
|
|
34
40
|
"script":"window.$('.list-view-btn-reload').click()"
|
|
35
41
|
},
|
|
36
42
|
{
|
|
37
43
|
"actionType": "custom",
|
|
38
|
-
"script":"window
|
|
44
|
+
"script":"window.postMessage({ type: 'approval-tree-menu:reload' }, '*')"
|
|
39
45
|
}
|
|
40
46
|
],
|
|
41
47
|
"weight": 0
|
|
@@ -68,7 +68,7 @@ amis_schema: |-
|
|
|
68
68
|
{
|
|
69
69
|
"actionType": "wait",
|
|
70
70
|
"args": {
|
|
71
|
-
"time":
|
|
71
|
+
"time": 500
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
74
|
{
|
|
@@ -77,7 +77,7 @@ amis_schema: |-
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
"actionType": "custom",
|
|
80
|
-
"script":"window
|
|
80
|
+
"script":"window.postMessage({ type: 'approval-tree-menu:reload' }, '*')"
|
|
81
81
|
}
|
|
82
82
|
]
|
|
83
83
|
}
|
|
@@ -330,11 +330,17 @@ router.post('/api/workflow/v2/auto_number', requireAuthentication, async functio
|
|
|
330
330
|
// 为每个自动编号字段生成编号
|
|
331
331
|
const result = {};
|
|
332
332
|
const updateObj = {};
|
|
333
|
+
let currentValues = {}
|
|
334
|
+
if(_.isEmpty(currentApprove.values)){
|
|
335
|
+
currentValues = instance.values || {};
|
|
336
|
+
}else{
|
|
337
|
+
currentValues = currentApprove.values;
|
|
338
|
+
}
|
|
333
339
|
|
|
334
340
|
for (const field of autoNumberFields) {
|
|
335
341
|
// 检查字段是否已有值
|
|
336
|
-
if (
|
|
337
|
-
result[field.code] =
|
|
342
|
+
if (currentValues && currentValues[field.code]) {
|
|
343
|
+
result[field.code] = currentValues[field.code];
|
|
338
344
|
continue;
|
|
339
345
|
}
|
|
340
346
|
|
|
@@ -291,6 +291,7 @@ router.get('/api/:appId/workflow/nav', requireAuthentication, async function (re
|
|
|
291
291
|
"label": t('inbox', {}, userSession.language),
|
|
292
292
|
"icon": "fa fa-download",
|
|
293
293
|
"tag":inboxResult.count,
|
|
294
|
+
"unfolded": true,
|
|
294
295
|
"options":{
|
|
295
296
|
"level":1,
|
|
296
297
|
"to": `/app/${appId}/instance_tasks/view/none?side_object=instance_tasks&side_listview_id=inbox&additionalFilters=`
|
|
@@ -262,8 +262,24 @@ router.post('/api/workflow/v2/nextStepUsersValue', requireAuthentication, async
|
|
|
262
262
|
const { instanceId, nextStepId } = req.body;
|
|
263
263
|
|
|
264
264
|
let instance = await UUFlowManager.getInstance(instanceId);
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
|
|
266
|
+
// 优先从最近一次 traces 中查找 nextStepId 对应的处理人
|
|
267
|
+
let newNextUsers = [];
|
|
268
|
+
const traces = instance.traces || [];
|
|
269
|
+
for (let i = traces.length - 1; i >= 0; i--) {
|
|
270
|
+
const trace = traces[i];
|
|
271
|
+
if (trace.step === nextStepId && trace.approves && trace.approves.length > 0) {
|
|
272
|
+
newNextUsers = trace.approves.map(approve => approve.handler);
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// 如果 traces 中没有找到,回退到 step_approve
|
|
278
|
+
if (newNextUsers.length === 0) {
|
|
279
|
+
const step_approve = instance.step_approve || {};
|
|
280
|
+
newNextUsers = step_approve[nextStepId] || [];
|
|
281
|
+
}
|
|
282
|
+
|
|
267
283
|
res.status(200).send({
|
|
268
284
|
'value': newNextUsers,
|
|
269
285
|
'error': error
|
|
@@ -12,11 +12,9 @@
|
|
|
12
12
|
const origLog = console.log;
|
|
13
13
|
|
|
14
14
|
// ---- 前置检查 ----
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (!navBtn || !treeBtn || !treeEl) {
|
|
19
|
-
console.error('缺少必要 DOM 元素'); return;
|
|
15
|
+
const menuEl = document.querySelector('.approval-tree-menu');
|
|
16
|
+
if (!menuEl) {
|
|
17
|
+
console.error('❌ 未找到 .approval-tree-menu 组件'); return;
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
let baseDraft = null;
|
|
@@ -92,26 +90,16 @@
|
|
|
92
90
|
function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
|
|
93
91
|
|
|
94
92
|
function getAllBadges() {
|
|
95
|
-
|
|
96
|
-
for (var s of sels) { var e = treeEl.querySelectorAll(s); if (e.length) return e; }
|
|
97
|
-
return [];
|
|
93
|
+
return menuEl.querySelectorAll('.ant-badge-count');
|
|
98
94
|
}
|
|
99
95
|
|
|
100
96
|
function findBadgeByLabel(label) {
|
|
101
|
-
|
|
102
|
-
for (
|
|
103
|
-
|
|
104
|
-
var badge = item.querySelector('[class*="Badge-text"]');
|
|
105
|
-
if (badge) return parseInt(badge.textContent.trim(), 10);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// fallback: 搜索所有tree item
|
|
109
|
-
var allItems = treeEl.querySelectorAll('.cxd-Tree-item, .antd-Tree-item');
|
|
110
|
-
for (var ai of allItems) {
|
|
111
|
-
var labelEl = ai.querySelector('.instance-menu-label');
|
|
97
|
+
const nodes = menuEl.querySelectorAll('.ant-tree-treenode');
|
|
98
|
+
for (const node of nodes) {
|
|
99
|
+
const labelEl = node.querySelector('.approval-tree-menu__label');
|
|
112
100
|
if (labelEl && labelEl.textContent.includes(label)) {
|
|
113
|
-
|
|
114
|
-
if (
|
|
101
|
+
const badge = node.querySelector('.ant-badge-count');
|
|
102
|
+
if (badge) return parseInt(badge.textContent.trim(), 10);
|
|
115
103
|
}
|
|
116
104
|
}
|
|
117
105
|
return null;
|
|
@@ -120,7 +108,7 @@
|
|
|
120
108
|
// ---- 初始化 ----
|
|
121
109
|
origLog.call(console, '%c=== Draft 角标测试 ===', 'color:blue;font-size:14px;font-weight:bold');
|
|
122
110
|
round = 0;
|
|
123
|
-
|
|
111
|
+
window.postMessage({ type: "approval-tree-menu:reload" }, "*");
|
|
124
112
|
await sleep(4000);
|
|
125
113
|
|
|
126
114
|
if (baseDraft === null) {
|
|
@@ -137,10 +125,8 @@
|
|
|
137
125
|
var expDraft = baseDraft + i;
|
|
138
126
|
origLog.call(console, '--- 第' + i + '轮: 期望 inbox=' + expInbox + ', draft=' + expDraft);
|
|
139
127
|
|
|
140
|
-
|
|
141
|
-
await sleep(
|
|
142
|
-
treeBtn.click();
|
|
143
|
-
await sleep(1500);
|
|
128
|
+
window.postMessage({ type: "approval-tree-menu:reload" }, "*");
|
|
129
|
+
await sleep(3000);
|
|
144
130
|
|
|
145
131
|
var domInbox = getAllBadges()[0] ? parseInt(getAllBadges()[0].textContent.trim(), 10) : null;
|
|
146
132
|
var domDraft = findBadgeByLabel('草稿') || findBadgeByLabel('Draft') || findBadgeByLabel('draft');
|
|
@@ -25,14 +25,10 @@
|
|
|
25
25
|
console.log('');
|
|
26
26
|
|
|
27
27
|
// 检查前置条件
|
|
28
|
-
const
|
|
29
|
-
const treeReloadBtn = document.querySelector('.instance-tree-reload');
|
|
30
|
-
const treeEl = document.querySelector('.instance-box-tree');
|
|
28
|
+
const menuEl = document.querySelector('.approval-tree-menu');
|
|
31
29
|
|
|
32
|
-
if (!
|
|
33
|
-
|
|
34
|
-
if (!treeEl) { console.error('❌ 未找到 .instance-box-tree 树组件'); return; }
|
|
35
|
-
console.log('✅ 前置条件检查通过: nav-reload, tree-reload, tree DOM 均存在');
|
|
30
|
+
if (!menuEl) { console.error('❌ 未找到 .approval-tree-menu 组件'); return; }
|
|
31
|
+
console.log('✅ 前置条件检查通过: .approval-tree-menu 组件存在');
|
|
36
32
|
|
|
37
33
|
// 状态
|
|
38
34
|
let roundCounter = 0;
|
|
@@ -42,16 +38,9 @@
|
|
|
42
38
|
let apiCallCount = 0;
|
|
43
39
|
let fetchInitedCount = 0;
|
|
44
40
|
|
|
45
|
-
//
|
|
41
|
+
// ---- 监听日志 ----
|
|
46
42
|
const origConsoleLog = console.log;
|
|
47
43
|
const fetchInitedLogs = [];
|
|
48
|
-
console.log = function() {
|
|
49
|
-
if (arguments[0] && typeof arguments[0] === 'string' && arguments[0].includes('[fetchInited]')) {
|
|
50
|
-
fetchInitedCount++;
|
|
51
|
-
fetchInitedLogs.push(Array.from(arguments).join(' '));
|
|
52
|
-
}
|
|
53
|
-
return origConsoleLog.apply(console, arguments);
|
|
54
|
-
};
|
|
55
44
|
|
|
56
45
|
// ======== 篡改 options 的通用函数 ========
|
|
57
46
|
function tamperOptions(json, source) {
|
|
@@ -170,12 +159,7 @@
|
|
|
170
159
|
|
|
171
160
|
// ======== DOM 读取 ========
|
|
172
161
|
function findBadgeElements() {
|
|
173
|
-
|
|
174
|
-
for (const sel of selectors) {
|
|
175
|
-
const els = treeEl.querySelectorAll(sel);
|
|
176
|
-
if (els.length > 0) return els;
|
|
177
|
-
}
|
|
178
|
-
return [];
|
|
162
|
+
return menuEl.querySelectorAll('.ant-badge-count');
|
|
179
163
|
}
|
|
180
164
|
|
|
181
165
|
function getInboxBadgeFromDOM() {
|
|
@@ -196,10 +180,8 @@
|
|
|
196
180
|
// 初始化:获取基准值(模拟完整 socket 流程:nav reload + tree reload)
|
|
197
181
|
origConsoleLog.call(console, '%c[初始化] 获取基准角标值...', 'color: orange;');
|
|
198
182
|
roundCounter = 0;
|
|
199
|
-
|
|
200
|
-
await sleep(
|
|
201
|
-
treeReloadBtn.click();
|
|
202
|
-
await sleep(2000);
|
|
183
|
+
window.postMessage({ type: "approval-tree-menu:reload" }, "*");
|
|
184
|
+
await sleep(4000);
|
|
203
185
|
const initDom = getInboxBadgeFromDOM();
|
|
204
186
|
origConsoleLog.call(console, `%c[初始化] 基准值: API=${baseInboxTag}, DOM=${initDom}, fetchInited=${fetchInitedCount}次`, 'color: orange;');
|
|
205
187
|
|
|
@@ -208,7 +190,6 @@
|
|
|
208
190
|
window.fetch = originalFetch;
|
|
209
191
|
XHR.open = origXHROpen;
|
|
210
192
|
XHR.send = origXHRSend;
|
|
211
|
-
console.log = origConsoleLog;
|
|
212
193
|
return;
|
|
213
194
|
}
|
|
214
195
|
origConsoleLog.call(console, '');
|
|
@@ -224,14 +205,9 @@
|
|
|
224
205
|
origConsoleLog.call(console, `%c[第 ${round}/${TOTAL_ROUNDS} 轮]`, 'color: #888; font-weight: bold;',
|
|
225
206
|
`期望角标: ${baseInboxTag} + ${round} = ${expectedInboxTag}`);
|
|
226
207
|
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
await sleep(1500); // 等待 API 返回 + fetchInited 事件处理
|
|
231
|
-
|
|
232
|
-
// 2. Tree reload(从 Service 数据域读取 options)
|
|
233
|
-
treeReloadBtn.click();
|
|
234
|
-
await sleep(1500); // 等待 Tree reloadOptions 完成
|
|
208
|
+
// 触发刷新
|
|
209
|
+
window.postMessage({ type: "approval-tree-menu:reload" }, "*");
|
|
210
|
+
await sleep(3000); // 等待 API 返回 + React 重新渲染
|
|
235
211
|
|
|
236
212
|
// 3. 读取结果
|
|
237
213
|
const apiCalls = apiCallCount - apiCountBefore;
|
|
@@ -270,25 +246,6 @@
|
|
|
270
246
|
origConsoleLog.call(console, ' API篡改后值:', actualApiInboxTag);
|
|
271
247
|
origConsoleLog.call(console, ' DOM当前值:', domValue);
|
|
272
248
|
origConsoleLog.call(console, ' DOM全部角标:', Array.from(findBadgeElements()).map(el => el.textContent.trim()));
|
|
273
|
-
// 检查 tree-reload 增强是否生效
|
|
274
|
-
origConsoleLog.call(console, ' 检查 tree-reload 增强...');
|
|
275
|
-
try {
|
|
276
|
-
var s = window.amisScoped || (document.querySelector('[data-amisScoped]') && document.querySelector('[data-amisScoped]').__amisScoped);
|
|
277
|
-
if (s) {
|
|
278
|
-
var svc = s.getComponentById('u:instanceNav');
|
|
279
|
-
var tr = s.getComponentById('u:instanceNavTree');
|
|
280
|
-
origConsoleLog.call(console, ' Service组件:', svc ? '存在' : '不存在');
|
|
281
|
-
origConsoleLog.call(console, ' Tree组件:', tr ? '存在' : '不存在');
|
|
282
|
-
if (svc && svc.props && svc.props.data) {
|
|
283
|
-
var svcOpts = svc.props.data.options;
|
|
284
|
-
origConsoleLog.call(console, ' Service.data.options[0].tag:', svcOpts && svcOpts[0] ? svcOpts[0].tag : 'N/A');
|
|
285
|
-
}
|
|
286
|
-
if (tr && tr.props && tr.props.formItem) {
|
|
287
|
-
var treeOpts = tr.props.formItem.getOptions ? tr.props.formItem.getOptions() : (tr.props.options || []);
|
|
288
|
-
origConsoleLog.call(console, ' Tree.options[0].tag:', treeOpts && treeOpts[0] ? treeOpts[0].tag : 'N/A');
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
} catch(e) { origConsoleLog.call(console, ' 诊断出错:', e); }
|
|
292
249
|
stopped = true;
|
|
293
250
|
break;
|
|
294
251
|
}
|
|
@@ -302,7 +259,6 @@
|
|
|
302
259
|
window.fetch = originalFetch;
|
|
303
260
|
XHR.open = origXHROpen;
|
|
304
261
|
XHR.send = origXHRSend;
|
|
305
|
-
console.log = origConsoleLog;
|
|
306
262
|
|
|
307
263
|
// 报告
|
|
308
264
|
const passed = results.filter(r => r.pass).length;
|