@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.
@@ -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-DRUi3eGk.js"></script>
9
- <link rel="stylesheet" crossorigin href="/api/workflow/designer-v2/assets/index-BIbXABqz.css">
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": "wrapper",
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
- clearTimeout(window.__navReloadTimer)
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
- return instance.step_approve[`${step_id}_options`];
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
- return users[0];
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.$('.instance-nav-reload').click()"
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": 100
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.$('.instance-nav-reload').click()"
80
+ "script":"window.postMessage({ type: 'approval-tree-menu:reload' }, '*')"
81
81
  }
82
82
  ]
83
83
  }
@@ -34,4 +34,6 @@ searchable_fields:
34
34
  extra_columns:
35
35
  - extras
36
36
  - values
37
- disableSwitch: true
37
+ disableSwitch: true
38
+ searchable_default:
39
+ submit_date: "${[STARTOF(DATEMODIFY(NOW(), -180, 'day'), 'day'),ENDOF(NOW(), 'day')]}"
@@ -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 (currentApprove.values && currentApprove.values[field.code]) {
337
- result[field.code] = currentApprove.values[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
- const step_approve = instance.step_approve || {};
266
- const newNextUsers = step_approve[nextStepId] || []
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 navBtn = document.querySelector('.instance-nav-reload');
16
- const treeBtn = document.querySelector('.instance-tree-reload');
17
- const treeEl = document.querySelector('.instance-box-tree');
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
- var sels = ['[class*="Badge-text"]', '.antd-Badge-text', '.cxd-Badge-text'];
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
- var items = treeEl.querySelectorAll('.cxd-Tree-itemLabel, .antd-Tree-itemLabel');
102
- for (var item of items) {
103
- if (item.textContent.includes(label)) {
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
- var b = ai.querySelector('[class*="Badge-text"]');
114
- if (b) return parseInt(b.textContent.trim(), 10);
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
- navBtn.click();
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
- navBtn.click();
141
- await sleep(1500);
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 navReloadBtn = document.querySelector('.instance-nav-reload');
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 (!navReloadBtn) { console.error('❌ 未找到 .instance-nav-reload 按钮'); return; }
33
- if (!treeReloadBtn) { console.error(' 未找到 .instance-tree-reload 按钮'); return; }
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
- // ======== 监听 fetchInited 日志 ========
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
- const selectors = ['[class*="Badge-text"]', '.antd-Badge-text', '.cxd-Badge-text'];
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
- navReloadBtn.click();
200
- await sleep(2000);
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
- // 模拟完整 socket 流程:
228
- // 1. Service reload(获取 API 数据)
229
- navReloadBtn.click();
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos-labs/plugin-workflow",
3
- "version": "3.0.40",
3
+ "version": "3.0.42",
4
4
  "main": "package.service.js",
5
5
  "license": "MIT",
6
6
  "files": [