n8n-nodes-kingsoft-airscript 2.0.4 → 2.0.7
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/dist/nodes/KingsoftAirscript/KingsoftAirscript.node.js +266 -153
- package/dist/nodes/KingsoftAirscript/KingsoftAirscript.node.js.map +1 -1
- package/dist/nodes/KingsoftAirscript/KingsoftAirscript.node.json +12 -0
- package/dist/package.json +2 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -71,6 +71,49 @@ class KingsoftAirscript {
|
|
|
71
71
|
default: '',
|
|
72
72
|
description: '支持同步/异步执行脚本、自动分批处理和智能参数生成。',
|
|
73
73
|
},
|
|
74
|
+
{
|
|
75
|
+
displayName: '数据输入模式',
|
|
76
|
+
name: 'payloadMode',
|
|
77
|
+
type: 'options',
|
|
78
|
+
default: 'argvFromUI',
|
|
79
|
+
options: [
|
|
80
|
+
{
|
|
81
|
+
name: '从 UI 配置 Argv(当前方式)',
|
|
82
|
+
value: 'argvFromUI',
|
|
83
|
+
description: 'Argv 完全由 UI 中的 JSON 模板决定,适合固定参数场景'
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: '从输入项直接作为 Argv',
|
|
87
|
+
value: 'argvFromItem',
|
|
88
|
+
description: '每个输入项的 $JSON 直接作为 argv,适合上游已整理好结构的场景'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: '追加输入项到 Argv 数组字段',
|
|
92
|
+
value: 'appendItemsToArrayField',
|
|
93
|
+
description: '将所有输入项聚合成数组写入 argv,适合批量处理场景(只执行一次)'
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
description: '选择如何将 n8n 输入数据传递给脚本。',
|
|
97
|
+
displayOptions: { show: { operation: ['runScriptSync', 'runScriptAsync'] } },
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
displayName: '目标数组字段路径',
|
|
101
|
+
name: 'targetArrayField',
|
|
102
|
+
type: 'string',
|
|
103
|
+
default: 'data',
|
|
104
|
+
hint: '例如:data 或 写表行列表',
|
|
105
|
+
description: '当选择「追加输入项到 argv 数组字段」时,指定 argv 中的目标数组字段。例如设置为 "data",则所有输入项会被聚合到 argv.data 数组中。',
|
|
106
|
+
displayOptions: { show: { operation: ['runScriptSync', 'runScriptAsync'], payloadMode: ['appendItemsToArrayField'] } },
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
displayName: '项目数据字段路径',
|
|
110
|
+
name: 'itemDataPath',
|
|
111
|
+
type: 'string',
|
|
112
|
+
default: '',
|
|
113
|
+
hint: '留空表示使用整个 $json',
|
|
114
|
+
description: '当选择「从输入项直接作为 argv」或「追加输入项到 argv 数组字段」时,指定从输入项中提取数据的字段路径。例如设置为 "payload",则会使用 $JSON.payload 作为数据来源。',
|
|
115
|
+
displayOptions: { show: { operation: ['runScriptSync', 'runScriptAsync'], payloadMode: ['argvFromItem', 'appendItemsToArrayField'] } },
|
|
116
|
+
},
|
|
74
117
|
{
|
|
75
118
|
displayName: '操作',
|
|
76
119
|
name: 'operation',
|
|
@@ -188,7 +231,7 @@ class KingsoftAirscript {
|
|
|
188
231
|
default: '{\n "message": "Hello from n8n!"\n}',
|
|
189
232
|
required: true,
|
|
190
233
|
displayOptions: { show: { operation: ['runScriptSync', 'runScriptAsync'], argvTemplate: ['custom'] } },
|
|
191
|
-
description: '自定义 JSON
|
|
234
|
+
description: '自定义 JSON 参数。 数据输入模式说明: - argvFromUI:完全使用此模板作为 argv - argvFromItem:此模板被忽略,使用输入项的 $JSON - appendItemsToArrayField:此模板作为基础,输入项会被聚合成数组添加到指定字段',
|
|
192
235
|
},
|
|
193
236
|
{
|
|
194
237
|
displayName: '脚本参数 (Argv)',
|
|
@@ -319,7 +362,7 @@ class KingsoftAirscript {
|
|
|
319
362
|
type: 'number',
|
|
320
363
|
default: 300,
|
|
321
364
|
typeOptions: { minValue: 5 },
|
|
322
|
-
displayOptions: { show: { '/operation': ['runScriptAsync'], '/c_waitForCompletion': [true] } },
|
|
365
|
+
displayOptions: { show: { '/operation': ['runScriptAsync'], '/options/c_waitForCompletion': [true] } },
|
|
323
366
|
description: '异步等待完成模式下,最多等待的总时长(秒)。',
|
|
324
367
|
},
|
|
325
368
|
{
|
|
@@ -346,7 +389,7 @@ class KingsoftAirscript {
|
|
|
346
389
|
{ name: '逐批输出(推荐)', value: 'split' },
|
|
347
390
|
{ name: '合并为一个 Item(批次输出列表)', value: 'merge' },
|
|
348
391
|
],
|
|
349
|
-
displayOptions: { show: { '/r_autoChunkEnabled': [true] } },
|
|
392
|
+
displayOptions: { show: { '/options/r_autoChunkEnabled': [true] } },
|
|
350
393
|
description: '自动分批时的输出策略。',
|
|
351
394
|
},
|
|
352
395
|
{
|
|
@@ -356,7 +399,7 @@ class KingsoftAirscript {
|
|
|
356
399
|
default: '写表行列表',
|
|
357
400
|
hint: '指定包含大量数据的数组字段',
|
|
358
401
|
description: '例:写表行列表 或 data.写表行列表(从 argv 根开始)',
|
|
359
|
-
displayOptions: { show: { '/r_autoChunkEnabled': [true] } },
|
|
402
|
+
displayOptions: { show: { '/options/r_autoChunkEnabled': [true] } },
|
|
360
403
|
},
|
|
361
404
|
{
|
|
362
405
|
displayName: '分批最大并发数(同一 Item 内)',
|
|
@@ -364,7 +407,7 @@ class KingsoftAirscript {
|
|
|
364
407
|
type: 'number',
|
|
365
408
|
default: 3,
|
|
366
409
|
typeOptions: { minValue: 1, maxValue: 20 },
|
|
367
|
-
displayOptions: { show: { '/r_autoChunkEnabled': [true] } },
|
|
410
|
+
displayOptions: { show: { '/options/r_autoChunkEnabled': [true] } },
|
|
368
411
|
description: '自动分批时,同一输入 item 内批次执行的最大并发数。',
|
|
369
412
|
},
|
|
370
413
|
{
|
|
@@ -381,7 +424,7 @@ class KingsoftAirscript {
|
|
|
381
424
|
type: 'number',
|
|
382
425
|
default: 5,
|
|
383
426
|
typeOptions: { minValue: 1 },
|
|
384
|
-
displayOptions: { show: { '/operation': ['runScriptAsync'], '/c_waitForCompletion': [true] } },
|
|
427
|
+
displayOptions: { show: { '/operation': ['runScriptAsync'], '/options/c_waitForCompletion': [true] } },
|
|
385
428
|
description: '异步等待完成模式下的轮询间隔(秒)。',
|
|
386
429
|
},
|
|
387
430
|
{
|
|
@@ -391,7 +434,7 @@ class KingsoftAirscript {
|
|
|
391
434
|
default: 200,
|
|
392
435
|
hint: '处理大量数据时建议减小此值',
|
|
393
436
|
typeOptions: { minValue: 1 },
|
|
394
|
-
displayOptions: { show: { '/r_autoChunkEnabled': [true] } },
|
|
437
|
+
displayOptions: { show: { '/options/r_autoChunkEnabled': [true] } },
|
|
395
438
|
description: '自动分批时,每批数组元素数量。',
|
|
396
439
|
},
|
|
397
440
|
{
|
|
@@ -400,7 +443,7 @@ class KingsoftAirscript {
|
|
|
400
443
|
type: 'number',
|
|
401
444
|
default: 10,
|
|
402
445
|
typeOptions: { minValue: 1 },
|
|
403
|
-
displayOptions: { show: { '/a_parallelExecution': [true] } },
|
|
446
|
+
displayOptions: { show: { '/options/a_parallelExecution': [true] } },
|
|
404
447
|
description: '并行执行开启时,每批并发处理的输入 item 数量。',
|
|
405
448
|
},
|
|
406
449
|
{
|
|
@@ -496,8 +539,57 @@ class KingsoftAirscript {
|
|
|
496
539
|
async execute() {
|
|
497
540
|
const 输入数据项列表 = this.getInputData();
|
|
498
541
|
const 凭证 = (await this.getCredentials('kingsoftAirscriptApi'));
|
|
542
|
+
const 读取高级选项 = (索引) => {
|
|
543
|
+
const raw = this.getNodeParameter('options', 索引, {});
|
|
544
|
+
const 取数 = (k, d) => {
|
|
545
|
+
const v = raw[k];
|
|
546
|
+
const n = typeof v === 'number' ? v : Number(v);
|
|
547
|
+
return Number.isFinite(n) ? n : d;
|
|
548
|
+
};
|
|
549
|
+
const 取布尔 = (k, d) => {
|
|
550
|
+
const v = raw[k];
|
|
551
|
+
return typeof v === 'boolean' ? v : d;
|
|
552
|
+
};
|
|
553
|
+
const 取字符串 = (k, d) => {
|
|
554
|
+
const v = raw[k];
|
|
555
|
+
return typeof v === 'string' ? v : d;
|
|
556
|
+
};
|
|
557
|
+
return {
|
|
558
|
+
a_parallelExecution: 取布尔('a_parallelExecution', false),
|
|
559
|
+
b_timeoutSeconds: 取数('b_timeoutSeconds', 300),
|
|
560
|
+
c_waitForCompletion: 取布尔('c_waitForCompletion', false),
|
|
561
|
+
d_pollIntervalSeconds: 取数('d_pollIntervalSeconds', 5),
|
|
562
|
+
e_batchSize: 取数('e_batchSize', 10),
|
|
563
|
+
f_outputFormat: 取字符串('f_outputFormat', 'fullResponse'),
|
|
564
|
+
g_parseResultString: 取布尔('g_parseResultString', false),
|
|
565
|
+
x_globalMaxConcurrency: 取数('x_globalMaxConcurrency', 5),
|
|
566
|
+
h_requestTimeoutSeconds: 取数('h_requestTimeoutSeconds', 120),
|
|
567
|
+
i_statusTimeoutSeconds: 取数('i_statusTimeoutSeconds', 30),
|
|
568
|
+
j_maxRetries: 取数('j_maxRetries', 2),
|
|
569
|
+
k_retryInitialDelayMs: 取数('k_retryInitialDelayMs', 800),
|
|
570
|
+
l_retryBackoffFactor: 取数('l_retryBackoffFactor', 2),
|
|
571
|
+
m_honorRetryAfter: 取布尔('m_honorRetryAfter', true),
|
|
572
|
+
n_failOnScriptError: 取布尔('n_failOnScriptError', true),
|
|
573
|
+
o_pollJitterMs: 取数('o_pollJitterMs', 300),
|
|
574
|
+
r_autoChunkEnabled: 取布尔('r_autoChunkEnabled', false),
|
|
575
|
+
s_chunkFieldPath: 取字符串('s_chunkFieldPath', '写表行列表'),
|
|
576
|
+
t_chunkSize: 取数('t_chunkSize', 200),
|
|
577
|
+
u_chunkMaxConcurrency: 取数('u_chunkMaxConcurrency', 3),
|
|
578
|
+
v_chunkOutputMode: 取字符串('v_chunkOutputMode', 'split'),
|
|
579
|
+
w_debug: 取布尔('w_debug', false),
|
|
580
|
+
};
|
|
581
|
+
};
|
|
582
|
+
const opt0 = 读取高级选项(0);
|
|
583
|
+
const 全局并发闸门 = 创建并发闸门(Math.max(1, opt0.x_globalMaxConcurrency));
|
|
499
584
|
const 等待毫秒 = async (ms) => {
|
|
500
|
-
|
|
585
|
+
if (ms <= 0)
|
|
586
|
+
return;
|
|
587
|
+
const 开始时间 = Date.now();
|
|
588
|
+
while (Date.now() - 开始时间 < ms) {
|
|
589
|
+
await new Promise((resolve) => {
|
|
590
|
+
Promise.resolve().then(() => resolve());
|
|
591
|
+
});
|
|
592
|
+
}
|
|
501
593
|
};
|
|
502
594
|
const 脱敏ID = (id) => {
|
|
503
595
|
const s = (id !== null && id !== void 0 ? id : '').toString();
|
|
@@ -522,9 +614,20 @@ class KingsoftAirscript {
|
|
|
522
614
|
const 是IDataObject = (v) => {
|
|
523
615
|
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
524
616
|
};
|
|
617
|
+
const getStatusCode = (err) => {
|
|
618
|
+
var _a, _b, _c, _d;
|
|
619
|
+
return (_c = (_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : err.statusCode) !== null && _c !== void 0 ? _c : (_d = err.response) === null || _d === void 0 ? void 0 : _d.statusCode;
|
|
620
|
+
};
|
|
621
|
+
const getBody = (err) => {
|
|
622
|
+
var _a, _b, _c, _d;
|
|
623
|
+
return ((_c = (_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : err.body) !== null && _c !== void 0 ? _c : (_d = err.response) === null || _d === void 0 ? void 0 : _d.body);
|
|
624
|
+
};
|
|
625
|
+
const getHeaders = (err) => {
|
|
626
|
+
var _a, _b, _c, _d;
|
|
627
|
+
return (_c = (_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.headers) !== null && _b !== void 0 ? _b : err.headers) !== null && _c !== void 0 ? _c : (_d = err.response) === null || _d === void 0 ? void 0 : _d.headers;
|
|
628
|
+
};
|
|
525
629
|
const 提取错误消息 = (err) => {
|
|
526
|
-
|
|
527
|
-
const data = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data;
|
|
630
|
+
const data = getBody(err);
|
|
528
631
|
if (是IDataObject(data)) {
|
|
529
632
|
const errorDetails = data.error_details;
|
|
530
633
|
if (是IDataObject(errorDetails)) {
|
|
@@ -541,15 +644,14 @@ class KingsoftAirscript {
|
|
|
541
644
|
return '未知错误';
|
|
542
645
|
};
|
|
543
646
|
const 判断是否可重试 = (e) => {
|
|
544
|
-
var _a;
|
|
545
647
|
const err = 提取Http错误(e);
|
|
546
648
|
const 错误码 = err.code;
|
|
547
|
-
const 状态码 = (
|
|
649
|
+
const 状态码 = getStatusCode(err);
|
|
548
650
|
return (['ETIMEDOUT', 'ECONNRESET', 'EAI_AGAIN', 'ECONNREFUSED', 'ECONNABORTED'].includes(String(错误码 !== null && 错误码 !== void 0 ? 错误码 : '')) ||
|
|
549
651
|
[408, 425, 429, 500, 502, 503, 504].includes(Number(状态码 !== null && 状态码 !== void 0 ? 状态码 : 0)));
|
|
550
652
|
};
|
|
551
653
|
const 带重试 = async (执行函数, 配置, 调试) => {
|
|
552
|
-
var _a, _b
|
|
654
|
+
var _a, _b;
|
|
553
655
|
let 尝试 = 0;
|
|
554
656
|
while (true) {
|
|
555
657
|
try {
|
|
@@ -560,7 +662,7 @@ class KingsoftAirscript {
|
|
|
560
662
|
}
|
|
561
663
|
catch (e) {
|
|
562
664
|
const err = 提取Http错误(e);
|
|
563
|
-
const 状态码 = (
|
|
665
|
+
const 状态码 = getStatusCode(err);
|
|
564
666
|
if (!判断是否可重试(e) || 尝试 >= 配置.最大重试次数) {
|
|
565
667
|
if (调试)
|
|
566
668
|
调试.重试次数 = 尝试;
|
|
@@ -568,8 +670,8 @@ class KingsoftAirscript {
|
|
|
568
670
|
}
|
|
569
671
|
let 等待 = Math.round(配置.初始等待毫秒 * Math.pow(配置.退避倍数, 尝试) + Math.random() * 200);
|
|
570
672
|
if (配置.尊重RetryAfter && 状态码 === 429) {
|
|
571
|
-
const headers = (
|
|
572
|
-
const ra = (
|
|
673
|
+
const headers = (_a = getHeaders(err)) !== null && _a !== void 0 ? _a : {};
|
|
674
|
+
const ra = (_b = headers['retry-after']) !== null && _b !== void 0 ? _b : headers['Retry-After'];
|
|
573
675
|
const raMs = 解析RetryAfter毫秒(ra);
|
|
574
676
|
if (raMs !== null)
|
|
575
677
|
等待 = Math.max(等待, raMs);
|
|
@@ -615,58 +717,19 @@ class KingsoftAirscript {
|
|
|
615
717
|
const 递归 = (cur, idx) => {
|
|
616
718
|
const k = keys[idx];
|
|
617
719
|
const isLast = idx === keys.length - 1;
|
|
618
|
-
|
|
720
|
+
if (Array.isArray(cur) && !isLast) {
|
|
721
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `路径中间节点不能是数组:${keys.slice(0, idx + 1).join('.')} 是数组,无法在其下创建子字段`);
|
|
722
|
+
}
|
|
723
|
+
const base = (cur && typeof cur === 'object' && !Array.isArray(cur)) ? cur : {};
|
|
619
724
|
const clone = { ...base };
|
|
620
|
-
if (isLast)
|
|
725
|
+
if (isLast)
|
|
621
726
|
clone[k] = value;
|
|
622
|
-
|
|
623
|
-
else {
|
|
727
|
+
else
|
|
624
728
|
clone[k] = 递归(base[k], idx + 1);
|
|
625
|
-
}
|
|
626
729
|
return clone;
|
|
627
730
|
};
|
|
628
731
|
return 递归(obj, 0);
|
|
629
732
|
};
|
|
630
|
-
const 读取高级选项 = (索引) => {
|
|
631
|
-
const raw = this.getNodeParameter('options', 索引, {});
|
|
632
|
-
const 取数 = (k, d) => {
|
|
633
|
-
const v = raw[k];
|
|
634
|
-
const n = typeof v === 'number' ? v : Number(v);
|
|
635
|
-
return Number.isFinite(n) ? n : d;
|
|
636
|
-
};
|
|
637
|
-
const 取布尔 = (k, d) => {
|
|
638
|
-
const v = raw[k];
|
|
639
|
-
return typeof v === 'boolean' ? v : d;
|
|
640
|
-
};
|
|
641
|
-
const 取字符串 = (k, d) => {
|
|
642
|
-
const v = raw[k];
|
|
643
|
-
return typeof v === 'string' ? v : d;
|
|
644
|
-
};
|
|
645
|
-
return {
|
|
646
|
-
a_parallelExecution: 取布尔('a_parallelExecution', false),
|
|
647
|
-
b_timeoutSeconds: 取数('b_timeoutSeconds', 300),
|
|
648
|
-
c_waitForCompletion: 取布尔('c_waitForCompletion', false),
|
|
649
|
-
d_pollIntervalSeconds: 取数('d_pollIntervalSeconds', 5),
|
|
650
|
-
e_batchSize: 取数('e_batchSize', 10),
|
|
651
|
-
f_outputFormat: 取字符串('f_outputFormat', 'fullResponse'),
|
|
652
|
-
g_parseResultString: 取布尔('g_parseResultString', false),
|
|
653
|
-
x_globalMaxConcurrency: 取数('x_globalMaxConcurrency', 5),
|
|
654
|
-
h_requestTimeoutSeconds: 取数('h_requestTimeoutSeconds', 120),
|
|
655
|
-
i_statusTimeoutSeconds: 取数('i_statusTimeoutSeconds', 30),
|
|
656
|
-
j_maxRetries: 取数('j_maxRetries', 2),
|
|
657
|
-
k_retryInitialDelayMs: 取数('k_retryInitialDelayMs', 800),
|
|
658
|
-
l_retryBackoffFactor: 取数('l_retryBackoffFactor', 2),
|
|
659
|
-
m_honorRetryAfter: 取布尔('m_honorRetryAfter', true),
|
|
660
|
-
n_failOnScriptError: 取布尔('n_failOnScriptError', true),
|
|
661
|
-
o_pollJitterMs: 取数('o_pollJitterMs', 300),
|
|
662
|
-
r_autoChunkEnabled: 取布尔('r_autoChunkEnabled', false),
|
|
663
|
-
s_chunkFieldPath: 取字符串('s_chunkFieldPath', '写表行列表'),
|
|
664
|
-
t_chunkSize: 取数('t_chunkSize', 200),
|
|
665
|
-
u_chunkMaxConcurrency: 取数('u_chunkMaxConcurrency', 3),
|
|
666
|
-
v_chunkOutputMode: 取字符串('v_chunkOutputMode', 'split'),
|
|
667
|
-
w_debug: 取布尔('w_debug', false),
|
|
668
|
-
};
|
|
669
|
-
};
|
|
670
733
|
const 提取脚本错误消息 = (响应) => {
|
|
671
734
|
var _a;
|
|
672
735
|
const error = String((_a = 响应.error) !== null && _a !== void 0 ? _a : '').trim();
|
|
@@ -695,8 +758,8 @@ class KingsoftAirscript {
|
|
|
695
758
|
const fromTop = 响应.task_id;
|
|
696
759
|
return String((_b = fromData !== null && fromData !== void 0 ? fromData : fromTop) !== null && _b !== void 0 ? _b : '').trim();
|
|
697
760
|
};
|
|
698
|
-
const 解析执行信息 = (itemIndex) => {
|
|
699
|
-
var _a;
|
|
761
|
+
const 解析执行信息 = (itemIndex, inputData) => {
|
|
762
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
700
763
|
const id输入模式 = this.getNodeParameter('idInputMode', itemIndex, 'url');
|
|
701
764
|
let 文件ID = '';
|
|
702
765
|
let 脚本ID = '';
|
|
@@ -715,8 +778,7 @@ class KingsoftAirscript {
|
|
|
715
778
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Webhook 链接格式不正确,无法解析出 File ID 和 Script ID。', { itemIndex });
|
|
716
779
|
}
|
|
717
780
|
}
|
|
718
|
-
catch
|
|
719
|
-
void e;
|
|
781
|
+
catch {
|
|
720
782
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Webhook 链接格式不正确,无法解析出 File ID 和 Script ID。', { itemIndex });
|
|
721
783
|
}
|
|
722
784
|
}
|
|
@@ -727,8 +789,14 @@ class KingsoftAirscript {
|
|
|
727
789
|
if (!文件ID || !脚本ID) {
|
|
728
790
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), '未能获取到有效的 File ID 和 Script ID。', { itemIndex });
|
|
729
791
|
}
|
|
730
|
-
const
|
|
792
|
+
const payloadMode = this.getNodeParameter('payloadMode', itemIndex, 'argvFromUI');
|
|
793
|
+
let argv参数 = {};
|
|
731
794
|
const 可选上下文参数 = this.getNodeParameter('contextParameters', itemIndex, {});
|
|
795
|
+
let 最终_sheet_name = '';
|
|
796
|
+
let 最终_range = '';
|
|
797
|
+
let 最终_link_from = '';
|
|
798
|
+
let 最终_db_active_view = '';
|
|
799
|
+
let 最终_db_selection = '';
|
|
732
800
|
const 模板到字段名 = {
|
|
733
801
|
custom: 'argv_custom',
|
|
734
802
|
basicInput: 'argv_basicInput',
|
|
@@ -742,20 +810,75 @@ class KingsoftAirscript {
|
|
|
742
810
|
compositeKey: 'argv_compositeKey',
|
|
743
811
|
createSheet: 'argv_createSheet',
|
|
744
812
|
};
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
813
|
+
if (payloadMode === 'argvFromUI') {
|
|
814
|
+
const argvTemplate = this.getNodeParameter('argvTemplate', itemIndex, 'custom');
|
|
815
|
+
const argv字段名 = (_a = 模板到字段名[argvTemplate]) !== null && _a !== void 0 ? _a : 'argv_custom';
|
|
816
|
+
const argv原始 = this.getNodeParameter(argv字段名, itemIndex, {});
|
|
817
|
+
if (typeof argv原始 === 'string') {
|
|
818
|
+
try {
|
|
819
|
+
argv参数 = JSON.parse(argv原始);
|
|
820
|
+
}
|
|
821
|
+
catch {
|
|
822
|
+
argv参数 = { value: argv原始 };
|
|
823
|
+
}
|
|
751
824
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
825
|
+
else if (argv原始 && typeof argv原始 === 'object' && !Array.isArray(argv原始)) {
|
|
826
|
+
argv参数 = argv原始;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
else if (payloadMode === 'argvFromItem') {
|
|
830
|
+
const itemDataPath = this.getNodeParameter('itemDataPath', itemIndex, '');
|
|
831
|
+
const item = (inputData === null || inputData === void 0 ? void 0 : inputData[itemIndex]) || 输入数据项列表[itemIndex];
|
|
832
|
+
if (item === null || item === void 0 ? void 0 : item.json) {
|
|
833
|
+
if (itemDataPath) {
|
|
834
|
+
const 数据值 = 取路径值(item.json, itemDataPath);
|
|
835
|
+
if (数据值 !== undefined) {
|
|
836
|
+
if (typeof 数据值 === 'object' && 数据值 !== null && !Array.isArray(数据值))
|
|
837
|
+
argv参数 = { ...数据值 };
|
|
838
|
+
else
|
|
839
|
+
argv参数 = { value: 数据值 };
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
argv参数 = { ...item.json };
|
|
844
|
+
}
|
|
755
845
|
}
|
|
756
846
|
}
|
|
757
|
-
else if (
|
|
758
|
-
|
|
847
|
+
else if (payloadMode === 'appendItemsToArrayField') {
|
|
848
|
+
const targetArrayField = this.getNodeParameter('targetArrayField', itemIndex, 'data');
|
|
849
|
+
const itemDataPath = this.getNodeParameter('itemDataPath', itemIndex, '');
|
|
850
|
+
const 输入数据 = inputData || 输入数据项列表;
|
|
851
|
+
const argvTemplate = this.getNodeParameter('argvTemplate', itemIndex, 'custom');
|
|
852
|
+
const argv字段名 = (_b = 模板到字段名[argvTemplate]) !== null && _b !== void 0 ? _b : 'argv_custom';
|
|
853
|
+
const argv原始 = this.getNodeParameter(argv字段名, itemIndex, {});
|
|
854
|
+
if (typeof argv原始 === 'string') {
|
|
855
|
+
try {
|
|
856
|
+
argv参数 = JSON.parse(argv原始);
|
|
857
|
+
}
|
|
858
|
+
catch {
|
|
859
|
+
argv参数 = { value: argv原始 };
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
else if (argv原始 && typeof argv原始 === 'object' && !Array.isArray(argv原始)) {
|
|
863
|
+
argv参数 = argv原始;
|
|
864
|
+
}
|
|
865
|
+
const 目标数组 = [];
|
|
866
|
+
for (const item of 输入数据) {
|
|
867
|
+
if (!(item === null || item === void 0 ? void 0 : item.json))
|
|
868
|
+
continue;
|
|
869
|
+
if (itemDataPath) {
|
|
870
|
+
const 数据值 = 取路径值(item.json, itemDataPath);
|
|
871
|
+
if (数据值 !== undefined)
|
|
872
|
+
目标数组.push(数据值);
|
|
873
|
+
}
|
|
874
|
+
else {
|
|
875
|
+
目标数组.push(item.json);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
if (targetArrayField.includes('.'))
|
|
879
|
+
argv参数 = 以不可变方式写入路径(argv参数, targetArrayField, 目标数组);
|
|
880
|
+
else
|
|
881
|
+
argv参数[targetArrayField] = 目标数组;
|
|
759
882
|
}
|
|
760
883
|
for (const key in argv参数) {
|
|
761
884
|
if (!Object.prototype.hasOwnProperty.call(argv参数, key))
|
|
@@ -764,8 +887,7 @@ class KingsoftAirscript {
|
|
|
764
887
|
if (typeof value !== 'string')
|
|
765
888
|
continue;
|
|
766
889
|
const trimmed = value.trim();
|
|
767
|
-
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
|
|
768
|
-
(trimmed.startsWith('[') && trimmed.endsWith(']'))) {
|
|
890
|
+
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
|
|
769
891
|
try {
|
|
770
892
|
argv参数[key] = JSON.parse(trimmed);
|
|
771
893
|
}
|
|
@@ -774,24 +896,18 @@ class KingsoftAirscript {
|
|
|
774
896
|
}
|
|
775
897
|
}
|
|
776
898
|
}
|
|
777
|
-
const
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
if (
|
|
781
|
-
return
|
|
782
|
-
|
|
783
|
-
const v2 = 规范化字符串(argv参数[camel]);
|
|
784
|
-
if (v2)
|
|
785
|
-
return v2;
|
|
786
|
-
}
|
|
787
|
-
return '';
|
|
899
|
+
const 从Argv提取 = (snakeKey, camelKey) => {
|
|
900
|
+
if (argv参数[snakeKey] !== undefined)
|
|
901
|
+
return argv参数[snakeKey];
|
|
902
|
+
if (argv参数[camelKey] !== undefined)
|
|
903
|
+
return argv参数[camelKey];
|
|
904
|
+
return undefined;
|
|
788
905
|
};
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
const 最终_db_selection = 从Argv取('db_selection', 'dbSelection') || 从UI取('dbSelection');
|
|
906
|
+
最终_sheet_name = String((_d = (_c = 从Argv提取('sheet_name', 'sheetName')) !== null && _c !== void 0 ? _c : 可选上下文参数.sheetName) !== null && _d !== void 0 ? _d : '').trim();
|
|
907
|
+
最终_range = String((_f = (_e = 从Argv提取('range', 'range')) !== null && _e !== void 0 ? _e : 可选上下文参数.range) !== null && _f !== void 0 ? _f : '').trim();
|
|
908
|
+
最终_link_from = String((_h = (_g = 从Argv提取('link_from', 'linkFrom')) !== null && _g !== void 0 ? _g : 可选上下文参数.linkFrom) !== null && _h !== void 0 ? _h : '').trim();
|
|
909
|
+
最终_db_active_view = String((_k = (_j = 从Argv提取('db_active_view', 'dbActiveView')) !== null && _j !== void 0 ? _j : 可选上下文参数.dbActiveView) !== null && _k !== void 0 ? _k : '').trim();
|
|
910
|
+
最终_db_selection = String((_m = (_l = 从Argv提取('db_selection', 'dbSelection')) !== null && _l !== void 0 ? _l : 可选上下文参数.dbSelection) !== null && _m !== void 0 ? _m : '').trim();
|
|
795
911
|
if (最终_sheet_name)
|
|
796
912
|
argv参数.sheet_name = 最终_sheet_name;
|
|
797
913
|
if (最终_range)
|
|
@@ -904,9 +1020,16 @@ class KingsoftAirscript {
|
|
|
904
1020
|
调试: 参数.调试,
|
|
905
1021
|
并发闸门: 参数.并发闸门,
|
|
906
1022
|
});
|
|
907
|
-
const 状态 = typeof 状态响应.status === 'string' ? 状态响应.status : '';
|
|
908
|
-
|
|
909
|
-
|
|
1023
|
+
const 状态 = typeof 状态响应.status === 'string' ? 状态响应.status.toLowerCase() : '';
|
|
1024
|
+
const 终端状态 = ['finished', 'failed', 'canceled', 'cancelled', 'error'];
|
|
1025
|
+
if (终端状态.includes(状态)) {
|
|
1026
|
+
if (状态 === 'finished') {
|
|
1027
|
+
校验脚本是否失败(状态响应, 参数.itemIndex, 参数.finished但error算失败);
|
|
1028
|
+
}
|
|
1029
|
+
else {
|
|
1030
|
+
const 错误信息 = `任务执行${状态}:${状态响应.error || 状态响应.message || '未知错误'}`;
|
|
1031
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 错误信息, { itemIndex: 参数.itemIndex });
|
|
1032
|
+
}
|
|
910
1033
|
if (参数.调试)
|
|
911
1034
|
参数.调试['轮询次数'] = (轮询次数 + 1);
|
|
912
1035
|
return 状态响应;
|
|
@@ -920,20 +1043,17 @@ class KingsoftAirscript {
|
|
|
920
1043
|
});
|
|
921
1044
|
};
|
|
922
1045
|
const 格式化输出 = (响应数据, 索引, opt, 附加, operation) => {
|
|
923
|
-
var _a, _b, _c, _d;
|
|
1046
|
+
var _a, _b, _c, _d, _e;
|
|
924
1047
|
const data = ((_a = 响应数据.data) !== null && _a !== void 0 ? _a : undefined);
|
|
925
1048
|
if (opt.g_parseResultString && data && typeof data.result === 'string') {
|
|
926
1049
|
try {
|
|
927
1050
|
data.result = JSON.parse(data.result);
|
|
928
1051
|
}
|
|
929
|
-
catch
|
|
930
|
-
void e;
|
|
1052
|
+
catch {
|
|
931
1053
|
data.result = data.result.replace(/\\n/g, '\n');
|
|
932
1054
|
}
|
|
933
1055
|
}
|
|
934
|
-
const _meta = {
|
|
935
|
-
operation: operation || 'unknown',
|
|
936
|
-
};
|
|
1056
|
+
const _meta = { operation: operation || 'unknown' };
|
|
937
1057
|
const sheetNameFromData = (data === null || data === void 0 ? void 0 : data.sheet_name) || (data === null || data === void 0 ? void 0 : data.sheetName);
|
|
938
1058
|
const sheetNameFromResponse = 是IDataObject(响应数据) ? (响应数据.sheet_name || 响应数据.sheetName) : undefined;
|
|
939
1059
|
const sheetNameFromArgv = 是IDataObject(附加) && 是IDataObject(附加.argv) ? (附加.argv.sheet_name || 附加.argv.sheetName) : undefined;
|
|
@@ -949,18 +1069,18 @@ class KingsoftAirscript {
|
|
|
949
1069
|
_meta.task_id = taskIdFromData;
|
|
950
1070
|
else if (taskIdFromResponse)
|
|
951
1071
|
_meta.task_id = taskIdFromResponse;
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1072
|
+
const batchIndex = (_b = 附加 === null || 附加 === void 0 ? void 0 : 附加.批次索引) !== null && _b !== void 0 ? _b : 附加 === null || 附加 === void 0 ? void 0 : 附加.batchIndex;
|
|
1073
|
+
if (batchIndex !== undefined)
|
|
1074
|
+
_meta.batchIndex = batchIndex;
|
|
955
1075
|
const out = [];
|
|
956
1076
|
if (opt.f_outputFormat === 'resultOnly') {
|
|
957
1077
|
out.push({
|
|
958
1078
|
json: {
|
|
959
1079
|
...(附加 !== null && 附加 !== void 0 ? 附加 : {}),
|
|
960
1080
|
_meta,
|
|
961
|
-
result: (
|
|
962
|
-
status: ((
|
|
963
|
-
error: ((
|
|
1081
|
+
result: (_c = data === null || data === void 0 ? void 0 : data.result) !== null && _c !== void 0 ? _c : null,
|
|
1082
|
+
status: ((_d = 响应数据.status) !== null && _d !== void 0 ? _d : null),
|
|
1083
|
+
error: ((_e = 响应数据.error) !== null && _e !== void 0 ? _e : ''),
|
|
964
1084
|
},
|
|
965
1085
|
pairedItem: { item: 索引 },
|
|
966
1086
|
});
|
|
@@ -993,7 +1113,7 @@ class KingsoftAirscript {
|
|
|
993
1113
|
out.push({ json: { ...(附加 !== null && 附加 !== void 0 ? 附加 : {}), _meta, ...响应数据 }, pairedItem: { item: 索引 } });
|
|
994
1114
|
return out;
|
|
995
1115
|
};
|
|
996
|
-
const 处理单个项目 = async (
|
|
1116
|
+
const 处理单个项目 = async (索引, 并发闸门) => {
|
|
997
1117
|
const 操作类型 = this.getNodeParameter('operation', 索引, 'runScriptSync');
|
|
998
1118
|
const opt = 读取高级选项(索引);
|
|
999
1119
|
const 重试 = {
|
|
@@ -1003,7 +1123,6 @@ class KingsoftAirscript {
|
|
|
1003
1123
|
尊重RetryAfter: opt.m_honorRetryAfter,
|
|
1004
1124
|
};
|
|
1005
1125
|
const 调试字段 = opt.w_debug ? {} : undefined;
|
|
1006
|
-
const 并发闸门 = 创建并发闸门(opt.x_globalMaxConcurrency);
|
|
1007
1126
|
if (操作类型 === 'getTaskStatus') {
|
|
1008
1127
|
const taskId = this.getNodeParameter('taskId', 索引, '');
|
|
1009
1128
|
if (!taskId || !taskId.trim()) {
|
|
@@ -1020,7 +1139,7 @@ class KingsoftAirscript {
|
|
|
1020
1139
|
const 附加 = opt.w_debug ? { _调试: 调试字段 } : undefined;
|
|
1021
1140
|
return 格式化输出(状态响应, 索引, opt, 附加, 操作类型);
|
|
1022
1141
|
}
|
|
1023
|
-
const { 文件ID, 脚本ID, argv参数, 上下文 } = 解析执行信息(
|
|
1142
|
+
const { 文件ID, 脚本ID, argv参数, 上下文 } = 解析执行信息(索引, 输入数据项列表);
|
|
1024
1143
|
const 组装批次失败响应 = (错误信息, 堆栈) => ({
|
|
1025
1144
|
status: 'finished',
|
|
1026
1145
|
error: 错误信息,
|
|
@@ -1058,9 +1177,8 @@ class KingsoftAirscript {
|
|
|
1058
1177
|
调试: 调试对象,
|
|
1059
1178
|
并发闸门,
|
|
1060
1179
|
});
|
|
1061
|
-
if (!opt.c_waitForCompletion)
|
|
1180
|
+
if (!opt.c_waitForCompletion)
|
|
1062
1181
|
return 初始响应;
|
|
1063
|
-
}
|
|
1064
1182
|
const taskId = 提取TaskId(初始响应);
|
|
1065
1183
|
if (!taskId) {
|
|
1066
1184
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), '异步执行返回的响应中未找到 task_id(data.task_id 或 task_id)。', { itemIndex: 索引 });
|
|
@@ -1083,18 +1201,13 @@ class KingsoftAirscript {
|
|
|
1083
1201
|
if (opt.r_autoChunkEnabled) {
|
|
1084
1202
|
const 数组路径 = opt.s_chunkFieldPath;
|
|
1085
1203
|
const 目标数组 = 取路径值(argv参数, 数组路径);
|
|
1086
|
-
if (!Array.isArray(目标数组)) {
|
|
1204
|
+
if (!Array.isArray(目标数组) || 目标数组.length === 0) {
|
|
1087
1205
|
const 响应 = await 执行一次(上下文, 调试字段);
|
|
1088
1206
|
const 附加 = opt.w_debug ? { _调试: 调试字段 } : undefined;
|
|
1089
1207
|
return 格式化输出(响应, 索引, opt, 附加, 操作类型);
|
|
1090
1208
|
}
|
|
1091
1209
|
const 批次大小 = Math.max(1, opt.t_chunkSize);
|
|
1092
1210
|
const 并发数 = Math.max(1, opt.u_chunkMaxConcurrency);
|
|
1093
|
-
if (目标数组.length === 0) {
|
|
1094
|
-
const 响应 = await 执行一次(上下文, 调试字段);
|
|
1095
|
-
const 附加 = opt.w_debug ? { _调试: 调试字段 } : undefined;
|
|
1096
|
-
return 格式化输出(响应, 索引, opt, 附加, 操作类型);
|
|
1097
|
-
}
|
|
1098
1211
|
const 任务列表 = [];
|
|
1099
1212
|
for (let i = 0; i < 目标数组.length; i += 批次大小) {
|
|
1100
1213
|
const 批次 = 目标数组.slice(i, i + 批次大小);
|
|
@@ -1108,18 +1221,17 @@ class KingsoftAirscript {
|
|
|
1108
1221
|
};
|
|
1109
1222
|
const 响应 = await 执行一次(批次上下文, 批次调试对象);
|
|
1110
1223
|
const 批次附加 = opt.w_debug
|
|
1111
|
-
? { _调试: { ...(批次调试对象 !== null && 批次调试对象 !== void 0 ? 批次调试对象 : {})
|
|
1224
|
+
? { 批次索引, _调试: { ...(批次调试对象 !== null && 批次调试对象 !== void 0 ? 批次调试对象 : {}) } }
|
|
1112
1225
|
: { 批次索引 };
|
|
1113
1226
|
return 格式化输出(响应, 索引, opt, 批次附加, 操作类型);
|
|
1114
1227
|
}
|
|
1115
1228
|
catch (错误) {
|
|
1116
|
-
if (!this.continueOnFail())
|
|
1229
|
+
if (!this.continueOnFail())
|
|
1117
1230
|
throw 错误;
|
|
1118
|
-
}
|
|
1119
1231
|
const err = 错误 instanceof Error ? 错误 : new Error(String(错误));
|
|
1120
1232
|
const 错误对象 = 组装批次失败响应(err.message, err.stack);
|
|
1121
1233
|
const 错误附加 = opt.w_debug
|
|
1122
|
-
? { _调试: {
|
|
1234
|
+
? { 批次索引, _调试: { 错误: err.message } }
|
|
1123
1235
|
: { 批次索引, 错误: err.message };
|
|
1124
1236
|
return 格式化输出(错误对象, 索引, opt, 错误附加, 操作类型);
|
|
1125
1237
|
}
|
|
@@ -1133,15 +1245,16 @@ class KingsoftAirscript {
|
|
|
1133
1245
|
.map(x => x.json)
|
|
1134
1246
|
.filter((json) => typeof json === 'object' && json !== null)
|
|
1135
1247
|
.map(json => {
|
|
1136
|
-
var _a;
|
|
1248
|
+
var _a, _b, _c;
|
|
1137
1249
|
const fromData = (_a = json.data) === null || _a === void 0 ? void 0 : _a.task_id;
|
|
1138
1250
|
const fromTop = json.task_id;
|
|
1139
|
-
|
|
1251
|
+
const fromMeta = (_b = json._meta) === null || _b === void 0 ? void 0 : _b.task_id;
|
|
1252
|
+
return (_c = fromData !== null && fromData !== void 0 ? fromData : fromTop) !== null && _c !== void 0 ? _c : fromMeta;
|
|
1140
1253
|
})
|
|
1141
1254
|
.filter((id) => typeof id === 'string' && id.length > 0);
|
|
1142
1255
|
const 批次数 = Math.ceil(目标数组.length / 批次大小);
|
|
1143
1256
|
const 分批汇总 = {
|
|
1144
|
-
|
|
1257
|
+
批次数,
|
|
1145
1258
|
每批条数: Array.from({ length: 批次数 }, (_, i) => {
|
|
1146
1259
|
const start = i * 批次大小;
|
|
1147
1260
|
const end = Math.min(start + 批次大小, 目标数组.length);
|
|
@@ -1149,7 +1262,7 @@ class KingsoftAirscript {
|
|
|
1149
1262
|
}),
|
|
1150
1263
|
字段路径: 数组路径,
|
|
1151
1264
|
总数据条数: 目标数组.length,
|
|
1152
|
-
|
|
1265
|
+
并发数,
|
|
1153
1266
|
};
|
|
1154
1267
|
const 合并结果 = {
|
|
1155
1268
|
分批汇总,
|
|
@@ -1159,20 +1272,16 @@ class KingsoftAirscript {
|
|
|
1159
1272
|
};
|
|
1160
1273
|
return [{ json: 合并结果, pairedItem: { item: 索引 } }];
|
|
1161
1274
|
}
|
|
1162
|
-
|
|
1163
|
-
return 批次结果.flat();
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
else {
|
|
1167
|
-
const 响应 = await 执行一次(上下文, 调试字段);
|
|
1168
|
-
const 附加 = opt.w_debug ? { _调试: 调试字段 } : undefined;
|
|
1169
|
-
return 格式化输出(响应, 索引, opt, 附加, 操作类型);
|
|
1275
|
+
return 批次结果.flat();
|
|
1170
1276
|
}
|
|
1277
|
+
const 响应 = await 执行一次(上下文, 调试字段);
|
|
1278
|
+
const 附加 = opt.w_debug ? { _调试: 调试字段 } : undefined;
|
|
1279
|
+
return 格式化输出(响应, 索引, opt, 附加, 操作类型);
|
|
1171
1280
|
};
|
|
1172
|
-
const 安全执行单个项目 = async (itemIndex) => {
|
|
1173
|
-
var _a, _b, _c
|
|
1281
|
+
const 安全执行单个项目 = async (itemIndex, 并发闸门) => {
|
|
1282
|
+
var _a, _b, _c;
|
|
1174
1283
|
try {
|
|
1175
|
-
return await 处理单个项目(itemIndex);
|
|
1284
|
+
return await 处理单个项目(itemIndex, 并发闸门);
|
|
1176
1285
|
}
|
|
1177
1286
|
catch (e) {
|
|
1178
1287
|
if (!this.continueOnFail())
|
|
@@ -1183,30 +1292,34 @@ class KingsoftAirscript {
|
|
|
1183
1292
|
json: {
|
|
1184
1293
|
error: 提取错误消息(err),
|
|
1185
1294
|
code: (_a = err.code) !== null && _a !== void 0 ? _a : null,
|
|
1186
|
-
statusCode: (
|
|
1187
|
-
details: (
|
|
1295
|
+
statusCode: (_b = getStatusCode(err)) !== null && _b !== void 0 ? _b : null,
|
|
1296
|
+
details: (_c = getBody(err)) !== null && _c !== void 0 ? _c : null,
|
|
1188
1297
|
},
|
|
1189
1298
|
pairedItem: { item: itemIndex },
|
|
1190
1299
|
},
|
|
1191
1300
|
];
|
|
1192
1301
|
}
|
|
1193
1302
|
};
|
|
1194
|
-
const
|
|
1303
|
+
const operation0 = this.getNodeParameter('operation', 0, 'runScriptSync');
|
|
1304
|
+
const payloadMode0 = this.getNodeParameter('payloadMode', 0, 'argvFromUI');
|
|
1305
|
+
const appendOnce = (operation0 === 'runScriptSync' || operation0 === 'runScriptAsync')
|
|
1306
|
+
&& payloadMode0 === 'appendItemsToArrayField';
|
|
1307
|
+
const indicesToRun = appendOnce ? [0] : Array.from({ length: 输入数据项列表.length }, (_, i) => i);
|
|
1195
1308
|
const 汇总输出 = [];
|
|
1196
|
-
if (
|
|
1197
|
-
const 批处理数量 = Math.max(1,
|
|
1198
|
-
for (let i = 0; i <
|
|
1199
|
-
const
|
|
1200
|
-
const 任务函数列表 =
|
|
1201
|
-
const 批次结果 = await 并发执行(任务函数列表,
|
|
1309
|
+
if (opt0.a_parallelExecution) {
|
|
1310
|
+
const 批处理数量 = Math.max(1, opt0.e_batchSize);
|
|
1311
|
+
for (let i = 0; i < indicesToRun.length; i += 批处理数量) {
|
|
1312
|
+
const slice = indicesToRun.slice(i, i + 批处理数量);
|
|
1313
|
+
const 任务函数列表 = slice.map((idx) => () => 安全执行单个项目(idx, 全局并发闸门));
|
|
1314
|
+
const 批次结果 = await 并发执行(任务函数列表, slice.length);
|
|
1202
1315
|
for (const 单项结果 of 批次结果) {
|
|
1203
1316
|
汇总输出.push(...单项结果);
|
|
1204
1317
|
}
|
|
1205
1318
|
}
|
|
1206
1319
|
}
|
|
1207
1320
|
else {
|
|
1208
|
-
for (
|
|
1209
|
-
const 单项结果 = await 安全执行单个项目(
|
|
1321
|
+
for (const idx of indicesToRun) {
|
|
1322
|
+
const 单项结果 = await 安全执行单个项目(idx, 全局并发闸门);
|
|
1210
1323
|
汇总输出.push(...单项结果);
|
|
1211
1324
|
}
|
|
1212
1325
|
}
|