weaver-e10-builder 1.0.4-beta → 1.0.8-beta
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/commands/form-add-detail-table.d.ts +3 -0
- package/dist/commands/form-add-detail-table.d.ts.map +1 -0
- package/dist/commands/form-add-detail-table.js +153 -0
- package/dist/commands/form-add-detail-table.js.map +1 -0
- package/dist/commands/form-association.d.ts +3 -0
- package/dist/commands/form-association.d.ts.map +1 -0
- package/dist/commands/form-association.js +299 -0
- package/dist/commands/form-association.js.map +1 -0
- package/dist/commands/form-list-filter.d.ts.map +1 -1
- package/dist/commands/form-list-filter.js +4 -2
- package/dist/commands/form-list-filter.js.map +1 -1
- package/dist/commands/form-list-search-group.d.ts.map +1 -1
- package/dist/commands/form-list-search-group.js +10 -3
- package/dist/commands/form-list-search-group.js.map +1 -1
- package/dist/commands/form-list-stats.d.ts.map +1 -1
- package/dist/commands/form-list-stats.js +3 -1
- package/dist/commands/form-list-stats.js.map +1 -1
- package/dist/commands/form-list-utils.d.ts +13 -0
- package/dist/commands/form-list-utils.d.ts.map +1 -1
- package/dist/commands/form-list-utils.js +87 -17
- package/dist/commands/form-list-utils.js.map +1 -1
- package/dist/commands/form-list.d.ts.map +1 -1
- package/dist/commands/form-list.js +51 -0
- package/dist/commands/form-list.js.map +1 -1
- package/dist/commands/form-native.d.ts +17 -0
- package/dist/commands/form-native.d.ts.map +1 -0
- package/dist/commands/form-native.js +136 -0
- package/dist/commands/form-native.js.map +1 -0
- package/dist/commands/form-permission.d.ts.map +1 -1
- package/dist/commands/form-permission.js +8 -1
- package/dist/commands/form-permission.js.map +1 -1
- package/dist/commands/matrix.d.ts.map +1 -1
- package/dist/commands/matrix.js +8 -6
- package/dist/commands/matrix.js.map +1 -1
- package/dist/commands/wf-form.d.ts +3 -0
- package/dist/commands/wf-form.d.ts.map +1 -0
- package/dist/commands/wf-form.js +1784 -0
- package/dist/commands/wf-form.js.map +1 -0
- package/dist/commands/workflow-action.d.ts.map +1 -1
- package/dist/commands/workflow-action.js +34 -28
- package/dist/commands/workflow-action.js.map +1 -1
- package/dist/commands/workflow-condition.d.ts.map +1 -1
- package/dist/commands/workflow-condition.js +193 -60
- package/dist/commands/workflow-condition.js.map +1 -1
- package/dist/commands/workflow-create-workflow.d.ts +3 -0
- package/dist/commands/workflow-create-workflow.d.ts.map +1 -0
- package/dist/commands/workflow-create-workflow.js +264 -0
- package/dist/commands/workflow-create-workflow.js.map +1 -0
- package/dist/commands/workflow-node-robot.d.ts +3 -0
- package/dist/commands/workflow-node-robot.d.ts.map +1 -0
- package/dist/commands/workflow-node-robot.js +180 -0
- package/dist/commands/workflow-node-robot.js.map +1 -0
- package/dist/commands/workflow-node-validate.d.ts.map +1 -1
- package/dist/commands/workflow-node-validate.js +57 -46
- package/dist/commands/workflow-node-validate.js.map +1 -1
- package/dist/commands/workflow-node.d.ts.map +1 -1
- package/dist/commands/workflow-node.js +171 -9
- package/dist/commands/workflow-node.js.map +1 -1
- package/dist/commands/workflow-numbering.d.ts.map +1 -1
- package/dist/commands/workflow-numbering.js +98 -2
- package/dist/commands/workflow-numbering.js.map +1 -1
- package/dist/commands/workflow-operator-sign.d.ts +3 -0
- package/dist/commands/workflow-operator-sign.d.ts.map +1 -0
- package/dist/commands/workflow-operator-sign.js +118 -0
- package/dist/commands/workflow-operator-sign.js.map +1 -0
- package/dist/commands/workflow-segment.d.ts +3 -0
- package/dist/commands/workflow-segment.d.ts.map +1 -0
- package/dist/commands/workflow-segment.js +333 -0
- package/dist/commands/workflow-segment.js.map +1 -0
- package/dist/commands/workflow-subprocess.d.ts +3 -0
- package/dist/commands/workflow-subprocess.d.ts.map +1 -0
- package/dist/commands/workflow-subprocess.js +496 -0
- package/dist/commands/workflow-subprocess.js.map +1 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +217 -62
- package/dist/commands/workflow.js.map +1 -1
- package/dist/core/lzw.d.ts +16 -0
- package/dist/core/lzw.d.ts.map +1 -0
- package/dist/core/lzw.js +71 -0
- package/dist/core/lzw.js.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/services/condition-rules.d.ts.map +1 -1
- package/dist/services/condition-rules.js +83 -30
- package/dist/services/condition-rules.js.map +1 -1
- package/dist/services/workflow-initiator.d.ts +15 -0
- package/dist/services/workflow-initiator.d.ts.map +1 -0
- package/dist/services/workflow-initiator.js +77 -0
- package/dist/services/workflow-initiator.js.map +1 -0
- package/dist/services/workflow-layout.d.ts +13 -2
- package/dist/services/workflow-layout.d.ts.map +1 -1
- package/dist/services/workflow-layout.js +73 -27
- package/dist/services/workflow-layout.js.map +1 -1
- package/package.json +1 -1
|
@@ -90,7 +90,9 @@ export function registerWorkflowCommands(program) {
|
|
|
90
90
|
.argument('<formObjId>', '表单 objId')
|
|
91
91
|
.argument('<name>', '流程名称')
|
|
92
92
|
.argument('[desc]', '流程描述', '')
|
|
93
|
+
.option('--workflow-type <type>', '工作流类型:名称(如"公文审批")或 ID(默认 -1=其它)', '-1')
|
|
93
94
|
.option('--no-menu', '不自动添加发起菜单(默认建流程后自动加,指向表单新建页)')
|
|
95
|
+
.option('--no-auto-layout', '跳过建后自动排版节点(默认建完跑 auto-layout)')
|
|
94
96
|
.action(async (appId, formObjId, name, desc, cmdOpts) => {
|
|
95
97
|
const opts = program.opts();
|
|
96
98
|
const auth = await AuthSession.fromOptions(opts);
|
|
@@ -106,6 +108,18 @@ export function registerWorkflowCommands(program) {
|
|
|
106
108
|
process.exit(1);
|
|
107
109
|
}
|
|
108
110
|
console.error(` objId ${formObjId} -> formId ${realFormId}`);
|
|
111
|
+
// 工作流类型:认 ID(如 -1=其它)或名称(如"公文审批")。名称走 workflowPathTypeBrowser 解析。
|
|
112
|
+
// eb 流程也有流程类型概念,只是默认 -1(其它)。
|
|
113
|
+
let workflowType = cmdOpts.workflowType || '-1';
|
|
114
|
+
if (workflowType !== '-1' && !/^-?\d+$/.test(workflowType)) {
|
|
115
|
+
const tRes = await client.post(`${baseUrl}/api/workflow/pathdef/common/browser/complete/workflowPathTypeBrowser`, { browserMultiple: false, belongType: 1, showAddBtn: true, checkDetachable: true, newly: 1, searchValue: workflowType });
|
|
116
|
+
const types = tRes?.data?.data || [];
|
|
117
|
+
const hit = types.find((t) => t.name === workflowType || t.content === workflowType) || (types.length === 1 ? types[0] : null);
|
|
118
|
+
if (!hit)
|
|
119
|
+
throw new Error(`工作流类型 "${workflowType}" 未找到(可用: ${types.map((t) => t.name).join(', ')} 或 -1=其它)`);
|
|
120
|
+
workflowType = String(hit.id);
|
|
121
|
+
console.error(` 工作流类型: ${hit.name} (${workflowType})`);
|
|
122
|
+
}
|
|
109
123
|
// Create workflow
|
|
110
124
|
const ts = Date.now();
|
|
111
125
|
const payload = {
|
|
@@ -113,7 +127,7 @@ export function registerWorkflowCommands(program) {
|
|
|
113
127
|
createClient: '0', ebFormId: realFormId, createPcShow: ['0'], wfSymbol: '',
|
|
114
128
|
orderId: '0.0', moduleCard: 0, createType: '0', workflowName: name,
|
|
115
129
|
workflowDesc: desc, relateForm: '4', isLock: '0', isFree: '0',
|
|
116
|
-
addDefaultHide: 0, createPcShowCustom: '', workflowType
|
|
130
|
+
addDefaultHide: 0, createPcShowCustom: '', workflowType, id: '0',
|
|
117
131
|
workflowNameMultiLang: { tablefiled: 'wfp_base.workflowname', targetId: String(ts), needReplaceTargetId: true },
|
|
118
132
|
createMobileShowCustom: '', status: '1', createMobileShow: ['0'],
|
|
119
133
|
formMode: '0', formId: 0, relateFormMode: '0', workflowId: -1,
|
|
@@ -179,6 +193,17 @@ export function registerWorkflowCommands(program) {
|
|
|
179
193
|
catch {
|
|
180
194
|
console.error(' 警告: 无法自动设置发起权限,请手动设置');
|
|
181
195
|
}
|
|
196
|
+
// 流程节点自动排版(建好即布局,避免节点堆叠在原点;与工作流程 create-workflow 对齐)。
|
|
197
|
+
if (cmdOpts.autoLayout) {
|
|
198
|
+
try {
|
|
199
|
+
const { autoLayoutWorkflow } = await import('../services/workflow-layout.js');
|
|
200
|
+
await autoLayoutWorkflow({ client, baseUrl, workflowId });
|
|
201
|
+
console.error(' 节点已自动排版(auto-layout)');
|
|
202
|
+
}
|
|
203
|
+
catch (e) {
|
|
204
|
+
console.error(` 警告: 自动排版失败: ${e.message}(可用 workflow auto-layout <wf> 手动重排)`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
182
207
|
const workflowUrl = `${baseUrl}/sp/workflow/flowpage/create/${workflowId}`;
|
|
183
208
|
// Auto-add 发起 menu (LAYOUT → form create page, triggers bound workflow)
|
|
184
209
|
let menuId = null;
|
|
@@ -256,7 +281,7 @@ export function registerWorkflowCommands(program) {
|
|
|
256
281
|
const baseUrl = auth.getBaseUrl();
|
|
257
282
|
const body = {
|
|
258
283
|
isTemplate: 0,
|
|
259
|
-
belongType: parseInt(cmdOpts.belong)
|
|
284
|
+
belongType: cmdOpts.belong !== undefined && cmdOpts.belong !== '' ? parseInt(cmdOpts.belong) : 1,
|
|
260
285
|
current: parseInt(cmdOpts.pageNo) || 1,
|
|
261
286
|
pageSize: parseInt(cmdOpts.pageSize) || 20,
|
|
262
287
|
searchParams: {
|
|
@@ -443,11 +468,13 @@ export function registerWorkflowCommands(program) {
|
|
|
443
468
|
.argument('<workflowId>', '流程 ID')
|
|
444
469
|
.argument('<nodeId>', '节点 ID')
|
|
445
470
|
.argument('[keyword]', '人员/角色关键词(--type form 时不需要)', '')
|
|
446
|
-
.option('--type <type>', '操作者类型: user(指定人) / role(指定角色) / dept(指定部门) / position(指定岗位) / all(所有人) / free(自由选择) / superior(发起人上级) / prev-node(上一节点) / form(表单相关人员) / matrix(矩阵对应)', 'user')
|
|
471
|
+
.option('--type <type>', '操作者类型: user(指定人) / role(指定角色) / dept(指定部门) / position(指定岗位) / all(所有人) / free(自由选择) / superior(发起人上级) / initiator(流程发起人本人) / prev-node(上一节点) / form(表单相关人员) / matrix(矩阵对应)', 'user')
|
|
447
472
|
.option('--source <formObjId>', '表单 ID(--type form 时必填)')
|
|
448
473
|
.option('--target <fieldId>', '人员字段 ID(--type form 时必填)')
|
|
449
474
|
.option('--condition <json>', '筛选条件 JSON / @文件(--type form 时可选)')
|
|
450
|
-
.option('--sign-order <order>', '签署顺序: 会签(默认) / 非会签 / 竞签 / 依次处理 / 抄送 / 抄送需批注', '会签')
|
|
475
|
+
.option('--sign-order <order>', '签署顺序: 会签(默认) / 非会签 / 竞签 / 依次处理(默认倒序) / 抄送 / 抄送需批注', '会签')
|
|
476
|
+
.option('--execute-order <spec>', '依次处理的执行顺序码: 2-2 人员显示顺序-倒序(默认) / 2-1 正序 / 1-1,2-2 安全级别正序+人员显示倒序', '')
|
|
477
|
+
.option('--dept-scope <scope>', '指定部门的范围: 本部门 / 本及下级(默认)', '本及下级')
|
|
451
478
|
.option('--orders <orders>', '批次号(两位小数,如 0.00 / 1.00)', '0.00')
|
|
452
479
|
.option('--workflow-form <objId>', '流程绑定的表单 objId(valueFieldId 引用字段时在此表单查找)')
|
|
453
480
|
.option('--matrix-id <id>', '矩阵 ID(--type matrix 必填)')
|
|
@@ -455,11 +482,15 @@ export function registerWorkflowCommands(program) {
|
|
|
455
482
|
.option('--matrix-rule <rules...>', '矩阵条件映射规则。格式: "条件configId:数据来源type:匹配operate:维度virtualId"。type: 0=指定部门/1=发起人部门/5=当前操作人部门。operate: 1=本部门/2=本及下级/3=本及上级/49=逐级向上/67=本及下级逐级向上')
|
|
456
483
|
.option('--batch-condition <expr>', '批次条件表达式(--type matrix 可选)')
|
|
457
484
|
.option('--append', '追加操作者组(不清空节点已有操作者组;默认是清空后全量重建)')
|
|
485
|
+
.option('--segment', '片段节点操作者(内部 workflowId 用 -99999999;nodeId 传片段节点 id)')
|
|
458
486
|
.action(async (workflowId, nodeId, keyword, cmdOpts) => {
|
|
459
487
|
const opts = program.opts();
|
|
460
488
|
const auth = await AuthSession.fromOptions(opts);
|
|
461
489
|
if (!auth)
|
|
462
490
|
process.exit(1);
|
|
491
|
+
// 片段节点操作者走 workflowId=-99999999 变体(抓包确认 saveOperatorGroup isPub=1)
|
|
492
|
+
if (cmdOpts.segment)
|
|
493
|
+
workflowId = '-99999999';
|
|
463
494
|
const client = new ApiClient(auth);
|
|
464
495
|
const baseUrl = auth.getBaseUrl();
|
|
465
496
|
// 追加模式(--append)下提示语用「追加」,否则「设置」
|
|
@@ -487,16 +518,19 @@ export function registerWorkflowCommands(program) {
|
|
|
487
518
|
let itemLevel = '';
|
|
488
519
|
let includeType = '';
|
|
489
520
|
let includeTypeCN = '';
|
|
490
|
-
const isSuperior = cmdOpts.type === 'superior';
|
|
521
|
+
const isSuperior = cmdOpts.type === 'superior' || cmdOpts.type === 'initiator';
|
|
491
522
|
if (isSuperior) {
|
|
492
|
-
//
|
|
523
|
+
// 发起人上级(superior) / 流程发起人本人(initiator):无 keyword,固定字段。
|
|
524
|
+
// 区别(抓包 2026-08-24):本人 includeType=12+itemName=本人+isSuportVirtualId/openProjectOrganization=true;
|
|
525
|
+
// 上级 includeType=13+itemName=直接上级+这两个 false。
|
|
526
|
+
const isInitiator = cmdOpts.type === 'initiator';
|
|
493
527
|
targetId = '';
|
|
494
|
-
targetName = '直接上级';
|
|
528
|
+
targetName = isInitiator ? '本人' : '直接上级';
|
|
495
529
|
groupType = '流程发起人';
|
|
496
530
|
groupTypeId = '114';
|
|
497
|
-
itemName = '直接上级';
|
|
498
|
-
// Build payload directly — superior has no browserData
|
|
499
|
-
console.error(` 操作者:
|
|
531
|
+
itemName = isInitiator ? '本人' : '直接上级';
|
|
532
|
+
// Build payload directly — superior/initiator has no browserData
|
|
533
|
+
console.error(` 操作者: ${isInitiator ? '流程发起人(本人)' : '发起人上级(直接上级)'} 类型: ${groupType}`);
|
|
500
534
|
const rg = await client.post(`${baseUrl}/api/bs/workflow/pathdef/nodeOperator/getLayoutConfigInfo`, {
|
|
501
535
|
groupId: '', workflowId, nodeId, sourceType: '1', isOperatorRuleAuth: true,
|
|
502
536
|
});
|
|
@@ -504,8 +538,10 @@ export function registerWorkflowCommands(program) {
|
|
|
504
538
|
const payload = {
|
|
505
539
|
workflowId, nodeId, groupId: '', isCreate: '', reserveGroupId,
|
|
506
540
|
itemDatas: [{
|
|
507
|
-
includeType: '13',
|
|
508
|
-
includeTypeCN: '上级',
|
|
541
|
+
includeType: isInitiator ? '12' : '13',
|
|
542
|
+
includeTypeCN: isInitiator ? '本人' : '上级',
|
|
543
|
+
virtualId: '',
|
|
544
|
+
virtualIdCN: '',
|
|
509
545
|
objLevelType: '1',
|
|
510
546
|
objLevelTypeCN: '全部机构',
|
|
511
547
|
objectId: '1',
|
|
@@ -530,8 +566,8 @@ export function registerWorkflowCommands(program) {
|
|
|
530
566
|
condition: '',
|
|
531
567
|
groupCondition: '',
|
|
532
568
|
level: '',
|
|
533
|
-
isSuportVirtualId:
|
|
534
|
-
openProjectOrganization:
|
|
569
|
+
isSuportVirtualId: isInitiator,
|
|
570
|
+
openProjectOrganization: isInitiator,
|
|
535
571
|
isExtendType: 0,
|
|
536
572
|
}],
|
|
537
573
|
oldGroupName: '',
|
|
@@ -543,9 +579,10 @@ export function registerWorkflowCommands(program) {
|
|
|
543
579
|
};
|
|
544
580
|
const data = await client.post(`${baseUrl}/api/bs/workflow/pathdef/nodeOperator/saveOperatorGroup`, payload);
|
|
545
581
|
if (data?.code === 200 && data?.status) {
|
|
582
|
+
const label = isInitiator ? '流程发起人(本人)' : '发起人上级(直接上级)';
|
|
546
583
|
const msg = opts.json
|
|
547
|
-
? JSON.stringify({ success: true, workflowId, nodeId, operator:
|
|
548
|
-
: `${verb}:
|
|
584
|
+
? JSON.stringify({ success: true, workflowId, nodeId, operator: label, type: groupType, append: !!cmdOpts.append })
|
|
585
|
+
: `${verb}: ${label} → 节点 ${nodeId}`;
|
|
549
586
|
console.log(msg);
|
|
550
587
|
}
|
|
551
588
|
else {
|
|
@@ -698,16 +735,38 @@ export function registerWorkflowCommands(program) {
|
|
|
698
735
|
};
|
|
699
736
|
ebFormConditionCn = `( ${cond.fieldName || cond.fieldId} ${funcMap[cond.func] || cond.func} '${valueDesc}' )`;
|
|
700
737
|
}
|
|
701
|
-
|
|
702
|
-
|
|
738
|
+
// 表单相关人员签署顺序:与 user/role 分支同码(会签1/非会签0/竞签0+competeSignOrder/依次2/抄送3/抄送需批注4)。
|
|
739
|
+
// 或签 当作竞签(表单字段多人"任一人签"语义一致)。
|
|
740
|
+
const formSignOrderMap = {
|
|
741
|
+
'会签': { code: '1', cn: '会签' },
|
|
742
|
+
'非会签': { code: '0', cn: '非会签' },
|
|
743
|
+
'竞签': { code: '0', cn: '非会签', competeSignOrder: '1', competeSignOrderCN: '竞签' },
|
|
744
|
+
'或签': { code: '0', cn: '非会签', competeSignOrder: '1', competeSignOrderCN: '竞签' },
|
|
745
|
+
'依次处理': { code: '2', cn: '依次逐个处理', executeOrders: '2-2', executeOrdersCN: '人员显示顺序-倒序' },
|
|
746
|
+
'抄送': { code: '3', cn: '抄送' },
|
|
747
|
+
'抄送需批注': { code: '4', cn: '抄送' },
|
|
748
|
+
};
|
|
749
|
+
const fso = formSignOrderMap[cmdOpts.signOrder || '会签'] || formSignOrderMap['会签'];
|
|
750
|
+
if (cmdOpts.executeOrder) {
|
|
751
|
+
const EC = { '2-2': '人员显示顺序-倒序', '2-1': '人员显示顺序-正序', '1-1': '安全级别-正序', '1-2': '安全级别-倒序', '1-1,2-2': '安全级别-正序,人员显示顺序-倒序', '1-1,2-1': '安全级别-正序,人员显示顺序-正序' };
|
|
752
|
+
fso.executeOrders = cmdOpts.executeOrder;
|
|
753
|
+
fso.executeOrdersCN = EC[cmdOpts.executeOrder] || cmdOpts.executeOrder;
|
|
754
|
+
}
|
|
755
|
+
const signOrder = fso.code;
|
|
756
|
+
const signOrderCN = fso.cn;
|
|
703
757
|
// Try to get form name and field name via API
|
|
704
758
|
let sourceIdCN = '';
|
|
705
759
|
let targetIdCN = '';
|
|
706
760
|
try {
|
|
707
761
|
const formFields = await client.post(`${baseUrl}/api/ebuilder/form/dataset/v1/getFields`, {
|
|
708
|
-
objId: cmdOpts.source, userid: auth.userId, tenantKey: auth.tenantKey,
|
|
762
|
+
objId: cmdOpts.source, userid: auth.userId, tenantKey: auth.tenantKey, isReturnDetail: 'y',
|
|
709
763
|
});
|
|
710
|
-
|
|
764
|
+
// 主表 + 明细字段都纳入(明细字段在 detailFields 里,含 subFormId)
|
|
765
|
+
const allFields = [
|
|
766
|
+
...(formFields?.data?.mainFields || []),
|
|
767
|
+
...(formFields?.data?.subFields || []),
|
|
768
|
+
...(formFields?.data?.detailFields || []).flatMap((dt) => dt.fields || []),
|
|
769
|
+
];
|
|
711
770
|
const targetField = allFields.find((f) => f.fieldId === cmdOpts.target || f.id === cmdOpts.target);
|
|
712
771
|
if (targetField) {
|
|
713
772
|
targetIdCN = targetField.fieldName || targetField.name || '';
|
|
@@ -723,6 +782,8 @@ export function registerWorkflowCommands(program) {
|
|
|
723
782
|
const itemData = {
|
|
724
783
|
signOrder,
|
|
725
784
|
signOrderCN,
|
|
785
|
+
...(fso.competeSignOrder ? { competeSignOrder: fso.competeSignOrder, competeSignOrderCN: fso.competeSignOrderCN } : {}),
|
|
786
|
+
...(fso.executeOrders ? { executeOrders: fso.executeOrders, executeOrdersCN: fso.executeOrdersCN } : {}),
|
|
726
787
|
isOut: false,
|
|
727
788
|
isSaveHrmOperator: false,
|
|
728
789
|
id: '1',
|
|
@@ -784,25 +845,43 @@ export function registerWorkflowCommands(program) {
|
|
|
784
845
|
console.error('--type dept 需要部门关键词');
|
|
785
846
|
process.exit(1);
|
|
786
847
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
848
|
+
// keyword 支持逗号分隔多部门;逐个解析
|
|
849
|
+
const deptNames = keyword.split(',').map((s) => s.trim()).filter(Boolean);
|
|
850
|
+
if (!deptNames.length) {
|
|
851
|
+
console.error('--type dept 需要部门关键词');
|
|
852
|
+
process.exit(1);
|
|
853
|
+
}
|
|
854
|
+
const depts = [];
|
|
855
|
+
const missingDepts = [];
|
|
856
|
+
for (const dn of deptNames) {
|
|
857
|
+
const deptRes = await client.post(`${baseUrl}/api/workflow/pathdef/common/browser/complete/department`, {
|
|
858
|
+
browserMultiple: true, virtualType: 'All', showSanYuan: true, newly: 0, searchValue: dn,
|
|
859
|
+
});
|
|
860
|
+
const d = deptRes?.data?.data?.[0];
|
|
861
|
+
if (!d) {
|
|
862
|
+
missingDepts.push(dn);
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
depts.push(d);
|
|
866
|
+
}
|
|
867
|
+
if (missingDepts.length) {
|
|
868
|
+
console.error(`未找到部门: ${missingDepts.join(',')}`);
|
|
793
869
|
process.exit(1);
|
|
794
870
|
}
|
|
871
|
+
// 部门范围:本部门(1, 单个部门内会签) / 本及下级(2, 默认)
|
|
872
|
+
const includeType = cmdOpts.deptScope === '本部门' ? '1' : '2';
|
|
873
|
+
const includeTypeCN = includeType === '1' ? '本部门' : '本部门及下级部门';
|
|
795
874
|
groupType = '指定部门';
|
|
796
875
|
groupTypeId = '102';
|
|
797
|
-
itemName =
|
|
798
|
-
itemData.hrmOperators =
|
|
799
|
-
itemData.hrmOperatorsCN =
|
|
800
|
-
itemData.includeType =
|
|
801
|
-
itemData.includeTypeCN =
|
|
876
|
+
itemName = depts.map((d) => `${d.name}(${includeTypeCN})`).join(',');
|
|
877
|
+
itemData.hrmOperators = depts.map((d) => d.id).join(',');
|
|
878
|
+
itemData.hrmOperatorsCN = depts.map((d) => d.name).join(',');
|
|
879
|
+
itemData.includeType = includeType;
|
|
880
|
+
itemData.includeTypeCN = includeTypeCN;
|
|
802
881
|
itemData.level = '10~90';
|
|
803
882
|
itemData.itemLevel = '10~90';
|
|
804
|
-
itemData.hrmBrowserDataDtos =
|
|
805
|
-
console.error(` 操作者: ${
|
|
883
|
+
itemData.hrmBrowserDataDtos = depts.map((d) => ({ id: d.id, name: d.name, _entityType: 'department' }));
|
|
884
|
+
console.error(` 操作者: ${depts.map((d) => d.name).join(',')} 类型: 指定部门(${includeTypeCN})`);
|
|
806
885
|
}
|
|
807
886
|
else if (cmdOpts.type === 'position') {
|
|
808
887
|
if (!keyword) {
|
|
@@ -861,11 +940,21 @@ export function registerWorkflowCommands(program) {
|
|
|
861
940
|
'会签': { code: '1', cn: '会签' },
|
|
862
941
|
'非会签': { code: '0', cn: '非会签' },
|
|
863
942
|
'竞签': { code: '0', cn: '非会签', competeSignOrder: '1', competeSignOrderCN: '竞签' },
|
|
864
|
-
'依次处理': { code: '2', cn: '
|
|
943
|
+
'依次处理': { code: '2', cn: '依次逐个处理', executeOrders: '2-2', executeOrdersCN: '人员显示顺序-倒序' },
|
|
865
944
|
'抄送': { code: '3', cn: '抄送' },
|
|
866
945
|
'抄送需批注': { code: '4', cn: '抄送' },
|
|
867
946
|
};
|
|
947
|
+
// executeOrders 顺序码 → 中文(依次处理时可 --execute-order 覆盖;默认 2-2 倒序)
|
|
948
|
+
const EXECUTE_ORDER_CN = {
|
|
949
|
+
'2-2': '人员显示顺序-倒序', '2-1': '人员显示顺序-正序',
|
|
950
|
+
'1-1': '安全级别-正序', '1-2': '安全级别-倒序',
|
|
951
|
+
'1-1,2-2': '安全级别-正序,人员显示顺序-倒序', '1-1,2-1': '安全级别-正序,人员显示顺序-正序',
|
|
952
|
+
};
|
|
868
953
|
const so = signOrderMap[cmdOpts.signOrder || '会签'] || signOrderMap['会签'];
|
|
954
|
+
if (cmdOpts.executeOrder) {
|
|
955
|
+
so.executeOrders = cmdOpts.executeOrder;
|
|
956
|
+
so.executeOrdersCN = EXECUTE_ORDER_CN[cmdOpts.executeOrder] || cmdOpts.executeOrder;
|
|
957
|
+
}
|
|
869
958
|
// Get reserveGroupId
|
|
870
959
|
const rg = await client.post(`${baseUrl}/api/bs/workflow/pathdef/nodeOperator/getLayoutConfigInfo`, {
|
|
871
960
|
groupId: '', workflowId, nodeId, sourceType: '1', isOperatorRuleAuth: true,
|
|
@@ -1037,24 +1126,13 @@ export function registerWorkflowCommands(program) {
|
|
|
1037
1126
|
includeTypeCN = '所有级别';
|
|
1038
1127
|
}
|
|
1039
1128
|
else {
|
|
1040
|
-
// Search users
|
|
1041
|
-
const
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
searchCount: 1,
|
|
1045
|
-
appDetachModule: 'EM',
|
|
1046
|
-
disableAppDetach: 0,
|
|
1047
|
-
pageNo: 1,
|
|
1048
|
-
pageSize: 1,
|
|
1049
|
-
});
|
|
1050
|
-
if (userData?.code !== 200 || !userData?.data?.userList?.length) {
|
|
1051
|
-
console.error(`未找到人员: ${keyword}`);
|
|
1129
|
+
// Search users — keyword 支持逗号分隔多人员(一个节点多人,如 闫宇,吴鹏)
|
|
1130
|
+
const names = keyword.split(',').map((s) => s.trim()).filter(Boolean);
|
|
1131
|
+
if (!names.length) {
|
|
1132
|
+
console.error('--type user 需要人员关键词');
|
|
1052
1133
|
process.exit(1);
|
|
1053
1134
|
}
|
|
1054
|
-
const
|
|
1055
|
-
targetId = emp.id || '';
|
|
1056
|
-
targetName = emp.name || '';
|
|
1057
|
-
browserData = {
|
|
1135
|
+
const mkBrowserData = (emp) => ({
|
|
1058
1136
|
id: emp.id || '',
|
|
1059
1137
|
cid: emp.cid || emp.companyId || '',
|
|
1060
1138
|
userid: emp.userid || emp.userId || emp.id || '',
|
|
@@ -1075,11 +1153,30 @@ export function registerWorkflowCommands(program) {
|
|
|
1075
1153
|
mainId: emp.mainId || emp.id || '',
|
|
1076
1154
|
stopDepartment: false,
|
|
1077
1155
|
leaf: true,
|
|
1078
|
-
};
|
|
1156
|
+
});
|
|
1157
|
+
const emps = [];
|
|
1158
|
+
const missing = [];
|
|
1159
|
+
for (const n of names) {
|
|
1160
|
+
const userData = await client.post(`${baseUrl}/api/hrm/common/getEmployeeByKeyWords`, {
|
|
1161
|
+
keyword: n, searchType: 1, searchCount: 1, appDetachModule: 'EM', disableAppDetach: 0, pageNo: 1, pageSize: 1,
|
|
1162
|
+
});
|
|
1163
|
+
const emp = userData?.data?.userList?.[0];
|
|
1164
|
+
if (!emp) {
|
|
1165
|
+
missing.push(n);
|
|
1166
|
+
continue;
|
|
1167
|
+
}
|
|
1168
|
+
emps.push(emp);
|
|
1169
|
+
}
|
|
1170
|
+
if (missing.length) {
|
|
1171
|
+
console.error(`未找到人员: ${missing.join(',')}`);
|
|
1172
|
+
process.exit(1);
|
|
1173
|
+
}
|
|
1174
|
+
targetId = emps.map((e) => e.id || '').join(',');
|
|
1175
|
+
targetName = emps.map((e) => e.name || '').join(',');
|
|
1176
|
+
browserDatas = emps.map(mkBrowserData);
|
|
1079
1177
|
groupType = '指定人';
|
|
1080
1178
|
groupTypeId = '101';
|
|
1081
|
-
itemName =
|
|
1082
|
-
browserDatas = [browserData];
|
|
1179
|
+
itemName = targetName;
|
|
1083
1180
|
}
|
|
1084
1181
|
console.error(` 操作者: ${targetName} (${targetId}) 类型: ${groupType}`);
|
|
1085
1182
|
// 2. Get reserveGroupId from layout config
|
|
@@ -1092,11 +1189,16 @@ export function registerWorkflowCommands(program) {
|
|
|
1092
1189
|
'会签': { code: '1', cn: '会签' },
|
|
1093
1190
|
'非会签': { code: '0', cn: '非会签' },
|
|
1094
1191
|
'竞签': { code: '0', cn: '非会签', competeSignOrder: '1', competeSignOrderCN: '竞签' },
|
|
1095
|
-
'依次处理': { code: '2', cn: '
|
|
1192
|
+
'依次处理': { code: '2', cn: '依次逐个处理', executeOrders: '2-2', executeOrdersCN: '人员显示顺序-倒序' },
|
|
1096
1193
|
'抄送': { code: '3', cn: '抄送' },
|
|
1097
1194
|
'抄送需批注': { code: '4', cn: '抄送' },
|
|
1098
1195
|
};
|
|
1099
1196
|
const so = soMap[cmdOpts.signOrder || '会签'] || soMap['会签'];
|
|
1197
|
+
if (cmdOpts.executeOrder) {
|
|
1198
|
+
const EXEC_CN = { '2-2': '人员显示顺序-倒序', '2-1': '人员显示顺序-正序', '1-1': '安全级别-正序', '1-2': '安全级别-倒序', '1-1,2-2': '安全级别-正序,人员显示顺序-倒序', '1-1,2-1': '安全级别-正序,人员显示顺序-正序' };
|
|
1199
|
+
so.executeOrders = cmdOpts.executeOrder;
|
|
1200
|
+
so.executeOrdersCN = EXEC_CN[cmdOpts.executeOrder] || cmdOpts.executeOrder;
|
|
1201
|
+
}
|
|
1100
1202
|
const itemData = {
|
|
1101
1203
|
hrmOperators: targetId,
|
|
1102
1204
|
hrmOperatorsCN: targetName,
|
|
@@ -1414,7 +1516,7 @@ export function registerWorkflowCommands(program) {
|
|
|
1414
1516
|
'1': '审批',
|
|
1415
1517
|
'2': '确认/会签',
|
|
1416
1518
|
'3': '归档',
|
|
1417
|
-
'5': '
|
|
1519
|
+
'5': '投票',
|
|
1418
1520
|
'7': '自动处理',
|
|
1419
1521
|
'8': '等待',
|
|
1420
1522
|
'forkstart': '分流点',
|
|
@@ -1568,6 +1670,7 @@ export function registerWorkflowCommands(program) {
|
|
|
1568
1670
|
.argument('<xml>', '浏览器格式的 XML 或 @文件路径')
|
|
1569
1671
|
.option('--delete-links <ids>', '要删除的连线 ID,逗号分隔')
|
|
1570
1672
|
.option('--delete-nodes <ids>', '要删除的节点 ID,逗号分隔')
|
|
1673
|
+
.option('--chart-src <n>', '图表来源:0=普通流程(默认) / 1=公用流转片段', '0')
|
|
1571
1674
|
.action(async (workflowId, xmlArg, cmdOpts) => {
|
|
1572
1675
|
const opts = program.opts();
|
|
1573
1676
|
const auth = await AuthSession.fromOptions(opts);
|
|
@@ -1592,7 +1695,7 @@ export function registerWorkflowCommands(program) {
|
|
|
1592
1695
|
// 不要转成 node_X/link_X——服务器解析不了会静默失败。直接回传浏览器格式 XML,
|
|
1593
1696
|
// 仅对服务器不存在的 nodeId/linkId(新增节点/连线)注入 flag="add"。
|
|
1594
1697
|
try {
|
|
1595
|
-
const chartData = await client.postForm(`${baseUrl}/api/bs/workflow/pathdef/chart/getXml`, `workflowId=${workflowId}&keepTitle=undefined&showType=0`);
|
|
1698
|
+
const chartData = await client.postForm(`${baseUrl}/api/bs/workflow/pathdef/chart/getXml`, `workflowId=${workflowId}&keepTitle=undefined&showType=0&chartSrc=${cmdOpts.chartSrc}`);
|
|
1596
1699
|
const serverXml = chartData?.data?.xml || '';
|
|
1597
1700
|
if (serverXml) {
|
|
1598
1701
|
const knownNodes = new Set([...serverXml.matchAll(/nodeId="(\d+)"/g)].map(m => m[1]));
|
|
@@ -1614,13 +1717,13 @@ export function registerWorkflowCommands(program) {
|
|
|
1614
1717
|
catch { /* best effort */ }
|
|
1615
1718
|
// Lock the chart for editing (browser does this before save)
|
|
1616
1719
|
try {
|
|
1617
|
-
await client.postForm(`${baseUrl}/api/bs/workflow/pathdef/chart/checkoutHeart`, `workflowId=${workflowId}&chartSrc
|
|
1720
|
+
await client.postForm(`${baseUrl}/api/bs/workflow/pathdef/chart/checkoutHeart`, `workflowId=${workflowId}&chartSrc=${cmdOpts.chartSrc}`);
|
|
1618
1721
|
}
|
|
1619
1722
|
catch { /* best effort */ }
|
|
1620
1723
|
// Base64-encode: standard base64 then replace + with $ (avoids form-decoding + as space)
|
|
1621
1724
|
const xmlB64 = Buffer.from(xml).toString('base64').replace(/\+/g, '$');
|
|
1622
1725
|
// Build form body — server expects unencoded JSON braces
|
|
1623
|
-
const body = `workflowId=${workflowId}&deleteLinks=${cmdOpts.deleteLinks || ''}&deleteNodes=${cmdOpts.deleteNodes || ''}&groups={"col":[],"row":[]}&deleteGroups=&templateKey=0&chartSrc
|
|
1726
|
+
const body = `workflowId=${workflowId}&deleteLinks=${cmdOpts.deleteLinks || ''}&deleteNodes=${cmdOpts.deleteNodes || ''}&groups={"col":[],"row":[]}&deleteGroups=&templateKey=0&chartSrc=${cmdOpts.chartSrc}&showConditionName=false&showLinkName=false&isSaveBySkipLinkValidate=false&xml=${xmlB64}`;
|
|
1624
1727
|
const data = await client.postForm(`${baseUrl}/api/bs/workflow/pathdef/chart/saveLayout`, body);
|
|
1625
1728
|
if (data?.code === 200 && data?.status) {
|
|
1626
1729
|
const msg = opts.json
|
|
@@ -2246,18 +2349,70 @@ export function registerWorkflowCommands(program) {
|
|
|
2246
2349
|
const fieldName = parsed.fieldName || '';
|
|
2247
2350
|
const value = String(parsed.value);
|
|
2248
2351
|
const nodeName = parsed.nodeName || '节点';
|
|
2249
|
-
const
|
|
2352
|
+
const client = new ApiClient(auth);
|
|
2353
|
+
const baseUrl = auth.getBaseUrl();
|
|
2354
|
+
// 触发时机(抓包确认):正向离开=after+["1"] / 退回到达=pre+["2"]。
|
|
2355
|
+
// trigger 值:pre(到达) / after 或 leave(正向离开) / back-arrive(退回到达) / delete / save / revert / pause / cancel
|
|
2356
|
+
// trigger 含 '-' 时为时机别名,拆出 triggerType + executeTime;其余直接当 triggerType,executeTime 默认 ["1"]。
|
|
2357
|
+
const rawTrigger = parsed.trigger || 'pre';
|
|
2358
|
+
let triggerType = rawTrigger;
|
|
2359
|
+
let executeTime = ['1'];
|
|
2360
|
+
if (rawTrigger === 'leave' || rawTrigger === 'after') {
|
|
2361
|
+
triggerType = 'after';
|
|
2362
|
+
executeTime = ['1'];
|
|
2363
|
+
}
|
|
2364
|
+
else if (rawTrigger === 'back-arrive' || rawTrigger === 'back') {
|
|
2365
|
+
triggerType = 'pre';
|
|
2366
|
+
executeTime = ['2'];
|
|
2367
|
+
}
|
|
2368
|
+
else if (Array.isArray(parsed.executeTime))
|
|
2369
|
+
executeTime = parsed.executeTime;
|
|
2370
|
+
// Select/SelectMultiple 字段常量赋值 customValue 必须存选项 valueKey:
|
|
2371
|
+
// 流程表单 Select valueKey=序号(0/1/2);eb 表 Select valueKey=雪花id(=selectionId)。
|
|
2372
|
+
// 存选项名会导致设计器打开值空、actionName 值部分被清。
|
|
2373
|
+
// 两类表单字段读取接口不同,需兼容:先 workflow 接口(流程表单),读不到再 eb 接口(eb 表关联流程)。
|
|
2374
|
+
// formId 从 getDisplayLayoutForm 反查(流程表单=formId,eb 表=关联 eb 表 formId)。
|
|
2375
|
+
let customValue = value;
|
|
2376
|
+
try {
|
|
2377
|
+
const dl = await client.get(`${baseUrl}/api/bs/workflow/pathdef/nodeLayout/getDisplayLayoutForm?workflowId=${wf}&nodeId=${nodeId}`);
|
|
2378
|
+
const fid = String(dl?.data?.formId || '');
|
|
2379
|
+
if (fid && parsed.fieldId) {
|
|
2380
|
+
let f = {};
|
|
2381
|
+
// ① workflow 接口(流程表单 Select,valueKey=0/1/2)
|
|
2382
|
+
try {
|
|
2383
|
+
const gf = await client.post(`${baseUrl}/api/workflow/core/form/field/manage/getFormField`, { module: 'workflow', formTableField: { formField: { id: parsed.fieldId, form: { id: fid } } } }, { ebbusinessid: fid });
|
|
2384
|
+
f = gf?.data || {};
|
|
2385
|
+
}
|
|
2386
|
+
catch { /* try eb */ }
|
|
2387
|
+
// ② workflow 接口读不到 options(eb 流程字段在 eb 表)→ eb 接口(valueKey=雪花id)
|
|
2388
|
+
// eb 接口需 customParam:{objId}(用 formId 当 objId 即可读到 options,抓包确认)
|
|
2389
|
+
if (!Array.isArray(f.options) || f.options.length === 0) {
|
|
2390
|
+
try {
|
|
2391
|
+
const gf2 = await client.post(`${baseUrl}/api/ebuilder/form/form/field/manage/getFormField`, { module: 'ebuilderform', customParam: { objId: fid }, formTableField: { formField: { id: parsed.fieldId, form: { id: fid } } } }, { ebbusinessid: fid });
|
|
2392
|
+
f = gf2?.data || {};
|
|
2393
|
+
}
|
|
2394
|
+
catch { /* 保持 */ }
|
|
2395
|
+
}
|
|
2396
|
+
if (/select/i.test(String(f.type || f.componentKey || ''))) {
|
|
2397
|
+
const opts = Array.isArray(f.options) ? f.options : [];
|
|
2398
|
+
const hit = opts.find((o) => o.name === value);
|
|
2399
|
+
if (hit)
|
|
2400
|
+
customValue = String(hit.valueKey);
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
catch { /* 解析失败保持原值(非 Select 或字段读不到) */ }
|
|
2250
2405
|
payload = {
|
|
2251
2406
|
workflowId: wf, objId: nodeId, triggerType: 'all',
|
|
2252
2407
|
data: [{
|
|
2253
2408
|
id: tempIdNeg(),
|
|
2254
2409
|
actionName: `${fieldName} = ${value}`.trim(),
|
|
2255
|
-
executeTime:
|
|
2256
|
-
dateRuleStr: '', triggerType:
|
|
2410
|
+
executeTime: executeTime, open: true, async: 0, actionType: 0,
|
|
2411
|
+
dateRuleStr: '', triggerType: triggerType, order: 0,
|
|
2257
2412
|
targetValue: parsed.fieldId,
|
|
2258
2413
|
firstValue: 'custom',
|
|
2259
2414
|
operatorValue: '', secondValue: '',
|
|
2260
|
-
customValue
|
|
2415
|
+
customValue,
|
|
2261
2416
|
dateRule: [], isCreate: false,
|
|
2262
2417
|
}],
|
|
2263
2418
|
isNodeFlag: '1', objName: nodeName,
|